]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Python/Python-2.7.2/Lib/distutils/util.py
EmbeddedPkg: Extend NvVarStoreFormattedLib LIBRARY_CLASS
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.2 / Lib / distutils / util.py
CommitLineData
4710c53d 1"""distutils.util\r
2\r
3Miscellaneous utility functions -- anything that doesn't fit into\r
4one of the other *util.py modules.\r
5"""\r
6\r
7__revision__ = "$Id$"\r
8\r
9import sys, os, string, re\r
10from distutils.errors import DistutilsPlatformError\r
11from distutils.dep_util import newer\r
12from distutils.spawn import spawn\r
13from distutils import log\r
14from distutils.errors import DistutilsByteCompileError\r
15\r
16def get_platform ():\r
17 """Return a string that identifies the current platform. This is used\r
18 mainly to distinguish platform-specific build directories and\r
19 platform-specific built distributions. Typically includes the OS name\r
20 and version and the architecture (as supplied by 'os.uname()'),\r
21 although the exact information included depends on the OS; eg. for IRIX\r
22 the architecture isn't particularly important (IRIX only runs on SGI\r
23 hardware), but for Linux the kernel version isn't particularly\r
24 important.\r
25\r
26 Examples of returned values:\r
27 linux-i586\r
28 linux-alpha (?)\r
29 solaris-2.6-sun4u\r
30 irix-5.3\r
31 irix64-6.2\r
32\r
33 Windows will return one of:\r
34 win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)\r
35 win-ia64 (64bit Windows on Itanium)\r
36 win32 (all others - specifically, sys.platform is returned)\r
37\r
38 For other non-POSIX platforms, currently just returns 'sys.platform'.\r
39 """\r
40 if os.name == 'nt':\r
41 # sniff sys.version for architecture.\r
42 prefix = " bit ("\r
43 i = string.find(sys.version, prefix)\r
44 if i == -1:\r
45 return sys.platform\r
46 j = string.find(sys.version, ")", i)\r
47 look = sys.version[i+len(prefix):j].lower()\r
48 if look=='amd64':\r
49 return 'win-amd64'\r
50 if look=='itanium':\r
51 return 'win-ia64'\r
52 return sys.platform\r
53\r
54 if os.name != "posix" or not hasattr(os, 'uname'):\r
55 # XXX what about the architecture? NT is Intel or Alpha,\r
56 # Mac OS is M68k or PPC, etc.\r
57 return sys.platform\r
58\r
59 # Try to distinguish various flavours of Unix\r
60\r
61 (osname, host, release, version, machine) = os.uname()\r
62\r
63 # Convert the OS name to lowercase, remove '/' characters\r
64 # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")\r
65 osname = string.lower(osname)\r
66 osname = string.replace(osname, '/', '')\r
67 machine = string.replace(machine, ' ', '_')\r
68 machine = string.replace(machine, '/', '-')\r
69\r
70 if osname[:5] == "linux":\r
71 # At least on Linux/Intel, 'machine' is the processor --\r
72 # i386, etc.\r
73 # XXX what about Alpha, SPARC, etc?\r
74 return "%s-%s" % (osname, machine)\r
75 elif osname[:5] == "sunos":\r
76 if release[0] >= "5": # SunOS 5 == Solaris 2\r
77 osname = "solaris"\r
78 release = "%d.%s" % (int(release[0]) - 3, release[2:])\r
79 # fall through to standard osname-release-machine representation\r
80 elif osname[:4] == "irix": # could be "irix64"!\r
81 return "%s-%s" % (osname, release)\r
82 elif osname[:3] == "aix":\r
83 return "%s-%s.%s" % (osname, version, release)\r
84 elif osname[:6] == "cygwin":\r
85 osname = "cygwin"\r
86 rel_re = re.compile (r'[\d.]+')\r
87 m = rel_re.match(release)\r
88 if m:\r
89 release = m.group()\r
90 elif osname[:6] == "darwin":\r
91 #\r
92 # For our purposes, we'll assume that the system version from\r
93 # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set\r
94 # to. This makes the compatibility story a bit more sane because the\r
95 # machine is going to compile and link as if it were\r
96 # MACOSX_DEPLOYMENT_TARGET.\r
97 from distutils.sysconfig import get_config_vars\r
98 cfgvars = get_config_vars()\r
99\r
100 macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET')\r
101\r
102 if 1:\r
103 # Always calculate the release of the running machine,\r
104 # needed to determine if we can build fat binaries or not.\r
105\r
106 macrelease = macver\r
107 # Get the system version. Reading this plist is a documented\r
108 # way to get the system version (see the documentation for\r
109 # the Gestalt Manager)\r
110 try:\r
111 f = open('/System/Library/CoreServices/SystemVersion.plist')\r
112 except IOError:\r
113 # We're on a plain darwin box, fall back to the default\r
114 # behaviour.\r
115 pass\r
116 else:\r
117 try:\r
118 m = re.search(\r
119 r'<key>ProductUserVisibleVersion</key>\s*' +\r
120 r'<string>(.*?)</string>', f.read())\r
121 if m is not None:\r
122 macrelease = '.'.join(m.group(1).split('.')[:2])\r
123 # else: fall back to the default behaviour\r
124 finally:\r
125 f.close()\r
126\r
127 if not macver:\r
128 macver = macrelease\r
129\r
130 if macver:\r
131 from distutils.sysconfig import get_config_vars\r
132 release = macver\r
133 osname = "macosx"\r
134\r
135 if (macrelease + '.') >= '10.4.' and \\r
136 '-arch' in get_config_vars().get('CFLAGS', '').strip():\r
137 # The universal build will build fat binaries, but not on\r
138 # systems before 10.4\r
139 #\r
140 # Try to detect 4-way universal builds, those have machine-type\r
141 # 'universal' instead of 'fat'.\r
142\r
143 machine = 'fat'\r
144 cflags = get_config_vars().get('CFLAGS')\r
145\r
146 archs = re.findall('-arch\s+(\S+)', cflags)\r
147 archs = tuple(sorted(set(archs)))\r
148\r
149 if len(archs) == 1:\r
150 machine = archs[0]\r
151 elif archs == ('i386', 'ppc'):\r
152 machine = 'fat'\r
153 elif archs == ('i386', 'x86_64'):\r
154 machine = 'intel'\r
155 elif archs == ('i386', 'ppc', 'x86_64'):\r
156 machine = 'fat3'\r
157 elif archs == ('ppc64', 'x86_64'):\r
158 machine = 'fat64'\r
159 elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'):\r
160 machine = 'universal'\r
161 else:\r
162 raise ValueError(\r
163 "Don't know machine value for archs=%r"%(archs,))\r
164\r
165 elif machine == 'i386':\r
166 # On OSX the machine type returned by uname is always the\r
167 # 32-bit variant, even if the executable architecture is\r
168 # the 64-bit variant\r
169 if sys.maxint >= 2**32:\r
170 machine = 'x86_64'\r
171\r
172 elif machine in ('PowerPC', 'Power_Macintosh'):\r
173 # Pick a sane name for the PPC architecture.\r
174 machine = 'ppc'\r
175\r
176 # See 'i386' case\r
177 if sys.maxint >= 2**32:\r
178 machine = 'ppc64'\r
179\r
180 return "%s-%s-%s" % (osname, release, machine)\r
181\r
182# get_platform ()\r
183\r
184\r
185def convert_path (pathname):\r
186 """Return 'pathname' as a name that will work on the native filesystem,\r
187 i.e. split it on '/' and put it back together again using the current\r
188 directory separator. Needed because filenames in the setup script are\r
189 always supplied in Unix style, and have to be converted to the local\r
190 convention before we can actually use them in the filesystem. Raises\r
191 ValueError on non-Unix-ish systems if 'pathname' either starts or\r
192 ends with a slash.\r
193 """\r
194 if os.sep == '/':\r
195 return pathname\r
196 if not pathname:\r
197 return pathname\r
198 if pathname[0] == '/':\r
199 raise ValueError, "path '%s' cannot be absolute" % pathname\r
200 if pathname[-1] == '/':\r
201 raise ValueError, "path '%s' cannot end with '/'" % pathname\r
202\r
203 paths = string.split(pathname, '/')\r
204 while '.' in paths:\r
205 paths.remove('.')\r
206 if not paths:\r
207 return os.curdir\r
208 return os.path.join(*paths)\r
209\r
210# convert_path ()\r
211\r
212\r
213def change_root (new_root, pathname):\r
214 """Return 'pathname' with 'new_root' prepended. If 'pathname' is\r
215 relative, this is equivalent to "os.path.join(new_root,pathname)".\r
216 Otherwise, it requires making 'pathname' relative and then joining the\r
217 two, which is tricky on DOS/Windows and Mac OS.\r
218 """\r
219 if os.name == 'posix':\r
220 if not os.path.isabs(pathname):\r
221 return os.path.join(new_root, pathname)\r
222 else:\r
223 return os.path.join(new_root, pathname[1:])\r
224\r
225 elif os.name == 'nt':\r
226 (drive, path) = os.path.splitdrive(pathname)\r
227 if path[0] == '\\':\r
228 path = path[1:]\r
229 return os.path.join(new_root, path)\r
230\r
231 elif os.name == 'os2':\r
232 (drive, path) = os.path.splitdrive(pathname)\r
233 if path[0] == os.sep:\r
234 path = path[1:]\r
235 return os.path.join(new_root, path)\r
236\r
237 else:\r
238 raise DistutilsPlatformError, \\r
239 "nothing known about platform '%s'" % os.name\r
240\r
241\r
242_environ_checked = 0\r
243def check_environ ():\r
244 """Ensure that 'os.environ' has all the environment variables we\r
245 guarantee that users can use in config files, command-line options,\r
246 etc. Currently this includes:\r
247 HOME - user's home directory (Unix only)\r
248 PLAT - description of the current platform, including hardware\r
249 and OS (see 'get_platform()')\r
250 """\r
251 global _environ_checked\r
252 if _environ_checked:\r
253 return\r
254\r
255 if os.name == 'posix' and 'HOME' not in os.environ:\r
256 import pwd\r
257 os.environ['HOME'] = pwd.getpwuid(os.getuid())[5]\r
258\r
259 if 'PLAT' not in os.environ:\r
260 os.environ['PLAT'] = get_platform()\r
261\r
262 _environ_checked = 1\r
263\r
264\r
265def subst_vars (s, local_vars):\r
266 """Perform shell/Perl-style variable substitution on 'string'. Every\r
267 occurrence of '$' followed by a name is considered a variable, and\r
268 variable is substituted by the value found in the 'local_vars'\r
269 dictionary, or in 'os.environ' if it's not in 'local_vars'.\r
270 'os.environ' is first checked/augmented to guarantee that it contains\r
271 certain values: see 'check_environ()'. Raise ValueError for any\r
272 variables not found in either 'local_vars' or 'os.environ'.\r
273 """\r
274 check_environ()\r
275 def _subst (match, local_vars=local_vars):\r
276 var_name = match.group(1)\r
277 if var_name in local_vars:\r
278 return str(local_vars[var_name])\r
279 else:\r
280 return os.environ[var_name]\r
281\r
282 try:\r
283 return re.sub(r'\$([a-zA-Z_][a-zA-Z_0-9]*)', _subst, s)\r
284 except KeyError, var:\r
285 raise ValueError, "invalid variable '$%s'" % var\r
286\r
287# subst_vars ()\r
288\r
289\r
290def grok_environment_error (exc, prefix="error: "):\r
291 """Generate a useful error message from an EnvironmentError (IOError or\r
292 OSError) exception object. Handles Python 1.5.1 and 1.5.2 styles, and\r
293 does what it can to deal with exception objects that don't have a\r
294 filename (which happens when the error is due to a two-file operation,\r
295 such as 'rename()' or 'link()'. Returns the error message as a string\r
296 prefixed with 'prefix'.\r
297 """\r
298 # check for Python 1.5.2-style {IO,OS}Error exception objects\r
299 if hasattr(exc, 'filename') and hasattr(exc, 'strerror'):\r
300 if exc.filename:\r
301 error = prefix + "%s: %s" % (exc.filename, exc.strerror)\r
302 else:\r
303 # two-argument functions in posix module don't\r
304 # include the filename in the exception object!\r
305 error = prefix + "%s" % exc.strerror\r
306 else:\r
307 error = prefix + str(exc[-1])\r
308\r
309 return error\r
310\r
311\r
312# Needed by 'split_quoted()'\r
313_wordchars_re = _squote_re = _dquote_re = None\r
314def _init_regex():\r
315 global _wordchars_re, _squote_re, _dquote_re\r
316 _wordchars_re = re.compile(r'[^\\\'\"%s ]*' % string.whitespace)\r
317 _squote_re = re.compile(r"'(?:[^'\\]|\\.)*'")\r
318 _dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"')\r
319\r
320def split_quoted (s):\r
321 """Split a string up according to Unix shell-like rules for quotes and\r
322 backslashes. In short: words are delimited by spaces, as long as those\r
323 spaces are not escaped by a backslash, or inside a quoted string.\r
324 Single and double quotes are equivalent, and the quote characters can\r
325 be backslash-escaped. The backslash is stripped from any two-character\r
326 escape sequence, leaving only the escaped character. The quote\r
327 characters are stripped from any quoted string. Returns a list of\r
328 words.\r
329 """\r
330\r
331 # This is a nice algorithm for splitting up a single string, since it\r
332 # doesn't require character-by-character examination. It was a little\r
333 # bit of a brain-bender to get it working right, though...\r
334 if _wordchars_re is None: _init_regex()\r
335\r
336 s = string.strip(s)\r
337 words = []\r
338 pos = 0\r
339\r
340 while s:\r
341 m = _wordchars_re.match(s, pos)\r
342 end = m.end()\r
343 if end == len(s):\r
344 words.append(s[:end])\r
345 break\r
346\r
347 if s[end] in string.whitespace: # unescaped, unquoted whitespace: now\r
348 words.append(s[:end]) # we definitely have a word delimiter\r
349 s = string.lstrip(s[end:])\r
350 pos = 0\r
351\r
352 elif s[end] == '\\': # preserve whatever is being escaped;\r
353 # will become part of the current word\r
354 s = s[:end] + s[end+1:]\r
355 pos = end+1\r
356\r
357 else:\r
358 if s[end] == "'": # slurp singly-quoted string\r
359 m = _squote_re.match(s, end)\r
360 elif s[end] == '"': # slurp doubly-quoted string\r
361 m = _dquote_re.match(s, end)\r
362 else:\r
363 raise RuntimeError, \\r
364 "this can't happen (bad char '%c')" % s[end]\r
365\r
366 if m is None:\r
367 raise ValueError, \\r
368 "bad string (mismatched %s quotes?)" % s[end]\r
369\r
370 (beg, end) = m.span()\r
371 s = s[:beg] + s[beg+1:end-1] + s[end:]\r
372 pos = m.end() - 2\r
373\r
374 if pos >= len(s):\r
375 words.append(s)\r
376 break\r
377\r
378 return words\r
379\r
380# split_quoted ()\r
381\r
382\r
383def execute (func, args, msg=None, verbose=0, dry_run=0):\r
384 """Perform some action that affects the outside world (eg. by\r
385 writing to the filesystem). Such actions are special because they\r
386 are disabled by the 'dry_run' flag. This method takes care of all\r
387 that bureaucracy for you; all you have to do is supply the\r
388 function to call and an argument tuple for it (to embody the\r
389 "external action" being performed), and an optional message to\r
390 print.\r
391 """\r
392 if msg is None:\r
393 msg = "%s%r" % (func.__name__, args)\r
394 if msg[-2:] == ',)': # correct for singleton tuple\r
395 msg = msg[0:-2] + ')'\r
396\r
397 log.info(msg)\r
398 if not dry_run:\r
399 func(*args)\r
400\r
401\r
402def strtobool (val):\r
403 """Convert a string representation of truth to true (1) or false (0).\r
404\r
405 True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values\r
406 are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if\r
407 'val' is anything else.\r
408 """\r
409 val = string.lower(val)\r
410 if val in ('y', 'yes', 't', 'true', 'on', '1'):\r
411 return 1\r
412 elif val in ('n', 'no', 'f', 'false', 'off', '0'):\r
413 return 0\r
414 else:\r
415 raise ValueError, "invalid truth value %r" % (val,)\r
416\r
417\r
418def byte_compile (py_files,\r
419 optimize=0, force=0,\r
420 prefix=None, base_dir=None,\r
421 verbose=1, dry_run=0,\r
422 direct=None):\r
423 """Byte-compile a collection of Python source files to either .pyc\r
424 or .pyo files in the same directory. 'py_files' is a list of files\r
425 to compile; any files that don't end in ".py" are silently skipped.\r
426 'optimize' must be one of the following:\r
427 0 - don't optimize (generate .pyc)\r
428 1 - normal optimization (like "python -O")\r
429 2 - extra optimization (like "python -OO")\r
430 If 'force' is true, all files are recompiled regardless of\r
431 timestamps.\r
432\r
433 The source filename encoded in each bytecode file defaults to the\r
434 filenames listed in 'py_files'; you can modify these with 'prefix' and\r
435 'basedir'. 'prefix' is a string that will be stripped off of each\r
436 source filename, and 'base_dir' is a directory name that will be\r
437 prepended (after 'prefix' is stripped). You can supply either or both\r
438 (or neither) of 'prefix' and 'base_dir', as you wish.\r
439\r
440 If 'dry_run' is true, doesn't actually do anything that would\r
441 affect the filesystem.\r
442\r
443 Byte-compilation is either done directly in this interpreter process\r
444 with the standard py_compile module, or indirectly by writing a\r
445 temporary script and executing it. Normally, you should let\r
446 'byte_compile()' figure out to use direct compilation or not (see\r
447 the source for details). The 'direct' flag is used by the script\r
448 generated in indirect mode; unless you know what you're doing, leave\r
449 it set to None.\r
450 """\r
451 # nothing is done if sys.dont_write_bytecode is True\r
452 if sys.dont_write_bytecode:\r
453 raise DistutilsByteCompileError('byte-compiling is disabled.')\r
454\r
455 # First, if the caller didn't force us into direct or indirect mode,\r
456 # figure out which mode we should be in. We take a conservative\r
457 # approach: choose direct mode *only* if the current interpreter is\r
458 # in debug mode and optimize is 0. If we're not in debug mode (-O\r
459 # or -OO), we don't know which level of optimization this\r
460 # interpreter is running with, so we can't do direct\r
461 # byte-compilation and be certain that it's the right thing. Thus,\r
462 # always compile indirectly if the current interpreter is in either\r
463 # optimize mode, or if either optimization level was requested by\r
464 # the caller.\r
465 if direct is None:\r
466 direct = (__debug__ and optimize == 0)\r
467\r
468 # "Indirect" byte-compilation: write a temporary script and then\r
469 # run it with the appropriate flags.\r
470 if not direct:\r
471 try:\r
472 from tempfile import mkstemp\r
473 (script_fd, script_name) = mkstemp(".py")\r
474 except ImportError:\r
475 from tempfile import mktemp\r
476 (script_fd, script_name) = None, mktemp(".py")\r
477 log.info("writing byte-compilation script '%s'", script_name)\r
478 if not dry_run:\r
479 if script_fd is not None:\r
480 script = os.fdopen(script_fd, "w")\r
481 else:\r
482 script = open(script_name, "w")\r
483\r
484 script.write("""\\r
485from distutils.util import byte_compile\r
486files = [\r
487""")\r
488\r
489 # XXX would be nice to write absolute filenames, just for\r
490 # safety's sake (script should be more robust in the face of\r
491 # chdir'ing before running it). But this requires abspath'ing\r
492 # 'prefix' as well, and that breaks the hack in build_lib's\r
493 # 'byte_compile()' method that carefully tacks on a trailing\r
494 # slash (os.sep really) to make sure the prefix here is "just\r
495 # right". This whole prefix business is rather delicate -- the\r
496 # problem is that it's really a directory, but I'm treating it\r
497 # as a dumb string, so trailing slashes and so forth matter.\r
498\r
499 #py_files = map(os.path.abspath, py_files)\r
500 #if prefix:\r
501 # prefix = os.path.abspath(prefix)\r
502\r
503 script.write(string.join(map(repr, py_files), ",\n") + "]\n")\r
504 script.write("""\r
505byte_compile(files, optimize=%r, force=%r,\r
506 prefix=%r, base_dir=%r,\r
507 verbose=%r, dry_run=0,\r
508 direct=1)\r
509""" % (optimize, force, prefix, base_dir, verbose))\r
510\r
511 script.close()\r
512\r
513 cmd = [sys.executable, script_name]\r
514 if optimize == 1:\r
515 cmd.insert(1, "-O")\r
516 elif optimize == 2:\r
517 cmd.insert(1, "-OO")\r
518 spawn(cmd, dry_run=dry_run)\r
519 execute(os.remove, (script_name,), "removing %s" % script_name,\r
520 dry_run=dry_run)\r
521\r
522 # "Direct" byte-compilation: use the py_compile module to compile\r
523 # right here, right now. Note that the script generated in indirect\r
524 # mode simply calls 'byte_compile()' in direct mode, a weird sort of\r
525 # cross-process recursion. Hey, it works!\r
526 else:\r
527 from py_compile import compile\r
528\r
529 for file in py_files:\r
530 if file[-3:] != ".py":\r
531 # This lets us be lazy and not filter filenames in\r
532 # the "install_lib" command.\r
533 continue\r
534\r
535 # Terminology from the py_compile module:\r
536 # cfile - byte-compiled file\r
537 # dfile - purported source filename (same as 'file' by default)\r
538 cfile = file + (__debug__ and "c" or "o")\r
539 dfile = file\r
540 if prefix:\r
541 if file[:len(prefix)] != prefix:\r
542 raise ValueError, \\r
543 ("invalid prefix: filename %r doesn't start with %r"\r
544 % (file, prefix))\r
545 dfile = dfile[len(prefix):]\r
546 if base_dir:\r
547 dfile = os.path.join(base_dir, dfile)\r
548\r
549 cfile_base = os.path.basename(cfile)\r
550 if direct:\r
551 if force or newer(file, cfile):\r
552 log.info("byte-compiling %s to %s", file, cfile_base)\r
553 if not dry_run:\r
554 compile(file, cfile, dfile)\r
555 else:\r
556 log.debug("skipping byte-compilation of %s to %s",\r
557 file, cfile_base)\r
558\r
559# byte_compile ()\r
560\r
561def rfc822_escape (header):\r
562 """Return a version of the string escaped for inclusion in an\r
563 RFC-822 header, by ensuring there are 8 spaces space after each newline.\r
564 """\r
565 lines = string.split(header, '\n')\r
566 header = string.join(lines, '\n' + 8*' ')\r
567 return header\r