Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
327a39b0
Commit
327a39b0
authored
Nov 18, 2007
by
Nick Coghlan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Patch #1739468: Directories and zipfiles containing __main__.py are now executable
parent
5cf449cf
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
254 additions
and
47 deletions
+254
-47
Include/import.h
Include/import.h
+2
-0
Lib/test/test_cmd_line.py
Lib/test/test_cmd_line.py
+3
-0
Lib/test/test_cmd_line_script.py
Lib/test/test_cmd_line_script.py
+145
-0
Misc/NEWS
Misc/NEWS
+4
-0
Modules/main.c
Modules/main.c
+80
-40
Python/import.c
Python/import.c
+20
-7
No files found.
Include/import.h
View file @
327a39b0
...
...
@@ -24,6 +24,7 @@ PyAPI_FUNC(PyObject *) PyImport_ImportModuleEx(
#define PyImport_ImportModuleEx(n, g, l, f) \
PyImport_ImportModuleLevel(n, g, l, f, -1)
PyAPI_FUNC
(
PyObject
*
)
PyImport_GetImporter
(
PyObject
*
path
);
PyAPI_FUNC
(
PyObject
*
)
PyImport_Import
(
PyObject
*
name
);
PyAPI_FUNC
(
PyObject
*
)
PyImport_ReloadModule
(
PyObject
*
m
);
PyAPI_FUNC
(
void
)
PyImport_Cleanup
(
void
);
...
...
@@ -42,6 +43,7 @@ struct _inittab {
void
(
*
initfunc
)(
void
);
};
PyAPI_DATA
(
PyTypeObject
)
PyNullImporter_Type
;
PyAPI_DATA
(
struct
_inittab
*
)
PyImport_Inittab
;
PyAPI_FUNC
(
int
)
PyImport_AppendInittab
(
char
*
name
,
void
(
*
initfunc
)(
void
));
...
...
Lib/test/test_cmd_line.py
View file @
327a39b0
# Tests invocation of the interpreter with various command line arguments
# All tests are executed with environment variables ignored
# See test_cmd_line_script.py for testing of script execution
import
test.test_support
,
unittest
import
sys
...
...
Lib/test/test_cmd_line_script.py
0 → 100644
View file @
327a39b0
# Tests command line execution of scripts
from
__future__
import
with_statement
import
unittest
import
os
import
os.path
import
sys
import
test
import
tempfile
import
subprocess
import
py_compile
import
contextlib
import
shutil
import
zipfile
verbose
=
test
.
test_support
.
verbose
# XXX ncoghlan: Should we consider moving these to test_support?
from
test_cmd_line
import
_spawn_python
,
_kill_python
def
_run_python
(
*
args
):
if
__debug__
:
p
=
_spawn_python
(
*
args
)
else
:
p
=
_spawn_python
(
'-O'
,
*
args
)
stdout_data
=
_kill_python
(
p
)
return
p
.
wait
(),
stdout_data
@
contextlib
.
contextmanager
def
temp_dir
():
dirname
=
tempfile
.
mkdtemp
()
try
:
yield
dirname
finally
:
shutil
.
rmtree
(
dirname
)
test_source
=
(
"""
\
# Script may be run with optimisation enabled, so don't rely on assert
# statements being executed
def assertEqual(lhs, rhs):
if lhs != rhs:
raise AssertionError("%r != %r" % (lhs, rhs))
def assertIdentical(lhs, rhs):
if lhs is not rhs:
raise AssertionError("%r is not %r" % (lhs, rhs))
# Check basic code execution
result = ['Top level assignment']
def f():
result.append('Lower level reference')
f()
assertEqual(result, ['Top level assignment', 'Lower level reference'])
# Check population of magic variables
assertEqual(__name__, '__main__')
print '__file__==%r' % __file__
# Check the sys module
import sys
assertIdentical(globals(), sys.modules[__name__].__dict__)
print 'sys.argv[0]==%r' % sys.argv[0]
"""
)
def
_make_test_script
(
script_dir
,
script_basename
):
script_filename
=
script_basename
+
os
.
extsep
+
"py"
script_name
=
os
.
path
.
join
(
script_dir
,
script_filename
)
script_file
=
open
(
script_name
,
"w"
)
script_file
.
write
(
test_source
)
script_file
.
close
()
return
script_name
def
_compile_test_script
(
script_name
):
py_compile
.
compile
(
script_name
,
doraise
=
True
)
if
__debug__
:
compiled_name
=
script_name
+
'c'
else
:
compiled_name
=
script_name
+
'o'
return
compiled_name
def
_make_test_zip
(
zip_dir
,
zip_basename
,
script_name
):
zip_filename
=
zip_basename
+
os
.
extsep
+
"zip"
zip_name
=
os
.
path
.
join
(
zip_dir
,
zip_filename
)
zip_file
=
zipfile
.
ZipFile
(
zip_name
,
'w'
)
zip_file
.
write
(
script_name
,
os
.
path
.
basename
(
script_name
))
zip_file
.
close
()
# if verbose:
# zip_file = zipfile.ZipFile(zip_name, 'r')
# print "Contents of %r:" % zip_name
# zip_file.printdir()
# zip_file.close()
return
zip_name
class
CmdLineTest
(
unittest
.
TestCase
):
def
_check_script
(
self
,
script_name
,
expected_file
,
expected_argv0
):
exit_code
,
data
=
_run_python
(
script_name
)
# if verbose:
# print "Output from test script %r:" % script_name
# print data
self
.
assertEqual
(
exit_code
,
0
)
printed_file
=
'__file__==%r'
%
expected_file
printed_argv0
=
'sys.argv[0]==%r'
%
expected_argv0
self
.
assert_
(
printed_file
in
data
)
self
.
assert_
(
printed_argv0
in
data
)
def
test_basic_script
(
self
):
with
temp_dir
()
as
script_dir
:
script_name
=
_make_test_script
(
script_dir
,
"script"
)
self
.
_check_script
(
script_name
,
script_name
,
script_name
)
def
test_script_compiled
(
self
):
with
temp_dir
()
as
script_dir
:
script_name
=
_make_test_script
(
script_dir
,
"script"
)
compiled_name
=
_compile_test_script
(
script_name
)
os
.
remove
(
script_name
)
self
.
_check_script
(
compiled_name
,
compiled_name
,
compiled_name
)
def
test_directory
(
self
):
with
temp_dir
()
as
script_dir
:
script_name
=
_make_test_script
(
script_dir
,
"__main__"
)
self
.
_check_script
(
script_dir
,
script_name
,
script_dir
)
def
test_directory_compiled
(
self
):
with
temp_dir
()
as
script_dir
:
script_name
=
_make_test_script
(
script_dir
,
"__main__"
)
compiled_name
=
_compile_test_script
(
script_name
)
os
.
remove
(
script_name
)
self
.
_check_script
(
script_dir
,
compiled_name
,
script_dir
)
def
test_zipfile
(
self
):
with
temp_dir
()
as
script_dir
:
script_name
=
_make_test_script
(
script_dir
,
"__main__"
)
zip_name
=
_make_test_zip
(
script_dir
,
"test_zip"
,
script_name
)
self
.
_check_script
(
zip_name
,
None
,
zip_name
)
def
test_zipfile_compiled
(
self
):
with
temp_dir
()
as
script_dir
:
script_name
=
_make_test_script
(
script_dir
,
"__main__"
)
compiled_name
=
_compile_test_script
(
script_name
)
zip_name
=
_make_test_zip
(
script_dir
,
"test_zip"
,
compiled_name
)
self
.
_check_script
(
zip_name
,
None
,
zip_name
)
def
test_main
():
test
.
test_support
.
run_unittest
(
CmdLineTest
)
test
.
test_support
.
reap_children
()
if
__name__
==
"__main__"
:
test_main
()
Misc/NEWS
View file @
327a39b0
...
...
@@ -12,6 +12,10 @@ What's New in Python 2.6 alpha 1?
Core and builtins
-----------------
- Patch #1739468: Directories and zipfiles containing a __main__.py file can
now be directly executed by passing their name to the interpreter. The
directory/zipfile is automatically inserted as the first entry in sys.path.
- Issue #1265: Fix a problem with sys.settrace, if the tracing function uses a
generator expression when at the same time the executed code is closing a
paused generator.
...
...
Modules/main.c
View file @
327a39b0
...
...
@@ -141,7 +141,7 @@ static void RunStartupFile(PyCompilerFlags *cf)
}
static
int
RunModule
(
char
*
module
)
static
int
RunModule
(
char
*
module
,
int
set_argv0
)
{
PyObject
*
runpy
,
*
runmodule
,
*
runargs
,
*
result
;
runpy
=
PyImport_ImportModule
(
"runpy"
);
...
...
@@ -155,7 +155,7 @@ static int RunModule(char *module)
Py_DECREF
(
runpy
);
return
-
1
;
}
runargs
=
Py_BuildValue
(
"(s
)"
,
module
);
runargs
=
Py_BuildValue
(
"(s
i)"
,
module
,
set_argv0
);
if
(
runargs
==
NULL
)
{
fprintf
(
stderr
,
"Could not create arguments for runpy._run_module_as_main
\n
"
);
...
...
@@ -177,6 +177,35 @@ static int RunModule(char *module)
return
0
;
}
static
int
RunMainFromImporter
(
char
*
filename
)
{
PyObject
*
argv0
=
NULL
,
*
importer
=
NULL
;
if
(
(
argv0
=
PyString_FromString
(
filename
))
&&
(
importer
=
PyImport_GetImporter
(
argv0
))
&&
(
importer
->
ob_type
!=
&
PyNullImporter_Type
))
{
/* argv0 is usable as an import source, so
put it in sys.path[0] and import __main__ */
PyObject
*
sys_path
=
NULL
;
if
(
(
sys_path
=
PySys_GetObject
(
"path"
))
&&
!
PyList_SetItem
(
sys_path
,
0
,
argv0
)
)
{
Py_INCREF
(
argv0
);
Py_CLEAR
(
importer
);
sys_path
=
NULL
;
return
RunModule
(
"__main__"
,
0
)
!=
0
;
}
}
PyErr_Clear
();
Py_CLEAR
(
argv0
);
Py_CLEAR
(
importer
);
return
-
1
;
}
/* Wait until threading._shutdown completes, provided
the threading module was imported in the first place.
The shutdown routine will wait until all non-daemon
...
...
@@ -388,39 +417,6 @@ Py_Main(int argc, char **argv)
#else
filename
=
argv
[
_PyOS_optind
];
#endif
if
(
filename
!=
NULL
)
{
if
((
fp
=
fopen
(
filename
,
"r"
))
==
NULL
)
{
#ifdef HAVE_STRERROR
fprintf
(
stderr
,
"%s: can't open file '%s': [Errno %d] %s
\n
"
,
argv
[
0
],
filename
,
errno
,
strerror
(
errno
));
#else
fprintf
(
stderr
,
"%s: can't open file '%s': Errno %d
\n
"
,
argv
[
0
],
filename
,
errno
);
#endif
return
2
;
}
else
if
(
skipfirstline
)
{
int
ch
;
/* Push back first newline so line numbers
remain the same */
while
((
ch
=
getc
(
fp
))
!=
EOF
)
{
if
(
ch
==
'\n'
)
{
(
void
)
ungetc
(
ch
,
fp
);
break
;
}
}
}
{
/* XXX: does this work on Win/Win64? (see posix_fstat) */
struct
stat
sb
;
if
(
fstat
(
fileno
(
fp
),
&
sb
)
==
0
&&
S_ISDIR
(
sb
.
st_mode
))
{
fprintf
(
stderr
,
"%s: '%s' is a directory, cannot continue
\n
"
,
argv
[
0
],
filename
);
fclose
(
fp
);
return
1
;
}
}
}
}
stdin_is_interactive
=
Py_FdIsInteractive
(
stdin
,
(
char
*
)
0
);
...
...
@@ -515,19 +511,63 @@ Py_Main(int argc, char **argv)
sts
=
PyRun_SimpleStringFlags
(
command
,
&
cf
)
!=
0
;
free
(
command
);
}
else
if
(
module
)
{
sts
=
RunModule
(
module
);
sts
=
RunModule
(
module
,
1
);
free
(
module
);
}
else
{
if
(
filename
==
NULL
&&
stdin_is_interactive
)
{
Py_InspectFlag
=
0
;
/* do exit on SystemExit */
RunStartupFile
(
&
cf
);
}
/* XXX */
sts
=
PyRun_AnyFileExFlags
(
fp
,
filename
==
NULL
?
"<stdin>"
:
filename
,
filename
!=
NULL
,
&
cf
)
!=
0
;
sts
=
-
1
;
/* keep track of whether we've already run __main__ */
if
(
filename
!=
NULL
)
{
sts
=
RunMainFromImporter
(
filename
);
}
if
(
sts
==-
1
&&
filename
!=
NULL
)
{
if
((
fp
=
fopen
(
filename
,
"r"
))
==
NULL
)
{
#ifdef HAVE_STRERROR
fprintf
(
stderr
,
"%s: can't open file '%s': [Errno %d] %s
\n
"
,
argv
[
0
],
filename
,
errno
,
strerror
(
errno
));
#else
fprintf
(
stderr
,
"%s: can't open file '%s': Errno %d
\n
"
,
argv
[
0
],
filename
,
errno
);
#endif
return
2
;
}
else
if
(
skipfirstline
)
{
int
ch
;
/* Push back first newline so line numbers
remain the same */
while
((
ch
=
getc
(
fp
))
!=
EOF
)
{
if
(
ch
==
'\n'
)
{
(
void
)
ungetc
(
ch
,
fp
);
break
;
}
}
}
{
/* XXX: does this work on Win/Win64? (see posix_fstat) */
struct
stat
sb
;
if
(
fstat
(
fileno
(
fp
),
&
sb
)
==
0
&&
S_ISDIR
(
sb
.
st_mode
))
{
fprintf
(
stderr
,
"%s: '%s' is a directory, cannot continue
\n
"
,
argv
[
0
],
filename
);
return
1
;
}
}
}
if
(
sts
==-
1
)
{
sts
=
PyRun_AnyFileExFlags
(
fp
,
filename
==
NULL
?
"<stdin>"
:
filename
,
filename
!=
NULL
,
&
cf
)
!=
0
;
}
}
/* Check this environment variable at the end, to give programs the
...
...
Python/import.c
View file @
327a39b0
...
...
@@ -104,7 +104,6 @@ static const struct filedescr _PyImport_StandardFiletab[] = {
};
#endif
static
PyTypeObject
NullImporterType
;
/* Forward reference */
/* Initialize things */
...
...
@@ -167,7 +166,7 @@ _PyImportHooks_Init(void)
/* adding sys.path_hooks and sys.path_importer_cache, setting up
zipimport */
if
(
PyType_Ready
(
&
NullImporter
Type
)
<
0
)
if
(
PyType_Ready
(
&
PyNullImporter_
Type
)
<
0
)
goto
error
;
if
(
Py_VerboseFlag
)
...
...
@@ -1088,7 +1087,7 @@ get_path_importer(PyObject *path_importer_cache, PyObject *path_hooks,
}
if
(
importer
==
NULL
)
{
importer
=
PyObject_CallFunctionObjArgs
(
(
PyObject
*
)
&
NullImporter
Type
,
p
,
NULL
(
PyObject
*
)
&
PyNullImporter_
Type
,
p
,
NULL
);
if
(
importer
==
NULL
)
{
if
(
PyErr_ExceptionMatches
(
PyExc_ImportError
))
{
...
...
@@ -1106,6 +1105,20 @@ get_path_importer(PyObject *path_importer_cache, PyObject *path_hooks,
return
importer
;
}
PyAPI_FUNC
(
PyObject
*
)
PyImport_GetImporter
(
PyObject
*
path
)
{
PyObject
*
importer
=
NULL
,
*
path_importer_cache
=
NULL
,
*
path_hooks
=
NULL
;
if
((
path_importer_cache
=
PySys_GetObject
(
"path_importer_cache"
)))
{
if
((
path_hooks
=
PySys_GetObject
(
"path_hooks"
)))
{
importer
=
get_path_importer
(
path_importer_cache
,
path_hooks
,
path
);
}
}
Py_XINCREF
(
importer
);
/* get_path_importer returns a borrowed reference */
return
importer
;
}
/* Search the path (default sys.path) for a module. Return the
corresponding filedescr struct, and (via return arguments) the
pathname and an open file. Return NULL if the module is not found. */
...
...
@@ -3049,7 +3062,7 @@ static PyMethodDef NullImporter_methods[] = {
};
static
PyTypeObject
NullImporter
Type
=
{
PyTypeObject
PyNullImporter_
Type
=
{
PyVarObject_HEAD_INIT
(
NULL
,
0
)
"imp.NullImporter"
,
/*tp_name*/
sizeof
(
NullImporter
),
/*tp_basicsize*/
...
...
@@ -3096,7 +3109,7 @@ initimp(void)
{
PyObject
*
m
,
*
d
;
if
(
PyType_Ready
(
&
NullImporter
Type
)
<
0
)
if
(
PyType_Ready
(
&
PyNullImporter_
Type
)
<
0
)
goto
failure
;
m
=
Py_InitModule4
(
"imp"
,
imp_methods
,
doc_imp
,
...
...
@@ -3118,8 +3131,8 @@ initimp(void)
if
(
setint
(
d
,
"PY_CODERESOURCE"
,
PY_CODERESOURCE
)
<
0
)
goto
failure
;
if
(
setint
(
d
,
"IMP_HOOK"
,
IMP_HOOK
)
<
0
)
goto
failure
;
Py_INCREF
(
&
NullImporter
Type
);
PyModule_AddObject
(
m
,
"NullImporter"
,
(
PyObject
*
)
&
NullImporter
Type
);
Py_INCREF
(
&
PyNullImporter_
Type
);
PyModule_AddObject
(
m
,
"NullImporter"
,
(
PyObject
*
)
&
PyNullImporter_
Type
);
failure:
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment