From 0f27805eedcc40ae34009aa31a4dc08cb949f867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sl=C3=A1vek=20Banko?= Date: Fri, 26 Mar 2021 13:52:33 +0100 Subject: [PATCH] DEB pyrex: Added to repository. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Slávek Banko --- debian/pyrex/pyrex-0.9.9/.hgtags | 8 + debian/pyrex/pyrex-0.9.9/CHANGES.txt | 1871 ++++++++ debian/pyrex/pyrex-0.9.9/CHECKLIST.txt | 24 + debian/pyrex/pyrex-0.9.9/Demos/Makefile | 15 + .../pyrex-0.9.9/Demos/Makefile.nodistutils | 21 + debian/pyrex/pyrex-0.9.9/Demos/Setup.py | 14 + .../pyrex/pyrex-0.9.9/Demos/callback/Makefile | 10 + .../Demos/callback/Makefile.nodistutils | 19 + .../pyrex-0.9.9/Demos/callback/README.txt | 1 + .../pyrex/pyrex-0.9.9/Demos/callback/Setup.py | 11 + .../pyrex-0.9.9/Demos/callback/cheese.pyx | 13 + .../pyrex-0.9.9/Demos/callback/cheesefinder.c | 21 + .../pyrex-0.9.9/Demos/callback/cheesefinder.h | 1 + .../pyrex-0.9.9/Demos/callback/run_cheese.py | 7 + debian/pyrex/pyrex-0.9.9/Demos/embed/Makefile | 1 + .../pyrex-0.9.9/Demos/embed/Makefile.msc | 35 + .../Demos/embed/Makefile.msc.static | 1 + .../pyrex-0.9.9/Demos/embed/Makefile.unix | 30 + debian/pyrex/pyrex-0.9.9/Demos/embed/README | 1 + .../pyrex-0.9.9/Demos/embed/embedded.pyx | 5 + debian/pyrex/pyrex-0.9.9/Demos/embed/main.c | 9 + .../pyrex/pyrex-0.9.9/Demos/numeric_demo.pyx | 39 + debian/pyrex/pyrex-0.9.9/Demos/primes.pyx | 18 + debian/pyrex/pyrex-0.9.9/Demos/pyprimes.py | 13 + .../pyrex-0.9.9/Demos/run_numeric_demo.py | 5 + debian/pyrex/pyrex-0.9.9/Demos/run_primes.py | 7 + debian/pyrex/pyrex-0.9.9/Demos/run_spam.py | 8 + debian/pyrex/pyrex-0.9.9/Demos/spam.pyx | 22 + debian/pyrex/pyrex-0.9.9/Doc/About.html | 149 + debian/pyrex/pyrex-0.9.9/Doc/FAQ.html | 75 + .../pyrex-0.9.9/Doc/LanguageOverview.html | 17 + .../pyrex-0.9.9/Doc/Manual/Limitations.html | 53 + .../pyrex/pyrex-0.9.9/Doc/Manual/basics.html | 1118 +++++ .../Doc/Manual/extension_types.html | 1079 +++++ .../pyrex-0.9.9/Doc/Manual/external.html | 294 ++ .../pyrex/pyrex-0.9.9/Doc/Manual/sharing.html | 342 ++ .../pyrex-0.9.9/Doc/Manual/source_files.html | 78 + .../Doc/Manual/special_methods.html | 1124 +++++ .../Doc/Manual/using_with_c++.html | 7 + .../pyrex-0.9.9/Doc/Release_Notes_0.9.9.html | 43 + debian/pyrex/pyrex-0.9.9/Doc/index.html | 70 + debian/pyrex/pyrex-0.9.9/Doc/primes.c | 1 + debian/pyrex/pyrex-0.9.9/INSTALL.txt | 33 + debian/pyrex/pyrex-0.9.9/LICENSE.txt | 173 + debian/pyrex/pyrex-0.9.9/MANIFEST.in | 7 + debian/pyrex/pyrex-0.9.9/Makefile | 15 + .../pyrex-0.9.9/Obsolete/PyrexTypes.py.old | 829 ++++ .../pyrex/pyrex-0.9.9/Obsolete/overview.html | 1485 +++++++ .../pyrex-0.9.9/Pyrex/Compiler/Builtin.py | 276 ++ .../pyrex-0.9.9/Pyrex/Compiler/CmdLine.py | 94 + .../pyrex/pyrex-0.9.9/Pyrex/Compiler/Code.py | 546 +++ .../pyrex-0.9.9/Pyrex/Compiler/DebugFlags.py | 4 + .../pyrex-0.9.9/Pyrex/Compiler/Errors.py | 77 + .../pyrex-0.9.9/Pyrex/Compiler/ExprNodes.py | 3954 +++++++++++++++++ .../pyrex-0.9.9/Pyrex/Compiler/Filenames.py | 9 + .../pyrex-0.9.9/Pyrex/Compiler/Lexicon.pickle | Bin 0 -> 19254 bytes .../pyrex-0.9.9/Pyrex/Compiler/Lexicon.py | 145 + .../pyrex/pyrex-0.9.9/Pyrex/Compiler/Main.py | 564 +++ .../pyrex-0.9.9/Pyrex/Compiler/ModuleNode.py | 1678 +++++++ .../pyrex-0.9.9/Pyrex/Compiler/Naming.py | 69 + .../pyrex/pyrex-0.9.9/Pyrex/Compiler/Nodes.py | 3249 ++++++++++++++ .../pyrex-0.9.9/Pyrex/Compiler/Options.py | 5 + .../pyrex-0.9.9/Pyrex/Compiler/Parsing.py | 2142 +++++++++ .../pyrex-0.9.9/Pyrex/Compiler/PyrexTypes.py | 974 ++++ .../pyrex-0.9.9/Pyrex/Compiler/Scanning.py | 390 ++ .../pyrex-0.9.9/Pyrex/Compiler/Symtab.py | 1342 ++++++ .../pyrex-0.9.9/Pyrex/Compiler/TypeSlots.py | 629 +++ .../pyrex-0.9.9/Pyrex/Compiler/Version.py | 1 + .../pyrex-0.9.9/Pyrex/Compiler/__init__.py | 0 debian/pyrex/pyrex-0.9.9/Pyrex/Debugging.py | 20 + .../pyrex-0.9.9/Pyrex/Distutils/__init__.py | 11 + .../pyrex-0.9.9/Pyrex/Distutils/build_ext.py | 194 + .../pyrex-0.9.9/Pyrex/Distutils/extension.py | 79 + .../Pyrex/DistutilsOld/__init__.py | 22 + .../Pyrex/DistutilsOld/build_ext.py | 63 + .../pyrex-0.9.9/Pyrex/Mac/DarwinSystem.py | 85 + .../pyrex/pyrex-0.9.9/Pyrex/Mac/MacSystem.py | 135 + .../pyrex/pyrex-0.9.9/Pyrex/Mac/MacUtils.py | 34 + debian/pyrex/pyrex-0.9.9/Pyrex/Mac/Makefile | 24 + .../pyrex-0.9.9/Pyrex/Mac/TS_Misc_Suite.py | 64 + .../Pyrex/Mac/_Filemodule_patched.c | 3345 ++++++++++++++ .../pyrex/pyrex-0.9.9/Pyrex/Mac/__init__.py | 0 debian/pyrex/pyrex-0.9.9/Pyrex/Mac/macglue.h | 135 + debian/pyrex/pyrex-0.9.9/Pyrex/Mac/setup.py | 12 + .../pyrex/pyrex-0.9.9/Pyrex/Plex/Actions.py | 109 + debian/pyrex/pyrex-0.9.9/Pyrex/Plex/DFA.py | 156 + debian/pyrex/pyrex-0.9.9/Pyrex/Plex/Errors.py | 52 + .../pyrex/pyrex-0.9.9/Pyrex/Plex/Lexicons.py | 192 + .../pyrex/pyrex-0.9.9/Pyrex/Plex/Machines.py | 326 ++ .../pyrex/pyrex-0.9.9/Pyrex/Plex/Regexps.py | 557 +++ .../pyrex/pyrex-0.9.9/Pyrex/Plex/Scanners.py | 377 ++ debian/pyrex/pyrex-0.9.9/Pyrex/Plex/Timing.py | 22 + .../pyrex-0.9.9/Pyrex/Plex/Traditional.py | 154 + .../pyrex-0.9.9/Pyrex/Plex/Transitions.py | 253 ++ .../pyrex/pyrex-0.9.9/Pyrex/Plex/__init__.py | 40 + .../pyrex/pyrex-0.9.9/Pyrex/Plex/test_tm.py | 24 + .../pyrex-0.9.9/Pyrex/Unix/LinuxSystem.py | 74 + .../pyrex/pyrex-0.9.9/Pyrex/Unix/__init__.py | 0 debian/pyrex/pyrex-0.9.9/Pyrex/Utils.py | 55 + debian/pyrex/pyrex-0.9.9/Pyrex/__init__.py | 0 debian/pyrex/pyrex-0.9.9/README.txt | 37 + debian/pyrex/pyrex-0.9.9/ToDo.txt | 164 + debian/pyrex/pyrex-0.9.9/Tools/pyrex-mode.el | 1 + debian/pyrex/pyrex-0.9.9/Tools/pyrex.st | 1 + debian/pyrex/pyrex-0.9.9/USAGE.txt | 69 + debian/pyrex/pyrex-0.9.9/bin/pyrexc | 8 + debian/pyrex/pyrex-0.9.9/bin/pyrexc2.5 | 8 + debian/pyrex/pyrex-0.9.9/bin/pyrexc2.6 | 8 + debian/pyrex/pyrex-0.9.9/bin/pyxcc | 15 + debian/pyrex/pyrex-0.9.9/bin/run_tests_2.5 | 7 + debian/pyrex/pyrex-0.9.9/bin/run_tests_2.6 | 7 + .../pyrex/pyrex-0.9.9/bin/update_references | 49 + debian/pyrex/pyrex-0.9.9/debian/changelog | 333 ++ debian/pyrex/pyrex-0.9.9/debian/compat | 1 + debian/pyrex/pyrex-0.9.9/debian/control | 35 + debian/pyrex/pyrex-0.9.9/debian/copyright | 44 + .../debian/patches/baseexception.patch | 24 + .../pyrex/pyrex-0.9.9/debian/patches/series | 1 + debian/pyrex/pyrex-0.9.9/debian/pyrex-mode.el | 15 + .../debian/pyrex-mode.emacsen-startup | 23 + .../pyrex-0.9.9/debian/pyrex-mode.install | 1 + debian/pyrex/pyrex-0.9.9/debian/pyrexc.1 | 43 + .../pyrex-0.9.9/debian/python-pyrex.doc-base | 10 + .../pyrex-0.9.9/debian/python-pyrex.docs | 5 + .../pyrex/pyrex-0.9.9/debian/pythonX.Y-pyrexc | 7 + debian/pyrex/pyrex-0.9.9/debian/rules | 93 + debian/pyrex/pyrex-0.9.9/debian/source/format | 1 + .../pyrex/pyrex-0.9.9/debian/source/options | 3 + debian/pyrex/pyrex-0.9.9/debian/watch | 2 + debian/pyrex/pyrex-0.9.9/hgignore | 10 + debian/pyrex/pyrex-0.9.9/pyrexc.py | 6 + debian/pyrex/pyrex-0.9.9/setup.py | 48 + debian/pyrex/pyrex_0.9.9.orig.tar.gz | Bin 0 -> 255272 bytes 133 files changed, 33063 insertions(+) create mode 100644 debian/pyrex/pyrex-0.9.9/.hgtags create mode 100644 debian/pyrex/pyrex-0.9.9/CHANGES.txt create mode 100644 debian/pyrex/pyrex-0.9.9/CHECKLIST.txt create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/Makefile create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/Makefile.nodistutils create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/Setup.py create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/callback/Makefile create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/callback/Makefile.nodistutils create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/callback/README.txt create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/callback/Setup.py create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/callback/cheese.pyx create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/callback/cheesefinder.c create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/callback/cheesefinder.h create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/callback/run_cheese.py create mode 120000 debian/pyrex/pyrex-0.9.9/Demos/embed/Makefile create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/embed/Makefile.msc create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/embed/Makefile.msc.static create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/embed/Makefile.unix create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/embed/README create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/embed/embedded.pyx create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/embed/main.c create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/numeric_demo.pyx create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/primes.pyx create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/pyprimes.py create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/run_numeric_demo.py create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/run_primes.py create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/run_spam.py create mode 100644 debian/pyrex/pyrex-0.9.9/Demos/spam.pyx create mode 100644 debian/pyrex/pyrex-0.9.9/Doc/About.html create mode 100644 debian/pyrex/pyrex-0.9.9/Doc/FAQ.html create mode 100644 debian/pyrex/pyrex-0.9.9/Doc/LanguageOverview.html create mode 100644 debian/pyrex/pyrex-0.9.9/Doc/Manual/Limitations.html create mode 100644 debian/pyrex/pyrex-0.9.9/Doc/Manual/basics.html create mode 100644 debian/pyrex/pyrex-0.9.9/Doc/Manual/extension_types.html create mode 100644 debian/pyrex/pyrex-0.9.9/Doc/Manual/external.html create mode 100644 debian/pyrex/pyrex-0.9.9/Doc/Manual/sharing.html create mode 100644 debian/pyrex/pyrex-0.9.9/Doc/Manual/source_files.html create mode 100644 debian/pyrex/pyrex-0.9.9/Doc/Manual/special_methods.html create mode 100644 debian/pyrex/pyrex-0.9.9/Doc/Manual/using_with_c++.html create mode 100644 debian/pyrex/pyrex-0.9.9/Doc/Release_Notes_0.9.9.html create mode 100644 debian/pyrex/pyrex-0.9.9/Doc/index.html create mode 100644 debian/pyrex/pyrex-0.9.9/Doc/primes.c create mode 100644 debian/pyrex/pyrex-0.9.9/INSTALL.txt create mode 100644 debian/pyrex/pyrex-0.9.9/LICENSE.txt create mode 100644 debian/pyrex/pyrex-0.9.9/MANIFEST.in create mode 100644 debian/pyrex/pyrex-0.9.9/Makefile create mode 100644 debian/pyrex/pyrex-0.9.9/Obsolete/PyrexTypes.py.old create mode 100644 debian/pyrex/pyrex-0.9.9/Obsolete/overview.html create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Builtin.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/CmdLine.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Code.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/DebugFlags.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Errors.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/ExprNodes.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Filenames.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Lexicon.pickle create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Lexicon.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Main.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/ModuleNode.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Naming.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Nodes.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Options.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Parsing.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/PyrexTypes.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Scanning.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Symtab.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/TypeSlots.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Version.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/__init__.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Debugging.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Distutils/__init__.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Distutils/build_ext.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Distutils/extension.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/DistutilsOld/__init__.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/DistutilsOld/build_ext.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Mac/DarwinSystem.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Mac/MacSystem.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Mac/MacUtils.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Mac/Makefile create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Mac/TS_Misc_Suite.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Mac/_Filemodule_patched.c create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Mac/__init__.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Mac/macglue.h create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Mac/setup.py create mode 100755 debian/pyrex/pyrex-0.9.9/Pyrex/Plex/Actions.py create mode 100755 debian/pyrex/pyrex-0.9.9/Pyrex/Plex/DFA.py create mode 100755 debian/pyrex/pyrex-0.9.9/Pyrex/Plex/Errors.py create mode 100755 debian/pyrex/pyrex-0.9.9/Pyrex/Plex/Lexicons.py create mode 100755 debian/pyrex/pyrex-0.9.9/Pyrex/Plex/Machines.py create mode 100755 debian/pyrex/pyrex-0.9.9/Pyrex/Plex/Regexps.py create mode 100755 debian/pyrex/pyrex-0.9.9/Pyrex/Plex/Scanners.py create mode 100755 debian/pyrex/pyrex-0.9.9/Pyrex/Plex/Timing.py create mode 100755 debian/pyrex/pyrex-0.9.9/Pyrex/Plex/Traditional.py create mode 100755 debian/pyrex/pyrex-0.9.9/Pyrex/Plex/Transitions.py create mode 100755 debian/pyrex/pyrex-0.9.9/Pyrex/Plex/__init__.py create mode 100755 debian/pyrex/pyrex-0.9.9/Pyrex/Plex/test_tm.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Unix/LinuxSystem.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Unix/__init__.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/Utils.py create mode 100644 debian/pyrex/pyrex-0.9.9/Pyrex/__init__.py create mode 100644 debian/pyrex/pyrex-0.9.9/README.txt create mode 100644 debian/pyrex/pyrex-0.9.9/ToDo.txt create mode 100644 debian/pyrex/pyrex-0.9.9/Tools/pyrex-mode.el create mode 100644 debian/pyrex/pyrex-0.9.9/Tools/pyrex.st create mode 100644 debian/pyrex/pyrex-0.9.9/USAGE.txt create mode 100755 debian/pyrex/pyrex-0.9.9/bin/pyrexc create mode 100755 debian/pyrex/pyrex-0.9.9/bin/pyrexc2.5 create mode 100755 debian/pyrex/pyrex-0.9.9/bin/pyrexc2.6 create mode 100755 debian/pyrex/pyrex-0.9.9/bin/pyxcc create mode 100755 debian/pyrex/pyrex-0.9.9/bin/run_tests_2.5 create mode 100755 debian/pyrex/pyrex-0.9.9/bin/run_tests_2.6 create mode 100755 debian/pyrex/pyrex-0.9.9/bin/update_references create mode 100644 debian/pyrex/pyrex-0.9.9/debian/changelog create mode 100644 debian/pyrex/pyrex-0.9.9/debian/compat create mode 100644 debian/pyrex/pyrex-0.9.9/debian/control create mode 100644 debian/pyrex/pyrex-0.9.9/debian/copyright create mode 100644 debian/pyrex/pyrex-0.9.9/debian/patches/baseexception.patch create mode 100644 debian/pyrex/pyrex-0.9.9/debian/patches/series create mode 100644 debian/pyrex/pyrex-0.9.9/debian/pyrex-mode.el create mode 100644 debian/pyrex/pyrex-0.9.9/debian/pyrex-mode.emacsen-startup create mode 100644 debian/pyrex/pyrex-0.9.9/debian/pyrex-mode.install create mode 100644 debian/pyrex/pyrex-0.9.9/debian/pyrexc.1 create mode 100644 debian/pyrex/pyrex-0.9.9/debian/python-pyrex.doc-base create mode 100644 debian/pyrex/pyrex-0.9.9/debian/python-pyrex.docs create mode 100644 debian/pyrex/pyrex-0.9.9/debian/pythonX.Y-pyrexc create mode 100755 debian/pyrex/pyrex-0.9.9/debian/rules create mode 100644 debian/pyrex/pyrex-0.9.9/debian/source/format create mode 100644 debian/pyrex/pyrex-0.9.9/debian/source/options create mode 100644 debian/pyrex/pyrex-0.9.9/debian/watch create mode 100644 debian/pyrex/pyrex-0.9.9/hgignore create mode 100755 debian/pyrex/pyrex-0.9.9/pyrexc.py create mode 100644 debian/pyrex/pyrex-0.9.9/setup.py create mode 100644 debian/pyrex/pyrex_0.9.9.orig.tar.gz diff --git a/debian/pyrex/pyrex-0.9.9/.hgtags b/debian/pyrex/pyrex-0.9.9/.hgtags new file mode 100644 index 00000000..f273732d --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/.hgtags @@ -0,0 +1,8 @@ +588a14055d1691eb3d0a14d69be108c6110fcee7 0.9.8 +66ff407aae9ec4fba986bfdbc6686f1eb7016dce 0.9.8.2 +37554acbb702072bdefef51980be33c551e38895 0.9.8.3 +ac76d2c45aa1f7055b6101064eac30cfb648a350 0.9.8.4 +ac4da2723c96ef0ffc792d9a763638a62e103426 0.9.8.5 +f89737e75fc5ef7c007abb97dd0f2694c7ae071b 0.9.8.6 +67efcff42bd53148cfdbb0767c64e1c7a852f82f 0.9.9 +f11df44eb1bfa2f7ed609c7affc89461e8aa91f5 0.9.9 diff --git a/debian/pyrex/pyrex-0.9.9/CHANGES.txt b/debian/pyrex/pyrex-0.9.9/CHANGES.txt new file mode 100644 index 00000000..be330a81 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/CHANGES.txt @@ -0,0 +1,1871 @@ +0.9.9 +----- + +New features: + + - C++ struct declarations, 'new' operator, and del for C++ delete. + + - As well as the 'not None' modifier for extension type arguments, there + is now 'or None' to explicitly allow passing None. It is planned to make + 'not None' the default in a future version. For now, a warning is issued + (once per Pyrex run) if you do not specify one or the other. + + - Extension types may have a 'nogc' option to suppress GC support. + +Modifications: + + - Exceptions caught by an except clause are no longer put into the thread + state and cannot be retrieved using sys.exc_info(). To access the caught + exception, it must be bound to a name in the except clause. A third name + can be supplied to capture the traceback. + + - PyString_InternFromString is now exposed under the name 'cintern' because + it is not a complete substitute for 'intern' (it can't handle strings + containing null bytes). [John Arbash Meinel] + + - Disabled size check for cimported types because it was generating too + many false positives in the field. + + - Added __fastcall calling convention. Also no longer assuming that an + unspecified calling convention is the same as __cdecl. + + - Operations between signed and unsigned ints of the same size now have + an unsigned result. + + - Py_ssize_t now ranked between long and long long. + + - Declaration of __new__ in an extension type is now an error, in + preparation for introducing new semantics. + + - Added size_t type, and made sizeof() return it. + +Bug fixes: + + - When casting the result of a function call to a Python type, the + function could be called twice. [David Martinez] + + - __Pyx_GetException was not taking account of the fact that the traceback + could be NULL. + + - sizeof(module.typename) did not work. [Daniele Pianu] + + +0.9.8.6 +------- + +Enhancements: + + - Check for gil when calling a function declared 'execpt *' or 'except ?'. + Acquire gil when reporting unraisable exception. + + - Added iter2() function for 2-argument form of iter(). + +Bug fixes: + + - Compiler crashed if base class of extension type was incompletely + defined. + + - Compiler crash on misspelled method name in property declaration. + [Stefan Behnel] + + - Fixed deprecation warnings in 2.6 + + - Always preserve explicit type casts for non-Python types. + [Alexander Belchenko] + + - Added workaround for threading initialisation bug in Python 2.3. + [Lisandro Dalcin] + + - Deleting dict item with integer key did not work. [Titus Brown] + + - Header files for cimported modules included in wrong order. + [Stephane Drouard] + + - Don't allow a member of a ctypedef struct to reference itself. + [Tim Wakeham] + + - Compiler crash due to attribute reference in compile-time expression. + [Hoyt Koepke] + + - Public extension type attribute with cname didn't work. + [Mark Ellis] + + - Memory leak related to exporting C functions. [Lisandro Dalcin] + + - Compiler crash on return outside function. [Kurt Smith] + + - Scope problem with extension types declared in pxd. [KS Sreeram] + + - Calling a builtin method of a subclass of a builtin class did not work. + + - Builtin hash() function had wrong return type. [John Arbash Meinel] + + +Modifications: + + - Added 'tags' to .hgignore file. [Kirill Smelkov] + + - Disallow overriding a builtin method in a subclass of a builtin class. + + +0.9.8.5 +------- + +Bug fixes: + + - Function export code was erroneously generated for 'extern' functions + declared in a .pxd file. [Sebastian Sable] + + - The 'api' option was not recognised with 'ctypedef public class'. + [Lisandro Dalcin] + + - MACOSX_DEPLOYMENT_TARGET is no longer set unless the undocumented -X + option is being used. Hopefully this will prevent complaints about it + from distutils. [Martin Field] + + - Recognize MS_WINDOWS as well as WIN32. [Alexander Belchenko] + + - Hexadecimal compile-time constants did not work. [Devan] + +Enhancements: + + - Dependency files (.dep) are only created when compiling with timestamp + checking or recursion enabled. + +Deprecations: + + - The features introducted in 0.9.8 and 0.9.8.1 for cross-forward-declaring + extension types between .pxd files turn out to be unnecessary, since + the circular import problems they are aimed at can be avoided using + ordinary forward delcarations in the .pxd files ahead of any cimports. + + +0.9.8.4 +------- + +Bug fixes: + + - Incorrect code generated for Python indexing with an unsigned int. + [Christopher Williams] + + +0.9.8.3 +------- + +Bug fixes: + + - Compiling multiple source files at once should work as advertised + now. + + - Assignment of a nogil function to a non-nogil function pointer + is now allowed. + + - Applying += or -= to a pointer and an integer did not work. + [Arc Riley] + + - Compiling a .pyx file whose name is not a valid module name now + reports an error instead of generating invalid C code. + [Robert Bradshaw] + + - Integer indexing optimisation now performed only for signed + index types, to avoid change of semantics with index values + greater than the maximum positive signed int value. [Robert + Bradshaw] + + - Non-void function declared 'except *' could produce C compiler + warning about uninitialised variable. [Lisandro Dalcin] + + +0.9.8.2 +------- + +Enhancements: + + - A block of external functions can be declared nogil at once. + + cdef extern from "somewhere.h" nogil: + ... + +Bug fixes: + + - The nogil attribute was not being checked for a match when + comparing function signatures. + + - Improved error message for C method signature mismatch between + a class and its base class. + +Bug workarounds: + + - Multiple source files passed to Main.compile are being compiled + in separate contexts for the time being until I can sort out a + problem. You probably won't notice any difference except that + there will be no speed advantage over compiling them separately. + + +0.9.8.1 +------- + +Enhancements: + + - It is no longer necessary to specify the base class of an + extension type in a forward declaration. Also, if the class is + defined in a .pxd file, the base class only needs to be specified + in the .pxd file, not the .pyx file. + [Arc Riley] + + - There's now an even easier way to forward-declare a struct, union + or extension type in another module: + + from blarg cimport class Foo + + This simultaneously cimports the name Foo and forward-declares + it as an extension type. As well as 'class', you can also use + 'struct' or 'union'. + +Modifications: + + - Casting a non-Python pointer type to a Python type no longer + generates an incref, unless one is required for other reasons. + [Arc Riley] + + - More checks added for gil-requiring operations performed without + holding the gil. + + +0.9.8 +----- + +New features: + + * Augmented assignment operators (+=, etc.) are now supported. + + * Package directories + + Modules in packages no longer need to have dotted names. Instead, + a Python-like package directory structure can be used, with + package dirs marked by containing an __init__.py or __init__.pyx. + + Top-level package directories are found by searching the include + directories specified by -I options (analogous to PYTHONPATH). + + * Dependency tracking + + The Pyrex compiler records information about other source files cimported + or included, and can automatically compile all the modules a given module + depends on, with timestamp checking. + + This is enabled by a -r (recursive) option to the compiler, e.g. + + pyrexc -r mainmodule.pyx + + There are also two other new command-line options: + + -t Enable timestamp checking. This is implied with -r. + + -f Overrides implied -t when using -r and forces all + dependent modules to be compiled regardless of timestamps. + + * Nogil restrictions relaxed + + C functions declared nogil can now have Python objects as arguments. + The argument names are read-only inside the function when this is done. + + Among other things, this allows C methods to be declared nogil (this + couldn't be done before because 'self' is always an object argument). + + * Circular cimports + + There is now a way of forward-declaring a struct, union or extension type + into another module. This allows two .pxd files to define extension types + that refer to each other without running into circular import problems. + For example: + + cimport blarg + cdef class blarg.Blarg # Forward declaration + + cdef class Foo: + cdef blarg.Blarg blg + + +0.9.7.2 +------- + + Bug fixes: + + - Another integer indexing problem fixed. + + +0.9.7.1 +------- + + Bug fixes: + + - The optimisation for indexing using a C int failed when the + object being indexed was a mapping rather than a sequence. + [Arc Riley] + + Modifications: + + - Old integer for-loop syntax is no longer deprecated. + + +0.9.7 +----- + +New features: + + - Builtin constants and types are known, and are referenced directly + with no dictionary lookup. + + - Direct calls are made to certain methods of lists and dicts when + their type is statically known. + + - New builtin functions 'typecheck' and 'issubtype' added, providing + safer type checking than isinstance and issubclass (which can be + overridden). + +Enhancements: + + - Redundant type test eliminated when assigning the result of an + extension type constructor call to a variable of the same type. + + - No tp_traverse and tp_clear functions generated for types + without Python attributes. + + - Safer code generated in tp_clear. [Stefan Behnel] + + - Indexing with a C int type generates calls to PySequence_GetItem + and PySequence_SetItem. + + - Integer for-loop syntax streamlined to 'for x < i < y'. + + - Appropriate C code generated for compile-time expressions + evaluating to float nan, inf and -inf. [Stefan Behnel] + +Bug fixes: + + - Value raised by assert statement now only evaluated if the + assertion fails. [Stefan Behnel] + + - Comparing a value of an enum type with another value of a type + which is ctypedefed to the same enum type gave a spurious type + error. [Matt Hammond] + + - Comparing an int with a float resulted in the float being cast + to an int before comparison. [Robin Becker] + + - Compiler crashed on an invalid argument to a 'with nogil' statement. + [Stefan Behnel] + + - Incorrect code generated for function with keyword only args + and no * or ** args. [Stefan Behnel] + + - GC type with non-GC base type caused crash due to trying to call + non-existent base tp_traverse and tp_clear functions. [Stefan Behnel] + + - Compile-time IF with no ELSE clause crashed compiler. [Kirk McDonald] + + - Values in enum declaration were not being checked for appropriate type. + [Simon Burton] + + - Improved the error message from attempting to declare a struct or + union member as a function. [Yong Sun] + + - Referring to an undefined name in a compile-time constant crashed + the compiler. [Stefan Behnel] + + +0.9.6.4 +------- + +Bug fixes: + + - Errors in setup.py corrected. + + - Incorrect error checking code generated for builtin functions + and type slots with return type Py_ssize_t. [Robert Bradshaw] + + - A counted reference was not kept to the module, so if the entry + in sys.modules was replaced, the module was freed prematurely. + [Franck Pommerau] + + - A cimport statement inside a function crashed the compiler. + [Robert Bradshaw] + + - __Pyx_ImportModule routine wasn't protected from multiple + definition when including _api.h files. [Stefan Behnel] + + - Temp variables holding exception values were not being set to + NULL after use in an except clause. [Robert Bradshaw] + + - Protect __stdcall and __cdecl from redefinition. [Jim Kleckner] + + - A temp var was not being set to NULL after api function import + code. [Stefan Behnel] + + - __Pyx_ImportFunction was incorrectly decrefing a borrowed + reference. [Stefan Behnel] + +Enhancements: + + - Functions declared with_gil and external functions declared nogil + are now allowed to have Python arguments and return types. + + +0.9.6.3 +------- + +Enhancements: + + - C API now only uses a single name in the module namespace + instead of one for each exported C function. [Stefan Behnel] + + - Multiple declarations with the same visibility and api options + can now be grouped into a 'cdef' block. + + - The 'api' keyword can now be used on extension types to cause + generation of an api.h file when there are no exported C functions. + + - Added a getattr3() builtin for the three-argument form of getattr. + +Bug fixes: + + - Setup.py no longer uses an import to get the version number + being installed, to avoid a problem with setuptools. + + - If a struct or union was forward-declared, certain types of error + message misleadingly referenced the source location of the forward + declaration rather than the definition. + + - Calling convention specifier was being emitted in function + prototypes but not the corresponding definitions. [Atsuo Ishimoto] + + - Added support for the --force option to Pyrex.Distutils. + [Alexander Belchenko] + + - Compile-time "==" operator did not work. [Simon King] + + - Header files generated for public and api declarations now + only contain types declared as 'public', instead of all types + defined in the module. [Stefan Behnel] + + +0.9.6.2 +------- + +Bug fixes: + + - Corrected a problem with declaration ordering in generated C + code involving forward-declared struct, union or extension types. + + - New distutils extension: Only compile .pyx if it is newer + than the corresponding .c file. + + +0.9.6.1 +------- + +Bug fixes: + + - Changed os.uname to platform.uname for portability. + [Alexander Belchenko] + + - Fixed C compiler warning about incompatible types in 2.5. + [Alexander Belchenko] + + - Also fixed a few other 2.5 problems. + + - Fixed problem with the Extension class in the new Pyrex.Distutils + module. + + +0.9.6 +----- + +New Features: + + - Top-level C functions defined in one module can now be used in + another via cimport, and a C API can be produced to allow them + to be used from C code without linking to the extension module. + See "Interfacing with External C Code" and "Sharing Declarations + between Pyrex Modules" in the Language Overview. [Stefan Behnel] + + - Facilities added for releasing the GIL around a section of code + and acquiring it on entry to a C function. See "Acquiring and + Releasing the GIL under "Interfacing with External C Code" in + the Language Overview. [Ulisses Furquim, Stefan Behnel] + + - Some conditional compilation facilities have been added. See + "Conditional Compilation" under "Language Basics" in the + Language Overview. [Sam Rushing] + +Language Changes: + + - The __new__ special method of extension types is being renamed + to "__cinit__". For now, you will get a warning whenever you + declare a __new__ method for an extension type, and it will + automatically be renamed to __cinit__ for you. In the next + release, the warning will become an error and no renaming will + occur. In some later release, the __new__ method may be + re-introduced with different semantics. It is recommended that + you begin updating your sources now to use __cinit__. + + - A 'raise' statement with no arguments (i.e. to re-raise the + last exception caught) is now required to be lexically within + the 'except' clause which caught the exception. This change was + necessary to efficiently support preserving the exception if an + intervening call raises and catches a different exception. + + - The following new reserved words have been added: + + with, DEF, IF, ELIF, ELSE + +Enhancements: + + - Calls to many of the builtin functions are now compiled as + direct calls to Python/C API routines. + + - A C type explicitly declared as 'signed' is represented as + such in the generated code, to acommodate platforms where + 'char' is unsigned by default. [Francesc Altet] + + - Python function can now have an argument of type "unsigned + char". [Alexander Belchenko] + + - A new Pyrex.Distutils implementation has been added, which + exports an Extension type supporting the following options: + + pyrex_include_dirs - list of dirs to search for Pyrex header files + pyrex_create_listing_file - bool - write errs to listing file + pyrex_cplus - bool - generate C++ code + pyrex_c_in_temp - bool - put generated C files in temp dir + pyrex_gen_pxi - bool - generate .pxi file for public declarations + + [Contributed by Billie G. Allie] + + - Assert statements can be compiled out by arranging for + PYREX_WITHOUT_ASSERTIONS to be #defined at C compilation time. + [Contributed by Stefan Behnel] + + - Support for __index__ slot added to extension types. + [William Stein] + + - Exception types now properly checked according to pre or post + 2.5 rules as appropriate. + + - Py_ssize_t support added. [Stefan Behnel] + + - Windows __stdcall and __cdecl qualifiers now supported. + [Suggested by Eric Devolder] + + - Keyword-only argument support added. [Suggested by Stefan Behnel] + + - An 'include' statement can now appear anywhere that another kind + of statement or declaration can appear, instead of being restricted + to the top level. [Caio Marcelo] + + - Unnecessary PyErr_Occurred() call to check result of + PyString_AsString() no longer made. + + - Complicated C types are displayed more readably in error messages. + +Modifications: + + - A Python function argument declared as "char" or "unsigned + char" now expects a Python integer rather than a string of + length 1, for consistency with the way automatic conversions + are done elsewhere. + + - Support for string and tuple exceptions dropped. + +Bug fixes: + + - If an external ctypedef type was used as the type of an + argument to a Python function, a declaration was generated + using the underlying type rather than the typedef name. + [Francesc Altet] + + - Some problems with int/enum and pointer/array compatibility + fixed. [Eric Huss, Stefan Behnel, Jiba] + + - Eliminated C compiler warning when comparing an extension + type reference to None using 'is' or 'is not' + + - Eliminated C compiler warnings about docstrings of C functions + and special methods being unused. [Francesc Altet] + + - When compiling with -O, raising an exception in a C function + that couldn't propagate exceptions produced a compiler + warning about the return value possibly being uninitialised. + + - Fixed warning about function declaration not being a prototype + caused by C method table initialisation code. + + - Spurious initialisation was generated for unused local variable. + [Helmut Jarausch] + + - Declaration of a non-extern C function without definition + was not detected. [Lenard Lindstrom] + + - Applying ** directly to two C int types is now disallowed due + to ambiguity (it's not clear whether to use C pow() or convert + to Python ints). [Didier Deshommes] + + - Traverse and clear code was being inadvertently generated for + the __weakref__ slot of a weakly-referenceable extension type. + [Peter Johnson] + + - Statements other than def inside a property declaration were + crashing the compiler. [Sven Berkvens] + + - Defining an extension type with different visibility from its + declaration in a .pxd file crashed the compiler. + [Alex Coventry] + + - Instantiating an exception type whose base class __new__ method + raises an exception caused a segfault. [Gustavo Sverzut Barbieri] + + - The 'import pkg.module as name' form of import statement did not + work correctly. [Dan] + + - Fixed error-checking typo in __Pyx_GetStarArgs(). [Eric Huss] + + - Trailing comma now allowed on argument list. [Jim Kleckner] + + - Behaviour of reraise made to match Python more closely. + [Eric Huss] + + - An empty C variable declaration crashed the compiler. + + - Now includes math.h instead of generating own declaration + of pow(). [Leif Strand] + + - Missing import of sys in LinuxSystem.py added. [Scott Jackson] + + - Typecasts using a ctypedef type were not using the ctypedef + name. [Alexander Belchenko] + + - Workaround added to setup.py for a problem with bdist_wininst. + [Alexander Belchenko] + + - Subtle error in parsing empty function declarators corrected. + + - Checks added for some type combinations that are illegal in C: + array of functions, function returning function or array, cast + to a function. + + +0.9.5.1a +-------- + +Bug fixes: + + - Package list now calculated dynamically in setup.py so that + it will work with or without the testing framework installed. + + +0.9.5.1 +------- + +Bug fixes: + + - Comparing two values of the same enum type incorrectly + produced an error. [Anders Gustafsson] + + - Compiler crash caused by assigning a Python value to + a variable of an enum type. [Peter Johnson] + + - Comparison between pointer and array incorrectly produced + a type mismatch error. [Helmut Jarausch] + + - Unused local Python variable had spurious init/cleanup code + generated for it, causing C compilation errors. [Helmut Jarausch] + + - Updated list of packages in setup.py. + +Modifications: + + - NULL in Pyrex source now translated into NULL instead of 0 + in C code, to allow for the possibility of calling something + not defined with a prototype in an external header. [Adapted Cat] + + +0.9.5 +----- + +Enhancements: + + - Exception return values may now be specified by arbitrary + constant expressions of appropriate type, not just literals. + [Stefan Behnel] + + - Redundant type check now omitted when passing a literal None + to a function expecting an extension type. [Patch by Sam Rushing] + + - New-style classes now allowed as exceptions for compatibility + with Python 2.5 (inheritance from BaseException not currently + checked). [Stefan Behnel] + + - Sequence unpacking is now done using the iterator protocol + instead of indexing. + + - Allocation of an empty tuple is avoided when making a + Python call with no arguments. [Stefan Behnel] + + - Most warnings about unused variables and labels have been + eliminated. + + - Support for running the test suite on Linux added but not + yet fully tested. [Based in part on patch by Eric Wald]. + + - Makefile included for compiling the patched Carbon File module + used by the MacOSX test code. + +Modifications: + + - Type rules for enums tightened for compatibility with C++. + + - Direct assignment from float to int disallowed to prevent + C++ compilation warnings. + + - Hex literals left as hex in C code to avoid warnings from + the C compiler about decimal constants becoming unsigned. + +Bug fixes: + + - Exception raised during argument conversion could cause crash + due to uninitialised local variables. [Konrad Hinsen] + + - Assignment to a C attribute of an extension type from a + different type could generate C code with a pointer type + mismatch. [Atsuo Ishimoto] + + - Backslash in a string literal before a non-special character + was not handled correctly. [Yuan Mang] + + - Temporary vars used by del statement not being properly + released, sometimes leading to double decrefs. [Jiba] + + - A return statement whose expression raises an exception + inside a try-except that catches the exception could cause + a crash. [Anders Gustafsson] + + - Fixed type compatibility checking problem between pointers + and arrays. [Lenard Lindstrom] + + - Circular imports between modules defining extension types + caused unresolvable import order conflicts. [Mike Wyatt] + + - Cimporting multiple submodules from the same package caused + a redefined name error for the top level name. [Martin Albrecht] + + - Incorrect reference counting when assigning to an element of an + array that is a C attribute of an extension type. [Igor Khavkine] + + - Weak-referenceable extension types were not implemented + properly. [Chris Perkins, Peter Johnson] + + - Crash if C variable declared readonly outside an extension + type definition. [Eric Huss] + +Doc updates: + + - Expanded discussion of the need for type declarations to enable + access to attributes of extension types. + + - Added a section "Source Files and Compilation" explaining the + rules for naming of source files of modules residing in packages, + and instructions for using the compiler and distutils extension. + + +0.9.4.1 +------- + +Bug fixes: + + - Fixed indentation problem in Pyrex.Distutils.build_ext. + [Oliver Grisel] + + +0.9.4 +----- + +Improvements: + + - All use of lvalue casts has been eliminated, for + compatibility with gcc4. + + - PyMODINIT_FUNC now used to declare the module init function. + + - Generated code should be compilable as either C or C++. + When compiling as C++, "extern C" is used where appropriate + to preserve linkage semantics. + + - An extension type can be made weak-referenceable by + giving it a C attribute of type object called __weakref__. + + - Source files opened in universal newlines mode. + + - Support for public extension type C attributes of type + long long and unsigned long long added (but not tested). + [Sam Rushing] + + - Distutils include directories now passed to Pyrex compiler. + [Konrad Hinsen] + + - Integer constants with an "L" suffix are now allowed + and are converted to Python long integers. [Rainer Deyke] + + - A broken .c file is no longer left behind if there are + compilation errors. + + - Using the result of a Python indexing or attribute access + operation as a char * is no longer considered an error in + most cases, as the former behaviour proved to be more + annoying than helpful. + +Bug fixes: + + - Fixed problems with conversion from Python integers to + C unsigned longs. Now use PyInt_AsUnsignedLongMask and + PyInt_AsUnsignedLongLongMask instead of the PyLong_* + functions (which only work on Python longs). [Wim Vree] + + - C unsigned ints now converted to/from Python longs intead + of Python ints to avoid overflow problems. [Heiko Wundram] + + - Correct PyArg_ParseTuple format characters now used for + unsigned types. [Jeff Bowden] + + - Nonzero return value from a base class tp_traverse call + is handled. + + - Taking sizeof an incomplete type caused a crash while + producing an error message. [Drew Perttula] + + - If a module cimported itself, definitions of global variables + were generated twice. [Parzival Herzog] + + - Distutils extension updated to handle changed signature of + swig_sources(). [David M. Cooke] + + - Incorrect C code generated for a raw string containing a double + quote preceded by a backslash. [Thomas Drake] + + - Declaration of public C function with an exception value written + to generated .pxi file without the except clause. [Robby Dermody] + + - __delitem__ method of an extension type with no __setitem__ + did not get called. [Richard Boulton] + + - A spurious Py_INCREF was generated when a return statement + required a type test. [Jonathan Doda] + + - Casting a value to a function pointer and then immediately + calling it generated a cast to a function instead of a cast + to a function pointer. [Simon Burton] + + - Py_TPFLAGS_HAVE_GC was not being set on an extension type that + inherited from an external extension type that used GC but did + not itself have any PyObject* attributes. + [Michael Hordijk] + + - A return statement inside a for statement leaked a reference + to the loop's iterator. + [Jürgen Kartnaller] + + - Full module name now appears in __module__ attribute of classes + and extension types, provided a correct dotted name is used + for the .pyx file. [Giovanni Bajo] + + - Public extension type with no C attributes produced an + invalid .pxi file. [Simon Burton] + + - Using a dict constructor as the second operand of a boolean + expression crashed the Pyrex compiler. + [Stefan Behnel] + + - A C declaration list ending with a comma resulted in invalid + C code being generated. [Alex Coventry] + + - A raw string containing two consecutive backslashes produced + incorrect C code. [Helmut Jarausch] + + - An error is reported if you attempt to declare a special + method of an extension type using 'cdef' instead of 'def'. + [Sam Rushing] + +0.9.3 +----- + +Enhancements: + + - Types defined with a ctypedef in a 'cdef extern from' block + are now referred to by the typedef name in generated C code, + so it is no longer necessary to match the type in the C + header file exactly. + + - Conversion to/from unsigned long now done with + PyLong_AsUnsignedLong and PyLong_FromUnsignedLong. [Dug Song] + + - A struct, union or enum definition in a 'cdef extern from' + block may now be left empty (using 'pass'). This can be useful + if you need to declare a variable of that type, but don't need + to refer to any of its members. + + - More flexible about ordering of qualifiers such as 'long' and + 'unsigned'. ["John (J5) Palmieri"] + + +Bug fixes: + + - Non-interned string literals used in a Python class + definition did not work. [Atsuo Ishimoto, Andreas Kostyrka] + + - Return types of the buffer interface functions for extension + types have been corrected. [Dug Song] + + - Added 'static' to declarations of string literals. [Phil Frost] + + - Float literals are now copied directly to the C code as written, + to avoid problems with loss of precision. [Mario Pernici] + + - Inheriting from an extension type with C methods defined in + another Pyrex module did not work. [Itamar Shtull-Trauring] + +0.9.2.1 +------- + +Bug fixes: + + - Corrected an import statement setup.py, and made it + check for a unix platform in a more reliable way. + +0.9.2 +----- + +Enhancements: + + - Names of Python global variables and attributes are now + interned, and PyObject_GetAttr/SetAttr are used instead + of PyObject_GetAttrString/SetAttrString. String literals + which resemble Python identifiers are also interned. + + - String literals are now converted to Python objects only + once instead of every time they are used. + + - NUL characters are now allowed in Python string literals. + + - Added some missing error checking code to the beginning + of module init functions. It's unlikely the operations + involved would ever fail, but you never know. + +Bug fixes: + + - Corrected some problems introduced by moving the Plex + package. + +0.9.1.1 +------- + +Bug fixes: + + - Corrected a problem in the setup.py (pyrexc script incorrectly + named). + + - Updated the distutils extension to match changes in the + Pyrex compiler calling interface. + + - Doing 'make clean' in Demos/callback was removing a little too + much (that's why cheesefinder.c kept disappearing). + +0.9.1 +----- + +Enhancements: + + - A C method can now call an inherited C method by the usual + Python technique. [Jiba] + + - The __modname__ of a Python class is now set correctly. [Paul Prescod] + + - A MANIFEST.in file has been added to the distribution to + facilitate building rpms. [contributed by Konrad Hinsen] + +Bug fixes: + + - Conditional code now generated to allow for the renaming of LONG_LONG + to PY_LONG_LONG that occurred between Python 2.2 and 2.3. + + - Header files referenced in cimported modules were not being included. + [Tom Popovich] + + - References to C functions and variables in a cimported module were + not being recognised if made from within a local scope. [Tom Popovich] + + - Spurious declarations in code generated for a "finally" block. + [Brandon Long] + + - Attempting to return a value from a __contains__ method didn't work. + [Andreas Kostyrka] + + - Incorrect code generated for an extension type with C methods + inheriting from a base type with no C methods. [Robin Becker] + + - Failure to report an error if a C method was defined in the + implementation part of an extension type that was not declared + in the corresponding definition part. Documentation also updated + to explain that this is necessary. [Jiba] + + - Made it an error to forward-declare an extension type with + a different base class specification from its subsequent + definition. [Jiba] + + - C attributes of an extension type were not being propagated + through more than one level of inheritance. [Jiba] + + - If a garbage collection occurred early enough in the __new__ + method of an extension type with Python-valued C attributes, + a crash could occur in its tp_traverse function. + [reported by Jiba, fix suggested by Paul Prescod] + + - An empty vtable struct is no longer generated for extension + types with no C methods. [Robin Becker] + + - Memory was leaked in the sq_item function of an extension + type with a __getitem__ method. [Atsuo Ishimoto] + + - Code generated to work around a bug in some versions of Python + 2.2 which fails to initialise the tp_free slot correctly in + some circumstances. [Matthias Baas] + + - Compiler crash when defining an extension type with a base + class specified by a dotted name. [Alain Pointdexter] + + - Referencing an extension type defined in a cimported module + at run time did not work correctly. [Alain Pointdexter] + + - Incorrect object struct code generated for an extension type + whose base class was defined in a .pxd file. [Alain Pointdexter] + + - Redeclaring a type that wasn't previously an extension type + as an extension type caused a compiler crash. [Scott Robinson] + + - Incorrect code was generated for return statements in a + special method with no return value. [Gary Bishop] + + - Single-line def statement did not work. [Francois Pinard] + +Modifications: + + - Only the last pathname component of the .pyx file is reported in + backtraces now. [Bryan Weingarten] + + - Documentation corrected to remove the erroneous statement that + extension classes can have a __del__ method. [Bryan Weingarten] + + - Note added to documentation explaining that it is not possible + for an extension type's __new__ method to explicitly call the + inherited __new__ method. + + - The version of Plex included with Pyrex is now installed + as a subpackage of the Pyrex package, rather than as a + top-level package, so as not to interfere with any other + version of Plex the user may have installed. + +0.9 +--- + +New features: + + - Extension types can have properties. See the new "Properties" + section in the "Extension Types" page. + + - An extension type can inherit from a builtin type or another + extension type. See "Subclassing" in the "Extension Types" page. + + - Extension types can have C methods, which can be overridden + in derived extension types. See "C Methods" in the "Extension Types" + page. + +Enhancements: + + - Conversion is now performed between C long longs and Python + long integers without chopping to the size of a C long. + Also the Python PY_LONG_LONG type is now used for long longs + for greater portability. + +Bug fixes: + + - Names were sometimes being generated that were insufficiently + unique in the presence of cimported declarations. + + - Changed the way the included filename table is declared from + char *[] to char **, to stop MSVC from complaining about it + having an unknown size. [Alexander A Naanou] + + - Second argument of assert statement was not being coerced + to a Python value. [Francois Pinard] + + - Return statement without value wasn't accepted in some + extension type special methods when it should have been. + [Francois Pinard] + + - Attempting to call a non-function C value crashed the + compiler. [John J Lee] + + - Functions declared as "except *" were not returning exceptions. + [John J Lee] + + - A syntax warning from Plex about assignment to None has + been eliminated. [Gordon Williams] + + - Public function declaration with empty argument list was + producing (void) in .pxi file. [Michael P. Dubner] + + - Incorrect error signalling code was being generated in the + __hash__ special method of an extension type. + + +0.8.1 +----- + +Bug fixes: + + - Names of structs, unions and enums in external header + files were getting mangled when they shouldn't have been. + [Norman Shelley] + + - Modified distutils extension so that it will stop before + compiling the C file if the Pyrex compiler reports errors. + [John J Lee] + + +0.8 +--- + +New features: + + - INCOMPATIBLE CHANGE: The type object of an external extension + type is now imported at run time using the Python import + mechanism. To make this possible, an 'extern' extension type + declaration must DECLARE THE MODULE from which the extension + type originates. See the new version of the "Extension Types" + documentation for details. + + This change was made to eliminate the need for Pyrex to be + told the C name of the type object, or for the Pyrex module + to be linked against the object code providing the type object. + + You will have to update any existing external extension type + declarations that you are using. I'm sorry about that, but it + was too hard to support both the old and new ways. + + - Compile-time importing: A Pyrex module can now import declarations + from another Pyrex module using the new 'cimport' statement. See + the new section on "Sharing Declarations Between Pyrex Modules" in + the documentation. + +Minor improvements: + + - An error is reported if you declare a struct, union or + extension type using 'cdef' in one place and 'ctypedef' + in another. + + - Struct, union and extension types can only be forward- + declared using 'cdef', not 'ctypedef' (otherwise invalid + C code would be generated). + + - The 'global' statement can be used at the module level to + declare that a name is a module-level name rather than a + builtin. This can be used to access module attributes such + as __name__ that would otherwise be assumed to be builtins. + [Pat Maupin] + + - The 'assert' statement now accepts a second argument. + [Francois Pinard] + +Bug fixes: + + - When using Python 2.3, "True" or "False" could sometimes + turn up in generated code instead of "1" or "0". [Adam Hixson] + + - Function return value not always converted to or from a + Python object when it should have been. + + - Certain kinds of error in a function call expression + could crash the compiler. ["Edward C. Jones"] + + - Fixed memory leak in functions with * or ** args. [Alexander A Naanou] + + +0.7.1 +----- + +Bug fixes: + + - Calling a function declared as returning an extension + type could crash the compiler. + + - A function call with type errors in the argument list + could crash the compiler. + + - An 'else' clause on a for-from statement could crash + the compiler. + + - Incorrect casting code was generated when a generic + object argument of a special method was declared as + being of an extension type. [Phillip J. Eby] + + - A blank line that couldn't be interpreted wholly as + a valid indentation sequence caused a syntax error. + In particular, a formfeed character on an otherwise + blank line wasn't accepted. [Francois Pinard] + + - Parallel assignments were incorrectly optimised. + + - A bare tuple constructor with an extra comma at the + end of a line caused a syntax error. + +0.7 +--- + +New features: + + - Attributes of extension types can be exposed to Python + code, either read/write or read-only. + + - Different internal and external names can be specified + for C entities. + + - None is a compile-time constant, and more efficient code + is generated to reference it. + + - Command line options for specifying directories to + search for include files. + +Enhancements: + + - More efficient code is generated for access to Python + valued C attributes of extension types. + + - Cosmetic code improvement: Less casting back and forth + between extension types and PyObject * when referencing + C members of the object struct. + + - C arguments and variables declared as an extension type + can take the value None. + + - Form feed characters are accepted as whitespace. + + - Function names in tracebacks are qualified with + module name and class name. + +Bug fixes: + + - A sufficiently complex expression in a boolean context + could cause code to be generated twice for the same + subexpression. + + - Incorrect casting code was generated when passing an + extension type to a function expecting a generic Python + object. + + - Executable statements are now disallowed inside a + cdef class block (previously they silently caused + crazy C code to be generated). + + - Tracebacks should now report the correct filename for + functions defined in files included with the 'include' + statement. + + - The documentation incorrectly claimed that an extension + type can't have a __del__ method. In fact, it can, and + it behaves as expected. + + +0.6.1 +----- + +Bug fixes: + + - Fixed broken distutils extension. + + + +0.6 +--- + +New features: + + - Command line options for reporting version number, + requesting a listing file and specifying the name of + the generated C file. + + - An 'include' statement allows inclusion of declarations + from other Pyrex source files. + + - If there are any public declarations, a Pyrex include + file is generated (as well as a .h file) containing + declarations for them. + + - Extension types can be declared public, so their C + attributes are visible to other Pyrex and C code. + + - Try-except statements can now have an 'else' clause. + [Francois Pinard] + + - Multiple simple statements can be placed on one line + separated by semicolons. + + - A suite consisting of a simple statement list can now + be placed on the same line after the colon in most + cases. [Francois Pinard] + + - The automatic coercion of a C string to a C char has + been removed (it proved to be too error-prone). + Instead, there is a new form of literal for C + character constants: c'X' + + - The __get__ special method (used by descriptor objects) + now allows for the possibility of the 2nd or 3rd + arguments being NULL. Also the __set__ method has been + split into two methods, __set__ and __delete__. + [Phillip J. Eby] + +Bug fixes: + + - Values unpacked into a non-Python destination variable + were not being converted before assignment. [Gareth Watts] + + - Hex constants greater than 0x7fffffff caused compiler + to crash. [Gareth Watts] + + - Type slots are no longer statically initialised with + extern function pointers, to avoid problems with + some compilers. The hack in the distutils extension + to work around this by compiling as C++ has been + disabled. [Phillip J. Eby] + + - Fixed several more instances of the error-reporting + routine being called with arguments in the wrong + order. Hoping I've *finally* got all of them now... + + - Nested for-from loops used the same control variable. + [Sebastien de Menten] + + - Fixed some other error message related bugs. [Francois Pinard] + + - Assigning to slice didn't work. [Francois Pinard] + + - Temp variables were being declared as extension + types and then being assigned PyObject *'s. All + Python temp vars are now declared as PyObject *. + [Francois Pinard] + +0.5 +--- + +Bug fixes: + + - Algorithm for allocating temp variables redesigned + to fix various errors concerning temp + variable re-use. [Mark Rowe] + + - Memory leak occured sometimes when an implicit + type test was applied to the result of an + expression. [Christoph Wiedemann] + + - __set__ method of extension types had wrong + signature. [Josh Littlefield] + +0.4.6 +----- + +Bug fixes: + + - Indexing multi-dimensional C arrays didn't + work. [Gary Dietachmayer] + + +0.4.5 +----- + +New features: + + - There is now a 'public' declaration for + making Pyrex-defined variables and functions + available to external C code. A .h file is + also generated if there are any public + declarations. + +Enhancements: + + - Defining __len__/__getitem__ methods in an + extension class fills sq_length/sq_item slots + as well as mp_length/mp_subscript. [Matthias Baas] + + - The Distutils extension now allows .c files + to be incorporated along with .pyx files. + [Modification to Distutils extension contributed + by Darrell Gallion] + +Bug fixes: + + - Float literals without a decimal point + work again now. [Mike Rovner, Peter Lepage] + + - Compiler crashed if exception value didn't + match function return type. [Michael JasonSmith] + + - The setup.py file should now install the + Lexicon.pickle file in the right place. + [Patch supplied by David M. Cooke] + + - Compiler crashed when compiling a C function that + returned an extension type. + [David M. Cooke] + + - Anonymous enum types did not have C code + suppressed inside an extern-from block. [Matthew Mueller] + + +0.4.4 +----- + +Enhancements: + + - Tracebacks now extend into Pyrex function + calls and show line numbers in the Pyrex + source file. + + - Syntax for float literals made more lenient + (no longer requires digits both before and + after the point). [Peter Lepage] + + - Method calls can be made on string literals + (e.g. ",".join(x)). [Pedro Rodriguez] + +Bug fixes: + + - Incorrect refcount code generated when a + Python function needing argument type tests + had local Python variables. [Matthias Baas] + + - 'self' parameter of __getitem__ method of + extension type had wrong implicit type. [Peter Lepage] + + - Repaired breakage introduced by trying to + allow an empty parameter list to be written + as (void). No longer attempting to allow + this (too hard to parse correctly). [Peter Lepage] + + - Found bug in Plex 1.1.2 which was the *real* + cause of the two-newlines-in-a-row problem. + Removed the Opt(Eol)+Str("\n") hacks in + the scanner which were working around this + before. [Pedro Rodriguez] + + - __call__ special method of extension types + had wrong signature. [Peter Lepage] + + +0.4.3 +----- + +New language features: + + - For-from loop for iterating over integer + ranges, using pure C loop where possible. + +Enhancements: + + - sizeof() can now be applied to types as + well as variables. + + - Improved handling of forward-declared + extension types. + +Bug fixes: + + - Two newlines in a row in a triple quoted + string caused a parse error on some + platforms. [Matthias Baas] + + - Fixed problem with break and continue in + the else-clause of a loop. + + +0.4.2 +----- + +New language features: + + - C functions can be declared as having an + exception return value, which is checked + whenever the function is called. If an + exception is detected inside a C function + for which no exception value is declared, + a warning message is printed and the + exception is cleared. + + - Cascaded assignments (i.e. a = b = c + are now supported. + + - Anonymous enum declarations are allowed, + for when you just want to declare constants. + + - The C types "long long" and "long double" + are now understood. Also, "int" is optional + after "short" or "long". + +Enhancements: + + - A * argument in a function call can now be + any sequence, not just a tuple. + + - A C char* or char[] will be turned into + a char by taking its first character if + used in a context where a char is required, + thus allowing a string literal to be used as + a char literal. + + - C string * C int or vice versa is now + interpreted as Python string replication. + + - Function arguments are checked for void or + incomplete type. + +Bug fixes: + + - Non-external extension types show up in the + module dict once more (this got broken in + 0.4.1). + + - A spurious decref has been removed from the + runtime support code for the "import" statement. + Hopefully this will prevent the crashes some + people have been experiencing when importing + builtin modules. [Mathew Yeates] + +0.4.1 +----- + +New language features: + + - "ctypedef struct/union/enum/class" statements + added, for use in extern-from blocks when a + header file uses a ctypedef to declare a + tagless struct, union or enum type. + + - "pass" allowed in an extern-from block. + + - "cdef extern from *" for when you don't want + to specify an include file name. + + - Argument names may be omitted in function + signatures when they're not needed. + + - New reserved word NULL for the null C pointer. + +Compiler enhancements: + + - Lexicon is now picked in binary format, so + startup should be much faster on slower + machines. + + - If Pyrex decides to rebuild the lexicon and + then finds that it can't write a pickle file, + it now prints a warning and carries on + instead of crashing. + + - Chat about hash codes and lexicon pickling + now turned off by default except when creating + a new lexicon (which ought never happen now + unless you change the scanner). + +Bug fixes: + + - Modified the runtime support code for "import" + statements, hopefully fixing problem with using + a Pyrex module in conjunction with py2exe. + + - DL_EXPORT now used in both the prototype and + definition of the module init function. + + - Exception state is now saved and restored around + calls to an extension type __dealloc__ method, + to avoid screwing up if the object is deallocated + while an exception is being propagated. + + - Making an attribute reference to a method of + an extension type caused a compiler crash. + + - Doc string in new-style class definition + caused a run-time error. + + - Insufficient parentheses were put around C type + casts. + + - Constructors for extension types are now read-only + C global variables instead of entries in the + module dict. This change was needed to prevent + Numeric from blowing up due to touching its + typeobject before import_numeric() could be called. + +0.4 +--- + +New features: + + - "cdef extern from" statement allows inclusion + of C header files to be specified, solving + a number of problems including: + - Clashes between Pyrex and C declarations, + due to "const" and other reasons + - Windows-specific features required in + function declarations + - Helping deal with types such as "size_t" + - Helping deal with functions defined as + macros + + - Access to internals of pre-existing extension + types is now possible by placing an extension + type declaration inside a "cdef extern from" + block. + +Bug fixes: + + - Error not reported properly when passing + wrong number of args to certain special + methods of extension types. [Mitch Chapman] + + - Compile-time crash when defining an extension + type with a __hash__ method. + +Minor enhancements: + + - Hashing of the scanner source file made more + platform-independent, making spurious regeneration + of the pickle less likely. + + +0.3.4 +----- + +Bug fixes: + + - Runtime crash when using * or ** args in + a method of an extension type fixed. [Matthew Mueller] + + - Compiler crash when using default argument + values in a method of a Python class. [Mike Rovner] + +Enhancements: + + - Type slots filled with functions from outside + the extension module are now initialised dynamically, + which should eliminate at least some of the + "initialiser is not constant" problems experienced + on Windows. [Marek Baczek] + + - On Windows, __declspec(dllexport) is now used for + the module init func declaration (or should be -- + I haven't tested this). [Marek Baczek] + + - The compiler shouldn't attempt to rewrite the + Lexicon.pickle file unless the source has been + changed (hashing is used now instead of comparing + timestamps). So there should be no problem any more + with installing Pyrex read-only. + +0.3.3 +----- + +Bug fixes: + +* A void * can be assigned from any other +pointer type. +* File names in error messages no longer +quoted (this was apparently confusing some +editors). [Matthew Mueller] + +* Reference to a struct member which is an +array is coerced to a pointer. [Matthew Mueller] + +* Default argument values did not work +in methods of an extension type. [Matthew Mueller] + +* Single or double quote characters in a +triple-quoted string didn't work. [Matthew Mueller] + +* Using *args in a function definition +sometimes caused a crash at runtime. [Matthew Mueller] + +* A hack is included which tries to make +functions in Python.h which use 'const' +accessible from Pyrex. But it doesn't +work on all platforms. Thinking about a +better solution. + + +New features: + +* Comment containing Pyrex version number +and date/time at top of generated C file. [Matthias Baas] + + +0.3.2 +----- + +Bug fixes: + +* The & operator works again. [Matthias Baas] + +* The & operator had incorrect precedence. + +* "SystemError: 'finally' pops bad exception" +under some circumstances when raising an +exception. [Matthias Baas] + +* Calling a Python function sometimes leaked +a reference. + +* Crash under some circumstances when casting +a Python object reference to a C pointer type. +[Michael JasonSmith] + +* Crash when redeclaring a function. [Matthias Baas] + +* Crash when using a string constant inside +a Python class definition. [Mike Rovner] + +* 2-element slice indexing expressions. [Mike Rovner] + +* Crash when encountering mixed tabs and +spaces. [Mike Rovner] + +New features: + +* A wider variety of constant expressions is +now accepted for enum values, array +dimensions, etc. [Mike Rovner] + + +0.3.1 +----- + +New features: + +* More special methods for extension types: +__delitem__, __delslice__, __getattr__, +__setattr__, __delattr__ + +* Module-level variable of a Python object type +declared with 'cdef' is private to the module, and +held in a C variable instead of the module dict. + +* External C functions with variable argument lists +can be declared and called. + +* Pyrex-defined Python functions can have default +argument values and * and ** arguments, and can be +called with keyword arguments. + +* Pointer-to-function types can be declared. + +* Pyrex now supports a declaration syntax that +C doesn't! Example: + + cdef (int (*)()) foo() # function returning a function ptr + +* There is now a ctypedef statement. + +* Extension types can now be forward-declared. + +* All permutations of (non-Unicode) string literals +and escape codes should work now. + +* Hex and octal integer literals. + +* Imaginary number literals. + +* Docstrings are now supported. + +Bug fixes: + +* Type tests are performed when using a Python object +in a context requiring a particular extension type. + +* Module-level variable holding the type object +of an extension type had incorrect type. + +0.3 +--- + +New features: + +* Extension types! Yay! + +0.2.2 +----- + +Bug fixes: + +* Fixed error message generation again after a previous +bug was accidentally re-indroduced. + +* Removed the declaration of isspace() from the code +generated for print statement support (it's not needed +and was conflicting with the system-supplied one on +some platforms). + +0.2 +--- + +New features: + +* Executable statements are now allowed at the +top level of a module. + +* Python class definitions are now supported, with +the following limitations: + + - Class definitions are only allowed at the top + level of a module, not inside a control structure + or function or another class definition. + + - Assigning a Pyrex-defined Python function to a + class attribute outside of the class definition + will not create a method (because it's not an + interpreted Python function and therefore + won't trigger the bound-method creation magic). + + - The __metaclass__ mechanism and the creation of + new-style classes is not (yet) supported. + +* Casting between Python and non-Python types is +better supported. + +Bug fixes: + +* Fixed bug preventing for-loops from working. + + +0.1.1 +----- + +* I've discovered a flaw in my algorithm for releasing +temp variables. Fixing this properly will require some +extensive reworking; I've put in a hack in the meantime +which should work at the cost of using more temp variables +than are strictly necessary. + +* Fixed bug preventing access to builtin names from +working. This should also have fixed the import +statement, but I haven't tested it. + +* Fixed some errors in __Pyx_GetExcValue. + +* Fixed bug causing boolean expressions to malfunction +sometimes. diff --git a/debian/pyrex/pyrex-0.9.9/CHECKLIST.txt b/debian/pyrex/pyrex-0.9.9/CHECKLIST.txt new file mode 100644 index 00000000..c35c0f77 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/CHECKLIST.txt @@ -0,0 +1,24 @@ +Release Checklist +================= + +* Update CHANGES.txt + +* Ensure all tests pass + +* cd Demos; make test + +* make test_setup + +* Check version number in Makefile + +* Update news in web page + +* Commit changes + +* Tag release + +* cd ..; make tar + +* make upload + +* make push diff --git a/debian/pyrex/pyrex-0.9.9/Demos/Makefile b/debian/pyrex/pyrex-0.9.9/Demos/Makefile new file mode 100644 index 00000000..e70687f4 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/Makefile @@ -0,0 +1,15 @@ +all: + python Setup.py build_ext --inplace + +test: all + python run_primes.py 20 + python run_numeric_demo.py + python run_spam.py + cd callback; $(MAKE) test + +clean: + @echo Cleaning Demos + @rm -f *.c *.o *.so *~ core + @rm -rf build + @cd callback; $(MAKE) clean + @cd embed; $(MAKE) clean diff --git a/debian/pyrex/pyrex-0.9.9/Demos/Makefile.nodistutils b/debian/pyrex/pyrex-0.9.9/Demos/Makefile.nodistutils new file mode 100644 index 00000000..d648f849 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/Makefile.nodistutils @@ -0,0 +1,21 @@ +PYHOME = $(HOME)/pkg/python/version +PYINCLUDE = \ + -I$(PYHOME)/include/python2.2 \ + -I$(PYHOME)/$(ARCH)/include/python2.2 + +%.c: %.pyx + ../bin/pyrexc $< + +%.o: %.c + gcc -c -fPIC $(PYINCLUDE) $< + +%.so: %.o + gcc -shared $< -lm -o $@ + +all: primes.so spam.so numeric_demo.so + +clean: + @echo Cleaning Demos + @rm -f *.c *.o *.so *~ core core.* + @cd callback; $(MAKE) clean + @cd embed; $(MAKE) clean diff --git a/debian/pyrex/pyrex-0.9.9/Demos/Setup.py b/debian/pyrex/pyrex-0.9.9/Demos/Setup.py new file mode 100644 index 00000000..e220d81b --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/Setup.py @@ -0,0 +1,14 @@ +from distutils.core import setup +#from distutils.extension import Extension +from Pyrex.Distutils.extension import Extension +from Pyrex.Distutils import build_ext + +setup( + name = 'Demos', + ext_modules=[ + Extension("primes", ["primes.pyx"]), + Extension("spam", ["spam.pyx"]), + Extension("numeric_demo", ["numeric_demo.pyx"]), + ], + cmdclass = {'build_ext': build_ext} +) diff --git a/debian/pyrex/pyrex-0.9.9/Demos/callback/Makefile b/debian/pyrex/pyrex-0.9.9/Demos/callback/Makefile new file mode 100644 index 00000000..890bc808 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/callback/Makefile @@ -0,0 +1,10 @@ +all: + python Setup.py build_ext --inplace + +test: all + python run_cheese.py + +clean: + @echo Cleaning Demos/callback + @rm -f cheese.c *.o *.so *~ core + @rm -rf build diff --git a/debian/pyrex/pyrex-0.9.9/Demos/callback/Makefile.nodistutils b/debian/pyrex/pyrex-0.9.9/Demos/callback/Makefile.nodistutils new file mode 100644 index 00000000..012c1a86 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/callback/Makefile.nodistutils @@ -0,0 +1,19 @@ +PYHOME = $(HOME)/pkg/python/version +PYINCLUDE = \ + -I$(PYHOME)/include/python2.2 \ + -I$(PYHOME)/$(ARCH)/include/python2.2 + +%.c: %.pyx + ../../bin/pyrexc $< + +%.o: %.c + gcc -c -fPIC $(PYINCLUDE) $< + +%.so: %.o + gcc -shared $< -lm -o $@ + +all: cheese.so + +clean: + @echo Cleaning Demos/callback + @rm -f *.c *.o *.so *~ core core.* diff --git a/debian/pyrex/pyrex-0.9.9/Demos/callback/README.txt b/debian/pyrex/pyrex-0.9.9/Demos/callback/README.txt new file mode 100644 index 00000000..fa3b871c --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/callback/README.txt @@ -0,0 +1 @@ +This example demonstrates how you can wrap a C API that has a callback interface, so that you can pass Python functions to it as callbacks. The files cheesefinder.h and cheesefinder.c represent the C library to be wrapped. The file cheese.pyx is the Pyrex module which wraps it. The file run_cheese.py demonstrates how to call the wrapper. \ No newline at end of file diff --git a/debian/pyrex/pyrex-0.9.9/Demos/callback/Setup.py b/debian/pyrex/pyrex-0.9.9/Demos/callback/Setup.py new file mode 100644 index 00000000..5e48206a --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/callback/Setup.py @@ -0,0 +1,11 @@ +from distutils.core import setup +from distutils.extension import Extension +from Pyrex.Distutils import build_ext + +setup( + name = 'callback', + ext_modules=[ + Extension("cheese", ["cheese.pyx", "cheesefinder.c"]), + ], + cmdclass = {'build_ext': build_ext} +) diff --git a/debian/pyrex/pyrex-0.9.9/Demos/callback/cheese.pyx b/debian/pyrex/pyrex-0.9.9/Demos/callback/cheese.pyx new file mode 100644 index 00000000..db0fc082 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/callback/cheese.pyx @@ -0,0 +1,13 @@ +# +# Pyrex wrapper for the cheesefinder API +# + +cdef extern from "cheesefinder.h": + ctypedef void (*cheesefunc)(char *name, void *user_data) + void find_cheeses(cheesefunc user_func, void *user_data) + +def find(f): + find_cheeses(callback, f) + +cdef void callback(char *name, void *f): + (f)(name) diff --git a/debian/pyrex/pyrex-0.9.9/Demos/callback/cheesefinder.c b/debian/pyrex/pyrex-0.9.9/Demos/callback/cheesefinder.c new file mode 100644 index 00000000..ab41853b --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/callback/cheesefinder.c @@ -0,0 +1,21 @@ +/* + * An example of a C API that provides a callback mechanism. + */ + +#include "cheesefinder.h" + +static char *cheeses[] = { + "cheddar", + "camembert", + "that runny one", + 0 +}; + +void find_cheeses(cheesefunc user_func, void *user_data) { + char **p = cheeses; + while (*p) { + user_func(*p, user_data); + ++p; + } +} + diff --git a/debian/pyrex/pyrex-0.9.9/Demos/callback/cheesefinder.h b/debian/pyrex/pyrex-0.9.9/Demos/callback/cheesefinder.h new file mode 100644 index 00000000..3c31bdc0 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/callback/cheesefinder.h @@ -0,0 +1 @@ +typedef void (*cheesefunc)(char *name, void *user_data); void find_cheeses(cheesefunc user_func, void *user_data); \ No newline at end of file diff --git a/debian/pyrex/pyrex-0.9.9/Demos/callback/run_cheese.py b/debian/pyrex/pyrex-0.9.9/Demos/callback/run_cheese.py new file mode 100644 index 00000000..65fd431b --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/callback/run_cheese.py @@ -0,0 +1,7 @@ +import cheese + +def report_cheese(name): + print "Found cheese:", name + +cheese.find(report_cheese) + diff --git a/debian/pyrex/pyrex-0.9.9/Demos/embed/Makefile b/debian/pyrex/pyrex-0.9.9/Demos/embed/Makefile new file mode 120000 index 00000000..a89ef208 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/embed/Makefile @@ -0,0 +1 @@ +Makefile.unix \ No newline at end of file diff --git a/debian/pyrex/pyrex-0.9.9/Demos/embed/Makefile.msc b/debian/pyrex/pyrex-0.9.9/Demos/embed/Makefile.msc new file mode 100644 index 00000000..37114c73 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/embed/Makefile.msc @@ -0,0 +1,35 @@ +# Makefile for Microsoft C Compiler, building a DLL +PYVERSION = 2.2 +PYHOME = \Python$(PYVERSION:.=) +PYINCLUDE = -I$(PYHOME)\include +PYLIB = /LIBPATH:$(PYHOME)\libs + +CFLAGS = $(PYINCLUDE) /Ox /W3 /GX -nologo +.SUFFIXES: .exe .dll .obj .c .cpp .pyx + +.pyx.c: + $(PYHOME)\Python.exe ../../pyrexc.py $< + +all: main.exe + +clean: + del /Q/F *.obj embedded.h embedded.c main.exe embedded.dll embedded.lib embedded.exp + +# When linking the DLL we must explicitly list all of the exports +# There doesn't seem to be an easy way to get DL_EXPORT to have the correct definition +# to do the export for us without breaking the importing of symbols from the core +# python library. +embedded.dll: embedded.obj + link /nologo /DLL /INCREMENTAL:NO $(PYLIB) $** /IMPLIB:$*.lib /DEF:<< /OUT:$*.dll +EXPORTS initembedded +EXPORTS spam +<< + +main.exe: main.obj embedded.lib + link /nologo $** $(PYLIB) /OUT:main.exe + +embedded.h: embedded.c +main.obj: embedded.h +embedded.obj: embedded.c + $(CC) /MD $(CFLAGS) -c $** +embedded.lib: embedded.dll diff --git a/debian/pyrex/pyrex-0.9.9/Demos/embed/Makefile.msc.static b/debian/pyrex/pyrex-0.9.9/Demos/embed/Makefile.msc.static new file mode 100644 index 00000000..14e1080c --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/embed/Makefile.msc.static @@ -0,0 +1 @@ +# Makefile for Microsoft compiler statically linking PYVERSION = 2.2 PYHOME = \Python$(PYVERSION:.=) PYINCLUDE = -I$(PYHOME)\include PYLIB = /LIBPATH:$(PYHOME)\libs python22.lib CFLAGS = $(PYINCLUDE) /Ox /W3 /GX -nologo .SUFFIXES: .exe .dll .obj .c .cpp .pyx .pyx.c: $(PYHOME)\Python.exe ../../pyrexc.py $< all: main.exe clean: -del /Q/F *.obj embedded.h embedded.c main.exe main.exe: main.obj embedded.obj link /nologo $** $(PYLIB) /OUT:main.exe embedded.h: embedded.c main.obj: embedded.h \ No newline at end of file diff --git a/debian/pyrex/pyrex-0.9.9/Demos/embed/Makefile.unix b/debian/pyrex/pyrex-0.9.9/Demos/embed/Makefile.unix new file mode 100644 index 00000000..c8c7dbeb --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/embed/Makefile.unix @@ -0,0 +1,30 @@ +PYVERSION = 2.2 +PYHOME = $(HOME)/pkg/python/$(PYVERSION) +PYARCH = $(PYHOME)/$(ARCH) +PYINCLUDE = \ + -I$(PYHOME)/include/python$(PYVERSION) \ + -I$(PYARCH)/include/python$(PYVERSION) +PYLIB = -L$(PYARCH)/lib/python$(PYVERSION)/config \ + -lpython$(PYVERSION) \ + -ldl -lpthread -lutil -lm + +%.c: %.pyx + ../../bin/pyrexc $< + +%.o: %.c + gcc -c -fPIC $(PYINCLUDE) $< + +#%.so: %.o +# gcc -shared $< -lm -o $@ + +all: main + +main: main.o embedded.o + gcc main.o embedded.o $(PYLIB) -o main + +clean: + @echo Cleaning Demos/embed + @rm -f *~ *.o *.so core core.* embedded.h embedded.c main + +embedded.h: embedded.c +main.o: embedded.h diff --git a/debian/pyrex/pyrex-0.9.9/Demos/embed/README b/debian/pyrex/pyrex-0.9.9/Demos/embed/README new file mode 100644 index 00000000..55283ac3 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/embed/README @@ -0,0 +1 @@ +This example demonstrates how Pyrex-generated code can be called directly from a main program written in C. In this example, the module's initialisation function (called "initembedded", since the module is called "embedded") is called explicitly. This is necessary because the module is not being imported using the normal Python import mechanism. The Windows makefiles were contributed by Duncan Booth . \ No newline at end of file diff --git a/debian/pyrex/pyrex-0.9.9/Demos/embed/embedded.pyx b/debian/pyrex/pyrex-0.9.9/Demos/embed/embedded.pyx new file mode 100644 index 00000000..90d62f67 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/embed/embedded.pyx @@ -0,0 +1,5 @@ +cdef public void spam(): + praise() + +def praise(): + print "Spam, glorious spam!" diff --git a/debian/pyrex/pyrex-0.9.9/Demos/embed/main.c b/debian/pyrex/pyrex-0.9.9/Demos/embed/main.c new file mode 100644 index 00000000..3e089abc --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/embed/main.c @@ -0,0 +1,9 @@ +#include "Python.h" +#include "embedded.h" + +int main(int argc, char *argv) { + Py_Initialize(); + initembedded(); + spam(); + Py_Finalize(); +} diff --git a/debian/pyrex/pyrex-0.9.9/Demos/numeric_demo.pyx b/debian/pyrex/pyrex-0.9.9/Demos/numeric_demo.pyx new file mode 100644 index 00000000..3a20fd90 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/numeric_demo.pyx @@ -0,0 +1,39 @@ +# +# This example demonstrates how to access the internals +# of a Numeric array object. +# + +cdef extern from "Numeric/arrayobject.h": + + struct PyArray_Descr: + int type_num, elsize + char type + + ctypedef class Numeric.ArrayType [object PyArrayObject]: + cdef char *data + cdef int nd + cdef int *dimensions, *strides + cdef object base + cdef PyArray_Descr *descr + cdef int flags + +def print_2d_array(ArrayType a): + print "Type:", chr(a.descr.type) + if chr(a.descr.type) <> "f": + raise TypeError("Float array required") + if a.nd <> 2: + raise ValueError("2 dimensional array required") + cdef int nrows, ncols + cdef float *elems, x + nrows = a.dimensions[0] + ncols = a.dimensions[1] + elems = a.data + hyphen = "-" + divider = ("+" + 10 * hyphen) * ncols + "+" + print divider + for row in range(nrows): + for col in range(ncols): + x = elems[row * ncols + col] + print "| %8f" % x, + print "|" + print divider diff --git a/debian/pyrex/pyrex-0.9.9/Demos/primes.pyx b/debian/pyrex/pyrex-0.9.9/Demos/primes.pyx new file mode 100644 index 00000000..dfbaae48 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/primes.pyx @@ -0,0 +1,18 @@ +def primes(int kmax): + cdef int n, k, i + cdef int p[1000] + result = [] + if kmax > 1000: + kmax = 1000 + k = 0 + n = 2 + while k < kmax: + i = 0 + while i < k and n % p[i] <> 0: + i = i + 1 + if i == k: + p[k] = n + k = k + 1 + result.append(n) + n = n + 1 + return result diff --git a/debian/pyrex/pyrex-0.9.9/Demos/pyprimes.py b/debian/pyrex/pyrex-0.9.9/Demos/pyprimes.py new file mode 100644 index 00000000..edcce852 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/pyprimes.py @@ -0,0 +1,13 @@ +def primes(kmax): + p = [] + k = 0 + n = 2 + while k < kmax: + i = 0 + while i < k and n % p[i] <> 0: + i = i + 1 + if i == k: + p.append(n) + k = k + 1 + n = n + 1 + return p diff --git a/debian/pyrex/pyrex-0.9.9/Demos/run_numeric_demo.py b/debian/pyrex/pyrex-0.9.9/Demos/run_numeric_demo.py new file mode 100644 index 00000000..803442d5 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/run_numeric_demo.py @@ -0,0 +1,5 @@ +import Numeric +import numeric_demo + +a = Numeric.array([[1.0, 3.5, 8.4], [2.3, 6.6, 4.1]], "f") +numeric_demo.print_2d_array(a) diff --git a/debian/pyrex/pyrex-0.9.9/Demos/run_primes.py b/debian/pyrex/pyrex-0.9.9/Demos/run_primes.py new file mode 100644 index 00000000..487767d4 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/run_primes.py @@ -0,0 +1,7 @@ +import sys +from primes import primes +if len(sys.argv) >= 2: + n = int(sys.argv[1]) +else: + n = 1000 +print primes(n) diff --git a/debian/pyrex/pyrex-0.9.9/Demos/run_spam.py b/debian/pyrex/pyrex-0.9.9/Demos/run_spam.py new file mode 100644 index 00000000..e1c1e155 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/run_spam.py @@ -0,0 +1,8 @@ +from spam import Spam + +s = Spam() +print "Created:", s +s.set_amount(42) +print "Amount =", s.get_amount() +s.describe() +s = None diff --git a/debian/pyrex/pyrex-0.9.9/Demos/spam.pyx b/debian/pyrex/pyrex-0.9.9/Demos/spam.pyx new file mode 100644 index 00000000..ab773378 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Demos/spam.pyx @@ -0,0 +1,22 @@ +# +# Example of an extension type. +# + +cdef class Spam: + + cdef int amount + + def __cinit__(self): + self.amount = 0 + + def __dealloc__(self): + print self.amount, "tons of spam is history." + + def get_amount(self): + return self.amount + + def set_amount(self, new_amount): + self.amount = new_amount + + def describe(self): + print self.amount, "tons of spam!" diff --git a/debian/pyrex/pyrex-0.9.9/Doc/About.html b/debian/pyrex/pyrex-0.9.9/Doc/About.html new file mode 100644 index 00000000..373625aa --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Doc/About.html @@ -0,0 +1,149 @@ + + + + + About Pyrex + + + +
+

+ +
Pyrex

+ +
A language for writing Python extension modules +
+ +

+What is Pyrex all about?

+Pyrex is a language specially designed for writing Python extension modules. +It's designed to bridge the gap between the nice, high-level, easy-to-use +world of Python and the messy, low-level world of C. +

You may be wondering why anyone would want a special language for this. +Python is really easy to extend using C or C++, isn't it? Why not just +write your extension modules in one of those languages? +

Well, if you've ever written an extension module for Python, you'll +know that things are not as easy as all that. First of all, there is a +fair bit of boilerplate code to write before you can even get off the ground. +Then you're faced with the problem of converting between Python and C data +types. For the basic types such as numbers and strings this is not too +bad, but anything more elaborate and you're into picking Python objects +apart using the Python/C API calls, which requires you to be meticulous +about maintaining reference counts, checking for errors at every step and +cleaning up properly if anything goes wrong. Any mistakes and you have +a nasty crash that's very difficult to debug. +

Various tools have been developed to ease some of the burdens of producing +extension code, of which perhaps SWIG +is the best known. SWIG takes a definition file consisting of a mixture +of C code and specialised declarations, and produces an extension module. +It writes all the boilerplate for you, and in many cases you can use it +without knowing about the Python/C API. But you need to use API calls if +any substantial restructuring of the data is required between Python and +C. +

What's more, SWIG gives you no help at all if you want to create a new +built-in Python type. It will generate pure-Python classes which +wrap (in a slightly unsafe manner) pointers to C data structures, but creation +of true extension types is outside its scope. +

Another notable attempt at making it easier to extend Python is PyInline +, inspired by a similar facility for Perl. PyInline lets you embed pieces +of C code in the midst of a Python file, and automatically extracts them +and compiles them into an extension. But it only converts the basic types +automatically, and as with SWIG,  it doesn't address the creation +of new Python types. +

Pyrex aims to go far beyond what any of these previous tools provides. +Pyrex deals with the basic types just as easily as SWIG, but it also lets +you write code to convert between arbitrary Python data structures and +arbitrary C data structures, in a simple and natural way, without knowing +anything about the Python/C API. That's right -- nothing at all! +Nor do you have to worry about reference counting or error checking -- +it's all taken care of automatically, behind the scenes, just as it is +in interpreted Python code. And what's more, Pyrex lets you define new +built-in Python types just as easily as you can define new classes +in Python. +

Sound too good to be true? Read on and find out how it's done. +

+The Basics of Pyrex

+The fundamental nature of Pyrex can be summed up as follows: Pyrex is +Python with C data types. +

Pyrex is Python: Almost any piece of Python code is also valid +Pyrex code. (There are a few limitations, but this approximation will serve +for now.) The Pyrex compiler will convert it into C code which makes equivalent +calls to the Python/C API. In this respect, Pyrex is similar to the former +Python2C project (to which I would supply a reference except that it no +longer seems to exist). +

...with C data types. But Pyrex is much more than that, because +parameters and variables can be declared to have C data types. Code which +manipulates Python values and C values can be freely intermixed, with conversions +occurring automatically wherever possible. Reference count maintenance +and error checking of Python operations is also automatic, and the full +power of Python's exception handling facilities, including the try-except +and try-finally statements, is available to you -- even in the midst of +manipulating C data. +

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. +

primes.pyx
+ +
+
 1  def primes(int kmax):
 2      cdef int n, k, i
 3      cdef int p[1000]
 4      result = []
 5      if kmax > 1000:
 6          kmax = 1000
 7      k = 0
 8      n = 2
 9      while k < kmax:
10          i = 0
11          while i < k and n % p[i] <> 0:
12              i = i + 1
13          if i == k:
14             p[k] = n
15             k = k + 1
16             result.append(n)
17          n = n + 1
18      return result
+
+You'll see that it starts out just like a normal Python function definition, +except that the parameter kmax is declared to be of type int +. This means that the object passed will be converted to a C integer (or +a TypeError will be raised if it can't be). +

Lines 2 and 3 use the cdef statement to define some local C variables. +Line 4 creates a Python list which will be used to return the result. You'll +notice that this is done exactly the same way it would be in Python. Because +the variable result hasn't been given a type, it is assumed to hold +a Python object. +

Lines 7-9 set up for a loop which will test candidate numbers for primeness +until the required number of primes has been found. Lines 11-12, which +try dividing a candidate by all the primes found so far, are of particular +interest. Because no Python objects are referred to, the loop is translated +entirely into C code, and thus runs very fast. +

When a prime is found, lines 14-15 add it to the p array for fast access +by the testing loop, and line 16 adds it to the result list. Again, you'll +notice that line 16 looks very much like a Python statement, and in fact +it is, with the twist that the C parameter n is automatically converted +to a Python object before being passed to the append method. Finally, +at line 18, a normal Python return statement returns the result +list. +

Compiling primes.pyx with the Pyrex compiler produces an extension module +which we can try out in the interactive interpreter as follows: +

+
>>> import primes
>>> primes.primes(10)
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
>>>
+
+See, it works! And if you're curious about how much work Pyrex has saved +you, take a look at the C code generated for this module +. +

+Language Details

+For more about the Pyrex language, see the Language +Overview . +

+Future Plans

+Pyrex is not finished. Substantial tasks remaining include: +
    +
  • +Support for certain Python language features which are planned but not +yet implemented. See the Limitations +section of the Language Overview for a current +list.
  • +
+ +
    +
  • +C++ support. This could be a very big can of worms - careful thought required +before going there.
  • +
+ +
    +
  • +Reading C/C++ header files directly would be very nice, but there are some +severe problems that I will have to find solutions for first, such as what +to do about preprocessor macros. My current thinking is to use a separate +tool to convert .h files into Pyrex declarations, possibly with some manual +intervention.
  • +
+ + \ No newline at end of file diff --git a/debian/pyrex/pyrex-0.9.9/Doc/FAQ.html b/debian/pyrex/pyrex-0.9.9/Doc/FAQ.html new file mode 100644 index 00000000..d55f3a6a --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Doc/FAQ.html @@ -0,0 +1,75 @@ + + + + FAQ.html + +


Pyrex FAQ +

+
+

Contents

+ +

How do I call Python/C API routines?

+ Declare them as C functions inside a cdef extern from block. +Use the type name object for any parameters and return types which +are Python object references. Don't use the word const anywhere. +Here is an example which defines and uses the PyString_FromStringAndSize routine: +
cdef extern from "Python.h":
+     object PyString_FromStringAndSize(char *, int)

cdef char buf[42]
+ my_string = PyString_FromStringAndSize(buf, 42)

+
+

How do I convert a C string containing null +bytes to a Python string?

+ Put in a declaration for the PyString_FromStringAndSize API routine + and use that. See How do I call Python/C API + routines?

How do I access the data inside a Numeric + array object?

+ Use a cdef extern from block to include the Numeric header file + and declare the array object as an external extension type. The following + code illustrates how to do this: +
cdef extern from "Numeric/arrayobject.h":

    struct PyArray_Descr:
+         int type_num, elsize
+         char type

+

    ctypedef class Numeric.ArrayType [object PyArrayObject]:
+         cdef char *data
+         cdef int nd
+         cdef int *dimensions, +*strides
+         cdef object base +
+         cdef PyArray_Descr *descr
+         cdef int flags
+

+
+

For more information about external extension types, see the "External Extension Types" +section of the "Extension Types" documentation +page.
+

+

Pyrex says my extension type object has no attribute +'rhubarb', but I know it does. What gives?

+You're probably trying to access it through a reference which Pyrex thinks +is a generic Python object. You need to tell Pyrex that it's a reference +to your extension type by means of a declaration. For example,
+
cdef class Vegetables:
+     cdef int rhubarb
+
+ ...
+ cdef Vegetables veg
+ veg.rhubarb = 42
+
+Also see the "Attributes" +section of the "Extension +Types" documentation page.
+

Python says my extension type has no method called 'quack', but I know it does. What gives?

+You may have declared the method using cdef instead of def. Only functions and methods declared with def are callable from Python code.

+--- + \ No newline at end of file diff --git a/debian/pyrex/pyrex-0.9.9/Doc/LanguageOverview.html b/debian/pyrex/pyrex-0.9.9/Doc/LanguageOverview.html new file mode 100644 index 00000000..17722e55 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Doc/LanguageOverview.html @@ -0,0 +1,17 @@ + +Pyrex Language Overview + + + +

+
Overview of the Pyrex Language  +

+ + + This is a combined tutorial and reference manual that describes the extensions to the Python language + made by Pyrex.

Contents

+ + + +--- \ No newline at end of file diff --git a/debian/pyrex/pyrex-0.9.9/Doc/Manual/Limitations.html b/debian/pyrex/pyrex-0.9.9/Doc/Manual/Limitations.html new file mode 100644 index 00000000..74131730 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Doc/Manual/Limitations.html @@ -0,0 +1,53 @@ + +Limitations +


+Limitations

Unsupported +Python features

+Pyrex is not quite a full superset of Python. The following +restrictions apply:
  • Function +definitions (whether using def or cdef) +cannot be nested within other function definitions.
  • Class definitions can only appear at the top +level of a module, not inside a function.
  • The import * form of import +is not allowed anywhere (other forms of the import statement are fine, +though).
  •  
  • Generators +cannot be defined in Pyrex.

  • +The globals() and locals() +functions cannot be used.
  • The above +restrictions will most likely remain, since removing them would be +difficult and they're not really needed for Pyrex's intended +applications.

    There are also some temporary limitations, +which may eventually be lifted, including:

    +
  • Class and function definitions cannot be placed inside +control structures.
  •  
  • List comprehensions are not yet +supported.
  •  
  • There is no +support for Unicode.
  •  
  • +Special methods of extension types cannot have functioning +docstrings.

  • The use of +string literals as comments is not recommended at present, because they are not accepted in +places where executable statements are not allowed.

  • Semantic +differences between Python and Pyrex

    Behaviour +of class scopes

    In Python, referring to a method of a class +inside the class definition, i.e. while the class is being defined, +yields a plain function object, but in Pyrex it yields an unbound method1. +A consequence of this is that the +usual idiom for using the classmethod and staticmethod functions, e.g.
    +
    class Spam:
      def method(cls):
        ...
      method = classmethod(method)
    +
    +will not work in Pyrex. This can be worked around by defining the +function outside the class, and then assigning the +result of classmethod or staticmethod inside the class, i.e.
    +
    def Spam_method(cls):
      ...
    class Spam:
      method = classmethod(Spam_method)
    +

    Footnotes

    1. +The reason for the different +behaviour +of class scopes is that Pyrex-defined Python functions are PyCFunction +objects, +not PyFunction objects, and are not recognised by the machinery that +creates +a bound or unbound method when a function is extracted from a class. To +get +around this, Pyrex wraps each method in an unbound method object itself +before +storing it in the class's dictionary.

    --- \ No newline at end of file diff --git a/debian/pyrex/pyrex-0.9.9/Doc/Manual/basics.html b/debian/pyrex/pyrex-0.9.9/Doc/Manual/basics.html new file mode 100644 index 00000000..132c2899 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Doc/Manual/basics.html @@ -0,0 +1,1118 @@ + + +Language Basics + + + +

    +
    Language +Basics +

    + +This +section describes the basic features of the Pyrex language. The +facilities covered in this section allow you to create Python-callable +functions that manipulate C data structures and convert between Python +and C data types. Later sections will cover facilities for wrapping external C code, creating new Python types +and cooperation between Pyrex +modules.
    +

    +Python +functions vs. C functions

    +There are two kinds of function +definition in Pyrex: +

    Python functions are +defined using the def statement, as in Python. They +take Python objects as parameters and return Python objects.

    +

    C functions are defined using the new cdef +statement. They take either Python objects or C values as parameters, +and can return either Python objects or C values.

    +

    Within +a Pyrex module, Python functions and C functions can call each other +freely, but only Python functions can be called from outside the module +by +interpreted Python code. So, any functions that you want to "export" +from your Pyrex module must be declared as Python functions using def.

    +

    Parameters +of either type of function can be declared to have C data types, using +normal C declaration syntax. For example,

    +
    +
    def spam(int i, char *s):
        ...
    +
    cdef int eggs(unsigned long l, float f):
        ...
    +
    +When +a parameter of a Python function is declared +to have a C data type, it is passed in as a Python object and +automatically converted to a C value, if possible. Automatic conversion +is currently only possible for numeric types and string types; +attempting to use any other type for the parameter of a Python function +will result in a compile-time error. +

    C functions, on the +other hand, can have parameters of any type, since they're passed in +directly using a normal C function call.

    +

    +Python objects as +parameters +and return values

    +If no type is specified for a parameter or +return value, it is assumed to be a Python object. +(Note that this is different from the C convention, where it would +default to int.) For example, the following +defines a C function that takes two Python objects as parameters and +returns a Python object: +
    +
    cdef spamobjs(x, y):
        ...
    +
    +Reference counting for these objects is performed +automatically according to the standard Python/C API rules (i.e. +borrowed references are taken as parameters and a new reference is +returned). +

    The name object can also be +used to explicitly declare something as a Python object. This can be +useful if the name being declared would otherwise +be taken as the name of a type, for example,

    +
    +
    cdef ftang(object int):
        ...
    +
    +declares +a parameter called int +which is a Python object. You can also use object as +the explicit return type of a function, e.g. +
    +
    cdef object ftang(object int):
        ...
    +
    +In the interests of clarity, it is probably a good +idea to always be explicit about object parameters +in C functions. +

    C +variable and type definitions

    +The cdef +statement is also used to declare C variables, either +local or module-level: +
    +
    cdef int i, j, k
    cdef float f, g[42], *h
    +
    +and C struct, union or enum types: +
    +
    cdef struct Grail:
        int age
        float volume
    +
    cdef union Food:
        char *spam
        float *eggs
    +
    cdef enum CheeseType:
        cheddar, edam, 
        camembert
    +
    cdef enum CheeseState:
        hard = 1
        soft = 2
        runny = 3
    +
    +There is currently no special syntax for defining a +constant, but you +can use an anonymous enum declaration for this purpose, for example, +
    cdef +enum:
    +    +tons_of_spam = 3
    +Note that the words struct, +union +and enum +are used +only when defining a type, not when referring to +it. For example, to declare a variable pointing to a Grail you would +write +
    +
    cdef Grail *gp
    +
    +and not +
    +
    cdef struct Grail *gp # WRONG
    +
    +There is also a ctypedef statement for giving names +to types, e.g. +
    +
    ctypedef unsigned long ULong
    +
    ctypedef int *IntPtr
    +
    +

    Forward +Declarations

    +If +you have two struct or union types containing pointers that refer to +each other, you will need to use a forward declaration for at least one +of them. This is simply the header of a struct or union without the +colon or body, for example,
    +
    +
    cdef struct Sandwich
    +
    +cdef struct Lunchbox:
    +
    Sandwich *lunch
    +
    +
    +cdef struct Sandwich:
    +
    Lunchbox *container
    +
    +
    +
    +You +can also forward-declare C functions, but there should be little need +to do this. Pyrex processes all declarations in a module before +analysing any executable statements, so calling a function defined +further down in the source file is usually not a problem. +

    Grouping +multiple C declarations

    +If you have a series of declarations that all begin with cdef, you can +group them into a cdef block like this:
    +
    cdef:

    struct Spam:
    int tons

    int i
    float f
    Spam *p

    void f(Spam *s):
    print s.tons, "Tons of spam"
    +

    Automatic +type conversions

    +In most situations, automatic conversions will be performed for the +basic numeric and string types when a Python object is used in a +context requiring a C value, or vice versa. The following table +summarises the conversion possibilities.
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    C +types
    +
    From +Python types
    +
    To +Python types
    +
    [unsigned] +char
    +[unsigned] short
    +int, long
    int, +long
    +
    int
    +
    unsigned +int
    +unsigned long
    +[unsigned] long long
    +
    int, long
    +
    +
    long
    +
    +
    float, +double, long double
    +
    int, +long, float
    +
    float
    +
    char +*
    +
    str
    +
    str
    +
    +
    +

    Caveats +when using a Python string in a C context

    +You need to be careful when using a Python string in a context +expecting a char *. +In this situation, a pointer to the contents of the Python string is +used, which is only valid as long as the Python string exists. So you +need to make sure that a reference to the original Python string is +held for as long as the C string is needed. If you can't guarantee that +the Python string will live long enough, you will need to copy the C +string.
    +
    +Pyrex detects and prevents some +mistakes of +this kind. For instance, if you attempt something like
    +
    cdef char *s
    s = pystring1 + pystring2
    +then +Pyrex will produce the error message "Obtaining char * from temporary +Python value". +The reason is that concatenating the two Python strings produces a new +Python string object that is referenced only by a temporary internal +variable that Pyrex generates. As soon as the statement has finished, +the temporary variable will be decrefed and the Python string +deallocated, leaving s +dangling. Since this code could not possibly work, Pyrex refuses to +compile it.
    +
    +The solution is to assign the result of the concatenation to +a Python variable, and then obtain the char * from that, i.e.
    +
    cdef char *s
    p = pystring1 + pystring2
    s = p
    +It +is then your responsibility to hold the reference p for as long +as necessary.
    +
    +Keep in mind that the rules used to detect such errors are +only +heuristics. Sometimes Pyrex will complain unnecessarily, and sometimes +it will fail to detect a problem that exists. Ultimately, you need to +understand the issue and be careful what you do. +

    Scope rules

    +Pyrex +determines whether a variable belongs to a local scope, the module +scope, or the built-in scope completely statically. +As with Python, assigning to a variable which is not otherwise declared +implicitly declares it to be a Python variable residing in the scope +where it is assigned. Unlike Python, however, a name which is referred +to but not declared or assigned is assumed to reside in the builtin +scope, not the module scope. +Names added to the module dictionary at run time will not shadow such +names.
    +
    +This can result in some odd things happening under rare circumstances, +for example
    +
    +
    print __name__
    +

    In +Pyrex, instead of printing the name of the current module, this prints +the name of the builtins module. The reason is that because Pyrex +hasn't seen a declaration of anything called __name__ in the +module, it's assumed to reside in the builtins. The solution is to use +a global +statement to declare __name__ +as a module-level name:

    +

    global +__name__
    +print __name__

    +Another +consequence of these rules is that the module-level scope behaves the +same way as a Python local scope if you refer to a variable before +assigning to it. In particular, tricks such as the following will not +work +in Pyrex:
    +
    +
    try:
      x = True
    except NameError:
      True = 1
    +
    +because, due to the assignment in the last line, True will +always be looked up in the module-level scope. You would have to do +something like this instead:
    +
    +
    import __builtin__
    try:
    True = __builtin__.True
    except AttributeError:
    True = 1
    +
    +
    +

    Statements and +expressions

    +Control structures and expressions follow Python syntax for the most +part. When applied to Python objects, they have the same semantics as +in Python (unless otherwise noted). Most of the Python operators can +also be applied to C values, with the obvious semantics. +

    If +Python objects and C values are mixed in an expression, conversions are +performed automatically between Python objects and C numeric or string +types.

    +

    Reference counts are maintained +automatically for all Python objects, and +all Python operations are automatically checked for errors, with +appropriate action taken.

    +

    +Differences +between C +and Pyrex +expressions

    +There +are some differences in syntax and semantics between C expressions and +Pyrex expressions, particularly in the area of C constructs which have +no direct equivalent in Python.
    +
      +
    • An integer literal without an L +suffix is treated as a C constant, and will be truncated to whatever +size your C compiler thinks appropriate. With an L +suffix, it will be converted to Python long integer (even if it would +be small enough to fit into a C int).
      +
      +
    • +
    • There is no -> +operator +in Pyrex. Instead of p->x, use p.x
    • There is no * +operator in Pyrex. Instead of *p, use p[0]
    • There is an & +operator, with the same semantics as in C.
    • +The null C pointer is called NULL, +not 0 (and NULL is a reserved word).
    • Character literals are written with a c +prefix, for +example:
    • +
        +
        c'X'
        +
      +
    • Type casts are written <type>value +, for example:
    • +
        +
        cdef char *p, float *q
        p = <char*>q
        +
      +Warning: +Don't attempt to use a typecast to convert between +Python and C data types -- it won't do the right thing. Leave Pyrex to +perform the conversion automatically. +
    +

    Operator Precedence

    +Keep in mind that there are +some differences +in operator precedence between Python and C, and that Pyrex uses the +Python precedences, not the C ones. +

    Integer +for-loops

    +You should be aware that a for-loop such as +
    for +i in range(n):
    +    +...
    +won't be very fast, even if i +and n are declared as +C integers, because range is a Python function. +For iterating over ranges of integers, Pyrex has another form of +for-loop: +
    for 0 <= i +< n:
    +    +...
    +Provided the loop variable and the lower +and upper bounds are all C integers, this form of loop will be much +faster, because Pyrex will translate it into pure C code. +

    Some +things to note about the integer for-loop:

    +
      +
    • The target expression (the middle one) must be a variable +name.
    • +
    • The direction of iteration is +determined by the relations. If they are both from the set {<, +<=} then it is upwards; if they are +both +from the set {>, >=} +then it is +downwards. (Any other combination is disallowed.)
    • +
    +Like other Python looping statements, break and continue +may be used in the body, and the loop may have an else +clause. +

    Catching +exceptions and tracebacks

    +For +reasons of efficiency, there are some differences between Pyrex and +Python concerning the way exceptions caught by a try-except statement +are handled.
    +
      +
    • Exceptions caught by an except clause cannot be retrieved +using sys.exc_info(). +To access the caught exception, you must bind it to a name in the +except clause.

      Pyrex also allows an additional name to be provided for +catching the traceback. For example,
    • +
    +
    try:
        start_engine()
    except HovercraftError, e, tb:
        print "Got an error:", e
        traceback.print_tb(tb)
    +
      +
    • A raise +statement with no arguments (to re-raise the last exception caught) +must be lexically enclosed in the except clause +which caught the exception. A raise statement in a Python function +called from the except clause will not +work.
    • +
    +
    try:
    start_engine()
    except HovercraftError, e:
    print "Unable to start:", e
    raise # the exception caught by the enclosing except clause
    +

    +

    +

    Error return values

    +If you don't do anything special, a function declared with cdef +that does not return a Python object has no way of reporting Python +exceptions to its caller. If an exception is detected in such a +function, a warning message is printed and the exception is ignored. +

    If +you want a C function that does not return a Python object to be able +to propagate exceptions to its caller, you need to declare an exception +value for it. Here is an example:

    +
    cdef +int spam() except -1:
    +    +...
    +With this declaration, whenever an +exception occurs inside spam, it will immediately +return with the value -1. Furthermore, whenever a +call to spam returns -1, an +exception will be assumed to have occurred and will be propagated. +

    When +you declare an exception value for a function, you should never +explicitly return that value. If all possible return values are legal +and you can't +reserve one entirely for signalling errors, you can use an alternative +form +of exception value declaration:

    +
    cdef +int spam() except? -1:
    +    +...
    +The "?" indicates that the value -1 +only indicates a possible error. In this case, +Pyrex generates a call to PyErr_Occurred if the +exception value is returned, to make sure it really is an error. +

    There +is also a third form of exception value declaration:

    +
    cdef +int spam() except *:
    +    +...
    +This form causes Pyrex to generate a +call to PyErr_Occurred after every +call to spam, regardless of what value it +returns. If you have a function returning void +that needs to propagate errors, you will have to use this form, since +there isn't any return value to test. +

    Some things to note:

    +
      +
    • Exception values can only declared for functions +returning an integer, enum, float or pointer type, and the value must +be a constant expression. The only possible pointer exception value is NULL. +Void functions can only use the except * form.
    • The exception value specification is part of the +signature +of the function. If you're passing a pointer to a function as a +parameter +or assigning it to a variable, the declared type of the parameter or +variable must have the same exception value specification (or lack +thereof). Here +is an example of a pointer-to-function declaration with an exception +value:
    • +
        +
        int (*grail)(int, char *) except -1
        +
      +
    • You don't need to (and shouldn't) declare exception values +for +functions which return Python objects. Remember that a function with no +declared return type implicitly returns a Python object.
    • +
    +

    +Checking +return values of non-Pyrex functions

    +It's important to +understand that the except clause does not +cause an error to be raised when the specified +value is returned. For +example, you can't write something like +
    +
    cdef extern FILE *fopen(char *filename, char *mode) except NULL # WRONG!
    +
    +and expect an exception to be automatically raised if a call to fopen +returns NULL. The except clause doesn't work that way; its only purpose +is for propagating exceptions that have already +been raised, either +by a Pyrex function or a C function that calls Python/C API routines. +To +get an exception from a non-Python-aware function such as fopen, you +will +have to check the return value and raise it yourself, for example, +
    +
    cdef FILE *p
    p = fopen("spam.txt", "r")
    if p == NULL:
        raise SpamError("Couldn't open the spam file")
    +
    +

    +

    +

    +The include +statement

    +A Pyrex source file can include material from other files +using the include +statement, for example +
    +
    include "spamstuff.pxi"
    +
    +The contents of the named file are textually +included at that point. The included file can contain any complete +statements or declarations that are valid in the context where the +include statement appears, including other include +statements. The contents of the included file should begin at an +indentation level of zero, and will be treated as though they were +indented to the level of the include statement that is including the +file.
    +
    +Note +that there are other mechanisms available for splitting Pyrex code into +separate parts that may be more appropriate in many cases. See Sharing Declarations Between +Pyrex Modules.
    +
    +

    Keyword-only arguments

    +

    Python +functions can have keyword-only arguments listed after the * parameter +and before the ** paramter if any, e.g.

    +
    def f(a, b, *args, c, d = 42, e, **kwds):
    ...
    +Here +c, d and e cannot be passed as position arguments and must be passed as +keyword arguments. Furthermore, c and e are required keyword arguments, +since they do not have a default value.
    +
    +If the +parameter name after the * is omitted, the function will not accept any +extra positional arguments, e.g.
    +
    +
    def g(a, b, *, c, d):
    ...
    +takes +exactly two positional parameters and has two required keyword +parameters.
    +
    +
    +

    Built-in Names

    +Pyrex +knows about many of the names in the builtin namespace, and treats them +specially in the interests of generating efficient code.
    +

    Built-in Constants

    +Pyrex +knows the following built-in constant and type names, and references +their values directly instead of using a dictionary lookup.
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Type +objects (type type)Exceptions +(type type)
    buffer
    +enumerate
    +file
    +float
    +int
    +long
    +open
    +property
    +str
    +tuple
    +xrange
    Exception
    +StopIteration
    +StandardError
    +ArithmeticError
    +LookupError
    +AsssertionError
    +EOFError
    +FloatingPointError
    +EnvironmentError
    +IOError
    +OSError
    +ImportError
    +IndexError
    +KeyError
    +KeyboardInterrupt
    +MemoryError
    +NameError
    +OverflowError
    +RuntimeError
    +NotImplementedError
    +SyntaxError
    IndentationError
    +TabError
    +ReferenceError
    +SystemError
    +SystemExit
    +TypeError
    +UnboundLocalError
    +UnicodeError
    +UnicodeEncodeError
    +UnicodeDecodeError
    +UnicodeTranslateError
    +ValueError
    +ZeroDivisionError
    +Warning
    +UserWarning
    +DeprecationWarning
    +PendingDeprecationWarning
    +SyntaxWarning
    +OverflowWarning
    +RuntimeWarning
    +FutureWarning
    Constants +(type object)
    True
    +False
    +Ellipsis
    +
    +Note that although some of the above names refer to type objects, they +are not Pyrex type names and therefore can't be used to declare the +type of a variable. Only the names listed under Built-in Types below +can be used as type names in declarations.
    +

    Built-in Functions

    +Pyrex +compiles calls to the following built-in functions into direct calls to +the corresponding Python/C API routines, making them particularly fast.
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Function +and argumentsReturn +typePython/C +API Equivalent
    abs(obj)objectPyNumber_Absolute
    bool(obj) +  (Note 3)intPyObject_IsTrue
    delattr(obj, name)intPyObject_DelAttr
    dir(obj)objectPyObject_Dir
    divmod(x, y)objectPyNumber_Divmod
    getattr(obj, name) +  (Note 1)
    +getattr3(obj, name, default)
    objectPyObject_GetAttr
    hasattr(obj, name)intPyObject_HasAttr
    hash(obj)intPyObject_Hash
    cintern(char *) +  (Note 5)objectPyString_InternFromString
    isinstance(obj, type)intPyObject_IsInstance
    issubclass(obj, type)intPyObject_IsSubclass
    issubtype(type, +type)   (Note 4)intPyType_IsSubType
    iter(obj)objectPyObject_GetIter
    iter2(obj, +obj)objectPyCallIter_New
    len(obj)Py_ssize_tPyObject_Length
    pow(x, y, z)   (Note 2)objectPyNumber_Power
    reload(obj)objectPyImport_ReloadModule
    repr(obj)objectPyObject_Repr
    setattr(obj, name)voidPyObject_SetAttr
    typecheck(obj, +type)   (Note +4)intPyObject_TypeCheck
    +
    +
    Note 1: There are +two different functions corresponding to the Python getattr +depending on whether a third argument is used. In a non-call context, +they both evaluate to the Python getattr +function.
    +
    +Note 2: +Only the three-argument form of pow() is +supported. Use the ** +operator otherwise.
    +
    +Note 3: In +a non-call context, the name bool +refers to the Python built-in bool type.
    +
    +Note 4: The +functions typecheck +and issubtype +have no exact Python equivalent. They are included for fast, safe type +checking of extension types. They are safer than using isinstance and issubclass +for this purpose, because the behaviour of the latter functions can be +overridden, so they don't necessarily reflect the true C types of the +objects involved.
    +
    +Note 5: +This function is named cintern +instead of intern +because it takes a null-terminated C string rather than a Python +string, and therefore cannot handle strings containing null bytes.
    +
    +
    +Only +direct function calls using these names are optimised. If you do +something else with one of these names that assumes it's a Python +object, such as assign it to a Python variable, and later call it, the +call will be made as a Python function call. +

    Built-in Types

    +Pyrex +knows about the following builtin +types:
    +
    +
    dict
    +list
    +object
    +slice
    +type
    +
    +
    +If you declare a variable as being of one of these types, then +calls to the methods in the table below will be compiled to direct +Python/C API calls, +avoiding the overhead of a Python attribute lookup and function call. +In the case of attributes, they will be accessed directly from the +object's C struct.
    +
    +Referring to the types themselves is also +slightly more efficient, because the relevant type object is accessed +directly rather than via a global variable lookup.
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Method +or AttributeReturn +typePython/C +API EquivalentNotes
    Type dict
    clear()PyDict_Clear
    copy()PyDict_Copy
    items()objectPyDict_Items
    keys()objectPyDict_Keys
    values()objectPyDict_Values
    merge(obj, +override)PyDict_MergeMerge +items from a mapping
    update(obj)PyDict_Update
    merge_pairs(obj, override)PyDict_MergeFromSeq2Merge +(key, value) pairs from a sequence
    Type list
    insert(int, +obj)PyList_Insert
    append(obj)PyList_Append
    sort()PyList_Sort
    reverse()PyList_Reverse
    as_tuple()objectPyList_AsTuple
    Type slice
    indices()objectPySlice_Indices
    startobject
    stopobject
    stepobject
    +
    +Some +of the above methods have no direct Python equivalent, but are there to +provide access to routines that exist in the Python/C API.
    +
    +As an example, the following compiles into code containing no Python +attribute lookups or function calls.
    +
    +
    cdef list cheeses
    +cheeses = []
    +cheeses.append("camembert")
    +cheeses.append("cheddar")
    +cheeses.insert(1, +"something runny")
    +
    +
    +
    +

    Conditional +Compilation

    +Some features are available for conditional compilation and +compile-time constants within a Pyrex source file.
    +

    Compile-Time +Definitions

    +A compile-time constant can be defined using the DEF +statement:
    +
    DEF FavouriteFood = "spam"
    DEF ArraySize = 42
    DEF OtherArraySize = 2 * ArraySize + 17
    +The +right-hand side of the DEF must be a valid compile-time expression. +Such expressions are made up of literal values and names defined using +DEF statements, combined using any of the Python expression syntax.
    +
    +The following compile-time names are predefined, corresponding to the +values returned by os.uname().
    +
    UNAME_SYSNAME, UNAME_NODENAME, UNAME_RELEASE,
    UNAME_VERSION, UNAME_MACHINE
    +The following selection of builtin constants and functions are also +available:
    +
    None, True, False,
    abs, bool, chr, cmp, complex, dict, divmod, enumerate,
    float, hash, hex, int, len, list, long, map, max, min,
    oct, ord, pow, range, reduce, repr, round, slice, str,
    sum, tuple, xrange, zip
    +A +name defined using DEF can be used anywhere an identifier can appear, +and it is replaced with its compile-time value as though it were +written into the source at that point as a literal. For this to work, +the compile-time expression must evaluate to a Python value of type int, long, float or str.
    +
    cdef int a1[ArraySize]
    cdef int a2[OtherArraySize]
    print "I like", FavouriteFood
    +

    Conditional +Statements

    +The IF +statement can be used to conditionally include or exclude sections of +code at compile time. It works in a similar way to the #if preprocessor +directive in C.
    +
    IF UNAME_SYSNAME == "Windows":
    include "icky_definitions.pxi"
    ELIF UNAME_SYSNAME == "Darwin":
    include "nice_definitions.pxi"
    ELIF UNAME_SYSNAME == "Linux":
    include "penguin_definitions.pxi"
    ELSE:
    include "other_definitions.pxi"
    +The +ELIF and ELSE clauses are optional. An IF statement can appear anywhere +that a normal statement or declaration can appear, and it can contain +any statements or declarations that would be valid in that context, +including DEF statements and other IF statements.
    +
    +The +expressions in the IF and ELIF clauses must be valid compile-time +expressions as for the DEF statement, although they can evaluate to any +Python value, and the truth of the result is determined in the usual +Python way.
    +
    +--- + \ No newline at end of file diff --git a/debian/pyrex/pyrex-0.9.9/Doc/Manual/extension_types.html b/debian/pyrex/pyrex-0.9.9/Doc/Manual/extension_types.html new file mode 100644 index 00000000..3cd3dc42 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Doc/Manual/extension_types.html @@ -0,0 +1,1079 @@ + + + + + + + + + + + + + + + Extension Types + + + + +

    +
    Extension Types +

    + + + +

    Contents

    + + + + + + + +

    Introduction

    + + + As well as creating normal user-defined classes with the Python class +statement, Pyrex also lets you create new built-in Python types, known as +extension types.

    WARNING: There are substantial differences in the way many of the +special methods work in extension types compared to Python classes. +Before attempting to define any __xxx__ methods, read the section on Special Methods of Extension Types.

    You define an extension type using the cdef class statement. Here's an example: +
    cdef class Shrubbery: + +

        cdef int width, height

    + + + + +

        def __init__(self, w, h):
    + + +         self.width = w
    + + +         self.height = h

    + + + + +

        def describe(self):
    + + +         print "This shrubbery is", +self.width, \
    + + +             +"by", self.height, "cubits."

    + + +
    + + + As you can see, a Pyrex extension type definition looks a lot like a Python + class definition. Within it, you use the def statement to define +methods that can be called from Python code. You can even define many of +the special methods such as __init__ as you would in Python. +

    The main difference is that you can use the cdef statement to define +attributes. The attributes may be Python objects (either generic or of a particular +extension type), or they may be of any C data type. So you can use extension +types to wrap arbitrary C data structures and provide a Python-like interface +to them.

    + + + +

    Attributes

    + + + Attributes of an extension type are stored directly in the object's C struct. + The set of attributes is fixed at compile time; you can't add attributes +to an extension type instance at run time simply by assigning to them, as +you could with a Python class instance. (You can subclass the extension type +in Python and add attributes to instances of the subclass, however.) +

    There are two ways that attributes of an extension type can be accessed: + by Python attribute lookup, or by direct access to the C struct from Pyrex + code. Python code is only able to access attributes of an extension type +by the first method, but Pyrex code can use either method.

    + + + +

    By default, extension type attributes are only accessible by direct access, +not Python access, which means that they are not accessible from Python code. +To make them accessible from Python code, you need to declare them as public or readonly. For example,

    + + + +
    cdef class Shrubbery:
    + + +     cdef public int width, height
    + + +     cdef readonly float depth
    + + + makes the width and height attributes readable and writable + from Python code, and the depth attribute readable but not writable. + +

    Note that you can only expose simple C types, such as ints, floats and + strings, for Python access. You can also expose Python-valued attributes, + although read-write exposure is only possible for generic Python attributes + (of type object). If the attribute is declared to be of an extension + type, it must be exposed readonly.

    + + + +

    Note also that the public and readonly options apply + only to Python access, not direct access. All the attributes of an +extension type are always readable and writable by direct access.

    + +

    Type declarations

    + + + +

    Before you can directly access the attributes of an extension type, the Pyrex compiler must know +that you have an instance of that type, and not just a generic Python object. +It knows this already in the case of the "self" parameter of the methods of +that type, but in other cases you will have to use a type declaration.

    + +

    For example, in the following function,

    + +
    cdef widen_shrubbery(sh, extra_width): # BAD
    + + +     sh.width = sh.width + extra_width
    + +

    because the sh parameter hasn't been given a type, the width +attribute will be accessed by a Python attribute lookup. If the +attribute has been declared public or readonly then this will work, but +it will be very inefficient. If the attribute is private, it will not work at all -- the +code will compile, but an attribute error will be raised at run time.

    + +

    The solution is to declare sh as being of type Shrubbery, as follows:

    + + + +
    cdef widen_shrubbery(Shrubbery sh, extra_width):
    + + +     sh.width = sh.width + extra_width
    + +Now the Pyrex compiler knows that sh has a C attribute called width and will generate code to access it directly and efficiently. The same consideration applies to local variables, for example,
    + +
    + +
    cdef Shrubbery another_shrubbery(Shrubbery sh1):
    + +    cdef Shrubbery sh2
    + +    sh2 = Shrubbery()
    + +    sh2.width = sh1.width
    + +    sh2.height = sh1.height
    + +    return sh2
    + + +

    Extension types and None

    + + + When you declare a parameter or C variable as being of an extension type, + Pyrex will allow it to take on the value None as well as values of its declared +type. This is analogous to the way a C pointer can take on the value NULL, +and you need to exercise the same caution because of it. There is no problem +as long as you are performing Python operations on it, because full dynamic +type checking will be applied. However, when you access C attributes of an +extension type (as in the widen_shrubbery function above), it's up +to you to make sure the reference you're using is not None -- in the interests +of efficiency, Pyrex does not check this. +

    You need to be particularly careful when exposing Python functions which + take extension types as arguments. If we wanted to make widen_shrubbery +a Python function, for example, if we simply wrote

    + + + +
    def widen_shrubbery(Shrubbery sh, extra_width): # This is
    + + +     sh.width = sh.width + extra_width           +# dangerous!
    + + + then users of our module could crash it by passing None for the sh +parameter. +

    One way to fix this would be

    + + + +
    def widen_shrubbery(Shrubbery sh, extra_width):
    + + +     if sh is None:
    + + +         raise TypeError
    + + +     sh.width = sh.width + extra_width
    + + + but since this is anticipated to be such a frequent requirement, Pyrex +provides a more convenient way. Parameters of a Python function declared +as an extension type can have a not None clause: +
    def widen_shrubbery(Shrubbery sh not None, extra_width): +
    + + +     sh.width = sh.width + extra_width
    + + + Now the function will automatically check that sh is not None +along with checking that it has the right type. +

    Note, however that the not None clause can only be used + in Python functions (defined with def) and not C functions (defined + with cdef). If you need to check whether a parameter to a C function + is None, you will need to do it yourself.

    + + + +

    Some more things to note:

    + + + +
      + + +
    • The self parameter of a method of an extension type is guaranteed + never to be None.
    • + + + +
    + + + +
      + + +
    • When comparing a value with None, keep in mind that, if x is a Python object, x is None and x is not None are very +efficient because they translate directly to C pointer comparisons, whereas + x == None and x != None, or simply using x as a boolean value (as in if x: ...) will invoke Python operations +and therefore be much slower.
    • + + + +
    + + + +

    Special methods

    + + + Although the principles are similar, there are substantial differences +between many of the __xxx__ special methods of extension types and their +Python counterparts. There is a separate page devoted to this subject, and you should read it carefully before attempting +to use any special methods in your extension types. +

    Properties

    + + + There is a special syntax for defining properties in an extension + class: +
    cdef class Spam: + +

        property cheese:

    + + + + +

            "A doc string can go +here."

    + + + + +

            def __get__(self): +
    + + +             +# This is called when the property is read.
    + + +             +...

    + + + + +

            def __set__(self, value): +
    + + +             +# This is called when the property is written.
    + + +             +...

    + + + + +

            def __del__(self): +
    + + +             +# This is called when the property is deleted.
    + + +  

    + + +
    + + + The __get__, __set__ and __del__ methods are +all optional; if they are omitted, an exception will be raised when the corresponding +operation is attempted. +

    Here's a complete example. It defines a property which adds to a list +each time it is written to, returns the list when it is read, and empties +the list when it is deleted.
    + + +  

    + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    cheesy.pyxTest input
    cdef class CheeseShop: + + +

      cdef object cheeses

    + + + + +

      def __cinit__(self):
    + + +     self.cheeses = []

    + + + + +

      property cheese:

    + + + + +

        def __get__(self):
    + + +       return "We don't have: %s" % self.cheeses +

    + + + + +

        def __set__(self, value):
    + + +       self.cheeses.append(value) +

    + + + + +

        def __del__(self):
    + + +       del self.cheeses[:]

    + + +
    from cheesy import CheeseShop + + +

    shop = CheeseShop()
    + + + print shop.cheese

    + + + + +

    shop.cheese = "camembert"
    + + + print shop.cheese

    + + + + +

    shop.cheese = "cheddar"
    + + + print shop.cheese

    + + + + +

    del shop.cheese
    + + + print shop.cheese

    + + +
    Test output
    We don't have: []
    + + + We don't have: ['camembert']
    + + + We don't have: ['camembert', 'cheddar']
    + + + We don't have: []
    + + +
    + + + +

    Subclassing

    + + + An extension type may inherit from a built-in type or another extension +type: +
    cdef class Parrot:
    + + +     ... + +

    cdef class Norwegian(Parrot):
    + + +     ...

    + + +
    + + + +


    + + + A complete definition of the base type must be available to Pyrex, so if +the base type is a built-in type, it must have been previously declared as +an extern extension type. If the base type is defined in another Pyrex +module, it must either be declared as an extern extension type or imported +using the cimport statement.

    + + + +

    An extension type can only have one base class (no multiple inheritance). +

    + + + +

    Pyrex extension types can also be subclassed in Python. A Python class + can inherit from multiple extension types provided that the usual Python +rules for multiple inheritance are followed (i.e. the C layouts of all the +base classes must be compatible).
    + + +

    + + + +

    C methods

    + + + Extension types can have C methods as well as Python methods. Like C functions, +C methods are declared using cdef instead of def. C methods +are "virtual", and may be overridden in derived extension types.
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    pets.pyx
    + + +
    Output
    + + +
    cdef class Parrot:
    + + +
    + + +   cdef void describe(self):
    + + +     print "This parrot is resting."
    + + +
    + + + cdef class Norwegian(Parrot):
    + + +
    + + +   cdef void describe(self):
    + + +    Parrot.describe(self)
    + + +     print "Lovely plumage!"
    + + +
    + + +
    + + + cdef Parrot p1, p2
    + + + p1 = Parrot()
    + + + p2 = Norwegian()
    + + +print "p1:"
    + + + p1.describe()
    + + +print "p2:"
    + + + p2.describe()

    + + +
    p1:
    + + +This parrot is resting.
    + + +p2:
    + + +
    This parrot is resting.
    + + +
    Lovely plumage!
    + + +
    + + +
    + + + The above example also illustrates that a C method can call an inherited +C method using the usual Python technique, i.e.
    + + +
    Parrot.describe(self)
    + + +
    + + + +

    Forward-declaring extension types

    + + + Extension types can be forward-declared, like struct and union types. This + will be necessary if you have two extension types that need to refer to +each other, e.g. +
    cdef class Shrubbery # forward declaration + +

    cdef class Shrubber:
    + + +     cdef Shrubbery work_in_progress

    + + + + +

    cdef class Shrubbery:
    + + +     cdef Shrubber creator

    + + +

    Making extension types weak-referenceable

    + +By +default, extension types do not support having weak references made to +them. You can enable weak referencing by declaring a C attribute of +type object called __weakref__. For example,
    + + +
    + + +
    cdef class ExplodingAnimal:

    + + +    """This animal will self-destruct when it is
    + + +       no longer strongly referenced."""
    + + +   
    + + +    cdef object __weakref__
    + + +
    + + +

    Garbage Collection

    Normally, any extension type which has +Python-valued attributes automatically participates in cyclic garbage +collection. You can prevent this as follows:
    cdef class Hovercraft [nogc]:

    """This object will not participate in cyclic gc
    even though it has a Python attribute."""

    cdef object eels
    However, +if there is a base type with Python attributes that participates in GC, +any subclasses of it will also participate in GC regardless of their nogc options. + + +

    Public and external extension types

    + + + + Extension types can be declared extern or public. An extern extension type declaration makes +an extension type defined in external C code available to a Pyrex module. +A public extension type declaration makes an extension type defined in a Pyrex module available to external C +code. +

    External extension types

    + + + An extern extension type allows you to gain access to the internals + of Python objects defined in the Python core or in a non-Pyrex extension +module. +
    NOTE: In Pyrex versions before 0.8, extern extension + types were also used to reference extension types defined in another Pyrex + module. While you can still do that, Pyrex 0.8 and later provides a better + mechanism for this. See Sharing C Declarations Between + Pyrex Modules.
    + + + Here is an example which will let you get at the C-level members of the +built-in complex object. +
    cdef extern from "complexobject.h": + +

        struct Py_complex:
    + + +         double real
    + + +         double imag

    + + + + +

        ctypedef class __builtin__.complex [object PyComplexObject]: +
    + + +         cdef Py_complex cval +

    + + + + +

    # A function which uses the above type
    + + + def spam(complex c):
    + + +     print "Real:", c.cval.real
    + + +     print "Imag:", c.cval.imag

    + + +
    + + + Some important things to note are: +
      + + +
    1. In this example, ctypedef class has been used. This is because, + in the Python header files, the PyComplexObject struct is declared + with
      + + +
      + + + + +
      ctypedef struct {
      + + +     ...
      + + + } PyComplexObject;
      + + +
      + + +
      + + +
    2. + +
    3. As well as the name of the extension type, the module in which +its type object can be found is also specified. See the implicit importing section below. 
      + + +
      + + +
    4. + + +
    5. When declaring an external extension type, you don't declare +any methods. Declaration of methods is not required in order to call them, +because the calls are Python method calls. Also, as with structs and unions, +if your extension class declaration is inside a cdef extern from block, + you only need to declare those C members which you wish to access.
    6. + + + +
    + + + +

    Implicit importing

    + + + +
    Backwards Incompatibility Note: +You will have to update any pre-0.8 Pyrex modules you have which use extern +extension types. I apologise for this, but for complicated reasons it proved + to be too difficult to continue supporting the old way of doing these while + introducing the new features that I wanted.
    + + + Pyrex 0.8 and later requires you to include a module name in an extern +extension class declaration, for example, +
    cdef extern class MyModule.Spam:
    + + +     ...
    + + + The type object will be implicitly imported from the specified module and + bound to the corresponding name in this module. In other words, in this +example an implicit +
      + + + + +
      from MyModule import Spam
      + + + +
    + + + statement will be executed at module load time. +

    The module name can be a dotted name to refer to a module inside a package + hierarchy, for example,

    + + + +
    cdef extern class My.Nested.Package.Spam:
    + + +     ...
    + + + You can also specify an alternative name under which to import the type +using an as clause, for example, +
      + + + cdef extern class My.Nested.Package.Spam as Yummy:
      + + +    ... +
    + + + which corresponds to the implicit import statement +
      + + + + +
      from My.Nested.Package import Spam as Yummy
      + + + +
    + + + +

    Type names vs. constructor names

    + + + Inside a Pyrex module, the name of an extension type serves two distinct + purposes. When used in an expression, it refers to a module-level global +variable holding the type's constructor (i.e. its type-object). However, +it can also be used as a C type name to declare variables, arguments and +return values of that type. +

    When you declare

    + + + +
    cdef extern class MyModule.Spam:
    + + +     ...
    + + + the name Spam serves both these roles. There may be other names + by which you can refer to the constructor, but only Spam can be +used as a type name. For example, if you were to explicity import MyModule, + you could use MyModule.Spam() to create a Spam instance, but you + wouldn't be able to use MyModule.Spam as a type name. +

    When an as clause is used, the name specified in the as +clause also takes over both roles. So if you declare

    + + + +
    cdef extern class MyModule.Spam as Yummy:
    + + +     ...
    + + + then Yummy becomes both the type name and a name for the constructor. + Again, there are other ways that you could get hold of the constructor, +but only Yummy is usable as a type name. +

    Public extension types

    + + + An extension type can be declared public, in which case a .h +file is generated containing declarations for its object struct and type +object. By including the .h file in external C code that you write, +that code can access the attributes of the extension type. +

    Name specification clause

    + + + The part of the class declaration in square brackets is a special feature + only available for extern or public extension types. The full +form of this clause is +
    [object object_struct_name, type type_object_name ]
    + + + where object_struct_name is the name to assume for the type's C +struct, and type_object_name is the name to assume for the type's +statically declared type object. (The object and type clauses can be written +in either order.) +

    If the extension type declaration is inside a cdef extern from +block, the object clause is required, because Pyrex must be able to +generate code that is compatible with the declarations in the header file. +Otherwise, for extern extension types, the object clause is +optional.

    + + + +

    For public extension types, the object and type clauses +are both required, because Pyrex must be able to generate code that is compatible +with external C code.

    + + + +

    + + + +

    + + + Back to the Language Overview
    + + +  
    + + +
    + + + \ No newline at end of file diff --git a/debian/pyrex/pyrex-0.9.9/Doc/Manual/external.html b/debian/pyrex/pyrex-0.9.9/Doc/Manual/external.html new file mode 100644 index 00000000..38f19270 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Doc/Manual/external.html @@ -0,0 +1,294 @@ + +Interfacing with External C Code +


    Interfacing with +External C Code

    +One of the main uses of Pyrex is wrapping existing libraries of C code. +This is achieved by using external +declarations to declare the C functions and variables from +the library that you want to use.

    You can also use public declarations to make C +functions and variables defined in a Pyrex module available to external +C code. The need for this is expected to be less frequent, but you +might want to do it, for example, if you are embedding Python in +another application as a scripting language. Just as a Pyrex module can +be used as a bridge to +allow Python code to call C code, it can also be used to allow C code +to +call Python code.


    External +declarations

    By default, C functions and variables declared +at the module level are local to the module (i.e. they have the C static +storage class). They can also be declared extern to +specify that they are defined elsewhere, for example:
    +
    cdef extern int spam_counter
    cdef extern void order_spam(int tons)
    +

    +Referencing C +header files

    When you use an extern definition on its own as +in the examples above, Pyrex includes a declaration for it in the +generated C file. This can cause problems if the declaration doesn't +exactly match the declaration that will be seen by other C code. If +you're wrapping an existing C library, for example, it's important that +the generated C code is compiled with exactly the same declarations as +the rest of the library.

    To achieve this, you can tell Pyrex +that the declarations are to be found in a C header file, like this:

    +
    cdef extern from "spam.h":
        int spam_counter
        void order_spam(int tons)
    +
    The cdef extern from clause +does three things:
    1. It directs Pyrex to place a #include +statement for the named header file in the generated C code.
    2. It prevents Pyrex from generating any C code for +the declarations found in the associated block.
    3. It treats all declarations within the block as +though they +started with cdef extern.
    +It's important to understand that Pyrex does not +itself read the C header file, so you still need to provide Pyrex +versions of any declarations from it that you use. However, the Pyrex +declarations don't always have to +exactly match the C ones, and in some cases they shouldn't or can't. In +particular:
    1. Don't use const. +Pyrex doesn't know anything about const, +so just leave it out. Most of the time this shouldn't cause any +problem, +although on rare occasions you might have to use a cast. 1
    2. Leave out any platform-specific extensions to C +declarations such as __declspec().
    3. If the header file declares a big struct and you +only want +to use a few members, you only need to declare the members you're +interested in. Leaving the rest out doesn't do any harm, because the C +compiler will use the full definition from the header file.

      +In some cases, you might not need any of the +struct's members, in +which case you can just put pass in the body of +the struct declaration, +e.g.

          cdef extern +from "foo.h":
              +struct spam:
              +    pass


      +Note that you can only do this inside a cdef extern from +block; struct +declarations anywhere else must be non-empty.

    4. +If the header file uses typedef names such as size_t to +refer to platform-dependent flavours of numeric types, you will need a +corresponding ctypedef statement, but you don't +need to match the type exactly, just use something of the right general +kind (int, float, etc). For example,
      1. ctypedef int size_t
      +will work okay whatever the actual size of a size_t is (provided the +header file defines it correctly).
       
    5. +If the header file uses macros to define constants, translate them into +a dummy enum declaration.
    6. If the header file defines a function using a +macro, declare it as though it were an ordinary function, with +appropriate argument and +result types.
    A few more tricks and tips:
    • +If you want to include a C header because it's needed by another +header, but don't want to use any declarations from it, put pass in the extern-from +block:
        cdef extern +from "spam.h":
            +pass
    • If you want +to include some external declarations, but don't want to specify a +header file (because it's included by some other header that you've +already included) you can put * in place of the +header file name:
    cdef +extern from *:
        +...

    Styles of struct, union +and enum declaration

    There are two main ways that structs, +unions and enums can be declared in C header files: using a tag name, +or using a typedef. There are also some variations based on various +combinations of these.

    It's important to make the Pyrex +declarations match the style used in the +header file, so that Pyrex can emit the right sort of references to the +type +in the code it generates. To make this possible, Pyrex provides two +different +syntaxes for declaring a struct, union or enum type. The style +introduced +above corresponds to the use of a tag name. To get the other style, you +prefix +the declaration with ctypedef, as illustrated +below.

    The following table shows the various +possible styles that can be found in a header file, and the +corresponding Pyrex declaration that you should put in the cdef +exern from block. Struct declarations are used as an +example; the same applies equally to union and enum declarations.

    +

    Note that in all the cases below, you refer to the type in +Pyrex code simply +as Foo, +not struct Foo. +

    + + + + + + + + +
      C codePossibilities +for corresponding Pyrex code Comments
    1struct Foo {
    +  ...
    };
    cdef struct Foo: +
      ...
    Pyrex +will refer to the type as struct Foo in the +generated C code.
    2typedef +struct {
      ...
    +} Foo;
    ctypedef struct Foo:
    +  ...
    Pyrex +will refer to the type simply as Foo +in the generated C code.
    3typedef +struct +foo {
      ...
    +} Foo;
    cdef struct +foo:
      ...
    +ctypedef foo Foo #optional
    If the C header uses both a +tag and a typedef with different names, you can use +either form of declaration in Pyrex (although if you need to forward +reference the type, you'll have to use +the first form).
    ctypedef struct Foo:
    +  ...
    4typedef +struct Foo {
      ... +
    } Foo;
    cdef struct +Foo:
      ...
    If the header uses the same name for the +tag and the typedef, you won't be able to include a ctypedef +for it -- but then, it's not +necessary.

    +Accessing +Python/C API routines

    One particular use of the cdef +extern from statement is for gaining access to routines in +the Python/C API. For example,
    cdef extern from "Python.h":
    +
        object PyString_FromStringAndSize(char *s, Py_ssize_t len)
    +will allow you to create Python strings containing +null bytes.

    Special +Types

    Pyrex predefines the name Py_ssize_t +for use with Python/C API routines. To make your extensions compatible +with 64-bit systems, you should always use this type where it is +specified in the documentation of Python/C API routines.

    Windows Calling +Conventions

    The __stdcall, __fastcall and __cdecl calling +convention specifiers can be used in Pyrex, with the same syntax as +used by C compilers on Windows, for example,

    cdef extern int __stdcall FrobnicateWindow(long handle)

    cdef void (__stdcall *callback)(void *)
    If +__stdcall is used, the function is only considered compatible with +other __stdcall functions of the same signature.


    Resolving +naming conflicts - C name specifications

    Each Pyrex module +has a single module-level namespace for both Python +and C names. This can be inconvenient if you want to wrap some external +C functions and provide the Python user with Python functions of the +same +names.

    Pyrex 0.8 provides a couple of different ways of +solving this problem. The best way, especially if you have many C +functions to wrap, is probably to put the extern C function +declarations into a different namespace using the facilities described +in the section on sharing +declarations between Pyrex modules.

    The +other way is to use a c name specification to give +different Pyrex and C names to the C function. Suppose, for example, +that you want to wrap an external function called eject_tomato. +If you declare it as

    cdef extern void c_eject_tomato "eject_tomato" (float speed)
    +
    then its name inside the Pyrex module will be c_eject_tomato, +whereas its name in C will be eject_tomato. You +can then wrap it with
    def eject_tomato(speed):
      c_eject_tomato(speed)
    +
    so that users of your module can refer to it as eject_tomato. +

    Another use for this feature is referring to external names +that happen to be Pyrex keywords. For example, if you want to call an +external function called print, you can rename it +to something else in your Pyrex module.

    As well +as functions, C names can be specified for variables, structs, unions, +enums, struct and union members, and enum values. For example,

    +
    cdef extern int one "ein", two "zwei"
    cdef extern float three "drei"

    cdef struct spam "SPAM":
      int i "eye"
    cdef +enum surprise "inquisition":
      +first "alpha"
      second +"beta" = 3

    +

    Using +Pyrex Declarations from C

    Pyrex +provides two methods for making C declarations from a Pyrex module +available for use by external C code – public declarations and C API +declarations.

    NOTE: You do not need to use +either of these to make declarations from one Pyrex module available to +another Pyrex module – you should use the cimport statement +for that. Sharing Declarations +Between Pyrex Modules.

    Public Declarations

    +You can make C types, variables and functions defined in a Pyrex module +accessible to C code that is linked with the module, by declaring them +with the public keyword:
    cdef +public struct Bunny: # public type declaration
      +  int vorpalness

    cdef public int spam # +public variable declaration

    cdef public +void grail(Bunny *): # public function declaration
    +    ...

    +If there are any public declarations in a Pyrex +module, a header file called modulename.h +file is generated containing equivalent C declarations for inclusion in +other C code.

    Any +C code wanting to make use of these declarations will need to be +linked, either statically or dynamically, with the extension module.

    If +the Pyrex module resides within a package, then the name of the .h file +consists of the full dotted name of the module, e.g. a module called foo.spam would have +a header file called foo.spam.h. +

    C API +Declarations

    The other way of making declarations available to C code is to declare them with the api +keyword. You can use this keyword with C functions and extension types. A header file called "modulename_api.h" +is produced containing declarations of the functions and extension types, and a function +called import_modulename().

    C +code wanting to use these functions or extension types needs to include the header and call +the import_modulename() +function. The other functions can then be called and the extension types used as usual.

    Any +public +C type or extension type declarations in the Pyrex module are also made available when you +include modulename_api.h.

    delorean.pyx
    marty.c
    cdef public struct Vehicle:
    int speed
    float power

    cdef api void activate(Vehicle *v):
    if v.speed >= 88 \
    and v.power >= 1.21:
    print "Time travel achieved"
    #include "delorean_api.h"

    Vehicle car;

    int main(int argc, char *argv[]) {
    import_delorean();
    car.speed = atoi(argv[1]);
    car.power = atof(argv[2]); 
    activate(&car);
    }

    Note +that any types defined in the Pyrex module that are used as argument or +return types of the exported functions will need to be declared public, +otherwise they won't be included in the generated header file, and you +will get errors when you try to compile a C file that uses the header.

    Using the api method does not require the C code using the declarations to be linked +with the extension module in any way, as the Python import machinery is +used to make the connection dynamically. However, only functions can be +accessed this way, not variables.

    You can use both public and api on the same +function to make it available by both methods, e.g.
    cdef public api void belt_and_braces():
    ...
    However, +note that you should include either +modulename.h +or modulename_api.h in +a given C file, not +both, otherwise you may get conflicting dual definitions.

    If +the Pyrex module resides within a package, then:
    • The +name of the header file contains of the full dotted name of the module.
    • The +name of the importing function contains the full name with dots +replaced by double underscores.
    E.g. a module +called foo.spam +would have an API header file called foo.spam_api.h and +an importing function called import_foo__spam().

    Multiple public and api declarations

    You can declare a whole group of items as public and/or api all at once by enclosing them in a cdef block, for example,
    cdef public api:
    void order_spam(int tons)
    char *get_lunch(float tomato_size)
    This can be a useful thing to do in a .pxd file (see Sharing Declarations +Between Pyrex Modules) to make the module's public interface available by all three methods.


    Acquiring and Releasing the GIL

    Pyrex +provides facilities for releasing the Global Interpreter Lock (GIL) +before calling C code, and for acquiring the GIL in functions that are +to be called back from C code that is executed without the GIL.

    Releasing the GIL

    You can release the GIL around a section of code using the with nogil statement:
    with nogil:
    <code to be executed with the GIL released>
    Code in the body of the statement must not manipulate Python objects, +and must +not call anything that manipulates Python objects without first +re-acquiring the GIL. Pyrex attempts to check that these restrictions +are being followed as far as it can, but it may not catch all possible +forms of violation.

    Any external C functions called inside the block must be declared as nogil (see below).

    Note: +It may be safe to do some things with Python objects under some +circumstances. Provided steps are taken (such as adequate locking) to +ensure that the objects involved cannot be deallocated by Python code +running in another thread, it is probably safe to access non-Python C +attributes of an extension type, and to pass references to Python +objects to another function that is safe to call with the GIL released.

    However, in the absence of such locking, it is not safe to do anything with Python objects with the GIL released -- not even look at them.

    Acquiring the GIL

    A +C function that is to be used as a callback from C code that is executed +without the GIL needs to acquire the GIL before it can manipulate +Python objects. This can be done by specifying with gil in the function header:
    cdef void my_callback(void *data) with gil:
    ...

    Declaring a function as callable without the GIL

    You can specify nogil in a C function header or function type to declare that it is safe to call without the GIL.

    cdef extern int swizzle_the_knob() nogil

    A block of external functions can be declared nogil at once.

    cdef extern from "somewhere.h" nogil:
    ...

    Note that declaring a function nogil does not +cause the GIL to be released before calling the function. It simply +allows the function to be called in situations where the GIL is not +held.

    You can also declare a function implemented in Pyrex as nogil.
    cdef void my_gil_free_func(int spam) nogil:
    ...
    Such a function cannot have any Python local variables, it cannot return a +Python type, and the same restrictions apply to the body of the function as for a with nogil block.

    Declaring a function with gil also implicitly makes its signature nogil.

    +
    Footnotes +
    1. +A problem with const +could arise if you have something like
    cdef extern from "grail.h":
      char *nun
    +
    where grail.h actually contains
    +
    extern const char *nun;
    and +you do
    cdef void languissement(char *s):
      #something that doesn't change s
    +
    ...
    languissement(nun)
    which +will cause the C compiler to complain. You can work around it by +casting away the constness:
    languissement(<char *>nun)  
    +
    --- \ No newline at end of file diff --git a/debian/pyrex/pyrex-0.9.9/Doc/Manual/sharing.html b/debian/pyrex/pyrex-0.9.9/Doc/Manual/sharing.html new file mode 100644 index 00000000..415bdfa1 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Doc/Manual/sharing.html @@ -0,0 +1,342 @@ + + + + + + + + + Sharing Declarations Between Pyrex Modules + + + +

    +
    Sharing Declarations Between Pyrex Modules +

    + + This section describes a new set of facilities introduced in Pyrex 0.8 +for making C declarations, functions and extension types in one Pyrex module available +for use in another Pyrex module. These facilities are closely modelled on +the Python import mechanism, and can be thought of as a compile-time version +of it. +

    Contents

    + + + + + +

    Definition and Implementation files

    + + A Pyrex module can be split into two parts: a definition file with + a .pxd suffix, containing C declarations that are to be available + to other Pyrex modules, and an implementation file with a .pyx +suffix, containing everything else. When a module wants to use something +declared in another module's definition file, it imports it using the cimport statement. +

    What a Definition File contains

    + + A definition file can contain: +
      + +
    • Any kind of C type declaration.
    • + +
    • extern C function or variable declarations.
    • Declarations of C functions defined in the module.
    • + +
    • The definition part of an extension type (see below).
    • + + +
    + + It cannot contain any non-extern C variable declarations. +

    It cannot contain the implementations of any C or Python functions, or +any Python class definitions, or any executable statements.

    + + +
    NOTE: You don't need to (and shouldn't) declare anything in a +declaration file public in order to make it available to other Pyrex +modules; its mere presence in a definition file does that. You only need a +public declaration if you want to make something available to external C code.
    + + +

    What an Implementation File contains

    + + An implementation file can contain any kind of Pyrex statement, although + there are some restrictions on the implementation part of an extension type +if the corresponding definition file also defines that type (see below). + +

    The cimport statement

    + + The cimport statement is used in a definition or implementation +file to gain access to names declared in another definition file. Its syntax +exactly parallels that of the normal Python import statement: +
    cimport module [, module...]
    + + +
    from module cimport name +[as name] [, name [as name] + ...]
    + + Here is an example. The file on the left is a definition file which exports + a C data type. The file on the right is an implementation file which imports + and uses it.
    + +   + + + + + + + + + + + + + + + + + + + + + + +
    dishes.pxdrestaurant.pyx
    cdef enum otherstuff:
    + +     sausage, eggs, lettuce +

    cdef struct spamdish:
    + +     int oz_of_spam
    + +     otherstuff filler

    + +
    cimport dishes
    + + from dishes cimport spamdish +

    cdef void prepare(spamdish *d):
    + +     d.oz_of_spam = 42
    + +     d.filler = dishes.sausage

    + + +

    def serve():
    + +     cdef spamdish d
    + +     prepare(&d)
    + +     print "%d oz spam, filler no. %d" % \ +
    + +          (d.oz_of_spam, + d.filler)

    + +
    + + +

    It is important to understand that the cimport statement can only +be used to import C data types, C functions and variables, and extension +types. It cannot be used to import any Python objects, and (with one exception) +it doesn't imply any Python import at run time. If you want to refer to any +Python names from a module that you have cimported, you will have to include +a regular import statement for it as well.

    + + +

    The exception is that when you use cimport to import an extension + type, its type object is imported at run time and made available by the +name under which you imported it. Using cimport to import extension +types is covered in more detail below. +

    + + +

    Search paths for definition files

    + + When you cimport a module called modulename, the Pyrex +compiler searches for a file called modulename.pxd along the search +path for include files, as specified by -I command line options. +

    Also, whenever you compile a file modulename.pyx, the corresponding + definition file modulename.pxd is first searched for along the +same path, and if found, it is processed before processing the .pyx +file.

    + + +

    Using cimport to resolve naming + conflicts

    + + The cimport mechanism provides a clean and simple way to solve the problem + of wrapping external C functions with Python functions of the same name. +All you need to do is put the extern C declarations into a .pxd file for +an imaginary module, and cimport that module. You can then refer to the C +functions by qualifying them with the name of the module. Here's an example: +
    + +   + + + + + + + + + + + + + + + + + + + + + + +
    c_lunch.pxdlunch.pyx
    cdef extern from "lunch.h": +
    + +     void eject_tomato(float)
    cimport c_lunch +

    def eject_tomato(float speed):
    + +     c_lunch.eject_tomato(speed)

    + +
    + + +

    You don't need any c_lunch.pyx file, because the only things +defined in c_lunch.pxd are extern C entities. There won't be any +actual c_lunch module at run time, but that doesn't matter; the c_lunch.pxd file has done its job of providing an additional namespace at compile time.

    Sharing C Functions

    C +functions defined at the top level of a module can be made available +via cimport by putting headers for them in the .pxd file, for example,

    volume.pxd
    spammery.pyx
    cdef float cube(float)
    from volume cimport cube

    def menu(description, size):
        print description, ":", cube(size), \
    "cubic metres of spam"

    menu("Entree", 1)
    menu("Main course", 3)
    menu("Dessert", 2)
    volume.pyx
    cdef float cube(float x):
        return x * x * x

    Sharing Extension Types

    + + An extension type can be made available via cimport by splitting its definition into two parts, one in +a definition file and the other in the corresponding implementation file. +
    + +
    + + The definition part of the extension type can only declare C attributes +and C methods, not Python methods, and it must declare all of that +type's C attributes and C methods.
    + +
    + + The implementation part must implement all of the C methods declared in +the definition part, and may not add any further C attributes or methods. It may also +define Python methods. +

    Here is an example of a module which defines and exports an extension +type, and another module which uses it.
    + +   + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Shrubbing.pxdShrubbing.pyx
    cdef class Shrubbery:
    + +     cdef int width
    + +     cdef int length
    cdef class Shrubbery:
    + +     def __cinit__(self, int w, int l):
    + +         self.width = w +
    + +         self.length = l + +

    def standard_shrubbery():
    + +     return Shrubbery(3, 7)

    + +
    Landscaping.pyx
    cimport Shrubbing +
    + + import Shrubbing +

    cdef Shrubbing.Shrubbery sh
    + + sh = Shrubbing.standard_shrubbery()
    + + print "Shrubbery size is %d x %d" % (sh.width, sh.length) +
    + +  

    + +
    + +

    + + +

    Some things to note about this example:

    + + +
      + +
    • There is a cdef class Shrubbery declaration in both Shrubbing.pxd + and Shrubbing.pyx. When the Shrubbing module is compiled, these two declarations + are combined into one.
    • + + +  
    • In Landscaping.pyx, the cimport Shrubbing declaration +allows us to refer to the Shrubbery type as Shrubbing.Shrubbery. +But it doesn't bind the name Shrubbing in Landscaping's module namespace + at run time, so to access Shrubbing.standard_shrubbery we also +need to import Shrubbing.
    • + + +
    If you are exporting an extension type that has a base class, the +base class must be declared in the definition part. Repeating the base +class in the implementation part is not necessary, but if you do, it +must match the base class in the definition part.

    Circular cimports

    If +you have two structs, unions or extension types defined in different +.pxd files, and they need to refer to each other, there is a potential +for problems with circular imports. These problems can be avoided by +placing forward declarations of all the structs, unions and extension +types defined in the .pxd file before the first cimport statement.

    For example:

    foo.pxdblarg.pxd
    cdef struct Spam

    from blarg cimport Eggs

    cdef struct Spam:
        Eggs *eggs
    cdef struct Eggs

    from foo cimport Spam

    cdef struct Eggs:
        Spam *spam

    If +the forward declarations weren't present, a circular import problem +would occur, analogous to that which arises in Python when two modules +try to import names from each +other. Placing the forward declarations before the cimport statements ensures that all type names are known to the Pyrex compiler sufficiently far in advance.

    Note +that any .pyx file is free to cimport anything it wants from any .pxd +file without needing this precaution. It's only when two .pxd files +import each other that circular +import issues arise.
    Back to the Language Overview +
    + +
    + + \ No newline at end of file diff --git a/debian/pyrex/pyrex-0.9.9/Doc/Manual/source_files.html b/debian/pyrex/pyrex-0.9.9/Doc/Manual/source_files.html new file mode 100644 index 00000000..0d47fdeb --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Doc/Manual/source_files.html @@ -0,0 +1,78 @@ + +Source Files and Compilation + +

    +
    +Source +Files and Compilation +
    +

    File Names and Extensions

    Pyrex +source file names consist of the name of the module followed by a .pyx extension, +for example a module called primes +would have a source file named primes.pyx.

    Modules in Packages

    If +your module is destined to live in a package, the Pyrex compiler needs +to know the fully-qualified name that the module will eventually have.

    There are currently two ways to give it this information:
    1. Name the source file with the full dotted name of the module. For +example, a module called primes to be installed in a package called numbers would +have a source file called numbers.primes.pyx.

    2. Place the source file in a package directory. To Pyrex, a package directory is one that contains a file called either __init__.py or __init__.pyx. For example, a package called numbers containing a module called primes would have the source files laid out like this:
    numbers
    __init__.py
    primes.pyx

    This will ensure that the __name__ properties of the module and any +classes defined in it are set correctly. If you don't do this, you may +find that pickling doesn't work, among other problems. It also ensures +that the Pyrex compiler has the right idea about the layout of the +module namespace, which can be important when accessing extension types +defined in other modules.
    +

    Building an Extension

    There are two steps involved in creating an extension module from Pyres sources:
    1. Use the Pyrex compiler to translate the .pyx file into a .c file.
    2. Compile the .c file with a C compiler and link it with whatever libraries it needs, to produce an extension module.
    There +are a variety of ways of accomplishing these steps, either separately +or together. One way is to compile the Pyrex source manually from the +command line +with the Pyrex compiler, e.g.
    +
    pyrexc -r primes.pyx
    +

    +This will compile primes.pyx +and any other source files that it depends on, if any of them have +changed since the last compilation, and produce a file called primes.c, +which then needs to be compiled with the C compiler using whatever +options are appropriate on your platform for generating an extension +module.

    You +can perform the C compilation using distutils and a setup.py file, or with a conventional +Makefile. There's a Makefile in the Demos directory (called Makefile.nodistutils) +that shows how to do this for Linux.

    Another approach is to put code at the beginning of your setup.py file to import the Pyrex compiler and call it from Python. You can then follow this with a normal call to setup() to compile the resulting .c files.
    +
    You can also perform both steps at once in a setup.py file using the distutils +extension provided with Pyrex. See the Setup.py +file in the Demos +directory for an example of how to use it. A disadvantage of this +method is that you won't be able to take advantage of Pyrex's own +dependency checking features to compile only the Pyrex sources which +have changed.

    Command Line

    You can run the Pyrex compiler from the command line using either the pyrexc shell command or the Python version of it, pyrexc.py.

    The following command line options exist:

    ShortLongDescription
    -v--versionDisplay the version number of the Pyrex compiler
    -l--create-listingProduces a .lis file for each compiled .pyx file containing error messages
    -I--include-dirSpecifies +a directory to be searched for included files and top-level package +directories. Multiple -I options may be given, each specifying one +directory.
    -o--output-fileSpecifies name of generated C file. Only meaningful when a single .pyx file is being compiled.
    -r--recursiveCompile the given .pyx files, plus those of any modules it depends on directly or indirectly via cimport statements. The include path specified by -I options is used to find the .pyx files of dependent modules.
    -t--timestampsUse +modification times of files to decide whether to compile a .pyx file. +This is the default when -r is used, unless -f is also used.
    -f--forceCompile all .pyx files regardless of modification times. This is the default when -r is not given.
    -q--quietWhen -r is given, don't display the names of source files being compiled.

    Calling the Pyrex compiler from Python

    The module Pyrex.Compiler.Main exports the following classes and functions to facilitate invoking the compiler from another Python program.

    compile(source [, options] [,  option  = value ]...)

    Compiles one or more Pyrex source files, which should be .pyx files. The source argument may be either a single filename or a list of filenames.

    Depending on the recursive option, +it may compile just the specified source files, or the specified source +files plus those of other modules that they depend on via cimport statements. The options may be given either as keyword arguments or a CompilationOptions instance. If both are used, keyword arguments take precedence.

    The return value depends on whether a list of sources was specifed and whether the recursive option is in effect. If a single source file is specified and the recursive option is false, the return value is a CompilationResult instance. Otherwise, the return value is a CompilationResultSet containing a CompilationResult +for each of the modules which were actually compiled (which may or may +not include ones corresponding to the specified source files).

    Note: +If you have more than one source file to compile, it is more efficient +to do so with a single call to compile rather than one call for each +source file. This is because, if more than one source cimports the same +.pxd file, the .pxd file is parsed only once instead of being +parsed each time it is cimported.

    compile_single(source_path [, options] [,  option  = value ]...)

    Compiles just a single .pyx source file, specified as a string, with no dependency or timestamp checking (the recursive and timestamps options are ignored). Always returns a CompilationResult.

    compile_multiple(source_list [, options] [,  option  = value ]...)

    Compiles +a list of .pyx source files, with optional dependency and timestamp +checking as for compile. Always takes a list of source pathnames, and +always returns a CompilationResultSet.

    class CompilationOptions


    A collection of options to be passed to the compile() function. The following options may be specified as keyword arguments to either the CompilationOptions constructor or the compile() function.
    show_version
    Display the version number of the Pyrex compiler.
    use_listing_file
    Produce a .lis file for each .pyx file containing compilation errors.
    include_path
    A list of directories to search for included files and top-level package directories.
    output_file
    Use the given name for the generated .c file (only in non-recursive mode).
    recursive
    Compile the .pyx files of any cimported modules in addition to the one specified.
    timestamps
    Only +compile modified sources as determined by file modification times. This +may be true, false or None. If None, timestamps are used if and only if +recursive mode is in effect.
    quiet
    Don't display names of sources being compiled in recursive mode.
    class CompilationResult

    An object providing information about the result of compiling a .pyx file. It has the following attributes:
    c_file
    Pathname of the generated C source file.
    h_file
    Pathname of the generated C header file, if any.
    api_file
    Pathname of the generated C API header file, if any.
    listing_file
    Pathname of the generated error message file, if any.
    num_errors
    Number of compilation errors.
    class CompilationResultSet
    This is a mapping object whose keys are the pathnames of .pyx files and whose values are the corresponding CompilationResult instances. It also has the following additional attributes:
    num_errors
    Total number of compilation errors.

    Using the distutils extension

    The +distutils extension provided with Pyrex allows you to pass .pyx files +directly to the Extension constructor in your setup file.

    To use it, you need to put the following at the top of your setup.py file:

    from Pyrex.Distutils.extension import Extension
    from Pyrex.Distutils import build_ext

    and you need to specify the Pyrex version of the build_ext command class in your setup() call:

    setup(
        ...
        cmdclass = {'build_ext': build_ext}
    )

    Using +the distutils extension is not currently recommended, because it's +unable to automatically find cimported modules or check the timestamps +of .pxd files and included sources. It also makes it harder to turn off +the use of Pyrex for people who are only installing your module and not +modifying the sources.

    Distributing Pyrex modules

    It +is strongly recommended that you distribute the generated .c files as +well as your Pyrex sources, so that users can install your module +without needing to have Pyrex available.

    It is also recommended that Pyrex compilation not +be enabled by default in the version you distribute. Even if the user +has Pyrex installed, he probably doesn't want to use it just to install +your module. Also, the version he has may not be the same one you used, +and may not compile your sources correctly.

    ---
    \ No newline at end of file diff --git a/debian/pyrex/pyrex-0.9.9/Doc/Manual/special_methods.html b/debian/pyrex/pyrex-0.9.9/Doc/Manual/special_methods.html new file mode 100644 index 00000000..087c51d7 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Doc/Manual/special_methods.html @@ -0,0 +1,1124 @@ + + + + + + + + + Special Methods of Extenstion Types + + + +

    +
    Special Methods of Extension Types +

    + + This page describes the special methods currently supported by Pyrex extension + types. A complete list of all the special methods appears in the table at +the bottom. Some of these methods behave differently from their Python counterparts +or have no direct Python counterparts, and require special mention. +

    Note: Everything said on this page applies only to extension +types, defined with the cdef class statement. It doesn't apply +to classes defined with the Python class statement, where the normal + Python rules apply.

    + + +

    Declaration

    +Special methods of extension types must be declared with def, not cdef.
    + +

    Docstrings

    + + + Currently, docstrings are not fully supported in special methods of extension + types. You can place a docstring in the source to serve as a comment, but + it won't show up in the corresponding __doc__ attribute at run time. (This + is a Python limitation -- there's nowhere in the PyTypeObject data structure + to put such docstrings.) +

    Initialisation methods: __cinit__ and __init__

    + + There are two methods concerned with initialising the object. +

    The __cinit__ method is where you should perform basic C-level +initialisation of the object, including allocation of any C data structures +that your object will own. You need to be careful what you do in the __cinit__ +method, because the object may not yet be a valid Python object when it is +called. Therefore, you must not invoke any Python operations which might touch +the object; in particular, do not try to call any of its methods.

    + + +

    By the time your __cinit__ method is called, memory has been allocated for the object +and any C attributes it has have been initialised to 0 or null. (Any Python +attributes have also been initialised to None, but you probably shouldn't +rely on that.) Your __cinit__ method is guaranteed to be called exactly +once.
    + +
    + +If your extension type has a base type, the __cinit__ method of the +base type is automatically called before your __cinit__ method +is called; you cannot explicitly call the inherited __cinit__ method. +If you need to pass a modified argument list to the base type, you will have +to do the relevant part of the initialisation in the __init__ method +instead (where the normal rules for calling inherited methods apply).
    + +

    + + + + + +

    Any initialisation which cannot safely be done in the __cinit__ +method should be done in the __init__ method. By the time + __init__ is called, the object is a fully valid Python object and +all operations are safe. Under some circumstances it is possible for __init__ +to be called more than once or not to be called at all, so your other methods + should be designed to be robust in such situations.

    + + +

    Any arguments passed to the constructor will be passed + to both the __cinit__ method and the __init__ method. +If you anticipate subclassing your extension type in Python, you may find +it useful to give the __cinit__ method * and ** arguments so that +it can accept and ignore extra arguments. Otherwise, any Python subclass +which has an __init__ with a different signature will have to override __new__ as well as __init__, which the writer of a Python +class wouldn't expect to have to do.

    + + +

    Finalization method: __dealloc__

    + + The counterpart to the __cinit__ method is the __dealloc__ +method, which should perform the inverse of the __cinit__ method. +Any C data structures that you allocated in your __cinit__ method +should be freed in your __dealloc__ method. +

    You need to be careful what you do in a __dealloc__ method. By +the time your __dealloc__ method is called, the object may already +have been partially destroyed and may not be in a valid state as far as Python +is concerned, so you should avoid invoking any Python operations which might +touch the object. In particular, don't call any other methods of the object +or do anything which might cause the object to be resurrected. It's best if +you stick to just deallocating C data.

    + + +

    You don't need to worry about deallocating Python attributes of your object, +because that will be done for you by Pyrex after your __dealloc__ +method returns.
    + +
    + + Note: There is no __del__ method for extension types.
    + +

    + + +

    Arithmetic methods

    + + Arithmetic operator methods, such as __add__, behave differently + from their Python counterparts. There are no separate "reversed" versions + of these methods (__radd__, etc.) Instead, if the first operand +cannot perform the operation, the same method of the second operand +is called, with the operands in the same order. +

    This means that you can't rely on the first parameter of these methods + being "self", and you should test the types of both operands before deciding + what to do. If you can't handle the combination of types you've been given, + you should return NotImplemented.

    + + +

    This also applies to the in-place arithmetic method __ipow__. + It doesn't apply to any of the other in-place methods (__iadd__, + etc.) which always take self as the first argument.

    Rich comparisons

    + + There are no separate methods for the individual rich comparison operations + (__eq__, __le__, etc.) Instead there is a single method + __richcmp__ which takes an integer indicating which operation is +to be performed, as follows: +
      + + +
        + +   + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        +
        <
        + +
        0
        + +
        +
        ==
        + +
        2
        + +
        +
        >
        + +
        4
        +
        <=
        + +
        1
        + +
        +
        !=
        + +
        3
        + +
        +
        >=
        + +
        5
        + + +
      + + +
    + + +

    The __next__ method

    + + Extension types wishing to implement the iterator interface should define + a method called __next__, not next. The Python + system will automatically supply a next method which calls your +__next__. Do NOT explicitly give your type a next method, +or bad things could happen.

    Type Testing in Special Methods (New in 0.9.7)

    When testing the types of operands to your special methods, the obvious way might appear to be to use the isinstance +function. However, this is not completely safe, because it's possible +for a class to override what gets returned by isinstance tests on its +instances. This is not a great problem in Python code, but in Pyrex it +could be disastrous, as we are relying on knowing the C layout of the +objects we're dealing with.

    Pyrex provides an alternative function, typecheck, +which corresponds to PyObject_TypeCheck in the Python/C API. This is +safe to use, as it always tests the actual C type of the object.

    Similarly, there is an issubtype function, corresponding to PyType_IsSubType, as a safe alternative to issubclass.

    As an example, here's how you might write an __add__ method for an extension type called MyNumber:

    def __add__(x, y):
        if typecheck(x, MyNumber):
            # we are the left operand
            if typecheck(y, MyNumber):
                # add ourselves to another MyNumber and return result
            if typecheck(y, int):
                # add ourselves to an int and return result
        elseif typecheck(y, MyNumber):
            # we are the right operand
            if typecheck(x, int):
                # add an int to ourselves and return the result
        # Get here if unknown combination
        return NotImplemented
    +

    Special Method Table

    + + This table lists all of the special methods together with their parameter + and return types. In the table below, a parameter name of self is used to indicate that the parameter has the type that the method + belongs to. Other parameters with no type specified in the table are generic Python objects. +

    You don't have to declare your method as taking these parameter types. + If you declare different types, conversions will be performed as necessary. +
    + +   + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameParametersReturn typeDescription
    General
    __cinit__self, ... Basic initialisation (no direct Python equivalent)
    __init__self, ... Further initialisation
    __dealloc__self Basic deallocation (no direct Python equivalent)
    __cmp__x, yint3-way comparison
    __richcmp__x, y, int opobjectRich comparison (no direct Python equivalent)
    __str__selfobjectstr(self)
    __repr__selfobjectrepr(self)
    __hash__selfintHash function
    __call__self, ...objectself(...)
    __iter__selfobjectReturn iterator for sequence
    __getattr__self, nameobjectGet attribute
    __setattr__self, name, val Set attribute
    __delattr__self, name Delete attribute
    Arithmetic operators
    __add__x, yobjectbinary + operator
    __sub__x, yobjectbinary - operator
    __mul__x, yobject* operator
    __div__x, yobject/  operator for old-style division
    __floordiv__x, yobject//  operator
    __truediv__x, yobject/  operator for new-style division
    __mod__x, yobject% operator
    __divmod__x, yobjectcombined div and mod
    __pow__x, y, zobject** operator or pow(x, y, z)
    __neg__selfobjectunary - operator
    __pos__selfobjectunary + operator
    __abs__selfobjectabsolute value
    __nonzero__selfintconvert to boolean
    __invert__selfobject~ operator
    __lshift__x, yobject<< operator
    __rshift__x, yobject>> operator
    __and__x, yobject& operator
    __or__x, yobject| operator
    __xor__x, yobject^ operator
    Numeric conversions
    __int__selfobjectConvert to integer
    __long__selfobjectConvert to long integer
    __float__selfobjectConvert to float
    __oct__selfobjectConvert to octal
    __hex__selfobjectConvert to hexadecimal
    __index__ (2.5+ only)selfobjectConvert to sequence index
    In-place arithmetic operators
    __iadd__self, xobject+= operator
    __isub__self, xobject-= operator
    __imul__self, xobject*= operator
    __idiv__self, xobject/= operator for old-style division
    __ifloordiv__self, xobject//= operator
    __itruediv__self, xobject/= operator for new-style division
    __imod__self, xobject%= operator
    __ipow__x, y, zobject**= operator
    __ilshift__self, xobject<<= operator
    __irshift__self, xobject>>= operator
    __iand__self, xobject&= operator
    __ior__self, xobject|= operator
    __ixor__self, xobject^= operator
    Sequences and mappings
    __len__selfintlen(self)
    __getitem__self, xobjectself[x]
    __setitem__self, x, y self[x] = y
    __delitem__self, x del self[x]
    __getslice__self, Py_ssize_t i, Py_ssize_t jobjectself[i:j]
    __setslice__self, Py_ssize_t i, Py_ssize_t j, x self[i:j] = x
    __delslice__self, Py_ssize_t i, Py_ssize_t j del self[i:j]
    __contains__self, xintx in self
    Iterators
    __next__selfobjectGet next item (called next in Python)
    Buffer interface  (no Python equivalents + - see note 1)
    __getreadbuffer__self, int i, void **p  
    __getwritebuffer__self, int i, void **p  
    __getsegcount__self, int *p  
    __getcharbuffer__self, int i, char **p  
    Descriptor objects  (see note 2)
    __get__self, instance, classobjectGet value of attribute
    __set__self, instance, value Set value of attribute
    __delete__self, instance Delete attribute
    + +

    + + +

    Note 1: The buffer interface is intended for use by C code and is not +directly accessible from Python. It is described in the Python/C API Reference +Manual under sections 6.6 +and 10.6. +

    + + +

    Note 2: Descriptor objects are part of the support mechanism for new-style + Python classes. See the discussion + of descriptors in the Python documentation. See also PEP 252, "Making Types Look +More Like Classes", and PEP 253, "Subtyping Built-In +Types".

    + +
    + + \ No newline at end of file diff --git a/debian/pyrex/pyrex-0.9.9/Doc/Manual/using_with_c++.html b/debian/pyrex/pyrex-0.9.9/Doc/Manual/using_with_c++.html new file mode 100644 index 00000000..df95c8e7 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Doc/Manual/using_with_c++.html @@ -0,0 +1,7 @@ + +Using with C++

    Using Pyrex with C++

    This section describes some features of Pyrex that are designed to facilitate wrapping of libraries written in C++.

    Source Filenames

    Pyrex source files that use C++ features should be named with an extension of ".pyx+". The corresponding generated C file will then have an extension of ".cpp", and should be compiled with a C++ compiler.

    Note that this only applies to implementation files, not definition files. Definition files should always have an extension of ".pxd", whether they use C++ features or not.

    C++ Structs and Classes

    C++ structs and classes are declared using cdef+ struct, for example,

    cdef extern from "somewhere.h":

        cdef+ struct Shrubbery:
            __init__()
            __init__(float width)
            __init__(float width, int price)
            float width
            int height
            void plant_with_rhododendrons(int howmany)

    Some important things to note:
    • All cdef+ struct declarations must appear inside a cdef extern from block.
    • In Pyrex, struct is used regardless of whether the type is declared as a "struct" or a "class" in C++.
    • Constructors are declared using the name __init__. There can be multiple constructors with different signatures. If no constructor is declared, a single constructor with no arguments is assumed.
    • Destructors are not declared in Pyrex.
    • Member functions are declared without "virtual", whether they are virtual in C++ or not.
    A whole extern from block can also be declared using cdef+ if desired. This can be convenient when declaring a number of C++ types at once.

    cdef+ extern from "shrubbing.h":

        struct Shrubbery:
            ...

    The effect is the same as if cdef+ had been used on all the contained struct declarations. Other declarations appearing in the block are treated as ordinary cdef declarations.

    Inheritance

    A C++ struct may inherit from one or more base structs.

    cdef+ extern from "shrubbing.h":

        struct FancyShrubbery(Shrubbery):
            ...

    Instantiation

    C++ structs can be instantiated using the new operator, similarly to C++.

    cdef Shrubbery *sh1, *sh2, *sh3
    sh1 = new Shrubbery()
    sh2 = new Shrubbery(3.2)
    sh3 = new Shrubbery(4.3, 800)

    Note that parentheses are required even if there are no arguments.

    Disposal

    The del statement can be applied to a pointer to a C++ struct to deallocate it. This is equivalent to delete in C++.

    cdef Shrubbery *big_sh
    big_sh = new Shrubbery(42.0)
    display_in_garden_show(big_sh)
    del big_sh

    Overloaded Functions

    Apart +from the special case of C++ struct constructors, there is no special +support for dealing with overloaded functions in C++. You will need to +declare each version of the function with a different name in Pyrex and +use C name specifications to map them all to the same C++ name. For +example,

    cdef extern from "shrubbing.h":

        void build_with_width "build_shrubbery" (float width)
        void build_with_petunias "build_shrubbery" (int number_of_petunias)

    \ No newline at end of file diff --git a/debian/pyrex/pyrex-0.9.9/Doc/Release_Notes_0.9.9.html b/debian/pyrex/pyrex-0.9.9/Doc/Release_Notes_0.9.9.html new file mode 100644 index 00000000..6a85fc0c --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Doc/Release_Notes_0.9.9.html @@ -0,0 +1,43 @@ + +0.9.9 Release Notes

    Release Notes for Pyrex 0.9.9

    C++ Features

    Some features for interfacing with C++ code have been introduced in this release. Structs declared with 'cdef+ struct' may have constructors and member functions, there is a 'new' operator for instantiating them, and they may be deallocated using the 'del' operator. Details may be found in the Language Overview under Using Pyrex with C++.

    Changes to Exception Semantics

    The +behaviour surrounding exceptions caught using a try-except statement +were previously an inconsistent mixture of Pyrex and Python semantics. +Attempts to make the behaviour match Python more closely were requiring +the generation of increasingly convoluted and inefficient code, so I +decided to backtrack and return to something simpler.

    Pyrex no +longer places caught exceptions into the thread state. This ensures +that exceptions and tracebacks do not leak out of the except clause +that caught them, unless you do something to explicitly preserve them.

    It also means that you cannot retrieve an caught exception in Pyrex using sys.exc_info(). If you want to capture the exception, you need to bind it to a name in the except clause.

    To capture the traceback, the syntax of the except clause has been extended to allow a third argument. For example,
    try:
    start_vehicle()
    except HovercraftError, err, tb:
    print "Can't start:", err
    traceback.print_tb(tb)
    As previously, a raise statement with no arguments must be lexically enclosed in the except +clause which caught the exception that you are trying to re-raise. In +order to re-raise it from somewhere else, you will need to explicity +communicate the exception and traceback to that place and use an +ordinary raise statement.

    Planned Change to None-checking

    Currently, +an argument to a Python function that is declared as an extension type +will, by default, be allowed to receive the value None; to prevent +this, you must qualify the argument declaration with 'not None'.

    This +arrangement has proved to be error-prone, because it requires the +programmer to be aware of the 'not None' feature and to remember to use +it everywhere necessary. Failure to do so results in a Pyrex module +that is prone to being crashed hard if it is passed a None value that +it is not expecting.

    To improve this situation, I am planning to make 'not None' the default in a future release of Pyrex. In order to allow None as a legal argument value, it will be necessary to use an 'or None' qualifier.

    In release 0.9.9, the 'or None' +qualifier may be used, but it is optional. In preparation for the +change of default, the Pyrex compiler will issue a warning (once per +run) if it encounters an extension type argument that is not qualified +with either 'or None' or 'not None'. For example, if Spam and Eggs are extension types and you have a function declared as
    def frobulate(Spam s, Eggs e not None):
    ...
    then in order to eliminate the warning, you will need to change it to
    def frobulate(Spam s or None, Eggs e not None):
    ...
    In a later release, when 'not None' has become the default, it will be possible to drop the 'not None' qualifiers.

    Non-GC Extension Types

    It +is now possible to define and extension type with Python attributes +that does not participate in cyclic garbage collection, using a new nogc option, for example:
    cdef class Spam [nogc]:
    """This class doesn't participate in GC even though
    it has a Python attribute."""
    object sausages

    Other New Features

    Some other minor feature additions and modifications have been made.
    • size_t is now a built-in type and is the type returned by the sizeof operator. Also, the sizes of size_t and Py_ssize_t are now assumed to be somewhere between long and long long.

    • Operations +between two int types of the same rank now return an +unsigned result if either of the operands is unsigned; if the ranks +differ, the result has the same type as the wider-ranked operand. I +think this is the best +approximation of the ANSI C rules that is possible without knowing the +exact sizes of the types.

    • PyString_InternFromString is now exposed under the name cintern rather than intern, because it is not a complete replacement for the Python intern function (it can't handle strings containing null bytes).
    • The +size check that was previously generated when importing an extension +type has been disabled for the time being until I can think of +something better. It was generating too many false positives, for +example from different versions of numpy.

    • The __fastcall calling convention option is now supported. Also, Pyrex no longer assumes that __cdecl +is the default calling convention. To be considered compatible, two +function types must either be declared with the same calling +convention, or both must leave it unspecified.

    • As I have been threatening for some time, using __new__ +as the name of the initialisation method of an extension type has +become an error rather than just a warning. In some future release, __new__ will re-emerge with more Python-like semantics.

    \ No newline at end of file diff --git a/debian/pyrex/pyrex-0.9.9/Doc/index.html b/debian/pyrex/pyrex-0.9.9/Doc/index.html new file mode 100644 index 00000000..e8246f5b --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Doc/index.html @@ -0,0 +1,70 @@ + + + + + Pyrex - Front Page + + +  + + + + + + +
    PyrexA +smooth blend of the finest Python  +
    with the unsurpassed power  +of raw C.
    + +
    Welcome to Pyrex, a language for writing Python +extension modules. Pyrex makes creating an extension module almost as +easy as creating a Python module.
    + +

    +Documentation

    + +
    +

    +About Pyrex

    + +
    Read this to find out what Pyrex is all about +and what it can do for you.
    + +

    +Language +Overview

    + +
    A comined tutorial and reference manual describing of all the features of the Pyrex +language.
    + +

    +FAQ

    + +
    Want to know how to do something in Pyrex? Check +here first.
    +
    + +

    +Other Resources

    + +
    +

    +Michael's +Quick Guide to Pyrex

    + +
    This tutorial-style presentation will take you +through the steps of creating some Pyrex modules to wrap existing C libraries. +Contributed by Michael JasonSmith.
    + +

    +Mail +to the Author

    + +
    If you have a question that's not answered by +anything here, you're not sure about something, or you have a bug to report +or a suggestion to make, or anything at all to say about Pyrex, feel free +to email me: greg.ewing@canterbury.ac.nz
    +
    + + \ No newline at end of file diff --git a/debian/pyrex/pyrex-0.9.9/Doc/primes.c b/debian/pyrex/pyrex-0.9.9/Doc/primes.c new file mode 100644 index 00000000..9a88b84c --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Doc/primes.c @@ -0,0 +1 @@ +#include "Python.h" static PyObject *__Pyx_UnpackItem(PyObject *, int); static int __Pyx_EndUnpack(PyObject *, int); static int __Pyx_PrintItem(PyObject *); static int __Pyx_PrintNewline(void); static void __Pyx_ReRaise(void); static void __Pyx_RaiseWithTraceback(PyObject *, PyObject *, PyObject *); static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); static PyObject *__Pyx_GetExcValue(void); static PyObject *__Pyx_GetName(PyObject *dict, char *name); static PyObject *__pyx_m; static PyObject *__pyx_d; static PyObject *__pyx_b; PyObject *__pyx_f_primes(PyObject *__pyx_self, PyObject *__pyx_args); /*proto*/ PyObject *__pyx_f_primes(PyObject *__pyx_self, PyObject *__pyx_args) { int __pyx_v_kmax; int __pyx_v_n; int __pyx_v_k; int __pyx_v_i; int (__pyx_v_p[1000]); PyObject *__pyx_v_result; PyObject *__pyx_r; PyObject *__pyx_1 = 0; int __pyx_2; int __pyx_3; int __pyx_4; PyObject *__pyx_5 = 0; PyObject *__pyx_6 = 0; if (!PyArg_ParseTuple(__pyx_args, "i", &__pyx_v_kmax)) return 0; __pyx_v_result = Py_None; Py_INCREF(__pyx_v_result); /* "ProjectsA:Python:Pyrex:Demos:primes.pyx":2 */ /* "ProjectsA:Python:Pyrex:Demos:primes.pyx":3 */ /* "ProjectsA:Python:Pyrex:Demos:primes.pyx":4 */ __pyx_1 = PyList_New(0); if (!__pyx_1) goto __pyx_L1; Py_DECREF(__pyx_v_result); __pyx_v_result = __pyx_1; __pyx_1 = 0; /* "ProjectsA:Python:Pyrex:Demos:primes.pyx":5 */ __pyx_2 = (__pyx_v_kmax > 1000); if (__pyx_2) { /* "ProjectsA:Python:Pyrex:Demos:primes.pyx":6 */ __pyx_v_kmax = 1000; goto __pyx_L2; } __pyx_L2:; /* "ProjectsA:Python:Pyrex:Demos:primes.pyx":7 */ __pyx_v_k = 0; /* "ProjectsA:Python:Pyrex:Demos:primes.pyx":8 */ __pyx_v_n = 2; /* "ProjectsA:Python:Pyrex:Demos:primes.pyx":9 */ while (1) { __pyx_L3:; __pyx_2 = (__pyx_v_k < __pyx_v_kmax); if (!__pyx_2) break; /* "ProjectsA:Python:Pyrex:Demos:primes.pyx":10 */ __pyx_v_i = 0; /* "ProjectsA:Python:Pyrex:Demos:primes.pyx":11 */ while (1) { __pyx_L5:; if (__pyx_3 = (__pyx_v_i < __pyx_v_k)) { __pyx_3 = ((__pyx_v_n % (__pyx_v_p[__pyx_v_i])) != 0); } if (!__pyx_3) break; /* "ProjectsA:Python:Pyrex:Demos:primes.pyx":12 */ __pyx_v_i = (__pyx_v_i + 1); } __pyx_L6:; /* "ProjectsA:Python:Pyrex:Demos:primes.pyx":13 */ __pyx_4 = (__pyx_v_i == __pyx_v_k); if (__pyx_4) { /* "ProjectsA:Python:Pyrex:Demos:primes.pyx":14 */ (__pyx_v_p[__pyx_v_k]) = __pyx_v_n; /* "ProjectsA:Python:Pyrex:Demos:primes.pyx":15 */ __pyx_v_k = (__pyx_v_k + 1); /* "ProjectsA:Python:Pyrex:Demos:primes.pyx":16 */ __pyx_1 = PyObject_GetAttrString(__pyx_v_result, "append"); if (!__pyx_1) goto __pyx_L1; __pyx_5 = PyInt_FromLong(__pyx_v_n); if (!__pyx_5) goto __pyx_L1; __pyx_6 = PyTuple_New(1); if (!__pyx_6) goto __pyx_L1; PyTuple_SET_ITEM(__pyx_6, 0, __pyx_5); __pyx_5 = 0; __pyx_5 = PyObject_CallObject(__pyx_1, __pyx_6); if (!__pyx_5) goto __pyx_L1; Py_DECREF(__pyx_6); __pyx_6 = 0; Py_DECREF(__pyx_5); __pyx_5 = 0; goto __pyx_L7; } __pyx_L7:; /* "ProjectsA:Python:Pyrex:Demos:primes.pyx":17 */ __pyx_v_n = (__pyx_v_n + 1); } __pyx_L4:; /* "ProjectsA:Python:Pyrex:Demos:primes.pyx":18 */ Py_INCREF(__pyx_v_result); __pyx_r = __pyx_v_result; goto __pyx_L0; __pyx_r = Py_None; Py_INCREF(__pyx_r); goto __pyx_L0; __pyx_L1:; Py_XDECREF(__pyx_1); Py_XDECREF(__pyx_5); Py_XDECREF(__pyx_6); __pyx_r = 0; __pyx_L0:; Py_DECREF(__pyx_v_result); return __pyx_r; } static struct PyMethodDef __pyx_methods[] = { {"primes", (PyCFunction)__pyx_f_primes, METH_VARARGS, 0}, {0, 0, 0, 0} }; void initprimes(void); /*proto*/ void initprimes(void) { __pyx_m = Py_InitModule4("primes", __pyx_methods, 0, 0, PYTHON_API_VERSION); __pyx_d = PyModule_GetDict(__pyx_m); __pyx_b = PyImport_AddModule("__builtin__"); PyDict_SetItemString(__pyx_d, "__builtins__", __pyx_b); } /* Runtime support code */ \ No newline at end of file diff --git a/debian/pyrex/pyrex-0.9.9/INSTALL.txt b/debian/pyrex/pyrex-0.9.9/INSTALL.txt new file mode 100644 index 00000000..a28d60c8 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/INSTALL.txt @@ -0,0 +1,33 @@ +Pyrex - Installation Instructions +================================= + +You have two installation options: + +(1) Run the setup.py script in this directory + as follows: + + python setup.py install + + This will install the Pyrex package + into your Python system. + +OR + +(2) If you prefer not to modify your Python + installation, arrange for the directory + containing this file (INSTALL.txt) to be in + your module search path. + + For example, create a pyrex.pth file in your + Python installation's Lib/site-packages + directory and insert a line containing the + fully qualified path to the directory containing + this file. + + On unix, also put the bin directory on your PATH. + + On Win32 copy the pyrexc.py file to your Python + installation's Scripts directory, which should + already be on the PATH. + +See README.txt for pointers to other documentation. diff --git a/debian/pyrex/pyrex-0.9.9/LICENSE.txt b/debian/pyrex/pyrex-0.9.9/LICENSE.txt new file mode 100644 index 00000000..ca14331a --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/LICENSE.txt @@ -0,0 +1,173 @@ +Apache License Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, +and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the +copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other +entities that control, are controlled by, or are under common control +with that entity. For the purposes of this definition, "control" means +(i) the power, direct or indirect, to cause the direction or +management of such entity, whether by contract or otherwise, or (ii) +ownership of fifty percent (50%) or more of the outstanding shares, or +(iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation +source, and configuration files. + +"Object" form shall mean any form resulting from mechanical +transformation or translation of a Source form, including but not +limited to compiled object code, generated documentation, and +conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object +form, made available under the License, as indicated by a copyright +notice that is included in or attached to the work (an example is +provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object +form, that is based on (or derived from) the Work and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. For the +purposes of this License, Derivative Works shall not include works +that remain separable from, or merely link (or bind by name) to the +interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the +original version of the Work and any modifications or additions to +that Work or Derivative Works thereof, that is intentionally submitted +to Licensor for inclusion in the Work by the copyright owner or by an +individual or Legal Entity authorized to submit on behalf of the +copyright owner. For the purposes of this definition, "submitted" +means any form of electronic, verbal, or written communication sent to +the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control +systems, and issue tracking systems that are managed by, or on behalf +of, the Licensor for the purpose of discussing and improving the Work, +but excluding communication that is conspicuously marked or otherwise +designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity +on behalf of whom a Contribution has been received by Licensor and +subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +copyright license to reproduce, prepare Derivative Works of, publicly +display, publicly perform, sublicense, and distribute the Work and +such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except +as stated in this section) patent license to make, have made, use, +offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such +Contributor that are necessarily infringed by their Contribution(s) +alone or by combination of their Contribution(s) with the Work to +which such Contribution(s) was submitted. If You institute patent +litigation against any entity (including a cross-claim or counterclaim +in a lawsuit) alleging that the Work or a Contribution incorporated +within the Work constitutes direct or contributory patent +infringement, then any patent licenses granted to You under this +License for that Work shall terminate as of the date such litigation +is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work +or Derivative Works thereof in any medium, with or without +modifications, and in Source or Object form, provided that You meet +the following conditions: + +1. You must give any other recipients of the Work or Derivative Works +a copy of this License; and + +2. You must cause any modified files to carry prominent notices +stating that You changed the files; and + +3. You must retain, in the Source form of any Derivative Works that +You distribute, all copyright, patent, trademark, and attribution +notices from the Source form of the Work, excluding those notices that +do not pertain to any part of the Derivative Works; and + +4. If the Work includes a "NOTICE" text file as part of its +distribution, then any Derivative Works that You distribute must +include a readable copy of the attribution notices contained within +such NOTICE file, excluding those notices that do not pertain to any +part of the Derivative Works, in at least one of the following places: +within a NOTICE text file distributed as part of the Derivative Works; +within the Source form or documentation, if provided along with the +Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The +contents of the NOTICE file are for informational purposes only and do +not modify the License. You may add Your own attribution notices +within Derivative Works that You distribute, alongside or as an +addendum to the NOTICE text from the Work, provided that such +additional attribution notices cannot be construed as modifying the +License. + +You may add Your own copyright statement to Your modifications and may +provide additional or different license terms and conditions for use, +reproduction, or distribution of Your modifications, or for any such +Derivative Works as a whole, provided Your use, reproduction, and +distribution of the Work otherwise complies with the conditions stated +in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, +any Contribution intentionally submitted for inclusion in the Work by +You to the Licensor shall be under the terms and conditions of this +License, without any additional terms or conditions. Notwithstanding +the above, nothing herein shall supersede or modify the terms of any +separate license agreement you may have executed with Licensor +regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade +names, trademarks, service marks, or product names of the Licensor, +except as required for reasonable and customary use in describing the +origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed +to in writing, Licensor provides the Work (and each Contributor +provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied, including, without +limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, +MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely +responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your +exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, +whether in tort (including negligence), contract, or otherwise, unless +required by applicable law (such as deliberate and grossly negligent +acts) or agreed to in writing, shall any Contributor be liable to You +for damages, including any direct, indirect, special, incidental, or +consequential damages of any character arising as a result of this +License or out of the use or inability to use the Work (including but +not limited to damages for loss of goodwill, work stoppage, computer +failure or malfunction, or any and all other commercial damages or +losses), even if such Contributor has been advised of the possibility +of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing +the Work or Derivative Works thereof, You may choose to offer, and +charge a fee for, acceptance of support, warranty, indemnity, or other +liability obligations and/or rights consistent with this License. +However, in accepting such obligations, You may act only on Your own +behalf and on Your sole responsibility, not on behalf of any other +Contributor, and only if You agree to indemnify, defend, and hold each +Contributor harmless for any liability incurred by, or claims asserted +against, such Contributor by reason of your accepting any such +warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/debian/pyrex/pyrex-0.9.9/MANIFEST.in b/debian/pyrex/pyrex-0.9.9/MANIFEST.in new file mode 100644 index 00000000..7710f3e0 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/MANIFEST.in @@ -0,0 +1,7 @@ +include MANIFEST.in README.txt INSTALL.txt CHANGES.txt ToDo.txt USAGE.txt +include setup.py +include bin/pyrexc +include pyrexc.py +include Pyrex/Compiler/Lexicon.pickle +include Doc/* +include Demos/* diff --git a/debian/pyrex/pyrex-0.9.9/Makefile b/debian/pyrex/pyrex-0.9.9/Makefile new file mode 100644 index 00000000..7042e68a --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Makefile @@ -0,0 +1,15 @@ +VERSION = 0.9.9 + +version: + @echo "Setting version to $(VERSION)" + @echo "version = '$(VERSION)'" > Pyrex/Compiler/Version.py + +clean: + @echo Cleaning Source + @rm -f *.pyc */*.pyc */*/*.pyc + @rm -f *~ */*~ */*/*~ + @rm -f core */core + @(cd Demos; $(MAKE) clean) + +test_setup: + python setup.py --dry-run install diff --git a/debian/pyrex/pyrex-0.9.9/Obsolete/PyrexTypes.py.old b/debian/pyrex/pyrex-0.9.9/Obsolete/PyrexTypes.py.old new file mode 100644 index 00000000..ef581dd0 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Obsolete/PyrexTypes.py.old @@ -0,0 +1,829 @@ +# +# Pyrex - Types +# + +import string +import Naming + +class PyrexType: + # + # Base class for all Pyrex types. + # + # is_pyobject boolean Is a Python object type + # is_extension_type boolean Is a Python extension type + # is_numeric boolean Is a C numeric type + # is_int boolean Is a C integer type + # is_float boolean Is a C floating point type + # is_void boolean Is the C void type + # is_array boolean Is a C array type + # is_ptr boolean Is a C pointer type + # is_null_ptr boolean Is the type of NULL + # is_cfunction boolean Is a C function type + # is_struct_or_union boolean Is a C struct or union type + # is_enum boolean Is a C enum type + # is_string boolean Is a C char * type + # is_returncode boolean Is used only to signal exceptions + # is_error boolean Is the dummy error type + # has_attributes boolean Has C dot-selectable attributes + # default_value string Initial value + # parsetuple_format string Format char for PyArg_ParseTuple + # pymemberdef_typecode string Type code for PyMemberDef struct + # + # declaration_code(entity_code, + # for_display = 0, dll_linkage = None, pyrex = 0) + # Returns a code fragment for the declaration of an entity + # of this type, given a code fragment for the entity. + # * If for_display, this is for reading by a human in an error + # message; otherwise it must be valid C code. + # * If dll_linkage is not None, it must be 'DL_EXPORT' or + # 'DL_IMPORT', and will be added to the base type part of + # the declaration. + # * If pyrex = 1, this is for use in a 'cdef extern' + # statement of a Pyrex include file. + # + # assignable_from(src_type) + # Tests whether a variable of this type can be + # assigned a value of type src_type. + # + # same_as(other_type) + # Tests whether this type represents the same type + # as other_type. + # + # as_argument_type(): + # Coerces array type into pointer type for use as + # a formal argument type. + # + + is_pyobject = 0 + is_extension_type = 0 + is_numeric = 0 + is_int = 0 + is_float = 0 + is_void = 0 + is_array = 0 + is_ptr = 0 + is_null_ptr = 0 + is_cfunction = 0 + is_struct_or_union = 0 + is_enum = 0 + is_string = 0 + is_returncode = 0 + is_error = 0 + has_attributes = 0 + default_value = "" + parsetuple_format = "" + pymemberdef_typecode = None + + def resolve(self): + # If a typedef, returns the base type. + return self + + def literal_code(self, value): + # Returns a C code fragment representing a literal + # value of this type. + return str(value) + + def __str__(self): + return string.strip(self.declaration_code("", for_display = 1)) + + def same_as(self, other_type, **kwds): + return self.same_as_resolved_type(other_type.resolve(), **kwds) + + def same_as_resolved_type(self, other_type): + return self is other_type or other_type is error_type + + def subtype_of(self, other_type): + return self.subtype_of_resolved_type(other_type.resolve()) + + def subtype_of_resolved_type(self, other_type): + return self.same_as(other_type) + + def assignable_from(self, src_type): + return self.assignable_from_resolved_type(src_type.resolve()) + + def assignable_from_resolved_type(self, src_type): + return self.same_as(src_type) + + def as_argument_type(self): + return self + + def is_complete(self): + # A type is incomplete if it is an unsized array, + # a struct whose attributes are not defined, etc. + return 1 + + def cast_code(self, expr_code): + return "((%s)%s)" % (self.declaration_code(""), expr_code) + + +class CTypedefType: + # + # Type defined with a ctypedef statement in a + # 'cdef extern from' block. Delegates most attribute + # lookups to the base type. + # + + def __init__(self, cname, base_type): + self.typedef_cname = cname + self.typedef_base_type = base_type + + def resolve(self): + return self.typedef_base_type.resolve() + + def declaration_code(self, entity_code, + for_display = 0, dll_linkage = None, pyrex = 0): + return "%s %s" % (self.typedef_cname, entity_code) + + def as_argument_type(self): + return self + + def __str__(self): + return self.typedef_cname + + def __getattr__(self, name): + return getattr(self.typedef_base_type, name) + + +class PyObjectType(PyrexType): + # + # Base class for all Python object types (reference-counted). + # + + is_pyobject = 1 + default_value = "0" + parsetuple_format = "O" + pymemberdef_typecode = "T_OBJECT" + + def __str__(self): + return "Python object" + + def __repr__(self): + return "PyObjectType" + + def assignable_from(self, src_type): + return 1 # Conversion will be attempted + + def declaration_code(self, entity_code, + for_display = 0, dll_linkage = None, pyrex = 0): + if pyrex: + return "object %s" % entity_code + else: + return "%s *%s" % (public_decl("PyObject", dll_linkage), entity_code) + + +class PyExtensionType(PyObjectType): + # + # A Python extension type. + # + # name string + # scope CClassScope Attribute namespace + # visibility string + # typedef_flag boolean + # base_type PyExtensionType or None + # module_name string or None Qualified name of defining module + # objstruct_cname string Name of PyObject struct + # typeobj_cname string or None C code fragment referring to type object + # typeptr_cname string or None Name of pointer to external type object + # vtabslot_cname string Name of C method table member + # vtabstruct_cname string Name of C method table struct + # vtabptr_cname string Name of pointer to C method table + # vtable_cname string Name of C method table definition + + is_extension_type = 1 + has_attributes = 1 + + def __init__(self, name, typedef_flag, base_type): + self.name = name + self.scope = None + self.typedef_flag = typedef_flag + self.base_type = base_type + self.module_name = None + self.objstruct_cname = None + self.typeobj_cname = None + self.typeptr_cname = None + self.vtabslot_cname = None + self.vtabstruct_cname = None + self.vtabptr_cname = None + self.vtable_cname = None + + def set_scope(self, scope): + self.scope = scope + if scope: + scope.parent_type = self + + def subtype_of_resolved_type(self, other_type): + if other_type.is_extension_type: + return self is other_type or ( + self.base_type and self.base_type.subtype_of(other_type)) + else: + return other_type is py_object_type + + def typeobj_is_available(self): + # Do we have a pointer to the type object? + return self.typeptr_cname + + def typeobj_is_imported(self): + # If we don't know the C name of the type object but we do + # know which module it's defined in, it will be imported. + return self.typeobj_cname is None and self.module_name is not None + + def declaration_code(self, entity_code, + for_display = 0, dll_linkage = None, pyrex = 0): + if pyrex: + return "%s %s" % (self.name, entity_code) + else: + if self.typedef_flag: + base_format = "%s" + else: + base_format = "struct %s" + base = public_decl(base_format % self.objstruct_cname, dll_linkage) + return "%s *%s" % (base, entity_code) + + def attributes_known(self): + return self.scope is not None + + def __str__(self): + return self.name + + def __repr__(self): + return "PyExtensionType(%s%s)" % (self.scope.class_name, + ("", ".typedef_flag=1")[self.typedef_flag]) + + +class CType(PyrexType): + # + # Base class for all C types (non-reference-counted). + # + # to_py_function string C function for converting to Python object + # from_py_function string C function for constructing from Python object + # + + to_py_function = None + from_py_function = None + + +#class CSimpleType(CType): +# # +# # Base class for all unstructured C types. +# # +# pass + + +class CVoidType(CType): + is_void = 1 + + def __repr__(self): + return "" + + def declaration_code(self, entity_code, + for_display = 0, dll_linkage = None, pyrex = 0): + base = public_decl("void", dll_linkage) + return "%s %s" % (base, entity_code) + + def is_complete(self): + return 0 + + +class CNumericType(CType): + # + # Base class for all C numeric types. + # + # rank integer Relative size + # signed boolean + # + + is_numeric = 1 + default_value = "0" + + parsetuple_formats = ( # rank -> format + "?HIkK???", # unsigned + "chilLfd?", # signed + ) + + def __init__(self, rank, signed = 1, pymemberdef_typecode = None): + self.rank = rank + self.signed = signed + ptf = self.parsetuple_formats[signed][rank] + if ptf == '?': + ptf = None + self.parsetuple_format = ptf + self.pymemberdef_typecode = pymemberdef_typecode + + def __repr__(self): + if self.signed: + u = "" + else: + u = "unsigned " + return "" % (u, rank_to_type_name[self.rank]) + + def declaration_code(self, entity_code, + for_display = 0, dll_linkage = None, pyrex = 0): + if self.signed: + u = "" + else: + u = "unsigned " + base = public_decl(u + rank_to_type_name[self.rank], dll_linkage) + return "%s %s" % (base, entity_code) + + +class CIntType(CNumericType): + + is_int = 1 + typedef_flag = 0 + to_py_function = "PyInt_FromLong" + from_py_function = "PyInt_AsLong" + + def __init__(self, rank, signed, pymemberdef_typecode = None, is_returncode = 0): + CNumericType.__init__(self, rank, signed, pymemberdef_typecode) + self.is_returncode = is_returncode + + def assignable_from_resolved_type(self, src_type): + return src_type.is_int or src_type.is_enum or src_type is error_type + + +class CUIntType(CIntType): + + to_py_function = "PyLong_FromUnsignedLong" + from_py_function = "PyInt_AsUnsignedLongMask" + + +class CULongType(CIntType): + + to_py_function = "PyLong_FromUnsignedLong" + from_py_function = "PyInt_AsUnsignedLongMask" + + +class CLongLongType(CIntType): + + to_py_function = "PyLong_FromLongLong" + from_py_function = "PyInt_AsUnsignedLongLongMask" + + +class CULongLongType(CIntType): + + to_py_function = "PyLong_FromUnsignedLongLong" + from_py_function = "PyInt_AsUnsignedLongLongMask" + + +class CFloatType(CNumericType): + + is_float = 1 + to_py_function = "PyFloat_FromDouble" + from_py_function = "PyFloat_AsDouble" + + def __init__(self, rank, pymemberdef_typecode = None): + CNumericType.__init__(self, rank, 1, pymemberdef_typecode) + + def assignable_from_resolved_type(self, src_type): + return src_type.is_numeric or src_type is error_type + + +class CArrayType(CType): + # base_type CType Element type + # size integer or None Number of elements + + is_array = 1 + + def __init__(self, base_type, size): + self.base_type = base_type + self.size = size + if base_type is c_char_type: + self.is_string = 1 + + def __repr__(self): + return "CArrayType(%s,%s)" % (self.size, repr(self.base_type)) + + def same_as_resolved_type(self, other_type): + return ((other_type.is_array and + self.base_type.same_as(other_type.base_type)) + or other_type is error_type) + + def assignable_from_resolved_type(self, src_type): + # Can't assign to a variable of an array type + return 0 + + def element_ptr_type(self): + return c_ptr_type(self.base_type) + + def declaration_code(self, entity_code, + for_display = 0, dll_linkage = None, pyrex = 0): + if self.size is not None: + dimension_code = self.size + else: + dimension_code = "" + return self.base_type.declaration_code( + "(%s[%s])" % (entity_code, dimension_code), + for_display, dll_linkage, pyrex) + + def as_argument_type(self): + return c_ptr_type(self.base_type) + + def is_complete(self): + return self.size is not None + + +class CPtrType(CType): + # base_type CType Referenced type + + is_ptr = 1 + default_value = 0 + + def __init__(self, base_type): + self.base_type = base_type + + def __repr__(self): + return "CPtrType(%s)" % repr(self.base_type) + + def same_as_resolved_type(self, other_type): + return ((other_type.is_ptr and + self.base_type.same_as(other_type.base_type)) + or other_type is error_type) + + def declaration_code(self, entity_code, + for_display = 0, dll_linkage = None, pyrex = 0): + #print "CPtrType.declaration_code: pointer to", self.base_type ### + return self.base_type.declaration_code( + "(*%s)" % entity_code, + for_display, dll_linkage, pyrex) + + def assignable_from_resolved_type(self, other_type): + if other_type is error_type: + return 1 + elif self.base_type.is_cfunction and other_type.is_cfunction: + return self.base_type.same_as(other_type) + elif other_type.is_array: + return self.base_type.same_as(other_type.base_type) + elif not other_type.is_ptr: + return 0 + elif self.base_type.is_void: + return 1 + elif other_type.is_null_ptr: + return 1 + else: + return self.base_type.same_as(other_type.base_type) + + +class CNullPtrType(CPtrType): + + is_null_ptr = 1 + + +class CFuncType(CType): + # return_type CType + # args [CFuncTypeArg] + # has_varargs boolean + # exception_value string + # exception_check boolean True if PyErr_Occurred check needed + + is_cfunction = 1 + + def __init__(self, return_type, args, has_varargs, + exception_value = None, exception_check = 0): + self.return_type = return_type + self.args = args + self.has_varargs = has_varargs + self.exception_value = exception_value + self.exception_check = exception_check + + def __repr__(self): + arg_reprs = map(repr, self.args) + if self.has_varargs: + arg_reprs.append("...") + return "CFuncType(%s,[%s])" % ( + repr(self.return_type), + string.join(arg_reprs, ",")) + + def same_c_signature_as(self, other_type, as_cmethod = 0): + return self.same_c_signature_as_resolved_type( + other_type.resolve(), as_cmethod) + + def same_c_signature_as_resolved_type(self, other_type, as_cmethod): + if other_type is error_type: + return 1 + if not other_type.is_cfunction: + return 0 + nargs = len(self.args) + if nargs <> len(other_type.args): + return 0 + # When comparing C method signatures, the first argument + # is exempt from compatibility checking (the proper check + # is performed elsewhere). + for i in range(as_cmethod, nargs): + if not self.args[i].type.same_as( + other_type.args[i].type): + return 0 + if self.has_varargs <> other_type.has_varargs: + return 0 + if not self.return_type.same_as(other_type.return_type): + return 0 + return 1 + + def same_exception_signature_as(self, other_type): + return self.same_exception_signature_as_resolved_type( + other_type.resolve()) + + def same_exception_signature_as_resolved_type(self, other_type): + return self.exception_value == other_type.exception_value \ + and self.exception_check == other_type.exception_check + + def same_as_resolved_type(self, other_type, as_cmethod = 0): + return self.same_c_signature_as_resolved_type(other_type, as_cmethod) \ + and self.same_exception_signature_as_resolved_type(other_type) + + def declaration_code(self, entity_code, + for_display = 0, dll_linkage = None, pyrex = 0): + arg_decl_list = [] + for arg in self.args: + arg_decl_list.append( + arg.type.declaration_code("", for_display, pyrex = pyrex)) + if self.has_varargs: + arg_decl_list.append("...") + arg_decl_code = string.join(arg_decl_list, ",") + if not arg_decl_code and not pyrex: + arg_decl_code = "void" + exc_clause = "" + if pyrex or for_display: + if self.exception_value and self.exception_check: + exc_clause = " except? %s" % self.exception_value + elif self.exception_value: + exc_clause = " except %s" % self.exception_value + elif self.exception_check: + exc_clause = " except *" + return self.return_type.declaration_code( + "(%s(%s)%s)" % (entity_code, arg_decl_code, exc_clause), + for_display, dll_linkage, pyrex) + + +class CFuncTypeArg: + # name string + # cname string + # type PyrexType + # pos source file position + + def __init__(self, name, type, pos): + self.name = name + self.cname = Naming.var_prefix + name + self.type = type + self.pos = pos + + def __repr__(self): + return "%s:%s" % (self.name, repr(self.type)) + + def declaration_code(self, for_display = 0): + return self.type.declaration_code(self.cname, for_display) + + +class CStructOrUnionType(CType): + # name string + # cname string + # kind string "struct" or "union" + # scope StructOrUnionScope, or None if incomplete + # typedef_flag boolean + + is_struct_or_union = 1 + has_attributes = 1 + + def __init__(self, name, kind, scope, typedef_flag, cname): + self.name = name + self.cname = cname + self.kind = kind + self.scope = scope + self.typedef_flag = typedef_flag + + def __repr__(self): + return "CStructOrUnionType(%s,%s%s)" % (self.name, self.cname, + ("", ",typedef_flag=1")[self.typedef_flag]) + + def declaration_code(self, entity_code, + for_display = 0, dll_linkage = None, pyrex = 0): + if pyrex: + return "%s %s" % (self.name, entity_code) + else: + if for_display: + base = self.name + elif self.typedef_flag: + base = self.cname + else: + base = "%s %s" % (self.kind, self.cname) + return "%s %s" % (public_decl(base, dll_linkage), entity_code) + + def is_complete(self): + return self.scope is not None + + def attributes_known(self): + return self.is_complete() + + +class CEnumType(CType): + # name string + # cname string or None + # typedef_flag boolean + + is_enum = 1 + #signed = 1 + #rank = 2 + to_py_function = "PyInt_FromLong" + from_py_function = "PyInt_AsLong" + + def __init__(self, name, cname, typedef_flag): + self.name = name + self.cname = cname + self.values = [] + self.typedef_flag = typedef_flag + + def __repr__(self): + return "CEnumType(%s,%s%s)" % (self.name, self.cname, + ("", ",typedef_flag=1")[self.typedef_flag]) + + def declaration_code(self, entity_code, + for_display = 0, dll_linkage = None, pyrex = 0): + if pyrex: + return "%s %s" % (self.cname, entity_code) + else: + if self.typedef_flag: + base = self.cname + else: + base = "enum %s" % self.cname + return "%s %s" % (public_decl(base, dll_linkage), entity_code) + + +class CStringType: + # Mixin class for C string types. + + is_string = 1 + + to_py_function = "PyString_FromString" + from_py_function = "PyString_AsString" + + def literal_code(self, value): + return '"%s"' % value + + +class CCharArrayType(CStringType, CArrayType): + # C 'char []' type. + + parsetuple_format = "s" + pymemberdef_typecode = "T_STRING_INPLACE" + + def __init__(self, size): + CArrayType.__init__(self, c_char_type, size) + + +class CCharPtrType(CStringType, CPtrType): + # C 'char *' type. + + parsetuple_format = "s" + pymemberdef_typecode = "T_STRING" + + def __init__(self): + CPtrType.__init__(self, c_char_type) + + +class ErrorType(PyrexType): + # Used to prevent propagation of error messages. + + is_error = 1 + exception_value = "0" + exception_check = 0 + to_py_function = "dummy" + from_py_function = "dummy" + + def declaration_code(self, entity_code, + for_display = 0, dll_linkage = None, pyrex = 0): + return "" + + def same_as_resolved_type(self, other_type): + return 1 + + +py_object_type = PyObjectType() + +c_void_type = CVoidType() +c_void_ptr_type = CPtrType(c_void_type) +c_void_ptr_ptr_type = CPtrType(c_void_ptr_type) + +c_char_type = CIntType(0, 1, "T_CHAR") +c_short_type = CIntType(1, 1, "T_SHORT") +c_int_type = CIntType(2, 1, "T_INT") +c_long_type = CIntType(3, 1, "T_LONG") +c_longlong_type = CLongLongType(4, 1, "T_LONGLONG") + +c_uchar_type = CIntType(0, 0, "T_UBYTE") +c_ushort_type = CIntType(1, 0, "T_USHORT") +c_uint_type = CUIntType(2, 0, "T_UINT") +c_ulong_type = CULongType(3, 0, "T_ULONG") +c_ulonglong_type = CULongLongType(4, 0, "T_ULONGLONG") + +c_float_type = CFloatType(5, "T_FLOAT") +c_double_type = CFloatType(6, "T_DOUBLE") +c_longdouble_type = CFloatType(7) + +c_null_ptr_type = CNullPtrType(c_void_type) +c_char_array_type = CCharArrayType(None) +c_char_ptr_type = CCharPtrType() +c_char_ptr_ptr_type = CPtrType(c_char_ptr_type) +c_int_ptr_type = CPtrType(c_int_type) + +c_returncode_type = CIntType(2, 1, "T_INT", is_returncode = 1) + +error_type = ErrorType() + +lowest_float_rank = 5 + +rank_to_type_name = ( + "char", # 0 + "short", # 1 + "int", # 2 + "long", # 3 + "PY_LONG_LONG", # 4 + "float", # 5 + "double", # 6 + "long double", # 7 +) + +sign_and_rank_to_type = { + #(signed, rank) + (0, 0, ): c_uchar_type, + (0, 1): c_ushort_type, + (0, 2): c_uint_type, + (0, 3): c_ulong_type, + (0, 4): c_ulonglong_type, + (1, 0): c_char_type, + (1, 1): c_short_type, + (1, 2): c_int_type, + (1, 3): c_long_type, + (1, 4): c_longlong_type, + (1, 5): c_float_type, + (1, 6): c_double_type, + (1, 7): c_longdouble_type, +} + +modifiers_and_name_to_type = { + #(signed, longness, name) + (0, 0, "char"): c_uchar_type, + (0, -1, "int"): c_ushort_type, + (0, 0, "int"): c_uint_type, + (0, 1, "int"): c_ulong_type, + (0, 2, "int"): c_ulonglong_type, + (1, 0, "void"): c_void_type, + (1, 0, "char"): c_char_type, + (1, -1, "int"): c_short_type, + (1, 0, "int"): c_int_type, + (1, 1, "int"): c_long_type, + (1, 2, "int"): c_longlong_type, + (1, 0, "float"): c_float_type, + (1, 0, "double"): c_double_type, + (1, 1, "double"): c_longdouble_type, + (1, 0, "object"): py_object_type, +} + +def widest_numeric_type(type1, type2): + # Given two numeric types, return the narrowest type + # encompassing both of them. + signed = type1.signed + rank = max(type1.rank, type2.rank) + if rank >= lowest_float_rank: + signed = 1 + return sign_and_rank_to_type[signed, rank] + +def simple_c_type(signed, longness, name): + # Find type descriptor for simple type given name and modifiers. + # Returns None if arguments don't make sense. + return modifiers_and_name_to_type.get((signed, longness, name)) + +def c_array_type(base_type, size): + # Construct a C array type. + if base_type is c_char_type: + return CCharArrayType(size) + else: + return CArrayType(base_type, size) + +def c_ptr_type(base_type): + # Construct a C pointer type. + if base_type is c_char_type: + return c_char_ptr_type + else: + return CPtrType(base_type) + +def public_decl(base, dll_linkage): + if dll_linkage: + return "%s(%s)" % (dll_linkage, base) + else: + return base + +def same_type(type1, type2): + return type1.same_as(type2) + +def assignable_from(type1, type2): + return type1.assignable_from(type2) + +def typecast(to_type, from_type, expr_code): + # Return expr_code cast to a C type which can be + # assigned to to_type, assuming its existing C type + # is from_type. + if to_type is from_type or \ + (not to_type.is_pyobject and assignable_from(to_type, from_type)): + return expr_code + else: + #print "typecast: to", to_type, "from", from_type ### + return to_type.cast_code(expr_code) diff --git a/debian/pyrex/pyrex-0.9.9/Obsolete/overview.html b/debian/pyrex/pyrex-0.9.9/Obsolete/overview.html new file mode 100644 index 00000000..f37a3e36 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Obsolete/overview.html @@ -0,0 +1,1485 @@ + +Pyrex Language Overview + + + +

    +
    Overview of the Pyrex Language  +

    + + + This document informally describes the extensions to the Python language + made by Pyrex. Some day there will be a reference manual covering everything + in more detail. 

    Contents

    + + + + + + + +

    +

    +

    Source Files and Compilation
    +

    +

    +Pyrex source file names consist of the name of the module followed by a .pyx extension, for example a module called primes would have a source file named primes.pyx.
    + +
    + +If your module is destined to live in a package, the source file name should include the full dotted name that the module will eventually have. For example, a module called primes that will be installed in a package called numbers should have a source file called numbers.primes.pyx. +This will ensure that the __name__ properties of the module and any +classes defined in it are set correctly. If you don't do this, you may +find that pickling doesn't work, among other problems. It also ensures +that the Pyrex compiler has the right idea about the layout of the +module namespace, which can be important when accessing extension types +defined in other modules.
    +
    +Once you have written your .pyx file, there are a couple of ways of +turning it into an extension module. One way is to compile it manually +with the Pyrex compiler, e.g.
    +
    +
    pyrexc primes.pyx
    +
    +
    +This will produce a file called primes.c, +which then needs to be compiled with the C compiler using whatever +options are appropriate on your platform for generating an extension +module. There's a Makefile in the Demos directory (called Makefile.nodistutils) that shows how to do this for Linux.
    +
    +The other, and probably better, way is to use the distutils extension provided with Pyrex. See the Setup.py +file in the Demos directory for an example of how to use it. This +method has the advantage of being cross-platform -- the same setup file +should work on any platform where distutils can compile an extension +module.
    +
    +
    +

    Language Basics +

    +This section describes the basic features of the Pyrex language. The facilities + covered in this section allow you to create Python-callable functions that + manipulate C data structures and convert between Python and C data types. + Later sections will cover facilities for wrapping external C code, creating new Python types and cooperation between Pyrex modules.
    + +

    Python functions vs. C functions

    + + + There are two kinds of function definition in Pyrex: +

    Python functions are defined using the def statement, as + in Python. They take Python objects as parameters and return Python objects. +

    + + + +

    C functions are defined using the new cdef statement. They + take either Python objects or C values as parameters, and can return either + Python objects or C values.

    + + + +

    Within a Pyrex module, Python functions and C functions can call each other +freely, but only Python functions can be called from outside the module by +interpreted Python code. So, any functions that you want to "export" from + your Pyrex module must be declared as Python functions using def.

    + + + +

    Parameters of either type of function can be declared to have C data types, + using normal C declaration syntax. For example,

    + + + +
    +
    def spam(int i, char *s):
        ...
    + + +
    cdef int eggs(unsigned long l, float f):
        ...
    + +
    + + + When a parameter of a Python function is declared to have a C data type, + it is passed in as a Python object and automatically converted to a C value, + if possible. Automatic conversion is currently only possible for numeric +types and string types; attempting to use any other type for the parameter +of a Python function will result in a compile-time error. +

    C functions, on the other hand, can have parameters of any type, since + they're passed in directly using a normal C function call.

    + + + +

    Python objects as parameters and return values

    + + + If no type is specified for a parameter or return value, it is assumed + to be a Python object. (Note that this is different from the C convention, + where it would default to int.) For example, the following defines + a C function that takes two Python objects as parameters and returns a Python + object: +
    +
    cdef spamobjs(x, y):
        ...
    + +
    + + + Reference counting for these objects is performed automatically according + to the standard Python/C API rules (i.e. borrowed references are taken as + parameters and a new reference is returned). +

    The name object can also be used to explicitly declare something + as a Python object. This can be useful if the name being declared would otherwise +be taken as the name of a type, for example,

    + + + +
    +
    cdef ftang(object int):
        ...
    + +
    + + + declares a parameter called int which is a Python object. You +can also use object as the explicit return type of a function, e.g. + +
    +
    cdef object ftang(object int):
        ...
    + +
    + + + In the interests of clarity, it is probably a good idea to always be explicit + about object parameters in C functions. +

    C variable and type definitions

    + + + The cdef statement is also used to declare C variables, either +local or module-level: +
    +
    cdef int i, j, k
    cdef float f, g[42], *h
    + +
    + + + and C struct, union or enum types: +
    +
    cdef struct Grail:
        int age
        float volume
    + + +
    cdef union Food:
        char *spam
        float *eggs
    + + +
    cdef enum CheeseType:
        cheddar, edam, 
        camembert
    + + +
    cdef enum CheeseState:
        hard = 1
        soft = 2
        runny = 3
    + +
    + + + There is currently no special syntax for defining a constant, but you +can use an anonymous enum declaration for this purpose, for example, +
    cdef enum:
    + +     tons_of_spam = 3
    + + + Note that the words struct, union and enum are used only when defining a type, not when referring to it. For example, to declare a variable pointing + to a Grail you would write +
    +
    cdef Grail *gp
    + +
    + + + and not +
    +
    cdef struct Grail *gp # WRONG
    + +
    + + + There is also a ctypedef statement for giving names to types, e.g. + +
    +
    ctypedef unsigned long ULong
    + + +
    ctypedef int *IntPtr
    +
    + + +

    Automatic type conversions

    + + +In most situations, automatic conversions will be performed for the +basic numeric and string types when a Python object is used in a +context requiring a C value, or vice versa. The following table +summarises the conversion possibilities.
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    C types
    + +
    From Python types
    + +
    To Python types
    + +
    [unsigned] char
    + +[unsigned] short
    + + int, long
    int, long
    + +
    int
    + +
    unsigned int
    + +unsigned long
    + + [unsigned] long long
    + + +
    int, long
    + +
    + + +
    long
    + +
    + + +
    float, double, long double
    + +
    int, long, float
    + +
    float
    + +
    char *
    + +
    str
    + +
    str
    + +
    + + +
    + + +

    Caveats when using a Python string in a C context

    + + +You need to be careful when using a Python string in a context expecting a char *. +In this situation, a pointer to the contents of the Python string is +used, which is only valid as long as the Python string exists. So you +need to make sure that a reference to the original Python string is +held for as long as the C string is needed. If you can't guarantee that +the Python string will live long enough, you will need to copy the C +string.
    + + +
    + + +Pyrex detects and prevents some mistakes of this kind. For instance, if you attempt something like
    + + +
    cdef char *s
    s = pystring1 + pystring2
    + + +then Pyrex will produce the error message "Obtaining char * from temporary Python value". +The reason is that concatenating the two Python strings produces a new +Python string object that is referenced only by a temporary internal +variable that Pyrex generates. As soon as the statement has finished, +the temporary variable will be decrefed and the Python string +deallocated, leaving s dangling. Since this code could not possibly work, Pyrex refuses to compile it.
    + + +
    + + +The solution is to assign the result of the concatenation to a Python variable, and then obtain the char * from that, i.e.
    + + +
    cdef char *s
    p = pystring1 + pystring2
    s = p
    + + +It is then your responsibility to hold the reference p for as long as necessary.
    + + +
    + + +Keep in mind that the rules used to detect such errors are only +heuristics. Sometimes Pyrex will complain unnecessarily, and sometimes +it will fail to detect a problem that exists. Ultimately, you need to +understand the issue and be careful what you do. + + + + +

    Scope rules

    + + + Pyrex determines whether a variable belongs to a local scope, the module + scope, or the built-in scope completely statically. As with Python, + assigning to a variable which is not otherwise declared implicitly declares + it to be a Python variable residing in the scope where it is assigned. Unlike + Python, however, a name which is referred to but not declared or assigned + is assumed to reside in the builtin scope, not the module scope. +Names added to the module dictionary at run time will not shadow such names. + +

    You can use a global statement at the module level to explicitly + declare a name to be a module-level name when there would otherwise not be +any indication of this, for example,

    + + + +
    global __name__
    + + print __name__
    + + + Without the global statement, the above would print the name of +the builtins module.
    + + +
    + + + Note: A consequence of these rules is that the module-level scope behaves + the same way as a Python local scope if you refer to a variable before assigning + to it. In particular, tricks such as the following will not work +in Pyrex:
    + + + +
    +
    try:
      x = True
    except NameError:
      True = 1
    + +
    + + + because, due to the assignment, the True will always be looked up in the + module-level scope. You would have to do something like this instead:
    + + + +
    +
    import __builtin__
    try:
    True = __builtin__.True
    except AttributeError:
    True = 1
    + +
    + + + +
    +

    Statements and expressions

    + + + Control structures and expressions follow Python syntax for the most part. + When applied to Python objects, they have the same semantics as in Python + (unless otherwise noted). Most of the Python operators can also be applied + to C values, with the obvious semantics. +

    If Python objects and C values are mixed in an expression, conversions + are performed automatically between Python objects and C numeric or string + types.

    + + + +

    Reference counts are maintained automatically for all Python objects, and +all Python operations are automatically checked for errors, with appropriate + action taken.

    + + + +

    Differences between C and Pyrex +expressions

    + +There +are some differences in syntax and semantics between C expressions and +Pyrex expressions, particularly in the area of C constructs which have +no direct equivalent in Python.
    + + +
      + +
    • An integer literal without an L suffix is treated as a C constant, and will be truncated to whatever size your C compiler thinks appropriate. With an L suffix, it will be converted to Python long integer (even if it would be small enough to fit into a C int).
      + +
      + +
    • + +
    • There is no -> operator in Pyrex. Instead of p->x, + use p.x
    • + + +  
    • There is no * operator in Pyrex. Instead of + *p, use p[0]
    • + + +  
    • There is an & operator, with the same semantics + as in C.
    • + + +  
    • The null C pointer is called NULL, not 0 (and + NULL is a reserved word).
    • + + +  
    • Character literals are written with a c prefix, for +example:
    • + + +
        + + +
        c'X'
        + + +
      + +
    • Type casts are written <type>value , for example:
    • + + +
        + + +
        cdef char *p, float *q
        p = <char*>q
        + + +
      + + Warning: Don't attempt to use a typecast to convert between +Python and C data types -- it won't do the right thing. Leave Pyrex to perform +the conversion automatically. +
    + + + +

    Integer for-loops

    + + + You should be aware that a for-loop such as +
    for i in range(n):
    + +     ...
    + + + won't be very fast, even if i and n are declared as +C integers, because range is a Python function. For iterating over +ranges of integers, Pyrex has another form of for-loop: +
    for i from 0 <= i < n:
    + +     ...
    + + + If the loop variable and the lower and upper bounds are all C integers, +this form of loop will be much faster, because Pyrex will translate it into +pure C code. +

    Some things to note about the for-from loop:

    + + + +
      + + +
    • The target expression must be a variable name.
    • + +
    • The name between the lower and upper bounds must be the same as +the target name.
    • + +
    • The direction of iteration is determined by the relations. If they + are both from the set {<, <=} then it is upwards; + if they are both from the set {>, >=} then it is +downwards. (Any other combination is disallowed.)
    • + + +
    + + + Like other Python looping statements, break and continue may be used in the body, and the loop may have an else clause. + +

    +

    + + + +

    Error return values

    + + + If you don't do anything special, a function declared with cdef that does not return a Python object has no way of reporting Python exceptions + to its caller. If an exception is detected in such a function, a warning +message is printed and the exception is ignored. +

    If you want a C function that does not return a Python object to be able + to propagate exceptions to its caller, you need to declare an exception + value for it. Here is an example:

    + + + +
    cdef int spam() except -1:
    + +     ...
    + + + With this declaration, whenever an exception occurs inside spam, + it will immediately return with the value -1. Furthermore, whenever + a call to spam returns -1, an exception will be assumed + to have occurred and will be propagated. +

    When you declare an exception value for a function, you should never explicitly + return that value. If all possible return values are legal and you can't +reserve one entirely for signalling errors, you can use an alternative form +of exception value declaration:

    + + + +
    cdef int spam() except? -1:
    + +     ...
    + + + The "?" indicates that the value -1 only indicates a possible error. In this case, Pyrex generates a call to PyErr_Occurred if the +exception value is returned, to make sure it really is an error. +

    There is also a third form of exception value declaration:

    + + + +
    cdef int spam() except *:
    + +     ...
    + + + This form causes Pyrex to generate a call to PyErr_Occurred after + every call to spam, regardless of what value it returns. If you have + a function returning void that needs to propagate errors, you will + have to use this form, since there isn't any return value to test. +

    Some things to note:

    + + + +
      + + +
    • Exception values can only declared for functions returning + an integer, enum, float or pointer type, and the value must be a constant expression. The only possible pointer + exception value is NULL. Void functions can only use the except + * form.
    • + + +  
    • The exception value specification is part of the signature +of the function. If you're passing a pointer to a function as a parameter +or assigning it to a variable, the declared type of the parameter or variable + must have the same exception value specification (or lack thereof). Here +is an example of a pointer-to-function declaration with an exception value:
    • + + +
        + + +
        int (*grail)(int, char *) except -1
        + + +
      + +
    • You don't need to (and shouldn't) declare exception values for functions + which return Python objects. Remember that a function with no declared return + type implicitly returns a Python object.
    • + + +
    + + + +

    Checking return values of non-Pyrex + functions

    + + + It's important to understand that the except clause does not cause an error to be raised when the specified value is returned. For +example, you can't write something like +
    +
    cdef extern FILE *fopen(char *filename, char *mode) except NULL # WRONG!
    + +
    + + + and expect an exception to be automatically raised if a call to fopen +returns NULL. The except clause doesn't work that way; its only purpose +is for propagating exceptions that have already been raised, either +by a Pyrex function or a C function that calls Python/C API routines. To +get an exception from a non-Python-aware function such as fopen, you will +have to check the return value and raise it yourself, for example, +
    +
    cdef FILE *p
    p = fopen("spam.txt", "r")
    if p == NULL:
        raise SpamError("Couldn't open the spam file")
    + +
    + + + +

    +

    + + + +

    The include statement

    + + + For convenience, a large Pyrex module can be split up into a number of +files which are put together using the include statement, for example + +
    +
    include "spamstuff.pxi"
    + +
    + + + The contents of the named file are textually included at that point. The + included file can contain any complete top-level Pyrex statements, including + other include statements. The include statement itself can +only appear at the top level of a file. +

    The include statement can also be used in conjunction with public declarations to make C functions and + variables defined in one Pyrex module accessible to another. However, note + that some of these uses have been superseded by the facilities described +in Sharing Declarations Between Pyrex Modules, +and it is expected that use of the include statement for this purpose +will be phased out altogether in future versions.


    Keyword-only arguments

    Python functions can have keyword-only arguments listed after the * parameter and before the ** paramter if any, e.g.

    def f(a, b, *args, c, d = 42, e, **kwds):
    ...
    Here +c, d and e cannot be passed as position arguments and must be passed as +keyword arguments. Furthermore, c and e are required keyword arguments, +since they do not have a default value.

    If the parameter name after the * is omitted, the function will not accept any extra positional arguments, e.g.

    def g(a, b, *, c, d):
    ...
    takes exactly two positional parameters and has two required keyword parameters. + + + +

    +
    Interfacing with External + C Code +

    + + + One of the main uses of Pyrex is wrapping existing libraries of C code. +This is achieved by using external declarations to declare the C functions and variables from the library that you want to + use. +

    You can also use public declarations to make + C functions and variables defined in a Pyrex module available to external + C code. The need for this is expected to be less frequent, but you might +want to do it, for example, if you are embedding Python in another application + as a scripting language. Just as a Pyrex module can be used as a bridge to +allow Python code to call C code, it can also be used to allow C code to +call Python code.

    + + + +

    External declarations

    + + + By default, C functions and variables declared at the module level are +local to the module (i.e. they have the C static storage class). They +can also be declared extern to specify that they are defined elsewhere, + for example: +
    +
    cdef extern int spam_counter
    + + +
    cdef extern void order_spam(int tons)
    + +
    + + + +
    + + + +

    Referencing C header files

    + + + When you use an extern definition on its own as in the examples above, +Pyrex includes a declaration for it in the generated C file. This can cause +problems if the declaration doesn't exactly match the declaration that will +be seen by other C code. If you're wrapping an existing C library, for example, +it's important that the generated C code is compiled with exactly the same +declarations as the rest of the library. +

    To achieve this, you can tell Pyrex that the declarations are to be found + in a C header file, like this:

    + + + +
    +
    cdef extern from "spam.h":
    + + +
        int spam_counter
    + + +
        void order_spam(int tons)
    + +
    + + + The cdef extern from clause does three things: +
      + + +
    1. It directs Pyrex to place a #include statement for the named + header file in the generated C code.
      + +
    2. + +  
    3. It prevents Pyrex from generating any C code for the declarations + found in the associated block.
      + +
    4. + +  
    5. It treats all declarations within the block as though they +started with cdef extern.
    6. + + +
    + + + It's important to understand that Pyrex does not itself read the +C header file, so you still need to provide Pyrex versions of any declarations + from it that you use. However, the Pyrex declarations don't always have to +exactly match the C ones, and in some cases they shouldn't or can't. In particular: + +
      + + +
    1. Don't use const. Pyrex doesn't know anything about const, +so just leave it out. Most of the time this shouldn't cause any problem, +although on rare occasions you might have to use a cast. 1
      + +
    2. + +  
    3. Leave out any platform-specific extensions to C declarations + such as __declspec().
      + +
    4. + +  
    5. If the header file declares a big struct and you only want +to use a few members, you only need to declare the members you're interested +in. Leaving the rest out doesn't do any harm, because the C compiler will +use the full definition from the header file.
      + +
      + + In some cases, you might not need any of the struct's members, in +which case you can just put pass in the body of the struct declaration, +e.g.
      + +
      + +     cdef extern from "foo.h":
      + +         struct spam:
      + +             pass

      + +
      + +Note that you can only do this inside a cdef extern from block; struct +declarations anywhere else must be non-empty.
      + +
      + +
    6. + +
    7. If the header file uses typedef names such as size_t to refer +to platform-dependent flavours of numeric types, you will need a corresponding + ctypedef statement, but you don't need to match the type exactly, + just use something of the right general kind (int, float, etc). For example,
    8. + + +
        + + +
        ctypedef int size_t
        + + +
      + + will work okay whatever the actual size of a size_t is (provided the header + file defines it correctly).
      + +  
    9. If the header file uses macros to define constants, translate + them into a dummy enum declaration.
      + +
    10. + +  
    11. If the header file defines a function using a macro, declare + it as though it were an ordinary function, with appropriate argument and +result types.
    12. + + +
    + + + A few more tricks and tips: +
      + + +
    • If you want to include a C header because it's needed by another +header, but don't want to use any declarations from it, put pass in the extern-from block:
    • + + +
    + + + +
      + + + +
        + + cdef extern from "spam.h":
        + +     pass +
      + + +
    + + + +
      + + +
    • If you want to include some external declarations, but don't want +to specify a header file (because it's included by some other header that +you've already included) you can put * in place of the header file +name:
    • + + +
    + + + +
    +
    cdef extern from *:
    + +     ...
    + +
    + + + +

    Styles of struct, union and enum declaration

    + + + There are two main ways that structs, unions and enums can be declared +in C header files: using a tag name, or using a typedef. There are also some + variations based on various combinations of these. +

    It's important to make the Pyrex declarations match the style used in the +header file, so that Pyrex can emit the right sort of references to the type +in the code it generates. To make this possible, Pyrex provides two different +syntaxes for declaring a struct, union or enum type. The style introduced +above corresponds to the use of a tag name. To get the other style, you prefix +the declaration with ctypedef, as illustrated below.

    + + + +

    The following table shows the various possible styles that can be found + in a header file, and the corresponding Pyrex declaration that you should + put in the cdef exern from block. Struct declarations are used as +an example; the same applies equally to union and enum declarations.

    + + + +

    Note that in all the cases below, you refer to the type in Pyrex code simply +as Foo, not struct Foo. +
    + +   + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     C codePossibilities for corresponding +Pyrex codeComments
    1struct Foo {
    + +   ...
    + + };
    cdef struct Foo:
    + +   ...
    Pyrex will refer to the type as struct Foo in the generated + C code.
    2typedef struct {
    + +   ...
    + + } Foo;
    ctypedef struct Foo:
    + +   ...
    Pyrex will refer to the type simply as Foo +in the generated C code.
    3typedef struct +foo {
    + +   ...
    + + } Foo;
    cdef struct foo:
    + +   ...
    + + ctypedef foo Foo #optional
    If the C header uses both a tag and a typedef + with different names, you can use either form of declaration in Pyrex + (although if you need to forward reference the type, you'll have to use +the first form).
    ctypedef struct Foo:
    + +   ...
    4typedef struct Foo {
    + +   ...
    + + } Foo;
    cdef struct Foo:
    + +   ...
    If the header uses the same name for the tag and the typedef, + you won't be able to include a ctypedef for it -- but then, it's not +necessary.
    + +

    + + + +

    Accessing Python/C API routines

    + + + One particular use of the cdef extern from statement is for gaining + access to routines in the Python/C API. For example, +
    +
    cdef extern from "Python.h":
    + + +
        object PyString_FromStringAndSize(char *s, Py_ssize_t len)
    + +
    + + + will allow you to create Python strings containing null bytes. +

    Special Types

    Pyrex predefines the name Py_ssize_t +for use with Python/C API routines. To make your extensions compatible +with 64-bit systems, you should always use this type where it is +specified in the documentation of Python/C API routines.

    Windows Calling Conventions

    The __stdcall and __cdecl calling convention specifiers can be used in Pyrex, with the same syntax as used by C compilers on Windows, for example,

    cdef extern int __stdcall FrobnicateWindow(long handle)

    cdef void (__stdcall *callback)(void *)
    If __stdcall is used, the function is only considered compatible with other __stdcall functions of the same signature.
    + + + +
    +

    Resolving naming conflicts - C name specifications

    + + + Each Pyrex module has a single module-level namespace for both Python +and C names. This can be inconvenient if you want to wrap some external +C functions and provide the Python user with Python functions of the same +names. +

    Pyrex 0.8 provides a couple of different ways of solving this problem. + The best way, especially if you have many C functions to wrap, is probably + to put the extern C function declarations into a different namespace using + the facilities described in the section on sharing + declarations between Pyrex modules.

    + + + +

    The other way is to use a c name specification to give different + Pyrex and C names to the C function. Suppose, for example, that you want +to wrap an external function called eject_tomato. If you declare +it as

    + + + +
    +
    cdef extern void c_eject_tomato "eject_tomato" (float speed)
    + +
    + + + then its name inside the Pyrex module will be c_eject_tomato, +whereas its name in C will be eject_tomato. You can then wrap it +with +
    +
    def eject_tomato(speed):
      c_eject_tomato(speed)
    + +
    + + + so that users of your module can refer to it as eject_tomato. + +

    Another use for this feature is referring to external names that happen + to be Pyrex keywords. For example, if you want to call an external function + called print, you can rename it to something else in your Pyrex +module.

    + + + +

    As well as functions, C names can be specified for variables, structs, + unions, enums, struct and union members, and enum values. For example,

    + + + +
    +
    cdef extern int one "ein", two "zwei"
    cdef extern float three "drei"

    cdef struct spam "SPAM":
      int i "eye"
    + + cdef enum surprise "inquisition":
    + +   first "alpha"
    + +   second "beta" = 3
    + + + +
    +

    Using Pyrex Declarations from C

    Pyrex +provides two methods for making C declarations from a Pyrex module +available for use by external C code – public declarations and C API +declarations.

    NOTE: You do not need to use either of these to make declarations from one Pyrex module available to another Pyrex module – you should use the cimport statement for that. Sharing Declarations Between + Pyrex Modules.

    Public Declarations

    + + + You can make C types, variables and functions defined in a Pyrex module accessible + to C code that is linked with the module, by declaring them with the public keyword: +
    cdef public struct Bunny: # public type declaration
        int vorpalness

    cdef public int spam # public variable declaration
    +

    cdef public void grail(Bunny *): # public function declaration
    + +     ...

    + +
    + + + If there are any public declarations in a Pyrex module, a header file called modulename.h file is generated containing equivalent C declarations for inclusion in other + C code.

    Any +C code wanting to make use of these declarations will need to be +linked, either statically or dynamically, with the extension module.

    If +the Pyrex module resides within a package, then the name of the .h file +consists of the full dotted name of the module, e.g. a module called foo.spam would have a header file called foo.spam.h. +

    C API Declarations

    The other way of making functions available to C code is by declaring them with the api keyword. A header file called "modulename_api.h" is produced containing declarations of the functions, and a function called import_modulename().

    C code wanting to use the functions needs to include the header and call the import_modulename() function. The other functions can then be called as usual.

    Any public type declarations in the Pyrex module are also made available when you include modulename_api.h.

    delorean.pyx
    marty.c
    cdef public struct Vehicle:
    int speed
    float power

    cdef api void activate(Vehicle *v):
    if v.speed >= 88 \
    and v.power >= 1.21:
    print "Time travel achieved"
    #include "delorean_api.h"

    Vehicle car;

    int main(int argc, char *argv[]) {
    import_delorean();
    car.speed = atoi(argv[1]);
    car.power = atof(argv[2]); 
    activate(&car);
    }

    This +method does not require the C code using the functions to be linked +with the extension module in any way, as the Python import machinery is +used to make the connection dynamically. However, only functions can be +accessed this way, not variables.You can use both public and api on the same function to make it available by both methods, e.g.
    cdef public api void belt_and_braces():
    ...
    However, note that you should include either modulename.h or modulename_api.h in a given C file, not both, otherwise you may get conflicting dual definitions.

    If the Pyrex module resides within a package, then:
    • The name of the header file contains of the full dotted name of the module.
    • The name of the importing function contains the full name with dots replaced by double underscores.
    E.g. a module called foo.spam would have an API header file called foo.spam_api.h and an importing function called import_foo__spam().

    +
    Extension Types +

    + + + One of the most powerful features of Pyrex is the ability to easily create + new built-in Python types, called extension types. This is a major + topic in itself, so there is a  separate + page devoted to it. +

    +
    Sharing Declarations Between Pyrex Modules +

    + + + Pyrex 0.8 introduces a substantial new set of facilities allowing a Pyrex + module to easily import and use C declarations and extension types from another +Pyrex module. You can now create a set of co-operating Pyrex modules just +as easily as you can create a set of co-operating Python modules. There is +a separate page devoted to this topic. +

    +
    Limitations +

    + + + +

    Unsupported Python features

    + + + Pyrex is not quite a full superset of Python. The following restrictions + apply: +
  • Function definitions (whether using def or cdef) + cannot be nested within other function definitions.
    + +
  • + +  
  • Class definitions can only appear at the top level of a module, + not inside a function.
    + +
  • + +  
  • The import * form of import is not allowed anywhere + (other forms of the import statement are fine, though).
    + +
  • + +  
  • Generators cannot be defined in Pyrex.
    + +
    + +
  • + +
  • The globals() and locals() functions cannot be +used.
  • + +
    + + + The above restrictions will most likely remain, since removing them would + be difficult and they're not really needed for Pyrex's intended applications. + +

    There are also some temporary limitations, which may eventually be lifted, including: +

    + + + +
  • Class and function definitions cannot be placed inside +control structures.
    + +
  • + +  
  • In-place arithmetic operators (+=, etc) are not yet supported.
    + +
  • + +  
  • List comprehensions are not yet supported.
    + +
  • + +  
  • There is no support for Unicode.
    + +
  • + +  
  • Special methods of extension types cannot have functioning +docstrings.
    + +
    + +
  • + +
  • The use of string literals as comments is not recommended at present, + because Pyrex doesn't optimize them away, and won't even accept them in +places where executable statements are not allowed.
  • + +
    + + +

    Semantic differences between Python + and Pyrex

    + + + +

    Behaviour of class scopes

    + + + In Python, referring to a method of a class inside the class definition, + i.e. while the class is being defined, yields a plain function object, but + in Pyrex it yields an unbound method2. A consequence of this is that the +usual idiom for using the classmethod and staticmethod functions, e.g. +
    +
    class Spam:
    + + +
      def method(cls):
        ...
    + + +
      method = classmethod(method)
    + +
    + + + will not work in Pyrex. This can be worked around by defining the function + outside the class, and then assigning the result of classmethod or + staticmethod inside the class, i.e. +
    +
    def Spam_method(cls):
      ...
    + + +
    class Spam:
    + + +
      method = classmethod(Spam_method)
    + +
    + + + +

    +
    Footnotes +

    + + + 1. A problem with const could arise if you have +something like +
    +
    cdef extern from "grail.h":
      char *nun
    + +
    + + + where grail.h actually contains +
    +
    extern const char *nun;
    + +
    + + + and you do +
    +
    cdef void languissement(char *s):
      #something that doesn't change s
    + + +
    ...
    + + +
    languissement(nun)
    + +
    + + + which will cause the C compiler to complain. You can work around it by +casting away the constness: +
    +
    languissement(<char *>nun)
    + +
    + + + +
    2. The reason for the different behaviour +of class scopes is that Pyrex-defined Python functions are PyCFunction objects, +not PyFunction objects, and are not recognised by the machinery that creates +a bound or unbound method when a function is extracted from a class. To get +around this, Pyrex wraps each method in an unbound method object itself before +storing it in the class's dictionary.
    + + +  
    + + +
    + + + + \ No newline at end of file diff --git a/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Builtin.py b/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Builtin.py new file mode 100644 index 00000000..62dbfbef --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Builtin.py @@ -0,0 +1,276 @@ +# +# Pyrex - Builtin Definitions +# + +from Symtab import BuiltinScope +from TypeSlots import Signature +from PyrexTypes import py_type_type, c_size_t_type, c_py_ssize_t_type + +builtin_constant_table = [ + # name, type/ctype, C API name + ("buffer", "t", "(&PyBuffer_Type)"), + ("enumerate", "t", "(&PyEnum_Type)"), + ("file", "t", "(&PyFile_Type)"), + ("float", "t", "(&PyFloat_Type)"), + ("int", "t", "(&PyInt_Type)"), + ("long", "t", "(&PyLong_Type)"), + ("open", "t", "(&PyFile_Type)"), + ("property", "t", "(&PyProperty_Type)"), + ("str", "t", "(&PyString_Type)"), + ("tuple", "t", "(&PyTuple_Type)"), + ("xrange", "t", "(&PyRange_Type)"), + + ("True", "O", "Py_True"), + ("False", "O", "Py_False"), + ("Ellipsis", "O", "Py_Ellipsis"), + + ("Exception", "t/O", "PyExc_Exception"), + ("StopIteration", "t/O", "PyExc_StopIteration"), + ("StandardError", "t/O", "PyExc_StandardError"), + ("ArithmeticError", "t/O", "PyExc_ArithmeticError"), + ("LookupError", "t/O", "PyExc_LookupError"), + + ("AssertionError", "t/O", "PyExc_AssertionError"), + ("EOFError", "t/O", "PyExc_EOFError"), + ("FloatingPointError", "t/O", "PyExc_FloatingPointError"), + ("EnvironmentError", "t/O", "PyExc_EnvironmentError"), + ("IOError", "t/O", "PyExc_IOError"), + ("OSError", "t/O", "PyExc_OSError"), + ("ImportError", "t/O", "PyExc_ImportError"), + ("IndexError", "t/O", "PyExc_IndexError"), + ("KeyError", "t/O", "PyExc_KeyError"), + ("KeyboardInterrupt", "t/O", "PyExc_KeyboardInterrupt"), + ("MemoryError", "t/O", "PyExc_MemoryError"), + ("NameError", "t/O", "PyExc_NameError"), + ("OverflowError", "t/O", "PyExc_OverflowError"), + ("RuntimeError", "t/O", "PyExc_RuntimeError"), + ("NotImplementedError", "t/O", "PyExc_NotImplementedError"), + ("SyntaxError", "t/O", "PyExc_SyntaxError"), + ("IndentationError", "t/O", "PyExc_IndentationError"), + ("TabError", "t/O", "PyExc_TabError"), + ("ReferenceError", "t/O", "PyExc_ReferenceError"), + ("SystemError", "t/O", "PyExc_SystemError"), + ("SystemExit", "t/O", "PyExc_SystemExit"), + ("TypeError", "t/O", "PyExc_TypeError"), + ("UnboundLocalError", "t/O", "PyExc_UnboundLocalError"), + ("UnicodeError", "t/O", "PyExc_UnicodeError"), + ("UnicodeEncodeError", "t/O", "PyExc_UnicodeEncodeError"), + ("UnicodeDecodeError", "t/O", "PyExc_UnicodeDecodeError"), + ("UnicodeTranslateError", "t/O", "PyExc_UnicodeTranslateError"), + ("ValueError", "t/O", "PyExc_ValueError"), + ("ZeroDivisionError", "t/O", "PyExc_ZeroDivisionError"), + # Not including these by default because they are platform-specific + #("WindowsError", "t/O", "PyExc_WindowsError"), + #("VMSError", "t/O", "PyExc_VMSError"), + + ("MemoryErrorInst", "t/O", "PyExc_MemoryErrorInst"), + + ("Warning", "t/O", "PyExc_Warning"), + ("UserWarning", "t/O", "PyExc_UserWarning"), + ("DeprecationWarning", "t/O", "PyExc_DeprecationWarning"), + ("PendingDeprecationWarning", "t/O", "PyExc_PendingDeprecationWarning"), + ("SyntaxWarning", "t/O", "PyExc_SyntaxWarning"), + ("OverflowWarning", "t/O", "PyExc_OverflowWarning"), + ("RuntimeWarning", "t/O", "PyExc_RuntimeWarning"), + ("FutureWarning", "t/O", "PyExc_FutureWarning"), + +] + +builtin_function_table = [ + # name, args, return, C API func, py equiv = "*" + ('abs', "O", "O", "PyNumber_Absolute"), + ('bool', "O", "i", "PyObject_IsTrue"), + #('chr', "", "", ""), + #('cmp', "", "", "", ""), # int PyObject_Cmp(PyObject *o1, PyObject *o2, int *result) + #('compile', "", "", ""), # PyObject* Py_CompileString( char *str, char *filename, int start) + ('delattr', "OO", "r", "PyObject_DelAttr"), + ('dir', "O", "O", "PyObject_Dir"), + ('divmod', "OO", "O", "PyNumber_Divmod"), + #('eval', "", "", ""), + #('execfile', "", "", ""), + #('filter', "", "", ""), + ('getattr', "OO", "O", "PyObject_GetAttr"), + ('getattr3', "OOO", "O", "__Pyx_GetAttr3", "getattr"), + ('hasattr', "OO", "i", "PyObject_HasAttr"), + ('hash', "O", "l", "PyObject_Hash"), + #('hex', "", "", ""), + #('id', "", "", ""), + #('input', "", "", ""), + ('cintern', "s", "O", "PyString_InternFromString"), # different name because doesn't handle null bytes + ('isinstance', "OO", "i", "PyObject_IsInstance"), + ('issubclass', "OO", "i", "PyObject_IsSubclass"), + ('iter', "O", "O", "PyObject_GetIter"), + ('iter2', "OO", "O", "PyCallIter_New"), + ('len', "O", "Z", "PyObject_Length"), + #('map', "", "", ""), + #('max', "", "", ""), + #('min', "", "", ""), + #('oct', "", "", ""), + # Not worth doing open, when second argument would become mandatory + #('open', "ss", "O", "PyFile_FromString"), + #('ord', "", "", ""), + ('pow', "OOO", "O", "PyNumber_Power"), + #('range', "", "", ""), + #('raw_input', "", "", ""), + #('reduce', "", "", ""), + ('reload', "O", "O", "PyImport_ReloadModule"), + ('repr', "O", "O", "PyObject_Repr"), + #('round', "", "", ""), + ('setattr', "OOO", "r", "PyObject_SetAttr"), + #('sum', "", "", ""), + #('unichr', "", "", ""), + #('unicode', "", "", ""), + #('vars', "", "", ""), + #('zip', "", "", ""), + ('typecheck', "Ot", "b", "PyObject_TypeCheck", False), + ('issubtype', "tt", "b", "PyType_IsSubtype", False), +] + +dict_methods = [ + # name, args, return, C API func + ("clear", "O", "v", "PyDict_Clear"), + ("copy", "O", "O", "PyDict_Copy"), + ("items", "O", "O", "PyDict_Items"), + ("keys", "O", "O", "PyDict_Keys"), + ("values", "O", "O", "PyDict_Values"), + ("merge", "OOi", "r", "PyDict_Merge"), + ("update", "OO", "r", "PyDict_Update"), + ("merge_pairs", "OOi", "r", "PyDict_MergeFromSeq2"), +] + +list_methods = [ + # name, args, return, C API func + ("insert", "OiO", "r", "PyList_Insert"), + ("append", "OO", "r", "PyList_Append"), + ("iappend", "OO", "i", "PyList_Append"), + ("sort", "O", "r", "PyList_Sort"), + ("reverse", "O", "r", "PyList_Reverse"), + ("as_tuple", "O", "O", "PyList_AsTuple"), +] + +slice_methods = [ + # name, args, return, C API func + ("indices", "O", "O", "PySlice_Indices"), +] + +slice_members = [ + # name, type + ("start", "O"), + ("stop", "O"), + ("step", "O"), +] + +builtin_c_type_table = [ + ("size_t", c_size_t_type), + ("Py_ssize_t", c_py_ssize_t_type), +] + +builtin_type_table = [ + # name, objstruct, typeobj, methods, members, flags +# bool - function +# buffer - constant +# classmethod + ("dict", "PyDictObject", "PyDict_Type", dict_methods), +# enumerate - constant +# file - constant +# float - constant +# int - constant + ("list", "PyListObject", "PyList_Type", list_methods, [], ['is_sequence']), +# long - constant +# object +# property - constant + ("slice", "PySliceObject", "PySlice_Type", slice_methods, slice_members), +# staticmethod +# super +# str - constant +# tuple - constant + ("type", "PyTypeObject", "PyType_Type", []), +# xrange - constant +] + +getattr3_utility_code = [""" +static PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *); /*proto*/ +""",""" +static PyObject *__Pyx_GetAttr3(PyObject *o, PyObject *n, PyObject *d) { + PyObject *r = PyObject_GetAttr(o, n); + if (!r) { + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) + goto bad; + PyErr_Clear(); + r = d; + Py_INCREF(d); + } + return r; +bad: + return 0; +} +"""] + +builtin_utility_code = { + 'getattr3': getattr3_utility_code, +} + +builtin_scope = BuiltinScope() + +def type_and_ctype(typecode, c_typecode = None): + type = Signature.format_map[typecode] + if c_typecode: + ctype = Signature.format_map[c_typecode] + else: + ctype = None + return type, ctype + +def declare_builtin_constant(name, typecode, cname): + type, ctype = type_and_ctype(*typecode.split("/")) + builtin_scope.declare_builtin_constant(name, type, cname, ctype) + +def declare_builtin_func(name, args, ret, cname, py_equiv = "*"): + sig = Signature(args, ret) + type = sig.function_type() + utility = builtin_utility_code.get(name) + builtin_scope.declare_builtin_cfunction(name, type, cname, py_equiv, utility) + +def declare_builtin_method(self_type, name, args, ret, cname): + sig = Signature(args, ret) + meth_type = sig.function_type(self_type) + self_type.scope.declare_builtin_method(name, meth_type, cname) + +def declare_builtin_member(self_type, name, typecode, cname = None): + member_type = Signature.format_map[typecode] + self_type.scope.declare_builtin_var(name, member_type, cname) + +def declare_builtin_c_type(name, type): + builtin_scope.declare_builtin_c_type(name, type) + +def declare_builtin_type(name, objstruct, typeobj, methods, members = [], + flags = []): + entry = builtin_scope.declare_builtin_class(name, objstruct, typeobj) + type = entry.type + for desc in methods: + declare_builtin_method(type, *desc) + for desc in members: + declare_builtin_member(type, *desc) + for flag in flags: + setattr(type, flag, 1) + +def init_builtin_constants(): + for desc in builtin_constant_table: + declare_builtin_constant(*desc) + +def init_builtin_funcs(): + for desc in builtin_function_table: + declare_builtin_func(*desc) + +def init_builtin_types(): + for desc in builtin_c_type_table: + declare_builtin_c_type(*desc) + for desc in builtin_type_table: + declare_builtin_type(*desc) + py_type_type.define(builtin_scope.find_type("type")) + +def init_builtins(): + init_builtin_constants() + init_builtin_funcs() + init_builtin_types() + +init_builtins() diff --git a/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/CmdLine.py b/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/CmdLine.py new file mode 100644 index 00000000..bf546d6e --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/CmdLine.py @@ -0,0 +1,94 @@ +# +# Pyrex - Command Line Parsing +# + +import sys +from Filenames import pyx_suffixes +from Pyrex.Utils import has_suffix + +usage = """\ +Usage: pyrexc [options] sourcefile... +Options: + -v, --version Display version number of pyrex compiler + -l, --create-listing Write error messages to a listing file + -I, --include-dir Search for include files in named directory + -o, --output-file Specify name of generated C file + -r, --recursive Recursively find and compile dependencies + -t, --timestamps Only compile newer source files (implied with -r) + -f, --force Compile all source files (overrides implied -t) + -q, --quiet Don't print module names in recursive mode +The following experimental options are supported only on MacOSX: + -C, --compile Compile generated .c file to .o file + -X, --link Link .o file to produce extension module (implies -C) + -+, --cplus Use C++ compiler for compiling and linking + Additional .o files to link may be supplied when using -X.""" + +def bad_usage(): + print >>sys.stderr, usage + sys.exit(1) + +def parse_command_line(args): + from Pyrex.Compiler.Main import \ + CompilationOptions, default_options + + def pop_arg(): + if args: + return args.pop(0) + else: + bad_usage() + + def get_param(option): + tail = option[2:] + if tail: + return tail + else: + return pop_arg() + + options = CompilationOptions(default_options) + sources = [] + while args: + if args[0].startswith("-"): + option = pop_arg() + if option in ("-v", "--version"): + options.show_version = 1 + elif option in ("-l", "--create-listing"): + options.use_listing_file = 1 + elif option in ("-C", "--compile"): + options.c_only = 0 + elif option in ("-X", "--link"): + options.c_only = 0 + options.obj_only = 0 + elif option in ("-+", "--cplus"): + options.cplus = 1 + elif option.startswith("-I"): + options.include_path.append(get_param(option)) + elif option == "--include-dir": + options.include_path.append(pop_arg()) + elif option in ("-o", "--output-file"): + options.output_file = pop_arg() + elif option in ("-r", "--recursive"): + options.recursive = 1 + elif option in ("-t", "--timestamps"): + options.timestamps = 1 + elif option in ("-f", "--force"): + options.timestamps = 0 + else: + bad_usage() + else: + arg = pop_arg() + if has_suffix(arg, pyx_suffixes): + sources.append(arg) + elif arg.endswith(".o"): + options.objects.append(arg) + else: + print >>sys.stderr, \ + "pyrexc: %s: Unknown filename suffix" % arg + if options.objects and len(sources) > 1: + print >>sys.stderr, \ + "pyrexc: Only one source file allowed together with .o files" + if options.use_listing_file and len(sources) > 1: + print >>sys.stderr, \ + "pyrexc: Only one source file allowed when using -o" + sys.exit(1) + return options, sources + diff --git a/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Code.py b/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Code.py new file mode 100644 index 00000000..a47692bb --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Code.py @@ -0,0 +1,546 @@ +########################################################################## +# +# Pyrex - Code output module +# +########################################################################## + +import os, re +import Naming +from Pyrex.Utils import open_new_file +from PyrexTypes import py_object_type, c_char_array_type, typecast + +identifier_pattern = re.compile(r"[A-Za-z_][A-Za-z0-9_]*$") +max_intern_length = 30 + +class CCodeWriter: + # f file output file + # level int indentation level + # bol bool beginning of line? + # marker string comment to emit before next line + + def __init__(self, f): + #self.f = open_new_file(outfile_name) + self.f = f + self.level = 0 + self.bol = 1 + self.marker = None + + def putln(self, code = ""): + if self.marker and self.bol: + self.emit_marker() + if code: + self.put(code) + self.f.write("\n"); + self.bol = 1 + + def emit_marker(self): + self.f.write("\n"); + self.indent() + self.f.write("/* %s */\n" % self.marker) + self.marker = None + + def put(self, code): + dl = code.count("{") - code.count("}") + if dl < 0: + self.level += dl + if self.bol: + self.indent() + self.f.write(code) + self.bol = 0 + if dl > 0: + self.level += dl + + def increase_indent(self): + self.level = self.level + 1 + + def decrease_indent(self): + self.level = self.level - 1 + + def begin_block(self): + self.putln("{") + self.increase_indent() + + def end_block(self): + self.decrease_indent() + self.putln("}") + + def indent(self): + self.f.write(" " * self.level) + + def mark_pos(self, pos): + file, line, col = pos + self.marker = '"%s":%s' % (file, line) + + def put_var_declarations(self, entries, static = 0, dll_linkage = None, + definition = True): + for entry in entries: + if not entry.in_cinclude: + self.put_var_declaration(entry, static, dll_linkage, definition) + + def put_var_declaration(self, entry, static = 0, dll_linkage = None, + definition = True): + #print "Code.put_var_declaration:", entry.name, repr(entry.type) ### + visibility = entry.visibility + if visibility == 'private' and not definition: + #print "...private and not definition, skipping" ### + return + if not entry.used and visibility == "private": + #print "not used and private, skipping" ### + return + storage_class = "" + if visibility == 'extern': + storage_class = Naming.extern_c_macro + elif visibility == 'public': + if not definition: + storage_class = Naming.extern_c_macro + elif visibility == 'private': + if static: + storage_class = "static" + if storage_class: + self.put("%s " % storage_class) + if visibility <> 'public': + dll_linkage = None + self.put(entry.type.declaration_code(entry.cname, + dll_linkage = dll_linkage)) + if entry.init is not None: + self.put(" = %s" % entry.type.literal_code(entry.init)) + self.putln(";") + + def entry_as_pyobject(self, entry): + type = entry.type + if (not entry.is_self_arg and not entry.type.is_complete()) \ + or (entry.type.is_extension_type and entry.type.base_type): + return "(PyObject *)" + entry.cname + else: + return entry.cname + + def as_pyobject(self, cname, type): + if type: + return typecast(py_object_type, type, cname) + else: + return cname + + def put_incref(self, cname, type = None): + self.putln("Py_INCREF(%s);" % self.as_pyobject(cname, type)) + + def put_decref(self, cname, type = None): + self.putln("Py_DECREF(%s);" % self.as_pyobject(cname, type)) + + def put_var_incref(self, entry): + if entry.type.is_pyobject: + self.putln("Py_INCREF(%s);" % self.entry_as_pyobject(entry)) + + def put_decref_clear(self, cname, type = None): + self.putln("Py_DECREF(%s); %s = 0;" % ( + self.as_pyobject(cname, type), cname)) # What was wrong with this? + #typecast(py_object_type, type, cname), cname)) + + def put_xdecref(self, cname, type): + self.putln("Py_XDECREF(%s);" % self.as_pyobject(cname, type)) + + def put_xdecref_clear(self, cname, type): + self.putln("Py_XDECREF(%s); %s = 0;" % ( + self.as_pyobject(cname, type), cname)) + + def put_var_decref(self, entry): + if entry.type.is_pyobject: + self.putln("Py_DECREF(%s);" % self.entry_as_pyobject(entry)) + + def put_var_decref_clear(self, entry): + if entry.type.is_pyobject: + self.putln("Py_DECREF(%s); %s = 0;" % ( + self.entry_as_pyobject(entry), entry.cname)) + + def put_var_xdecref(self, entry): + if entry.type.is_pyobject: + self.putln("Py_XDECREF(%s);" % self.entry_as_pyobject(entry)) + + def put_var_xdecref_clear(self, entry): + if entry.type.is_pyobject: + self.putln("Py_XDECREF(%s); %s = 0;" % ( + self.entry_as_pyobject(entry), entry.cname)) + + def put_var_decrefs(self, entries, used_only = 0): + for entry in entries: + if not used_only or entry.used: + if entry.xdecref_cleanup: + self.put_var_xdecref(entry) + else: + self.put_var_decref(entry) + + def put_var_xdecrefs(self, entries): + for entry in entries: + self.put_var_xdecref(entry) + + def put_var_xdecrefs_clear(self, entries): + for entry in entries: + self.put_var_xdecref_clear(entry) + + def put_init_to_py_none(self, cname, type): + py_none = typecast(type, py_object_type, "Py_None") + self.putln("%s = %s; Py_INCREF(Py_None);" % (cname, py_none)) + + def put_init_var_to_py_none(self, entry, template = "%s"): + code = template % entry.cname + self.put_init_to_py_none(code, entry.type) + + def put_pymethoddef(self, entry, term): + if entry.doc: + doc_code = entry.doc_cname + else: + doc_code = 0 + self.putln( + '{"%s", (PyCFunction)%s, METH_VARARGS|METH_KEYWORDS, %s}%s' % ( + entry.name, + entry.func_cname, + doc_code, + term)) + + def put_h_guard(self, guard): + self.putln("#ifndef %s" % guard) + self.putln("#define %s" % guard) + +#-------------------------------------------------------------------------- + +class MainCCodeWriter(CCodeWriter): + # Code writer for executable C code. + # + # global_state GlobalCodeState module-wide state + # return_label string function return point label + # error_label string error catch point label + # continue_label string loop continue point label + # break_label string loop break point label + # label_counter integer counter for naming labels + # in_try_finally boolean inside try of try...finally + # exc_vars (string * 3) exception vars for reraise, or None + + in_try_finally = 0 + + def __init__(self, f, base = None): + CCodeWriter.__init__(self, f) + if base: + self.global_state = base.global_state + else: + self.global_state = GlobalCodeState() + self.label_counter = 1 + self.error_label = None + self.exc_vars = None + + def init_labels(self): + self.label_counter = 0 + self.labels_used = {} + self.return_label = self.new_label() + self.new_error_label() + self.continue_label = None + self.break_label = None + + def new_label(self): + n = self.label_counter + self.label_counter = n + 1 + return "%s%d" % (Naming.label_prefix, n) + + def new_error_label(self): + old_err_lbl = self.error_label + self.error_label = self.new_label() + return old_err_lbl + + def get_loop_labels(self): + return ( + self.continue_label, + self.break_label) + + def set_loop_labels(self, labels): + (self.continue_label, + self.break_label) = labels + + def new_loop_labels(self): + old_labels = self.get_loop_labels() + self.set_loop_labels( + (self.new_label(), + self.new_label())) + return old_labels + + def get_all_labels(self): + return ( + self.continue_label, + self.break_label, + self.return_label, + self.error_label) + + def set_all_labels(self, labels): + (self.continue_label, + self.break_label, + self.return_label, + self.error_label) = labels + + def all_new_labels(self): + old_labels = self.get_all_labels() + new_labels = [] + for old_label in old_labels: + if old_label: + new_labels.append(self.new_label()) + else: + new_labels.append(old_label) + self.set_all_labels(new_labels) + return old_labels + + def use_label(self, lbl): + self.labels_used[lbl] = 1 + + def put_label(self, lbl): + if lbl in self.labels_used: + self.putln("%s:;" % lbl) + + def put_goto(self, lbl): + self.use_label(lbl) + self.putln("goto %s;" % lbl) + + def error_goto(self, pos): + lbl = self.error_label + self.use_label(lbl) + return "{%s; goto %s;}" % ( + self.error_setup(pos), + lbl) + + def error_setup(self, pos): + return "%s = %s[%s]; %s = %s" % ( + Naming.filename_cname, + Naming.filetable_cname, + self.lookup_filename(pos[0]), + Naming.lineno_cname, + pos[1]) + + def lookup_filename(self, filename): + return self.global_state.lookup_filename(filename) + + def use_utility_code(self, uc): + self.global_state.use_utility_code(uc) + + def get_string_const(self, text): + # Get C name for a string constant, adding a new one + # if necessary. + return self.global_state.get_string_const(text).cname + + def new_const(self, type): + # Get C name for a new precalculated value. + return self.global_state.new_const(type).cname + + def get_py_string_const(self, text): + # Get C name for a Python string constant, adding a new one + # if necessary. If the string is name-like, it will be interned. + return self.global_state.get_py_string_const(text).cname + + def intern(self, name): + return self.get_py_string_const(name) + +#-------------------------------------------------------------------------- + +class StringConst: + # Info held by GlobalCodeState about a string constant. + # + # cname string + # text string + # py_const Const Corresponding Python string + + py_const = None + + def __init__(self, cname, text): + self.cname = cname + self.text = text + +#-------------------------------------------------------------------------- + +class Const: + # Info held by GlobalCodeState about a precalculated value. + # + # cname string + # type PyrexType + # intern boolean for Python strings + + intern = 0 + + def __init__(self, cname, type): + self.cname = cname + self.type = type + +#-------------------------------------------------------------------------- + +class GlobalCodeState: + # State pertaining to code generation for a whole module. + # + # filename_table {string : int} for finding filename table indexes + # filename_list [string] filenames in filename table order + # utility_code {int : int} id to utility_list index + # utility_list list utility code used + # const_counter int for generating const names + # string_index {string : String} string constant index + # string_consts [StringConst] all string constants + # other_consts [Const] other precalculated values + + def __init__(self): + self.filename_table = {} + self.filename_list = [] + self.utility_code = {} + self.utility_list = [] + self.const_counter = 1 + self.string_index = {} + self.string_consts = [] + self.other_consts = [] + + def lookup_filename(self, filename): + try: + index = self.filename_table[filename] + except KeyError: + index = len(self.filename_list) + self.filename_list.append(filename) + self.filename_table[filename] = index + return index + + def generate_filename_table(self, code): + code.putln("") + code.putln("static char *%s[] = {" % Naming.filenames_cname) + if self.filename_list: + for filename in self.filename_list: + filename = os.path.basename(filename) + escaped_filename = filename.replace("\\", "\\\\").replace('"', r'\"') + code.putln('"%s",' % + escaped_filename) + else: + # Some C compilers don't like an empty array + code.putln("0") + code.putln("};") + + def use_utility_code(self, uc): + i = id(uc) + if i not in self.utility_code: + self.utility_code[i] = len(self.utility_list) + self.utility_list.append(uc) + + def generate_utility_functions(self, code): + code.putln("") + code.putln("/* Runtime support code */") + code.putln("") + code.putln("static void %s(void) {" % Naming.fileinit_cname) + code.putln("%s = %s;" % + (Naming.filetable_cname, Naming.filenames_cname)) + code.putln("}") + for utility_code in self.utility_list: + code.h.put(utility_code[0]) + code.put(utility_code[1]) + + def new_const_name(self): + # Create a new globally-unique name for a constant. + name = "%s%s" % (Naming.const_prefix, self.const_counter) + self.const_counter += 1 + return name + + def new_string_const(self, text): + # Add a new C string constant. + c = StringConst(self.new_const_name(), text) + self.string_consts.append(c) + self.string_index[text] = c + return c + + def new_const(self, type, cname = None): + if not cname: + cname = self.new_const_name() + c = Const(cname, type) + self.other_consts.append(c) + return c + + def new_py_const(self, cname = None, intern = 0): + # Add a new Python constant. + c = self.new_const(py_object_type, cname) + if intern: + c.intern = 1 + return c + + def get_string_const(self, text): + # Get a C string constant, adding a new one if necessary. + c = self.string_index.get(text) + if not c: + c = self.new_string_const(text) + return c + + def get_py_string_const(self, text): + # Get a Python string constant, adding a new one if necessary. + # If the string is name-like, it will be interned. + s = self.get_string_const(text) + if not s.py_const: + intern = len(text) <= max_intern_length and identifier_pattern.match(text) + if intern: + cname = Naming.interned_prefix + text + else: + cname = s.cname + "p" + s.py_const = self.new_py_const(cname, intern) + return s.py_const + + def generate_const_declarations(self, code): + self.generate_string_const_declarations(code) + self.generate_other_const_declarations(code) + self.generate_stringtab(code) + + def generate_string_const_declarations(self, code): + code.putln("") + for c in self.string_consts: + code.putln('static char %s[] = "%s";' % (c.cname, c.text)) + + def generate_other_const_declarations(self, code): + interned = [] + uninterned = [] + for c in self.other_consts: + if c.intern: + interned.append(c) + else: + uninterned.append(c) + interned.sort(lambda c1, c2: cmp(c1.cname, c2.cname)) + def put_consts(consts): + code.putln("") + for c in consts: + decl = c.type.declaration_code(c.cname) + code.putln("static %s;" % decl) + put_consts(interned) + put_consts(uninterned) + + def generate_stringtab(self, code): + interned = [] + uninterned = [] + for s in self.string_consts: + p = s.py_const + if p: + if p.intern: + interned.append(s) + else: + uninterned.append(s) + interned.sort(lambda c1, c2: cmp(c1.py_const.cname, c2.py_const.cname)) + def put_stringtab(consts, intern): + for c in consts: + cname = c.cname + code.putln("{&%s, %d, %s, sizeof(%s)}," % ( + c.py_const.cname, intern, cname, cname)) + code.putln("") + code.putln("static __Pyx_StringTabEntry %s[] = {" % Naming.stringtab_cname) + put_stringtab(interned, 1) + put_stringtab(uninterned, 0) + code.putln("{0, 0, 0, 0}") + code.putln("};") + +#-------------------------------------------------------------------------- + +class PyrexCodeWriter: + # f file output file + # level int indentation level + + def __init__(self, outfile_name): + self.f = open_new_file(outfile_name) + self.level = 0 + + def putln(self, code): + self.f.write("%s%s\n" % (" " * self.level, code)) + + def indent(self): + self.level += 1 + + def dedent(self): + self.level -= 1 + diff --git a/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/DebugFlags.py b/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/DebugFlags.py new file mode 100644 index 00000000..e36e0bd2 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/DebugFlags.py @@ -0,0 +1,4 @@ +debug_disposal_code = 0 +debug_temp_alloc = 0 +debug_coercion = 0 + diff --git a/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Errors.py b/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Errors.py new file mode 100644 index 00000000..1eef3a33 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Errors.py @@ -0,0 +1,77 @@ +# +# Pyrex - Errors +# + +import sys +from Pyrex.Utils import open_new_file + +warnings_issued = {} + +class PyrexError(EnvironmentError): + pass + + +class CompileError(PyrexError): + + def __init__(self, position = None, message = ""): + self.position = position + if position: + pos_str = "%s:%d:%d: " % position + else: + pos_str = "" + PyrexError.__init__(self, pos_str + message) + + +class InternalError(Exception): + # If this is ever raised, there is a bug in the compiler. + + def __init__(self, message): + Exception.__init__(self, "Internal compiler error: %s" + % message) + + +listing_file = None +num_errors = 0 +echo_file = None + +def open_listing_file(path, echo_to_stderr = 1): + # Begin a new error listing. If path is None, no file + # is opened, the error counter is just reset. + global listing_file, num_errors, echo_file + if path is not None: + listing_file = open_new_file(path) + else: + listing_file = None + if echo_to_stderr: + echo_file = sys.stderr + else: + echo_file = None + num_errors = 0 + +def close_listing_file(): + global listing_file + if listing_file: + listing_file.close() + listing_file = None + +def report(position, message): + err = CompileError(position, message) + line = "%s\n" % err + if listing_file: + listing_file.write(line) + if echo_file: + echo_file.write(line) + return err + +def warning(position, message): + return report(position, "Warning: %s" % message) + +def one_time_warning(position, key, message): + if key not in warnings_issued: + warnings_issued[key] = 1 + warning(position, message) + +def error(position, message): + global num_errors + num_errors = num_errors + 1 + return report(position, message) diff --git a/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/ExprNodes.py b/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/ExprNodes.py new file mode 100644 index 00000000..c2848286 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/ExprNodes.py @@ -0,0 +1,3954 @@ +# +# Pyrex - Parse tree nodes for expressions +# + +import operator +from string import join + +from Errors import error, InternalError +import Naming +from Nodes import Node +import PyrexTypes +from PyrexTypes import py_object_type, c_long_type, typecast, error_type, \ + CPtrType, CFuncType, COverloadedFuncType +import Symtab +import Options + +from Pyrex.Debugging import print_call_chain +from DebugFlags import debug_disposal_code, debug_temp_alloc, \ + debug_coercion + +class ExprNode(Node): + # subexprs [string] Class var holding names of subexpr node attrs + # type PyrexType Type of the result + # result_code string Code fragment + # result_ctype string C type of result_code if different from type + # inplace_result string Temp var holding in-place operation result + # is_temp boolean Result is in a temporary variable + # is_sequence_constructor + # boolean Is a list or tuple constructor expression + # saved_subexpr_nodes + # [ExprNode or [ExprNode or None] or None] + # Cached result of subexpr_nodes() + + result_ctype = None + + # The Analyse Expressions phase for expressions is split + # into two sub-phases: + # + # Analyse Types + # Determines the result type of the expression based + # on the types of its sub-expressions, and inserts + # coercion nodes into the expression tree where needed. + # Marks nodes which will need to have temporary variables + # allocated. + # + # Allocate Temps + # Allocates temporary variables where needed, and fills + # in the result_code field of each node. + # + # ExprNode provides some convenience routines which + # perform both of the above phases. These should only + # be called from statement nodes, and only when no + # coercion nodes need to be added around the expression + # being analysed. If coercion is needed, the above two phases + # should be invoked separately. + # + # Framework code in ExprNode provides much of the common + # processing for the various phases. It makes use of the + # 'subexprs' class attribute of ExprNodes, which should + # contain a list of the names of attributes which can + # hold sub-nodes or sequences of sub-nodes. + # + # The framework makes use of a number of abstract methods. + # Their responsibilities are as follows. + # + # Declaration Analysis phase + # + # analyse_target_declaration + # Called during the Analyse Declarations phase to analyse + # the LHS of an assignment or argument of a del statement. + # Nodes which cannot be the LHS of an assignment need not + # implement it. + # + # Expression Analysis phase + # + # analyse_types + # - Call analyse_types on all sub-expressions. + # - Check operand types, and wrap coercion nodes around + # sub-expressions where needed. + # - Set the type of this node. + # - If a temporary variable will be required for the + # result, set the is_temp flag of this node. + # + # analyse_target_types + # Called during the Analyse Types phase to analyse + # the LHS of an assignment or argument of a del + # statement. Similar responsibilities to analyse_types. + # + # allocate_temps + # - Call allocate_temps for all sub-nodes. + # - Call allocate_temp for this node. + # - If a temporary was allocated, call release_temp on + # all sub-expressions. + # + # allocate_target_temps + # - Call allocate_temps on sub-nodes and allocate any other + # temps used during assignment. + # - Fill in result_code with a C lvalue if needed. + # - If a rhs node is supplied, call release_temp on it. + # - Call release_temp on sub-nodes and release any other + # temps used during assignment. + # + # #calculate_result_code + # # - Called during the Allocate Temps phase. Should return a + # # C code fragment evaluating to the result. This is only + # # called when the result is not a temporary. + # + # target_code + # Called by the default implementation of allocate_target_temps. + # Should return a C lvalue for assigning to the node. The default + # implementation calls calculate_result_code. + # + # check_const + # - Check that this node and its subnodes form a + # legal constant expression. If so, do nothing, + # otherwise call not_const. + # + # The default implementation of check_const + # assumes that the expression is not constant. + # + # check_const_addr + # - Same as check_const, except check that the + # expression is a C lvalue whose address is + # constant. Otherwise, call addr_not_const. + # + # The default implementation of calc_const_addr + # assumes that the expression is not a constant + # lvalue. + # + # Code Generation phase + # + # generate_evaluation_code + # 1. Call generate_evaluation_code for sub-expressions. + # 2. Generate any C statements necessary to calculate + # the result of this node from the results of its + # sub-expressions. If result is not in a temporary, record + # any information that will be needed by this node's + # implementation of calculate_result_code(). + # 4. If result is in a temporary, call generate_disposal_code + # on all sub-expressions. + # + # A default implementation of generate_evaluation_code + # is provided which uses the folling abstract methods: + # generate_result_code (for no. 2) + # + # generate_assignment_code + # Called on the LHS of an assignment. + # - Call generate_evaluation_code for sub-expressions. + # - Generate code to perform the assignment. + # - If the assignment absorbed a reference, call + # generate_post_assignment_code on the RHS, + # otherwise call generate_disposal_code on it. + # + # generate_deletion_code + # Called on an argument of a del statement. + # - Call generate_evaluation_code for sub-expressions. + # - Generate code to perform the deletion. + # - Call generate_disposal_code on all sub-expressions. + # + # calculate_result_code + # Return a C code fragment representing the result of this node. + # This is only called if the result is not in a temporary. + # + + is_sequence_constructor = 0 + is_attribute = 0 + + saved_subexpr_nodes = None + is_temp = 0 + + def not_implemented(self, method_name): + print_call_chain(method_name, "not implemented") ### + raise InternalError( + "%s.%s not implemented" % + (self.__class__.__name__, method_name)) + + def is_lvalue(self): + return 0 + + def is_inplace_lvalue(self): + return 0 + + def is_ephemeral(self): + # An ephemeral node is one whose result is in + # a Python temporary and we suspect there are no + # other references to it. Certain operations are + # disallowed on such values, since they are + # likely to result in a dangling pointer. + return self.type.is_pyobject and self.is_temp + + def subexpr_nodes(self): + # Extract a list of subexpression nodes based + # on the contents of the subexprs class attribute. + if self.saved_subexpr_nodes is None: + nodes = [] + for name in self.subexprs: + item = getattr(self, name) + if item: + if isinstance(item, ExprNode): + nodes.append(item) + else: + nodes.extend(item) + self.saved_subexpr_nodes = nodes + return self.saved_subexpr_nodes + + def result(self): + # Return a C code fragment for the result of this node. + if self.is_temp: + result_code = self.result_code + else: + result_code = self.calculate_result_code() + return result_code + + def result_as(self, type = None): + # Return the result code cast to the specified C type. + return typecast(type, self.ctype(), self.result()) + + def py_result(self): + # Return the result code cast to PyObject *. + return self.result_as(py_object_type) + + def ctype(self): + # Return the native C type of the result. + return self.result_ctype or self.type + + def compile_time_value(self, denv): + # Return value of compile-time expression, or report error. + error(self.pos, "Invalid compile-time expression") + + def compile_time_value_error(self, e): + error(self.pos, "Error in compile-time expression: %s: %s" % ( + e.__class__.__name__, e)) + + # ------------- Declaration Analysis ---------------- + + def analyse_target_declaration(self, env): + error(self.pos, "Cannot assign to or delete this") + + # ------------- Expression Analysis ---------------- + + def analyse_const_expression(self, env): + # Called during the analyse_declarations phase of a + # constant expression. Analyses the expression's type, + # checks whether it is a legal const expression, + # and determines its value. + self.analyse_types(env) + self.allocate_temps(env) + self.check_const() + + def analyse_expressions(self, env): + # Convenience routine performing both the Type + # Analysis and Temp Allocation phases for a whole + # expression. + self.analyse_types(env) + self.allocate_temps(env) + + def analyse_target_expression(self, env, rhs): + # Convenience routine performing both the Type + # Analysis and Temp Allocation phases for the LHS of + # an assignment. + self.analyse_target_types(env) + self.allocate_target_temps(env, rhs) + + def analyse_boolean_expression(self, env): + # Analyse expression and coerce to a boolean. + self.analyse_types(env) + bool = self.coerce_to_boolean(env) + bool.allocate_temps(env) + return bool + + def analyse_temp_boolean_expression(self, env): + # Analyse boolean expression and coerce result into + # a temporary. This is used when a branch is to be + # performed on the result and we won't have an + # opportunity to ensure disposal code is executed + # afterwards. By forcing the result into a temporary, + # we ensure that all disposal has been done by the + # time we get the result. + self.analyse_types(env) + bool = self.coerce_to_boolean(env) + temp_bool = bool.coerce_to_temp(env) + temp_bool.allocate_temps(env) + return temp_bool + + # --------------- Type Analysis ------------------ + + def analyse_as_function(self, env): + # Analyse types for an expression that is to be called. + self.analyse_types(env) + + def analyse_as_module(self, env): + # If this node can be interpreted as a reference to a + # cimported module, return its scope, else None. + return None + + def analyse_as_extension_type(self, env): + # If this node can be interpreted as a reference to an + # extension type, return its type, else None. + return None + + def analyse_as_cimported_attribute(self, env, *args, **kwds): + # If this node can be interpreted as a cimported name, + # finish type analysis and return true, else return false. + return 0 + + def analyse_types(self, env): + self.not_implemented("analyse_types") + + def analyse_target_types(self, env): + self.analyse_types(env) + + def analyse_inplace_types(self, env): + if self.is_inplace_lvalue(): + self.analyse_types(env) + else: + error(self.pos, "Invalid target for in-place operation") + self.type = error_type + + def gil_assignment_check(self, env): + if env.nogil and self.type.is_pyobject: + error(self.pos, "Assignment of Python object not allowed without gil") + + def check_const(self): + self.not_const() + + def not_const(self): + error(self.pos, "Not allowed in a constant expression") + + def check_const_addr(self): + self.addr_not_const() + + def addr_not_const(self): + error(self.pos, "Address is not constant") + + def gil_check(self, env): + if env.nogil and self.type.is_pyobject: + self.gil_error() + + # ----------------- Result Allocation ----------------- + + def result_in_temp(self): + # Return true if result is in a temporary owned by + # this node or one of its subexpressions. Overridden + # by certain nodes which can share the result of + # a subnode. + return self.is_temp + + def allocate_target_temps(self, env, rhs, inplace = 0): + # Perform temp allocation for the LHS of an assignment. + if debug_temp_alloc: + print self, "Allocating target temps" + self.allocate_subexpr_temps(env) + #self.result_code = self.target_code() + if rhs: + rhs.release_temp(env) + self.release_subexpr_temps(env) + + def allocate_inplace_target_temps(self, env, rhs): + if debug_temp_alloc: + print self, "Allocating inplace target temps" + self.allocate_subexpr_temps(env) + #self.result_code = self.target_code() + py_inplace = self.type.is_pyobject + if py_inplace: + self.allocate_temp(env) + self.inplace_result = env.allocate_temp(py_object_type) + self.release_temp(env) + rhs.release_temp(env) + if py_inplace: + env.release_temp(self.inplace_result) + self.release_subexpr_temps(env) + + def allocate_temps(self, env, result = None): + # Allocate temporary variables for this node and + # all its sub-expressions. If a result is specified, + # this must be a temp node and the specified variable + # is used as the result instead of allocating a new + # one. + if debug_temp_alloc: + print self, "Allocating temps" + self.allocate_subexpr_temps(env) + self.allocate_temp(env, result) + if self.is_temp: + self.release_subexpr_temps(env) + + def allocate_subexpr_temps(self, env): + # Allocate temporary variables for all sub-expressions + # of this node. + if debug_temp_alloc: + print self, "Allocating temps for:", self.subexprs + for node in self.subexpr_nodes(): + if node: + if debug_temp_alloc: + print self, "Allocating temps for", node + node.allocate_temps(env) + + def allocate_temp(self, env, result = None): + # If this node requires a temporary variable for its + # result, allocate one. If a result is specified, + # this must be a temp node and the specified variable + # is used as the result instead of allocating a new + # one. + if debug_temp_alloc: + print self, "Allocating temp" + if result: + if not self.is_temp: + raise InternalError("Result forced on non-temp node") + self.result_code = result + elif self.is_temp: + type = self.type + if not type.is_void: + if type.is_pyobject: + type = PyrexTypes.py_object_type + self.result_code = env.allocate_temp(type) + else: + self.result_code = None + if debug_temp_alloc: + print self, "Allocated result", self.result_code + #else: + # self.result_code = self.calculate_result_code() + + def target_code(self): + # Return code fragment for use as LHS of a C assignment. + return self.calculate_result_code() + + def calculate_result_code(self): + self.not_implemented("calculate_result_code") + + def release_temp(self, env): + # If this node owns a temporary result, release it, + # otherwise release results of its sub-expressions. + if self.is_temp: + if debug_temp_alloc: + print self, "Releasing result", self.result_code + env.release_temp(self.result_code) + else: + self.release_subexpr_temps(env) + + def release_subexpr_temps(self, env): + # Release the results of all sub-expressions of + # this node. + for node in self.subexpr_nodes(): + if node: + node.release_temp(env) + + # ---------------- Code Generation ----------------- + + def mark_vars_used(self): + for node in self.subexpr_nodes(): + node.mark_vars_used() + + def make_owned_reference(self, code): + # If result is a pyobject, make sure we own + # a reference to it. + if self.type.is_pyobject and not self.result_in_temp(): + code.put_incref(self.py_result()) + + def generate_evaluation_code(self, code): + # Generate code to evaluate this node and + # its sub-expressions, and dispose of any + # temporary results of its sub-expressions. + self.generate_subexpr_evaluation_code(code) + self.generate_result_code(code) + if self.is_temp: + self.generate_subexpr_disposal_code(code) + + def generate_subexpr_evaluation_code(self, code): + for node in self.subexpr_nodes(): + node.generate_evaluation_code(code) + + def generate_result_code(self, code): + self.not_implemented("generate_result_code") + + inplace_functions = { + "+=": "PyNumber_InPlaceAdd", + "-=": "PyNumber_InPlaceSubtract", + "*=": "PyNumber_InPlaceMultiply", + "/=": "PyNumber_InPlaceDivide", + "%=": "PyNumber_InPlaceRemainder", + "**=": "PyNumber_InPlacePower", + "<<=": "PyNumber_InPlaceLshift", + ">>=": "PyNumber_InPlaceRshift", + "&=": "PyNumber_InPlaceAnd", + "^=": "PyNumber_InPlaceXor", + "|=": "PyNumber_InPlaceOr", + } + + def generate_inplace_operation_code(self, operator, rhs, code): + args = (self.py_result(), rhs.py_result()) + if operator == "**=": + arg_code = "%s, %s, Py_None" % args + else: + arg_code = "%s, %s" % args + code.putln("%s = %s(%s); if (!%s) %s" % ( + self.inplace_result, + self.inplace_functions[operator], + arg_code, + self.inplace_result, + code.error_goto(self.pos))) + if self.is_temp: + code.put_decref_clear(self.py_result()) + rhs.generate_disposal_code(code) + if self.type.is_extension_type: + code.putln( + "if (!__Pyx_TypeTest(%s, %s)) %s" % ( + self.inplace_result, + self.type.typeptr_cname, + code.error_goto(self.pos))) + + def generate_disposal_code(self, code): + # If necessary, generate code to dispose of + # temporary Python reference. + if self.is_temp: + if self.type.is_pyobject: + code.put_decref_clear(self.py_result(), self.ctype()) + else: + self.generate_subexpr_disposal_code(code) + + def generate_subexpr_disposal_code(self, code): + # Generate code to dispose of temporary results + # of all sub-expressions. + for node in self.subexpr_nodes(): + node.generate_disposal_code(code) + + def generate_post_assignment_code(self, code): + # Same as generate_disposal_code except that + # assignment will have absorbed a reference to + # the result if it is a Python object. + if self.is_temp: + if self.type.is_pyobject: + code.putln("%s = 0;" % self.result()) + else: + self.generate_subexpr_disposal_code(code) + + def generate_inplace_result_disposal_code(self, code): + code.put_decref_clear(self.inplace_result, py_object_type) + + def generate_assignment_code(self, rhs, code): + # Stub method for nodes which are not legal as + # the LHS of an assignment. An error will have + # been reported earlier. + pass + + def generate_deletion_code(self, code): + # Stub method for nodes that are not legal as + # the argument of a del statement. An error + # will have been reported earlier. + pass + + # ----------------- Coercion ---------------------- + + def coerce_to(self, dst_type, env): + # Coerce the result so that it can be assigned to + # something of type dst_type. If processing is necessary, + # wraps this node in a coercion node and returns that. + # Otherwise, returns this node unchanged. + # + # This method is called during the analyse_expressions + # phase of the src_node's processing. + src = self + src_type = self.type + src_is_py_type = src_type.is_pyobject + dst_is_py_type = dst_type.is_pyobject + + if dst_type.is_pyobject: + if not src.type.is_pyobject: + src = CoerceToPyTypeNode(src, env) + if not src.type.subtype_of(dst_type): + if not isinstance(src, NoneNode): + src = PyTypeTestNode(src, dst_type, env) + elif src.type.is_pyobject: + src = CoerceFromPyTypeNode(dst_type, src, env) + else: # neither src nor dst are py types + if not dst_type.assignable_from(src_type): + error(self.pos, "Cannot assign type '%s' to '%s'" % + (src.type, dst_type)) + return src + + def coerce_to_pyobject(self, env): + return self.coerce_to(PyrexTypes.py_object_type, env) + + def coerce_to_boolean(self, env): + # Coerce result to something acceptable as + # a boolean value. + type = self.type + if type.is_pyobject or type.is_ptr or type.is_float: + return CoerceToBooleanNode(self, env) + else: + if not type.is_int and not type.is_error: + error(self.pos, + "Type '%s' not acceptable as a boolean" % type) + return self + + def coerce_to_integer(self, env): + # If not already some C integer type, coerce to longint. + if self.type.is_int: + return self + else: + return self.coerce_to(PyrexTypes.c_long_type, env) + + def coerce_to_temp(self, env): + # Ensure that the result is in a temporary. + if self.result_in_temp(): + return self + else: + return CoerceToTempNode(self, env) + + def coerce_to_simple(self, env): + # Ensure that the result is simple (see is_simple). + if self.is_simple(): + return self + else: + return self.coerce_to_temp(env) + + def is_simple(self): + # A node is simple if its result is something that can + # be referred to without performing any operations, e.g. + # a constant, local var, C global var, struct member + # reference, or temporary. + return self.result_in_temp() + + +class AtomicExprNode(ExprNode): + # Abstract base class for expression nodes which have + # no sub-expressions. + + subexprs = [] + + +class PyConstNode(AtomicExprNode): + # Abstract base class for constant Python values. + + def is_simple(self): + return 1 + + def analyse_types(self, env): + self.type = py_object_type + + def calculate_result_code(self): + return self.value + + def generate_result_code(self, code): + pass + + +class NoneNode(PyConstNode): + # The constant value None + + value = "Py_None" + + def compile_time_value(self, denv): + return None + + +class EllipsisNode(PyConstNode): + # '...' in a subscript list. + + value = "Py_Ellipsis" + + def compile_time_value(self, denv): + return Ellipsis + + +class ConstNode(AtomicExprNode): + # Abstract base type for literal constant nodes. + # + # value string C code fragment + + is_literal = 1 + + def is_simple(self): + return 1 + + def analyse_types(self, env): + pass # Types are held in class variables + + def check_const(self): + pass + + def calculate_result_code(self): + return str(self.value) + + def generate_result_code(self, code): + pass + + +class NullNode(ConstNode): + type = PyrexTypes.c_null_ptr_type + value = "NULL" + + +class CharNode(ConstNode): + type = PyrexTypes.c_char_type + + def compile_time_value(self, denv): + return ord(self.value) + + def calculate_result_code(self): + return "'%s'" % self.value + + +class IntNode(ConstNode): + type = PyrexTypes.c_long_type + + def compile_time_value(self, denv): + return int(self.value, 0) + + +class FloatNode(ConstNode): + type = PyrexTypes.c_double_type + + def compile_time_value(self, denv): + return float(self.value) + + def calculate_result_code(self): + strval = str(self.value) + if strval == 'nan': + return "NAN" + elif strval == 'inf': + return "INFINITY" + elif strval == '-inf': + return "(-INFINITY)" + else: + return strval + + +class StringNode(ConstNode): + # #entry Symtab.Entry + + type = PyrexTypes.c_char_ptr_type + + def compile_time_value(self, denv): + return eval('"%s"' % self.value) + +# def analyse_types(self, env): +# self.entry = env.add_string_const(self.value) + + def coerce_to(self, dst_type, env): + # Arrange for a Python version of the string to be pre-allocated + # when coercing to a Python type. + if dst_type.is_pyobject and not self.type.is_pyobject: + node = self.as_py_string_node(env) + else: + node = self + # We still need to perform normal coerce_to processing on the + # result, because we might be coercing to an extension type, + # in which case a type test node will be needed. + return ConstNode.coerce_to(node, dst_type, env) + + def as_py_string_node(self, env): + # Return a new StringNode with the same value as this node + # but whose type is a Python type instead of a C type. + #entry = self.entry + #env.add_py_string(entry) + return StringNode(self.pos, type = py_object_type, value = self.value) + + def generate_evaluation_code(self, code): + if self.type.is_pyobject: + self.result_code = code.get_py_string_const(self.value) + else: + self.result_code = code.get_string_const(self.value) + + def calculate_result_code(self): + return self.result_code + + +class LongNode(AtomicExprNode): + # Python long integer literal + # + # value string + + def compile_time_value(self, denv): + return long(self.value) + + gil_message = "Constructing Python long int" + + def analyse_types(self, env): + self.type = py_object_type + self.gil_check(env) + self.is_temp = 1 + + def generate_evaluation_code(self, code): + result = self.result() + code.putln( + '%s = PyLong_FromString("%s", 0, 0); if (!%s) %s' % ( + self.result(), + self.value, + self.result(), + code.error_goto(self.pos))) + + +class ImagNode(AtomicExprNode): + # Imaginary number literal + # + # value float imaginary part + + def compile_time_value(self, denv): + return complex(0.0, self.value) + + gil_message = "Constructing complex number" + + def analyse_types(self, env): + self.type = py_object_type + self.gil_check(env) + self.is_temp = 1 + + def generate_evaluation_code(self, code): + result = self.result() + code.putln( + "%s = PyComplex_FromDoubles(0.0, %s); if (!%s) %s" % ( + self.result(), + self.value, + self.result(), + code.error_goto(self.pos))) + + +class NameNode(AtomicExprNode): + # Reference to a local or global variable name. + # + # name string Python name of the variable + # + # entry Entry Symbol table entry + # type_entry Entry For extension type names, the original type entry + # interned_cname string + + is_name = 1 + entry = None + type_entry = None + + def compile_time_value(self, denv): + try: + return denv.lookup(self.name) + except KeyError: + error(self.pos, "Compile-time name '%s' not defined" % self.name) + + def coerce_to(self, dst_type, env): + # If coercing to a generic pyobject and this is a builtin + # C function with a Python equivalent, manufacture a NameNode + # referring to the Python builtin. + #print "NameNode.coerce_to:", self.name, dst_type ### + if dst_type is py_object_type: + entry = self.entry + if entry.is_cfunction: + var_entry = entry.as_variable + if var_entry: + node = NameNode(self.pos, name = self.name) + node.entry = var_entry + node.analyse_rvalue_entry(env) + return node + return AtomicExprNode.coerce_to(self, dst_type, env) + + def analyse_as_module(self, env): + # Try to interpret this as a reference to a cimported module. + # Returns the module scope, or None. + entry = env.lookup(self.name) + if entry and entry.as_module: + return entry.as_module + return None + + def analyse_as_extension_type(self, env): + # Try to interpret this as a reference to an extension type. + # Returns the extension type, or None. + entry = env.lookup(self.name) + if entry and entry.is_type and entry.type.is_extension_type: + return entry.type + else: + return None + + def analyse_target_declaration(self, env): + self.entry = env.lookup_here(self.name) + if not self.entry: + self.entry = env.declare_var(self.name, py_object_type, self.pos) + + def analyse_types(self, env): + self.lookup_entry(env) + self.analyse_rvalue_entry(env) + + def lookup_entry(self, env): + self.entry = env.lookup(self.name) + if not self.entry: + self.entry = env.declare_builtin(self.name, self.pos) + + def analyse_target_types(self, env): + self.analyse_entry(env) + self.finish_analysing_lvalue() + + def analyse_inplace_types(self, env): + self.analyse_rvalue_entry(env) + self.finish_analysing_lvalue() + + def finish_analysing_lvalue(self): + if self.entry.is_readonly: + error(self.pos, "Assignment to read-only name '%s'" + % self.name) + elif not self.is_lvalue(): + error(self.pos, "Assignment to non-lvalue '%s'" + % self.name) + self.type = PyrexTypes.error_type + self.entry.used = 1 + + def analyse_as_function(self, env): + self.lookup_entry(env) + if self.entry.is_type: + self.analyse_constructor_entry(env) + else: + self.analyse_rvalue_entry(env) + + def analyse_constructor_entry(self, env): + entry = self.entry + type = entry.type + if type.is_struct_or_union: + self.type = entry.type.cplus_constructor_type + elif type.is_pyobject: + self.analyse_rvalue_entry(env) + else: + error(self.pos, "Type '%s' not callable as a C++ constructor" % type) + self.type = error_type + + def analyse_rvalue_entry(self, env): + #print "NameNode.analyse_rvalue_entry:", self.name ### + #print "Entry:", self.entry.__dict__ ### + self.analyse_entry(env) + entry = self.entry + if entry.is_declared_generic: + self.result_ctype = py_object_type + if entry.is_pyglobal or entry.is_builtin: + self.is_temp = 1 + self.gil_check(env) + + gil_message = "Accessing Python global or builtin" + + def analyse_entry(self, env): + #print "NameNode.analyse_entry:", self.name ### + self.check_identifier_kind() + entry = self.entry + type = entry.type + ctype = entry.ctype + self.type = type + if ctype: + self.result_ctype = ctype + if entry.is_pyglobal or entry.is_builtin: + assert type.is_pyobject, "Python global or builtin not a Python object" + #self.interned_cname = env.intern(self.entry.name) + + def check_identifier_kind(self): + # Check that this is an appropriate kind of name for use in an expression. + # Also finds the variable entry associated with an extension type. + entry = self.entry + if entry.is_type and entry.type.is_extension_type: + self.type_entry = entry + if not (entry.is_const or entry.is_variable + or entry.is_builtin or entry.is_cfunction): + if self.entry.as_variable: + self.entry = self.entry.as_variable + else: + error(self.pos, + "'%s' is not a constant, variable or function identifier" % self.name) + + def is_simple(self): + # If it's not a C variable, it'll be in a temp. + return 1 + + def calculate_target_results(self, env): + pass + + def check_const(self): + entry = self.entry + if not (entry.is_const or entry.is_cfunction): + self.not_const() + + def check_const_addr(self): + entry = self.entry + if not (entry.is_cglobal or entry.is_cfunction): + self.addr_not_const() + + def is_lvalue(self): + entry = self.entry + return entry.is_variable and \ + not entry.type.is_array and \ + not entry.is_readonly + + def is_inplace_lvalue(self): + return self.is_lvalue() + + def is_ephemeral(self): + # Name nodes are never ephemeral, even if the + # result is in a temporary. + return 0 + + def allocate_temp(self, env, result = None): + AtomicExprNode.allocate_temp(self, env, result) + entry = self.entry + if entry: + entry.used = 1 + + def calculate_result_code(self): + entry = self.entry + if not entry: + return "" # There was an error earlier + return entry.cname + + def generate_result_code(self, code): + assert hasattr(self, 'entry') + entry = self.entry + if entry is None: + return # There was an error earlier + if entry.utility_code: + code.use_utility_code(entry.utility_code) + if entry.is_pyglobal or entry.is_builtin: + if entry.is_builtin: + namespace = Naming.builtins_cname + else: # entry.is_pyglobal + namespace = entry.namespace_cname + result = self.result() + cname = code.intern(self.entry.name) + code.use_utility_code(get_name_interned_utility_code) + code.putln( + '%s = __Pyx_GetName(%s, %s); if (!%s) %s' % ( + result, + namespace, + cname, + result, + code.error_goto(self.pos))) + + def generate_setattr_code(self, value_code, code): + entry = self.entry + namespace = self.entry.namespace_cname + cname = code.intern(self.entry.name) + code.putln( + 'if (PyObject_SetAttr(%s, %s, %s) < 0) %s' % ( + namespace, + cname, + value_code, + code.error_goto(self.pos))) + + def generate_assignment_code(self, rhs, code): + #print "NameNode.generate_assignment_code:", self.name ### + entry = self.entry + if entry is None: + return # There was an error earlier + if entry.is_pyglobal: + self.generate_setattr_code(rhs.py_result(), code) + if debug_disposal_code: + print "NameNode.generate_assignment_code:" + print "...generating disposal code for", rhs + rhs.generate_disposal_code(code) + else: + if self.type.is_pyobject: + rhs.make_owned_reference(code) + code.put_decref(self.py_result()) + code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype()))) + if debug_disposal_code: + print "NameNode.generate_assignment_code:" + print "...generating post-assignment code for", rhs + rhs.generate_post_assignment_code(code) + + def generate_inplace_assignment_code(self, operator, rhs, code): + entry = self.entry + if entry is None: + return # There was an error earlier + if self.type.is_pyobject: + self.generate_result_code(code) + self.generate_inplace_operation_code(operator, rhs, code) + if entry.is_pyglobal: + self.generate_setattr_code(self.inplace_result, code) + self.generate_inplace_result_disposal_code(code) + else: + code.put_decref(self.py_result()) + cast_inplace_result = typecast(self.ctype(), py_object_type, self.inplace_result) + code.putln('%s = %s;' % (self.result(), cast_inplace_result)) + else: + code.putln("%s %s %s;" % (self.result(), operator, rhs.result())) + rhs.generate_disposal_code(code) + + def generate_deletion_code(self, code): + if self.entry is None: + return # There was an error earlier + if not self.entry.is_pyglobal: + error(self.pos, "Deletion of local or C global name not supported") + return + cname = code.intern(self.entry.name) + code.putln( + 'if (PyObject_DelAttr(%s, %s) < 0) %s' % ( + Naming.module_cname, + cname, + code.error_goto(self.pos))) + + def mark_vars_used(self): + if self.entry: + self.entry.used = 1 + + +class BackquoteNode(ExprNode): + # `expr` + # + # arg ExprNode + + subexprs = ['arg'] + + def analyse_types(self, env): + self.arg.analyse_types(env) + self.arg = self.arg.coerce_to_pyobject(env) + self.type = py_object_type + self.gil_check(env) + self.is_temp = 1 + + gil_message = "Backquote expression" + + def generate_result_code(self, code): + result = self.result() + code.putln( + "%s = PyObject_Repr(%s); if (!%s) %s" % ( + self.result(), + self.arg.py_result(), + self.result(), + code.error_goto(self.pos))) + + +class ImportNode(ExprNode): + # Used as part of import statement implementation. + # Implements result = + # __import__(module_name, globals(), None, name_list) + # + # module_name StringNode dotted name of module + # name_list ListNode or None list of names to be imported + + subexprs = ['module_name', 'name_list'] + + def analyse_types(self, env): + self.module_name.analyse_types(env) + self.module_name = self.module_name.coerce_to_pyobject(env) + if self.name_list: + self.name_list.analyse_types(env) + self.type = py_object_type + self.gil_check(env) + self.is_temp = 1 +# env.use_utility_code(import_utility_code) + + gil_message = "Python import" + + def generate_result_code(self, code): + if self.name_list: + name_list_code = self.name_list.py_result() + else: + name_list_code = "0" + code.use_utility_code(import_utility_code) + result = self.result() + code.putln( + "%s = __Pyx_Import(%s, %s); if (!%s) %s" % ( + result, + self.module_name.py_result(), + name_list_code, + result, + code.error_goto(self.pos))) + + +class IteratorNode(ExprNode): + # Used as part of for statement implementation. + # Implements result = iter(sequence) + # + # sequence ExprNode + + subexprs = ['sequence'] + + def analyse_types(self, env): + self.sequence.analyse_types(env) + self.sequence = self.sequence.coerce_to_pyobject(env) + self.type = py_object_type + self.gil_check(env) + self.is_temp = 1 + + gil_message = "Iterating over Python object" + + def generate_result_code(self, code): + result = self.result() + code.putln( + "%s = PyObject_GetIter(%s); if (!%s) %s" % ( + result, + self.sequence.py_result(), + result, + code.error_goto(self.pos))) + + +class NextNode(AtomicExprNode): + # Used as part of for statement implementation. + # Implements result = iterator.next() + # Created during analyse_types phase. + # The iterator is not owned by this node. + # + # iterator ExprNode + + def __init__(self, iterator, env): + self.pos = iterator.pos + self.iterator = iterator + self.type = py_object_type + self.is_temp = 1 + + def generate_result_code(self, code): + result = self.result() + code.putln( + "%s = PyIter_Next(%s);" % ( + result, + self.iterator.py_result())) + code.putln( + "if (!%s) {" % + result) + code.putln( + "if (PyErr_Occurred()) %s" % + code.error_goto(self.pos)) + code.putln( + "break;") + code.putln( + "}") + + +class ExcValueNode(AtomicExprNode): + # Node created during analyse_types phase + # of an ExceptClauseNode to fetch the current + # exception or traceback value. + + def __init__(self, pos, env, var): + ExprNode.__init__(self, pos) + self.type = py_object_type + self.var = var + + def calculate_result_code(self): + return self.var + + def generate_result_code(self, code): + pass + + +class TempNode(AtomicExprNode): + # Node created during analyse_types phase + # of some nodes to hold a temporary value. + + def __init__(self, pos, type, env): + ExprNode.__init__(self, pos) + self.type = type + if type.is_pyobject: + self.result_ctype = py_object_type + self.is_temp = 1 + + def generate_result_code(self, code): + pass + + +class PyTempNode(TempNode): + # TempNode holding a Python value. + + def __init__(self, pos, env): + TempNode.__init__(self, pos, PyrexTypes.py_object_type, env) + + +#------------------------------------------------------------------- +# +# Trailer nodes +# +#------------------------------------------------------------------- + +class IndexNode(ExprNode): + # Sequence indexing. + # + # base ExprNode + # index ExprNode + + subexprs = ['base', 'index'] + + def compile_time_value(self, denv): + base = self.base.compile_time_value(denv) + index = self.index.compile_time_value(denv) + try: + return base[index] + except Exception, e: + self.compile_time_value_error(e) + + def is_ephemeral(self): + return self.base.is_ephemeral() + + def analyse_target_declaration(self, env): + pass + + def analyse_types(self, env): + self.analyse_base_and_index_types(env, getting = 1) + + def analyse_target_types(self, env): + self.analyse_base_and_index_types(env, setting = 1) + + def analyse_inplace_types(self, env): + self.analyse_base_and_index_types(env, getting = 1, setting = 1) + + def analyse_base_and_index_types(self, env, getting = 0, setting = 0): + self.base.analyse_types(env) + self.index.analyse_types(env) + btype = self.base.type + if btype.is_pyobject: + itype = self.index.type + if not (btype.is_sequence and itype.is_int and itype.signed): + self.index = self.index.coerce_to_pyobject(env) + self.type = py_object_type + self.gil_check(env) + self.is_temp = 1 + else: + if self.base.type.is_ptr or self.base.type.is_array: + self.type = self.base.type.base_type + else: + error(self.pos, + "Attempting to index non-array type '%s'" % + self.base.type) + self.type = PyrexTypes.error_type + if self.index.type.is_pyobject: + self.index = self.index.coerce_to( + PyrexTypes.c_py_ssize_t_type, env) + if not self.index.type.is_int: + error(self.pos, + "Invalid index type '%s'" % + self.index.type) + + gil_message = "Indexing Python object" + + def check_const_addr(self): + self.base.check_const_addr() + self.index.check_const() + + def is_lvalue(self): + return 1 + + def is_inplace_lvalue(self): + return 1 + + def calculate_result_code(self): + return "(%s[%s])" % ( + self.base.result(), self.index.result()) + + def generate_result_code(self, code): + if self.type.is_pyobject: + itype = self.index.type + if itype.is_int and itype.signed: + code.use_utility_code(getitem_int_utility_code) + function = "__Pyx_GetItemInt" + index_code = self.index.result() + else: + function = "PyObject_GetItem" + index_code = self.index.py_result() + result = self.result() + code.putln( + "%s = %s(%s, %s); if (!%s) %s" % ( + result, + function, + self.base.py_result(), + index_code, + result, + code.error_goto(self.pos))) + + def generate_setitem_code(self, value_code, code): + itype = self.index.type + if itype.is_int and itype.signed: + code.use_utility_code(setitem_int_utility_code) + function = "__Pyx_SetItemInt" + index_code = self.index.result() + else: + function = "PyObject_SetItem" + index_code = self.index.py_result() + code.putln( + "if (%s(%s, %s, %s) < 0) %s" % ( + function, + self.base.py_result(), + index_code, + value_code, + code.error_goto(self.pos))) + + def generate_assignment_code(self, rhs, code): + self.generate_subexpr_evaluation_code(code) + if self.type.is_pyobject: + self.generate_setitem_code(rhs.py_result(), code) + else: + code.putln( + "%s = %s;" % ( + self.result(), rhs.result())) + self.generate_subexpr_disposal_code(code) + rhs.generate_disposal_code(code) + + def generate_inplace_assignment_code(self, operator, rhs, code): + self.generate_subexpr_evaluation_code(code) + if self.type.is_pyobject: + self.generate_result_code(code) + self.generate_inplace_operation_code(operator, rhs, code) + self.generate_setitem_code(self.inplace_result, code) + self.generate_inplace_result_disposal_code(code) + else: + code.putln("%s %s %s;" % (self.result(), operator, rhs.result())) + rhs.generate_disposal_code(code) + self.generate_subexpr_disposal_code(code) + + def generate_deletion_code(self, code): + self.generate_subexpr_evaluation_code(code) + if self.base.type.is_sequence and self.index.type.is_int: + function = "PySequence_DelItem" + index_code = self.index.result() + else: + function = "PyObject_DelItem" + index_code = self.index.py_result() + code.putln( + "if (%s(%s, %s) < 0) %s" % ( + function, + self.base.py_result(), + index_code, + code.error_goto(self.pos))) + #else: + # error(self.pos, "Cannot delete non-Python variable") + self.generate_subexpr_disposal_code(code) + + +class SliceIndexNode(ExprNode): + # 2-element slice indexing + # + # base ExprNode + # start ExprNode or None + # stop ExprNode or None + + subexprs = ['base', 'start', 'stop'] + + def is_inplace_lvalue(self): + return 1 + + def compile_time_value(self, denv): + base = self.base.compile_time_value(denv) + start = self.start.compile_time_value(denv) + stop = self.stop.compile_time_value(denv) + try: + return base[start:stop] + except Exception, e: + self.compile_time_value_error(e) + + def analyse_target_declaration(self, env): + pass + + def analyse_types(self, env): + self.base.analyse_types(env) + if self.start: + self.start.analyse_types(env) + if self.stop: + self.stop.analyse_types(env) + self.base = self.base.coerce_to_pyobject(env) + c_int = PyrexTypes.c_py_ssize_t_type + if self.start: + self.start = self.start.coerce_to(c_int, env) + if self.stop: + self.stop = self.stop.coerce_to(c_int, env) + self.type = py_object_type + self.gil_check(env) + self.is_temp = 1 + + gil_message = "Slicing Python object" + + def generate_result_code(self, code): + result = self.result() + code.putln( + "%s = PySequence_GetSlice(%s, %s, %s); if (!%s) %s" % ( + result, + self.base.py_result(), + self.start_code(), + self.stop_code(), + result, + code.error_goto(self.pos))) + + def generate_setslice_code(self, value_code, code): + code.putln( + "if (PySequence_SetSlice(%s, %s, %s, %s) < 0) %s" % ( + self.base.py_result(), + self.start_code(), + self.stop_code(), + value_code, + code.error_goto(self.pos))) + + def generate_assignment_code(self, rhs, code): + self.generate_subexpr_evaluation_code(code) + self.generate_setslice_code(rhs.result(), code) + self.generate_subexpr_disposal_code(code) + rhs.generate_disposal_code(code) + + def generate_inplace_assignment_code(self, operator, rhs, code): + self.generate_subexpr_evaluation_code(code) + self.generate_result_code(code) + self.generate_inplace_operation_code(operator, rhs, code) + self.generate_setslice_code(self.inplace_result, code) + self.generate_inplace_result_disposal_code(code) + self.generate_subexpr_disposal_code(code) + + def generate_deletion_code(self, code): + self.generate_subexpr_evaluation_code(code) + code.putln( + "if (PySequence_DelSlice(%s, %s, %s) < 0) %s" % ( + self.base.py_result(), + self.start_code(), + self.stop_code(), + code.error_goto(self.pos))) + self.generate_subexpr_disposal_code(code) + + def start_code(self): + if self.start: + return self.start.result() + else: + return "0" + + def stop_code(self): + if self.stop: + return self.stop.result() + else: + return "PY_SSIZE_T_MAX" + +# def calculate_result_code(self): +# # self.result_code is not used, but this method must exist +# return "" + + +class SliceNode(ExprNode): + # start:stop:step in subscript list + # + # start ExprNode + # stop ExprNode + # step ExprNode + + def compile_time_value(self, denv): + start = self.start.compile_time_value(denv) + stop = self.stop.compile_time_value(denv) + step = step.step.compile_time_value(denv) + try: + return slice(start, stop, step) + except Exception, e: + self.compile_time_value_error(e) + + subexprs = ['start', 'stop', 'step'] + + def analyse_types(self, env): + self.start.analyse_types(env) + self.stop.analyse_types(env) + self.step.analyse_types(env) + self.start = self.start.coerce_to_pyobject(env) + self.stop = self.stop.coerce_to_pyobject(env) + self.step = self.step.coerce_to_pyobject(env) + self.type = py_object_type + self.gil_check(env) + self.is_temp = 1 + + gil_message = "Constructing Python slice object" + + def generate_result_code(self, code): + result = self.result() + code.putln( + "%s = PySlice_New(%s, %s, %s); if (!%s) %s" % ( + result, + self.start.py_result(), + self.stop.py_result(), + self.step.py_result(), + result, + code.error_goto(self.pos))) + + +class CallNode(ExprNode): + + def gil_check(self, env): + # Make sure we're not in a nogil environment + if env.nogil: + error(self.pos, "Calling gil-requiring function without gil") + + +class SimpleCallNode(CallNode): + # Function call without keyword, * or ** args. + # + # function ExprNode + # args [ExprNode] + # arg_tuple ExprNode or None used internally + # self ExprNode or None used internally + # coerced_self ExprNode or None used internally + # function_type PyrexType used internally + + subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple'] + + self = None + coerced_self = None + arg_tuple = None + is_new = False + + cplus_argless_constr_type = CFuncType(None, []) + + def compile_time_value(self, denv): + function = self.function.compile_time_value(denv) + args = [arg.compile_time_value(denv) for arg in self.args] + try: + return function(*args) + except Exception, e: + self.compile_time_value_error(e) + + def analyse_types(self, env): + #print "SimpleCallNode.analyse_types:", self.pos ### + function = self.function + function.is_called = 1 + function.analyse_as_function(env) + if function.is_name or function.is_attribute: + #print "SimpleCallNode.analyse_types:", self.pos, "is name or attribute" ### + func_entry = function.entry + if func_entry: + if func_entry.is_cmethod or func_entry.is_builtin_method: + # Take ownership of the object from which the attribute + # was obtained, because we need to pass it as 'self'. + #print "SimpleCallNode: Snarfing self argument" ### + self.self = function.obj + function.obj = CloneNode(self.self) + elif self.is_new: + if not (func_entry.is_type and func_entry.type.is_struct_or_union + and func_entry.type.scope.is_cplus): + error(self.pos, "'new' operator can only be used on a C++ struct type") + self.type = error_type + return + else: + #print "SimpleCallNode.analyse_types:", self.pos, "not name or attribute" ### + if self.is_new: + error(self.pos, "Invalid use of 'new' operator") + self.type = error_type + return + func_type = self.function.type + if func_type.is_ptr: + func_type = func_type.base_type + self.function_type = func_type + if func_type.is_pyobject: + #print "SimpleCallNode: Python call" ### + if self.args: + self.arg_tuple = TupleNode(self.pos, args = self.args) + self.arg_tuple.analyse_types(env) + else: + self.arg_tuple = None + self.args = None + if function.is_name and function.type_entry: + # We are calling an extension type constructor + self.type = function.type_entry.type + self.result_ctype = py_object_type + else: + self.type = py_object_type + self.gil_check(env) + self.is_temp = 1 + else: + #print "SimpleCallNode: C call" ### + for arg in self.args: + arg.analyse_types(env) + if func_type.is_cfunction: + self.type = func_type.return_type + if self.is_new: + self.type = CPtrType(self.type) + if func_type.is_overloaded: + func_type = self.resolve_overloading() + if not func_type: + self.type = error_type + return + if self.self and func_type.args: + #print "SimpleCallNode: Inserting self into argument list" ### + # Coerce 'self' to the type expected by the method. + expected_type = func_type.args[0].type + self.coerced_self = CloneNode(self.self).coerce_to( + expected_type, env) + # Insert coerced 'self' argument into argument list. + self.args.insert(0, self.coerced_self) + self.analyse_c_function_call(env) + + def resolve_overloading(self): + func_type = self.function_type + arg_types = [arg.type for arg in self.args] + signatures = func_type.signatures or [self.cplus_argless_constr_type] + for signature in signatures: + if signature.callable_with(arg_types): + signature.return_type = func_type.return_type + self.function_type = signature + return signature + def display_types(types): + return ", ".join([str(type) for type in types]) + error(self.pos, "No matching signature found for argument types (%s)" + % display_types(arg_types)) + if signatures: + error(self.pos, "Candidates are:") + for signature in signatures: + error(signature.pos, "(%s)" % display_types(signature.args)) + + def analyse_c_function_call(self, env): + func_type = self.function_type + # Check function type + if not func_type.is_cfunction: + if not func_type.is_error: + error(self.pos, "Calling non-function type '%s'" % + func_type) + self.type = PyrexTypes.error_type + return + # Check no. of args + expected_nargs = len(func_type.args) + actual_nargs = len(self.args) + if actual_nargs < expected_nargs \ + or (not func_type.has_varargs and actual_nargs > expected_nargs): + expected_str = str(expected_nargs) + if func_type.has_varargs: + expected_str = "at least " + expected_str + error(self.pos, + "Call with wrong number of arguments (expected %s, got %s)" + % (expected_str, actual_nargs)) + self.args = None + self.type = PyrexTypes.error_type + return + # Coerce arguments + for i in range(expected_nargs): + formal_type = func_type.args[i].type + self.args[i] = self.args[i].coerce_to(formal_type, env) + for i in range(expected_nargs, actual_nargs): + if self.args[i].type.is_pyobject: + error(self.args[i].pos, + "Python object cannot be passed as a varargs parameter") + # Calc result code fragment + #print "SimpleCallNode.analyse_c_function_call: self.type =", self.type ### + if self.type.is_pyobject \ + or func_type.exception_value is not None \ + or func_type.exception_check: + self.is_temp = 1 + if self.type.is_pyobject: + self.result_ctype = py_object_type + # Check gil + if not func_type.nogil: + self.gil_check(env) + if func_type.exception_check and env.nogil: + self.gil_error("Calling 'except ?' or 'except *' function") + + def calculate_result_code(self): + return self.c_call_code() + + def c_call_code(self): + if self.type.is_error or self.args is None or not self.function_type.is_cfunction: + return "" + func_type = self.function_type + formal_args = func_type.args + arg_list_code = [] + for (formal_arg, actual_arg) in zip(formal_args, self.args): + arg_code = actual_arg.result_as(formal_arg.type) + arg_list_code.append(arg_code) + for actual_arg in self.args[len(formal_args):]: + arg_list_code.append(actual_arg.result()) + result = "%s(%s)" % (self.function.result(), + join(arg_list_code, ",")) + if self.is_new: + result = "new " + result + return result + + def generate_result_code(self, code): + if self.type.is_error: + return + func_type = self.function_type + result = self.result() + if func_type.is_pyobject: + if self.arg_tuple: + arg_code = self.arg_tuple.py_result() + else: + arg_code = "0" + code.putln( + "%s = PyObject_CallObject(%s, %s); if (!%s) %s" % ( + result, + self.function.py_result(), + arg_code, + result, + code.error_goto(self.pos))) + elif func_type.is_cfunction: + exc_checks = [] + if self.type.is_pyobject: + exc_checks.append("!%s" % result) + else: + exc_val = func_type.exception_value + exc_check = func_type.exception_check + if exc_val is not None: + exc_checks.append("%s == %s" % (self.result(), exc_val)) + if exc_check: + exc_checks.append("PyErr_Occurred()") + if self.is_temp or exc_checks: + rhs = self.c_call_code() + result = self.result() + if result: + lhs = "%s = " % result + if self.is_temp and self.type.is_pyobject: + #return_type = self.type # func_type.return_type + #print "SimpleCallNode.generate_result_code: casting", rhs, \ + # "from", return_type, "to pyobject" ### + rhs = typecast(py_object_type, self.type, rhs) + else: + lhs = "" + code.putln( + "%s%s; if (%s) %s" % ( + lhs, + rhs, + " && ".join(exc_checks), + code.error_goto(self.pos))) + + +class GeneralCallNode(CallNode): + # General Python function call, including keyword, + # * and ** arguments. + # + # function ExprNode + # positional_args ExprNode Tuple of positional arguments + # keyword_args ExprNode or None Dict of keyword arguments + # starstar_arg ExprNode or None Dict of extra keyword args + + subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg'] + + def compile_time_value(self, denv): + function = self.function.compile_time_value(denv) + positional_args = self.positional_args.compile_time_value(denv) + keyword_args = self.keyword_args.compile_time_value(denv) + starstar_arg = self.starstar_arg.compile_time_value(denv) + try: + keyword_args.update(starstar_arg) + return function(*positional_args, **keyword_args) + except Exception, e: + self.compile_time_value_error(e) + + def analyse_types(self, env): + function = self.function + function.analyse_types(env) + self.positional_args.analyse_types(env) + if self.keyword_args: + self.keyword_args.analyse_types(env) + if self.starstar_arg: + self.starstar_arg.analyse_types(env) + self.function = self.function.coerce_to_pyobject(env) + self.positional_args = \ + self.positional_args.coerce_to_pyobject(env) + if self.starstar_arg: + self.starstar_arg = \ + self.starstar_arg.coerce_to_pyobject(env) + if function.is_name and function.type_entry: + # We are calling an extension type constructor + self.type = function.type_entry.type + self.result_ctype = py_object_type + else: + self.type = py_object_type + self.gil_check(env) + self.is_temp = 1 + + def generate_result_code(self, code): + if self.keyword_args and self.starstar_arg: + code.putln( + "if (PyDict_Update(%s, %s) < 0) %s" % ( + self.keyword_args.py_result(), + self.starstar_arg.py_result(), + code.error_goto(self.pos))) + keyword_code = self.keyword_args.py_result() + elif self.keyword_args: + keyword_code = self.keyword_args.py_result() + elif self.starstar_arg: + keyword_code = self.starstar_arg.py_result() + else: + keyword_code = None + if not keyword_code: + call_code = "PyObject_CallObject(%s, %s)" % ( + self.function.py_result(), + self.positional_args.py_result()) + else: + call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % ( + self.function.py_result(), + self.positional_args.py_result(), + keyword_code) + result = self.result() + code.putln( + "%s = %s; if (!%s) %s" % ( + result, + call_code, + result, + code.error_goto(self.pos))) + + +class AsTupleNode(ExprNode): + # Convert argument to tuple. Used for normalising + # the * argument of a function call. + # + # arg ExprNode + + subexprs = ['arg'] + + def compile_time_value(self, denv): + arg = self.arg.compile_time_value(denv) + try: + return tuple(arg) + except Exception, e: + self.compile_time_value_error(e) + + def analyse_types(self, env): + self.arg.analyse_types(env) + self.arg = self.arg.coerce_to_pyobject(env) + self.type = py_object_type + self.gil_check(env) + self.is_temp = 1 + + gil_message = "Constructing Python tuple" + + def generate_result_code(self, code): + result = self.result() + code.putln( + "%s = PySequence_Tuple(%s); if (!%s) %s" % ( + result, + self.arg.py_result(), + result, + code.error_goto(self.pos))) + + +class AttributeNode(ExprNode): + # obj.attribute + # + # obj ExprNode + # attribute string + # + # Used internally: + # + # is_py_attr boolean Is a Python getattr operation + # member string C name of struct member + # is_called boolean Function call is being done on result + # entry Entry Symbol table entry of attribute + # interned_attr_cname string C name of interned attribute name + + is_attribute = 1 + subexprs = ['obj'] + + type = PyrexTypes.error_type + result_code = "" + entry = None + is_called = 0 + + def compile_time_value(self, denv): + attr = self.attribute + if attr.startswith("__") and attr.endswith("__"): + self.error("Invalid attribute name '%s' in compile-time expression" + % attr) + return None + obj = self.obj.compile_time_value(denv) + try: + return getattr(obj, attr) + except Exception, e: + self.compile_time_value_error(e) + + def analyse_target_declaration(self, env): + pass + + def analyse_target_types(self, env): + self.analyse_types(env, target = 1) + + def analyse_as_function(self, env): + module_scope = self.obj.analyse_as_module(env) + if module_scope: + entry = module_scope.lookup_here(self.attribute) + if entry and entry.is_type: + self.mutate_into_name_node(entry) + self.analyse_constructor_entry(env) + return + self.analyse_types(env) + + def analyse_types(self, env, target = 0): + if self.analyse_as_cimported_attribute(env, target): + return + if not target and self.analyse_as_unbound_cmethod(env): + return + self.analyse_as_ordinary_attribute(env, target) + + def analyse_as_cimported_attribute(self, env, target = 0, allow_type = 0): + # Try to interpret this as a reference to an imported + # C const, type, var or function. If successful, mutates + # this node into a NameNode and returns 1, otherwise + # returns 0. + module_scope = self.obj.analyse_as_module(env) + if module_scope: + entry = module_scope.lookup_here(self.attribute) + if entry and ( + entry.is_cglobal or entry.is_cfunction + or entry.is_type or entry.is_const): + self.mutate_into_name_node(entry) + if entry.is_type and allow_type: + pass + elif target: + self.analyse_target_types(env) + else: + self.analyse_rvalue_entry(env) + return 1 + return 0 + + def analyse_as_unbound_cmethod(self, env): + # Try to interpret this as a reference to an unbound + # C method of an extension type. If successful, mutates + # this node into a NameNode and returns 1, otherwise + # returns 0. + type = self.obj.analyse_as_extension_type(env) + if type: + entry = type.scope.lookup_here(self.attribute) + if entry and entry.is_cmethod: + # Create a temporary entry describing the C method + # as an ordinary function. + ubcm_entry = Symtab.Entry(entry.name, + "%s->%s" % (type.vtabptr_cname, entry.cname), + entry.type) + ubcm_entry.is_cfunction = 1 + ubcm_entry.func_cname = entry.func_cname + self.mutate_into_name_node(ubcm_entry) + self.analyse_rvalue_entry(env) + return 1 + return 0 + + def analyse_as_extension_type(self, env): + # Try to interpret this as a reference to an extension type + # in a cimported module. Returns the extension type, or None. + module_scope = self.obj.analyse_as_module(env) + if module_scope: + entry = module_scope.lookup_here(self.attribute) + if entry and entry.is_type and entry.type.is_extension_type: + return entry.type + return None + + def analyse_as_module(self, env): + # Try to interpret this as a reference to a cimported module + # in another cimported module. Returns the module scope, or None. + module_scope = self.obj.analyse_as_module(env) + if module_scope: + entry = module_scope.lookup_here(self.attribute) + if entry and entry.as_module: + return entry.as_module + return None + + def mutate_into_name_node(self, entry): + # Turn this node into a NameNode with the given entry. + self.__class__ = NameNode + self.name = self.attribute + self.entry = entry + del self.obj + del self.attribute + + def analyse_as_ordinary_attribute(self, env, target): + self.obj.analyse_types(env) + self.analyse_attribute(env) + if self.entry and self.entry.is_cmethod and not self.is_called: + error(self.pos, "C method can only be called") + if self.is_py_attr: + if not target: + self.is_temp = 1 + self.result_ctype = py_object_type + + def analyse_attribute(self, env): + # Look up attribute and set self.type and self.member. + self.is_py_attr = 0 + self.member = self.attribute + if self.obj.type.is_string: + self.obj = self.obj.coerce_to_pyobject(env) + obj_type = self.obj.type + if obj_type.is_ptr: + obj_type = obj_type.base_type + self.op = "->" + elif obj_type.is_extension_type: + self.op = "->" + else: + self.op = "." + if obj_type.has_attributes: + entry = None + if obj_type.attributes_known(): + entry = obj_type.scope.lookup_here(self.attribute) + else: + error(self.pos, + "Cannot select attribute of incomplete type '%s'" + % obj_type) + obj_type = PyrexTypes.error_type + self.entry = entry + if entry: + if obj_type.is_extension_type and entry.name == "__weakref__": + error(self.pos, "Illegal use of special attribute __weakref__") + if entry.is_variable or entry.is_cmethod: + self.type = entry.type + self.member = entry.cname + return + if entry.is_builtin_method and self.is_called: + # Mutate into NameNode referring to C function + #print "AttributeNode: Mutating builtin method into NameNode" ### + self.type = entry.type + self.__class__ = NameNode + return + else: + # If it's not a variable or C method, it must be a Python + # method of an extension type, so we treat it like a Python + # attribute. + pass + # If we get here, the base object is not a struct/union/extension + # type, or it is an extension type and the attribute is either not + # declared or is declared as a Python method. Treat it as a Python + # attribute reference. + if obj_type.is_pyobject: + self.type = py_object_type + self.is_py_attr = 1 + #self.interned_attr_cname = env.intern(self.attribute) + self.gil_check(env) + else: + if not obj_type.is_error: + error(self.pos, + "Object of type '%s' has no attribute '%s'" % + (obj_type, self.attribute)) + + gil_message = "Accessing Python attribute" + + def is_simple(self): + if self.obj: + return self.result_in_temp() or self.obj.is_simple() + else: + return NameNode.is_simple(self) + + def is_lvalue(self): + if self.obj: + return 1 + else: + return NameNode.is_lvalue(self) + + def is_inplace_lvalue(self): + return self.is_lvalue() + + def is_ephemeral(self): + if self.obj: + return self.obj.is_ephemeral() + else: + return NameNode.is_ephemeral(self) + + def calculate_result_code(self): + obj = self.obj + obj_code = obj.result_as(obj.type) + if self.entry and self.entry.is_cmethod: + return "((struct %s *)%s%s%s)->%s" % ( + obj.type.vtabstruct_cname, obj_code, self.op, + obj.type.vtabslot_cname, self.member) + else: + return "%s%s%s" % (obj_code, self.op, self.member) + + def generate_result_code(self, code): + if self.is_py_attr: + result = self.result() + cname = code.intern(self.attribute) + code.putln( + '%s = PyObject_GetAttr(%s, %s); if (!%s) %s' % ( + result, + self.obj.py_result(), + cname, + result, + code.error_goto(self.pos))) + + def generate_setattr_code(self, value_code, code): + cname = code.intern(self.attribute) + code.putln( + 'if (PyObject_SetAttr(%s, %s, %s) < 0) %s' % ( + self.obj.py_result(), + cname, + value_code, + code.error_goto(self.pos))) + + def generate_assignment_code(self, rhs, code): + self.obj.generate_evaluation_code(code) + if self.is_py_attr: + self.generate_setattr_code(rhs.py_result(), code) + rhs.generate_disposal_code(code) + else: + select_code = self.result() + if self.type.is_pyobject: + rhs.make_owned_reference(code) + code.put_decref(select_code, self.ctype()) + code.putln( + "%s = %s;" % ( + select_code, + rhs.result_as(self.ctype()))) + rhs.generate_post_assignment_code(code) + self.obj.generate_disposal_code(code) + + def generate_inplace_assignment_code(self, operator, rhs, code): + self.obj.generate_evaluation_code(code) + select_code = self.result() + if self.type.is_pyobject: + self.generate_result_code(code) + self.generate_inplace_operation_code(operator, rhs, code) + if self.is_py_attr: + self.generate_setattr_code(self.inplace_result, code) + self.generate_inplace_result_disposal_code(code) + else: + code.put_decref(select_code, self.ctype()) + cast_inplace_result = typecast(self.ctype(), py_object_type, self.inplace_result) + code.putln("%s = %s;" % (select_code, cast_inplace_result)) + else: + code.putln("%s %s %s;" % (select_code, operator, rhs.result())) + rhs.generate_disposal_code(code) + self.obj.generate_disposal_code(code) + + def generate_deletion_code(self, code): + self.obj.generate_evaluation_code(code) + if self.is_py_attr: + cname = code.intern(self.attribute) + code.putln( + 'if (PyObject_DelAttr(%s, %s) < 0) %s' % ( + self.obj.py_result(), + cname, + code.error_goto(self.pos))) + else: + error(self.pos, "Cannot delete C attribute of extension type") + self.obj.generate_disposal_code(code) + +#------------------------------------------------------------------- +# +# Constructor nodes +# +#------------------------------------------------------------------- + +class SequenceNode(ExprNode): + # Base class for list and tuple constructor nodes. + # Contains common code for performing sequence unpacking. + # + # args [ExprNode] + # iterator ExprNode + # unpacked_items [ExprNode] or None + # coerced_unpacked_items [ExprNode] or None + + subexprs = ['args'] + + is_sequence_constructor = 1 + unpacked_items = None + + def compile_time_value_list(self, denv): + return [arg.compile_time_value(denv) for arg in self.args] + + def analyse_target_declaration(self, env): + for arg in self.args: + arg.analyse_target_declaration(env) + + def analyse_types(self, env): + for i in range(len(self.args)): + arg = self.args[i] + arg.analyse_types(env) + self.args[i] = arg.coerce_to_pyobject(env) + self.type = py_object_type + self.gil_check(env) + self.is_temp = 1 + + def analyse_target_types(self, env): + self.iterator = PyTempNode(self.pos, env) + self.unpacked_items = [] + self.coerced_unpacked_items = [] + for arg in self.args: + arg.analyse_target_types(env) + unpacked_item = PyTempNode(self.pos, env) + coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env) + self.unpacked_items.append(unpacked_item) + self.coerced_unpacked_items.append(coerced_unpacked_item) + self.type = py_object_type +# env.use_utility_code(unpacking_utility_code) + + def allocate_target_temps(self, env, rhs): + self.iterator.allocate_temps(env) + if rhs: + rhs.release_temp(env) + for arg, node in zip(self.args, self.coerced_unpacked_items): + node.allocate_temps(env) + arg.allocate_target_temps(env, node) + #arg.release_target_temp(env) + #node.release_temp(env) + self.iterator.release_temp(env) + +# def release_target_temp(self, env): +# #for arg in self.args: +# # arg.release_target_temp(env) +# #for node in self.coerced_unpacked_items: +# # node.release_temp(env) +# self.iterator.release_temp(env) + + def generate_result_code(self, code): + self.generate_operation_code(code) + + def generate_assignment_code(self, rhs, code): + iter_result = self.iterator.result() + code.putln( + "%s = PyObject_GetIter(%s); if (!%s) %s" % ( + iter_result, + rhs.py_result(), + iter_result, + code.error_goto(self.pos))) + rhs.generate_disposal_code(code) + for i in range(len(self.args)): + item = self.unpacked_items[i] + code.use_utility_code(unpacking_utility_code) + unpack_code = "__Pyx_UnpackItem(%s)" % ( + self.iterator.py_result()) + item_result = item.result() + code.putln( + "%s = %s; if (!%s) %s" % ( + item_result, + typecast(item.ctype(), py_object_type, unpack_code), + item_result, + code.error_goto(self.pos))) + value_node = self.coerced_unpacked_items[i] + value_node.generate_evaluation_code(code) + self.args[i].generate_assignment_code(value_node, code) + code.putln( + "if (__Pyx_EndUnpack(%s) < 0) %s" % ( + self.iterator.py_result(), + code.error_goto(self.pos))) + if debug_disposal_code: + print "UnpackNode.generate_assignment_code:" + print "...generating disposal code for", rhs + self.iterator.generate_disposal_code(code) + + +class TupleNode(SequenceNode): + # Tuple constructor. + + gil_message = "Constructing Python tuple" + + def compile_time_value(self, denv): + values = self.compile_time_value_list(denv) + try: + return tuple(values) + except Exception, e: + self.compile_time_value_error(e) + + def generate_operation_code(self, code): + result = self.result() + code.putln( + "%s = PyTuple_New(%s); if (!%s) %s" % ( + result, + len(self.args), + result, + code.error_goto(self.pos))) + for i in range(len(self.args)): + arg = self.args[i] + arg_result = arg.py_result() + # ??? Change this to use make_owned_reference? + if not arg.result_in_temp(): + code.put_incref(arg_result) + code.putln( + "PyTuple_SET_ITEM(%s, %s, %s);" % ( + result, + i, + arg_result)) + + def generate_subexpr_disposal_code(self, code): + # We call generate_post_assignment_code here instead + # of generate_disposal_code, because values were stored + # in the tuple using a reference-stealing operation. + for arg in self.args: + arg.generate_post_assignment_code(code) + + +class ListNode(SequenceNode): + # List constructor. + + gil_message = "Constructing Python list" + + def compile_time_value(self, denv): + return self.compile_time_value_list(denv) + + def generate_operation_code(self, code): + result = self.result() + code.putln("%s = PyList_New(%s); if (!%s) %s" % + (result, + len(self.args), + result, + code.error_goto(self.pos))) + for i in range(len(self.args)): + arg = self.args[i] + arg_result = arg.py_result() + #if not arg.is_temp: + if not arg.result_in_temp(): + code.put_incref(arg_result) + code.putln("PyList_SET_ITEM(%s, %s, %s);" % + (result, + i, + arg_result)) + + def generate_subexpr_disposal_code(self, code): + # We call generate_post_assignment_code here instead + # of generate_disposal_code, because values were stored + # in the list using a reference-stealing operation. + for arg in self.args: + arg.generate_post_assignment_code(code) + + +class DictNode(ExprNode): + # Dictionary constructor. + # + # key_value_pairs [(ExprNode, ExprNode)] + + def compile_time_value(self, denv): + pairs = [(key.compile_time_value(denv), value.compile_time_value(denv)) + for (key, value) in self.key_value_pairs] + try: + return dict(pairs) + except Exception, e: + self.compile_time_value_error(e) + + def analyse_types(self, env): + new_pairs = [] + for key, value in self.key_value_pairs: + key.analyse_types(env) + value.analyse_types(env) + key = key.coerce_to_pyobject(env) + value = value.coerce_to_pyobject(env) + new_pairs.append((key, value)) + self.key_value_pairs = new_pairs + self.type = py_object_type + self.gil_check(env) + self.is_temp = 1 + + gil_message = "Constructing Python dict" + + def allocate_temps(self, env, result = None): + # Custom method used here because key-value + # pairs are evaluated and used one at a time. + self.allocate_temp(env, result) + for key, value in self.key_value_pairs: + key.allocate_temps(env) + value.allocate_temps(env) + key.release_temp(env) + value.release_temp(env) + + def generate_evaluation_code(self, code): + # Custom method used here because key-value + # pairs are evaluated and used one at a time. + result = self.result() + code.putln( + "%s = PyDict_New(); if (!%s) %s" % ( + result, + result, + code.error_goto(self.pos))) + for key, value in self.key_value_pairs: + key.generate_evaluation_code(code) + value.generate_evaluation_code(code) + code.putln( + "if (PyDict_SetItem(%s, %s, %s) < 0) %s" % ( + result, + key.py_result(), + value.py_result(), + code.error_goto(self.pos))) + key.generate_disposal_code(code) + value.generate_disposal_code(code) + + +class ClassNode(ExprNode): + # Helper class used in the implementation of Python + # class definitions. Constructs a class object given + # a name, tuple of bases and class dictionary. + # + # name ExprNode Name of the class + # bases ExprNode Base class tuple + # dict ExprNode Class dict (not owned by this node) + # doc ExprNode or None Doc string + # module_name string Name of defining module + + subexprs = ['name', 'bases', 'doc'] + + def analyse_types(self, env): + self.name.analyse_types(env) + self.name = self.name.coerce_to_pyobject(env) + self.bases.analyse_types(env) + if self.doc: + self.doc.analyse_types(env) + self.doc = self.doc.coerce_to_pyobject(env) + self.module_name = env.global_scope().qualified_name + self.type = py_object_type + self.gil_check(env) + self.is_temp = 1 +# env.use_utility_code(create_class_utility_code) + + gil_message = "Constructing Python class" + + def generate_result_code(self, code): + result = self.result() + if self.doc: + code.putln( + 'if (PyDict_SetItemString(%s, "__doc__", %s) < 0) %s' % ( + self.dict.py_result(), + self.doc.py_result(), + code.error_goto(self.pos))) + code.use_utility_code(create_class_utility_code) + code.putln( + '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); if (!%s) %s' % ( + result, + self.bases.py_result(), + self.dict.py_result(), + self.name.py_result(), + self.module_name, + result, + code.error_goto(self.pos))) + + +class UnboundMethodNode(ExprNode): + # Helper class used in the implementation of Python + # class definitions. Constructs an unbound method + # object from a class and a function. + # + # class_cname string C var holding the class object + # function ExprNode Function object + + subexprs = ['function'] + + def analyse_types(self, env): + self.function.analyse_types(env) + self.type = py_object_type + self.gil_check(env) + self.is_temp = 1 + + gil_message = "Constructing an unbound method" + + def generate_result_code(self, code): + result = self.result() + code.putln( + "%s = PyMethod_New(%s, 0, %s); if (!%s) %s" % ( + result, + self.function.py_result(), + self.class_cname, + result, + code.error_goto(self.pos))) + + +class PyCFunctionNode(AtomicExprNode): + # Helper class used in the implementation of Python + # class definitions. Constructs a PyCFunction object + # from a PyMethodDef struct. + # + # pymethdef_cname string PyMethodDef structure + # module_name string Name of defining module + + def analyse_types(self, env): + self.type = py_object_type + self.module_name = env.global_scope().module_name + self.gil_check(env) + self.is_temp = 1 + + gil_message = "Constructing Python function" + + def generate_result_code(self, code): + result = self.result() + code.putln( + "%s = PyCFunction_NewEx(&%s, 0, %s); if (!%s) %s" % ( + result, + self.pymethdef_cname, + code.get_py_string_const(self.module_name), + result, + code.error_goto(self.pos))) + +#------------------------------------------------------------------- +# +# Unary operator nodes +# +#------------------------------------------------------------------- + +compile_time_unary_operators = { + 'not': operator.not_, + '~': operator.inv, + '-': operator.neg, + '+': operator.pos, +} + +class UnopNode(ExprNode): + # operator string + # operand ExprNode + # + # Processing during analyse_expressions phase: + # + # analyse_c_operation + # Called when the operand is not a pyobject. + # - Check operand type and coerce if needed. + # - Determine result type and result code fragment. + # - Allocate temporary for result if needed. + + subexprs = ['operand'] + + def compile_time_value(self, denv): + func = compile_time_unary_operators.get(self.operator) + if not func: + error(self.pos, + "Unary '%s' not supported in compile-time expression" + % self.operator) + operand = self.operand.compile_time_value(denv) + try: + return func(operand) + except Exception, e: + self.compile_time_value_error(e) + + def analyse_types(self, env): + self.operand.analyse_types(env) + if self.is_py_operation(): + self.coerce_operand_to_pyobject(env) + self.type = py_object_type + self.gil_check(env) + self.is_temp = 1 + else: + self.analyse_c_operation(env) + + def check_const(self): + self.operand.check_const() + + def is_py_operation(self): + return self.operand.type.is_pyobject + + def coerce_operand_to_pyobject(self, env): + self.operand = self.operand.coerce_to_pyobject(env) + + def generate_result_code(self, code): + if self.operand.type.is_pyobject: + self.generate_py_operation_code(code) + else: + if self.is_temp: + self.generate_c_operation_code(code) + + def generate_py_operation_code(self, code): + function = self.py_operation_function() + result = self.result() + code.putln( + "%s = %s(%s); if (!%s) %s" % ( + result, + function, + self.operand.py_result(), + result, + code.error_goto(self.pos))) + + def type_error(self): + if not self.operand.type.is_error: + error(self.pos, "Invalid operand type for '%s' (%s)" % + (self.operator, self.operand.type)) + self.type = PyrexTypes.error_type + + +class NotNode(ExprNode): + # 'not' operator + # + # operand ExprNode + + def compile_time_value(self, denv): + operand = self.operand.compile_time_value(denv) + try: + return not operand + except Exception, e: + self.compile_time_value_error(e) + + subexprs = ['operand'] + + def analyse_types(self, env): + self.operand.analyse_types(env) + self.operand = self.operand.coerce_to_boolean(env) + self.type = PyrexTypes.c_int_type + + def calculate_result_code(self): + return "(!%s)" % self.operand.result() + + def generate_result_code(self, code): + pass + + +class UnaryPlusNode(UnopNode): + # unary '+' operator + + operator = '+' + + def analyse_c_operation(self, env): + self.type = self.operand.type + + def py_operation_function(self): + return "PyNumber_Positive" + + def calculate_result_code(self): + return self.operand.result() + + +class UnaryMinusNode(UnopNode): + # unary '-' operator + + operator = '-' + + def analyse_c_operation(self, env): + if self.operand.type.is_numeric: + self.type = self.operand.type + else: + self.type_error() + + def py_operation_function(self): + return "PyNumber_Negative" + + def calculate_result_code(self): + return "(-%s)" % self.operand.result() + + +class TildeNode(UnopNode): + # unary '~' operator + + def analyse_c_operation(self, env): + if self.operand.type.is_int: + self.type = self.operand.type + else: + self.type_error() + + def py_operation_function(self): + return "PyNumber_Invert" + + def calculate_result_code(self): + return "(~%s)" % self.operand.result() + + +class AmpersandNode(ExprNode): + # The C address-of operator. + # + # operand ExprNode + + subexprs = ['operand'] + + def analyse_types(self, env): + self.operand.analyse_types(env) + argtype = self.operand.type + if not (argtype.is_cfunction or self.operand.is_lvalue()): + self.error("Taking address of non-lvalue") + return + if argtype.is_pyobject: + self.error("Cannot take address of Python variable") + return + self.type = PyrexTypes.c_ptr_type(argtype) + + def check_const(self): + self.operand.check_const_addr() + + def error(self, mess): + error(self.pos, mess) + self.type = PyrexTypes.error_type + self.result_code = "" + + def calculate_result_code(self): + return "(&%s)" % self.operand.result() + + def generate_result_code(self, code): + pass + + +unop_node_classes = { + "+": UnaryPlusNode, + "-": UnaryMinusNode, + "~": TildeNode, +} + +def unop_node(pos, operator, operand): + # Construct unnop node of appropriate class for + # given operator. + return unop_node_classes[operator](pos, + operator = operator, + operand = operand) + + +class TypecastNode(ExprNode): + # C type cast + # + # base_type CBaseTypeNode + # declarator CDeclaratorNode + # operand ExprNode + + subexprs = ['operand'] + + def analyse_types(self, env): + base_type = self.base_type.analyse(env) + _, self.type = self.declarator.analyse(base_type, env) + if self.type.is_cfunction: + error(self.pos, + "Cannot cast to a function type") + self.type = PyrexTypes.error_type + self.operand.analyse_types(env) + to_py = self.type.is_pyobject + from_py = self.operand.type.is_pyobject + if from_py and not to_py and self.operand.is_ephemeral(): + error(self.pos, "Casting temporary Python object to non-Python type") + # Must do the following, so that the result can be increfed without + # the operand getting evaluated twice. + if to_py and not from_py: + #self.result_ctype = py_object_type + #self.is_temp = 1 + self.operand = self.operand.coerce_to_simple(env) + + def check_const(self): + self.operand.check_const() + + def calculate_result_code(self): + opnd = self.operand + result_code = self.type.cast_code(opnd.result()) + return result_code + + def result_as(self, type): + if not self.is_temp and type.is_pyobject and self.type.is_pyobject: + # Optimise away some unnecessary casting + return self.operand.result_as(type) + else: + return ExprNode.result_as(self, type) + + def generate_result_code(self, code): + if self.is_temp: + code.putln( + "%s = %s;" % ( + self.result(), + self.operand.py_result())) + code.put_incref(self.py_result()) + + +class SizeofNode(ExprNode): + # Base class for sizeof(x) expression nodes. + # + # sizeof_code string + + subexprs = [] + + def check_const(self): + pass + + def analyse_types(self, env): + self.analyse_argument(env) + self.type = PyrexTypes.c_size_t_type + + def analyse_type_argument(self, arg_type): + if arg_type.is_pyobject: + error(self.pos, "Cannot take sizeof Python object") + elif arg_type.is_void: + error(self.pos, "Cannot take sizeof void") + elif not arg_type.is_complete(): + error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type) + arg_code = arg_type.declaration_code("") + self.sizeof_code = "(sizeof(%s))" % arg_code + + def calculate_result_code(self): + return self.sizeof_code + + def generate_result_code(self, code): + pass + + +class SizeofTypeNode(SizeofNode): + # C sizeof function applied to a type + # + # base_type CBaseTypeNode + # declarator CDeclaratorNode + + def analyse_argument(self, env): + base_type = self.base_type.analyse(env) + _, arg_type = self.declarator.analyse(base_type, env) + self.analyse_type_argument(arg_type) + + +class SizeofVarNode(SizeofNode): + # C sizeof function applied to a variable or qualified name + # (which may actually refer to a type) + # + # operand ExprNode + + #subexprs = ['operand'] + + def analyse_argument(self, env): + is_type = 0 + operand = self.operand + if operand.analyse_as_cimported_attribute(env, allow_type = 1): + if operand.entry.is_type: + is_type = 1 + self.analyse_type_argument(operand.entry.type) + else: + self.operand.analyse_types(env) + self.operand.mark_vars_used() + if not is_type: + self.sizeof_code = "(sizeof(%s))" % operand.result() + + +#------------------------------------------------------------------- +# +# Binary operator nodes +# +#------------------------------------------------------------------- + +compile_time_binary_operators = { + '<': operator.lt, + '<=': operator.le, + '==': operator.eq, + '!=': operator.ne, + '>=': operator.ge, + '>': operator.gt, + 'is': operator.is_, + 'is_not': operator.is_not, + '+': operator.add, + '&': operator.and_, + '/': operator.div, + '//': operator.floordiv, + '<<': operator.lshift, + '%': operator.mod, + '*': operator.mul, + '|': operator.or_, + '**': operator.pow, + '>>': operator.rshift, + '-': operator.sub, + #'/': operator.truediv, + '^': operator.xor, + 'in': lambda x, y: x in y, + 'not_in': lambda x, y: x not in y, +} + +def get_compile_time_binop(node): + func = compile_time_binary_operators.get(node.operator) + if not func: + error(node.pos, + "Binary '%s' not supported in compile-time expression" + % node.operator) + return func + +class BinopNode(ExprNode): + # operator string + # operand1 ExprNode + # operand2 ExprNode + # + # Processing during analyse_expressions phase: + # + # analyse_c_operation + # Called when neither operand is a pyobject. + # - Check operand types and coerce if needed. + # - Determine result type and result code fragment. + # - Allocate temporary for result if needed. + + subexprs = ['operand1', 'operand2'] + + def compile_time_value(self, denv): + func = get_compile_time_binop(self) + operand1 = self.operand1.compile_time_value(denv) + operand2 = self.operand2.compile_time_value(denv) + try: + return func(operand1, operand2) + except Exception, e: + self.compile_time_value_error(e) + + def analyse_types(self, env): + self.operand1.analyse_types(env) + self.operand2.analyse_types(env) + if self.is_py_operation(): + self.coerce_operands_to_pyobjects(env) + self.type = py_object_type + self.gil_check(env) + self.is_temp = 1 + else: + self.analyse_c_operation(env) + + def is_py_operation(self): + return (self.operand1.type.is_pyobject + or self.operand2.type.is_pyobject) + + def coerce_operands_to_pyobjects(self, env): + self.operand1 = self.operand1.coerce_to_pyobject(env) + self.operand2 = self.operand2.coerce_to_pyobject(env) + + def check_const(self): + self.operand1.check_const() + self.operand2.check_const() + + def generate_result_code(self, code): + #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ### + if self.operand1.type.is_pyobject: + function = self.py_operation_function() + if function == "PyNumber_Power": + extra_args = ", Py_None" + else: + extra_args = "" + result = self.result() + code.putln( + "%s = %s(%s, %s%s); if (!%s) %s" % ( + result, + function, + self.operand1.py_result(), + self.operand2.py_result(), + extra_args, + result, + code.error_goto(self.pos))) + else: + if self.is_temp: + self.generate_c_operation_code(code) + + def type_error(self): + if not (self.operand1.type.is_error + or self.operand2.type.is_error): + error(self.pos, "Invalid operand types for '%s' (%s; %s)" % + (self.operator, self.operand1.type, + self.operand2.type)) + self.type = PyrexTypes.error_type + + +class NumBinopNode(BinopNode): + # Binary operation taking numeric arguments. + + def analyse_c_operation(self, env): + type1 = self.operand1.type + type2 = self.operand2.type + if self.operator == "**" and type1.is_int and type2.is_int: + error(self.pos, "** with two C int types is ambiguous") + self.type = error_type + return + self.type = self.compute_c_result_type(type1, type2) + if not self.type: + self.type_error() + + def compute_c_result_type(self, type1, type2): + if self.c_types_okay(type1, type2): + return PyrexTypes.widest_numeric_type(type1, type2) + else: + return None + + def c_types_okay(self, type1, type2): + #print "NumBinopNode.c_types_okay:", type1, type2 ### + return (type1.is_numeric or type1.is_enum) \ + and (type2.is_numeric or type2.is_enum) + + def calculate_result_code(self): + return "(%s %s %s)" % ( + self.operand1.result(), + self.operator, + self.operand2.result()) + + def py_operation_function(self): + return self.py_functions[self.operator] + + py_functions = { + "|": "PyNumber_Or", + "^": "PyNumber_Xor", + "&": "PyNumber_And", + "<<": "PyNumber_Lshift", + ">>": "PyNumber_Rshift", + "+": "PyNumber_Add", + "-": "PyNumber_Subtract", + "*": "PyNumber_Multiply", + "/": "PyNumber_Divide", + "%": "PyNumber_Remainder", + "**": "PyNumber_Power" + } + + +class IntBinopNode(NumBinopNode): + # Binary operation taking integer arguments. + + def c_types_okay(self, type1, type2): + #print "IntBinopNode.c_types_okay:", type1, type2 ### + return (type1.is_int or type1.is_enum) \ + and (type2.is_int or type2.is_enum) + + +class AddNode(NumBinopNode): + # '+' operator. + + def is_py_operation(self): + if self.operand1.type.is_string \ + and self.operand2.type.is_string: + return 1 + else: + return NumBinopNode.is_py_operation(self) + + def compute_c_result_type(self, type1, type2): + #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ### + if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum): + return type1 + elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum): + return type2 + else: + return NumBinopNode.compute_c_result_type( + self, type1, type2) + + +class SubNode(NumBinopNode): + # '-' operator. + + def compute_c_result_type(self, type1, type2): + if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum): + return type1 + elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array): + return PyrexTypes.c_int_type + else: + return NumBinopNode.compute_c_result_type( + self, type1, type2) + + +class MulNode(NumBinopNode): + # '*' operator. + + def is_py_operation(self): + type1 = self.operand1.type + type2 = self.operand2.type + if (type1.is_string and type2.is_int) \ + or (type2.is_string and type1.is_int): + return 1 + else: + return NumBinopNode.is_py_operation(self) + + +class ModNode(IntBinopNode): + # '%' operator. + + def is_py_operation(self): + return (self.operand1.type.is_string + or self.operand2.type.is_string + or IntBinopNode.is_py_operation(self)) + + +class PowNode(NumBinopNode): + # '**' operator. + + def analyse_types(self, env): + env.pow_function_used = 1 + NumBinopNode.analyse_types(self, env) + + def compute_c_result_type(self, type1, type2): + if self.c_types_okay(type1, type2): + return PyrexTypes.c_double_type + else: + return None + + def calculate_result_code(self): + return "pow(%s, %s)" % ( + self.operand1.result(), self.operand2.result()) + + +class BoolBinopNode(ExprNode): + # Short-circuiting boolean operation. + # + # operator string + # operand1 ExprNode + # operand2 ExprNode + # temp_bool ExprNode used internally + + temp_bool = None + + subexprs = ['operand1', 'operand2', 'temp_bool'] + + def compile_time_value(self, denv): + if self.operator == 'and': + return self.operand1.compile_time_value(denv) \ + and self.operand2.compile_time_value(denv) + else: + return self.operand1.compile_time_value(denv) \ + or self.operand2.compile_time_value(denv) + + def analyse_types(self, env): + self.operand1.analyse_types(env) + self.operand2.analyse_types(env) + if self.operand1.type.is_pyobject or \ + self.operand2.type.is_pyobject: + self.operand1 = self.operand1.coerce_to_pyobject(env) + self.operand2 = self.operand2.coerce_to_pyobject(env) + self.temp_bool = TempNode(self.pos, + PyrexTypes.c_int_type, env) + self.type = py_object_type + self.gil_check(env) + else: + self.operand1 = self.operand1.coerce_to_boolean(env) + self.operand2 = self.operand2.coerce_to_boolean(env) + self.type = PyrexTypes.c_int_type + # For what we're about to do, it's vital that + # both operands be temp nodes. + self.operand1 = self.operand1.coerce_to_temp(env) #CTT + self.operand2 = self.operand2.coerce_to_temp(env) + self.is_temp = 1 + + gil_message = "Truth-testing Python object" + + def allocate_temps(self, env, result_code = None): + # We don't need both operands at the same time, and + # one of the operands will also be our result. So we + # use an allocation strategy here which results in + # this node and both its operands sharing the same + # result variable. This allows us to avoid some + # assignments and increfs/decrefs that would otherwise + # be necessary. + self.allocate_temp(env, result_code) + self.operand1.allocate_temps(env, self.result_code) + if self.temp_bool: + self.temp_bool.allocate_temp(env) + self.temp_bool.release_temp(env) + self.operand2.allocate_temps(env, self.result_code) + # We haven't called release_temp on either operand, + # because although they are temp nodes, they don't own + # their result variable. And because they are temp + # nodes, any temps in their subnodes will have been + # released before their allocate_temps returned. + # Therefore, they contain no temp vars that need to + # be released. + + def check_const(self): + self.operand1.check_const() + self.operand2.check_const() + + def calculate_result_code(self): + return "(%s %s %s)" % ( + self.operand1.result(), + self.py_to_c_op[self.operator], + self.operand2.result()) + + py_to_c_op = {'and': "&&", 'or': "||"} + + def generate_evaluation_code(self, code): + self.operand1.generate_evaluation_code(code) + test_result = self.generate_operand1_test(code) + if self.operator == 'and': + sense = "" + else: + sense = "!" + code.putln( + "if (%s%s) {" % ( + sense, + test_result)) + self.operand1.generate_disposal_code(code) + self.operand2.generate_evaluation_code(code) + code.putln( + "}") + + def generate_operand1_test(self, code): + # Generate code to test the truth of the first operand. + if self.type.is_pyobject: + test_result = self.temp_bool.result() + code.putln( + "%s = PyObject_IsTrue(%s); if (%s < 0) %s" % ( + test_result, + self.operand1.py_result(), + test_result, + code.error_goto(self.pos))) + else: + test_result = self.operand1.result() + return test_result + + +class CmpNode: + # Mixin class containing code common to PrimaryCmpNodes + # and CascadedCmpNodes. + + def cascaded_compile_time_value(self, operand1, denv): + func = get_compile_time_binop(self) + operand2 = self.operand2.compile_time_value(denv) + try: + result = func(operand1, operand2) + except Exception, e: + self.compile_time_value_error(e) + result = None + if result: + cascade = self.cascade + if cascade: + result = result and cascade.compile_time_value(operand2, denv) + return result + + def is_python_comparison(self): + return (self.has_python_operands() + or (self.cascade and self.cascade.is_python_comparison()) + or self.operator in ('in', 'not_in')) + + def check_types(self, env, operand1, op, operand2): + if not self.types_okay(operand1, op, operand2): + error(self.pos, "Invalid types for '%s' (%s, %s)" % + (self.operator, operand1.type, operand2.type)) + + def types_okay(self, operand1, op, operand2): + type1 = operand1.type + type2 = operand2.type + if type1.is_error or type2.is_error: + return 1 + if type1.is_pyobject: # type2 will be, too + return 1 + elif type1.is_ptr or type1.is_array: + return type1.is_null_ptr or type2.is_null_ptr \ + or ((type2.is_ptr or type2.is_array) + and type1.base_type.same_as(type2.base_type)) + elif ((type1.is_numeric and type2.is_numeric + or type1.is_enum and (type2.is_int or type1.same_as(type2)) + or type1.is_int and type2.is_enum) + and op not in ('is', 'is_not')): + return 1 + else: + return 0 + + def generate_operation_code(self, code, result, + operand1, op , operand2): + if op == 'in' or op == 'not_in': + code.putln( + "%s = PySequence_Contains(%s, %s); if (%s < 0) %s" % ( + result, + operand2.py_result(), + operand1.py_result(), + result, + code.error_goto(self.pos))) + if op == 'not_in': + code.putln( + "%s = !%s;" % ( + result, result)) + elif (operand1.type.is_pyobject + and op not in ('is', 'is_not')): + code.putln( + "if (PyObject_Cmp(%s, %s, &%s) < 0) %s" % ( + operand1.py_result(), + operand2.py_result(), + result, + code.error_goto(self.pos))) + code.putln( + "%s = %s %s 0;" % ( + result, result, op)) + else: + type1 = operand1.type + type2 = operand2.type + if (type1.is_extension_type or type2.is_extension_type) \ + and not operand1.ctype().same_as(operand2.ctype()): + code1 = operand1.result_as(py_object_type) + code2 = operand2.result_as(py_object_type) + else: + code1 = operand1.result() + code2 = operand2.result() + code.putln("%s = %s %s %s;" % ( + result, + code1, + self.c_operator(op), + code2)) + + def c_operator(self, op): + if op == 'is': + return "==" + elif op == 'is_not': + return "!=" + else: + return op + + +class PrimaryCmpNode(ExprNode, CmpNode): + # Non-cascaded comparison or first comparison of + # a cascaded sequence. + # + # operator string + # operand1 ExprNode + # operand2 ExprNode + # cascade CascadedCmpNode + + # We don't use the subexprs mechanism, because + # things here are too complicated for it to handle. + # Instead, we override all the framework methods + # which use it. + + cascade = None + + def compile_time_value(self, denv): + operand1 = self.operand1.compile_time_value(denv) + return self.cascaded_compile_time_value(operand1, denv) + + def analyse_types(self, env): + self.operand1.analyse_types(env) + self.operand2.analyse_types(env) + if self.cascade: + self.cascade.analyse_types(env, self.operand2) + self.is_pycmp = self.is_python_comparison() + if self.is_pycmp: + self.coerce_operands_to_pyobjects(env) + if self.cascade: + self.operand2 = self.operand2.coerce_to_simple(env) + self.cascade.coerce_cascaded_operands_to_temp(env) + self.check_operand_types(env) + self.type = PyrexTypes.c_int_type + if self.is_pycmp or self.cascade: + self.is_temp = 1 + + def check_operand_types(self, env): + self.check_types(env, + self.operand1, self.operator, self.operand2) + if self.cascade: + self.cascade.check_operand_types(env, self.operand2) + + def has_python_operands(self): + return (self.operand1.type.is_pyobject + or self.operand2.type.is_pyobject) + + def coerce_operands_to_pyobjects(self, env): + self.operand1 = self.operand1.coerce_to_pyobject(env) + self.operand2 = self.operand2.coerce_to_pyobject(env) + if self.cascade: + self.cascade.coerce_operands_to_pyobjects(env) + + def allocate_subexpr_temps(self, env): + self.operand1.allocate_temps(env) + self.operand2.allocate_temps(env) + if self.cascade: + self.cascade.allocate_subexpr_temps(env) + + def release_subexpr_temps(self, env): + self.operand1.release_temp(env) + self.operand2.release_temp(env) + if self.cascade: + self.cascade.release_subexpr_temps(env) + + def check_const(self): + self.operand1.check_const() + self.operand2.check_const() + if self.cascade: + self.not_const() + + def calculate_result_code(self): + return "(%s %s %s)" % ( + self.operand1.result(), + self.c_operator(self.operator), + self.operand2.result()) + + def generate_evaluation_code(self, code): + self.operand1.generate_evaluation_code(code) + self.operand2.generate_evaluation_code(code) + if self.is_temp: + result = self.result() + self.generate_operation_code(code, result, + self.operand1, self.operator, self.operand2) + if self.cascade: + self.cascade.generate_evaluation_code(code, + result, self.operand2) + self.operand1.generate_disposal_code(code) + self.operand2.generate_disposal_code(code) + + def generate_subexpr_disposal_code(self, code): + # If this is called, it is a non-cascaded cmp, + # so only need to dispose of the two main operands. + self.operand1.generate_disposal_code(code) + self.operand2.generate_disposal_code(code) + + +class CascadedCmpNode(Node, CmpNode): + # A CascadedCmpNode is not a complete expression node. It + # hangs off the side of another comparison node, shares + # its left operand with that node, and shares its result + # with the PrimaryCmpNode at the head of the chain. + # + # operator string + # operand2 ExprNode + # cascade CascadedCmpNode + + cascade = None + + def analyse_types(self, env, operand1): + self.operand2.analyse_types(env) + if self.cascade: + self.cascade.analyse_types(env, self.operand2) + + def check_operand_types(self, env, operand1): + self.check_types(env, + operand1, self.operator, self.operand2) + if self.cascade: + self.cascade.check_operand_types(env, self.operand2) + + def has_python_operands(self): + return self.operand2.type.is_pyobject + + def coerce_operands_to_pyobjects(self, env): + self.operand2 = self.operand2.coerce_to_pyobject(env) + if self.cascade: + self.cascade.coerce_operands_to_pyobjects(env) + + def coerce_cascaded_operands_to_temp(self, env): + if self.cascade: + #self.operand2 = self.operand2.coerce_to_temp(env) #CTT + self.operand2 = self.operand2.coerce_to_simple(env) + self.cascade.coerce_cascaded_operands_to_temp(env) + + def allocate_subexpr_temps(self, env): + self.operand2.allocate_temps(env) + if self.cascade: + self.cascade.allocate_subexpr_temps(env) + + def release_subexpr_temps(self, env): + self.operand2.release_temp(env) + if self.cascade: + self.cascade.release_subexpr_temps(env) + + def generate_evaluation_code(self, code, result, operand1): + code.putln("if (%s) {" % result) + self.operand2.generate_evaluation_code(code) + self.generate_operation_code(code, result, + operand1, self.operator, self.operand2) + if self.cascade: + self.cascade.generate_evaluation_code( + code, result, self.operand2) + # Cascaded cmp result is always temp + self.operand2.generate_disposal_code(code) + code.putln("}") + + +binop_node_classes = { + "or": BoolBinopNode, + "and": BoolBinopNode, + "|": IntBinopNode, + "^": IntBinopNode, + "&": IntBinopNode, + "<<": IntBinopNode, + ">>": IntBinopNode, + "+": AddNode, + "-": SubNode, + "*": MulNode, + "/": NumBinopNode, + "%": ModNode, + "**": PowNode +} + +def binop_node(pos, operator, operand1, operand2): + # Construct binop node of appropriate class for + # given operator. + return binop_node_classes[operator](pos, + operator = operator, + operand1 = operand1, + operand2 = operand2) + +#------------------------------------------------------------------- +# +# Coercion nodes +# +# Coercion nodes are special in that they are created during +# the analyse_types phase of parse tree processing. +# Their __init__ methods consequently incorporate some aspects +# of that phase. +# +#------------------------------------------------------------------- + +class CoercionNode(ExprNode): + # Abstract base class for coercion nodes. + # + # arg ExprNode node being coerced + + subexprs = ['arg'] + + def __init__(self, arg): + self.pos = arg.pos + self.arg = arg + if debug_coercion: + print self, "Coercing", self.arg + + +class CastNode(CoercionNode): + # Wrap a node in a C type cast. + + def __init__(self, arg, new_type): + CoercionNode.__init__(self, arg) + self.type = new_type + + def calculate_result_code(self): + return self.arg.result_as(self.type) + + def generate_result_code(self, code): + self.arg.generate_result_code(code) + + +class PyTypeTestNode(CoercionNode): + # This node is used to check that a generic Python + # object is an instance of a particular extension type. + # This node borrows the result of its argument node. + + def __init__(self, arg, dst_type, env): + # The arg is know to be a Python object, and + # the dst_type is known to be an extension type. + assert dst_type.is_extension_type, "PyTypeTest on non extension type" + CoercionNode.__init__(self, arg) + self.type = dst_type + self.result_ctype = arg.ctype() +# env.use_utility_code(type_test_utility_code) + self.gil_check(env) + + gil_message = "Python type test" + + def result_in_temp(self): + return self.arg.result_in_temp() + + def is_ephemeral(self): + return self.arg.is_ephemeral() + + def calculate_result_code(self): + return self.arg.result() + + def generate_result_code(self, code): + if self.type.typeobj_is_available(): + code.use_utility_code(type_test_utility_code) + code.putln( + "if (!__Pyx_TypeTest(%s, %s)) %s" % ( + self.arg.py_result(), + self.type.typeptr_cname, + code.error_goto(self.pos))) + else: + error(self.pos, "Cannot test type of extern C class " + "without type object name specification") + + def generate_post_assignment_code(self, code): + self.arg.generate_post_assignment_code(code) + + +class CoerceToPyTypeNode(CoercionNode): + # This node is used to convert a C data type + # to a Python object. + + def __init__(self, arg, env): + CoercionNode.__init__(self, arg) + self.type = py_object_type + self.gil_check(env) + self.is_temp = 1 + if not arg.type.to_py_function: + error(arg.pos, + "Cannot convert '%s' to Python object" % arg.type) + + gil_message = "Converting to Python object" + + def generate_result_code(self, code): + function = self.arg.type.to_py_function + result = self.result() + code.putln('%s = %s(%s); if (!%s) %s' % ( + result, + function, + self.arg.result(), + result, + code.error_goto(self.pos))) + + +class CoerceFromPyTypeNode(CoercionNode): + # This node is used to convert a Python object + # to a C data type. + + def __init__(self, result_type, arg, env): + CoercionNode.__init__(self, arg) + self.type = result_type + self.is_temp = 1 + if not result_type.from_py_function: + error(arg.pos, + "Cannot convert Python object to '%s'" % result_type) + if self.type.is_string and self.arg.is_ephemeral(): + error(arg.pos, + "Obtaining char * from temporary Python value") + + def generate_result_code(self, code): + function = self.type.from_py_function + operand = self.arg.py_result() + rhs = "%s(%s)" % (function, operand) + if self.type.is_enum: + rhs = typecast(self.type, c_long_type, rhs) + result = self.result() + if self.type.is_string: + err_code = "!%s" % result + else: + err_code = "PyErr_Occurred()" + code.putln('%s = %s; if (%s) %s' % ( + result, + rhs, + err_code, + code.error_goto(self.pos))) + + +class CoerceToBooleanNode(CoercionNode): + # This node is used when a result needs to be used + # in a boolean context. + + def __init__(self, arg, env): + CoercionNode.__init__(self, arg) + self.type = PyrexTypes.c_int_type + if arg.type.is_pyobject: + if env.nogil: + self.gil_error() + self.is_temp = 1 + + gil_message = "Truth-testing Python object" + + def check_const(self): + if self.is_temp: + self.not_const() + self.arg.check_const() + + def calculate_result_code(self): + return "(%s != 0)" % self.arg.result() + + def generate_result_code(self, code): + if self.arg.type.is_pyobject: + result = self.result() + code.putln( + "%s = PyObject_IsTrue(%s); if (%s < 0) %s" % ( + result, + self.arg.py_result(), + result, + code.error_goto(self.pos))) + + +class CoerceToTempNode(CoercionNode): + # This node is used to force the result of another node + # to be stored in a temporary. It is only used if the + # argument node's result is not already in a temporary. + + def __init__(self, arg, env): + CoercionNode.__init__(self, arg) + self.type = self.arg.type + self.is_temp = 1 + if self.type.is_pyobject: + self.gil_check(env) + self.result_ctype = py_object_type + + gil_message = "Creating temporary Python reference" + + + def generate_result_code(self, code): + #self.arg.generate_evaluation_code(code) # Already done + # by generic generate_subexpr_evaluation_code! + code.putln("%s = %s;" % ( + self.result(), self.arg.result_as(self.ctype()))) + if self.type.is_pyobject: + code.put_incref(self.py_result()) + + +class CloneNode(CoercionNode): + # This node is employed when the result of another node needs + # to be used multiple times. The argument node's result must + # be in a temporary. This node "borrows" the result from the + # argument node, and does not generate any evaluation or + # disposal code for it. The original owner of the argument + # node is responsible for doing those things. + + subexprs = [] # Arg is not considered a subexpr + + def __init__(self, arg): + CoercionNode.__init__(self, arg) + self.type = arg.type + self.result_ctype = arg.result_ctype + + def calculate_result_code(self): + return self.arg.result() + + def generate_evaluation_code(self, code): + pass + + def generate_result_code(self, code): + pass + +#------------------------------------------------------------------------------------ +# +# Runtime support code +# +#------------------------------------------------------------------------------------ + +get_name_utility_code = [ +""" +static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/ +""",""" +static PyObject *__Pyx_GetName(PyObject *dict, char *name) { + PyObject *result; + result = PyObject_GetAttrString(dict, name); + if (!result) + PyErr_SetString(PyExc_NameError, name); + return result; +} +"""] + +get_name_interned_utility_code = [ +""" +static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/ +""",""" +static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) { + PyObject *result; + result = PyObject_GetAttr(dict, name); + if (!result) + PyErr_SetObject(PyExc_NameError, name); + return result; +} +"""] + +#------------------------------------------------------------------------------------ + +import_utility_code = [ +""" +static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/ +""",""" +static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) { + PyObject *__import__ = 0; + PyObject *empty_list = 0; + PyObject *module = 0; + PyObject *global_dict = 0; + PyObject *empty_dict = 0; + PyObject *list; + __import__ = PyObject_GetAttrString(%(BUILTINS)s, "__import__"); + if (!__import__) + goto bad; + if (from_list) + list = from_list; + else { + empty_list = PyList_New(0); + if (!empty_list) + goto bad; + list = empty_list; + } + global_dict = PyModule_GetDict(%(GLOBALS)s); + if (!global_dict) + goto bad; + empty_dict = PyDict_New(); + if (!empty_dict) + goto bad; + module = PyObject_CallFunction(__import__, "OOOO", + name, global_dict, empty_dict, list); +bad: + Py_XDECREF(empty_list); + Py_XDECREF(__import__); + Py_XDECREF(empty_dict); + return module; +} +""" % { + "BUILTINS": Naming.builtins_cname, + "GLOBALS": Naming.module_cname, +}] + +#------------------------------------------------------------------------------------ +# +#get_exception_utility_code = [ +#""" +#static PyObject *__Pyx_GetExcValue(void); /*proto*/ +#""",""" +#static PyObject *__Pyx_GetExcValue(void) { +# PyObject *type = 0, *value = 0, *tb = 0; +# PyObject *result = 0; +# PyThreadState *tstate = PyThreadState_Get(); +# PyErr_Fetch(&type, &value, &tb); +# PyErr_NormalizeException(&type, &value, &tb); +# if (PyErr_Occurred()) +# goto bad; +# if (!value) { +# value = Py_None; +# Py_INCREF(value); +# } +# Py_XDECREF(tstate->exc_type); +# Py_XDECREF(tstate->exc_value); +# Py_XDECREF(tstate->exc_traceback); +# tstate->exc_type = type; +# tstate->exc_value = value; +# tstate->exc_traceback = tb; +# result = value; +# Py_XINCREF(result); +# type = 0; +# value = 0; +# tb = 0; +#bad: +# Py_XDECREF(type); +# Py_XDECREF(value); +# Py_XDECREF(tb); +# return result; +#} +#"""] +# +#------------------------------------------------------------------------------------ + +unpacking_utility_code = [ +""" +static PyObject *__Pyx_UnpackItem(PyObject *); /*proto*/ +static int __Pyx_EndUnpack(PyObject *); /*proto*/ +""",""" +static void __Pyx_UnpackError(void) { + PyErr_SetString(PyExc_ValueError, "unpack sequence of wrong size"); +} + +static PyObject *__Pyx_UnpackItem(PyObject *iter) { + PyObject *item; + if (!(item = PyIter_Next(iter))) { + if (!PyErr_Occurred()) + __Pyx_UnpackError(); + } + return item; +} + +static int __Pyx_EndUnpack(PyObject *iter) { + PyObject *item; + if ((item = PyIter_Next(iter))) { + Py_DECREF(item); + __Pyx_UnpackError(); + return -1; + } + else if (!PyErr_Occurred()) + return 0; + else + return -1; +} +"""] + +#------------------------------------------------------------------------------------ + +type_test_utility_code = [ +""" +static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/ +""",""" +static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) { + if (!type) { + PyErr_Format(PyExc_SystemError, "Missing type object"); + return 0; + } + if (obj == Py_None || PyObject_TypeCheck(obj, type)) + return 1; + PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s", + obj->ob_type->tp_name, type->tp_name); + return 0; +} +"""] + +#------------------------------------------------------------------------------------ + +create_class_utility_code = [ +""" +static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, char *modname); /*proto*/ +""",""" +static PyObject *__Pyx_CreateClass( + PyObject *bases, PyObject *dict, PyObject *name, char *modname) +{ + PyObject *py_modname; + PyObject *result = 0; + + py_modname = PyString_FromString(modname); + if (!py_modname) + goto bad; + if (PyDict_SetItemString(dict, "__module__", py_modname) < 0) + goto bad; + result = PyClass_New(bases, dict, name); +bad: + Py_XDECREF(py_modname); + return result; +} +"""] + +#------------------------------------------------------------------------------------ + +getitem_int_utility_code = [ +""" +static PyObject *__Pyx_GetItemInt(PyObject *o, Py_ssize_t i); /*proto*/ +""",""" +static PyObject *__Pyx_GetItemInt(PyObject *o, Py_ssize_t i) { + PyTypeObject *t = o->ob_type; + PyObject *r; + if (t->tp_as_sequence && t->tp_as_sequence->sq_item) + r = PySequence_GetItem(o, i); + else { + PyObject *j = PyInt_FromLong(i); + if (!j) + return 0; + r = PyObject_GetItem(o, j); + Py_DECREF(j); + } + return r; +} +"""] + +#------------------------------------------------------------------------------------ + +setitem_int_utility_code = [ +""" +static int __Pyx_SetItemInt(PyObject *o, Py_ssize_t i, PyObject *v); /*proto*/ +""",""" +static int __Pyx_SetItemInt(PyObject *o, Py_ssize_t i, PyObject *v) { + PyTypeObject *t = o->ob_type; + int r; + if (t->tp_as_sequence && t->tp_as_sequence->sq_item) + r = PySequence_SetItem(o, i, v); + else { + PyObject *j = PyInt_FromLong(i); + if (!j) + return -1; + r = PyObject_SetItem(o, j, v); + Py_DECREF(j); + } + return r; +} +"""] diff --git a/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Filenames.py b/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Filenames.py new file mode 100644 index 00000000..09092e28 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Filenames.py @@ -0,0 +1,9 @@ +# +# Pyrex - Filename suffixes +# + +cplus_suffix = ".cpp" +pxd_suffixes = (".pxd",) +pyx_suffixes = (".pyx", ".pyx+") +package_init_files = ("__init__.py", "__init__.pyx", "__init__.pyx+") +pyx_to_c_suffix = {".pyx": ".c", ".pyx+": cplus_suffix} diff --git a/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Lexicon.pickle b/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Lexicon.pickle new file mode 100644 index 0000000000000000000000000000000000000000..1631a72c7e1d31838bb605c51fc4e722c58466bd GIT binary patch literal 19254 zcmeI4d3;<)eZaHCabh{PEcw3ImJj)ob*?1eI##l@I;`VawtUDdY2}e3YdtF|b^?r_8q->}nR#IG2m8uvltxl!}N|H$(DJmQ|a!)38 zvFOOCpe1#2cpyDCp5rfabR?~xW%RAV?dOsMYIrQA=S+K`)oI6b8j|A^K9QquOY6Bt z-(DEZ9iK=}q{j6fr}Vr+qjL&_TiSxiokq`hSM${T;MV^1s20_NDV4gjEx0w69?}aX zb5yd-O%6;9r^j@z)sN~$6oP(i@?3u^qw^AngE^_u@s!SQn^gWOl{>AaHMWTHoTjs5 z=}am|FHY+vMlTI+@9P^(5A^lvWx>mHqS2F?^a?jvaA@Vm zKCPohZzv4z=<6Fxo=eGqZ44Ior_K(K^|{{lc_S4BbI71Kse;LV+Xrd>MVcSBtxftR zx~6QMTH}=STtBxMy?NH|bf+#(wbhM4z8#jl z#GP&=WZCS<&Q_?zemjlcrPdWHu}YEAy9<@rB7HtJ*4Lj&4&0TR2yIcUHmTxER#@nY z+-`IUMFtVMD$Oq3wjqe@SKGxtt+pY4K25u`$d$8GZ4V++f0->JFR?__L8RK~a#woX z=n8-9p72)8-D)i}KDC9w`-4b@ zipkmw%iLk~A>XYR%&hS$DwFD6xx3V%Yk90$x|Ww{^DQW+eS(y#n9*@j7IUWzl&W&y zaYt-}ql*LL=21@0&vy>z%(ZodK8(e1_?4B2^)cZQ0J+pM*9eH@xf~{33cbBTamd9NG zmW92J`vFn4LB!o!?i&}U>v3B}i_s0X>EU8v8a5hzSf=5emiD$r-4sssPI+1ymr}Li zpxG7J99B~iR?{A~AaU8PdwmNMv_NqAlo4eycgjGiN_Y!Mq7qF^G~NOUYXQ++Zy_a0 z2Ba92fl?V7XLdsE&ZLGp<972h#WAw%NJ&J_Z3SBYza@c zTdi{C)EXVwr}Gl4rJF_{^{JzDT2KngK@3!ZT2K!fz+un~TGUY~Hi#S{(FwZ2QE&|O zf_^XvhJXSiU=)mj^B@Bzz}?^?xEGXwGEf03K{c2JHJ}c}K_h4a3D64KK?k@8bb$c$ zfa9PI^noN804eDnar9Xd!{9D(4y5HCmeVB0CBYoOAkr<*9;1)3e>T;}Wq}?a@3%8W zvi|?jUdPa?9vQ}Z6)+J6he0!FQGxi22s2SqoksWiX}ucmvvdR%Ah3bJPI#*#~t^ z!cuoQxx-~HFnZAU(&*I8%rYto@`c?Ghbl+q8$INoQ>mG^n^nFVnw$(Gn~gr3UFNhc zYrboNSTcxgGg@V5w1>1|qeuK9?JlE7IixKa7)_6-W}ec{$tmsJrBhn2D_8>BvFtLZ zRi5Ya>@qri#XO5$o^b|#x6$XXm~pAgXt#eGeO0ih+o-FWt4T`Oi&^Asq_0@aN>|K5 zGS=`&9n&DrRU>Eu3D64KK?k@8bb$c$faBnV+972IkyA3$WQP(>5)4poO8nkJqchpf zvBN%Y^n@SwNu%#(*mLA%Qg|f3AcKA3(qM0JjXq1c!{9D(4y2_9Sw$DAA&AJbyXUgH z?lt<^zAl;ChPoDxr7n!hi?Xo3`=q}6F4fmdeNz+eUMjfXSD@|*^?sS2uzB+m8(kYU zjcSud$;-0mx@UL^X5WxGSHDGV4kCqWhaBuxNf2@8b5+J3Q1j!$HPsy+IRrHjL<-cPtW0%QHVnJ;m>WCP7$>$g@rd+b zw>s~m*;%Hu(m~{A&R3a7SDb0;A|X|1V##?yOf7FbBhSX5MybgsQ5pTbspq~;jLa+$rgC$@Y zSOHdnHDDcxf{jX^-Ne-vPzbhzouCL5gHliqVxS7_0sFuKa0t|bde8t4gJ#g8ULr2P zfLSW3PS6dGf@7c;oTNSTxmo~nK^|BPmV)JAC0GsCg7shnC;*$mRA81 zE5#qY@{&K;?EJyaTg1S0qZ~%Yy_LY7ElPbgPouV6dU~-*RC3pb)Xi+K|N?t4~m;Q zEiJ((h@uJ%f+QFK{U9YdIff63w6A21e#mw;FL9qd9xnP4@)mQ5H0S!|0kpiwr?tLS9xMA=L@G!BKDw^n#P%G&lqLDP#}~f%)hbfLxFV z7K5c=Iamo+gSB8i*Z>N^X0R1(13SPjup5*x#AToYRDx>i-OJtm;2@|$R|n#t5nU5V zfL72BIzSf)Ko2+$PRL-`Ie&^&A4pQt07$9V+KFZK>zt``?0iBO9>>qPRn+Egh}*hh z`>D~d4=a7z1RPst^;Q4Z0}l04@fk0ZS@6^dg^YfK^^)12r~Im@%9G&tKn|2 zjd{!&?2X~1dtk;HY9fF5Bn?iFqV8+wg&gAA&NrYD!nDNw7eZM`mLn0W`@yk^Y@K@d-lEX z4O7Zatnkwac|&LPJHis*o>dSp?uKmMyu@xV2dwnoR=rJf?BspbJHzLtMe41gH@5ft z#hJfzl5f69x8FvC-{mqFsJCQQX7eU(>DFbte%~qz!W;T6+2x(eyR&;_->LkX(ZB9v z#@{gdHzj6NGv1>V*yQ90IkV9yEZ%pc%BNM`Q*S;|3(v3A({ia18VUeWPvA$=A@*!3WDyG<^|Y9D&qSxw$?J;SY*eJ1`xqyI?lRpDV+ z?0j`A&gc(MU-fcK{9~j4#FgnjL@9M^d=sUs6-PJjnDd+WGz)6!@mk*K+d-x|A~4xaxJ~P%5Ll- z|2}X490IlK%4^$Y9txe~MHeNK(=ONU4w8iDmRBoT+o{d_otVZ|`!esLkE*=UZ_J z*S|L!{Yg8)r;a8P^8A_6f9^w%zcBhQ2|Z@Kek*hBd1`E`Mt^F07sQYLmC=7KZfNRY z6{EpKy`K(;_=8!2C{b@^IK*~u{>)Ui>xig6jPJTxj=N%3$E`lXg1RBIMt$-r6j7;9 z`;aQ@VD(vVKchc)+1&UWqyJV;-nX~Kds>>>;`;Bx(|5I-0uq{iJ~Y1#s6WrvC0GRV z!4j|xtN^RP8n6yTfe)zVY75CiupR6KMW7gzf^rZ8RbUU;2M&Nkpcd4F25=ZOgBJC9 znZ8w+Us9c*8yp44KriqCwOlPAnG5p3Vz3k}2P?s9uokQb8$bcr417Q>S35}V0=q#8 zC<7Is5>$h|U_UqrYCs)`gGSH<5}*~dgAULI0?-4FgA>wcF+{i@x5=eg?F&yktBpS6 zt(F~7|Gm-wkQGpiov&`i8T~~!1LS8YUz)o5GFPFqw@3PaH2R)-f^dUyU>dUuuG*hBt( z-~c!TYSlLwWkCZtjIJ59*g@aNbdppj=mtl@G0+Q6g45s(=%C9ogt_XSdNh%6~WdKeD6o12mXu{5#HgI461brg&!g{nBjV*jHIGH)L9&3VaYQ zS6fIHg6&`@C<4Wx6qJJ)r~-SyK5zgW0=1wXG=RgP8MLS$$gXt=t4pdAbc3Vd80ZB) z2$!n`By&L?SPYhe%5G5xzWo_UT*QS(97*!?)0+A z%VLw6>pLMU-Ye_8to1VPWxbaTR*FBHlun8B@aifr2fa*sIpAf#mnkd7El6DGF5Oqf zGPnDdNXgHal0(N);-4$_vdqg;_plAty{gj7n7frbf-%I=*(9<12z7}2^Rm=R7sPv2 zrI#^x>rxRsNlZV&fXQy)Wz5Selet4~xVdrFBYF3Y97#V2H(_@efCdBDp-(TQm zu9taUF7|S%m&?6e>E&uK*Lu0$%MD%@c)8ijtzK^Pa)+0@yxi?&iJvHCURHQn>1DNV z|6ZSezn2HStnv5jyo`I<=H<-Wy{ zSs+T2StxWbelodMv535vf4uPk{g^t>jl0wcyO`U#>Rdm!v2*>@qc4-mqZiX&a>+K8 zZ#%e{HfMbf(qQ|t$YhrIXXJ-O>igmT<_}+uu6r(^%Ph^#$@xnt>l+)s#nRcrc}RruF9y3@};#0)GO5M)vMH-)Em?rUs_&|AtM5ql-&a4fgJZ{ggvm6*e6zog&*T~m^UngJ7dZ&EZ z?7iyk>K*Ds@^R?Latez!vYDxzNg zu;Yk)tNbzbW%a}e?!tuvhg2*T%pa3~;^}k$tP*$DF3Fg&z^mTQ2HnlZoR*F(RFPPiZ#;?sYt4O{%nAbIxVKtf$1UcQ8o>_zH Sv!c3`Yb~npP4a!RqW=XQ?d{G0 literal 0 HcmV?d00001 diff --git a/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Lexicon.py b/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Lexicon.py new file mode 100644 index 00000000..ca303c0d --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Lexicon.py @@ -0,0 +1,145 @@ +# +# Pyrex Scanner - Lexical Definitions +# +# Changing anything in this file will cause Lexicon.pickle +# to be rebuilt next time pyrexc is run. +# + +string_prefixes = "cCrR" + +def make_lexicon(): + from Pyrex.Plex import \ + Str, Any, AnyBut, AnyChar, Rep, Rep1, Opt, Bol, Eol, Eof, \ + TEXT, IGNORE, State, Lexicon + from Scanning import Method + + letter = Any("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_") + digit = Any("0123456789") + octdigit = Any("01234567") + hexdigit = Any("0123456789ABCDEFabcdef") + indentation = Bol + Rep(Any(" \t")) + + decimal = Rep1(digit) + dot = Str(".") + exponent = Any("Ee") + Opt(Any("+-")) + decimal + decimal_fract = (decimal + dot + Opt(decimal)) | (dot + decimal) + + name = letter + Rep(letter | digit) + intconst = decimal | (Str("0x") + Rep1(hexdigit)) + longconst = intconst + Str("L") + fltconst = (decimal_fract + Opt(exponent)) | (decimal + exponent) + imagconst = (intconst | fltconst) + Any("jJ") + +# sq_string = ( +# Str("'") + +# Rep(AnyBut("\\\n'") | (Str("\\") + AnyChar)) + +# Str("'") +# ) +# +# dq_string = ( +# Str('"') + +# Rep(AnyBut('\\\n"') | (Str("\\") + AnyChar)) + +# Str('"') +# ) +# +# non_sq = AnyBut("'") | (Str('\\') + AnyChar) +# tsq_string = ( +# Str("'''") +# + Rep(non_sq | (Str("'") + non_sq) | (Str("''") + non_sq)) +# + Str("'''") +# ) +# +# non_dq = AnyBut('"') | (Str('\\') + AnyChar) +# tdq_string = ( +# Str('"""') +# + Rep(non_dq | (Str('"') + non_dq) | (Str('""') + non_dq)) +# + Str('"""') +# ) +# +# stringlit = Opt(Any(string_prefixes)) + (sq_string | dq_string | tsq_string| tdq_string) + + beginstring = Opt(Any(string_prefixes)) + (Str("'") | Str('"') | Str("'''") | Str('"""')) + two_oct = octdigit + octdigit + three_oct = octdigit + octdigit + octdigit + two_hex = hexdigit + hexdigit + escapeseq = Str("\\") + (two_oct | three_oct | two_hex | AnyChar) + + bra = Any("([{") + ket = Any(")]}") + punct = Any(":,;+-*/|&<>=.%`~^?") + diphthong = Str("==", "<>", "!=", "<=", ">=", "<<", ">>", "**", + "+=", "-=", "*=", "/=", "%=", "**=", "<<=", ">>=", "&=", "^=", "|=") + spaces = Rep1(Any(" \t\f")) + comment = Str("#") + Rep(AnyBut("\n")) + escaped_newline = Str("\\\n") + lineterm = Eol + Opt(Str("\n")) + + return Lexicon([ + (name, 'IDENT'), + (intconst, 'INT'), + (longconst, 'LONG'), + (fltconst, 'FLOAT'), + (imagconst, 'IMAG'), + (punct | diphthong, TEXT), + + (bra, Method('open_bracket_action')), + (ket, Method('close_bracket_action')), + (lineterm, Method('newline_action')), + + #(stringlit, 'STRING'), + (beginstring, Method('begin_string_action')), + + (comment, IGNORE), + (spaces, IGNORE), + (escaped_newline, IGNORE), + + State('INDENT', [ + (Opt(spaces) + Opt(comment) + lineterm, IGNORE), + (indentation, Method('indentation_action')), + (Eof, Method('eof_action')) + ]), + + State('SQ_STRING', [ + (escapeseq, 'ESCAPE'), + (Rep1(AnyBut("'\"\n\\")), 'CHARS'), + (Str('"'), 'CHARS'), + (Str("\n"), Method('unclosed_string_action')), + (Str("'"), Method('end_string_action')), + (Eof, 'EOF') + ]), + + State('DQ_STRING', [ + (escapeseq, 'ESCAPE'), + (Rep1(AnyBut('"\n\\')), 'CHARS'), + (Str("'"), 'CHARS'), + (Str("\n"), Method('unclosed_string_action')), + (Str('"'), Method('end_string_action')), + (Eof, 'EOF') + ]), + + State('TSQ_STRING', [ + (escapeseq, 'ESCAPE'), + (Rep1(AnyBut("'\"\n\\")), 'CHARS'), + (Any("'\""), 'CHARS'), + (Str("\n"), 'NEWLINE'), + (Str("'''"), Method('end_string_action')), + (Eof, 'EOF') + ]), + + State('TDQ_STRING', [ + (escapeseq, 'ESCAPE'), + (Rep1(AnyBut('"\'\n\\')), 'CHARS'), + (Any("'\""), 'CHARS'), + (Str("\n"), 'NEWLINE'), + (Str('"""'), Method('end_string_action')), + (Eof, 'EOF') + ]), + + (Eof, Method('eof_action')) + ], + + # FIXME: Plex 1.9 needs different args here from Plex 1.1.4 + #debug_flags = scanner_debug_flags, + #debug_file = scanner_dump_file + ) + diff --git a/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Main.py b/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Main.py new file mode 100644 index 00000000..2769b771 --- /dev/null +++ b/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Main.py @@ -0,0 +1,564 @@ +# +# Pyrex Top Level +# + +import os, re, sys +if sys.version_info[:2] < (2, 3): + print >>sys.stderr, "Sorry, Pyrex requires Python 2.3 or later" + sys.exit(1) + +import os +from time import time +import Builtin +import Code +import Errors +import Parsing +import Version +from Errors import PyrexError, CompileError, error +from Scanning import PyrexScanner +from Symtab import BuiltinScope, DefinitionScope, ImplementationScope +from Pyrex.Utils import set, replace_suffix, modification_time, \ + file_newer_than, castrate_file, map_suffix +from Filenames import cplus_suffix, pxd_suffixes, pyx_suffixes, \ + package_init_files, pyx_to_c_suffix + +verbose = 0 +debug_timestamps = 0 + +module_name_pattern = re.compile( + r"[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)*$") + +class Context: + # This class encapsulates the context needed for compiling + # one or more Pyrex implementation files along with their + # associated and imported declaration files. It holds + # the root of the module import namespace and the list + # of directories to search for include files. + # + # modules {string : DefinitionScope} + # include_directories [string] + + def __init__(self, include_directories): + self.modules = {"__builtin__" : Builtin.builtin_scope} + self.include_directories = include_directories + + def find_module(self, module_name, + relative_to = None, pos = None, need_pxd = 1): + # Finds and returns the module scope corresponding to + # the given relative or absolute module name. If this + # is the first time the module has been requested, finds + # the corresponding .pxd file and process it. + # If relative_to is not None, it must be a module scope, + # and the module will first be searched for relative to + # that module, provided its name is not a dotted name. + debug_find_module = 0 + if debug_find_module: + print "Context.find_module: module_name =", module_name, \ + "relative_to =", relative_to, "pos =", pos, "need_pxd =", need_pxd + scope = None + pxd_pathname = None + if "." not in module_name and relative_to: + if debug_find_module: + print "...trying relative import" + scope = relative_to.lookup_submodule(module_name) + if not scope: + qualified_name = relative_to.qualify_name(module_name) + pxd_pathname = self.find_pxd_file(qualified_name, pos) + if pxd_pathname: + scope = relative_to.find_submodule(module_name) + if not scope: + if debug_find_module: + print "...trying absolute import" + scope = self + for name in module_name.split("."): + scope = scope.find_submodule(name) + if debug_find_module: + print "...scope =", scope + if not scope.pxd_file_loaded: + if debug_find_module: + print "...pxd not loaded" + scope.pxd_file_loaded = 1 + if not pxd_pathname: + if debug_find_module: + print "...looking for pxd file" + pxd_pathname = self.find_pxd_file(module_name, pos) + if debug_find_module: + print "......found ", pxd_pathname + if not pxd_pathname and need_pxd: + error(pos, "Cannot find .pxd file for module '%s'" % module_name) + if pxd_pathname: + try: + if debug_find_module: + print "Context.find_module: Parsing", pxd_pathname + pxd_tree = self.parse(pxd_pathname, scope, pxd = 1) + pxd_tree.analyse_declarations(scope) + except CompileError: + pass + return scope + + def find_pxd_file(self, qualified_name, pos): + # Search include path for the .pxd file corresponding to the + # given fully-qualified module name. + # Will find either a dotted filename or a file in a + # package directory. If a source file position is given, + # the directory containing the source file is searched first + # for a dotted filename, and its containing package root + # directory is searched first for a non-dotted filename. + return self.search_package_directories(qualified_name, pxd_suffixes, pos) + + def find_pyx_file(self, qualified_name, pos): + # Search include path for the .pyx file corresponding to the + # given fully-qualified module name, as for find_pxd_file(). + return self.search_package_directories(qualified_name, pyx_suffixes, pos) + + def search_package_directories(self, qualified_name, suffixes, pos): + dotted_filenames = [qualified_name + suffix for suffix in suffixes] + if pos: + here = os.path.dirname(pos[0]) + for dotted_filename in dotted_filenames: + path = os.path.join(here, dotted_filename) + if os.path.exists(path): + return path + dirs = self.include_directories + if pos: + here = self.find_root_package_dir(pos[0]) + dirs = [here] + dirs + names = qualified_name.split(".") + package_names = names[:-1] + module_name = names[-1] + filenames = [module_name + suffix for suffix in suffixes] + for root in dirs: + for dotted_filename in dotted_filenames: + path = os.path.join(root, dotted_filename) + if os.path.exists(path): + return path + dir = self.descend_to_package_dir(root, package_names) + if dir: + for filename in filenames: + path = os.path.join(dir, filename) + if os.path.exists(path): + return path + for init_filename in package_init_files: + path = os.path.join(dir, module_name, init_filename) + if os.path.exists(path): + return path + + def find_root_package_dir(self, file_path): + # Given the full pathname of a source file, find the directory + # containing the top-level package that it ultimately belongs to. + dir = os.path.dirname(file_path) + while 1: + if not self.is_package_dir(dir): + return dir + parent = os.path.dirname(dir) + if parent == dir: + return dir + dir = parent + + def descend_to_package_dir(self, root_dir, package_names): + # Starting from the given root directory, look for a nested + # succession of package directories. Returns the full pathname + # of the innermost one, or None. + dir = root_dir + for name in package_names: + dir = os.path.join(dir, name) + if self.is_package_dir(dir): + return dir + + def is_package_dir(self, dir_path): + # Return true if the given directory is a package directory. + for filename in package_init_files: + path = os.path.join(dir_path, filename) + if os.path.exists(path): + return 1 + + def find_include_file(self, filename, pos): + # Search list of include directories for filename. + # Reports an error and returns None if not found. + path = self.search_include_directories(filename, pos) + if not path: + error(pos, "'%s' not found" % filename) + return path + + def search_include_directories(self, filename, pos): + # Search the list of include directories for the given + # file name. If a source file position is given, first + # searches the directory containing that file. Returns + # None if not found, but does not report an error. + dirs = self.include_directories + if pos: + here_dir = os.path.dirname(pos[0]) + dirs = [here_dir] + dirs + for dir in dirs: + path = os.path.join(dir, filename) + if os.path.exists(path): + return path + return None + + def lookup_submodule(self, name): + # Look up a top-level module. Returns None if not found. + return self.modules.get(name, None) + + def find_submodule(self, name): + # Find a top-level module, creating a new one if needed. + scope = self.lookup_submodule(name) + if not scope: + scope = DefinitionScope(name, + parent_module = None, context = self) + self.modules[name] = scope + return scope + + def parse(self, source_filename, scope, pxd): + # Parse the given source file and return a parse tree. + f = open(source_filename, "rU") + s = PyrexScanner(f, source_filename, scope = scope, context = self) + try: + tree = Parsing.p_module(s, pxd) + finally: + f.close() + if Errors.num_errors > 0: + raise CompileError + return tree + + def extract_module_name(self, path): + # Find fully_qualified module name from the full pathname + # of a source file. + dir, filename = os.path.split(path) + module_name, _ = os.path.splitext(filename) + if "." not in module_name: + if module_name == "__init__": + dir, module_name = os.path.split(dir) + names = [module_name] + while self.is_package_dir(dir): + parent, package_name = os.path.split(dir) + if parent == dir: + break + names.insert(0, package_name) + dir = parent + module_name = ".".join(names) + if not module_name_pattern.match(module_name): + raise CompileError((path, 0, 0), + "'%s' is not a valid module name" % module_name) + return module_name + + def dep_file_out_of_date(self, source_path): + dep_path = replace_suffix(source_path, ".dep") + if not os.path.exists(dep_path): + return 1 + dep_time = modification_time(dep_path) + return file_newer_than(source_path, dep_time) + + def c_file_out_of_date(self, source_path): + if debug_timestamps: + print "Checking whether", source_path, "is out of date" + c_path = map_suffix(source_path, pyx_to_c_suffix, ".c") + if not os.path.exists(c_path): + if debug_timestamps: + print "...yes, c file doesn't exist" + return 1 + c_time = modification_time(c_path) + if file_newer_than(source_path, c_time): + if debug_timestamps: + print "...yes, newer than c file" + return 1 + pos = [source_path] + module_name = self.extract_module_name(source_path) + pxd_path = self.find_pxd_file(module_name, pos) + if pxd_path and file_newer_than(pxd_path, c_time): + if debug_timestamps: + print "...yes, pxd file newer than c file" + return 1 + dep_path = replace_suffix(source_path, ".dep") + if not os.path.exists(dep_path): + if debug_timestamps: + print "...yes, dep file does not exist" + return 1 + for kind, name in self.read_dependency_file(source_path): + if kind == "cimport": + dep_path = self.find_pxd_file(name, pos) + elif kind == "include": + dep_path = self.search_include_directories(name, pos) + else: + continue + if dep_path and file_newer_than(dep_path, c_time): + if debug_timestamps: + print "...yes,", dep_path, "newer than c file" + return 1 + if debug_timestamps: + print "...no" + + def find_cimported_module_names(self, source_path): + for kind, name in self.read_dependency_file(source_path): + if kind == "cimport": + yield name + + def read_dependency_file(self, source_path): + dep_path = replace_suffix(source_path, ".dep") + if os.path.exists(dep_path): + f = open(dep_path, "rU") + for line in f.readlines(): + chunks = line.strip().split(" ", 1) + if len(chunks) == 2: + yield chunks + f.close() + + def compile(self, source, options = None): + # Compile a Pyrex implementation file in this context + # and return a CompilationResult. + if not options: + options = default_options + result = CompilationResult() + cwd = os.getcwd() + source = os.path.join(cwd, source) + if options.use_listing_file: + result.listing_file = replace_suffix(source, ".lis") + Errors.open_listing_file(result.listing_file, + echo_to_stderr = options.errors_to_stderr) + else: + Errors.open_listing_file(None) + if options.output_file: + result.c_file = os.path.join(cwd, options.output_file) + else: + if options.cplus: + result.c_file = replace_suffix(source, cplus_suffix) + else: + result.c_file = map_suffix(source, pyx_to_c_suffix, ".c") + module_name = self.extract_module_name(source) + initial_pos = (source, 1, 0) + def_scope = self.find_module(module_name, pos = initial_pos, need_pxd = 0) + imp_scope = ImplementationScope(def_scope) + errors_occurred = False + try: + tree = self.parse(source, imp_scope, pxd = 0) + tree.process_implementation(imp_scope, options, result) + except CompileError: + errors_occurred = True + Errors.close_listing_file() + result.num_errors = Errors.num_errors + if result.num_errors > 0: + errors_occurred = True + if errors_occurred and result.c_file: + try: + st = os.stat(source) + castrate_file(result.c_file, st) + except EnvironmentError: + pass + result.c_file = None + if result.c_file and not options.c_only and c_compile: + result.object_file = c_compile(result.c_file, + verbose_flag = options.show_version, + cplus = options.cplus) + if not options.obj_only and c_link: + result.extension_file = c_link(result.object_file, + extra_objects = options.objects, + verbose_flag = options.show_version, + cplus = options.cplus) + return result + +#------------------------------------------------------------------------ +# +# Main Python entry points +# +#------------------------------------------------------------------------ + +class CompilationOptions: + """ + Options to the Pyrex compiler: + + show_version boolean Display version number + use_listing_file boolean Generate a .lis file + errors_to_stderr boolean Echo errors to stderr when using .lis + include_path [string] Directories to search for include files + output_file string Name of generated .c file + generate_pxi boolean Generate .pxi file for public declarations + recursive boolean Recursively find and compile dependencies + timestamps boolean Only compile changed source files. If None, + defaults to true when recursive is true. + verbose boolean Always print source names being compiled + quiet boolean Don't print source names in recursive mode + + Following options are experimental and only used on MacOSX: + + c_only boolean Stop after generating C file (default) + obj_only boolean Stop after compiling to .o file + objects [string] Extra .o files to link with + cplus boolean Compile as c++ code + """ + + def __init__(self, defaults = None, c_compile = 0, c_link = 0, **kw): + self.include_path = [] + self.objects = [] + if defaults: + if isinstance(defaults, CompilationOptions): + defaults = defaults.__dict__ + else: + defaults = default_options + self.__dict__.update(defaults) + self.__dict__.update(kw) + if c_compile: + self.c_only = 0 + if c_link: + self.obj_only = 0 + + +class CompilationResult: + """ + Results from the Pyrex compiler: + + c_file string or None The generated C source file + h_file string or None The generated C header file + i_file string or None The generated .pxi file + api_file string or None The generated C API .h file + listing_file string or None File of error messages + object_file string or None Result of compiling the C file + extension_file string or None Result of linking the object file + num_errors integer Number of compilation errors + """ + + def __init__(self): + self.c_file = None + self.h_file = None + self.i_file = None + self.api_file = None + self.listing_file = None + self.object_file = None + self.extension_file = None + + +class CompilationResultSet(dict): + """ + Results from compiling multiple Pyrex source files. A mapping + from source file paths to CompilationResult instances. Also + has the following attributes: + + num_errors integer Total number of compilation errors + """ + + num_errors = 0 + + def add(self, source, result): + self[source] = result + self.num_errors += result.num_errors + + +def compile_single(source, options): + """ + compile_single(source, options) + + Compile the given Pyrex implementation file and return a CompilationResult. + Always compiles a single file; does not perform timestamp checking or + recursion. + """ + context = Context(options.include_path) + return context.compile(source, options) + +def compile_multiple(sources, options): + """ + compile_multiple(sources, options) + + Compiles the given sequence of Pyrex implementation files and returns + a CompilationResultSet. Performs timestamp checking and/or recursion + if these are specified in the options. + """ + sources = [os.path.abspath(source) for source in sources] + processed = set() + results = CompilationResultSet() + context = Context(options.include_path) + recursive = options.recursive + timestamps = options.timestamps + if timestamps is None: + timestamps = recursive + verbose = options.verbose or ((recursive or timestamps) and not options.quiet) + for source in sources: + if source not in processed: + if not timestamps or context.c_file_out_of_date(source): + if verbose: + print >>sys.stderr, "Compiling", source + result = context.compile(source, options) + results.add(source, result) + processed.add(source) + if recursive: + for module_name in context.find_cimported_module_names(source): + path = context.find_pyx_file(module_name, [source]) + if path: + sources.append(path) + else: + print >>sys.stderr, \ + "Cannot find .pyx file for cimported module '%s'" % module_name + return results + +def compile(source, options = None, c_compile = 0, c_link = 0, **kwds): + """ + compile(source [, options], [,