googlecode_upload.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 #
3 # Copyright 2006, 2007 Google Inc. All Rights Reserved.
4 # Author: danderson@google.com (David Anderson)
5 #
6 # Script for uploading files to a Google Code project.
7 #
8 # This is intended to be both a useful script for people who want to
9 # streamline project uploads and a reference implementation for
10 # uploading files to Google Code projects.
11 #
12 # To upload a file to Google Code, you need to provide a path to the
13 # file on your local machine, a small summary of what the file is, a
14 # project name, and a valid account that is a member or owner of that
15 # project. You can optionally provide a list of labels that apply to
16 # the file. The file will be uploaded under the same name that it has
17 # in your local filesystem (that is, the "basename" or last path
18 # component). Run the script with '--help' to get the exact syntax
19 # and available options.
20 #
21 # Note that the upload script requests that you enter your
22 # googlecode.com password. This is NOT your Gmail account password!
23 # This is the password you use on googlecode.com for committing to
24 # Subversion and uploading files. You can find your password by going
25 # to http://code.google.com/hosting/settings when logged in with your
26 # Gmail account. If you have already committed to your project's
27 # Subversion repository, the script will automatically retrieve your
28 # credentials from there (unless disabled, see the output of '--help'
29 # for details).
30 #
31 # If you are looking at this script as a reference for implementing
32 # your own Google Code file uploader, then you should take a look at
33 # the upload() function, which is the meat of the uploader. You
34 # basically need to build a multipart/form-data POST request with the
35 # right fields and send it to https://PROJECT.googlecode.com/files .
36 # Authenticate the request using HTTP Basic authentication, as is
37 # shown below.
38 #
39 # Licensed under the terms of the Apache Software License 2.0:
40 # http://www.apache.org/licenses/LICENSE-2.0
41 #
42 # Questions, comments, feature requests and patches are most welcome.
43 # Please direct all of these to the Google Code users group:
44 # http://groups.google.com/group/google-code-hosting
45 
46 """Google Code file uploader script.
47 """
48 
49 __author__ = 'danderson@google.com (David Anderson)'
50 
51 import httplib
52 import os.path
53 import optparse
54 import getpass
55 import base64
56 import sys
57 
58 
59 def upload(file, project_name, user_name, password, summary, labels=None):
60  """Upload a file to a Google Code project's file server.
61 
62  Args:
63  file: The local path to the file.
64  project_name: The name of your project on Google Code.
65  user_name: Your Google account name.
66  password: The googlecode.com password for your account.
67  Note that this is NOT your global Google Account password!
68  summary: A small description for the file.
69  labels: an optional list of label strings with which to tag the file.
70 
71  Returns: a tuple:
72  http_status: 201 if the upload succeeded, something else if an
73  error occured.
74  http_reason: The human-readable string associated with http_status
75  file_url: If the upload succeeded, the URL of the file on Google
76  Code, None otherwise.
77  """
78  # The login is the user part of user@gmail.com. If the login provided
79  # is in the full user@domain form, strip it down.
80  if user_name.endswith('@gmail.com'):
81  user_name = user_name[:user_name.index('@gmail.com')]
82 
83  form_fields = [('summary', summary)]
84  if labels is not None:
85  form_fields.extend([('label', l.strip()) for l in labels])
86 
87  content_type, body = encode_upload_request(form_fields, file)
88 
89  upload_host = '%s.googlecode.com' % project_name
90  upload_uri = '/files'
91  auth_token = base64.b64encode('%s:%s'% (user_name, password))
92  headers = {
93  'Authorization': 'Basic %s' % auth_token,
94  'User-Agent': 'Googlecode.com uploader v0.9.4',
95  'Content-Type': content_type,
96  }
97 
98  server = httplib.HTTPSConnection(upload_host)
99  server.request('POST', upload_uri, body, headers)
100  resp = server.getresponse()
101  server.close()
102 
103  if resp.status == 201:
104  location = resp.getheader('Location', None)
105  else:
106  location = None
107  return resp.status, resp.reason, location
108 
109 
110 def encode_upload_request(fields, file_path):
111  """Encode the given fields and file into a multipart form body.
112 
113  fields is a sequence of (name, value) pairs. file is the path of
114  the file to upload. The file will be uploaded to Google Code with
115  the same file name.
116 
117  Returns: (content_type, body) ready for httplib.HTTP instance
118  """
119  BOUNDARY = '----------Googlecode_boundary_reindeer_flotilla'
120  CRLF = '\r\n'
121 
122  body = []
123 
124  # Add the metadata about the upload first
125  for key, value in fields:
126  body.extend(
127  ['--' + BOUNDARY,
128  'Content-Disposition: form-data; name="%s"' % key,
129  '',
130  value,
131  ])
132 
133  # Now add the file itself
134  file_name = os.path.basename(file_path)
135  f = open(file_path, 'rb')
136  file_content = f.read()
137  f.close()
138 
139  body.extend(
140  ['--' + BOUNDARY,
141  'Content-Disposition: form-data; name="filename"; filename="%s"'
142  % file_name,
143  # The upload server determines the mime-type, no need to set it.
144  'Content-Type: application/octet-stream',
145  '',
146  file_content,
147  ])
148 
149  # Finalize the form body
150  body.extend(['--' + BOUNDARY + '--', ''])
151 
152  return 'multipart/form-data; boundary=%s' % BOUNDARY, CRLF.join(body)
153 
154 
155 def upload_find_auth(file_path, project_name, summary, labels=None,
156  user_name=None, password=None, tries=3):
157  """Find credentials and upload a file to a Google Code project's file server.
158 
159  file_path, project_name, summary, and labels are passed as-is to upload.
160 
161  Args:
162  file_path: The local path to the file.
163  project_name: The name of your project on Google Code.
164  summary: A small description for the file.
165  labels: an optional list of label strings with which to tag the file.
166  config_dir: Path to Subversion configuration directory, 'none', or None.
167  user_name: Your Google account name.
168  tries: How many attempts to make.
169  """
170  if user_name is None or password is None:
171  from netrc import netrc
172  authenticators = netrc().authenticators("code.google.com")
173  if authenticators:
174  if user_name is None:
175  user_name = authenticators[0]
176  if password is None:
177  password = authenticators[2]
178 
179  while tries > 0:
180  if user_name is None:
181  # Read username if not specified or loaded from svn config, or on
182  # subsequent tries.
183  sys.stdout.write('Please enter your googlecode.com username: ')
184  sys.stdout.flush()
185  user_name = sys.stdin.readline().rstrip()
186  if password is None:
187  # Read password if not loaded from svn config, or on subsequent tries.
188  print 'Please enter your googlecode.com password.'
189  print '** Note that this is NOT your Gmail account password! **'
190  print 'It is the password you use to access Subversion repositories,'
191  print 'and can be found here: http://code.google.com/hosting/settings'
192  password = getpass.getpass()
193 
194  status, reason, url = upload(file_path, project_name, user_name, password,
195  summary, labels)
196  # Returns 403 Forbidden instead of 401 Unauthorized for bad
197  # credentials as of 2007-07-17.
198  if status in [httplib.FORBIDDEN, httplib.UNAUTHORIZED]:
199  # Rest for another try.
200  user_name = password = None
201  tries = tries - 1
202  else:
203  # We're done.
204  break
205 
206  return status, reason, url
207 
208 
209 def main():
210  parser = optparse.OptionParser(usage='googlecode-upload.py -s SUMMARY '
211  '-p PROJECT [options] FILE')
212  parser.add_option('-s', '--summary', dest='summary',
213  help='Short description of the file')
214  parser.add_option('-p', '--project', dest='project',
215  help='Google Code project name')
216  parser.add_option('-u', '--user', dest='user',
217  help='Your Google Code username')
218  parser.add_option('-w', '--password', dest='password',
219  help='Your Google Code password')
220  parser.add_option('-l', '--labels', dest='labels',
221  help='An optional list of comma-separated labels to attach '
222  'to the file')
223 
224  options, args = parser.parse_args()
225 
226  if not options.summary:
227  parser.error('File summary is missing.')
228  elif not options.project:
229  parser.error('Project name is missing.')
230  elif len(args) < 1:
231  parser.error('File to upload not provided.')
232  elif len(args) > 1:
233  parser.error('Only one file may be specified.')
234 
235  file_path = args[0]
236 
237  if options.labels:
238  labels = options.labels.split(',')
239  else:
240  labels = None
241 
242  status, reason, url = upload_find_auth(file_path, options.project,
243  options.summary, labels,
244  options.user, options.password)
245  if url:
246  print 'The file was uploaded successfully.'
247  print 'URL: %s' % url
248  return 0
249  else:
250  print 'An error occurred. Your file was not uploaded.'
251  print 'Google Code upload server said: %s (%s)' % (reason, status)
252  return 1
253 
254 
255 if __name__ == '__main__':
256  sys.exit(main())
def encode_upload_request(fields, file_path)
def upload_find_auth(file_path, project_name, summary, labels=None, user_name=None, password=None, tries=3)
procfile open("FD_BRL_v0.txt")
def upload(file, project_name, user_name, password, summary, labels=None)