Status: | Merged |
---|---|
Merge reported by: | Barry Warsaw |
Merged at revision: | not available |
Proposed branch: | lp:~barry/python/pep3147 |
Merge into: | lp:python/py3k |
Diff against target: |
2808 lines (+1209/-293) 39 files modified
.bzrignore (+1/-0) .hgignore (+1/-0) Doc/c-api/import.rst (+17/-0) Doc/library/compileall.rst (+12/-6) Doc/library/imp.rst (+35/-2) Doc/library/py_compile.rst (+7/-3) Doc/library/runpy.rst (+4/-1) Include/import.h (+3/-0) Lib/compileall.py (+48/-26) Lib/importlib/_bootstrap.py (+20/-1) Lib/importlib/test/__main__.py (+6/-1) Lib/importlib/test/source/test_file_loader.py (+5/-4) Lib/importlib/test/source/test_finder.py (+12/-1) Lib/importlib/test/source/test_source_encoding.py (+1/-1) Lib/importlib/test/source/util.py (+11/-8) Lib/importlib/util.py (+1/-0) Lib/inspect.py (+1/-0) Lib/py_compile.py (+27/-21) Lib/pydoc.py (+2/-1) Lib/runpy.py (+2/-0) Lib/site.py (+8/-4) Lib/test/script_helper.py (+12/-11) Lib/test/support.py (+64/-26) Lib/test/test_cmd_line_script.py (+18/-12) Lib/test/test_compileall.py (+69/-10) Lib/test/test_frozen.py (+5/-5) Lib/test/test_imp.py (+125/-2) Lib/test/test_import.py (+176/-30) Lib/test/test_pkg.py (+10/-10) Lib/test/test_pkgimport.py (+14/-12) Lib/test/test_pydoc.py (+7/-9) Lib/test/test_runpy.py (+17/-8) Lib/test/test_site.py (+32/-13) Lib/test/test_zipfile.py (+8/-1) Lib/test/test_zipimport.py (+19/-20) Lib/zipfile.py (+40/-13) Makefile.pre.in (+1/-0) Python/import.c (+366/-31) Python/pythonrun.c (+2/-0) |
To merge this branch: | bzr merge lp:~barry/python/pep3147 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Python Development | Pending | ||
Review via email: mp+22648@code.launchpad.net |
Commit message
Description of the change
Work-in-progress implementation of PEP 3147
- 41150. By raymond.hettinger
-
Document sorting HowTo
- 41151. By raymond.hettinger
-
Add and update itertools recipes.
- 41152. By raymond.hettinger
-
Fix nits in itertools recipes.
- 41153. By georg.brandl
-
#8213: document behavior of -u on py3k better.
- 41154. By larry.hastings
-
Blocked revisions 79590 via svnmerge
........
r79590 | larry.hastings | 2010-04-02 04:01:35 -0700 (Fri, 02 Apr 2010) | 10 linesCapsule-related changes:
* PyCObject_AsVoidPtr( ) can now open capsules. This addresses
most of the remaining backwards-compatibility concerns about
the conversion of Python 2.7 from CObjects to capsules.
* CObjects were marked Pending Deprecation.
* Documentation about this pending deprecation was added to
cobject.h.
* The capsule source files were added to the legacy PC build
processes.
........ - 41155. By larry.hastings
-
Blocked revisions 79592 via svnmerge
........
r79592 | larry.hastings | 2010-04-02 04:18:17 -0700 (Fri, 02 Apr 2010) | 3 linesIssue #8235: _socket: Add the constant ``SO_SETFIB``. SO_SETFIB is
a socket option available on FreeBSD 7.1 and newer.
........ - 41156. By larry.hastings
-
- Issue #8235: _socket: Add the constant ``SO_SETFIB``. SO_SETFIB is
a socket option available on FreeBSD 7.1 and newer. - 41157. By ezio.melotti
-
Merged revisions 79540-79541 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk Add -Wd to the flags used to run the tests (-3 is not necessary here).
........
r79540 | ezio.melotti | 2010-04-01 01:18:09 +0300 (Thu, 01 Apr 2010) | 1 lineAdd -Wd and -3 to the flags used to run the tests.
........
r79541 | ezio.melotti | 2010-04-01 01:43:31 +0300 (Thu, 01 Apr 2010) | 1 lineAdd -Wd and -3 to the flags used to run the tests on Windows.
........ - 41158. By raymond.hettinger
-
Issue 8257: Decimal constructor to accept float argument.
- 41159. By andrew.kuchling
-
Merged revisions 79603 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79603 | andrew.kuchling | 2010-04-02 12:59:16 -0400 (Fri, 02 Apr 2010) | 1 line#4440: modernize a use of filter(), making it compatible with 3.x
........ - 41160. By antoine.pitrou
-
Furniture is not very reliable these days (buildbot failures).
- 41161. By florent.xicluna
-
(partially)
Merged revisions 79534,79537,
79539,79558, 79606 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79534 | florent.xicluna | 2010-03-31 23:21:54 +0200 (mer, 31 mar 2010) | 2 linesFix test for xml.etree when using a non-ascii path. And use check_warnings instead of catch_warnings.
........
r79537 | florent.xicluna | 2010-03-31 23:40:32 +0200 (mer, 31 mar 2010) | 2 linesFix typo
........
r79539 | florent.xicluna | 2010-04-01 00:01:03 +0200 (jeu, 01 avr 2010) | 2 linesReplace catch_warnings with check_warnings when it makes sense. Use assertRaises context manager to simplify some tests.
........
r79558 | florent.xicluna | 2010-04-01 20:17:09 +0200 (jeu, 01 avr 2010) | 2 lines#7092: Fix some -3 warnings, and fix Lib/platform.py when the path contains a double-quote.
........
r79606 | florent.xicluna | 2010-04-02 19:26:42 +0200 (ven, 02 avr 2010) | 2 linesBackport some robotparser test and skip the test if the external resource is not available.
........ - 41162. By raymond.hettinger
-
Add nice docstrings to namedtuples.
- 41163. By florent.xicluna
-
An oversight in previous merge, r79610: test_doctest is sensible to the line numbering.
- 41164. By georg.brandl
-
#8288: fix next -> __next__.
- 41165. By tarek.ziade
-
Merged revisions 79618 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79618 | tarek.ziade | 2010-04-02 23:14:04 +0200 (Fri, 02 Apr 2010) | 1 lineremoved the local copy of xxmodule, and skip only test_build_ext when xxmodule is not found, not the whole unittest
........ - 41166. By ezio.melotti
-
Blocked revisions 79582 via svnmerge
........
r79582 | georg.brandl | 2010-04-02 11:51:31 +0300 (Fri, 02 Apr 2010) | 1 lineFix typo in unicode character name.
........ - 41167. By brian.curtin
-
Change test_support to support. Fixes a failing test on Windows.
- 41168. By benjamin.peterson
-
Blocked revisions 79636,79639 via svnmerge
........
r79636 | benjamin.peterson | 2010-04-02 18:59:41 -0500 (Fri, 02 Apr 2010) | 4 linesalways check _PyString_Resize for error
also normalize how this error is checked
........
r79639 | benjamin.peterson | 2010-04-02 19:57:33 -0500 (Fri, 02 Apr 2010) | 1 linemore _PyString_Resize error checking
........ - 41169. By benjamin.peterson
-
Merged revisions 79642,79644 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79642 | benjamin.peterson | 2010-04-02 20:08:34 -0500 (Fri, 02 Apr 2010) | 1 linesplit out large test function
........
r79644 | benjamin.peterson | 2010-04-02 20:28:57 -0500 (Fri, 02 Apr 2010) | 1 linegive TypeError when trying to set T_STRING_INPLACE
........ - 41170. By victor.stinner
-
Blocked revisions 79654 via svnmerge
........
r79654 | victor.stinner | 2010-04-03 10:40:16 +0200 (sam., 03 avril 2010) | 5 linesIssue #8227: Fix C API documentation, argument parsing
* 'z', 'z#', 'z*' does also accept Unicode
* unify types name: replace "string or Unicode objet" by "string or Unicode"
........ - 41171. By tarek.ziade
-
Merged revisions 79652 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79652 | tarek.ziade | 2010-04-03 10:37:59 +0200 (Sat, 03 Apr 2010) | 1 lineIssue #1222585: Added LDCXXSHARED for C++ support
........ - 41172. By raymond.hettinger
-
Add a subtract() method to collections.
Counter( ) - 41173. By mark.dickinson
-
Merged revisions 79661 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79661 | mark.dickinson | 2010-04-03 11:27:05 +0100 (Sat, 03 Apr 2010) | 14 linesFix a couple of issues with the test_structmemb
ersType class in _testcapimodule - rename to _test_structmem
bersType to avoid the class being automatically
called by test_capi- allow space for trailing NUL in inplace_member field of all_structmembers
- use T_STRING_INPLACE instead of T_INPLACE_STRING as keyword argument
to _test_structmembersType initializer - don't attempt to initialize inplace_member field if T_STRING_INPLACE
argument wasn't supplied.
........ - 41174. By mark.dickinson
-
Merged revisions 79583,79588-79589 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79583 | mark.dickinson | 2010-04-02 09:53:22 +0100 (Fri, 02 Apr 2010) | 7 linesIssue #2531: Make float-to-decimal comparisons return correct results.
Float to decimal comparison operations now return a result based on
the numeric values of the operands. Decimal.__hash__ has also been
fixed so that Decimal and float values that compare equal have equal
hash value.
........
r79588 | mark.dickinson | 2010-04-02 11:17:07 +0100 (Fri, 02 Apr 2010) | 2 linesIssue #7279: Make comparisons involving a Decimal sNaN signal InvalidOperation.
........
r79589 | mark.dickinson | 2010-04-02 11:35:12 +0100 (Fri, 02 Apr 2010) | 6 linesIssue #7279: Make Decimal('nan') hashable. Decimal('snan') remains unhashable.
Also rewrite the Decimal __hash__ method so that it doesn't rely on
float('inf') being valid: float('inf') could raise an exception on
platforms not using IEEE 754 arithmetic.
........ - 41175. By mark.dickinson
-
Merged revisions 79629 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79629 | mark.dickinson | 2010-04-02 23:27:36 +0100 (Fri, 02 Apr 2010) | 2 linesIssue #8294: Allow float and Decimal arguments in Fraction constructor.
........ - 41176. By mark.dickinson
-
Remove unused define.
- 41177. By ezio.melotti
-
Merged revisions 79678 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79678 | ezio.melotti | 2010-04-03 17:51:00 +0300 (Sat, 03 Apr 2010) | 1 lineUse more specific assert* methods in test_decimal.
........ - 41178. By mark.dickinson
-
Clean up integer tests in test_struct, and bring them more in line with the trunk tests.
- 41179. By mark.dickinson
-
Internal refactoring in struct.pack: make all integer conversions go through get_pylong.
- 41180. By ezio.melotti
-
Add -bb to rt.bat to do some extra checks during the tests (it is already used by the non-Windows buildbots).
- 41181. By ezio.melotti
-
Blocked revisions 79624 via svnmerge
........
r79624 | ezio.melotti | 2010-04-03 00:43:10 +0300 (Sat, 03 Apr 2010) | 1 lineFix test_compiler.py that was using unittest.__file__ to find Lib/ (unittest is now a package).
........ - 41182. By benjamin.peterson
-
Blocked revisions 79693,79695 via svnmerge
........
r79693 | benjamin.peterson | 2010-04-03 10:38:38 -0500 (Sat, 03 Apr 2010) | 1 linewrap
........
r79695 | benjamin.peterson | 2010-04-03 10:40:29 -0500 (Sat, 03 Apr 2010) | 1 lineremove unneeded argument
........ - 41183. By mark.dickinson
-
Merged revisions 79699 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79699 | mark.dickinson | 2010-04-03 16:47:46 +0100 (Sat, 03 Apr 2010) | 1 lineAdd Misc/NEWS entry for r79609.
........ - 41184. By mark.dickinson
-
Merged revisions 79674 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79674 | mark.dickinson | 2010-04-03 15:05:10 +0100 (Sat, 03 Apr 2010) | 3 linesIssue #8300: Let struct.pack use __index__ to convert and pack non-integers.
Based on a patch by Meador Inge.
........ - 41185. By benjamin.peterson
-
Blocked revisions 79697-79698,79704 via svnmerge
........
r79697 | benjamin.peterson | 2010-04-03 10:44:56 -0500 (Sat, 03 Apr 2010) | 1 linesilence PyCObject warnings in bsddb
........
r79698 | benjamin.peterson | 2010-04-03 10:45:59 -0500 (Sat, 03 Apr 2010) | 1 linespelling
........
r79704 | benjamin.peterson | 2010-04-03 10:58:15 -0500 (Sat, 03 Apr 2010) | 1 lineremove deprecation warnings silence attempting
........ - 41186. By mark.dickinson
-
Blocked revisions 79707 via svnmerge
........
r79707 | mark.dickinson | 2010-04-03 17:41:20 +0100 (Sat, 03 Apr 2010) | 5 linesEnsure 'module removed' warning messages contain the word 'module' or 'package'.
This should fix the test_py3kwarn failure on OS X. test_support.
import_ module
also requires this.
........ - 41187. By mark.dickinson
-
Blocked revisions 79714 via svnmerge
........
r79714 | mark.dickinson | 2010-04-03 19:17:54 +0100 (Sat, 03 Apr 2010) | 1 lineSilence DeprecationWarnings from uses of has_key and <> in plat-mac.
........ - 41188. By benjamin.peterson
-
Blocked revisions 79712 via svnmerge
........
r79712 | raymond.hettinger | 2010-04-03 12:10:05 -0500 (Sat, 03 Apr 2010) | 1 lineSilence a compiler warning.
........ - 41189. By benjamin.peterson
-
Blocked revisions 79718-79719 via svnmerge
........
r79718 | antoine.pitrou | 2010-04-03 16:42:18 -0500 (Sat, 03 Apr 2010) | 3 linesRemove useless (?) import from r79706
........
r79719 | benjamin.peterson | 2010-04-03 16:50:40 -0500 (Sat, 03 Apr 2010) | 1 lineimport bsddb more robustly
........ - 41190. By benjamin.peterson
-
Merged revisions 79723 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79723 | benjamin.peterson | 2010-04-03 17:48:51 -0500 (Sat, 03 Apr 2010) | 1 lineensure that the locale does not affect the tokenization of identifiers
........ - 41191. By benjamin.peterson
-
Merged revisions 79725 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79725 | benjamin.peterson | 2010-04-03 18:03:35 -0500 (Sat, 03 Apr 2010) | 4 linesuse our own locale independent ctype macros
requires building pyctype.o into pgen
........ - 41192. By raymond.hettinger
-
Add count() method to collections.
deque() . - 41193. By benjamin.peterson
-
add missing decrefs
- 41194. By ezio.melotti
-
Fix versionchanged from 2.7 to 3.2 in decimal.rst.
- 41195. By ezio.melotti
-
Merged revisions 79733,79735 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79733 | ezio.melotti | 2010-04-04 09:41:27 +0300 (Sun, 04 Apr 2010) | 1 lineAdd a versionadded to Counter.subtract() doc.
........
r79735 | ezio.melotti | 2010-04-04 09:50:58 +0300 (Sun, 04 Apr 2010) | 1 lineRevert 79733 - Counter is new in 2.7, the versionadded is not necessary - and fix a typo.
........ - 41196. By ezio.melotti
-
Recorded merge of revisions 79660 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79660 | raymond.hettinger | 2010-04-03 13:22:00 +0300 (Sat, 03 Apr 2010) | 1 lineAdd subtract() method to collections.
Counter( ) objects.
........ - 41197. By ezio.melotti
-
Merged revisions 79740 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79740 | ezio.melotti | 2010-04-04 10:00:02 +0300 (Sun, 04 Apr 2010) | 1 lineUse more specific assert* methods in test_struct.
........ - 41198. By mark.dickinson
-
Merged revisions 79745 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79745 | mark.dickinson | 2010-04-04 09:43:04 +0100 (Sun, 04 Apr 2010) | 3 linesIssue #8300 (__index__ handling in struct.pack): Remove redundant check
and improve test coverage. Thanks Meador Inge for the patch.
........ - 41199. By mark.dickinson
-
Merged revisions 79751 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79751 | mark.dickinson | 2010-04-04 22:19:35 +0100 (Sun, 04 Apr 2010) | 1 lineA handful of whitespace fixes in Modules/_struct.c.
........ - 41200. By mark.dickinson
-
Merged revisions 79756 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79756 | mark.dickinson | 2010-04-04 23:09:21 +0100 (Sun, 04 Apr 2010) | 6 linesAdd versionchanged entry for Decimal(float) construction.
Also add an example of constructing a Decimal directly from a float,
update the quickstart tutorial, and tweak another couple of
sentences.
........ - 41201. By benjamin.peterson
-
Merged revisions 79762 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79762 | benjamin.peterson | 2010-04-04 18:01:03 -0500 (Sun, 04 Apr 2010) | 1 linetabify
........ - 41202. By benjamin.peterson
-
Merged revisions 79763 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79763 | benjamin.peterson | 2010-04-04 18:03:22 -0500 (Sun, 04 Apr 2010) | 1 linefix tabs
........ - 41203. By benjamin.peterson
-
Blocked revisions 79769 via svnmerge
........
r79769 | benjamin.peterson | 2010-04-04 18:23:22 -0500 (Sun, 04 Apr 2010) | 1 linefix dis on new style classes #8310
........ - 41204. By benjamin.peterson
-
factor out constant
- 41205. By ezio.melotti
-
Merged revisions 79768 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79768 | ezio.melotti | 2010-04-05 02:21:53 +0300 (Mon, 05 Apr 2010) | 1 lineFix markup in decimal.rst.
........ - 41206. By philip.jenvey
-
Merged revisions 79779 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79779 | philip.jenvey | 2010-04-04 19:51:51 -0700 (Sun, 04 Apr 2010) | 2 linesfix escape_encode to return the correct consumed size
........ - 41207. By ezio.melotti
-
Merged revisions 79781 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79781 | ezio.melotti | 2010-04-05 06:51:38 +0300 (Mon, 05 Apr 2010) | 1 line#8212: rephrase the webservers howto and fix some mistakes.
........ - 41208. By ezio.melotti
-
Merged revisions 79788 via svnmerge from
svn+ssh://<email address hidden>/python/ trunk ........
r79788 | ezio.melotti | 2010-04-05 11:16:41 +0300 (Mon, 05 Apr 2010) | 1 lineFix markup errors.
........ - 41209. By Barry Warsaw
-
branch merge
- 41210. By Barry Warsaw
-
Ensure that no .pyc file outside of __pycache__ is written by the test suite.
- 41211. By Barry Warsaw
-
merge trunk
- 41212. By Barry Warsaw
-
Many updates based on Rietveld review by Antoine Pitrou.
- 41213. By Barry Warsaw
-
trunk merge
- 41214. By Barry Warsaw
-
trunk merge
- 41215. By Barry Warsaw
-
trunk merge
- 41216. By Barry Warsaw
-
Second round of Rietveld comments.
* Added documentation for cache_from_
source( ), source_ from_cache( ), and
magic_tags.
* Use addCleanup() where appropriate.
* Other style cleanup. - 41217. By Barry Warsaw
-
Test repairs.
- 41218. By Barry Warsaw
-
trunk merge
- 41219. By Barry Warsaw
-
Fixes for Windows compatibility.
- 41220. By Barry Warsaw
-
Be more aggressive for Windows.
- 41221. By Barry Warsaw
-
trunk merge
- 41222. By Barry Warsaw
-
Benjamin makes a good point that debug_override should accept true-ish and
false-ish values (when not None) to more closely mirror a pure-Python
implementation. - 41223. By Barry Warsaw
-
* Add __cached__ attribute to modules.
* PyImport_ExecCodeModuleE x() gets a new parameter. - 41224. By Barry Warsaw
-
Remove some unnecessary code.
- 41225. By Barry Warsaw
-
Based on Guido's recommendation, add PyImport_
ExecCodeModuleE xEx() - 41226. By Barry Warsaw
-
trunk merge
- 41227. By Barry Warsaw
-
* PyImport_
ExecCodeModuleE xEx() -> PyImport_ ExecCodeModuleW ithPathnames( )
* Document the above.
* Added PyImport_GetMagicTag( ) and document.
* Removed imp.magic_tags and replaced with imp.get_tag(). - 41228. By Barry Warsaw
-
More responses to Rietveld and mailing list comments. The most important
change here is an additional guard against buffer overflows in
make_compiled_pathname( ). - 41229. By Barry Warsaw
-
trunk merge
- 41230. By Barry Warsaw
-
Patches from Brian Curtin for Windows.
- 41231. By Barry Warsaw
-
Support -b flag for compile to create legacy .pyc files. This does not delete
the source files. - 41232. By Barry Warsaw
-
Document extended compileall options.
- 41233. By Barry Warsaw
-
trunk merge
- 41234. By Barry Warsaw
-
Make sure __cache__ shows up in modules executed via command line and -m
(runpy). Update runpy documentation. - 41235. By Barry Warsaw
-
Typo.
- 41236. By Barry Warsaw
-
trunk merge
- 41237. By Barry Warsaw
-
* abs__file__() -> abs_paths() since this now also modifies m.__cached__
* actually make test_abs_path() not suck. - 41238. By Barry Warsaw
-
trunk merge
- 41239. By Barry Warsaw
-
trunk merge
Preview Diff
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2010-04-11 20:49:28 +0000 |
3 | +++ .bzrignore 2010-04-16 18:55:41 +0000 |
4 | @@ -33,3 +33,4 @@ |
5 | Lib/test/data/* |
6 | Lib/lib2to3/Grammar*.pickle |
7 | Lib/lib2to3/PatternGrammar*.pickle |
8 | +__pycache__ |
9 | |
10 | === modified file '.hgignore' |
11 | --- .hgignore 2010-04-13 16:37:01 +0000 |
12 | +++ .hgignore 2010-04-16 18:55:41 +0000 |
13 | @@ -54,3 +54,4 @@ |
14 | PCbuild/*.ncb |
15 | PCbuild/*.bsc |
16 | PCbuild/Win32-temp-* |
17 | +__pycache__ |
18 | |
19 | === modified file 'Doc/c-api/import.rst' |
20 | --- Doc/c-api/import.rst 2010-04-11 15:12:57 +0000 |
21 | +++ Doc/c-api/import.rst 2010-04-16 18:55:41 +0000 |
22 | @@ -124,12 +124,24 @@ |
23 | If *name* points to a dotted name of the form ``package.module``, any package |
24 | structures not already created will still not be created. |
25 | |
26 | + See also :func:`PyImport_ExecCodeModuleEx` and |
27 | + :func:`PyImport_ExecCodeModuleWithPathnames`. |
28 | + |
29 | |
30 | .. cfunction:: PyObject* PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname) |
31 | |
32 | Like :cfunc:`PyImport_ExecCodeModule`, but the :attr:`__file__` attribute of |
33 | the module object is set to *pathname* if it is non-``NULL``. |
34 | |
35 | + See also :func:`PyImport_ExecCodeModuleWithPathnames`. |
36 | + |
37 | + |
38 | +.. cfunction:: PyObject* PyImport_ExecCodeModuleWithPathnames(char *name, PyObject *co, char *pathname, char *cpathname) |
39 | + |
40 | + Like :cfunc:`PyImport_ExecCodeModuleEx`, but the :attr:`__cached__` |
41 | + attribute of the module object is set to *cpathname* if it is |
42 | + non-``NULL``. Of the three functions, this is the preferred one to use. |
43 | + |
44 | |
45 | .. cfunction:: long PyImport_GetMagicNumber() |
46 | |
47 | @@ -138,6 +150,11 @@ |
48 | of the bytecode file, in little-endian byte order. |
49 | |
50 | |
51 | +.. cfunction:: const char * PyImport_GetMagicTag() |
52 | + |
53 | + Return the magic tag string for :pep:`3147` format Python bytecode file |
54 | + names. |
55 | + |
56 | .. cfunction:: PyObject* PyImport_GetModuleDict() |
57 | |
58 | Return the dictionary used for the module administration (a.k.a. |
59 | |
60 | === modified file 'Doc/library/compileall.rst' |
61 | --- Doc/library/compileall.rst 2009-05-17 11:29:12 +0000 |
62 | +++ Doc/library/compileall.rst 2010-04-16 18:55:41 +0000 |
63 | @@ -17,9 +17,11 @@ |
64 | sys.path``. Printing lists of the files compiled can be disabled with the |
65 | :option:`-q` flag. In addition, the :option:`-x` option takes a regular |
66 | expression argument. All files that match the expression will be skipped. |
67 | - |
68 | - |
69 | -.. function:: compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None, quiet=False) |
70 | +The :option:`-b` flag may be given to write legacy ``.pyc`` file path names, |
71 | +otherwise :pep:`3147` style byte-compiled path names are written. |
72 | + |
73 | + |
74 | +.. function:: compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None, quiet=False, legacy=False) |
75 | |
76 | Recursively descend the directory tree named by *dir*, compiling all :file:`.py` |
77 | files along the way. The *maxlevels* parameter is used to limit the depth of |
78 | @@ -34,12 +36,16 @@ |
79 | If *quiet* is true, nothing is printed to the standard output in normal |
80 | operation. |
81 | |
82 | - |
83 | -.. function:: compile_path(skip_curdir=True, maxlevels=0, force=False) |
84 | + If *legacy* is true, old-style ``.pyc`` file path names are written, |
85 | + otherwise (the default), :pep:`3147` style path names are written. |
86 | + |
87 | + |
88 | +.. function:: compile_path(skip_curdir=True, maxlevels=0, force=False, legacy=False) |
89 | |
90 | Byte-compile all the :file:`.py` files found along ``sys.path``. If |
91 | *skip_curdir* is true (the default), the current directory is not included in |
92 | - the search. The *maxlevels* and *force* parameters default to ``0`` and are |
93 | + the search. The *maxlevels* parameter defaults to ``0``, and the *force* |
94 | + and *legacy* parameters default to ``False``. All are |
95 | passed to the :func:`compile_dir` function. |
96 | |
97 | To force a recompile of all the :file:`.py` files in the :file:`Lib/` |
98 | |
99 | === modified file 'Doc/library/imp.rst' |
100 | --- Doc/library/imp.rst 2009-07-17 09:42:05 +0000 |
101 | +++ Doc/library/imp.rst 2010-04-16 18:55:41 +0000 |
102 | @@ -204,8 +204,41 @@ |
103 | function does nothing. |
104 | |
105 | |
106 | -The following constants with integer values, defined in this module, are used to |
107 | -indicate the search result of :func:`find_module`. |
108 | +The following functions and data provide conveniences for handling :pep:`3147` |
109 | +byte-compiled file paths. |
110 | + |
111 | +.. versionadded:: 3.2 |
112 | + |
113 | +.. function:: cache_from_source(path, debug_override=None) |
114 | + |
115 | + Return the PEP 3147 path to the byte-compiled file associated with the |
116 | + source *path*. For example, if *path* is ``/foo/bar/baz.py`` the return |
117 | + value would be ``/foo/bar/__pycache__/baz.cpython-32.pyc`` for Python 3.2. |
118 | + The ``cpython-32`` string comes from the current magic tag (see |
119 | + :func:`get_tag`). The returned path will end in ``.pyc`` when |
120 | + ``__debug__`` is True or ``.pyo`` for an optimized Python |
121 | + (i.e. ``__debug__`` is False). By passing in True or False for |
122 | + *debug_override* you can override the system's value for ``__debug__`` for |
123 | + extension selection. |
124 | + |
125 | + *path* need not exist. |
126 | + |
127 | +.. function:: source_from_cache(path) |
128 | + |
129 | + Given the *path* to a PEP 3147 file name, return the associated source code |
130 | + file path. For example, if *path* is |
131 | + ``/foo/bar/__pycache__/baz.cpython-32.pyc`` the returned path would be |
132 | + ``/foo/bar/baz.py``. *path* need not exist, however if it does not conform |
133 | + to PEP 3147 format, a ``ValueError`` is raised. |
134 | + |
135 | +.. function:: get_tag() |
136 | + |
137 | + Return the PEP 3147 magic tag string matching this version of Python's |
138 | + magic number, as returned by :func:`get_magic`. |
139 | + |
140 | + |
141 | +The following constants with integer values, defined in this module, are used |
142 | +to indicate the search result of :func:`find_module`. |
143 | |
144 | |
145 | .. data:: PY_SOURCE |
146 | |
147 | === modified file 'Doc/library/py_compile.rst' |
148 | --- Doc/library/py_compile.rst 2009-09-02 19:34:52 +0000 |
149 | +++ Doc/library/py_compile.rst 2010-04-16 18:55:41 +0000 |
150 | @@ -26,12 +26,16 @@ |
151 | |
152 | Compile a source file to byte-code and write out the byte-code cache file. The |
153 | source code is loaded from the file name *file*. The byte-code is written to |
154 | - *cfile*, which defaults to *file* ``+`` ``'c'`` (``'o'`` if optimization is |
155 | - enabled in the current interpreter). If *dfile* is specified, it is used as the |
156 | + *cfile*, which defaults to the :PEP:`3147` path, ending in ``.pyc`` |
157 | + (``'.pyo`` if optimization is enabled in the current interpreter). For |
158 | + example, if *file* is ``/foo/bar/baz.py`` *cfile* will default to |
159 | + ``/foo/bar/__pycache__/baz.cpython-32.pyc`` for Python 3.2. If *dfile* is specified, it is used as the |
160 | name of the source file in error messages instead of *file*. If *doraise* is |
161 | true, a :exc:`PyCompileError` is raised when an error is encountered while |
162 | compiling *file*. If *doraise* is false (the default), an error string is |
163 | - written to ``sys.stderr``, but no exception is raised. |
164 | + written to ``sys.stderr``, but no exception is raised. This function |
165 | + returns the path to byte-compiled file, i.e. whatever *cfile* value was |
166 | + used. |
167 | |
168 | |
169 | .. function:: main(args=None) |
170 | |
171 | === modified file 'Doc/library/runpy.rst' |
172 | --- Doc/library/runpy.rst 2010-01-04 09:29:10 +0000 |
173 | +++ Doc/library/runpy.rst 2010-04-16 18:55:41 +0000 |
174 | @@ -32,7 +32,8 @@ |
175 | below are defined in the supplied dictionary, those definitions are |
176 | overridden by :func:`run_module`. |
177 | |
178 | - The special global variables ``__name__``, ``__file__``, ``__loader__`` |
179 | + The special global variables ``__name__``, ``__file__``, ``__cached__``, |
180 | + ``__loader__`` |
181 | and ``__package__`` are set in the globals dictionary before the module |
182 | code is executed (Note that this is a minimal set of variables - other |
183 | variables may be set implicitly as an interpreter implementation detail). |
184 | @@ -45,6 +46,8 @@ |
185 | loader does not make filename information available, this variable is set |
186 | to :const:`None`. |
187 | |
188 | + ``__cached__`` will be set to ``None``. |
189 | + |
190 | ``__loader__`` is set to the PEP 302 module loader used to retrieve the |
191 | code for the module (This loader may be a wrapper around the standard |
192 | import mechanism). |
193 | |
194 | === modified file 'Include/import.h' |
195 | --- Include/import.h 2009-10-04 19:32:25 +0000 |
196 | +++ Include/import.h 2010-04-16 18:55:41 +0000 |
197 | @@ -8,9 +8,12 @@ |
198 | #endif |
199 | |
200 | PyAPI_FUNC(long) PyImport_GetMagicNumber(void); |
201 | +PyAPI_FUNC(const char *) PyImport_GetMagicTag(void); |
202 | PyAPI_FUNC(PyObject *) PyImport_ExecCodeModule(char *name, PyObject *co); |
203 | PyAPI_FUNC(PyObject *) PyImport_ExecCodeModuleEx( |
204 | char *name, PyObject *co, char *pathname); |
205 | +PyAPI_FUNC(PyObject *) PyImport_ExecCodeModuleWithPathnames( |
206 | + char *name, PyObject *co, char *pathname, char *cpathname); |
207 | PyAPI_FUNC(PyObject *) PyImport_GetModuleDict(void); |
208 | PyAPI_FUNC(PyObject *) PyImport_AddModule(const char *name); |
209 | PyAPI_FUNC(PyObject *) PyImport_ImportModule(const char *name); |
210 | |
211 | === modified file 'Lib/compileall.py' |
212 | --- Lib/compileall.py 2010-03-21 23:13:07 +0000 |
213 | +++ Lib/compileall.py 2010-04-16 18:55:41 +0000 |
214 | @@ -12,6 +12,7 @@ |
215 | |
216 | """ |
217 | import os |
218 | +import errno |
219 | import sys |
220 | import py_compile |
221 | import struct |
222 | @@ -20,7 +21,7 @@ |
223 | __all__ = ["compile_dir","compile_file","compile_path"] |
224 | |
225 | def compile_dir(dir, maxlevels=10, ddir=None, |
226 | - force=0, rx=None, quiet=0): |
227 | + force=False, rx=None, quiet=False, legacy=False): |
228 | """Byte-compile all modules in the given directory tree. |
229 | |
230 | Arguments (only dir is required): |
231 | @@ -29,8 +30,9 @@ |
232 | maxlevels: maximum recursion level (default 10) |
233 | ddir: if given, purported directory name (this is the |
234 | directory name that will show up in error messages) |
235 | - force: if 1, force compilation, even if timestamps are up-to-date |
236 | - quiet: if 1, be quiet during compilation |
237 | + force: if True, force compilation, even if timestamps are up-to-date |
238 | + quiet: if True, be quiet during compilation |
239 | + legacy: if True, produce legacy pyc paths instead of PEP 3147 paths |
240 | |
241 | """ |
242 | if not quiet: |
243 | @@ -49,24 +51,26 @@ |
244 | else: |
245 | dfile = None |
246 | if not os.path.isdir(fullname): |
247 | - if not compile_file(fullname, ddir, force, rx, quiet): |
248 | + if not compile_file(fullname, ddir, force, rx, quiet, legacy): |
249 | success = 0 |
250 | elif maxlevels > 0 and \ |
251 | name != os.curdir and name != os.pardir and \ |
252 | os.path.isdir(fullname) and \ |
253 | not os.path.islink(fullname): |
254 | if not compile_dir(fullname, maxlevels - 1, dfile, force, rx, |
255 | - quiet): |
256 | + quiet, legacy): |
257 | success = 0 |
258 | return success |
259 | |
260 | -def compile_file(fullname, ddir=None, force=0, rx=None, quiet=0): |
261 | +def compile_file(fullname, ddir=None, force=0, rx=None, quiet=False, |
262 | + legacy=False): |
263 | """Byte-compile file. |
264 | - file: the file to byte-compile |
265 | + fullname: the file to byte-compile |
266 | ddir: if given, purported directory name (this is the |
267 | directory name that will show up in error messages) |
268 | - force: if 1, force compilation, even if timestamps are up-to-date |
269 | - quiet: if 1, be quiet during compilation |
270 | + force: if True, force compilation, even if timestamps are up-to-date |
271 | + quiet: if True, be quiet during compilation |
272 | + legacy: if True, produce legacy pyc paths instead of PEP 3147 paths |
273 | |
274 | """ |
275 | success = 1 |
276 | @@ -80,13 +84,22 @@ |
277 | if mo: |
278 | return success |
279 | if os.path.isfile(fullname): |
280 | + if legacy: |
281 | + cfile = fullname + ('c' if __debug__ else 'o') |
282 | + else: |
283 | + cfile = imp.cache_from_source(fullname) |
284 | + cache_dir = os.path.dirname(cfile) |
285 | + try: |
286 | + os.mkdir(cache_dir) |
287 | + except OSError as error: |
288 | + if error.errno != errno.EEXIST: |
289 | + raise |
290 | head, tail = name[:-3], name[-3:] |
291 | if tail == '.py': |
292 | if not force: |
293 | try: |
294 | mtime = int(os.stat(fullname).st_mtime) |
295 | expect = struct.pack('<4sl', imp.get_magic(), mtime) |
296 | - cfile = fullname + (__debug__ and 'c' or 'o') |
297 | with open(cfile, 'rb') as chandle: |
298 | actual = chandle.read(8) |
299 | if expect == actual: |
300 | @@ -96,14 +109,15 @@ |
301 | if not quiet: |
302 | print('Compiling', fullname, '...') |
303 | try: |
304 | - ok = py_compile.compile(fullname, None, dfile, True) |
305 | + ok = py_compile.compile(fullname, cfile, dfile, True) |
306 | except py_compile.PyCompileError as err: |
307 | if quiet: |
308 | print('*** Error compiling', fullname, '...') |
309 | else: |
310 | print('*** ', end='') |
311 | # escape non-printable characters in msg |
312 | - msg = err.msg.encode(sys.stdout.encoding, errors='backslashreplace') |
313 | + msg = err.msg.encode(sys.stdout.encoding, |
314 | + errors='backslashreplace') |
315 | msg = msg.decode(sys.stdout.encoding) |
316 | print(msg) |
317 | success = 0 |
318 | @@ -119,15 +133,17 @@ |
319 | success = 0 |
320 | return success |
321 | |
322 | -def compile_path(skip_curdir=1, maxlevels=0, force=0, quiet=0): |
323 | +def compile_path(skip_curdir=1, maxlevels=0, force=False, quiet=False, |
324 | + legacy=False): |
325 | """Byte-compile all module on sys.path. |
326 | |
327 | Arguments (all optional): |
328 | |
329 | skip_curdir: if true, skip current directory (default true) |
330 | maxlevels: max recursion level (default 0) |
331 | - force: as for compile_dir() (default 0) |
332 | - quiet: as for compile_dir() (default 0) |
333 | + force: as for compile_dir() (default False) |
334 | + quiet: as for compile_dir() (default False) |
335 | + legacy: as for compile_dir() (default False) |
336 | |
337 | """ |
338 | success = 1 |
339 | @@ -136,7 +152,8 @@ |
340 | print('Skipping current directory') |
341 | else: |
342 | success = success and compile_dir(dir, maxlevels, None, |
343 | - force, quiet=quiet) |
344 | + force, quiet=quiet, |
345 | + legacy=legacy) |
346 | return success |
347 | |
348 | def expand_args(args, flist): |
349 | @@ -162,10 +179,10 @@ |
350 | """Script main program.""" |
351 | import getopt |
352 | try: |
353 | - opts, args = getopt.getopt(sys.argv[1:], 'lfqd:x:i:') |
354 | + opts, args = getopt.getopt(sys.argv[1:], 'lfqd:x:i:b') |
355 | except getopt.error as msg: |
356 | print(msg) |
357 | - print("usage: python compileall.py [-l] [-f] [-q] [-d destdir] " \ |
358 | + print("usage: python compileall.py [-l] [-f] [-q] [-d destdir] " |
359 | "[-x regexp] [-i list] [directory|file ...]") |
360 | print("-l: don't recurse down") |
361 | print("-f: force rebuild even if timestamps are up-to-date") |
362 | @@ -174,23 +191,27 @@ |
363 | print(" if no directory arguments, -l sys.path is assumed") |
364 | print("-x regexp: skip files matching the regular expression regexp") |
365 | print(" the regexp is searched for in the full path of the file") |
366 | - print("-i list: expand list with its content (file and directory names)") |
367 | + print("-i list: expand list with its content " |
368 | + "(file and directory names)") |
369 | + print("-b: Produce legacy byte-compile file paths") |
370 | sys.exit(2) |
371 | maxlevels = 10 |
372 | ddir = None |
373 | - force = 0 |
374 | - quiet = 0 |
375 | + force = False |
376 | + quiet = False |
377 | rx = None |
378 | flist = None |
379 | + legacy = False |
380 | for o, a in opts: |
381 | if o == '-l': maxlevels = 0 |
382 | if o == '-d': ddir = a |
383 | - if o == '-f': force = 1 |
384 | - if o == '-q': quiet = 1 |
385 | + if o == '-f': force = True |
386 | + if o == '-q': quiet = True |
387 | if o == '-x': |
388 | import re |
389 | rx = re.compile(a) |
390 | if o == '-i': flist = a |
391 | + if o == '-b': legacy = True |
392 | if ddir: |
393 | if len(args) != 1 and not os.path.isdir(args[0]): |
394 | print("-d destdir require exactly one directory argument") |
395 | @@ -207,13 +228,14 @@ |
396 | for arg in args: |
397 | if os.path.isdir(arg): |
398 | if not compile_dir(arg, maxlevels, ddir, |
399 | - force, rx, quiet): |
400 | + force, rx, quiet, legacy): |
401 | success = 0 |
402 | else: |
403 | - if not compile_file(arg, ddir, force, rx, quiet): |
404 | + if not compile_file(arg, ddir, force, rx, |
405 | + quiet, legacy): |
406 | success = 0 |
407 | else: |
408 | - success = compile_path() |
409 | + success = compile_path(legacy=legacy) |
410 | except KeyboardInterrupt: |
411 | print("\n[interrupt]") |
412 | success = 0 |
413 | |
414 | === modified file 'Lib/importlib/_bootstrap.py' |
415 | --- Lib/importlib/_bootstrap.py 2010-03-19 20:44:28 +0000 |
416 | +++ Lib/importlib/_bootstrap.py 2010-04-16 18:55:41 +0000 |
417 | @@ -488,6 +488,16 @@ |
418 | |
419 | """Load a module from a source or bytecode file.""" |
420 | |
421 | + def _find_path(self, ext_type): |
422 | + """Return PEP 3147 path if ext_type is PY_COMPILED, otherwise |
423 | + super()._find_path() is called.""" |
424 | + if ext_type == imp.PY_COMPILED: |
425 | + # We don't really care what the extension on self._base_path is, |
426 | + # as long as it has exactly one dot. |
427 | + bytecode_path = imp.cache_from_source(self._base_path + '.py') |
428 | + return (bytecode_path if _path_exists(bytecode_path) else None) |
429 | + return super()._find_path(ext_type) |
430 | + |
431 | @_check_name |
432 | def source_mtime(self, name): |
433 | """Return the modification time of the source for the specified |
434 | @@ -515,7 +525,16 @@ |
435 | """ |
436 | bytecode_path = self.bytecode_path(name) |
437 | if not bytecode_path: |
438 | - bytecode_path = self._base_path + _suffix_list(imp.PY_COMPILED)[0] |
439 | + source_path = self.source_path(name) |
440 | + bytecode_path = imp.cache_from_source(source_path) |
441 | + # Ensure that the __pycache__ directory exists. We can't use |
442 | + # os.path.dirname() here. |
443 | + dirname, sep, basename = bytecode_path.rpartition(path_sep) |
444 | + try: |
445 | + _os.mkdir(dirname) |
446 | + except OSError as error: |
447 | + if error.errno != errno.EEXIST: |
448 | + raise |
449 | try: |
450 | # Assuming bytes. |
451 | with _closing(_io.FileIO(bytecode_path, 'w')) as bytecode_file: |
452 | |
453 | === modified file 'Lib/importlib/test/__main__.py' |
454 | --- Lib/importlib/test/__main__.py 2010-03-19 20:44:28 +0000 |
455 | +++ Lib/importlib/test/__main__.py 2010-04-16 18:55:41 +0000 |
456 | @@ -13,7 +13,12 @@ |
457 | |
458 | |
459 | def test_main(): |
460 | - start_dir = os.path.dirname(__file__) |
461 | + if '__pycache__' in __file__: |
462 | + parts = __file__.split(os.path.sep) |
463 | + start_dir = sep.join(parts[:-2]) |
464 | + else: |
465 | + start_dir = os.path.dirname(__file__) |
466 | + # XXX 2010-03-18 barry: Fix __file__ |
467 | top_dir = os.path.dirname(os.path.dirname(start_dir)) |
468 | test_loader = unittest.TestLoader() |
469 | if '--builtin' in sys.argv: |
470 | |
471 | === modified file 'Lib/importlib/test/source/test_file_loader.py' |
472 | --- Lib/importlib/test/source/test_file_loader.py 2010-03-19 20:44:28 +0000 |
473 | +++ Lib/importlib/test/source/test_file_loader.py 2010-04-16 18:55:41 +0000 |
474 | @@ -127,7 +127,7 @@ |
475 | except KeyError: |
476 | pass |
477 | py_compile.compile(mapping[name]) |
478 | - bytecode_path = source_util.bytecode_path(mapping[name]) |
479 | + bytecode_path = imp.cache_from_source(mapping[name]) |
480 | with open(bytecode_path, 'rb') as file: |
481 | bc = file.read() |
482 | new_bc = manipulator(bc) |
483 | @@ -226,7 +226,7 @@ |
484 | zeros = b'\x00\x00\x00\x00' |
485 | with source_util.create_modules('_temp') as mapping: |
486 | py_compile.compile(mapping['_temp']) |
487 | - bytecode_path = source_util.bytecode_path(mapping['_temp']) |
488 | + bytecode_path = imp.cache_from_source(mapping['_temp']) |
489 | with open(bytecode_path, 'r+b') as bytecode_file: |
490 | bytecode_file.seek(4) |
491 | bytecode_file.write(zeros) |
492 | @@ -242,9 +242,10 @@ |
493 | def test_bad_marshal(self): |
494 | # Bad marshal data should raise a ValueError. |
495 | with source_util.create_modules('_temp') as mapping: |
496 | - bytecode_path = source_util.bytecode_path(mapping['_temp']) |
497 | + bytecode_path = imp.cache_from_source(mapping['_temp']) |
498 | source_mtime = os.path.getmtime(mapping['_temp']) |
499 | source_timestamp = importlib._w_long(source_mtime) |
500 | + source_util.ensure_bytecode_path(bytecode_path) |
501 | with open(bytecode_path, 'wb') as bytecode_file: |
502 | bytecode_file.write(imp.get_magic()) |
503 | bytecode_file.write(source_timestamp) |
504 | @@ -260,7 +261,7 @@ |
505 | with source_util.create_modules('_temp') as mapping: |
506 | # Create bytecode that will need to be re-created. |
507 | py_compile.compile(mapping['_temp']) |
508 | - bytecode_path = source_util.bytecode_path(mapping['_temp']) |
509 | + bytecode_path = imp.cache_from_source(mapping['_temp']) |
510 | with open(bytecode_path, 'r+b') as bytecode_file: |
511 | bytecode_file.seek(0) |
512 | bytecode_file.write(b'\x00\x00\x00\x00') |
513 | |
514 | === modified file 'Lib/importlib/test/source/test_finder.py' |
515 | --- Lib/importlib/test/source/test_finder.py 2010-03-19 20:44:28 +0000 |
516 | +++ Lib/importlib/test/source/test_finder.py 2010-04-16 18:55:41 +0000 |
517 | @@ -1,7 +1,9 @@ |
518 | from importlib import _bootstrap |
519 | from .. import abc |
520 | from . import util as source_util |
521 | +from test.support import make_legacy_pyc |
522 | import os |
523 | +import errno |
524 | import py_compile |
525 | import unittest |
526 | import warnings |
527 | @@ -52,6 +54,14 @@ |
528 | if unlink: |
529 | for name in unlink: |
530 | os.unlink(mapping[name]) |
531 | + try: |
532 | + make_legacy_pyc(mapping[name]) |
533 | + except OSError as error: |
534 | + # Some tests do not set compile_=True so the source |
535 | + # module will not get compiled and there will be no |
536 | + # PEP 3147 pyc file to rename. |
537 | + if error.errno != errno.ENOENT: |
538 | + raise |
539 | loader = self.import_(mapping['.root'], test) |
540 | self.assertTrue(hasattr(loader, 'load_module')) |
541 | return loader |
542 | @@ -60,7 +70,8 @@ |
543 | # [top-level source] |
544 | self.run_test('top_level') |
545 | # [top-level bc] |
546 | - self.run_test('top_level', compile_={'top_level'}, unlink={'top_level'}) |
547 | + self.run_test('top_level', compile_={'top_level'}, |
548 | + unlink={'top_level'}) |
549 | # [top-level both] |
550 | self.run_test('top_level', compile_={'top_level'}) |
551 | |
552 | |
553 | === modified file 'Lib/importlib/test/source/test_source_encoding.py' |
554 | --- Lib/importlib/test/source/test_source_encoding.py 2010-03-19 20:44:28 +0000 |
555 | +++ Lib/importlib/test/source/test_source_encoding.py 2010-04-16 18:55:41 +0000 |
556 | @@ -33,7 +33,7 @@ |
557 | |
558 | def run_test(self, source): |
559 | with source_util.create_modules(self.module_name) as mapping: |
560 | - with open(mapping[self.module_name], 'wb')as file: |
561 | + with open(mapping[self.module_name], 'wb') as file: |
562 | file.write(source) |
563 | loader = _bootstrap._PyPycFileLoader(self.module_name, |
564 | mapping[self.module_name], False) |
565 | |
566 | === modified file 'Lib/importlib/test/source/util.py' |
567 | --- Lib/importlib/test/source/util.py 2010-03-19 20:44:28 +0000 |
568 | +++ Lib/importlib/test/source/util.py 2010-04-16 18:55:41 +0000 |
569 | @@ -1,5 +1,6 @@ |
570 | from .. import util |
571 | import contextlib |
572 | +import errno |
573 | import functools |
574 | import imp |
575 | import os |
576 | @@ -26,14 +27,16 @@ |
577 | return wrapper |
578 | |
579 | |
580 | -def bytecode_path(source_path): |
581 | - for suffix, _, type_ in imp.get_suffixes(): |
582 | - if type_ == imp.PY_COMPILED: |
583 | - bc_suffix = suffix |
584 | - break |
585 | - else: |
586 | - raise ValueError("no bytecode suffix is defined") |
587 | - return os.path.splitext(source_path)[0] + bc_suffix |
588 | +def ensure_bytecode_path(bytecode_path): |
589 | + """Ensure that the __pycache__ directory for PEP 3147 pyc file exists. |
590 | + |
591 | + :param bytecode_path: File system path to PEP 3147 pyc file. |
592 | + """ |
593 | + try: |
594 | + os.mkdir(os.path.dirname(bytecode_path)) |
595 | + except OSError as error: |
596 | + if error.errno != errno.EEXIST: |
597 | + raise |
598 | |
599 | |
600 | @contextlib.contextmanager |
601 | |
602 | === modified file 'Lib/importlib/util.py' |
603 | --- Lib/importlib/util.py 2010-03-19 20:44:28 +0000 |
604 | +++ Lib/importlib/util.py 2010-04-16 18:55:41 +0000 |
605 | @@ -1,4 +1,5 @@ |
606 | """Utility code for constructing importers, etc.""" |
607 | + |
608 | from ._bootstrap import module_for_loader |
609 | from ._bootstrap import set_loader |
610 | from ._bootstrap import set_package |
611 | |
612 | === modified file 'Lib/inspect.py' |
613 | --- Lib/inspect.py 2010-03-30 17:42:32 +0000 |
614 | +++ Lib/inspect.py 2010-04-16 18:55:41 +0000 |
615 | @@ -54,6 +54,7 @@ |
616 | """Return true if the object is a module. |
617 | |
618 | Module objects provide these attributes: |
619 | + __cached__ pathname to byte compiled file |
620 | __doc__ documentation string |
621 | __file__ filename (missing for built-in modules)""" |
622 | return isinstance(object, types.ModuleType) |
623 | |
624 | === modified file 'Lib/py_compile.py' |
625 | --- Lib/py_compile.py 2010-03-31 20:36:22 +0000 |
626 | +++ Lib/py_compile.py 2010-04-16 18:55:41 +0000 |
627 | @@ -4,6 +4,7 @@ |
628 | """ |
629 | |
630 | import builtins |
631 | +import errno |
632 | import imp |
633 | import marshal |
634 | import os |
635 | @@ -37,16 +38,18 @@ |
636 | can be accesses as class variable 'file' |
637 | |
638 | msg: string message to be written as error message |
639 | - If no value is given, a default exception message will be given, |
640 | - consistent with 'standard' py_compile output. |
641 | - message (or default) can be accesses as class variable 'msg' |
642 | + If no value is given, a default exception message will be |
643 | + given, consistent with 'standard' py_compile output. |
644 | + message (or default) can be accesses as class variable |
645 | + 'msg' |
646 | |
647 | """ |
648 | |
649 | def __init__(self, exc_type, exc_value, file, msg=''): |
650 | exc_type_name = exc_type.__name__ |
651 | if exc_type is SyntaxError: |
652 | - tbtext = ''.join(traceback.format_exception_only(exc_type, exc_value)) |
653 | + tbtext = ''.join(traceback.format_exception_only( |
654 | + exc_type, exc_value)) |
655 | errmsg = tbtext.replace('File "<string>"', 'File "%s"' % file) |
656 | else: |
657 | errmsg = "Sorry: %s: %s" % (exc_type_name,exc_value) |
658 | @@ -64,7 +67,7 @@ |
659 | |
660 | def wr_long(f, x): |
661 | """Internal; write a 32-bit int to a file in little-endian order.""" |
662 | - f.write(bytes([x & 0xff, |
663 | + f.write(bytes([x & 0xff, |
664 | (x >> 8) & 0xff, |
665 | (x >> 16) & 0xff, |
666 | (x >> 24) & 0xff])) |
667 | @@ -72,20 +75,18 @@ |
668 | def compile(file, cfile=None, dfile=None, doraise=False): |
669 | """Byte-compile one Python source file to Python bytecode. |
670 | |
671 | - Arguments: |
672 | - |
673 | - file: source filename |
674 | - cfile: target filename; defaults to source with 'c' or 'o' appended |
675 | - ('c' normally, 'o' in optimizing mode, giving .pyc or .pyo) |
676 | - dfile: purported filename; defaults to source (this is the filename |
677 | - that will show up in error messages) |
678 | - doraise: flag indicating whether or not an exception should be |
679 | - raised when a compile error is found. If an exception |
680 | - occurs and this flag is set to False, a string |
681 | - indicating the nature of the exception will be printed, |
682 | - and the function will return to the caller. If an |
683 | - exception occurs and this flag is set to True, a |
684 | - PyCompileError exception will be raised. |
685 | + :param file: The source file name. |
686 | + :param cfile: The target byte compiled file name. When not given, this |
687 | + defaults to the PEP 3147 location. |
688 | + :param dfile: Purported file name, i.e. the file name that shows up in |
689 | + error messages. Defaults to the source file name. |
690 | + :param doraise: Flag indicating whether or not an exception should be |
691 | + raised when a compile error is found. If an exception occurs and this |
692 | + flag is set to False, a string indicating the nature of the exception |
693 | + will be printed, and the function will return to the caller. If an |
694 | + exception occurs and this flag is set to True, a PyCompileError |
695 | + exception will be raised. |
696 | + :return: Path to the resulting byte compiled file. |
697 | |
698 | Note that it isn't necessary to byte-compile Python modules for |
699 | execution efficiency -- Python itself byte-compiles a module when |
700 | @@ -102,7 +103,6 @@ |
701 | See compileall.py for a script/module that uses this module to |
702 | byte-compile all installed files (or all files in selected |
703 | directories). |
704 | - |
705 | """ |
706 | with open(file, "rb") as f: |
707 | encoding = tokenize.detect_encoding(f.readline)[0] |
708 | @@ -122,7 +122,12 @@ |
709 | sys.stderr.write(py_exc.msg + '\n') |
710 | return |
711 | if cfile is None: |
712 | - cfile = file + (__debug__ and 'c' or 'o') |
713 | + cfile = imp.cache_from_source(file) |
714 | + try: |
715 | + os.mkdir(os.path.dirname(cfile)) |
716 | + except OSError as error: |
717 | + if error.errno != errno.EEXIST: |
718 | + raise |
719 | with open(cfile, 'wb') as fc: |
720 | fc.write(b'\0\0\0\0') |
721 | wr_long(fc, timestamp) |
722 | @@ -130,6 +135,7 @@ |
723 | fc.flush() |
724 | fc.seek(0, 0) |
725 | fc.write(MAGIC) |
726 | + return cfile |
727 | |
728 | def main(args=None): |
729 | """Compile several source files. |
730 | |
731 | === modified file 'Lib/pydoc.py' |
732 | --- Lib/pydoc.py 2010-04-01 03:05:25 +0000 |
733 | +++ Lib/pydoc.py 2010-04-16 18:55:41 +0000 |
734 | @@ -159,7 +159,8 @@ |
735 | """Decide whether to show documentation on a variable.""" |
736 | # Certain special names are redundant. |
737 | _hidden_names = ('__builtins__', '__doc__', '__file__', '__path__', |
738 | - '__module__', '__name__', '__slots__', '__package__') |
739 | + '__module__', '__name__', '__slots__', '__package__', |
740 | + '__cached__') |
741 | if name in _hidden_names: return 0 |
742 | # Private names are hidden, but special names are displayed. |
743 | if name.startswith('__') and name.endswith('__'): return 1 |
744 | |
745 | === modified file 'Lib/runpy.py' |
746 | --- Lib/runpy.py 2009-12-20 17:28:31 +0000 |
747 | +++ Lib/runpy.py 2010-04-16 18:55:41 +0000 |
748 | @@ -67,6 +67,7 @@ |
749 | run_globals.update(init_globals) |
750 | run_globals.update(__name__ = mod_name, |
751 | __file__ = mod_fname, |
752 | + __cached__ = None, |
753 | __loader__ = mod_loader, |
754 | __package__ = pkg_name) |
755 | exec(code, run_globals) |
756 | @@ -130,6 +131,7 @@ |
757 | At the very least, these variables in __main__ will be overwritten: |
758 | __name__ |
759 | __file__ |
760 | + __cached__ |
761 | __loader__ |
762 | __package__ |
763 | """ |
764 | |
765 | === modified file 'Lib/site.py' |
766 | --- Lib/site.py 2010-04-12 22:33:42 +0000 |
767 | +++ Lib/site.py 2010-04-16 18:55:41 +0000 |
768 | @@ -74,15 +74,19 @@ |
769 | return dir, os.path.normcase(dir) |
770 | |
771 | |
772 | -def abs__file__(): |
773 | - """Set all module' __file__ attribute to an absolute path""" |
774 | +def abs_paths(): |
775 | + """Set all module __file__ and __cached__ attributes to an absolute path""" |
776 | for m in set(sys.modules.values()): |
777 | if hasattr(m, '__loader__'): |
778 | continue # don't mess with a PEP 302-supplied __file__ |
779 | try: |
780 | m.__file__ = os.path.abspath(m.__file__) |
781 | except AttributeError: |
782 | - continue |
783 | + pass |
784 | + try: |
785 | + m.__cached__ = os.path.abspath(m.__cached__) |
786 | + except AttributeError: |
787 | + pass |
788 | |
789 | |
790 | def removeduppaths(): |
791 | @@ -518,7 +522,7 @@ |
792 | def main(): |
793 | global ENABLE_USER_SITE |
794 | |
795 | - abs__file__() |
796 | + abs_paths() |
797 | known_paths = removeduppaths() |
798 | if (os.name == "posix" and sys.path and |
799 | os.path.basename(sys.path[-1]) == "Modules"): |
800 | |
801 | === modified file 'Lib/test/script_helper.py' |
802 | --- Lib/test/script_helper.py 2010-02-27 16:12:22 +0000 |
803 | +++ Lib/test/script_helper.py 2010-04-16 18:55:41 +0000 |
804 | @@ -11,6 +11,9 @@ |
805 | import shutil |
806 | import zipfile |
807 | |
808 | +from imp import source_from_cache |
809 | +from test.support import make_legacy_pyc |
810 | + |
811 | # Executing the interpreter in a subprocess |
812 | def python_exit_code(*args): |
813 | cmd_line = [sys.executable, '-E'] |
814 | @@ -62,20 +65,18 @@ |
815 | script_file.close() |
816 | return script_name |
817 | |
818 | -def compile_script(script_name): |
819 | - py_compile.compile(script_name, doraise=True) |
820 | - if __debug__: |
821 | - compiled_name = script_name + 'c' |
822 | - else: |
823 | - compiled_name = script_name + 'o' |
824 | - return compiled_name |
825 | - |
826 | def make_zip_script(zip_dir, zip_basename, script_name, name_in_zip=None): |
827 | zip_filename = zip_basename+os.extsep+'zip' |
828 | zip_name = os.path.join(zip_dir, zip_filename) |
829 | zip_file = zipfile.ZipFile(zip_name, 'w') |
830 | if name_in_zip is None: |
831 | - name_in_zip = os.path.basename(script_name) |
832 | + parts = script_name.split(os.sep) |
833 | + if len(parts) >= 2 and parts[-2] == '__pycache__': |
834 | + legacy_pyc = make_legacy_pyc(source_from_cache(script_name)) |
835 | + name_in_zip = os.path.basename(legacy_pyc) |
836 | + script_name = legacy_pyc |
837 | + else: |
838 | + name_in_zip = os.path.basename(script_name) |
839 | zip_file.write(script_name, name_in_zip) |
840 | zip_file.close() |
841 | #if test.test_support.verbose: |
842 | @@ -98,8 +99,8 @@ |
843 | script_name = make_script(zip_dir, script_basename, source) |
844 | unlink.append(script_name) |
845 | if compiled: |
846 | - init_name = compile_script(init_name) |
847 | - script_name = compile_script(script_name) |
848 | + init_name = py_compile(init_name, doraise=True) |
849 | + script_name = py_compile(script_name, doraise=True) |
850 | unlink.extend((init_name, script_name)) |
851 | pkg_names = [os.sep.join([pkg_name]*i) for i in range(1, depth+1)] |
852 | script_name_in_zip = os.path.join(pkg_names[-1], os.path.basename(script_name)) |
853 | |
854 | === modified file 'Lib/test/support.py' |
855 | --- Lib/test/support.py 2010-04-11 20:22:10 +0000 |
856 | +++ Lib/test/support.py 2010-04-16 18:55:41 +0000 |
857 | @@ -17,22 +17,25 @@ |
858 | import importlib |
859 | import collections |
860 | import re |
861 | +import imp |
862 | import time |
863 | |
864 | -__all__ = ["Error", "TestFailed", "ResourceDenied", "import_module", |
865 | - "verbose", "use_resources", "max_memuse", "record_original_stdout", |
866 | - "get_original_stdout", "unload", "unlink", "rmtree", "forget", |
867 | - "is_resource_enabled", "requires", "find_unused_port", "bind_port", |
868 | - "fcmp", "is_jython", "TESTFN", "HOST", "FUZZ", "SAVEDCWD", "temp_cwd", |
869 | - "findfile", "sortdict", "check_syntax_error", "open_urlresource", |
870 | - "check_warnings", "CleanImport", "EnvironmentVarGuard", |
871 | - "TransientResource", "captured_output", "captured_stdout", |
872 | - "time_out", "socket_peer_reset", "ioerror_peer_reset", |
873 | - "run_with_locale", |
874 | - "set_memlimit", "bigmemtest", "bigaddrspacetest", "BasicTestRunner", |
875 | - "run_unittest", "run_doctest", "threading_setup", "threading_cleanup", |
876 | - "reap_children", "cpython_only", "check_impl_detail", "get_attribute", |
877 | - "swap_item", "swap_attr"] |
878 | +__all__ = [ |
879 | + "Error", "TestFailed", "ResourceDenied", "import_module", |
880 | + "verbose", "use_resources", "max_memuse", "record_original_stdout", |
881 | + "get_original_stdout", "unload", "unlink", "rmtree", "forget", |
882 | + "is_resource_enabled", "requires", "find_unused_port", "bind_port", |
883 | + "fcmp", "is_jython", "TESTFN", "HOST", "FUZZ", "SAVEDCWD", "temp_cwd", |
884 | + "findfile", "sortdict", "check_syntax_error", "open_urlresource", |
885 | + "check_warnings", "CleanImport", "EnvironmentVarGuard", |
886 | + "TransientResource", "captured_output", "captured_stdout", |
887 | + "time_out", "socket_peer_reset", "ioerror_peer_reset", |
888 | + "run_with_locale", 'temp_umask', |
889 | + "set_memlimit", "bigmemtest", "bigaddrspacetest", "BasicTestRunner", |
890 | + "run_unittest", "run_doctest", "threading_setup", "threading_cleanup", |
891 | + "reap_children", "cpython_only", "check_impl_detail", "get_attribute", |
892 | + "swap_item", "swap_attr", |
893 | + ] |
894 | |
895 | |
896 | class Error(Exception): |
897 | @@ -177,27 +180,50 @@ |
898 | def unlink(filename): |
899 | try: |
900 | os.unlink(filename) |
901 | - except OSError: |
902 | - pass |
903 | + except OSError as error: |
904 | + # The filename need not exist. |
905 | + if error.errno != errno.ENOENT: |
906 | + raise |
907 | |
908 | def rmtree(path): |
909 | try: |
910 | shutil.rmtree(path) |
911 | - except OSError as e: |
912 | + except OSError as error: |
913 | # Unix returns ENOENT, Windows returns ESRCH. |
914 | - if e.errno not in (errno.ENOENT, errno.ESRCH): |
915 | + if error.errno not in (errno.ENOENT, errno.ESRCH): |
916 | raise |
917 | |
918 | +def make_legacy_pyc(source): |
919 | + """Move a PEP 3147 pyc/pyo file to its legacy pyc/pyo location. |
920 | + |
921 | + The choice of .pyc or .pyo extension is done based on the __debug__ flag |
922 | + value. |
923 | + |
924 | + :param source: The file system path to the source file. The source file |
925 | + does not need to exist, however the PEP 3147 pyc file must exist. |
926 | + :return: The file system path to the legacy pyc file. |
927 | + """ |
928 | + pyc_file = imp.cache_from_source(source) |
929 | + up_one = os.path.dirname(os.path.abspath(source)) |
930 | + legacy_pyc = os.path.join(up_one, source + ('c' if __debug__ else 'o')) |
931 | + os.rename(pyc_file, legacy_pyc) |
932 | + return legacy_pyc |
933 | + |
934 | def forget(modname): |
935 | - '''"Forget" a module was ever imported by removing it from sys.modules and |
936 | - deleting any .pyc and .pyo files.''' |
937 | + """'Forget' a module was ever imported. |
938 | + |
939 | + This removes the module from sys.modules and deletes any PEP 3147 or |
940 | + legacy .pyc and .pyo files. |
941 | + """ |
942 | unload(modname) |
943 | for dirname in sys.path: |
944 | - unlink(os.path.join(dirname, modname + '.pyc')) |
945 | - # Deleting the .pyo file cannot be within the 'try' for the .pyc since |
946 | - # the chance exists that there is no .pyc (and thus the 'try' statement |
947 | - # is exited) but there is a .pyo file. |
948 | - unlink(os.path.join(dirname, modname + '.pyo')) |
949 | + source = os.path.join(dirname, modname + '.py') |
950 | + # It doesn't matter if they exist or not, unlink all possible |
951 | + # combinations of PEP 3147 and legacy pyc and pyo files. |
952 | + unlink(source + 'c') |
953 | + unlink(source + 'o') |
954 | + unlink(imp.cache_from_source(source, debug_override=True)) |
955 | + unlink(imp.cache_from_source(source, debug_override=False)) |
956 | |
957 | def is_resource_enabled(resource): |
958 | """Test whether a resource is enabled. Known resources are set by |
959 | @@ -208,7 +234,9 @@ |
960 | """Raise ResourceDenied if the specified resource is not available. |
961 | |
962 | If the caller's module is __main__ then automatically return True. The |
963 | - possibility of False being returned occurs when regrtest.py is executing.""" |
964 | + possibility of False being returned occurs when regrtest.py is |
965 | + executing. |
966 | + """ |
967 | # see if the caller's module is __main__ - if so, treat as if |
968 | # the resource was set |
969 | if sys._getframe(1).f_globals.get("__name__") == "__main__": |
970 | @@ -405,6 +433,16 @@ |
971 | rmtree(name) |
972 | |
973 | |
974 | +@contextlib.contextmanager |
975 | +def temp_umask(umask): |
976 | + """Context manager that temporarily sets the process umask.""" |
977 | + oldmask = os.umask(umask) |
978 | + try: |
979 | + yield |
980 | + finally: |
981 | + os.umask(oldmask) |
982 | + |
983 | + |
984 | def findfile(file, here=__file__, subdir=None): |
985 | """Try to find a file on sys.path and the working directory. If it is not |
986 | found the argument passed to the function is returned (this does not |
987 | |
988 | === modified file 'Lib/test/test_cmd_line_script.py' |
989 | --- Lib/test/test_cmd_line_script.py 2010-03-14 10:45:50 +0000 |
990 | +++ Lib/test/test_cmd_line_script.py 2010-04-16 18:55:41 +0000 |
991 | @@ -1,12 +1,14 @@ |
992 | -# Tests command line execution of scripts |
993 | +# tests command line execution of scripts |
994 | |
995 | import unittest |
996 | import os |
997 | import os.path |
998 | +import py_compile |
999 | + |
1000 | import test.support |
1001 | -from test.script_helper import (run_python, |
1002 | - temp_dir, make_script, compile_script, |
1003 | - make_pkg, make_zip_script, make_zip_pkg) |
1004 | +from test.script_helper import ( |
1005 | + make_pkg, make_script, make_zip_pkg, make_zip_script, run_python, |
1006 | + temp_dir) |
1007 | |
1008 | verbose = test.support.verbose |
1009 | |
1010 | @@ -28,6 +30,7 @@ |
1011 | # Check population of magic variables |
1012 | assertEqual(__name__, '__main__') |
1013 | print('__file__==%r' % __file__) |
1014 | +assertEqual(__cached__, None) |
1015 | print('__package__==%r' % __package__) |
1016 | # Check the sys module |
1017 | import sys |
1018 | @@ -101,9 +104,10 @@ |
1019 | def test_script_compiled(self): |
1020 | with temp_dir() as script_dir: |
1021 | script_name = _make_test_script(script_dir, 'script') |
1022 | - compiled_name = compile_script(script_name) |
1023 | + compiled_name = py_compile.compile(script_name, doraise=True) |
1024 | os.remove(script_name) |
1025 | - self._check_script(compiled_name, compiled_name, compiled_name, None) |
1026 | + self._check_script(compiled_name, compiled_name, |
1027 | + compiled_name, None) |
1028 | |
1029 | def test_directory(self): |
1030 | with temp_dir() as script_dir: |
1031 | @@ -113,9 +117,10 @@ |
1032 | def test_directory_compiled(self): |
1033 | with temp_dir() as script_dir: |
1034 | script_name = _make_test_script(script_dir, '__main__') |
1035 | - compiled_name = compile_script(script_name) |
1036 | + compiled_name = py_compile.compile(script_name, doraise=True) |
1037 | os.remove(script_name) |
1038 | - self._check_script(script_dir, compiled_name, script_dir, '') |
1039 | + pyc_file = test.support.make_legacy_pyc(script_name) |
1040 | + self._check_script(script_dir, pyc_file, script_dir, '') |
1041 | |
1042 | def test_directory_error(self): |
1043 | with temp_dir() as script_dir: |
1044 | @@ -131,7 +136,7 @@ |
1045 | def test_zipfile_compiled(self): |
1046 | with temp_dir() as script_dir: |
1047 | script_name = _make_test_script(script_dir, '__main__') |
1048 | - compiled_name = compile_script(script_name) |
1049 | + compiled_name = py_compile.compile(script_name, doraise=True) |
1050 | zip_name, run_name = make_zip_script(script_dir, 'test_zip', compiled_name) |
1051 | self._check_script(zip_name, run_name, zip_name, '') |
1052 | |
1053 | @@ -176,11 +181,12 @@ |
1054 | pkg_dir = os.path.join(script_dir, 'test_pkg') |
1055 | make_pkg(pkg_dir) |
1056 | script_name = _make_test_script(pkg_dir, '__main__') |
1057 | - compiled_name = compile_script(script_name) |
1058 | + compiled_name = py_compile.compile(script_name, doraise=True) |
1059 | os.remove(script_name) |
1060 | + pyc_file = test.support.make_legacy_pyc(script_name) |
1061 | launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg') |
1062 | - self._check_script(launch_name, compiled_name, |
1063 | - compiled_name, 'test_pkg') |
1064 | + self._check_script(launch_name, pyc_file, |
1065 | + pyc_file, 'test_pkg') |
1066 | |
1067 | def test_package_error(self): |
1068 | with temp_dir() as script_dir: |
1069 | |
1070 | === modified file 'Lib/test/test_compileall.py' |
1071 | --- Lib/test/test_compileall.py 2010-03-16 13:19:21 +0000 |
1072 | +++ Lib/test/test_compileall.py 2010-04-16 18:55:41 +0000 |
1073 | @@ -5,22 +5,23 @@ |
1074 | import py_compile |
1075 | import shutil |
1076 | import struct |
1077 | +import subprocess |
1078 | import tempfile |
1079 | -from test import support |
1080 | import unittest |
1081 | import io |
1082 | |
1083 | +from test import support |
1084 | |
1085 | class CompileallTests(unittest.TestCase): |
1086 | |
1087 | def setUp(self): |
1088 | self.directory = tempfile.mkdtemp() |
1089 | self.source_path = os.path.join(self.directory, '_test.py') |
1090 | - self.bc_path = self.source_path + ('c' if __debug__ else 'o') |
1091 | + self.bc_path = imp.cache_from_source(self.source_path) |
1092 | with open(self.source_path, 'w') as file: |
1093 | file.write('x = 123\n') |
1094 | self.source_path2 = os.path.join(self.directory, '_test2.py') |
1095 | - self.bc_path2 = self.source_path2 + ('c' if __debug__ else 'o') |
1096 | + self.bc_path2 = imp.cache_from_source(self.source_path2) |
1097 | shutil.copyfile(self.source_path, self.source_path2) |
1098 | |
1099 | def tearDown(self): |
1100 | @@ -65,17 +66,19 @@ |
1101 | except: |
1102 | pass |
1103 | compileall.compile_file(self.source_path, force=False, quiet=True) |
1104 | - self.assertTrue(os.path.isfile(self.bc_path) \ |
1105 | - and not os.path.isfile(self.bc_path2)) |
1106 | + self.assertTrue(os.path.isfile(self.bc_path) and |
1107 | + not os.path.isfile(self.bc_path2)) |
1108 | os.unlink(self.bc_path) |
1109 | compileall.compile_dir(self.directory, force=False, quiet=True) |
1110 | - self.assertTrue(os.path.isfile(self.bc_path) \ |
1111 | - and os.path.isfile(self.bc_path2)) |
1112 | + self.assertTrue(os.path.isfile(self.bc_path) and |
1113 | + os.path.isfile(self.bc_path2)) |
1114 | os.unlink(self.bc_path) |
1115 | os.unlink(self.bc_path2) |
1116 | |
1117 | + |
1118 | class EncodingTest(unittest.TestCase): |
1119 | - 'Issue 6716: compileall should escape source code when printing errors to stdout.' |
1120 | + """Issue 6716: compileall should escape source code when printing errors |
1121 | + to stdout.""" |
1122 | |
1123 | def setUp(self): |
1124 | self.directory = tempfile.mkdtemp() |
1125 | @@ -95,9 +98,65 @@ |
1126 | finally: |
1127 | sys.stdout = orig_stdout |
1128 | |
1129 | +class CommandLineTests(unittest.TestCase): |
1130 | + """Test some aspects of compileall's CLI.""" |
1131 | + |
1132 | + def setUp(self): |
1133 | + self.addCleanup(self._cleanup) |
1134 | + self.directory = tempfile.mkdtemp() |
1135 | + self.pkgdir = os.path.join(self.directory, 'foo') |
1136 | + os.mkdir(self.pkgdir) |
1137 | + # Touch the __init__.py and a package module. |
1138 | + with open(os.path.join(self.pkgdir, '__init__.py'), 'w'): |
1139 | + pass |
1140 | + with open(os.path.join(self.pkgdir, 'bar.py'), 'w'): |
1141 | + pass |
1142 | + sys.path.insert(0, self.directory) |
1143 | + |
1144 | + def _cleanup(self): |
1145 | + support.rmtree(self.directory) |
1146 | + assert sys.path[0] == self.directory, 'Missing path' |
1147 | + del sys.path[0] |
1148 | + |
1149 | + def test_pep3147_paths(self): |
1150 | + # Ensure that the default behavior of compileall's CLI is to create |
1151 | + # PEP 3147 pyc/pyo files. |
1152 | + retcode = subprocess.call( |
1153 | + (sys.executable, '-m', 'compileall', '-q', self.pkgdir)) |
1154 | + self.assertEqual(retcode, 0) |
1155 | + # Verify the __pycache__ directory contents. |
1156 | + cachedir = os.path.join(self.pkgdir, '__pycache__') |
1157 | + self.assertTrue(os.path.exists(cachedir)) |
1158 | + ext = ('pyc' if __debug__ else 'pyo') |
1159 | + expected = sorted(base.format(imp.get_tag(), ext) for base in |
1160 | + ('__init__.{}.{}', 'bar.{}.{}')) |
1161 | + self.assertEqual(sorted(os.listdir(cachedir)), expected) |
1162 | + # Make sure there are no .pyc files in the source directory. |
1163 | + self.assertFalse([pyc_file for pyc_file in os.listdir(self.pkgdir) |
1164 | + if pyc_file.endswith(ext)]) |
1165 | + |
1166 | + def test_legacy_paths(self): |
1167 | + # Ensure that with the proper switch, compileall leaves legacy |
1168 | + # pyc/pyo files, and no __pycache__ directory. |
1169 | + retcode = subprocess.call( |
1170 | + (sys.executable, '-m', 'compileall', '-b', '-q', self.pkgdir)) |
1171 | + self.assertEqual(retcode, 0) |
1172 | + # Verify the __pycache__ directory contents. |
1173 | + cachedir = os.path.join(self.pkgdir, '__pycache__') |
1174 | + self.assertFalse(os.path.exists(cachedir)) |
1175 | + ext = ('pyc' if __debug__ else 'pyo') |
1176 | + expected = [base.format(ext) for base in ('__init__.{}', 'bar.{}')] |
1177 | + expected.extend(['__init__.py', 'bar.py']) |
1178 | + expected.sort() |
1179 | + self.assertEqual(sorted(os.listdir(self.pkgdir)), expected) |
1180 | + |
1181 | + |
1182 | def test_main(): |
1183 | - support.run_unittest(CompileallTests, |
1184 | - EncodingTest) |
1185 | + support.run_unittest( |
1186 | + CommandLineTests, |
1187 | + CompileallTests, |
1188 | + EncodingTest, |
1189 | + ) |
1190 | |
1191 | |
1192 | if __name__ == "__main__": |
1193 | |
1194 | === modified file 'Lib/test/test_frozen.py' |
1195 | --- Lib/test/test_frozen.py 2010-03-14 10:45:50 +0000 |
1196 | +++ Lib/test/test_frozen.py 2010-04-16 18:55:41 +0000 |
1197 | @@ -11,7 +11,7 @@ |
1198 | except ImportError as x: |
1199 | self.fail("import __hello__ failed:" + str(x)) |
1200 | self.assertEqual(__hello__.initialized, True) |
1201 | - self.assertEqual(len(dir(__hello__)), 6, dir(__hello__)) |
1202 | + self.assertEqual(len(dir(__hello__)), 7, dir(__hello__)) |
1203 | |
1204 | try: |
1205 | import __phello__ |
1206 | @@ -19,9 +19,9 @@ |
1207 | self.fail("import __phello__ failed:" + str(x)) |
1208 | self.assertEqual(__phello__.initialized, True) |
1209 | if not "__phello__.spam" in sys.modules: |
1210 | - self.assertEqual(len(dir(__phello__)), 7, dir(__phello__)) |
1211 | - else: |
1212 | self.assertEqual(len(dir(__phello__)), 8, dir(__phello__)) |
1213 | + else: |
1214 | + self.assertEqual(len(dir(__phello__)), 9, dir(__phello__)) |
1215 | self.assertEquals(__phello__.__path__, [__phello__.__name__]) |
1216 | |
1217 | try: |
1218 | @@ -29,8 +29,8 @@ |
1219 | except ImportError as x: |
1220 | self.fail("import __phello__.spam failed:" + str(x)) |
1221 | self.assertEqual(__phello__.spam.initialized, True) |
1222 | - self.assertEqual(len(dir(__phello__.spam)), 6) |
1223 | - self.assertEqual(len(dir(__phello__)), 8) |
1224 | + self.assertEqual(len(dir(__phello__.spam)), 7) |
1225 | + self.assertEqual(len(dir(__phello__)), 9) |
1226 | |
1227 | try: |
1228 | import __phello__.foo |
1229 | |
1230 | === modified file 'Lib/test/test_imp.py' |
1231 | --- Lib/test/test_imp.py 2010-03-20 20:31:34 +0000 |
1232 | +++ Lib/test/test_imp.py 2010-04-16 18:55:41 +0000 |
1233 | @@ -1,6 +1,7 @@ |
1234 | import imp |
1235 | import os |
1236 | import os.path |
1237 | +import shutil |
1238 | import sys |
1239 | import unittest |
1240 | from test import support |
1241 | @@ -139,7 +140,8 @@ |
1242 | mod = imp.load_source(temp_mod_name, temp_mod_name + '.py') |
1243 | self.assertEqual(mod.a, 1) |
1244 | |
1245 | - mod = imp.load_compiled(temp_mod_name, temp_mod_name + '.pyc') |
1246 | + mod = imp.load_compiled( |
1247 | + temp_mod_name, imp.cache_from_source(temp_mod_name + '.py')) |
1248 | self.assertEqual(mod.a, 1) |
1249 | |
1250 | if not os.path.exists(test_package_name): |
1251 | @@ -184,11 +186,132 @@ |
1252 | imp.reload(marshal) |
1253 | |
1254 | |
1255 | +class PEP3147Tests(unittest.TestCase): |
1256 | + """Tests of PEP 3147.""" |
1257 | + |
1258 | + tag = imp.get_tag() |
1259 | + |
1260 | + def test_cache_from_source(self): |
1261 | + # Given the path to a .py file, return the path to its PEP 3147 |
1262 | + # defined .pyc file (i.e. under __pycache__). |
1263 | + self.assertEqual( |
1264 | + imp.cache_from_source('/foo/bar/baz/qux.py', True), |
1265 | + '/foo/bar/baz/__pycache__/qux.{}.pyc'.format(self.tag)) |
1266 | + |
1267 | + def test_cache_from_source_optimized(self): |
1268 | + # Given the path to a .py file, return the path to its PEP 3147 |
1269 | + # defined .pyo file (i.e. under __pycache__). |
1270 | + self.assertEqual( |
1271 | + imp.cache_from_source('/foo/bar/baz/qux.py', False), |
1272 | + '/foo/bar/baz/__pycache__/qux.{}.pyo'.format(self.tag)) |
1273 | + |
1274 | + def test_cache_from_source_cwd(self): |
1275 | + self.assertEqual(imp.cache_from_source('foo.py', True), |
1276 | + os.sep.join(('__pycache__', |
1277 | + 'foo.{}.pyc'.format(self.tag)))) |
1278 | + |
1279 | + def test_cache_from_source_override(self): |
1280 | + # When debug_override is not None, it can be any true-ish or false-ish |
1281 | + # value. |
1282 | + self.assertEqual( |
1283 | + imp.cache_from_source('/foo/bar/baz.py', []), |
1284 | + '/foo/bar/__pycache__/baz.{}.pyo'.format(self.tag)) |
1285 | + self.assertEqual( |
1286 | + imp.cache_from_source('/foo/bar/baz.py', [17]), |
1287 | + '/foo/bar/__pycache__/baz.{}.pyc'.format(self.tag)) |
1288 | + # However if the bool-ishness can't be determined, the exception |
1289 | + # propagates. |
1290 | + class Bearish: |
1291 | + def __bool__(self): raise RuntimeError |
1292 | + self.assertRaises( |
1293 | + RuntimeError, |
1294 | + imp.cache_from_source, '/foo/bar/baz.py', Bearish()) |
1295 | + |
1296 | + @unittest.skipIf(os.altsep is None, |
1297 | + 'test meaningful only where os.altsep is defined') |
1298 | + def test_altsep_cache_from_source(self): |
1299 | + # Windows path and PEP 3147. |
1300 | + self.assertEqual( |
1301 | + imp.cache_from_source('\\foo\\bar\\baz\\qux.py', True), |
1302 | + '\\foo\\bar\\baz\\__pycache__\\qux.{}.pyc'.format(self.tag)) |
1303 | + |
1304 | + @unittest.skipIf(os.altsep is None, |
1305 | + 'test meaningful only where os.altsep is defined') |
1306 | + def test_altsep_and_sep_cache_from_source(self): |
1307 | + # Windows path and PEP 3147 where altsep is right of sep. |
1308 | + self.assertEqual( |
1309 | + imp.cache_from_source('\\foo\\bar/baz\\qux.py', True), |
1310 | + '\\foo\\bar/baz\\__pycache__\\qux.{}.pyc'.format(self.tag)) |
1311 | + |
1312 | + @unittest.skipIf(os.altsep is None, |
1313 | + 'test meaningful only where os.altsep is defined') |
1314 | + def test_sep_altsep_and_sep_cache_from_source(self): |
1315 | + # Windows path and PEP 3147 where sep is right of altsep. |
1316 | + self.assertEqual( |
1317 | + imp.cache_from_source('\\foo\\bar\\baz/qux.py', True), |
1318 | + '\\foo\\bar\\baz/__pycache__/qux.{}.pyc'.format(self.tag)) |
1319 | + |
1320 | + def test_source_from_cache(self): |
1321 | + # Given the path to a PEP 3147 defined .pyc file, return the path to |
1322 | + # its source. This tests the good path. |
1323 | + self.assertEqual(imp.source_from_cache( |
1324 | + '/foo/bar/baz/__pycache__/qux.{}.pyc'.format(self.tag)), |
1325 | + '/foo/bar/baz/qux.py') |
1326 | + |
1327 | + def test_source_from_cache_bad_path(self): |
1328 | + # When the path to a pyc file is not in PEP 3147 format, a ValueError |
1329 | + # is raised. |
1330 | + self.assertRaises( |
1331 | + ValueError, imp.source_from_cache, '/foo/bar/bazqux.pyc') |
1332 | + |
1333 | + def test_source_from_cache_no_slash(self): |
1334 | + # No slashes at all in path -> ValueError |
1335 | + self.assertRaises( |
1336 | + ValueError, imp.source_from_cache, 'foo.cpython-32.pyc') |
1337 | + |
1338 | + def test_source_from_cache_too_few_dots(self): |
1339 | + # Too few dots in final path component -> ValueError |
1340 | + self.assertRaises( |
1341 | + ValueError, imp.source_from_cache, '__pycache__/foo.pyc') |
1342 | + |
1343 | + def test_source_from_cache_too_many_dots(self): |
1344 | + # Too many dots in final path component -> ValueError |
1345 | + self.assertRaises( |
1346 | + ValueError, imp.source_from_cache, |
1347 | + '__pycache__/foo.cpython-32.foo.pyc') |
1348 | + |
1349 | + def test_source_from_cache_no__pycache__(self): |
1350 | + # Another problem with the path -> ValueError |
1351 | + self.assertRaises( |
1352 | + ValueError, imp.source_from_cache, |
1353 | + '/foo/bar/foo.cpython-32.foo.pyc') |
1354 | + |
1355 | + def test_package___file__(self): |
1356 | + # Test that a package's __file__ points to the right source directory. |
1357 | + os.mkdir('pep3147') |
1358 | + sys.path.insert(0, os.curdir) |
1359 | + def cleanup(): |
1360 | + if sys.path[0] == os.curdir: |
1361 | + del sys.path[0] |
1362 | + shutil.rmtree('pep3147') |
1363 | + self.addCleanup(cleanup) |
1364 | + # Touch the __init__.py file. |
1365 | + with open('pep3147/__init__.py', 'w'): |
1366 | + pass |
1367 | + m = __import__('pep3147') |
1368 | + # Ensure we load the pyc file. |
1369 | + support.forget('pep3147') |
1370 | + m = __import__('pep3147') |
1371 | + self.assertEqual(m.__file__, |
1372 | + os.sep.join(('.', 'pep3147', '__init__.py'))) |
1373 | + |
1374 | + |
1375 | def test_main(): |
1376 | tests = [ |
1377 | ImportTests, |
1378 | + PEP3147Tests, |
1379 | ReloadTests, |
1380 | - ] |
1381 | + ] |
1382 | try: |
1383 | import _thread |
1384 | except ImportError: |
1385 | |
1386 | === modified file 'Lib/test/test_import.py' |
1387 | --- Lib/test/test_import.py 2010-03-17 20:29:51 +0000 |
1388 | +++ Lib/test/test_import.py 2010-04-16 18:55:41 +0000 |
1389 | @@ -1,4 +1,5 @@ |
1390 | import builtins |
1391 | +import errno |
1392 | import imp |
1393 | import marshal |
1394 | import os |
1395 | @@ -8,8 +9,11 @@ |
1396 | import stat |
1397 | import sys |
1398 | import unittest |
1399 | -from test.support import (unlink, TESTFN, unload, run_unittest, is_jython, |
1400 | - check_warnings, EnvironmentVarGuard, swap_attr, swap_item) |
1401 | + |
1402 | +from test.support import ( |
1403 | + EnvironmentVarGuard, TESTFN, check_warnings, forget, is_jython, |
1404 | + make_legacy_pyc, rmtree, run_unittest, swap_attr, swap_item, temp_umask, |
1405 | + unlink, unload) |
1406 | |
1407 | |
1408 | def remove_files(name): |
1409 | @@ -19,12 +23,18 @@ |
1410 | name + ".pyw", |
1411 | name + "$py.class"): |
1412 | unlink(f) |
1413 | + try: |
1414 | + shutil.rmtree('__pycache__') |
1415 | + except OSError as error: |
1416 | + if error.errno != errno.ENOENT: |
1417 | + raise |
1418 | |
1419 | |
1420 | class ImportTests(unittest.TestCase): |
1421 | |
1422 | def tearDown(self): |
1423 | unload(TESTFN) |
1424 | + |
1425 | setUp = tearDown |
1426 | |
1427 | def test_case_sensitivity(self): |
1428 | @@ -53,8 +63,8 @@ |
1429 | pyc = TESTFN + ".pyc" |
1430 | |
1431 | with open(source, "w") as f: |
1432 | - print("# This tests Python's ability to import a", ext, "file.", |
1433 | - file=f) |
1434 | + print("# This tests Python's ability to import a", |
1435 | + ext, "file.", file=f) |
1436 | a = random.randrange(1000) |
1437 | b = random.randrange(1000) |
1438 | print("a =", a, file=f) |
1439 | @@ -73,10 +83,10 @@ |
1440 | self.assertEqual(mod.b, b, |
1441 | "module loaded (%s) but contents invalid" % mod) |
1442 | finally: |
1443 | + forget(TESTFN) |
1444 | unlink(source) |
1445 | unlink(pyc) |
1446 | unlink(pyo) |
1447 | - unload(TESTFN) |
1448 | |
1449 | sys.path.insert(0, os.curdir) |
1450 | try: |
1451 | @@ -87,32 +97,31 @@ |
1452 | finally: |
1453 | del sys.path[0] |
1454 | |
1455 | - @unittest.skipUnless(os.name == 'posix', "test meaningful only on posix systems") |
1456 | + @unittest.skipUnless(os.name == 'posix', |
1457 | + "test meaningful only on posix systems") |
1458 | def test_execute_bit_not_copied(self): |
1459 | # Issue 6070: under posix .pyc files got their execute bit set if |
1460 | # the .py file had the execute bit set, but they aren't executable. |
1461 | - oldmask = os.umask(0o022) |
1462 | - sys.path.insert(0, os.curdir) |
1463 | - try: |
1464 | - fname = TESTFN + os.extsep + "py" |
1465 | - f = open(fname, 'w').close() |
1466 | - os.chmod(fname, (stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | |
1467 | - stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)) |
1468 | - __import__(TESTFN) |
1469 | - fn = fname + 'c' |
1470 | - if not os.path.exists(fn): |
1471 | - fn = fname + 'o' |
1472 | + with temp_umask(0o022): |
1473 | + sys.path.insert(0, os.curdir) |
1474 | + try: |
1475 | + fname = TESTFN + os.extsep + "py" |
1476 | + f = open(fname, 'w').close() |
1477 | + os.chmod(fname, (stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | |
1478 | + stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)) |
1479 | + __import__(TESTFN) |
1480 | + fn = imp.cache_from_source(fname) |
1481 | if not os.path.exists(fn): |
1482 | self.fail("__import__ did not result in creation of " |
1483 | "either a .pyc or .pyo file") |
1484 | - s = os.stat(fn) |
1485 | - self.assertEqual(stat.S_IMODE(s.st_mode), |
1486 | - stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH) |
1487 | - finally: |
1488 | - os.umask(oldmask) |
1489 | - remove_files(TESTFN) |
1490 | - unload(TESTFN) |
1491 | - del sys.path[0] |
1492 | + s = os.stat(fn) |
1493 | + self.assertEqual( |
1494 | + stat.S_IMODE(s.st_mode), |
1495 | + stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH) |
1496 | + finally: |
1497 | + del sys.path[0] |
1498 | + remove_files(TESTFN) |
1499 | + unload(TESTFN) |
1500 | |
1501 | def test_imp_module(self): |
1502 | # Verify that the imp module can correctly load and find .py files |
1503 | @@ -144,10 +153,12 @@ |
1504 | f.write('"",\n') |
1505 | f.write(']') |
1506 | |
1507 | - # Compile & remove .py file, we only need .pyc (or .pyo). |
1508 | + # Compile & remove .py file, we only need .pyc (or .pyo), but that |
1509 | + # must be relocated to the PEP 3147 bytecode-only location. |
1510 | with open(filename, 'r') as f: |
1511 | py_compile.compile(filename) |
1512 | unlink(filename) |
1513 | + make_legacy_pyc(filename) |
1514 | |
1515 | # Need to be able to load from current dir. |
1516 | sys.path.append('') |
1517 | @@ -247,8 +258,9 @@ |
1518 | self.assertTrue(mod.__file__.endswith('.py')) |
1519 | os.remove(source) |
1520 | del sys.modules[TESTFN] |
1521 | + make_legacy_pyc(source) |
1522 | mod = __import__(TESTFN) |
1523 | - ext = mod.__file__[-4:] |
1524 | + base, ext = os.path.splitext(mod.__file__) |
1525 | self.assertIn(ext, ('.pyc', '.pyo')) |
1526 | finally: |
1527 | del sys.path[0] |
1528 | @@ -298,7 +310,7 @@ |
1529 | """ |
1530 | dir_name = os.path.abspath(TESTFN) |
1531 | file_name = os.path.join(dir_name, module_name) + os.extsep + "py" |
1532 | - compiled_name = file_name + ("c" if __debug__ else "o") |
1533 | + compiled_name = imp.cache_from_source(file_name) |
1534 | |
1535 | def setUp(self): |
1536 | self.sys_path = sys.path[:] |
1537 | @@ -346,8 +358,9 @@ |
1538 | target = "another_module.py" |
1539 | py_compile.compile(self.file_name, dfile=target) |
1540 | os.remove(self.file_name) |
1541 | + pyc_file = make_legacy_pyc(self.file_name) |
1542 | mod = self.import_module() |
1543 | - self.assertEqual(mod.module_filename, self.compiled_name) |
1544 | + self.assertEqual(mod.module_filename, pyc_file) |
1545 | self.assertEqual(mod.code_filename, target) |
1546 | self.assertEqual(mod.func_filename, target) |
1547 | |
1548 | @@ -476,10 +489,143 @@ |
1549 | self.assertEqual(foo(), os) |
1550 | |
1551 | |
1552 | +class PycacheTests(unittest.TestCase): |
1553 | + # Test the various PEP 3147 related behaviors. |
1554 | + |
1555 | + tag = imp.get_tag() |
1556 | + |
1557 | + def _clean(self): |
1558 | + forget(TESTFN) |
1559 | + rmtree('__pycache__') |
1560 | + unlink(self.source) |
1561 | + |
1562 | + def setUp(self): |
1563 | + self.source = TESTFN + '.py' |
1564 | + self._clean() |
1565 | + with open(self.source, 'w') as fp: |
1566 | + print('# This is a test file written by test_import.py', file=fp) |
1567 | + sys.path.insert(0, os.curdir) |
1568 | + |
1569 | + def tearDown(self): |
1570 | + assert sys.path[0] == os.curdir, 'Unexpected sys.path[0]' |
1571 | + del sys.path[0] |
1572 | + self._clean() |
1573 | + |
1574 | + def test_import_pyc_path(self): |
1575 | + self.assertFalse(os.path.exists('__pycache__')) |
1576 | + __import__(TESTFN) |
1577 | + self.assertTrue(os.path.exists('__pycache__')) |
1578 | + self.assertTrue(os.path.exists(os.path.join( |
1579 | + '__pycache__', '{}.{}.pyc'.format(TESTFN, self.tag)))) |
1580 | + |
1581 | + @unittest.skipUnless(os.name == 'posix', |
1582 | + "test meaningful only on posix systems") |
1583 | + def test_unwritable_directory(self): |
1584 | + # When the umask causes the new __pycache__ directory to be |
1585 | + # unwritable, the import still succeeds but no .pyc file is written. |
1586 | + with temp_umask(0o222): |
1587 | + __import__(TESTFN) |
1588 | + self.assertTrue(os.path.exists('__pycache__')) |
1589 | + self.assertFalse(os.path.exists(os.path.join( |
1590 | + '__pycache__', '{}.{}.pyc'.format(TESTFN, self.tag)))) |
1591 | + |
1592 | + def test_missing_source(self): |
1593 | + # With PEP 3147 cache layout, removing the source but leaving the pyc |
1594 | + # file does not satisfy the import. |
1595 | + __import__(TESTFN) |
1596 | + pyc_file = imp.cache_from_source(self.source) |
1597 | + self.assertTrue(os.path.exists(pyc_file)) |
1598 | + os.remove(self.source) |
1599 | + forget(TESTFN) |
1600 | + self.assertRaises(ImportError, __import__, TESTFN) |
1601 | + |
1602 | + def test_missing_source_legacy(self): |
1603 | + # Like test_missing_source() except that for backward compatibility, |
1604 | + # when the pyc file lives where the py file would have been (and named |
1605 | + # without the tag), it is importable. The __file__ of the imported |
1606 | + # module is the pyc location. |
1607 | + __import__(TESTFN) |
1608 | + # pyc_file gets removed in _clean() via tearDown(). |
1609 | + pyc_file = make_legacy_pyc(self.source) |
1610 | + os.remove(self.source) |
1611 | + unload(TESTFN) |
1612 | + m = __import__(TESTFN) |
1613 | + self.assertEqual(m.__file__, |
1614 | + os.path.join(os.curdir, os.path.relpath(pyc_file))) |
1615 | + |
1616 | + def test___cached__(self): |
1617 | + # Modules now also have an __cached__ that points to the pyc file. |
1618 | + m = __import__(TESTFN) |
1619 | + pyc_file = imp.cache_from_source(TESTFN + '.py') |
1620 | + self.assertEqual(m.__cached__, os.path.join(os.curdir, pyc_file)) |
1621 | + |
1622 | + def test___cached___legacy_pyc(self): |
1623 | + # Like test___cached__() except that for backward compatibility, |
1624 | + # when the pyc file lives where the py file would have been (and named |
1625 | + # without the tag), it is importable. The __cached__ of the imported |
1626 | + # module is the pyc location. |
1627 | + __import__(TESTFN) |
1628 | + # pyc_file gets removed in _clean() via tearDown(). |
1629 | + pyc_file = make_legacy_pyc(self.source) |
1630 | + os.remove(self.source) |
1631 | + unload(TESTFN) |
1632 | + m = __import__(TESTFN) |
1633 | + self.assertEqual(m.__cached__, |
1634 | + os.path.join(os.curdir, os.path.relpath(pyc_file))) |
1635 | + |
1636 | + def test_package___cached__(self): |
1637 | + # Like test___cached__ but for packages. |
1638 | + def cleanup(): |
1639 | + shutil.rmtree('pep3147') |
1640 | + os.mkdir('pep3147') |
1641 | + self.addCleanup(cleanup) |
1642 | + # Touch the __init__.py |
1643 | + with open(os.path.join('pep3147', '__init__.py'), 'w'): |
1644 | + pass |
1645 | + with open(os.path.join('pep3147', 'foo.py'), 'w'): |
1646 | + pass |
1647 | + unload('pep3147.foo') |
1648 | + unload('pep3147') |
1649 | + m = __import__('pep3147.foo') |
1650 | + init_pyc = imp.cache_from_source( |
1651 | + os.path.join('pep3147', '__init__.py')) |
1652 | + self.assertEqual(m.__cached__, os.path.join(os.curdir, init_pyc)) |
1653 | + foo_pyc = imp.cache_from_source(os.path.join('pep3147', 'foo.py')) |
1654 | + self.assertEqual(sys.modules['pep3147.foo'].__cached__, |
1655 | + os.path.join(os.curdir, foo_pyc)) |
1656 | + |
1657 | + def test_package___cached___from_pyc(self): |
1658 | + # Like test___cached__ but ensuring __cached__ when imported from a |
1659 | + # PEP 3147 pyc file. |
1660 | + def cleanup(): |
1661 | + shutil.rmtree('pep3147') |
1662 | + os.mkdir('pep3147') |
1663 | + self.addCleanup(cleanup) |
1664 | + unload('pep3147.foo') |
1665 | + unload('pep3147') |
1666 | + # Touch the __init__.py |
1667 | + with open(os.path.join('pep3147', '__init__.py'), 'w'): |
1668 | + pass |
1669 | + with open(os.path.join('pep3147', 'foo.py'), 'w'): |
1670 | + pass |
1671 | + m = __import__('pep3147.foo') |
1672 | + unload('pep3147.foo') |
1673 | + unload('pep3147') |
1674 | + m = __import__('pep3147.foo') |
1675 | + init_pyc = imp.cache_from_source( |
1676 | + os.path.join('pep3147', '__init__.py')) |
1677 | + self.assertEqual(m.__cached__, os.path.join(os.curdir, init_pyc)) |
1678 | + foo_pyc = imp.cache_from_source(os.path.join('pep3147', 'foo.py')) |
1679 | + self.assertEqual(sys.modules['pep3147.foo'].__cached__, |
1680 | + os.path.join(os.curdir, foo_pyc)) |
1681 | + |
1682 | + |
1683 | def test_main(verbose=None): |
1684 | - run_unittest(ImportTests, PycRewritingTests, PathsTests, RelativeImportTests, |
1685 | + run_unittest(ImportTests, PycacheTests, |
1686 | + PycRewritingTests, PathsTests, RelativeImportTests, |
1687 | OverridingImportBuiltinTests) |
1688 | |
1689 | + |
1690 | if __name__ == '__main__': |
1691 | # Test needs to be a package, so we can do relative imports. |
1692 | from test.test_import import test_main |
1693 | |
1694 | === modified file 'Lib/test/test_pkg.py' |
1695 | --- Lib/test/test_pkg.py 2010-02-24 01:46:21 +0000 |
1696 | +++ Lib/test/test_pkg.py 2010-04-16 18:55:41 +0000 |
1697 | @@ -196,14 +196,14 @@ |
1698 | |
1699 | import t5 |
1700 | self.assertEqual(fixdir(dir(t5)), |
1701 | - ['__doc__', '__file__', '__name__', |
1702 | + ['__cached__', '__doc__', '__file__', '__name__', |
1703 | '__package__', '__path__', 'foo', 'string', 't5']) |
1704 | self.assertEqual(fixdir(dir(t5.foo)), |
1705 | - ['__doc__', '__file__', '__name__', '__package__', |
1706 | - 'string']) |
1707 | + ['__cached__', '__doc__', '__file__', '__name__', |
1708 | + '__package__', 'string']) |
1709 | self.assertEqual(fixdir(dir(t5.string)), |
1710 | - ['__doc__', '__file__', '__name__','__package__', |
1711 | - 'spam']) |
1712 | + ['__cached__', '__doc__', '__file__', '__name__', |
1713 | + '__package__', 'spam']) |
1714 | |
1715 | def test_6(self): |
1716 | hier = [ |
1717 | @@ -218,13 +218,13 @@ |
1718 | |
1719 | import t6 |
1720 | self.assertEqual(fixdir(dir(t6)), |
1721 | - ['__all__', '__doc__', '__file__', |
1722 | + ['__all__', '__cached__', '__doc__', '__file__', |
1723 | '__name__', '__package__', '__path__']) |
1724 | s = """ |
1725 | import t6 |
1726 | from t6 import * |
1727 | self.assertEqual(fixdir(dir(t6)), |
1728 | - ['__all__', '__doc__', '__file__', |
1729 | + ['__all__', '__cached__', '__doc__', '__file__', |
1730 | '__name__', '__package__', '__path__', |
1731 | 'eggs', 'ham', 'spam']) |
1732 | self.assertEqual(dir(), ['eggs', 'ham', 'self', 'spam', 't6']) |
1733 | @@ -252,18 +252,18 @@ |
1734 | t7, sub, subsub = None, None, None |
1735 | import t7 as tas |
1736 | self.assertEqual(fixdir(dir(tas)), |
1737 | - ['__doc__', '__file__', '__name__', |
1738 | + ['__cached__', '__doc__', '__file__', '__name__', |
1739 | '__package__', '__path__']) |
1740 | self.assertFalse(t7) |
1741 | from t7 import sub as subpar |
1742 | self.assertEqual(fixdir(dir(subpar)), |
1743 | - ['__doc__', '__file__', '__name__', |
1744 | + ['__cached__', '__doc__', '__file__', '__name__', |
1745 | '__package__', '__path__']) |
1746 | self.assertFalse(t7) |
1747 | self.assertFalse(sub) |
1748 | from t7.sub import subsub as subsubsub |
1749 | self.assertEqual(fixdir(dir(subsubsub)), |
1750 | - ['__doc__', '__file__', '__name__', |
1751 | + ['__cached__', '__doc__', '__file__', '__name__', |
1752 | '__package__', '__path__', 'spam']) |
1753 | self.assertFalse(t7) |
1754 | self.assertFalse(sub) |
1755 | |
1756 | === modified file 'Lib/test/test_pkgimport.py' |
1757 | --- Lib/test/test_pkgimport.py 2010-01-23 15:40:09 +0000 |
1758 | +++ Lib/test/test_pkgimport.py 2010-04-16 18:55:41 +0000 |
1759 | @@ -1,5 +1,12 @@ |
1760 | -import os, sys, string, random, tempfile, unittest |
1761 | +import os |
1762 | +import sys |
1763 | +import shutil |
1764 | +import string |
1765 | +import random |
1766 | +import tempfile |
1767 | +import unittest |
1768 | |
1769 | +from imp import cache_from_source |
1770 | from test.support import run_unittest |
1771 | |
1772 | class TestImport(unittest.TestCase): |
1773 | @@ -26,22 +33,17 @@ |
1774 | self.module_path = os.path.join(self.package_dir, 'foo.py') |
1775 | |
1776 | def tearDown(self): |
1777 | - for file in os.listdir(self.package_dir): |
1778 | - os.remove(os.path.join(self.package_dir, file)) |
1779 | - os.rmdir(self.package_dir) |
1780 | - os.rmdir(self.test_dir) |
1781 | + shutil.rmtree(self.test_dir) |
1782 | self.assertNotEqual(sys.path.count(self.test_dir), 0) |
1783 | sys.path.remove(self.test_dir) |
1784 | self.remove_modules() |
1785 | |
1786 | def rewrite_file(self, contents): |
1787 | - for extension in "co": |
1788 | - compiled_path = self.module_path + extension |
1789 | - if os.path.exists(compiled_path): |
1790 | - os.remove(compiled_path) |
1791 | - f = open(self.module_path, 'w') |
1792 | - f.write(contents) |
1793 | - f.close() |
1794 | + compiled_path = cache_from_source(self.module_path) |
1795 | + if os.path.exists(compiled_path): |
1796 | + os.remove(compiled_path) |
1797 | + with open(self.module_path, 'w') as f: |
1798 | + f.write(contents) |
1799 | |
1800 | def test_package_import__semantics(self): |
1801 | |
1802 | |
1803 | === modified file 'Lib/test/test_pydoc.py' |
1804 | --- Lib/test/test_pydoc.py 2010-03-31 02:19:28 +0000 |
1805 | +++ Lib/test/test_pydoc.py 2010-04-16 18:55:41 +0000 |
1806 | @@ -19,8 +19,7 @@ |
1807 | if hasattr(pydoc_mod, "__loader__"): |
1808 | del pydoc_mod.__loader__ |
1809 | |
1810 | -expected_text_pattern = \ |
1811 | -""" |
1812 | +expected_text_pattern = """ |
1813 | NAME |
1814 | test.pydoc_mod - This is a test module for test_pydoc |
1815 | |
1816 | @@ -87,8 +86,7 @@ |
1817 | Nobody |
1818 | """.strip() |
1819 | |
1820 | -expected_html_pattern = \ |
1821 | -""" |
1822 | +expected_html_pattern = """ |
1823 | <table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading"> |
1824 | <tr bgcolor="#7799ee"> |
1825 | <td valign=bottom> <br> |
1826 | @@ -186,7 +184,7 @@ |
1827 | \x20\x20\x20\x20 |
1828 | <tr><td bgcolor="#7799ee"><tt> </tt></td><td> </td> |
1829 | <td width="100%%">Nobody</td></tr></table> |
1830 | -""".strip() |
1831 | +""".strip() # ' <- emacs turd |
1832 | |
1833 | |
1834 | # output pattern for missing module |
1835 | @@ -287,7 +285,8 @@ |
1836 | ('i_am_not_here', 'i_am_not_here'), |
1837 | ('test.i_am_not_here_either', 'i_am_not_here_either'), |
1838 | ('test.i_am_not_here.neither_am_i', 'i_am_not_here.neither_am_i'), |
1839 | - ('i_am_not_here.{}'.format(modname), 'i_am_not_here.{}'.format(modname)), |
1840 | + ('i_am_not_here.{}'.format(modname), |
1841 | + 'i_am_not_here.{}'.format(modname)), |
1842 | ('test.{}'.format(modname), modname), |
1843 | ) |
1844 | |
1845 | @@ -304,9 +303,8 @@ |
1846 | fullmodname = os.path.join(TESTFN, modname) |
1847 | sourcefn = fullmodname + os.extsep + "py" |
1848 | for importstring, expectedinmsg in testpairs: |
1849 | - f = open(sourcefn, 'w') |
1850 | - f.write("import {}\n".format(importstring)) |
1851 | - f.close() |
1852 | + with open(sourcefn, 'w') as f: |
1853 | + f.write("import {}\n".format(importstring)) |
1854 | try: |
1855 | result = run_pydoc(modname).decode("ascii") |
1856 | finally: |
1857 | |
1858 | === modified file 'Lib/test/test_runpy.py' |
1859 | --- Lib/test/test_runpy.py 2010-01-19 00:09:57 +0000 |
1860 | +++ Lib/test/test_runpy.py 2010-04-16 18:55:41 +0000 |
1861 | @@ -5,9 +5,10 @@ |
1862 | import sys |
1863 | import re |
1864 | import tempfile |
1865 | -from test.support import verbose, run_unittest, forget |
1866 | -from test.script_helper import (temp_dir, make_script, compile_script, |
1867 | - make_pkg, make_zip_script, make_zip_pkg) |
1868 | +import py_compile |
1869 | +from test.support import forget, make_legacy_pyc, run_unittest, verbose |
1870 | +from test.script_helper import ( |
1871 | + make_pkg, make_script, make_zip_pkg, make_zip_script, temp_dir) |
1872 | |
1873 | |
1874 | from runpy import _run_code, _run_module_code, run_module, run_path |
1875 | @@ -45,6 +46,7 @@ |
1876 | self.assertEqual(d["result"], self.expected_result) |
1877 | self.assertIs(d["__name__"], None) |
1878 | self.assertIs(d["__file__"], None) |
1879 | + self.assertIs(d["__cached__"], None) |
1880 | self.assertIs(d["__loader__"], None) |
1881 | self.assertIs(d["__package__"], None) |
1882 | self.assertIs(d["run_argv0"], saved_argv0) |
1883 | @@ -73,6 +75,7 @@ |
1884 | self.assertTrue(d2["run_name_in_sys_modules"]) |
1885 | self.assertTrue(d2["module_in_sys_modules"]) |
1886 | self.assertIs(d2["__file__"], file) |
1887 | + self.assertIs(d2["__cached__"], None) |
1888 | self.assertIs(d2["run_argv0"], file) |
1889 | self.assertIs(d2["__loader__"], loader) |
1890 | self.assertIs(d2["__package__"], package) |
1891 | @@ -170,6 +173,7 @@ |
1892 | del d1 # Ensure __loader__ entry doesn't keep file open |
1893 | __import__(mod_name) |
1894 | os.remove(mod_fname) |
1895 | + make_legacy_pyc(mod_fname) |
1896 | if verbose: print("Running from compiled:", mod_name) |
1897 | d2 = run_module(mod_name) # Read from bytecode |
1898 | self.assertIn("x", d2) |
1899 | @@ -192,6 +196,7 @@ |
1900 | del d1 # Ensure __loader__ entry doesn't keep file open |
1901 | __import__(mod_name) |
1902 | os.remove(mod_fname) |
1903 | + make_legacy_pyc(mod_fname) |
1904 | if verbose: print("Running from compiled:", pkg_name) |
1905 | d2 = run_module(pkg_name) # Read from bytecode |
1906 | self.assertIn("x", d2) |
1907 | @@ -246,6 +251,7 @@ |
1908 | del d1 # Ensure __loader__ entry doesn't keep file open |
1909 | __import__(mod_name) |
1910 | os.remove(mod_fname) |
1911 | + make_legacy_pyc(mod_fname) |
1912 | if verbose: print("Running from compiled:", mod_name) |
1913 | d2 = run_module(mod_name, run_name=run_name) # Read from bytecode |
1914 | self.assertIn("__package__", d2) |
1915 | @@ -313,6 +319,7 @@ |
1916 | result = run_path(script_name) |
1917 | self.assertEqual(result["__name__"], expected_name) |
1918 | self.assertEqual(result["__file__"], expected_file) |
1919 | + self.assertEqual(result["__cached__"], None) |
1920 | self.assertIn("argv0", result) |
1921 | self.assertEqual(result["argv0"], expected_argv0) |
1922 | self.assertEqual(result["__package__"], expected_package) |
1923 | @@ -332,7 +339,7 @@ |
1924 | with temp_dir() as script_dir: |
1925 | mod_name = 'script' |
1926 | script_name = self._make_test_script(script_dir, mod_name) |
1927 | - compiled_name = compile_script(script_name) |
1928 | + compiled_name = py_compile.compile(script_name, doraise=True) |
1929 | os.remove(script_name) |
1930 | self._check_script(compiled_name, "<run_path>", compiled_name, |
1931 | compiled_name, None) |
1932 | @@ -348,9 +355,10 @@ |
1933 | with temp_dir() as script_dir: |
1934 | mod_name = '__main__' |
1935 | script_name = self._make_test_script(script_dir, mod_name) |
1936 | - compiled_name = compile_script(script_name) |
1937 | + compiled_name = py_compile.compile(script_name, doraise=True) |
1938 | os.remove(script_name) |
1939 | - self._check_script(script_dir, "<run_path>", compiled_name, |
1940 | + legacy_pyc = make_legacy_pyc(script_name) |
1941 | + self._check_script(script_dir, "<run_path>", legacy_pyc, |
1942 | script_dir, '') |
1943 | |
1944 | def test_directory_error(self): |
1945 | @@ -371,8 +379,9 @@ |
1946 | with temp_dir() as script_dir: |
1947 | mod_name = '__main__' |
1948 | script_name = self._make_test_script(script_dir, mod_name) |
1949 | - compiled_name = compile_script(script_name) |
1950 | - zip_name, fname = make_zip_script(script_dir, 'test_zip', compiled_name) |
1951 | + compiled_name = py_compile.compile(script_name, doraise=True) |
1952 | + zip_name, fname = make_zip_script(script_dir, 'test_zip', |
1953 | + compiled_name) |
1954 | self._check_script(zip_name, "<run_path>", fname, zip_name, '') |
1955 | |
1956 | def test_zipfile_error(self): |
1957 | |
1958 | === modified file 'Lib/test/test_site.py' |
1959 | --- Lib/test/test_site.py 2010-01-29 11:41:03 +0000 |
1960 | +++ Lib/test/test_site.py 2010-04-16 18:55:41 +0000 |
1961 | @@ -258,19 +258,38 @@ |
1962 | """Restore sys.path""" |
1963 | sys.path[:] = self.sys_path |
1964 | |
1965 | - def test_abs__file__(self): |
1966 | - # Make sure all imported modules have their __file__ attribute |
1967 | - # as an absolute path. |
1968 | - # Handled by abs__file__() |
1969 | - site.abs__file__() |
1970 | - for module in (sys, os, builtins): |
1971 | - try: |
1972 | - self.assertTrue(os.path.isabs(module.__file__), repr(module)) |
1973 | - except AttributeError: |
1974 | - continue |
1975 | - # We could try everything in sys.modules; however, when regrtest.py |
1976 | - # runs something like test_frozen before test_site, then we will |
1977 | - # be testing things loaded *after* test_site did path normalization |
1978 | + def test_abs_paths(self): |
1979 | + # Make sure all imported modules have their __file__ and __cached__ |
1980 | + # attributes as absolute paths. Arranging to put the Lib directory on |
1981 | + # PYTHONPATH would cause the os module to have a relative path for |
1982 | + # __file__ if abs_paths() does not get run. sys and builtins (the |
1983 | + # only other modules imported before site.py runs) do not have |
1984 | + # __file__ or __cached__ because they are built-in. |
1985 | + parent = os.path.relpath(os.path.dirname(os.__file__)) |
1986 | + env = os.environ.copy() |
1987 | + env['PYTHONPATH'] = parent |
1988 | + command = 'import os; print(os.__file__, os.__cached__)' |
1989 | + # First, prove that with -S (no 'import site'), the paths are |
1990 | + # relative. |
1991 | + proc = subprocess.Popen([sys.executable, '-S', '-c', command], |
1992 | + env=env, |
1993 | + stdout=subprocess.PIPE, |
1994 | + stderr=subprocess.PIPE) |
1995 | + stdout, stderr = proc.communicate() |
1996 | + self.assertEqual(proc.returncode, 0) |
1997 | + os__file__, os__cached__ = stdout.split() |
1998 | + self.assertFalse(os.path.isabs(os__file__)) |
1999 | + self.assertFalse(os.path.isabs(os__cached__)) |
2000 | + # Now, with 'import site', it works. |
2001 | + proc = subprocess.Popen([sys.executable, '-c', command], |
2002 | + env=env, |
2003 | + stdout=subprocess.PIPE, |
2004 | + stderr=subprocess.PIPE) |
2005 | + stdout, stderr = proc.communicate() |
2006 | + self.assertEqual(proc.returncode, 0) |
2007 | + os__file__, os__cached__ = stdout.split() |
2008 | + self.assertTrue(os.path.isabs(os__file__)) |
2009 | + self.assertTrue(os.path.isabs(os__cached__)) |
2010 | |
2011 | def test_no_duplicate_paths(self): |
2012 | # No duplicate paths should exist in sys.path |
2013 | |
2014 | === modified file 'Lib/test/test_zipfile.py' |
2015 | --- Lib/test/test_zipfile.py 2010-02-07 20:24:02 +0000 |
2016 | +++ Lib/test/test_zipfile.py 2010-04-16 18:55:41 +0000 |
2017 | @@ -6,6 +6,7 @@ |
2018 | |
2019 | import io |
2020 | import os |
2021 | +import imp |
2022 | import time |
2023 | import shutil |
2024 | import struct |
2025 | @@ -587,7 +588,13 @@ |
2026 | with zipfile.PyZipFile(TemporaryFile(), "w") as zipfp: |
2027 | fn = __file__ |
2028 | if fn.endswith('.pyc') or fn.endswith('.pyo'): |
2029 | - fn = fn[:-1] |
2030 | + path_split = fn.split(os.sep) |
2031 | + if os.altsep is not None: |
2032 | + path_split.extend(fn.split(os.altsep)) |
2033 | + if '__pycache__' in path_split: |
2034 | + fn = imp.source_from_cache(fn) |
2035 | + else: |
2036 | + fn = fn[:-1] |
2037 | |
2038 | zipfp.writepy(fn) |
2039 | |
2040 | |
2041 | === modified file 'Lib/test/test_zipimport.py' |
2042 | --- Lib/test/test_zipimport.py 2010-03-14 10:23:39 +0000 |
2043 | +++ Lib/test/test_zipimport.py 2010-04-16 18:55:41 +0000 |
2044 | @@ -48,17 +48,14 @@ |
2045 | test_pyc = make_pyc(test_co, NOW) |
2046 | |
2047 | |
2048 | -if __debug__: |
2049 | - pyc_ext = ".pyc" |
2050 | -else: |
2051 | - pyc_ext = ".pyo" |
2052 | - |
2053 | - |
2054 | TESTMOD = "ziptestmodule" |
2055 | TESTPACK = "ziptestpackage" |
2056 | TESTPACK2 = "ziptestpackage2" |
2057 | TEMP_ZIP = os.path.abspath("junk95142.zip") |
2058 | |
2059 | +pyc_file = imp.cache_from_source(TESTMOD + '.py') |
2060 | +pyc_ext = ('.pyc' if __debug__ else '.pyo') |
2061 | + |
2062 | |
2063 | class UncompressedZipImportTestCase(ImportHooksBaseTestCase): |
2064 | |
2065 | @@ -83,14 +80,11 @@ |
2066 | stuff = kw.get("stuff", None) |
2067 | if stuff is not None: |
2068 | # Prepend 'stuff' to the start of the zipfile |
2069 | - f = open(TEMP_ZIP, "rb") |
2070 | - data = f.read() |
2071 | - f.close() |
2072 | - |
2073 | - f = open(TEMP_ZIP, "wb") |
2074 | - f.write(stuff) |
2075 | - f.write(data) |
2076 | - f.close() |
2077 | + with open(TEMP_ZIP, "rb") as f: |
2078 | + data = f.read() |
2079 | + with open(TEMP_ZIP, "wb") as f: |
2080 | + f.write(stuff) |
2081 | + f.write(data) |
2082 | |
2083 | sys.path.insert(0, TEMP_ZIP) |
2084 | |
2085 | @@ -180,8 +174,9 @@ |
2086 | |
2087 | def testBadMTime(self): |
2088 | badtime_pyc = bytearray(test_pyc) |
2089 | - badtime_pyc[7] ^= 0x02 # flip the second bit -- not the first as that one |
2090 | - # isn't stored in the .py's mtime in the zip archive. |
2091 | + # flip the second bit -- not the first as that one isn't stored in the |
2092 | + # .py's mtime in the zip archive. |
2093 | + badtime_pyc[7] ^= 0x02 |
2094 | files = {TESTMOD + ".py": (NOW, test_src), |
2095 | TESTMOD + pyc_ext: (NOW, badtime_pyc)} |
2096 | self.doTest(".py", files, TESTMOD) |
2097 | @@ -232,7 +227,8 @@ |
2098 | self.assertEquals(zi.get_source(TESTPACK), None) |
2099 | self.assertEquals(zi.get_source(mod_path), None) |
2100 | self.assertEquals(zi.get_filename(mod_path), mod.__file__) |
2101 | - # To pass in the module name instead of the path, we must use the right importer |
2102 | + # To pass in the module name instead of the path, we must use the |
2103 | + # right importer |
2104 | loader = mod.__loader__ |
2105 | self.assertEquals(loader.get_source(mod_name), None) |
2106 | self.assertEquals(loader.get_filename(mod_name), mod.__file__) |
2107 | @@ -266,8 +262,10 @@ |
2108 | mod = zi.load_module(TESTPACK2) |
2109 | self.assertEquals(zi.get_filename(TESTPACK2), mod.__file__) |
2110 | |
2111 | - self.assertEquals(zi.is_package(TESTPACK2 + os.sep + '__init__'), False) |
2112 | - self.assertEquals(zi.is_package(TESTPACK2 + os.sep + TESTMOD), False) |
2113 | + self.assertEquals( |
2114 | + zi.is_package(TESTPACK2 + os.sep + '__init__'), False) |
2115 | + self.assertEquals( |
2116 | + zi.is_package(TESTPACK2 + os.sep + TESTMOD), False) |
2117 | |
2118 | mod_path = TESTPACK2 + os.sep + TESTMOD |
2119 | mod_name = module_path_to_dotted_name(mod_path) |
2120 | @@ -276,7 +274,8 @@ |
2121 | self.assertEquals(zi.get_source(TESTPACK2), None) |
2122 | self.assertEquals(zi.get_source(mod_path), None) |
2123 | self.assertEquals(zi.get_filename(mod_path), mod.__file__) |
2124 | - # To pass in the module name instead of the path, we must use the right importer |
2125 | + # To pass in the module name instead of the path, we must use the |
2126 | + # right importer |
2127 | loader = mod.__loader__ |
2128 | self.assertEquals(loader.get_source(mod_name), None) |
2129 | self.assertEquals(loader.get_filename(mod_name), mod.__file__) |
2130 | |
2131 | === modified file 'Lib/zipfile.py' |
2132 | --- Lib/zipfile.py 2010-02-07 20:24:02 +0000 |
2133 | +++ Lib/zipfile.py 2010-04-16 18:55:41 +0000 |
2134 | @@ -3,10 +3,17 @@ |
2135 | |
2136 | XXX references to utf-8 need further investigation. |
2137 | """ |
2138 | -import struct, os, time, sys, shutil |
2139 | -import binascii, io, stat |
2140 | import io |
2141 | +import os |
2142 | import re |
2143 | +import imp |
2144 | +import sys |
2145 | +import time |
2146 | +import stat |
2147 | +import shutil |
2148 | +import struct |
2149 | +import binascii |
2150 | + |
2151 | |
2152 | try: |
2153 | import zlib # We may need its compression method |
2154 | @@ -1303,22 +1310,42 @@ |
2155 | file_py = pathname + ".py" |
2156 | file_pyc = pathname + ".pyc" |
2157 | file_pyo = pathname + ".pyo" |
2158 | - if os.path.isfile(file_pyo) and \ |
2159 | - os.stat(file_pyo).st_mtime >= os.stat(file_py).st_mtime: |
2160 | - fname = file_pyo # Use .pyo file |
2161 | - elif not os.path.isfile(file_pyc) or \ |
2162 | - os.stat(file_pyc).st_mtime < os.stat(file_py).st_mtime: |
2163 | + pycache_pyc = imp.cache_from_source(file_py, True) |
2164 | + pycache_pyo = imp.cache_from_source(file_py, False) |
2165 | + if (os.path.isfile(file_pyo) and |
2166 | + os.stat(file_pyo).st_mtime >= os.stat(file_py).st_mtime): |
2167 | + # Use .pyo file. |
2168 | + arcname = fname = file_pyo |
2169 | + elif (os.path.isfile(file_pyc) and |
2170 | + os.stat(file_pyc).st_mtime >= os.stat(file_py).st_mtime): |
2171 | + # Use .pyc file. |
2172 | + arcname = fname = file_pyc |
2173 | + elif (os.path.isfile(pycache_pyc) and |
2174 | + os.stat(pycache_pyc).st_mtime >= os.stat(file_py).st_mtime): |
2175 | + # Use the __pycache__/*.pyc file, but write it to the legacy pyc |
2176 | + # file name in the archive. |
2177 | + fname = pycache_pyc |
2178 | + arcname = file_pyc |
2179 | + elif (os.path.isfile(pycache_pyo) and |
2180 | + os.stat(pycache_pyo).st_mtime >= os.stat(file_py).st_mtime): |
2181 | + # Use the __pycache__/*.pyo file, but write it to the legacy pyo |
2182 | + # file name in the archive. |
2183 | + fname = pycache_pyo |
2184 | + arcname = file_pyo |
2185 | + else: |
2186 | + # Compile py into PEP 3147 pyc file. |
2187 | import py_compile |
2188 | if self.debug: |
2189 | print("Compiling", file_py) |
2190 | try: |
2191 | - py_compile.compile(file_py, file_pyc, None, True) |
2192 | - except py_compile.PyCompileError as err: |
2193 | + py_compile.compile(file_py, doraise=True) |
2194 | + except py_compile.PyCompileError as error: |
2195 | print(err.msg) |
2196 | - fname = file_pyc |
2197 | - else: |
2198 | - fname = file_pyc |
2199 | - archivename = os.path.split(fname)[1] |
2200 | + fname = file_py |
2201 | + else: |
2202 | + fname = (pycache_pyc if __debug__ else pycache_pyo) |
2203 | + arcname = (file_pyc if __debug__ else file_pyo) |
2204 | + archivename = os.path.split(arcname)[1] |
2205 | if basename: |
2206 | archivename = "%s/%s" % (basename, archivename) |
2207 | return (fname, archivename) |
2208 | |
2209 | === modified file 'Makefile.pre.in' |
2210 | --- Makefile.pre.in 2010-04-11 23:16:50 +0000 |
2211 | +++ Makefile.pre.in 2010-04-16 18:55:41 +0000 |
2212 | @@ -1161,6 +1161,7 @@ |
2213 | # files, which clobber removes as well |
2214 | pycremoval: |
2215 | find $(srcdir) -name '*.py[co]' -exec rm -f {} ';' |
2216 | + find $(srcdir) -name '__pycache__' | xargs rmdir |
2217 | |
2218 | rmtestturds: |
2219 | -rm -f *BAD *GOOD *SKIPPED |
2220 | |
2221 | === modified file 'Python/import.c' |
2222 | --- Python/import.c 2010-03-25 23:30:20 +0000 |
2223 | +++ Python/import.c 2010-04-16 18:55:41 +0000 |
2224 | @@ -43,6 +43,15 @@ |
2225 | The current working scheme is to increment the previous value by |
2226 | 10. |
2227 | |
2228 | + Starting with the adoption of PEP 3147 in Python 3.2, every bump in magic |
2229 | + number also includes a new "magic tag", i.e. a human readable string used |
2230 | + to represent the magic number in __pycache__ directories. When you change |
2231 | + the magic number, you must also set a new unique magic tag. Generally this |
2232 | + can be named after the Python major version of the magic number bump, but |
2233 | + it can really be anything, as long as it's different than anything else |
2234 | + that's come before. The tags are included in the following table, starting |
2235 | + with Python 3.2a0. |
2236 | + |
2237 | Known values: |
2238 | Python 1.5: 20121 |
2239 | Python 1.5.1: 20121 |
2240 | @@ -91,11 +100,18 @@ |
2241 | Python 3.1a0: 3151 (optimize conditional branches: |
2242 | introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE) |
2243 | Python 3.2a0: 3160 (add SETUP_WITH) |
2244 | + tag: cpython-32 |
2245 | */ |
2246 | |
2247 | +/* If you change MAGIC, you must change TAG and you must insert the old value |
2248 | + into _PyMagicNumberTags below. |
2249 | +*/ |
2250 | #define MAGIC (3160 | ((long)'\r'<<16) | ((long)'\n'<<24)) |
2251 | -/* Magic word as global */ |
2252 | +#define TAG "cpython-32" |
2253 | +#define CACHEDIR "__pycache__" |
2254 | +/* Current magic word and string tag as globals. */ |
2255 | static long pyc_magic = MAGIC; |
2256 | +static const char *pyc_tag = TAG; |
2257 | |
2258 | /* See _PyImport_FixupExtension() below */ |
2259 | static PyObject *extensions = NULL; |
2260 | @@ -517,7 +533,7 @@ |
2261 | } |
2262 | |
2263 | |
2264 | -/* Helper for pythonrun.c -- return magic number */ |
2265 | +/* Helper for pythonrun.c -- return magic number and tag. */ |
2266 | |
2267 | long |
2268 | PyImport_GetMagicNumber(void) |
2269 | @@ -526,6 +542,12 @@ |
2270 | } |
2271 | |
2272 | |
2273 | +const char * |
2274 | +PyImport_GetMagicTag(void) |
2275 | +{ |
2276 | + return pyc_tag; |
2277 | +} |
2278 | + |
2279 | /* Magic for extension modules (built-in as well as dynamically |
2280 | loaded). To prevent initializing an extension module more than |
2281 | once, we keep a static dictionary 'extensions' keyed by module name |
2282 | @@ -671,7 +693,10 @@ |
2283 | "sys.modules failed"); |
2284 | } |
2285 | |
2286 | -static PyObject * get_sourcefile(const char *file); |
2287 | +static PyObject * get_sourcefile(char *file); |
2288 | +static char *make_source_pathname(char *pathname, char *buf); |
2289 | +static char *make_compiled_pathname(char *pathname, char *buf, size_t buflen, |
2290 | + int debug); |
2291 | |
2292 | /* Execute a code object in a module and return the module object |
2293 | * WITH INCREMENTED REFERENCE COUNT. If an error occurs, name is |
2294 | @@ -679,16 +704,28 @@ |
2295 | * in sys.modules. The caller may wish to restore the original |
2296 | * module object (if any) in this case; PyImport_ReloadModule is an |
2297 | * example. |
2298 | + * |
2299 | + * Note that PyImport_ExecCodeModuleWithPathnames() is the preferred, richer |
2300 | + * interface. The other two exist primarily for backward compatibility. |
2301 | */ |
2302 | PyObject * |
2303 | PyImport_ExecCodeModule(char *name, PyObject *co) |
2304 | { |
2305 | - return PyImport_ExecCodeModuleEx(name, co, (char *)NULL); |
2306 | + return PyImport_ExecCodeModuleWithPathnames( |
2307 | + name, co, (char *)NULL, (char *)NULL); |
2308 | } |
2309 | |
2310 | PyObject * |
2311 | PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname) |
2312 | { |
2313 | + return PyImport_ExecCodeModuleWithPathnames( |
2314 | + name, co, pathname, (char *)NULL); |
2315 | +} |
2316 | + |
2317 | +PyObject * |
2318 | +PyImport_ExecCodeModuleWithPathnames(char *name, PyObject *co, char *pathname, |
2319 | + char *cpathname) |
2320 | +{ |
2321 | PyObject *modules = PyImport_GetModuleDict(); |
2322 | PyObject *m, *d, *v; |
2323 | |
2324 | @@ -718,6 +755,20 @@ |
2325 | PyErr_Clear(); /* Not important enough to report */ |
2326 | Py_DECREF(v); |
2327 | |
2328 | + /* Remember the pyc path name as the __cached__ attribute. */ |
2329 | + if (cpathname == NULL) { |
2330 | + v = Py_None; |
2331 | + Py_INCREF(v); |
2332 | + } |
2333 | + else if ((v = PyUnicode_FromString(cpathname)) == NULL) { |
2334 | + PyErr_Clear(); /* Not important enough to report */ |
2335 | + v = Py_None; |
2336 | + Py_INCREF(v); |
2337 | + } |
2338 | + if (PyDict_SetItemString(d, "__cached__", v) != 0) |
2339 | + PyErr_Clear(); /* Not important enough to report */ |
2340 | + Py_DECREF(v); |
2341 | + |
2342 | v = PyEval_EvalCode((PyCodeObject *)co, d, d); |
2343 | if (v == NULL) |
2344 | goto error; |
2345 | @@ -740,31 +791,188 @@ |
2346 | } |
2347 | |
2348 | |
2349 | +/* Like strrchr(string, '/') but searches for the rightmost of either SEP |
2350 | + or ALTSEP, if the latter is defined. |
2351 | +*/ |
2352 | +static char * |
2353 | +rightmost_sep(char *s) |
2354 | +{ |
2355 | + char *found, c; |
2356 | + for (found = NULL; (c = *s); s++) { |
2357 | + if (c == SEP |
2358 | +#ifdef ALTSEP |
2359 | + || c == ALTSEP |
2360 | +#endif |
2361 | + ) |
2362 | + { |
2363 | + found = s; |
2364 | + } |
2365 | + } |
2366 | + return found; |
2367 | +} |
2368 | + |
2369 | + |
2370 | /* Given a pathname for a Python source file, fill a buffer with the |
2371 | pathname for the corresponding compiled file. Return the pathname |
2372 | for the compiled file, or NULL if there's no space in the buffer. |
2373 | Doesn't set an exception. */ |
2374 | |
2375 | static char * |
2376 | -make_compiled_pathname(char *pathname, char *buf, size_t buflen) |
2377 | +make_compiled_pathname(char *pathname, char *buf, size_t buflen, int debug) |
2378 | { |
2379 | + /* foo.py -> __pycache__/foo.<tag>.pyc */ |
2380 | size_t len = strlen(pathname); |
2381 | - if (len+2 > buflen) |
2382 | + size_t i, save; |
2383 | + char *pos; |
2384 | + int sep = SEP; |
2385 | + |
2386 | + /* Sanity check that the buffer has roughly enough space to hold what |
2387 | + will eventually be the full path to the compiled file. The 5 extra |
2388 | + bytes include the slash afer __pycache__, the two extra dots, the |
2389 | + extra trailing character ('c' or 'o') and null. This isn't exact |
2390 | + because the contents of the buffer can affect how many actual |
2391 | + characters of the string get into the buffer. We'll do a final |
2392 | + sanity check before writing the extension to ensure we do not |
2393 | + overflow the buffer. |
2394 | + */ |
2395 | + if (len + strlen(CACHEDIR) + strlen(pyc_tag) + 5 > buflen) |
2396 | return NULL; |
2397 | |
2398 | -#ifdef MS_WINDOWS |
2399 | - /* Treat .pyw as if it were .py. The case of ".pyw" must match |
2400 | - that used in _PyImport_StandardFiletab. */ |
2401 | - if (len >= 4 && strcmp(&pathname[len-4], ".pyw") == 0) |
2402 | - --len; /* pretend 'w' isn't there */ |
2403 | + /* Find the last path separator and copy everything from the start of |
2404 | + the source string up to and including the separator. |
2405 | + */ |
2406 | + if ((pos = rightmost_sep(pathname)) == NULL) { |
2407 | + i = 0; |
2408 | + } |
2409 | + else { |
2410 | + sep = *pos; |
2411 | + i = pos - pathname + 1; |
2412 | + strncpy(buf, pathname, i); |
2413 | + } |
2414 | + |
2415 | + save = i; |
2416 | + buf[i++] = '\0'; |
2417 | + /* Add __pycache__/ */ |
2418 | + strcat(buf, CACHEDIR); |
2419 | + i += strlen(CACHEDIR) - 1; |
2420 | + buf[i++] = sep; |
2421 | + buf[i++] = '\0'; |
2422 | + /* Add the base filename, but remove the .py or .pyw extension, since |
2423 | + the tag name must go before the extension. |
2424 | + */ |
2425 | + strcat(buf, pathname + save); |
2426 | + if ((pos = strrchr(buf, '.')) != NULL) |
2427 | + *++pos = '\0'; |
2428 | + strcat(buf, pyc_tag); |
2429 | + /* The length test above assumes that we're only adding one character |
2430 | + to the end of what would normally be the extension. What if there |
2431 | + is no extension, or the string ends in '.' or '.p', and otherwise |
2432 | + fills the buffer? By appending 4 more characters onto the string |
2433 | + here, we could overrun the buffer. |
2434 | + |
2435 | + As a simple example, let's say buflen=32 and the input string is |
2436 | + 'xxx.py'. strlen() would be 6 and the test above would yield: |
2437 | + |
2438 | + (6 + 11 + 10 + 5 == 32) > 32 |
2439 | + |
2440 | + which is false and so the name mangling would continue. This would |
2441 | + be fine because we'd end up with this string in buf: |
2442 | + |
2443 | + __pycache__/xxx.cpython-32.pyc\0 |
2444 | + |
2445 | + strlen(of that) == 30 + the nul fits inside a 32 character buffer. |
2446 | + We can even handle an input string of say 'xxxxx' above because |
2447 | + that's (5 + 11 + 10 + 5 == 31) > 32 which is also false. Name |
2448 | + mangling that yields: |
2449 | + |
2450 | + __pycache__/xxxxxcpython-32.pyc\0 |
2451 | + |
2452 | + which is 32 characters including the nul, and thus fits in the |
2453 | + buffer. However, an input string of 'xxxxxx' would yield a result |
2454 | + string of: |
2455 | + |
2456 | + __pycache__/xxxxxxcpython-32.pyc\0 |
2457 | + |
2458 | + which is 33 characters long (including the nul), thus overflowing |
2459 | + the buffer, even though the first test would fail, i.e.: the input |
2460 | + string is also 6 characters long, so 32 > 32 is false. |
2461 | + |
2462 | + The reason the first test fails but we still overflow the buffer is |
2463 | + that the test above only expects to add one extra character to be |
2464 | + added to the extension, and here we're adding three (pyc). We |
2465 | + don't add the first dot, so that reclaims one of expected |
2466 | + positions, leaving us overflowing by 1 byte (3 extra - 1 reclaimed |
2467 | + dot - 1 expected extra == 1 overflowed). |
2468 | + |
2469 | + The best we can do is ensure that we still have enough room in the |
2470 | + target buffer before we write the extension. Because it's always |
2471 | + only the extension that can cause the overflow, and never the other |
2472 | + path bytes we've written, it's sufficient to just do one more test |
2473 | + here. Still, the assertion that follows can't hurt. |
2474 | + */ |
2475 | +#if 0 |
2476 | + printf("strlen(buf): %d; buflen: %d\n", (int)strlen(buf), (int)buflen); |
2477 | #endif |
2478 | - memcpy(buf, pathname, len); |
2479 | - buf[len] = Py_OptimizeFlag ? 'o' : 'c'; |
2480 | - buf[len+1] = '\0'; |
2481 | - |
2482 | - return buf; |
2483 | -} |
2484 | - |
2485 | + if (strlen(buf) + 5 > buflen) |
2486 | + return NULL; |
2487 | + strcat(buf, debug ? ".pyc" : ".pyo"); |
2488 | + assert(strlen(buf) < buflen); |
2489 | + return buf; |
2490 | +} |
2491 | + |
2492 | + |
2493 | +/* Given a pathname to a Python byte compiled file, return the path to the |
2494 | + source file, if the path matches the PEP 3147 format. This does not check |
2495 | + for any file existence, however, if the pyc file name does not match PEP |
2496 | + 3147 style, NULL is returned. buf must be at least as big as pathname; |
2497 | + the resulting path will always be shorter. */ |
2498 | + |
2499 | +static char * |
2500 | +make_source_pathname(char *pathname, char *buf) |
2501 | +{ |
2502 | + /* __pycache__/foo.<tag>.pyc -> foo.py */ |
2503 | + size_t i, j; |
2504 | + char *left, *right, *dot0, *dot1, sep; |
2505 | + |
2506 | + /* Look back two slashes from the end. In between these two slashes |
2507 | + must be the string __pycache__ or this is not a PEP 3147 style |
2508 | + path. It's possible for there to be only one slash. |
2509 | + */ |
2510 | + if ((right = rightmost_sep(pathname)) == NULL) |
2511 | + return NULL; |
2512 | + sep = *right; |
2513 | + *right = '\0'; |
2514 | + left = rightmost_sep(pathname); |
2515 | + *right = sep; |
2516 | + if (left == NULL) |
2517 | + left = pathname; |
2518 | + else |
2519 | + left++; |
2520 | + if (right-left != strlen(CACHEDIR) || |
2521 | + strncmp(left, CACHEDIR, right-left) != 0) |
2522 | + return NULL; |
2523 | + |
2524 | + /* Now verify that the path component to the right of the last slash |
2525 | + has two dots in it. |
2526 | + */ |
2527 | + if ((dot0 = strchr(right + 1, '.')) == NULL) |
2528 | + return NULL; |
2529 | + if ((dot1 = strchr(dot0 + 1, '.')) == NULL) |
2530 | + return NULL; |
2531 | + /* Too many dots? */ |
2532 | + if (strchr(dot1 + 1, '.') != NULL) |
2533 | + return NULL; |
2534 | + |
2535 | + /* This is a PEP 3147 path. Start by copying everything from the |
2536 | + start of pathname up to and including the leftmost slash. Then |
2537 | + copy the file's basename, removing the magic tag and adding a .py |
2538 | + suffix. |
2539 | + */ |
2540 | + strncpy(buf, pathname, (i=left-pathname)); |
2541 | + strncpy(buf+i, right+1, (j=dot0-right)); |
2542 | + strcpy(buf+i+j, "py"); |
2543 | + return buf; |
2544 | +} |
2545 | |
2546 | /* Given a pathname for a Python source file, its time of last |
2547 | modification, and a pathname for a compiled file, check whether the |
2548 | @@ -846,7 +1054,8 @@ |
2549 | if (Py_VerboseFlag) |
2550 | PySys_WriteStderr("import %s # precompiled from %s\n", |
2551 | name, cpathname); |
2552 | - m = PyImport_ExecCodeModuleEx(name, (PyObject *)co, cpathname); |
2553 | + m = PyImport_ExecCodeModuleWithPathnames( |
2554 | + name, (PyObject *)co, cpathname, cpathname); |
2555 | Py_DECREF(co); |
2556 | |
2557 | return m; |
2558 | @@ -919,12 +1128,41 @@ |
2559 | write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat) |
2560 | { |
2561 | FILE *fp; |
2562 | + char *dirpath; |
2563 | time_t mtime = srcstat->st_mtime; |
2564 | #ifdef MS_WINDOWS /* since Windows uses different permissions */ |
2565 | mode_t mode = srcstat->st_mode & ~S_IEXEC; |
2566 | + mode_t dirmode = srcstat->st_mode | S_IEXEC; /* XXX Is this correct |
2567 | + for Windows? |
2568 | + 2010-04-07 BAW */ |
2569 | #else |
2570 | mode_t mode = srcstat->st_mode & ~S_IXUSR & ~S_IXGRP & ~S_IXOTH; |
2571 | + mode_t dirmode = (srcstat->st_mode | |
2572 | + S_IXUSR | S_IXGRP | S_IXOTH | |
2573 | + S_IWUSR | S_IWGRP | S_IWOTH); |
2574 | #endif |
2575 | + int saved; |
2576 | + |
2577 | + /* Ensure that the __pycache__ directory exists. */ |
2578 | + dirpath = rightmost_sep(cpathname); |
2579 | + if (dirpath == NULL) { |
2580 | + if (Py_VerboseFlag) |
2581 | + PySys_WriteStderr( |
2582 | + "# no %s path found %s\n", |
2583 | + CACHEDIR, cpathname); |
2584 | + return; |
2585 | + } |
2586 | + saved = *dirpath; |
2587 | + *dirpath = '\0'; |
2588 | + /* XXX call os.mkdir() or maybe CreateDirectoryA() on Windows? */ |
2589 | + if (mkdir(cpathname, dirmode) < 0 && errno != EEXIST) { |
2590 | + *dirpath = saved; |
2591 | + if (Py_VerboseFlag) |
2592 | + PySys_WriteStderr( |
2593 | + "# cannot create cache dir %s\n", cpathname); |
2594 | + return; |
2595 | + } |
2596 | + *dirpath = saved; |
2597 | |
2598 | fp = open_exclusive(cpathname, mode); |
2599 | if (fp == NULL) { |
2600 | @@ -1032,8 +1270,8 @@ |
2601 | return NULL; |
2602 | } |
2603 | #endif |
2604 | - cpathname = make_compiled_pathname(pathname, buf, |
2605 | - (size_t)MAXPATHLEN + 1); |
2606 | + cpathname = make_compiled_pathname( |
2607 | + pathname, buf, (size_t)MAXPATHLEN + 1, !Py_OptimizeFlag); |
2608 | if (cpathname != NULL && |
2609 | (fpc = check_compiled_module(pathname, st.st_mtime, cpathname))) { |
2610 | co = read_compiled_module(cpathname, fpc); |
2611 | @@ -1060,7 +1298,8 @@ |
2612 | write_compiled_module(co, cpathname, &st); |
2613 | } |
2614 | } |
2615 | - m = PyImport_ExecCodeModuleEx(name, (PyObject *)co, pathname); |
2616 | + m = PyImport_ExecCodeModuleWithPathnames( |
2617 | + name, (PyObject *)co, pathname, cpathname); |
2618 | Py_DECREF(co); |
2619 | |
2620 | return m; |
2621 | @@ -1070,7 +1309,7 @@ |
2622 | * Returns the path to the py file if available, else the given path |
2623 | */ |
2624 | static PyObject * |
2625 | -get_sourcefile(const char *file) |
2626 | +get_sourcefile(char *file) |
2627 | { |
2628 | char py[MAXPATHLEN + 1]; |
2629 | Py_ssize_t len; |
2630 | @@ -1087,8 +1326,15 @@ |
2631 | return PyUnicode_DecodeFSDefault(file); |
2632 | } |
2633 | |
2634 | - strncpy(py, file, len-1); |
2635 | - py[len-1] = '\0'; |
2636 | + /* Start by trying to turn PEP 3147 path into source path. If that |
2637 | + * fails, just chop off the trailing character, i.e. legacy pyc path |
2638 | + * to py. |
2639 | + */ |
2640 | + if (make_source_pathname(file, py) == NULL) { |
2641 | + strncpy(py, file, len-1); |
2642 | + py[len-1] = '\0'; |
2643 | + } |
2644 | + |
2645 | if (stat(py, &statbuf) == 0 && |
2646 | S_ISREG(statbuf.st_mode)) { |
2647 | u = PyUnicode_DecodeFSDefault(py); |
2648 | @@ -2813,16 +3059,28 @@ |
2649 | */ |
2650 | |
2651 | static PyObject * |
2652 | -imp_get_magic(PyObject *self, PyObject *noargs) |
2653 | +imp_make_magic(long magic) |
2654 | { |
2655 | char buf[4]; |
2656 | |
2657 | - buf[0] = (char) ((pyc_magic >> 0) & 0xff); |
2658 | - buf[1] = (char) ((pyc_magic >> 8) & 0xff); |
2659 | - buf[2] = (char) ((pyc_magic >> 16) & 0xff); |
2660 | - buf[3] = (char) ((pyc_magic >> 24) & 0xff); |
2661 | + buf[0] = (char) ((magic >> 0) & 0xff); |
2662 | + buf[1] = (char) ((magic >> 8) & 0xff); |
2663 | + buf[2] = (char) ((magic >> 16) & 0xff); |
2664 | + buf[3] = (char) ((magic >> 24) & 0xff); |
2665 | |
2666 | return PyBytes_FromStringAndSize(buf, 4); |
2667 | +}; |
2668 | + |
2669 | +static PyObject * |
2670 | +imp_get_magic(PyObject *self, PyObject *noargs) |
2671 | +{ |
2672 | + return imp_make_magic(pyc_magic); |
2673 | +} |
2674 | + |
2675 | +static PyObject * |
2676 | +imp_get_tag(PyObject *self, PyObject *noargs) |
2677 | +{ |
2678 | + return PyUnicode_FromString(pyc_tag); |
2679 | } |
2680 | |
2681 | static PyObject * |
2682 | @@ -3190,6 +3448,75 @@ |
2683 | \n\ |
2684 | Reload the module. The module must have been successfully imported before."); |
2685 | |
2686 | +static PyObject * |
2687 | +imp_cache_from_source(PyObject *self, PyObject *args, PyObject *kws) |
2688 | +{ |
2689 | + static char *kwlist[] = {"path", "debug_override", NULL}; |
2690 | + |
2691 | + char buf[MAXPATHLEN+1]; |
2692 | + char *pathname, *cpathname; |
2693 | + PyObject *debug_override = Py_None; |
2694 | + int debug = !Py_OptimizeFlag; |
2695 | + |
2696 | + if (!PyArg_ParseTupleAndKeywords( |
2697 | + args, kws, "es|O", kwlist, |
2698 | + Py_FileSystemDefaultEncoding, &pathname, &debug_override)) |
2699 | + return NULL; |
2700 | + |
2701 | + if (debug_override != Py_None) |
2702 | + if ((debug = PyObject_IsTrue(debug_override)) < 0) |
2703 | + return NULL; |
2704 | + |
2705 | + cpathname = make_compiled_pathname(pathname, buf, MAXPATHLEN+1, debug); |
2706 | + PyMem_Free(pathname); |
2707 | + |
2708 | + if (cpathname == NULL) { |
2709 | + PyErr_Format(PyExc_SystemError, "path buffer too short"); |
2710 | + return NULL; |
2711 | + } |
2712 | + return PyUnicode_FromString(buf); |
2713 | +} |
2714 | + |
2715 | +PyDoc_STRVAR(doc_cache_from_source, |
2716 | +"Given the path to a .py file, return the path to its .pyc/.pyo file.\n\ |
2717 | +\n\ |
2718 | +The .py file does not need to exist; this simply returns the path to the\n\ |
2719 | +.pyc/.pyo file calculated as if the .py file were imported. The extension\n\ |
2720 | +will be .pyc unless __debug__ is not defined, then it will be .pyo.\n\ |
2721 | +\n\ |
2722 | +If debug_override is not None, then it must be a boolean and is taken as\n\ |
2723 | +the value of __debug__ instead."); |
2724 | + |
2725 | +static PyObject * |
2726 | +imp_source_from_cache(PyObject *self, PyObject *args, PyObject *kws) |
2727 | +{ |
2728 | + static char *kwlist[] = {"path", NULL}; |
2729 | + |
2730 | + char *pathname; |
2731 | + char buf[MAXPATHLEN+1]; |
2732 | + |
2733 | + if (!PyArg_ParseTupleAndKeywords( |
2734 | + args, kws, "es", kwlist, |
2735 | + Py_FileSystemDefaultEncoding, &pathname)) |
2736 | + return NULL; |
2737 | + |
2738 | + if (make_source_pathname(pathname, buf) == NULL) { |
2739 | + PyErr_Format(PyExc_ValueError, "Not a PEP 3147 pyc path: %s", |
2740 | + pathname); |
2741 | + PyMem_Free(pathname); |
2742 | + return NULL; |
2743 | + } |
2744 | + PyMem_Free(pathname); |
2745 | + return PyUnicode_FromString(buf); |
2746 | +} |
2747 | + |
2748 | +PyDoc_STRVAR(doc_source_from_cache, |
2749 | +"Given the path to a .pyc./.pyo file, return the path to its .py file.\n\ |
2750 | +\n\ |
2751 | +The .pyc/.pyo file does not need to exist; this simply returns the path to\n\ |
2752 | +the .py file calculated to correspond to the .pyc/.pyo file. If path\n\ |
2753 | +does not conform to PEP 3147 format, ValueError will be raised."); |
2754 | + |
2755 | /* Doc strings */ |
2756 | |
2757 | PyDoc_STRVAR(doc_imp, |
2758 | @@ -3212,6 +3539,10 @@ |
2759 | "get_magic() -> string\n\ |
2760 | Return the magic number for .pyc or .pyo files."); |
2761 | |
2762 | +PyDoc_STRVAR(doc_get_tag, |
2763 | +"get_tag() -> string\n\ |
2764 | +Return the magic tag for .pyc or .pyo files."); |
2765 | + |
2766 | PyDoc_STRVAR(doc_get_suffixes, |
2767 | "get_suffixes() -> [(suffix, mode, type), ...]\n\ |
2768 | Return a list of (suffix, mode, type) tuples describing the files\n\ |
2769 | @@ -3242,6 +3573,7 @@ |
2770 | static PyMethodDef imp_methods[] = { |
2771 | {"find_module", imp_find_module, METH_VARARGS, doc_find_module}, |
2772 | {"get_magic", imp_get_magic, METH_NOARGS, doc_get_magic}, |
2773 | + {"get_tag", imp_get_tag, METH_NOARGS, doc_get_tag}, |
2774 | {"get_suffixes", imp_get_suffixes, METH_NOARGS, doc_get_suffixes}, |
2775 | {"load_module", imp_load_module, METH_VARARGS, doc_load_module}, |
2776 | {"new_module", imp_new_module, METH_VARARGS, doc_new_module}, |
2777 | @@ -3249,6 +3581,10 @@ |
2778 | {"acquire_lock", imp_acquire_lock, METH_NOARGS, doc_acquire_lock}, |
2779 | {"release_lock", imp_release_lock, METH_NOARGS, doc_release_lock}, |
2780 | {"reload", imp_reload, METH_O, doc_reload}, |
2781 | + {"cache_from_source", (PyCFunction)imp_cache_from_source, |
2782 | + METH_VARARGS | METH_KEYWORDS, doc_cache_from_source}, |
2783 | + {"source_from_cache", (PyCFunction)imp_source_from_cache, |
2784 | + METH_VARARGS | METH_KEYWORDS, doc_source_from_cache}, |
2785 | /* The rest are obsolete */ |
2786 | {"get_frozen_object", imp_get_frozen_object, METH_VARARGS}, |
2787 | {"is_frozen_package", imp_is_frozen_package, METH_VARARGS}, |
2788 | @@ -3436,7 +3772,6 @@ |
2789 | failure: |
2790 | Py_XDECREF(m); |
2791 | return NULL; |
2792 | - |
2793 | } |
2794 | |
2795 | |
2796 | |
2797 | === modified file 'Python/pythonrun.c' |
2798 | --- Python/pythonrun.c 2010-03-14 06:49:55 +0000 |
2799 | +++ Python/pythonrun.c 2010-04-16 18:55:41 +0000 |
2800 | @@ -1155,6 +1155,8 @@ |
2801 | Py_DECREF(f); |
2802 | return -1; |
2803 | } |
2804 | + if (PyDict_SetItemString(d, "__cached__", Py_None) < 0) |
2805 | + return -1; |
2806 | set_file_name = 1; |
2807 | Py_DECREF(f); |
2808 | } |