Commit bbba7ca8 authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

merge

parents bd9d0283 a5e1aea2
......@@ -11,3 +11,5 @@ build/
*.orig
*.rej
*.dep
tags
import re
from Cython.Compiler.Visitor import CythonTransform
from Cython.Compiler.Nodes import DefNode, CFuncDefNode
from Cython.Compiler.Errors import CompileError
from Cython.Compiler.StringEncoding import EncodedString
from Cython.Compiler import Options
class EmbedSignature(CythonTransform):
SPECIAL_METHOD_RE = re.compile(r'__\w+__')
def __init__(self, context):
super(EmbedSignature, self).__init__(context)
self.denv = None # XXX
self.is_in_class = False
self.class_name = None
def _fmt_basic_c_type_modifiers(self, ctype):
longness = ctype.longness
modifiers = ''
if longness < 0:
modifiers = 'short '
elif longness > 0:
modifiers = 'long ' * longness
signed = ctype.signed
if signed == 0:
modifiers = 'unsigned ' + modifiers
elif signed == 2:
modifiers = 'signed ' + modifiers
return modifiers[:-1] # strip final space
def _fmt_arg_type(self, arg):
try:
base_type = arg.base_type
arg_type = base_type.name
except AttributeError:
return ''
if base_type.is_basic_c_type:
modifiers = self._fmt_basic_c_type_modifiers(base_type)
if modifiers:
arg_type = '%s %s' % (modifiers, arg_type)
return arg_type
def _fmt_arg_name(self, arg):
try:
return arg.declarator.name
except AttributeError:
return arg.declarator.base.name
def _fmt_arg_defv(self, arg):
if not arg.default:
return None
try:
denv = self.denv # XXX
ctval = arg.default.compile_time_value(self.denv)
return '%s' % ctval
except Exception:
try:
return arg.default.name # XXX
except AttributeError:
return '<???>'
def _fmt_arg(self, arg):
arg_type = self._fmt_arg_type(arg)
arg_name = self._fmt_arg_name(arg)
arg_defv = self._fmt_arg_defv(arg)
doc = arg_name
if arg_type:
doc = ('%s ' % arg_type) + doc
if arg_defv:
doc = doc + ('=%s' % arg_defv)
return doc
def _fmt_arglist(self, args,
npargs=0, pargs=None,
nkargs=0, kargs=None):
arglist = []
for arg in args:
arg_doc = self._fmt_arg(arg)
arglist.append(arg_doc)
if pargs:
arglist.insert(npargs, '*%s' % pargs.name)
elif nkargs:
arglist.insert(npargs, '*')
if kargs:
arglist.append('**%s' % kargs.name)
return arglist
def _fmt_ret_type(self, ret):
ret_type = ret.name
if ret_type is None:
return ''
modifiers = self._fmt_basic_c_type_modifiers(ret)
if modifiers:
ret_type = '%s %s' % (modifiers, ret_type)
return ret_type
def _fmt_signature(self, cls_name, func_name, args,
npargs=0, pargs=None,
nkargs=0, kargs=None,
return_type=None):
arglist = self._fmt_arglist(args,
npargs, pargs,
nkargs, kargs)
arglist_doc = ', '.join(arglist)
func_doc = '%s(%s)' % (func_name, arglist_doc)
if cls_name:
func_doc = '%s.%s' % (cls_name, func_doc)
if return_type:
ret_doc = self._fmt_ret_type(return_type)
if ret_doc:
func_doc = '%s -> %s' % (func_doc, ret_doc)
return func_doc
def _embed_signature(self, signature, node_doc):
if node_doc:
return signature + '\n' + node_doc
else:
return signature
def __call__(self, node):
if not Options.docstrings:
return node
else:
return super(EmbedSignature, self).__call__(node)
def visit_ClassDefNode(self, node):
oldincls = self.is_in_class
oldname = self.class_name
self.is_in_class = True
try:
# PyClassDefNode
self.class_name = node.name
except AttributeError:
# CClassDefNode
self.class_name = node.class_name
self.visitchildren(node)
self.is_in_class = oldincls
self.class_name = oldname
return node
def visit_FuncDefNode(self, node):
if not self.current_directives['embedsignature']:
return node
signature = None
if type(node) is DefNode: # def FOO(...):
special_method = (self.is_in_class and \
self.SPECIAL_METHOD_RE.match(node.name))
if not special_method:
nkargs = getattr(node, 'num_kwonly_args', 0)
npargs = len(node.args) - nkargs
signature = self._fmt_signature(
self.class_name, node.name, node.args,
npargs, node.star_arg,
nkargs, node.starstar_arg,
return_type=None)
elif type(node) is CFuncDefNode:
if node.overridable: # cpdef FOO(...):
signature = self._fmt_signature(
self.class_name, node.declarator.base.name,
node.declarator.args,
return_type=node.base_type)
else: # should not fall here ...
assert False
if signature:
new_doc = self._embed_signature(signature, node.doc)
node.doc = EncodedString(new_doc) # XXX
return node
This diff is collapsed.
......@@ -181,7 +181,8 @@ def init_builtins():
init_builtin_funcs()
init_builtin_types()
init_builtin_structs()
global list_type, tuple_type, dict_type, unicode_type
global list_type, tuple_type, dict_type, unicode_type, type_type
type_type = builtin_scope.lookup('type').type
list_type = builtin_scope.lookup('list').type
tuple_type = builtin_scope.lookup('tuple').type
dict_type = builtin_scope.lookup('dict').type
......
......@@ -36,7 +36,7 @@ Options:
-D, --no-docstrings Remove docstrings.
-a, --annotate Produce a colorized HTML version of the source.
--convert-range Convert for loops using range() function to for...from loops.
--line-directives Produce #line directives pointing to the .pyx source
--cplus Output a c++ rather than c file.
-X, --directive <name>=<value>[,<name=value,...] Overrides a compiler directive
"""
......@@ -114,6 +114,8 @@ def parse_command_line(args):
Options.annotate = True
elif option == "--convert-range":
Options.convert_range = True
elif option == "--line-directives":
options.emit_linenums = True
elif option in ("-X", "--directive"):
try:
options.pragma_overrides = Options.parse_option_list(pop_arg())
......
......@@ -161,7 +161,13 @@ class GlobalState(object):
# interned_nums
# cached_builtins
def __init__(self, rootwriter):
# directives set Temporary variable used to track
# the current set of directives in the code generation
# process.
directives = {}
def __init__(self, rootwriter, emit_linenums=False):
self.filename_table = {}
self.filename_list = []
self.input_file_contents = {}
......@@ -169,6 +175,7 @@ class GlobalState(object):
self.declared_cnames = {}
self.pystring_table_needed = False
self.in_utility_code_generation = False
self.emit_linenums = emit_linenums
def initwriters(self, rootwriter):
self.utilprotowriter = rootwriter.new_writer()
......@@ -379,6 +386,8 @@ class GlobalState(object):
writer.insert(self.utilprotowriter)
def put_utility_code_defs(self, writer):
if self.emit_linenums:
writer.write('\n#line 1 "cython_utility"\n')
writer.insert(self.utildefwriter)
......@@ -404,7 +413,7 @@ class CCodeWriter(object):
- marker: Not copied to insertion point
- filename_table, filename_list, input_file_contents: All codewriters
coming from the same root share the same instances simultaneously.
"""
"""
# f file output file
# buffer StringIOTree
......@@ -416,19 +425,21 @@ class CCodeWriter(object):
# generation (labels and temps state etc.)
# globalstate GlobalState contains state global for a C file (input file info,
# utility code, declared constants etc.)
def __init__(self, create_from=None, buffer=None, copy_formatting=False):
# emit_linenums boolean whether or not to write #line pragmas
def __init__(self, create_from=None, buffer=None, copy_formatting=False, emit_linenums=None):
if buffer is None: buffer = StringIOTree()
self.buffer = buffer
self.marker = None
self.last_marker_line = 0
self.source_desc = ""
self.funcstate = None
self.level = 0
self.bol = 1
if create_from is None:
# Root CCodeWriter
self.globalstate = GlobalState(self)
self.globalstate = GlobalState(self, emit_linenums=emit_linenums)
self.globalstate.initwriters(self)
# ^^^ need seperate step because this will reference self.globalstate
else:
......@@ -438,6 +449,10 @@ class CCodeWriter(object):
if copy_formatting:
self.level = create_from.level
self.bol = create_from.bol
if emit_linenums is None:
self.emit_linenums = self.globalstate.emit_linenums
else:
self.emit_linenums = emit_linenums
def create_new(self, create_from, buffer, copy_formatting):
# polymorphic constructor -- very slightly more versatile
......@@ -505,6 +520,8 @@ class CCodeWriter(object):
def putln(self, code = ""):
if self.marker and self.bol:
self.emit_marker()
if self.emit_linenums and self.last_marker_line != 0:
self.write('\n#line %s "%s"\n' % (self.last_marker_line, self.source_desc))
if code:
self.put(code)
self.write("\n");
......@@ -581,7 +598,8 @@ class CCodeWriter(object):
marker = u'"%s":%d\n%s\n' % (
source_desc.get_escaped_description(), line, u'\n'.join(lines))
self.marker = (line, marker)
if self.emit_linenums:
self.source_desc = source_desc.get_escaped_description()
def put_label(self, lbl):
if lbl in self.funcstate.labels_used:
......
This diff is collapsed.
......@@ -79,8 +79,9 @@ class Context:
from ParseTreeTransforms import WithTransform, NormalizeTree, PostParse, PxdPostParse
from ParseTreeTransforms import AnalyseDeclarationsTransform, AnalyseExpressionsTransform
from ParseTreeTransforms import CreateClosureClasses, MarkClosureVisitor, DecoratorTransform
from ParseTreeTransforms import ResolveOptions
from Optimize import FlattenInListTransform, SwitchTransform, OptimizeRefcounting
from ParseTreeTransforms import InterpretCompilerDirectives
from AutoDocTransforms import EmbedSignature
from Optimize import FlattenInListTransform, SwitchTransform, FinalOptimizePhase
from Buffer import IntroduceBufferAuxiliaryVars
from ModuleNode import check_c_classes
......@@ -95,7 +96,8 @@ class Context:
NormalizeTree(self),
PostParse(self),
_specific_post_parse,
ResolveOptions(self, self.pragma_overrides),
InterpretCompilerDirectives(self, self.pragma_overrides),
EmbedSignature(self),
FlattenInListTransform(),
WithTransform(self),
DecoratorTransform(self),
......@@ -104,7 +106,7 @@ class Context:
_check_c_classes,
AnalyseExpressionsTransform(self),
SwitchTransform(),
OptimizeRefcounting(self),
FinalOptimizePhase(self),
# SpecialFunctions(self),
# CreateClosureClasses(context),
]
......@@ -727,7 +729,8 @@ default_options = dict(
timestamps = None,
verbose = 0,
quiet = 0,
pragma_overrides = {}
pragma_overrides = {},
emit_linenums = False,
)
if sys.platform == "mac":
from Cython.Mac.MacSystem import c_compile, c_link, CCompilerError
......
......@@ -3,7 +3,6 @@
#
import os, time
from cStringIO import StringIO
from PyrexTypes import CPtrType
import Future
......@@ -41,8 +40,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
#
# scope The module scope.
# compilation_source A CompilationSource (see Main)
# directives Top-level compiler directives
child_attrs = ["body"]
directives = None
def analyse_declarations(self, env):
if Options.embed_pos_in_docstring:
......@@ -52,6 +53,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
env.doc.encoding = self.doc.encoding
else:
env.doc = self.doc
env.directives = self.directives
self.body.analyse_declarations(env)
def process_implementation(self, options, result):
......@@ -240,11 +242,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if Options.annotate or options.annotate:
code = Annotate.AnnotationCCodeWriter()
else:
code = Code.CCodeWriter()
code = Code.CCodeWriter(emit_linenums=options.emit_linenums)
h_code = code.insertion_point()
self.generate_module_preamble(env, modules, h_code)
code.globalstate.module_pos = self.pos
code.globalstate.directives = self.directives
code.putln("")
code.putln("/* Implementation of %s */" % env.qualified_name)
......@@ -872,7 +875,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
else:
code.put_init_var_to_py_none(entry, "p->%s")
entry = scope.lookup_here("__new__")
if entry:
if entry and entry.is_special:
if entry.trivial_signature:
cinit_args = "o, %s, NULL" % Naming.empty_tuple
else:
......@@ -1958,11 +1961,11 @@ builtin_module_name_utility_code = [
import_module_utility_code = [
"""
static PyObject *__Pyx_ImportModule(char *name); /*proto*/
static PyObject *__Pyx_ImportModule(const char *name); /*proto*/
""","""
#ifndef __PYX_HAVE_RT_ImportModule
#define __PYX_HAVE_RT_ImportModule
static PyObject *__Pyx_ImportModule(char *name) {
static PyObject *__Pyx_ImportModule(const char *name) {
PyObject *py_name = 0;
PyObject *py_module = 0;
......@@ -1987,29 +1990,32 @@ bad:
type_import_utility_code = [
"""
static PyTypeObject *__Pyx_ImportType(char *module_name, char *class_name, long size); /*proto*/
static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class_name, long size); /*proto*/
""","""
#ifndef __PYX_HAVE_RT_ImportType
#define __PYX_HAVE_RT_ImportType
static PyTypeObject *__Pyx_ImportType(char *module_name, char *class_name,
static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class_name,
long size)
{
PyObject *py_module = 0;
PyObject *result = 0;
PyObject *py_name = 0;
py_module = __Pyx_ImportModule(module_name);
if (!py_module)
goto bad;
#if PY_MAJOR_VERSION < 3
py_name = PyString_FromString(module_name);
py_name = PyString_FromString(class_name);
#else
py_name = PyUnicode_FromString(module_name);
py_name = PyUnicode_FromString(class_name);
#endif
if (!py_name)
goto bad;
py_module = __Pyx_ImportModule(module_name);
if (!py_module)
goto bad;
result = PyObject_GetAttrString(py_module, class_name);
result = PyObject_GetAttr(py_module, py_name);
Py_DECREF(py_name);
py_name = 0;
Py_DECREF(py_module);
py_module = 0;
if (!result)
goto bad;
if (!PyType_Check(result)) {
......@@ -2026,7 +2032,7 @@ static PyTypeObject *__Pyx_ImportType(char *module_name, char *class_name,
}
return (PyTypeObject *)result;
bad:
Py_XDECREF(py_name);
Py_XDECREF(py_module);
Py_XDECREF(result);
return 0;
}
......
......@@ -76,7 +76,6 @@ print_function_kwargs = pyrex_prefix + "print_kwargs"
cleanup_cname = pyrex_prefix + "module_cleanup"
pymoduledef_cname = pyrex_prefix + "moduledef"
optional_args_cname = pyrex_prefix + "optional_args"
no_opt_args = pyrex_prefix + "no_opt_args"
import_star = pyrex_prefix + "import_star"
import_star_set = pyrex_prefix + "import_star_set"
cur_scope_cname = pyrex_prefix + "cur_scope"
......
This diff is collapsed.
......@@ -56,9 +56,8 @@ class SwitchTransform(Visitor.VisitorTransform):
def visit_IfStatNode(self, node):
self.visitchildren(node)
if len(node.if_clauses) < 3:
return node
common_var = None
case_count = 0
cases = []
for if_clause in node.if_clauses:
var, conditions = self.extract_conditions(if_clause.condition)
......@@ -70,9 +69,12 @@ class SwitchTransform(Visitor.VisitorTransform):
return node
else:
common_var = var
case_count += len(conditions)
cases.append(Nodes.SwitchCaseNode(pos = if_clause.pos,
conditions = conditions,
body = if_clause.body))
if case_count < 2:
return node
common_var = unwrap_node(common_var)
return Nodes.SwitchStatNode(pos = node.pos,
......@@ -138,7 +140,15 @@ class FlattenInListTransform(Visitor.VisitorTransform):
return node
class OptimizeRefcounting(Visitor.CythonTransform):
class FinalOptimizePhase(Visitor.CythonTransform):
"""
This visitor handles several commuting optimizations, and is run
just before the C code generation phase.
The optimizations currently implemented in this class are:
- Eliminate None assignment and refcounting for first assignment.
- isinstance -> typecheck for cdef types
"""
def visit_SingleAssignmentNode(self, node):
if node.first:
lhs = node.lhs
......@@ -149,3 +159,16 @@ class OptimizeRefcounting(Visitor.CythonTransform):
# Set a flag in NameNode to skip the decref
lhs.skip_assignment_decref = True
return node
def visit_SimpleCallNode(self, node):
self.visitchildren(node)
if node.function.type.is_cfunction and isinstance(node.function, ExprNodes.NameNode):
if node.function.name == 'isinstance':
type_arg = node.args[1]
if type_arg.type.is_builtin_type and type_arg.type.name == 'type':
object_module = self.context.find_module('python_object')
node.function.entry = object_module.lookup('PyObject_TypeCheck')
node.function.type = node.function.entry.type
PyTypeObjectPtr = PyrexTypes.CPtrType(object_module.lookup('PyTypeObject').type)
node.args[1] = ExprNodes.CastNode(node.args[1], PyTypeObjectPtr)
return node
......@@ -56,11 +56,15 @@ c_line_in_traceback = 1
# Declare pragmas
option_types = {
'boundscheck' : bool
'boundscheck' : bool,
'nonecheck' : bool,
'embedsignature' : bool
}
option_defaults = {
'boundscheck' : True
'boundscheck' : True,
'nonecheck' : False,
'embedsignature' : False,
}
def parse_option_value(name, value):
......
......@@ -240,7 +240,7 @@ class PxdPostParse(CythonTransform):
else:
return node
class ResolveOptions(CythonTransform):
class InterpretCompilerDirectives(CythonTransform):
"""
After parsing, options can be stored in a number of places:
- #cython-comments at the top of the file (stored in ModuleNode)
......@@ -248,28 +248,38 @@ class ResolveOptions(CythonTransform):
- @cython.optionname decorators
- with cython.optionname: statements
This transform is responsible for annotating each node with an
"options" attribute linking it to a dict containing the exact
options that are in effect for that node. Any corresponding decorators
or with statements are removed in the process.
This transform is responsible for interpreting these various sources
and store the option in two ways:
- Set the directives attribute of the ModuleNode for global directives.
- Use a CompilerDirectivesNode to override directives for a subtree.
(The first one is primarily to not have to modify with the tree
structure, so that ModuleNode stay on top.)
The directives are stored in dictionaries from name to value in effect.
Each such dictionary is always filled in for all possible directives,
using default values where no value is given by the user.
The available directives are controlled in Options.py.
Note that we have to run this prior to analysis, and so some minor
duplication of functionality has to occur: We manually track cimports
to correctly intercept @cython... and with cython...
and which names the "cython" module may have been imported to.
"""
def __init__(self, context, compilation_option_overrides):
super(ResolveOptions, self).__init__(context)
super(InterpretCompilerDirectives, self).__init__(context)
self.compilation_option_overrides = compilation_option_overrides
self.cython_module_names = set()
self.option_names = {}
# Set up processing and handle the cython: comments.
def visit_ModuleNode(self, node):
options = copy.copy(Options.option_defaults)
options.update(node.option_comments)
options.update(self.compilation_option_overrides)
self.options = options
node.options = options
node.directives = options
self.visitchildren(node)
return node
......@@ -299,7 +309,6 @@ class ResolveOptions(CythonTransform):
return node
def visit_Node(self, node):
node.options = self.options
self.visitchildren(node)
return node
......@@ -331,14 +340,17 @@ class ResolveOptions(CythonTransform):
return None
def visit_with_options(self, node, options):
def visit_with_options(self, body, options):
oldoptions = self.options
newoptions = copy.copy(oldoptions)
newoptions.update(options)
self.options = newoptions
node = self.visit_Node(node)
assert isinstance(body, StatListNode), body
retbody = self.visit_Node(body)
directive = CompilerDirectivesNode(pos=retbody.pos, body=retbody,
directives=newoptions)
self.options = oldoptions
return node
return directive
# Handle decorators
def visit_DefNode(self, node):
......@@ -361,7 +373,8 @@ class ResolveOptions(CythonTransform):
for option in options:
name, value = option
optdict[name] = value
return self.visit_with_options(node, optdict)
body = StatListNode(node.pos, stats=[node])
return self.visit_with_options(body, optdict)
else:
return self.visit_Node(node)
......@@ -372,8 +385,7 @@ class ResolveOptions(CythonTransform):
if node.target is not None:
raise PostParseError(node.pos, "Compiler option with statements cannot contain 'as'")
name, value = option
self.visit_with_options(node.body, {name:value})
return node.body.stats
return self.visit_with_options(node.body, {name:value})
else:
return self.visit_Node(node)
......@@ -429,7 +441,7 @@ class WithTransform(CythonTransform):
u'BODY' : node.body,
u'TARGET' : node.target,
u'EXCINFO' : excinfo_namenode
}, pos = node.pos)
}, pos=node.pos)
# Set except excinfo target to EXCINFO
result.stats[4].body.stats[0].except_clauses[0].excinfo_target = excinfo_target
else:
......@@ -437,7 +449,7 @@ class WithTransform(CythonTransform):
u'EXPR' : node.manager,
u'BODY' : node.body,
u'EXCINFO' : excinfo_namenode
}, pos = node.pos)
}, pos=node.pos)
# Set except excinfo target to EXCINFO
result.stats[4].body.stats[0].except_clauses[0].excinfo_target = excinfo_target
......
......@@ -229,6 +229,8 @@ def p_typecast(s):
pos = s.position()
s.next()
base_type = p_c_base_type(s)
if base_type.name is None:
s.error("Unknown type")
declarator = p_c_declarator(s, empty = 1)
if s.sy == '?':
s.next()
......
......@@ -197,20 +197,24 @@ class BufferType(BaseType):
# lookups to the base type. ANYTHING NOT DEFINED
# HERE IS DELEGATED!
# dtype PyrexType
# ndim int
# mode str
# is_buffer boolean
# writable boolean
# dtype PyrexType
# ndim int
# mode str
# negative_indices bool
# cast bool
# is_buffer bool
# writable bool
is_buffer = 1
writable = True
def __init__(self, base, dtype, ndim, mode):
def __init__(self, base, dtype, ndim, mode, negative_indices, cast):
self.base = base
self.dtype = dtype
self.ndim = ndim
self.buffer_ptr_type = CPtrType(dtype)
self.mode = mode
self.negative_indices = negative_indices
self.cast = cast
def as_argument_type(self):
return self
......@@ -732,7 +736,7 @@ class CFuncType(CType):
return 1
if not other_type.is_cfunction:
return 0
if not self.is_overridable and other_type.is_overridable:
if self.is_overridable != other_type.is_overridable:
return 0
nargs = len(self.args)
if nargs != len(other_type.args):
......@@ -846,6 +850,8 @@ class CFuncType(CType):
for arg in self.args[:len(self.args)-self.optional_arg_count]:
arg_decl_list.append(
arg.type.declaration_code("", for_display, pyrex = pyrex))
if self.is_overridable:
arg_decl_list.append("int %s" % Naming.skip_dispatch_cname)
if self.optional_arg_count:
arg_decl_list.append(self.op_arg_struct.declaration_code(Naming.optional_args_cname))
if self.has_varargs:
......@@ -1184,11 +1190,16 @@ def widest_numeric_type(type1, type2):
# Given two numeric types, return the narrowest type
# encompassing both of them.
if type1.is_enum and type2.is_enum:
widest_type = c_int_type
elif type2.rank > type1.rank:
widest_type = type2
return c_int_type
elif type1 is type2:
return type1
elif (type1.signed and type2.signed) or (not type1.signed and not type2.signed):
if type2.rank > type1.rank:
return type2
else:
return type1
else:
widest_type = type1
return sign_and_rank_to_type[min(type1.signed, type2.signed), max(type1.rank, type2.rank)]
return widest_type
def simple_c_type(signed, longness, name):
......
......@@ -6,8 +6,7 @@ import re
from Cython import Utils
from Errors import warning, error, InternalError
from StringEncoding import EncodedString
import Options
import Naming
import Options, Naming
import PyrexTypes
from PyrexTypes import py_object_type
import TypeSlots
......@@ -138,6 +137,7 @@ class Entry:
utility_code = None
is_overridable = 0
buffer_aux = None
prev_entry = None
def __init__(self, name, cname, type, pos = None, init = None):
self.name = name
......@@ -178,6 +178,8 @@ class Scope:
# Python strings in this scope
# control_flow ControlFlow Used for keeping track of environment state
# nogil boolean In a nogil section
# directives dict Helper variable for the recursive
# analysis, contains directive values.
is_py_class_scope = 0
is_c_class_scope = 0
......@@ -185,6 +187,7 @@ class Scope:
scope_prefix = ""
in_cinclude = 0
nogil = 0
directives = {}
temp_prefix = Naming.pyrex_prefix
......@@ -277,7 +280,7 @@ class Scope:
if name and dict.has_key(name):
if visibility == 'extern':
warning(pos, "'%s' redeclared " % name, 0)
else:
elif visibility != 'ignore':
error(pos, "'%s' redeclared " % name)
entry = Entry(name, cname, type, pos = pos)
entry.in_cinclude = self.in_cinclude
......@@ -707,7 +710,7 @@ class BuiltinScope(Scope):
entry = self.declare_type(name, type, None, visibility='extern')
var_entry = Entry(name = entry.name,
type = py_object_type,
type = self.lookup('type').type, # make sure "type" is the first type declared...
pos = entry.pos,
cname = "((PyObject*)%s)" % entry.type.typeptr_cname)
var_entry.is_variable = 1
......@@ -1106,8 +1109,9 @@ class ModuleScope(Scope):
# variable entry attached to it. For the variable entry,
# we use a read-only C global variable whose name is an
# expression that refers to the type object.
import Builtin
var_entry = Entry(name = entry.name,
type = py_object_type,
type = Builtin.type_type,
pos = entry.pos,
cname = "((PyObject*)%s)" % entry.type.typeptr_cname)
var_entry.is_variable = 1
......@@ -1411,22 +1415,8 @@ class CClassScope(ClassScope):
if type.same_c_signature_as(entry.type, as_cmethod = 1) and type.nogil == entry.type.nogil:
pass
elif type.compatible_signature_with(entry.type, as_cmethod = 1) and type.nogil == entry.type.nogil:
if type.optional_arg_count and not type.original_sig.optional_arg_count:
# Need to put a wrapper taking no optional arguments
# into the method table.
wrapper_func_cname = self.mangle(Naming.func_prefix, name) + Naming.no_opt_args
wrapper_func_name = name + Naming.no_opt_args
if entry.type.optional_arg_count:
old_entry = self.lookup_here(wrapper_func_name)
old_entry.func_cname = wrapper_func_cname
else:
entry.func_cname = wrapper_func_cname
entry.name = wrapper_func_name
entry = self.add_cfunction(name, type, pos, cname or name, visibility)
defining = 1
entry.type = type
# if type.narrower_c_signature_than(entry.type, as_cmethod = 1):
# entry.type = type
entry = self.add_cfunction(name, type, pos, cname or name, visibility='ignore')
defining = 1
else:
error(pos, "Signature not compatible with previous declaration")
error(entry.pos, "Previous declaration is here")
......@@ -1442,8 +1432,10 @@ class CClassScope(ClassScope):
def add_cfunction(self, name, type, pos, cname, visibility):
# Add a cfunction entry without giving it a func_cname.
prev_entry = self.lookup_here(name)
entry = ClassScope.add_cfunction(self, name, type, pos, cname, visibility)
entry.is_cmethod = 1
entry.prev_entry = prev_entry
return entry
def declare_property(self, name, doc, pos):
......
......@@ -16,12 +16,11 @@ class BasicVisitor(object):
self.dispatch_table = {}
def visit(self, obj):
pattern = "visit_%s"
cls = obj.__class__
mname = pattern % cls.__name__
m = self.dispatch_table.get(mname)
m = self.dispatch_table.get(cls.__name__)
if m is None:
# Must resolve, try entire hierarchy
pattern = "visit_%s"
mro = inspect.getmro(cls)
for cls in mro:
m = getattr(self, pattern % cls.__name__, None)
......@@ -33,7 +32,7 @@ class BasicVisitor(object):
print self.access_path[-1][0].pos
print self.access_path[-1][0].__dict__
raise RuntimeError("Visitor does not accept object: %s" % obj)
self.dispatch_table[mname] = m
self.dispatch_table[cls.__name__] = m
return m(obj)
class TreeVisitor(BasicVisitor):
......@@ -111,6 +110,7 @@ class TreeVisitor(BasicVisitor):
childretval = [self.visitchild(x, parent, attr, idx) for idx, x in enumerate(child)]
else:
childretval = self.visitchild(child, parent, attr, None)
assert not isinstance(childretval, list), 'Cannot insert list here: %s in %r' % (attr, parent)
result[attr] = childretval
return result
......@@ -163,11 +163,26 @@ class CythonTransform(VisitorTransform):
super(CythonTransform, self).__init__()
self.context = context
def __call__(self, node):
import ModuleNode
if isinstance(node, ModuleNode.ModuleNode):
self.current_directives = node.directives
return super(CythonTransform, self).__call__(node)
def visit_CompilerDirectivesNode(self, node):
old = self.current_directives
self.current_directives = node.directives
self.visitchildren(node)
self.current_directives = old
return node
def visit_Node(self, node):
self.visitchildren(node)
return node
# Utils
def ensure_statlist(node):
if not isinstance(node, Nodes.StatListNode):
......
cimport python_buffer as pybuf
cdef extern from "Python.h":
ctypedef int Py_intptr_t
......@@ -19,7 +21,11 @@ cdef extern from "numpy/arrayobject.h":
NPY_NTYPES,
NPY_NOTYPE,
NPY_CHAR,
NPY_USERDEF
NPY_USERDEF,
NPY_C_CONTIGUOUS,
NPY_F_CONTIGUOUS
ctypedef class numpy.ndarray [object PyArrayObject]:
cdef __cythonbufferdefaults__ = {"mode": "strided"}
......@@ -29,19 +35,27 @@ cdef extern from "numpy/arrayobject.h":
int ndim "nd"
npy_intp *shape "dimensions"
npy_intp *strides
int flags
# Note: This syntax (function definition in pxd files) is an
# experimental exception made for __getbuffer__ and __releasebuffer__
# -- the details of this may change.
def __getbuffer__(ndarray self, Py_buffer* info, int flags):
# This implementation of getbuffer is geared towards Cython
# requirements, and does not yet fullfill the PEP (specifically,
# Cython always requests and we always provide strided access,
# so the flags are not even checked).
# requirements, and does not yet fullfill the PEP.
# In particular strided access is always provided regardless
# of flags
if sizeof(npy_intp) != sizeof(Py_ssize_t):
raise RuntimeError("Py_intptr_t and Py_ssize_t differs in size, numpy.pxd does not support this")
if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)
and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)):
raise ValueError("ndarray is not C contiguous")
if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)):
raise ValueError("ndarray is not Fortran contiguous")
info.buf = PyArray_DATA(self)
# info.obj = None # this is automatic
info.ndim = PyArray_NDIM(self)
......@@ -85,6 +99,7 @@ cdef extern from "numpy/arrayobject.h":
cdef npy_intp PyArray_STRIDES(ndarray arr)
cdef npy_intp PyArray_DIMS(ndarray arr)
cdef Py_ssize_t PyArray_ITEMSIZE(ndarray arr)
cdef int PyArray_CHKFLAGS(ndarray arr, int flags)
ctypedef signed int npy_byte
ctypedef signed int npy_short
......
......@@ -233,7 +233,7 @@ cdef extern from "Python.h":
# pointer of type PyTypeObject*, except when the incremented
# reference count is needed.
bint PyObject_TypeCheck(object o, object type) # object o, PyTypeObject *type)
bint PyObject_TypeCheck(object o, PyTypeObject *type)
# Return true if the object o is of type type or a subtype of
# type. Both parameters must be non-NULL.
......
This diff is collapsed.
#! /usr/bin/env python
# --------------------------------------------------------------------
import re
from epydoc import docstringparser as dsp
CYTHON_SIGNATURE_RE = re.compile(
# Class name (for builtin methods)
r'^\s*((?P<class>\w+)\.)?' +
# The function name
r'(?P<func>\w+)' +
# The parameters
r'\(((?P<self>(?:self|cls|mcs)),?)?(?P<params>.*)\)' +
# The return value (optional)
r'(\s*(->)\s*(?P<return>\w+(?:\s*\w+)))?' +
# The end marker
r'\s*(?:\n|$)')
parse_signature = dsp.parse_function_signature
def parse_function_signature(func_doc, doc_source,
docformat, parse_errors):
PYTHON_SIGNATURE_RE = dsp._SIGNATURE_RE
assert PYTHON_SIGNATURE_RE is not CYTHON_SIGNATURE_RE
try:
dsp._SIGNATURE_RE = CYTHON_SIGNATURE_RE
found = parse_signature(func_doc, doc_source,
docformat, parse_errors)
dsp._SIGNATURE_RE = PYTHON_SIGNATURE_RE
if not found:
found = parse_signature(func_doc, doc_source,
docformat, parse_errors)
return found
finally:
dsp._SIGNATURE_RE = PYTHON_SIGNATURE_RE
dsp.parse_function_signature = parse_function_signature
# --------------------------------------------------------------------
from epydoc.cli import cli
cli()
# --------------------------------------------------------------------
......@@ -460,8 +460,11 @@ if __name__ == '__main__':
action="store_true", default=False,
help="collect source coverage data for the Compiler")
parser.add_option("-A", "--annotate", dest="annotate_source",
action="store_true", default=False,
action="store_true", default=True,
help="generate annotated HTML versions of the test source files")
parser.add_option("--no-annotate", dest="annotate_source",
action="store_false",
help="do not generate annotated HTML versions of the test source files")
parser.add_option("-v", "--verbose", dest="verbosity",
action="count", default=0,
help="display test progress, pass twice to print test names")
......
cdef int x = 3
if x == NONEXISTING:
print 2
elif x == 2:
print 2342
elif x == 4:
print 34
_ERRORS = """
4:23: undeclared name not builtin: NONEXISTING
"""
cdef class Test:
cdef __cinit__(self):
pass
cdef __len__(self):
pass
_ERRORS = u"""
3:9: Special methods must be declared with 'def', not 'cdef'
6:9: Special methods must be declared with 'def', not 'cdef'
"""
def f():
a = <foao>x
_ERRORS = """
2:13: Unknown type
"""
\ No newline at end of file
......@@ -487,6 +487,25 @@ def list_comprehension(object[int] buf, len):
cdef int i
print u"|".join([unicode(buf[i]) for i in range(len)])
#
# The negative_indices buffer option
#
@testcase
def no_negative_indices(object[int, negative_indices=False] buf, int idx):
"""
The most interesting thing here is to inspect the C source and
make sure optimal code is produced.
>>> A = IntMockBuffer(None, range(6))
>>> no_negative_indices(A, 3)
3
>>> no_negative_indices(A, -1)
Traceback (most recent call last):
...
IndexError: Out of bounds on buffer access (axis 0)
"""
return buf[idx]
#
# Buffer type mismatch examples. Varying the type and access
# method simultaneously, the odds of an interaction is virtually
......@@ -567,6 +586,54 @@ def strided(object[int, ndim=1, mode='strided'] buf):
"""
return buf[2]
@testcase
def c_contig(object[int, ndim=1, mode='c'] buf):
"""
>>> A = IntMockBuffer(None, range(4))
>>> c_contig(A)
2
>>> [str(x) for x in A.recieved_flags]
['FORMAT', 'ND', 'STRIDES', 'C_CONTIGUOUS']
"""
return buf[2]
@testcase
def c_contig_2d(object[int, ndim=2, mode='c'] buf):
"""
Multi-dim has seperate implementation
>>> A = IntMockBuffer(None, range(12), shape=(3,4))
>>> c_contig_2d(A)
7
>>> [str(x) for x in A.recieved_flags]
['FORMAT', 'ND', 'STRIDES', 'C_CONTIGUOUS']
"""
return buf[1, 3]
@testcase
def f_contig(object[int, ndim=1, mode='fortran'] buf):
"""
>>> A = IntMockBuffer(None, range(4))
>>> f_contig(A)
2
>>> [str(x) for x in A.recieved_flags]
['FORMAT', 'ND', 'STRIDES', 'F_CONTIGUOUS']
"""
return buf[2]
@testcase
def f_contig_2d(object[int, ndim=2, mode='fortran'] buf):
"""
Must set up strides manually to ensure Fortran ordering.
>>> A = IntMockBuffer(None, range(12), shape=(4,3), strides=(1, 4))
>>> f_contig_2d(A)
7
>>> [str(x) for x in A.recieved_flags]
['FORMAT', 'ND', 'STRIDES', 'F_CONTIGUOUS']
"""
return buf[3, 1]
#
# Test compiler options for bounds checking. We create an array with a
# safe "boundary" (memory
......@@ -601,7 +668,7 @@ def safe_get(object[int] buf, int idx):
return buf[idx]
@testcase
@cython.boundscheck(False)
@cython.boundscheck(False) # outer decorators should take precedence
@cython.boundscheck(True)
def unsafe_get(object[int] buf, int idx):
"""
......@@ -616,6 +683,18 @@ def unsafe_get(object[int] buf, int idx):
"""
return buf[idx]
@testcase
@cython.boundscheck(False)
def unsafe_get_nonegative(object[int, negative_indices=False] buf, int idx):
"""
Also inspect the C source to see that it is optimal...
>>> A = IntMockBuffer(None, range(10), shape=(3,), offset=5)
>>> unsafe_get_nonegative(A, -2)
3
"""
return buf[idx]
@testcase
def mixed_get(object[int] buf, int unsafe_idx, int safe_idx):
"""
......@@ -878,7 +957,32 @@ def assign_to_object(object[object] buf, int idx, obj):
"""
buf[idx] = obj
#
# cast option
#
@testcase
def buffer_cast(object[unsigned int, cast=True] buf, int idx):
"""
Round-trip a signed int through unsigned int buffer access.
>>> A = IntMockBuffer(None, [-100])
>>> buffer_cast(A, 0)
-100
"""
cdef unsigned int data = buf[idx]
return <int>data
@testcase
def buffer_cast_fails(object[char, cast=True] buf):
"""
Cannot cast between datatype of different sizes.
>>> buffer_cast_fails(IntMockBuffer(None, [0]))
Traceback (most recent call last):
...
ValueError: Attempted cast of buffer to datatype of different size.
"""
return buf[0]
#
......@@ -891,6 +995,8 @@ available_flags = (
('INDIRECT', python_buffer.PyBUF_INDIRECT),
('ND', python_buffer.PyBUF_ND),
('STRIDES', python_buffer.PyBUF_STRIDES),
('C_CONTIGUOUS', python_buffer.PyBUF_C_CONTIGUOUS),
('F_CONTIGUOUS', python_buffer.PyBUF_F_CONTIGUOUS),
('WRITABLE', python_buffer.PyBUF_WRITABLE)
)
......@@ -927,7 +1033,6 @@ cdef class MockBuffer:
strides.reverse()
strides = [x * self.itemsize for x in strides]
suboffsets = [-1] * len(shape)
datashape = [len(data)]
p = data
while True:
......@@ -1035,6 +1140,13 @@ cdef class MockBuffer:
cdef get_default_format(self):
print "ERROR, not subclassed", self.__class__
cdef class CharMockBuffer(MockBuffer):
cdef int write(self, char* buf, object value) except -1:
(<char*>buf)[0] = <int>value
return 0
cdef get_itemsize(self): return sizeof(char)
cdef get_default_format(self): return b"@b"
cdef class IntMockBuffer(MockBuffer):
cdef int write(self, char* buf, object value) except -1:
(<int*>buf)[0] = <int>value
......@@ -1042,6 +1154,13 @@ cdef class IntMockBuffer(MockBuffer):
cdef get_itemsize(self): return sizeof(int)
cdef get_default_format(self): return b"@i"
cdef class UnsignedIntMockBuffer(MockBuffer):
cdef int write(self, char* buf, object value) except -1:
(<unsigned int*>buf)[0] = <unsigned int>value
return 0
cdef get_itemsize(self): return sizeof(unsigned int)
cdef get_default_format(self): return b"@I"
cdef class ShortMockBuffer(MockBuffer):
cdef int write(self, char* buf, object value) except -1:
(<short*>buf)[0] = <short>value
......
#cython: embedsignature=True
# note the r, we use \n below
__doc__ = ur"""
>>> print (Ext.a.__doc__)
Ext.a(self)
>>> print (Ext.b.__doc__)
Ext.b(self, a, b, c)
>>> print (Ext.c.__doc__)
Ext.c(self, a, b, c=1)
>>> print (Ext.d.__doc__)
Ext.d(self, a, b, *, c=88)
>>> print (Ext.e.__doc__)
Ext.e(self, a, b, c=88, **kwds)
>>> print (Ext.f.__doc__)
Ext.f(self, a, b, *, c, d=42)
>>> print (Ext.g.__doc__)
Ext.g(self, a, b, *, c, d=42, e=17, f, **kwds)
>>> print (Ext.h.__doc__)
Ext.h(self, a, b, *args, c, d=42, e=17, f, **kwds)
>>> print (Ext.k.__doc__)
Ext.k(self, a, b, c=1, *args, d=42, e=17, f, **kwds)
>>> print (Ext.get_int.__doc__)
Ext.get_int(self) -> int
>>> print (Ext.get_float.__doc__)
Ext.get_float(self) -> float
>>> print (Ext.clone.__doc__)
Ext.clone(self) -> Ext
>>> print (foo.__doc__)
foo()
>>> with_doc_1.__doc__
'with_doc_1(a, b, c)\nExisting string'
>>> with_doc_2.__doc__
'with_doc_2(a, b, c)\n\n Existing string\n '
>>> types.__doc__
'types(Ext a, int b, unsigned short int c, float d, e)'
>>> print (f_c.__doc__)
f_c(char c) -> char
>>> print (f_uc.__doc__)
f_uc(unsigned char c) -> unsigned char
>>> print (f_sc.__doc__)
f_sc(signed char c) -> signed char
>>> print (f_s.__doc__)
f_s(short int s) -> short int
>>> print (f_us.__doc__)
f_us(unsigned short int s) -> unsigned short int
>>> print (f_ss.__doc__)
f_ss(signed short int s) -> signed short int
>>> print (f_i.__doc__)
f_i(int i) -> int
>>> print (f_ui.__doc__)
f_ui(unsigned int i) -> unsigned int
>>> print (f_si.__doc__)
f_si(signed int i) -> signed int
>>> print (f_l.__doc__)
f_l(long int l) -> long int
>>> print (f_ul.__doc__)
f_ul(unsigned long int l) -> unsigned long int
>>> print (f_sl.__doc__)
f_sl(signed long int l) -> signed long int
>>> print (f_L.__doc__)
f_L(long long int L) -> long long int
>>> print (f_uL.__doc__)
f_uL(unsigned long long int L) -> unsigned long long int
>>> print (f_sL.__doc__)
f_sL(signed long long int L) -> signed long long int
>>> print (f_f.__doc__)
f_f(float f) -> float
>>> print (f_d.__doc__)
f_d(double d) -> double
>>> print (f_D.__doc__)
f_D(long double D) -> long double
"""
cdef class Ext:
def a(self):
pass
def b(self, a, b, c):
pass
def c(self, a, b, c=1):
pass
def d(self, a, b, *, c = 88):
pass
def e(self, a, b, c = 88, **kwds):
pass
def f(self, a, b, *, c, d = 42):
pass
def g(self, a, b, *, c, d = 42, e = 17, f, **kwds):
pass
def h(self, a, b, *args, c, d = 42, e = 17, f, **kwds):
pass
def k(self, a, b, c=1, *args, d = 42, e = 17, f, **kwds):
pass
cpdef int get_int(self):
return 0
cpdef float get_float(self):
return 0.0
cpdef Ext clone(self):
return Ext()
def foo():
pass
def types(Ext a, int b, unsigned short c, float d, e):
pass
def with_doc_1(a, b, c):
"""Existing string"""
pass
def with_doc_2(a, b, c):
"""
Existing string
"""
pass
cpdef char f_c(char c):
return c
cpdef unsigned char f_uc(unsigned char c):
return c
cpdef signed char f_sc(signed char c):
return c
cpdef short f_s(short s):
return s
cpdef unsigned short f_us(unsigned short s):
return s
cpdef signed short f_ss(signed short s):
return s
cpdef int f_i(int i):
return i
cpdef unsigned int f_ui(unsigned int i):
return i
cpdef signed int f_si(signed int i):
return i
cpdef long f_l(long l):
return l
cpdef unsigned long f_ul(unsigned long l):
return l
cpdef signed long f_sl(signed long l):
return l
cpdef long long f_L(long long L):
return L
cpdef unsigned long long f_uL(unsigned long long L):
return L
cpdef signed long long f_sL(signed long long L):
return L
cpdef float f_f(float f):
return f
cpdef double f_d(double d):
return d
cpdef long double f_D(long double D):
return D
"""
Tests accessing attributes of extension type variables
set to None
>>> obj = MyClass(2, 3)
>>> getattr_(obj)
2
>>> getattr_(None)
Traceback (most recent call last):
...
AttributeError: 'NoneType' object has no attribute 'a'
>>> setattr_(obj)
>>> getattr_(obj)
10
>>> setattr_(None)
Traceback (most recent call last):
...
AttributeError: 'NoneType' object has no attribute 'a'
>>> obj = MyClass(2, 3)
>>> checking(obj)
2
2
>>> checking(None)
var is None
>>> check_and_assign(obj)
Traceback (most recent call last):
...
AttributeError: 'NoneType' object has no attribute 'a'
"""
cimport cython
cdef class MyClass:
cdef int a, b
def __init__(self, a, b):
self.a = a
self.b = b
@cython.nonecheck(True)
def getattr_(MyClass var):
print var.a
@cython.nonecheck(True)
def setattr_(MyClass var):
var.a = 10
def some():
return MyClass(4, 5)
@cython.nonecheck(True)
def checking(MyClass var):
state = (var is None)
if not state:
print var.a
if var is not None:
print var.a
else:
print "var is None"
@cython.nonecheck(True)
def check_and_assign(MyClass var):
if var is not None:
print var.a
var = None
print var.a
......@@ -78,6 +78,30 @@ try:
>>> print a
[[0 0 0 0 0]
[0 0 0 0 0]]
Test contiguous access modes:
>>> c_arr = np.array(np.arange(12, dtype='i').reshape(3,4), order='C')
>>> f_arr = np.array(np.arange(12, dtype='i').reshape(3,4), order='F')
>>> test_c_contig(c_arr)
0 1 2 3
4 5 6 7
8 9 10 11
>>> test_f_contig(f_arr)
0 1 2 3
4 5 6 7
8 9 10 11
>>> test_c_contig(f_arr)
Traceback (most recent call last):
...
ValueError: ndarray is not C contiguous
>>> test_f_contig(c_arr)
Traceback (most recent call last):
...
ValueError: ndarray is not Fortran contiguous
>>> test_c_contig(c_arr[::2,::2])
Traceback (most recent call last):
...
ValueError: ndarray is not C contiguous
>>> test_dtype('b', inc1_byte)
>>> test_dtype('B', inc1_ubyte)
......@@ -111,6 +135,13 @@ try:
Traceback (most recent call last):
...
ValueError: only objects, int and float dtypes supported for ndarray buffer access so far (dtype is 20)
>>> test_good_cast()
True
>>> test_bad_cast()
Traceback (most recent call last):
...
ValueError: Attempted cast of buffer to datatype of different size.
"""
except:
......@@ -151,6 +182,15 @@ def put_range_long_1d(np.ndarray[long] arr):
arr[i] = value
value += 1
def test_c_contig(np.ndarray[int, ndim=2, mode='c'] arr):
cdef int i, j
for i in range(arr.shape[0]):
print " ".join([str(arr[i, j]) for j in range(arr.shape[1])])
def test_f_contig(np.ndarray[int, ndim=2, mode='fortran'] arr):
cdef int i, j
for i in range(arr.shape[0]):
print " ".join([str(arr[i, j]) for j in range(arr.shape[1])])
cdef struct cfloat:
float real
......@@ -224,3 +264,13 @@ def test_dtype(dtype, inc1):
a = np.array([0, 10], dtype=dtype)
inc1(a)
if a[1] != 11: print "failed!"
def test_good_cast():
# Check that a signed int can round-trip through casted unsigned int access
cdef np.ndarray[unsigned int, cast=True] arr = np.array([-100], dtype='i')
cdef unsigned int data = arr[0]
return -100 == <int>data
def test_bad_cast():
# This should raise an exception
cdef np.ndarray[long, cast=True] arr = np.array([1], dtype='b')
......@@ -62,6 +62,33 @@ __doc__ = u"""
12
>>> switch_c(13)
0
>>> switch_or(0)
0
>>> switch_or(1)
1
>>> switch_or(2)
1
>>> switch_or(3)
1
>>> switch_or(4)
0
>>> switch_short(0)
0
>>> switch_short(1)
1
>>> switch_short(2)
2
>>> switch_short(3)
0
>>> switch_off(0)
0
>>> switch_off(1)
1
>>> switch_off(2)
0
"""
def switch_simple_py(x):
......@@ -123,3 +150,26 @@ def switch_c(int x):
else:
return 0
return -1
def switch_or(int x):
if x == 1 or x == 2 or x == 3:
return 1
else:
return 0
return -1
def switch_short(int x):
if x == 1:
return 1
elif 2 == x:
return 2
else:
return 0
return -1
def switch_off(int x):
if x == 1:
return 1
else:
return 0
return -1
__doc__ = """
>>> test_signed()
3 <type 'int'>
9 <type 'long'>
6 <type 'long'>
12 <type 'long'>
"""
cdef int i = 1
cdef long l = 2
cdef unsigned int ui = 4
cdef unsigned long ul = 8
def test_signed():
print i + l, type(i+l)
print i + ul, type(i+ul)
print ui + l, type(ui+l)
print ui + ul, type(ui+ul)
__doc__ = u"""
>>> class PyTest(object):
... def __private(self): pass
>>> py = PyTest()
>>> '_PyTest__private' in dir(py)
True
>>> '__private' in dir(py)
False
>>> cy = CyTest()
>>> '_PyTest__private' in dir(cy)
True
>>> '__private' in dir(cy)
False
"""
class CyTest(object):
def __private(self): pass
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