Commit 02d30c6d authored by Stefan Behnel's avatar Stefan Behnel

merge

parents 4f3af12a 001ed0f1
# cython: language_level = 3 # cython: language_level = 3, py2_import=True
# #
# Pyrex - Code output module # Pyrex - Code output module
# #
......
...@@ -1735,20 +1735,33 @@ class BackquoteNode(ExprNode): ...@@ -1735,20 +1735,33 @@ class BackquoteNode(ExprNode):
code.put_gotref(self.py_result()) code.put_gotref(self.py_result())
class ImportNode(ExprNode): class ImportNode(ExprNode):
# Used as part of import statement implementation. # Used as part of import statement implementation.
# Implements result = # Implements result =
# __import__(module_name, globals(), None, name_list) # __import__(module_name, globals(), None, name_list, level)
# #
# module_name StringNode dotted name of module # module_name StringNode dotted name of module. Empty module
# name means importing the parent package accourding
# to level
# name_list ListNode or None list of names to be imported # name_list ListNode or None list of names to be imported
# level int relative import level:
# -1: attempt both relative import and absolute import;
# 0: absolute import;
# >0: the number of parent directories to search
# relative to the current module.
# None: decide the level according to language level and
# directives
type = py_object_type type = py_object_type
subexprs = ['module_name', 'name_list'] subexprs = ['module_name', 'name_list']
def analyse_types(self, env): def analyse_types(self, env):
if self.level is None:
if env.directives['language_level'] < 3 or env.directives['py2_import']:
self.level = -1
else:
self.level = 0
self.module_name.analyse_types(env) self.module_name.analyse_types(env)
self.module_name = self.module_name.coerce_to_pyobject(env) self.module_name = self.module_name.coerce_to_pyobject(env)
if self.name_list: if self.name_list:
...@@ -1765,10 +1778,11 @@ class ImportNode(ExprNode): ...@@ -1765,10 +1778,11 @@ class ImportNode(ExprNode):
else: else:
name_list_code = "0" name_list_code = "0"
code.putln( code.putln(
"%s = __Pyx_Import(%s, %s); %s" % ( "%s = __Pyx_Import(%s, %s, %d); %s" % (
self.result(), self.result(),
self.module_name.py_result(), self.module_name.py_result(),
name_list_code, name_list_code,
self.level,
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.py_result()) code.put_gotref(self.py_result())
...@@ -7659,10 +7673,10 @@ static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) { ...@@ -7659,10 +7673,10 @@ static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
import_utility_code = UtilityCode( import_utility_code = UtilityCode(
proto = """ proto = """
static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level); /*proto*/
""", """,
impl = """ impl = """
static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) { static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level) {
PyObject *py_import = 0; PyObject *py_import = 0;
PyObject *empty_list = 0; PyObject *empty_list = 0;
PyObject *module = 0; PyObject *module = 0;
...@@ -7686,8 +7700,23 @@ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) { ...@@ -7686,8 +7700,23 @@ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
empty_dict = PyDict_New(); empty_dict = PyDict_New();
if (!empty_dict) if (!empty_dict)
goto bad; goto bad;
#if PY_VERSION_HEX >= 0x02050000
{
PyObject *py_level = PyInt_FromLong(level);
if (!py_level)
goto bad;
module = PyObject_CallFunctionObjArgs(py_import,
name, global_dict, empty_dict, list, py_level, NULL);
Py_DECREF(py_level);
}
#else
if (level>0) {
PyErr_SetString(PyExc_RuntimeError, "Relative import is not supported for Python <=2.4.");
goto bad;
}
module = PyObject_CallFunctionObjArgs(py_import, module = PyObject_CallFunctionObjArgs(py_import,
name, global_dict, empty_dict, list, NULL); name, global_dict, empty_dict, list, NULL);
#endif
bad: bad:
Py_XDECREF(empty_list); Py_XDECREF(empty_list);
Py_XDECREF(py_import); Py_XDECREF(py_import);
......
# cython: language_level=3 # cython: language_level=3, py2_import=True
# #
# Cython Scanner - Lexical Definitions # Cython Scanner - Lexical Definitions
# #
......
...@@ -90,6 +90,7 @@ directive_defaults = { ...@@ -90,6 +90,7 @@ directive_defaults = {
'autotestdict.all': False, 'autotestdict.all': False,
'language_level': 2, 'language_level': 2,
'fast_getattr': False, # Undocumented until we come up with a better way to handle this everywhere. 'fast_getattr': False, # Undocumented until we come up with a better way to handle this everywhere.
'py2_import': False, # For backward compatibility of Cython's source code
'warn': None, 'warn': None,
'warn.undeclared': False, 'warn.undeclared': False,
......
# cython: auto_cpdef=True, infer_types=True, language_level=3 # cython: auto_cpdef=True, infer_types=True, language_level=3, py2_import=True
# #
# Pyrex Parser # Pyrex Parser
# #
...@@ -1216,6 +1216,7 @@ def p_import_statement(s): ...@@ -1216,6 +1216,7 @@ def p_import_statement(s):
rhs = ExprNodes.ImportNode(pos, rhs = ExprNodes.ImportNode(pos,
module_name = ExprNodes.IdentifierStringNode( module_name = ExprNodes.IdentifierStringNode(
pos, value = dotted_name), pos, value = dotted_name),
level = None,
name_list = name_list)) name_list = name_list))
stats.append(stat) stats.append(stat)
return Nodes.StatListNode(pos, stats = stats) return Nodes.StatListNode(pos, stats = stats)
...@@ -1224,6 +1225,23 @@ def p_from_import_statement(s, first_statement = 0): ...@@ -1224,6 +1225,23 @@ def p_from_import_statement(s, first_statement = 0):
# s.sy == 'from' # s.sy == 'from'
pos = s.position() pos = s.position()
s.next() s.next()
if s.sy == '.':
# count relative import level
level = 0
while s.sy == '.':
level += 1
s.next()
if s.sy == 'cimport':
s.error("Relative cimport is not supported yet")
else:
level = None
if level is not None and s.sy == 'import':
# we are dealing with "from .. import foo, bar"
dotted_name_pos, dotted_name = s.position(), ''
elif level is not None and s.sy == 'cimport':
# "from .. cimport"
s.error("Relative cimport is not supported yet")
else:
(dotted_name_pos, _, dotted_name, _) = \ (dotted_name_pos, _, dotted_name, _) = \
p_dotted_name(s, as_allowed = 0) p_dotted_name(s, as_allowed = 0)
if s.sy in ('import', 'cimport'): if s.sy in ('import', 'cimport'):
...@@ -1231,6 +1249,7 @@ def p_from_import_statement(s, first_statement = 0): ...@@ -1231,6 +1249,7 @@ def p_from_import_statement(s, first_statement = 0):
s.next() s.next()
else: else:
s.error("Expected 'import' or 'cimport'") s.error("Expected 'import' or 'cimport'")
is_cimport = kind == 'cimport' is_cimport = kind == 'cimport'
is_parenthesized = False is_parenthesized = False
if s.sy == '*': if s.sy == '*':
...@@ -1252,6 +1271,8 @@ def p_from_import_statement(s, first_statement = 0): ...@@ -1252,6 +1271,8 @@ def p_from_import_statement(s, first_statement = 0):
if dotted_name == '__future__': if dotted_name == '__future__':
if not first_statement: if not first_statement:
s.error("from __future__ imports must occur at the beginning of the file") s.error("from __future__ imports must occur at the beginning of the file")
elif level is not None:
s.error("invalid syntax")
else: else:
for (name_pos, name, as_name, kind) in imported_names: for (name_pos, name, as_name, kind) in imported_names:
if name == "braces": if name == "braces":
...@@ -1285,6 +1306,7 @@ def p_from_import_statement(s, first_statement = 0): ...@@ -1285,6 +1306,7 @@ def p_from_import_statement(s, first_statement = 0):
return Nodes.FromImportStatNode(pos, return Nodes.FromImportStatNode(pos,
module = ExprNodes.ImportNode(dotted_name_pos, module = ExprNodes.ImportNode(dotted_name_pos,
module_name = ExprNodes.IdentifierStringNode(pos, value = dotted_name), module_name = ExprNodes.IdentifierStringNode(pos, value = dotted_name),
level = level,
name_list = import_list), name_list = import_list),
items = items) items = items)
......
# cython: infer_types=True, language_level=3 # cython: infer_types=True, language_level=3, py2_import=True
# #
# Cython Scanner # Cython Scanner
# #
......
...@@ -95,7 +95,7 @@ Fibonacci Fun ...@@ -95,7 +95,7 @@ Fibonacci Fun
From the official Python tutorial a simple fibonacci function is defined as: From the official Python tutorial a simple fibonacci function is defined as:
.. literalinclude:: ../examples/tutorial/fib1/fib.pyx .. literalinclude:: ../../examples/tutorial/fib1/fib.pyx
Now following the steps for the Hello World example we first rename the file Now following the steps for the Hello World example we first rename the file
to have a `.pyx` extension, lets say :file:`fib.pyx`, then we create the to have a `.pyx` extension, lets say :file:`fib.pyx`, then we create the
...@@ -103,7 +103,7 @@ to have a `.pyx` extension, lets say :file:`fib.pyx`, then we create the ...@@ -103,7 +103,7 @@ to have a `.pyx` extension, lets say :file:`fib.pyx`, then we create the
that you need to change is the name of the Cython filename, and the resulting that you need to change is the name of the Cython filename, and the resulting
module name, doing this we have: module name, doing this we have:
.. literalinclude:: ../examples/tutorial/fib1/setup.py .. literalinclude:: ../../examples/tutorial/fib1/setup.py
Build the extension with the same command used for the helloworld.pyx: Build the extension with the same command used for the helloworld.pyx:
...@@ -126,7 +126,7 @@ them as a Python list. ...@@ -126,7 +126,7 @@ them as a Python list.
:file:`primes.pyx`: :file:`primes.pyx`:
.. literalinclude:: ../examples/tutorial/primes/primes.pyx .. literalinclude:: ../../examples/tutorial/primes/primes.pyx
:linenos: :linenos:
You'll see that it starts out just like a normal Python function definition, You'll see that it starts out just like a normal Python function definition,
......
...@@ -93,6 +93,8 @@ VER_DEP_MODULES = { ...@@ -93,6 +93,8 @@ VER_DEP_MODULES = {
]), ]),
(2,5) : (operator.lt, lambda x: x in ['run.any', (2,5) : (operator.lt, lambda x: x in ['run.any',
'run.all', 'run.all',
'run.relativeimport_T542',
'run.relativeimport_star_T542',
]), ]),
(2,6) : (operator.lt, lambda x: x in ['run.print_function', (2,6) : (operator.lt, lambda x: x in ['run.print_function',
'run.cython3', 'run.cython3',
......
...@@ -4,4 +4,12 @@ def f(): ...@@ -4,4 +4,12 @@ def f():
from spam import eggs from spam import eggs
from spam.morespam import bacon, eggs, ham from spam.morespam import bacon, eggs, ham
from spam import eggs as ova from spam import eggs as ova
from . import spam
from ... import spam
from .. import spam, foo
from ... import spam, foobar
from .spam import foo
from ...spam import foo, bar
from ...spam.foo import bar
from ...spam.foo import foo, bar
from ...spam.foo import (foo, bar)
# mode: compile
from spam import *
from ...spam.foo import *
from . import *
from ... import *
...@@ -61,16 +61,16 @@ def typed_imports(): ...@@ -61,16 +61,16 @@ def typed_imports():
cdef type t cdef type t
from sys import maxunicode from sys import maxunicode
print maxunicode == sys.maxunicode print(maxunicode == sys.maxunicode)
from types import ModuleType as t from types import ModuleType as t
print t is types.ModuleType print(t is types.ModuleType)
try: try:
from sys import version_info as maxunicode from sys import version_info as maxunicode
except TypeError, e: except TypeError, e:
print e print(e)
try: try:
from sys import maxunicode as t from sys import maxunicode as t
except TypeError, e: except TypeError, e:
print e print(e)
# cython: language_level=3
import sys
# fool Python we are in distutils
if sys.version_info >= (3,):
__name__='distutils.cytest_relativeimport_T542'
else:
__name__=b'distutils.cytest_relativeimport_T542'
from distutils import cmd, core, version
from .core import *
def test_relative():
"""
>>> test_relative() == (cmd, core, 'distutils.version')
True
"""
from . import cmd, core
from . import (version, core)
from .version import __name__
return cmd, core, __name__
def test_absolute():
"""
>>> test_absolute()
Traceback (most recent call last):
...
ImportError: No module named debug
"""
import debug
return
__doc__ = """
>>> setup == core.setup
True
"""
from distutils import core, version
__name__='distutils.core.cytest_relativeimport_T542' # fool Python we are in distutils
from . import *
__doc__ = """
>>> core.setup == setup
True
"""
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment