tesseract v5.3.3.20231005
upload Namespace Reference

Classes

class  AbstractRpcServer
 
class  ClientLoginError
 
class  GitVCS
 
class  HttpRpcServer
 elif e.code >= 500 and e.code < 600: More...
 
class  MercurialVCS
 
class  SubversionVCS
 
class  VersionControlSystem
 

Functions

def GetEmail (prompt)
 
def StatusUpdate (msg)
 
def ErrorExit (msg)
 
def GetRpcServer (options)
 
def EncodeMultipartFormData (fields, files)
 
def GetContentType (filename)
 
def RunShellWithReturnCode (command, print_output=False, universal_newlines=True)
 
def RunShell (command, silent_ok=False, universal_newlines=True, print_output=False)
 
def SplitPatch (data)
 
def UploadSeparatePatches (issue, rpc_server, patchset, data, options)
 
def GuessVCS (options)
 
def RealMain (argv, data=None)
 
def main ()
 

Variables

int verbosity = 1
 
int MAX_UPLOAD_SIZE = 900 * 1024
 
 parser = optparse.OptionParser(usage="%prog [options] [-- diff_options]")
 
 action
 
 dest
 
 default
 
 help
 
 group = parser.add_option_group("Logging options")
 
 const
 
 metavar
 
 type
 
 use_shell = sys.platform.startswith("win")
 

Function Documentation

◆ EncodeMultipartFormData()

def upload.EncodeMultipartFormData (   fields,
  files 
)
Encode form fields for multipart/form-data.

Args:
  fields: A sequence of (name, value) elements for regular form fields.
  files: A sequence of (name, filename, value) elements for data to be
         uploaded as files.
Returns:
  (content_type, body) ready for httplib.HTTP instance.

Source:
  https://web.archive.org/web/20160116052001/code.activestate.com/recipes/146306

Definition at line 513 of file upload.py.

513def EncodeMultipartFormData(fields, files):
514 """Encode form fields for multipart/form-data.
515
516 Args:
517 fields: A sequence of (name, value) elements for regular form fields.
518 files: A sequence of (name, filename, value) elements for data to be
519 uploaded as files.
520 Returns:
521 (content_type, body) ready for httplib.HTTP instance.
522
523 Source:
524 https://web.archive.org/web/20160116052001/code.activestate.com/recipes/146306
525 """
526 BOUNDARY = '-M-A-G-I-C---B-O-U-N-D-A-R-Y-'
527 CRLF = '\r\n'
528 lines = []
529 for (key, value) in fields:
530 lines.append('--' + BOUNDARY)
531 lines.append('Content-Disposition: form-data; name="%s"' % key)
532 lines.append('')
533 lines.append(value)
534 for (key, filename, value) in files:
535 lines.append('--' + BOUNDARY)
536 lines.append('Content-Disposition: form-data; name="%s"; filename="%s"' %
537 (key, filename))
538 lines.append('Content-Type: %s' % GetContentType(filename))
539 lines.append('')
540 lines.append(value)
541 lines.append('--' + BOUNDARY + '--')
542 lines.append('')
543 body = CRLF.join(lines)
544 content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
545 return content_type, body
546
547
def GetContentType(filename)
Definition: upload.py:548
def EncodeMultipartFormData(fields, files)
Definition: upload.py:513

◆ ErrorExit()

def upload.ErrorExit (   msg)
Print an error message to stderr and exit.

Definition at line 124 of file upload.py.

124def ErrorExit(msg):
125 """Print an error message to stderr and exit."""
126 print >>sys.stderr, msg
127 sys.exit(1)
128
129
def ErrorExit(msg)
Definition: upload.py:124

◆ GetContentType()

def upload.GetContentType (   filename)
Helper to guess the content-type from the filename.

Definition at line 548 of file upload.py.

548def GetContentType(filename):
549 """Helper to guess the content-type from the filename."""
550 return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
551
552
553# Use a shell for subcommands on Windows to get a PATH search.

◆ GetEmail()

def upload.GetEmail (   prompt)
Prompts the user for their email address and returns it.

The last used email address is saved to a file and offered up as a suggestion
to the user. If the user presses enter without typing in anything the last
used email address is used. If the user enters a new address, it is saved
for next time we prompt.

Definition at line 80 of file upload.py.

80def GetEmail(prompt):
81 """Prompts the user for their email address and returns it.
82
83 The last used email address is saved to a file and offered up as a suggestion
84 to the user. If the user presses enter without typing in anything the last
85 used email address is used. If the user enters a new address, it is saved
86 for next time we prompt.
87
88 """
89 last_email_file_name = os.path.expanduser("~/.last_codereview_email_address")
90 last_email = ""
91 if os.path.exists(last_email_file_name):
92 try:
93 last_email_file = open(last_email_file_name, "r")
94 last_email = last_email_file.readline().strip("\n")
95 last_email_file.close()
96 prompt += " [%s]" % last_email
97 except IOError, e:
98 pass
99 email = raw_input(prompt + ": ").strip()
100 if email:
101 try:
102 last_email_file = open(last_email_file_name, "w")
103 last_email_file.write(email)
104 last_email_file.close()
105 except IOError, e:
106 pass
107 else:
108 email = last_email
109 return email
110
111
def GetEmail(prompt)
Definition: upload.py:80

◆ GetRpcServer()

def upload.GetRpcServer (   options)
Returns an instance of an AbstractRpcServer.

Returns:
  A new AbstractRpcServer, on which RPC calls can be made.

Definition at line 473 of file upload.py.

473def GetRpcServer(options):
474 """Returns an instance of an AbstractRpcServer.
475
476 Returns:
477 A new AbstractRpcServer, on which RPC calls can be made.
478 """
479
480 rpc_server_class = HttpRpcServer
481
482 def GetUserCredentials():
483 """Prompts the user for a username and password."""
484 email = options.email
485 if email is None:
486 email = GetEmail("Email (login for uploading to %s)" % options.server)
487 password = getpass.getpass("Password for %s: " % email)
488 return (email, password)
489
490 # If this is the dev_appserver, use fake authentication.
491 host = (options.host or options.server).lower()
492 if host == "localhost" or host.startswith("localhost:"):
493 email = options.email
494 if email is None:
495 email = "test@example.com"
496 logging.info("Using debug user %s. Override with --email" % email)
497 server = rpc_server_class(
498 options.server,
499 lambda: (email, "password"),
500 host_override=options.host,
501 extra_headers={"Cookie":
502 'dev_appserver_login="%s:False"' % email},
503 save_cookies=options.save_cookies)
504 # Don't try to talk to ClientLogin.
505 server.authenticated = True
506 return server
507
508 return rpc_server_class(options.server, GetUserCredentials,
509 host_override=options.host,
510 save_cookies=options.save_cookies)
511
512
def GetRpcServer(options)
Definition: upload.py:473

◆ GuessVCS()

def upload.GuessVCS (   options)
Helper to guess the version control system.

This examines the current directory, guesses which VersionControlSystem
we're using, and returns an instance of the appropriate class.  Exit with an
error if we can't figure it out.

Returns:
  A VersionControlSystem instance. Exits if the VCS can't be guessed.

Definition at line 1224 of file upload.py.

1224def GuessVCS(options):
1225 """Helper to guess the version control system.
1226
1227 This examines the current directory, guesses which VersionControlSystem
1228 we're using, and returns an instance of the appropriate class. Exit with an
1229 error if we can't figure it out.
1230
1231 Returns:
1232 A VersionControlSystem instance. Exits if the VCS can't be guessed.
1233 """
1234 # Mercurial has a command to get the base directory of a repository
1235 # Try running it, but don't die if we don't have hg installed.
1236 # NOTE: we try Mercurial first as it can sit on top of an SVN working copy.
1237 try:
1238 out, returncode = RunShellWithReturnCode(["hg", "root"])
1239 if returncode == 0:
1240 return MercurialVCS(options, out.strip())
1241 except OSError, (errno, message):
1242 if errno != 2: # ENOENT -- they don't have hg installed.
1243 raise
1244
1245 # Subversion has a .svn in all working directories.
1246 if os.path.isdir('.svn'):
1247 logging.info("Guessed VCS = Subversion")
1248 return SubversionVCS(options)
1249
1250 # Git has a command to test if you're in a git tree.
1251 # Try running it, but don't die if we don't have git installed.
1252 try:
1253 out, returncode = RunShellWithReturnCode(["git", "rev-parse",
1254 "--is-inside-work-tree"])
1255 if returncode == 0:
1256 return GitVCS(options)
1257 except OSError, (errno, message):
1258 if errno != 2: # ENOENT -- they don't have git installed.
1259 raise
1260
1261 ErrorExit(("Could not guess version control system. "
1262 "Are you in a working copy directory?"))
1263
1264
def RunShellWithReturnCode(command, print_output=False, universal_newlines=True)
Definition: upload.py:557
def GuessVCS(options)
Definition: upload.py:1224

◆ main()

def upload.main ( )

Definition at line 1392 of file upload.py.

1392def main():
1393 try:
1394 RealMain(sys.argv)
1395 except KeyboardInterrupt:
1396 print
1397 StatusUpdate("Interrupted.")
1398 sys.exit(1)
1399
1400
def main()
Definition: upload.py:1392
def RealMain(argv, data=None)
Definition: upload.py:1265
def StatusUpdate(msg)
Definition: upload.py:112

◆ RealMain()

def upload.RealMain (   argv,
  data = None 
)
The real main function.

Args:
  argv: Command line arguments.
  data: Diff contents. If None (default) the diff is generated by
    the VersionControlSystem implementation returned by GuessVCS().

Returns:
  A 2-tuple (issue id, patchset id).
  The patchset id is None if the base files are not uploaded by this
  script (applies only to SVN checkouts).

Definition at line 1265 of file upload.py.

1265def RealMain(argv, data=None):
1266 """The real main function.
1267
1268 Args:
1269 argv: Command line arguments.
1270 data: Diff contents. If None (default) the diff is generated by
1271 the VersionControlSystem implementation returned by GuessVCS().
1272
1273 Returns:
1274 A 2-tuple (issue id, patchset id).
1275 The patchset id is None if the base files are not uploaded by this
1276 script (applies only to SVN checkouts).
1277 """
1278 logging.basicConfig(format=("%(asctime).19s %(levelname)s %(filename)s:"
1279 "%(lineno)s %(message)s "))
1280 os.environ['LC_ALL'] = 'C'
1281 options, args = parser.parse_args(argv[1:])
1282 global verbosity
1283 verbosity = options.verbose
1284 if verbosity >= 3:
1285 logging.getLogger().setLevel(logging.DEBUG)
1286 elif verbosity >= 2:
1287 logging.getLogger().setLevel(logging.INFO)
1288 vcs = GuessVCS(options)
1289 if isinstance(vcs, SubversionVCS):
1290 # base field is only allowed for Subversion.
1291 # Note: Fetching base files may become deprecated in future releases.
1292 base = vcs.GuessBase(options.download_base)
1293 else:
1294 base = None
1295 if not base and options.download_base:
1296 options.download_base = True
1297 logging.info("Enabled upload of base file")
1298 if not options.assume_yes:
1299 vcs.CheckForUnknownFiles()
1300 if data is None:
1301 data = vcs.GenerateDiff(args)
1302 files = vcs.GetBaseFiles(data)
1303 if verbosity >= 1:
1304 print "Upload server:", options.server, "(change with -s/--server)"
1305 if options.issue:
1306 prompt = "Message describing this patch set: "
1307 else:
1308 prompt = "New issue subject: "
1309 message = options.message or raw_input(prompt).strip()
1310 if not message:
1311 ErrorExit("A non-empty message is required")
1312 rpc_server = GetRpcServer(options)
1313 form_fields = [("subject", message)]
1314 if base:
1315 form_fields.append(("base", base))
1316 if options.issue:
1317 form_fields.append(("issue", str(options.issue)))
1318 if options.email:
1319 form_fields.append(("user", options.email))
1320 if options.reviewers:
1321 for reviewer in options.reviewers.split(','):
1322 if "@" in reviewer and not reviewer.split("@")[1].count(".") == 1:
1323 ErrorExit("Invalid email address: %s" % reviewer)
1324 form_fields.append(("reviewers", options.reviewers))
1325 if options.cc:
1326 for cc in options.cc.split(','):
1327 if "@" in cc and not cc.split("@")[1].count(".") == 1:
1328 ErrorExit("Invalid email address: %s" % cc)
1329 form_fields.append(("cc", options.cc))
1330 description = options.description
1331 if options.description_file:
1332 if options.description:
1333 ErrorExit("Can't specify description and description_file")
1334 file = open(options.description_file, 'r')
1335 description = file.read()
1336 file.close()
1337 if description:
1338 form_fields.append(("description", description))
1339 # Send a hash of all the base file so the server can determine if a copy
1340 # already exists in an earlier patchset.
1341 base_hashes = ""
1342 for file, info in files.iteritems():
1343 if not info[0] is None:
1344 checksum = md5.new(info[0]).hexdigest()
1345 if base_hashes:
1346 base_hashes += "|"
1347 base_hashes += checksum + ":" + file
1348 form_fields.append(("base_hashes", base_hashes))
1349 # If we're uploading base files, don't send the email before the uploads, so
1350 # that it contains the file status.
1351 if options.send_mail and options.download_base:
1352 form_fields.append(("send_mail", "1"))
1353 if not options.download_base:
1354 form_fields.append(("content_upload", "1"))
1355 if len(data) > MAX_UPLOAD_SIZE:
1356 print "Patch is large, so uploading file patches separately."
1357 uploaded_diff_file = []
1358 form_fields.append(("separate_patches", "1"))
1359 else:
1360 uploaded_diff_file = [("data", "data.diff", data)]
1361 ctype, body = EncodeMultipartFormData(form_fields, uploaded_diff_file)
1362 response_body = rpc_server.Send("/upload", body, content_type=ctype)
1363 patchset = None
1364 if not options.download_base or not uploaded_diff_file:
1365 lines = response_body.splitlines()
1366 if len(lines) >= 2:
1367 msg = lines[0]
1368 patchset = lines[1].strip()
1369 patches = [x.split(" ", 1) for x in lines[2:]]
1370 else:
1371 msg = response_body
1372 else:
1373 msg = response_body
1374 StatusUpdate(msg)
1375 if not response_body.startswith("Issue created.") and \
1376 not response_body.startswith("Issue updated."):
1377 sys.exit(0)
1378 issue = msg[msg.rfind("/")+1:]
1379
1380 if not uploaded_diff_file:
1381 result = UploadSeparatePatches(issue, rpc_server, patchset, data, options)
1382 if not options.download_base:
1383 patches = result
1384
1385 if not options.download_base:
1386 vcs.UploadBaseFiles(issue, rpc_server, patches, patchset, options, files)
1387 if options.send_mail:
1388 rpc_server.Send("/" + issue + "/mail", payload="")
1389 return issue, patchset
1390
1391
int * count
def UploadSeparatePatches(issue, rpc_server, patchset, data, options)
Definition: upload.py:1196

◆ RunShell()

def upload.RunShell (   command,
  silent_ok = False,
  universal_newlines = True,
  print_output = False 
)

Definition at line 592 of file upload.py.

593 print_output=False):
594 data, retcode = RunShellWithReturnCode(command, print_output,
595 universal_newlines)
596 if retcode:
597 ErrorExit("Got error status from %s:\n%s" % (command, data))
598 if not silent_ok and not data:
599 ErrorExit("No output from %s" % command)
600 return data
601
602

◆ RunShellWithReturnCode()

def upload.RunShellWithReturnCode (   command,
  print_output = False,
  universal_newlines = True 
)
Executes a command and returns the output from stdout and the return code.

Args:
  command: Command to execute.
  print_output: If True, the output is printed to stdout.
                If False, both stdout and stderr are ignored.
  universal_newlines: Use universal_newlines flag (default: True).

Returns:
  Tuple (output, return code)

Definition at line 556 of file upload.py.

557 universal_newlines=True):
558 """Executes a command and returns the output from stdout and the return code.
559
560 Args:
561 command: Command to execute.
562 print_output: If True, the output is printed to stdout.
563 If False, both stdout and stderr are ignored.
564 universal_newlines: Use universal_newlines flag (default: True).
565
566 Returns:
567 Tuple (output, return code)
568 """
569 logging.info("Running %s", command)
570 p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
571 shell=use_shell, universal_newlines=universal_newlines)
572 if print_output:
573 output_array = []
574 while True:
575 line = p.stdout.readline()
576 if not line:
577 break
578 print line.strip("\n")
579 output_array.append(line)
580 output = "".join(output_array)
581 else:
582 output = p.stdout.read()
583 p.wait()
584 errout = p.stderr.read()
585 if print_output and errout:
586 print >>sys.stderr, errout
587 p.stdout.close()
588 p.stderr.close()
589 return output, p.returncode
590
591

◆ SplitPatch()

def upload.SplitPatch (   data)
Splits a patch into separate pieces for each file.

Args:
  data: A string containing the output of svn diff.

Returns:
  A list of 2-tuple (filename, text) where text is the svn diff output
    pertaining to filename.

Definition at line 1156 of file upload.py.

1156def SplitPatch(data):
1157 """Splits a patch into separate pieces for each file.
1158
1159 Args:
1160 data: A string containing the output of svn diff.
1161
1162 Returns:
1163 A list of 2-tuple (filename, text) where text is the svn diff output
1164 pertaining to filename.
1165 """
1166 patches = []
1167 filename = None
1168 diff = []
1169 for line in data.splitlines(True):
1170 new_filename = None
1171 if line.startswith('Index:'):
1172 unused, new_filename = line.split(':', 1)
1173 new_filename = new_filename.strip()
1174 elif line.startswith('Property changes on:'):
1175 unused, temp_filename = line.split(':', 1)
1176 # When a file is modified, paths use '/' between directories, however
1177 # when a property is modified '\' is used on Windows. Make them the same
1178 # otherwise the file shows up twice.
1179 temp_filename = temp_filename.strip().replace('\\', '/')
1180 if temp_filename != filename:
1181 # File has property changes but no modifications, create a new diff.
1182 new_filename = temp_filename
1183 if new_filename:
1184 if filename and diff:
1185 patches.append((filename, ''.join(diff)))
1186 filename = new_filename
1187 diff = [line]
1188 continue
1189 if diff is not None:
1190 diff.append(line)
1191 if filename and diff:
1192 patches.append((filename, ''.join(diff)))
1193 return patches
1194
1195
def SplitPatch(data)
Definition: upload.py:1156

◆ StatusUpdate()

def upload.StatusUpdate (   msg)
Print a status message to stdout.

If 'verbosity' is greater than 0, print the message.

Args:
  msg: The string to print.

Definition at line 112 of file upload.py.

112def StatusUpdate(msg):
113 """Print a status message to stdout.
114
115 If 'verbosity' is greater than 0, print the message.
116
117 Args:
118 msg: The string to print.
119 """
120 if verbosity > 0:
121 print msg
122
123

◆ UploadSeparatePatches()

def upload.UploadSeparatePatches (   issue,
  rpc_server,
  patchset,
  data,
  options 
)
Uploads a separate patch for each file in the diff output.

Returns a list of [patch_key, filename] for each file.

Definition at line 1196 of file upload.py.

1196def UploadSeparatePatches(issue, rpc_server, patchset, data, options):
1197 """Uploads a separate patch for each file in the diff output.
1198
1199 Returns a list of [patch_key, filename] for each file.
1200 """
1201 patches = SplitPatch(data)
1202 rv = []
1203 for patch in patches:
1204 if len(patch[1]) > MAX_UPLOAD_SIZE:
1205 print ("Not uploading the patch for " + patch[0] +
1206 " because the file is too large.")
1207 continue
1208 form_fields = [("filename", patch[0])]
1209 if not options.download_base:
1210 form_fields.append(("content_upload", "1"))
1211 files = [("data", "data.diff", patch[1])]
1212 ctype, body = EncodeMultipartFormData(form_fields, files)
1213 url = "/%d/upload_patch/%d" % (int(issue), int(patchset))
1214 print "Uploading patch for " + patch[0]
1215 response_body = rpc_server.Send(url, body, content_type=ctype)
1216 lines = response_body.splitlines()
1217 if not lines or lines[0] != "OK":
1218 StatusUpdate(" --> %s" % response_body)
1219 sys.exit(1)
1220 rv.append([lines[1], patch[0]])
1221 return rv
1222
1223

Variable Documentation

◆ action

upload.action

Definition at line 408 of file upload.py.

◆ const

upload.const

Definition at line 413 of file upload.py.

◆ default

upload.default

Definition at line 409 of file upload.py.

◆ dest

upload.dest

Definition at line 409 of file upload.py.

◆ group

upload.group = parser.add_option_group("Logging options")

Definition at line 412 of file upload.py.

◆ help

upload.help

Definition at line 410 of file upload.py.

◆ MAX_UPLOAD_SIZE

int upload.MAX_UPLOAD_SIZE = 900 * 1024

Definition at line 77 of file upload.py.

◆ metavar

upload.metavar

Definition at line 424 of file upload.py.

◆ parser

upload.parser = optparse.OptionParser(usage="%prog [options] [-- diff_options]")

Definition at line 407 of file upload.py.

◆ type

upload.type

Definition at line 458 of file upload.py.

◆ use_shell

upload.use_shell = sys.platform.startswith("win")

Definition at line 554 of file upload.py.

◆ verbosity

int upload.verbosity = 1

Definition at line 74 of file upload.py.