Commit a8c0f8e4 authored by Stefan Behnel's avatar Stefan Behnel

merge

parents c13aff5d 9f13ae43
# cython: language_level = 3
# cython: language_level = 3, py2_import=True
#
# Pyrex - Code output module
#
......
......@@ -1735,20 +1735,33 @@ class BackquoteNode(ExprNode):
code.put_gotref(self.py_result())
class ImportNode(ExprNode):
# Used as part of import statement implementation.
# 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
# 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
subexprs = ['module_name', 'name_list']
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 = self.module_name.coerce_to_pyobject(env)
if self.name_list:
......@@ -1765,10 +1778,11 @@ class ImportNode(ExprNode):
else:
name_list_code = "0"
code.putln(
"%s = __Pyx_Import(%s, %s); %s" % (
"%s = __Pyx_Import(%s, %s, %d); %s" % (
self.result(),
self.module_name.py_result(),
name_list_code,
self.level,
code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.py_result())
......@@ -7659,10 +7673,10 @@ static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
import_utility_code = UtilityCode(
proto = """
static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level); /*proto*/
""",
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 *empty_list = 0;
PyObject *module = 0;
......@@ -7686,8 +7700,23 @@ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
empty_dict = PyDict_New();
if (!empty_dict)
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,
name, global_dict, empty_dict, list, NULL);
#endif
bad:
Py_XDECREF(empty_list);
Py_XDECREF(py_import);
......
# cython: language_level=3
# cython: language_level=3, py2_import=True
#
# Cython Scanner - Lexical Definitions
#
......
......@@ -90,6 +90,7 @@ directive_defaults = {
'autotestdict.all': False,
'language_level': 2,
'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.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
#
......@@ -1216,6 +1216,7 @@ def p_import_statement(s):
rhs = ExprNodes.ImportNode(pos,
module_name = ExprNodes.IdentifierStringNode(
pos, value = dotted_name),
level = None,
name_list = name_list))
stats.append(stat)
return Nodes.StatListNode(pos, stats = stats)
......@@ -1224,13 +1225,31 @@ def p_from_import_statement(s, first_statement = 0):
# s.sy == 'from'
pos = s.position()
s.next()
(dotted_name_pos, _, dotted_name, _) = \
p_dotted_name(s, as_allowed = 0)
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, _) = \
p_dotted_name(s, as_allowed = 0)
if s.sy in ('import', 'cimport'):
kind = s.sy
s.next()
else:
s.error("Expected 'import' or 'cimport'")
is_cimport = kind == 'cimport'
is_parenthesized = False
if s.sy == '*':
......@@ -1252,6 +1271,8 @@ def p_from_import_statement(s, first_statement = 0):
if dotted_name == '__future__':
if not first_statement:
s.error("from __future__ imports must occur at the beginning of the file")
elif level is not None:
s.error("invalid syntax")
else:
for (name_pos, name, as_name, kind) in imported_names:
if name == "braces":
......@@ -1285,6 +1306,7 @@ def p_from_import_statement(s, first_statement = 0):
return Nodes.FromImportStatNode(pos,
module = ExprNodes.ImportNode(dotted_name_pos,
module_name = ExprNodes.IdentifierStringNode(pos, value = dotted_name),
level = level,
name_list = import_list),
items = items)
......
# cython: infer_types=True, language_level=3
# cython: infer_types=True, language_level=3, py2_import=True
#
# Cython Scanner
#
......
......@@ -15,7 +15,7 @@ with C data types.
Cython is Python: Almost any piece of Python code is also valid Cython code.
(There are a few :ref:`cython-limitations`, but this approximation will
serve for now.) The Cython compiler will convert it into C code which makes
equivalent calls to the Python/C API.
equivalent calls to the Python/C API.
But Cython is much more than that, because parameters and variables can be
declared to have C data types. Code which manipulates Python values and C
......@@ -48,7 +48,7 @@ information see :ref:`compilation`). Your :file:`setup.py` should look like::
setup(
cmdclass = {'build_ext': build_ext},
ext_modules = [Extension("helloworld", ["helloworld.pyx"])]
)
)
To use this to build your Cython file use the commandline options:
......@@ -95,7 +95,7 @@ Fibonacci Fun
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
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
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:
......@@ -124,9 +124,9 @@ Here's a small example showing some of what can be done. It's a routine for
finding prime numbers. You tell it how many primes you want, and it returns
them as a Python list.
:file:`primes.pyx`:
:file:`primes.pyx`:
.. literalinclude:: ../examples/tutorial/primes/primes.pyx
.. literalinclude:: ../../examples/tutorial/primes/primes.pyx
:linenos:
You'll see that it starts out just like a normal Python function definition,
......@@ -161,11 +161,11 @@ which we can try out in the interactive interpreter as follows::
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
See, it works! And if you're curious about how much work Cython has saved you,
take a look at the C code generated for this module.
take a look at the C code generated for this module.
Language Details
================
For more about the Cython language, see :ref:`language-basics`.
For more about the Cython language, see :ref:`language-basics`.
To dive right in to using Cython in a numerical computation context, see :ref:`numpy_tutorial`.
......@@ -93,6 +93,8 @@ VER_DEP_MODULES = {
]),
(2,5) : (operator.lt, lambda x: x in ['run.any',
'run.all',
'run.relativeimport_T542',
'run.relativeimport_star_T542',
]),
(2,6) : (operator.lt, lambda x: x in ['run.print_function',
'run.cython3',
......
......@@ -4,4 +4,12 @@ def f():
from spam import eggs
from spam.morespam import bacon, eggs, ham
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():
cdef type t
from sys import maxunicode
print maxunicode == sys.maxunicode
print(maxunicode == sys.maxunicode)
from types import ModuleType as t
print t is types.ModuleType
print(t is types.ModuleType)
try:
from sys import version_info as maxunicode
except TypeError, e:
print e
print(e)
try:
from sys import maxunicode as t
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