├── .gitignore ├── .travis.yml ├── AUTHORS ├── LICENSE ├── MANIFEST.in ├── NEWS ├── README.rst ├── TODO.rst ├── bin ├── __init__.py ├── _preamble.py ├── pythonect └── test │ ├── foobar.py │ ├── helloworld.dia │ ├── helloworld.p2y │ └── test_interpreter.py ├── distribute_setup.py ├── doc ├── Makefile ├── _static │ ├── 123_sum_reduce.png │ ├── 123_to_print.png │ ├── dia_step_0.jpeg │ ├── dia_step_0.png │ ├── dia_step_1.png │ ├── dia_step_2.png │ ├── dia_step_3.png │ ├── dia_step_4.png │ ├── dia_step_5.png │ ├── dia_step_6.png │ ├── dia_step_7.png │ ├── dia_step_8.png │ ├── helloworld_1_2.png │ ├── multiple_x_values.png │ └── single_x_value.png ├── _templates │ └── page.html ├── api.rst ├── changelog.rst ├── conf.py ├── foreword.rst ├── index.rst ├── installation.rst ├── license.rst ├── make.bat ├── requirements.txt └── tutorial │ ├── controlflow.rst │ ├── flow.rst │ ├── helloworld.rst │ ├── index.rst │ ├── interpreter.rst │ ├── power.rst │ └── vars.rst ├── examples ├── hello.dia ├── hello.p2y ├── palindrome.dia └── repl.dia ├── pythonect ├── __init__.py ├── _version.py ├── internal │ ├── __init__.py │ ├── _graph.py │ ├── _ordereddict.py │ ├── eval.py │ ├── lang.py │ └── parsers │ │ ├── __init__.py │ │ ├── dia.py │ │ ├── p2y.py │ │ ├── test │ │ ├── __init__.py │ │ ├── dia_examples │ │ │ ├── even_expr_atom_op_expr.dia │ │ │ ├── expr_atom.dia │ │ │ ├── odd_expr_atom_op_expr.dia │ │ │ ├── odd_expr_atom_op_expr_gzipped.dia │ │ │ ├── program_empty.dia │ │ │ └── program_expr_list.dia │ │ ├── test_dia.py │ │ ├── test_p2y.py │ │ ├── test_vdx07.py │ │ ├── test_vdx10.py │ │ ├── vdx07_examples │ │ │ ├── even_expr_atom_op_expr.vdx │ │ │ ├── expr_atom.vdx │ │ │ ├── odd_expr_atom_op_expr.vdx │ │ │ ├── program_empty.vdx │ │ │ └── program_expr_list.vdx │ │ └── vdx10_examples │ │ │ ├── even_expr_atom_op_expr.vdx │ │ │ ├── expr_atom.vdx │ │ │ ├── odd_expr_atom_op_expr.vdx │ │ │ ├── program_empty.vdx │ │ │ └── program_expr_list.vdx │ │ └── vdx.py └── test │ ├── __init__.py │ ├── eval_tst_gen.py │ ├── test_eval.py │ └── test_xmlrpc_app.py ├── setup.cfg └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.pyc 3 | /dist/ 4 | /build/ 5 | *.egg-info 6 | .coverage 7 | .noseids 8 | .DS_Store 9 | doc/_build 10 | bin/pythonectc 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - 2.7 4 | - 2.6 5 | install: 6 | - pip install pep8 7 | - pip install nose 8 | - pip install coverage 9 | - python setup.py install 10 | before_script: 11 | # This is needed for Python multiprocessing. 12 | # https://github.com/travis-ci/travis-cookbooks/issues/155 13 | - sudo rm -rf /dev/shm 14 | - sudo ln -s /run/shm /dev/shm 15 | script: 16 | - python setup.py nosetests 17 | notifications: 18 | email: 19 | on_success: change 20 | on_failure: change 21 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Pythonect is written and maintained by Itzik Kotler and various contributors: 2 | 3 | Development Lead 4 | ```````````````` 5 | 6 | - Itzik Kotler 7 | 8 | 9 | Patches and Suggestions 10 | ``````````````````````` 11 | 12 | - Guy Adini 13 | 14 | Portions derived from other open source works are clearly marked. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2013, Itzik Kotler 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the author nor the names of its contributors may 15 | be used to endorse or promote products derived from this software without 16 | specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 22 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE 2 | include NEWS 3 | include README.rst 4 | include MANIFEST.in 5 | include setup.cfg 6 | include setup.py 7 | include distribute_setup.py 8 | 9 | recursive-include doc * 10 | recursive-include examples * 11 | prune doc/_build 12 | 13 | global-include *.rst 14 | global-exclude *.DS_Store* 15 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | Pythonect Changelog 2 | =================== 3 | 4 | Here you can see the full list of changes between each Pythonect release. 5 | 6 | Ticket numbers in this file can be looked up by visiting 7 | http://github.com/ikotler/pythonect/issues/ 8 | 9 | 10 | What's New In Pythonect 0.6? 11 | ---------------------------- 12 | 13 | *Release date: 22-Jul-2013* 14 | 15 | Core and builtins 16 | ^^^^^^^^^^^^^^^^^ 17 | 18 | - Rewrite engine to be both a visual programming language and a text-based scripting language. 19 | 20 | - Add support for GNOME Dia (*.DIA) as an Input File Format for Visual Programming 21 | 22 | - Add support for Microsoft Visio (*.VDX) as an Input File Format for Visual Programming 23 | 24 | - Rewrite Pythonect's Text-based scripting parser (*.P2Y) to use Python's tokenize instead of PLY 25 | 26 | - Modify Pythonect's parse() to return a directed graph (i.e. NetworkX.DiGraph) 27 | 28 | - Add auto-generated SphinX doc (i.e. doc/) 29 | 30 | - Modify NEWS reStructuredText Format to better suit the auto-generated doc 31 | 32 | Build 33 | ^^^^^ 34 | 35 | - Modify setup.cfg to stop running tests after the first error or failure 36 | 37 | Miscellaneous 38 | ^^^^^^^^^^^^^ 39 | 40 | - Add examples/ directory with a few example programs 41 | 42 | 43 | What's New In Pythonect 0.5? 44 | ---------------------------- 45 | 46 | *Release date: 24-Apr-2013* 47 | 48 | Core and builtins 49 | ^^^^^^^^^^^^^^^^^ 50 | 51 | - Issue #71: Unable to run Pythonect in Script Mode 52 | 53 | - Issue #72: Can't Load Local Modules with '-m' 54 | 55 | - Issue #58: Install argparse if Python 2.6 56 | 57 | - Feature #70: Pythonect now supports Max Threads Limit (i.e. '--mt' command-line argument) 58 | 59 | - Feature #73: '_' is no longer implicit in the 1st call to eval() 60 | 61 | 62 | What's New In Pythonect 0.4.2? 63 | ------------------------------ 64 | 65 | *Release date: 16-Feb-2013* 66 | 67 | Core and builtins 68 | ^^^^^^^^^^^^^^^^^ 69 | 70 | - Feature #61: Interpreter supports command line '-c', '-i' and '-m' 71 | 72 | - Enhancement #68: Improved Interpreter Banner 73 | 74 | - Enhancement #67: args globals_ and locals_ of eval() are now optional 75 | 76 | - Feature #66: Within Pythonect Program: eval() now takes Pythonect code and __eval__() takes Python 77 | 78 | - Refactor __run() [Guy Adini] 79 | 80 | - Feature #65: Pythonect now supports PyPy 81 | 82 | - Feature #55: Pythonect now supports Python 2.6 83 | 84 | - Issue #48: 'print "B" in "ABC"' and 'print 2 is 2' throws Exception 85 | 86 | - Issue #60: "copyright", "license", and "credits" are not of Pythonect 87 | 88 | - Issue #62: Parameterless functions are now handled properly 89 | 90 | - Issue #63: "quit" and "exit" raises ValueError: I/O operation on closed file 91 | 92 | - Issue #64: Interpreter command line option '--version'/'-V' output wrong banner 93 | 94 | - Issue #69: print/print_ can not be overridden by locals or globals value 95 | 96 | Build 97 | ^^^^^ 98 | 99 | - Switched to nosetests (+ coverage) 100 | 101 | - Issue #49: zip_safe is not False by default 102 | 103 | 104 | What's New In Pythonect 0.4.1? 105 | ------------------------------ 106 | 107 | *Release date: 03-Sep-2012* 108 | 109 | Core and builtins 110 | ^^^^^^^^^^^^^^^^^ 111 | 112 | - PEP8 Fixes 113 | 114 | - PEP 3110 Fixes 115 | 116 | - Added Travis CI Support 117 | 118 | - Issue #38: No docstrings for eval(), parse(), and Pythonect module 119 | 120 | - Issue #39: eval_test_gen.py fails due to incorrect import 121 | 122 | - Issue #41: Pythonect split() renamed to parse() to better fit it's purpose 123 | 124 | - Issue #42: Pythonect fails on Python implementations that do not include the multiprocessing module 125 | 126 | - Enhancement #45: Dict can now be used as a return value, only literal dict will be treated as switch 127 | 128 | - Issue #47: Pythonect parse() is not included in the testsuite 129 | 130 | Build 131 | ^^^^^ 132 | 133 | - Issue #43: Pythonect unittest runner is not cross-platform 134 | 135 | - Issue #44: Warnings during installation due to MANIFEST.in 136 | 137 | 138 | What's New In Pythonect 0.4? 139 | ---------------------------- 140 | 141 | *Release date: 09-Aug-2012* 142 | 143 | Core and builtins 144 | ^^^^^^^^^^^^^^^^^ 145 | 146 | - Issue #31: Synchronous/Asynchronous is not enforced when execution return value is callable and iterable 147 | 148 | - Issue #32: Script can't accept command line args 149 | 150 | - Issue #34: Script file can't contain Backslash 151 | 152 | - Feature #34: Interpreter (in Interactive mode) now logs commands for further use 153 | 154 | - Feature #35: Pythonect module now exports split() function to parse Pythonect code 155 | 156 | - Feature #36: Backticks can be used to evaluate a Pythonect expression 157 | 158 | Miscellaneous 159 | ^^^^^^^^^^^^^ 160 | 161 | - Removed eXecute bit from pythonect/__init__.py and pythonect/internal/__init__.py 162 | 163 | - Reorganized Pythonect module structure (pythonect.eval.eval is now pythonect.eval) 164 | 165 | 166 | What's New In Pythonect 0.3.1? 167 | ------------------------------ 168 | 169 | *Release date: 14-Jul-2012* 170 | 171 | Core and builtins 172 | ^^^^^^^^^^^^^^^^^ 173 | 174 | - Issue #25: Pythonect package namespsace (when importing from Python) is polluted 175 | 176 | - Issue #26: Odd Single quote char breaks double quote String (and vice versa) 177 | 178 | - Issue #27: Multiprocessing is not working with multi-threading 179 | 180 | - Issue #28: Autoload always throws NameError regardless to the actual Exception type 181 | 182 | - Issue #29: Preprocessor breaks on a List with Function Call that contains String 183 | 184 | - Issue #30: Preprocessor incorrectly process non-String literals in List 185 | 186 | 187 | What's New in Pythonect 0.3? 188 | ---------------------------- 189 | 190 | *Release date: 20-Jun-2012* 191 | 192 | Core and builtins 193 | ^^^^^^^^^^^^^^^^^ 194 | 195 | - Feature #13: Improved print function 196 | 197 | - Feature #15: Implemented Stateful Interpreter 198 | 199 | - Feature #17: Remote procedure URL can be an expression 200 | 201 | - Feature #18: Implemented Multiprocessing 202 | 203 | - Feature #20: Backslash can be used to join two or more physical lines into a logical line 204 | 205 | - Feature #22: Implemented None as pseudo remote protocol / URL 206 | 207 | - Issue #14: Print does not act as a pass-through statement 208 | 209 | - Issue #16: TypeError Exceptions are not been displayed 210 | 211 | - Issue #19: Autloading is not working in a statement 212 | 213 | - Issue #21: Preprocessor breaks on a List with a String that contains comma 214 | 215 | Build 216 | ^^^^^ 217 | 218 | - Issue #12: No newline at the end of _version.py (PEP8) 219 | 220 | 221 | What's New in Pythonect 0.2.1? 222 | ------------------------------ 223 | 224 | *Release date: 27-May-2012* 225 | 226 | Core and builtins 227 | ^^^^^^^^^^^^^^^^^ 228 | 229 | - Issue #9: Autoload won't load modules from current working directory 230 | 231 | - Issue #11: Autoload parses name incorrectly if in a list or tuple 232 | 233 | 234 | What's New in Pythonect 0.2? 235 | ---------------------------- 236 | 237 | *Release date: 30-Apr-2012* 238 | 239 | Core and builtins 240 | ^^^^^^^^^^^^^^^^^ 241 | 242 | - Feature #8: Implemented Autoloading. 243 | 244 | - Feature #7: Python built-in dictionary can be used as a switch statement. 245 | 246 | - Issue #6: Interpreter prints Strings without quotes 247 | 248 | - Issue #5: Interpreter lags when pressing Enter key multiple times 249 | 250 | Build 251 | ^^^^^ 252 | 253 | - Issue #4: Pythonect reports incorrect version if installed via pip/sdist. 254 | 255 | 256 | What's New in Pythonect 0.1.1? 257 | ------------------------------ 258 | 259 | *Release date: 18-Apr-2012* 260 | 261 | Core and builtins 262 | ^^^^^^^^^^^^^^^^^ 263 | 264 | - Issue #3: Check that the program return value is not None before printing it 265 | 266 | Build 267 | ^^^^^ 268 | 269 | - Issue #1: Removed import from __init__ to avoid PLY imports via setup.py. 270 | 271 | Miscellaneous 272 | ^^^^^^^^^^^^^ 273 | 274 | - Add NEWS file 275 | 276 | 277 | What's New in Pythonect 0.1? 278 | ---------------------------- 279 | 280 | *Release date: 01-Apr-2012* 281 | 282 | Everything :-) 283 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Pythonect 2 | ========= 3 | 4 | .. image:: https://badge.fury.io/py/Pythonect.png 5 | :target: http://badge.fury.io/py/Pythonect 6 | :alt: Latest version 7 | 8 | .. image:: https://travis-ci.org/ikotler/pythonect.png?branch=master 9 | :target: https://travis-ci.org/ikotler/pythonect 10 | :alt: Travis-CI 11 | 12 | .. image:: https://pypip.in/d/Pythonect/badge.png 13 | :target: https://crate.io/packages/Pythonect/ 14 | :alt: Number of PyPI downloads 15 | 16 | Homepage: `http://www.pythonect.org/ `_ 17 | 18 | `Pythonect` is a new, experimental, general-purpose dataflow programming 19 | language based on Python. It provides both a visual programming language and a 20 | text-based scripting language. The text-based scripting language aims to 21 | combine the quick and intuitive feel of shell scripting, with the power of 22 | Python. The visual programming language is based on the idea of a diagram with 23 | “boxes and arrows”. Crazy? Most definitely. And yet, strangely enough, it 24 | works! 25 | 26 | 27 | Hello, world 28 | ------------ 29 | 30 | Here is the canonical "Hello, world" example program in Pythonect:: 31 | 32 | "Hello, world" -> print 33 | 34 | Or: 35 | 36 | .. image:: http://pythonect.org/HelloWorld2.png 37 | 38 | 39 | Installation 40 | ------------ 41 | 42 | There are a few ways to install Pythonect. 43 | 44 | 1. You can install directly from PyPI_ using `setuptools/easy_install `_ or pip_:: 45 | 46 | pip install Pythonect 47 | 48 | or:: 49 | 50 | easy_install Pythonect 51 | 52 | 2. You can clone the git repository somewhere in your system:: 53 | 54 | git clone git://github.com/ikotler/pythonect.git 55 | 56 | Then you should do following steps:: 57 | 58 | cd pythonect 59 | python setup.py install 60 | 61 | Alternatively, if you use pip_, you can install directly from the git repository:: 62 | 63 | pip install \ 64 | git+git://github.com/ikotler/pythonect.git@master#egg=pythonect \ 65 | -r https://github.com/ikotler/pythonect/raw/master/doc/requirements.txt 66 | 67 | For any of the above methods, if you want to do a system-wide installation, 68 | you will have to do this with *root* permissions (e.g. using ``su`` or 69 | ``sudo``). 70 | 71 | .. _PyPI: http://pypi.python.org/pypi/Pythonect/ 72 | .. _pip: http://www.pip-installer.org/ 73 | 74 | 75 | Examples 76 | -------- 77 | 78 | See more examples at the `Pythonect Tutorial `_. 79 | 80 | 81 | Documentation 82 | ------------- 83 | 84 | Full documentation is available at http://docs.pythonect.org/. 85 | 86 | 87 | Please Help Out 88 | --------------- 89 | 90 | This project is still under development. Feedback and suggestions are very 91 | welcome and I encourage you to use the `Issues list 92 | `_ on GitHub to provide that 93 | feedback. 94 | 95 | Feel free to fork this repo and to commit your additions. For a list of all 96 | contributors, please see the `AUTHORS 97 | `_ file. 98 | 99 | Any questions, tips, or general discussion can be posted to our Google group: 100 | `http://groups.google.com/group/pythonect `_ 102 | 103 | 104 | Licensing 105 | --------- 106 | 107 | Pythonect is published under the liberal terms of the BSD 3-Clause License, 108 | see the `LICENSE `_ 109 | file. Although the BSD License does not require you to share any modifications 110 | you make to the source code, you are very much encouraged and invited to 111 | contribute back your modifications to the community, preferably in a GitHub 112 | fork, of course. 113 | 114 | 115 | Showing Your Appreciation 116 | ========================= 117 | 118 | The best way to show your appreciation for Pythonect remains contributing to 119 | the community. If you'd like to show your appreciation in another way, 120 | consider Flattr'ing or Gittip'ing me: 121 | 122 | |FlattrThis|_ |GittipThis|_ 123 | 124 | .. |GittipThis| image:: https://www.gittip.com/assets/10.0.6/logo.png 125 | .. _GittipThis: https://www.gittip.com/ikotler 126 | 127 | .. |FlattrThis| image:: http://api.flattr.com/button/button-static-50x60.png 128 | .. _FlattrThis: https://flattr.com/thing/1713050/ikotlerpythonect-on-GitHub 129 | -------------------------------------------------------------------------------- /TODO.rst: -------------------------------------------------------------------------------- 1 | * Add "Embedding Pythonect" Section to Documentation 2 | * Add "Writing Domain-Specific Languages with Pythonect" Section to Documentation 3 | * Add FAQ Page to Documentation 4 | * Add Small Code Example for each New Change in the ChangeLog 5 | * Modify Pythonect to use ``logging.getLogger()`` instead of ``logging.debug()`` and etc. 6 | * Add REST Support for Remote Call Power Feature 7 | * Add SOAP Support for Remote Call Power Feature 8 | * Improve Visual Programming by Recognizing Flowchart Symbols (See Fig. 1 at http://cnx.org/content/m27193/latest/) 9 | * Improve Visual Programming by Parsing Text on Lines as Control Flow Conditions (See Fig. 3 at http://cnx.org/content/m27193/latest/) 10 | * Add Support for GraphML (via `NetworkX `_) + Find Editor + Document 11 | * Add Support for YAML (via `NetworkX `_) + Find Editor + Document 12 | * Add Support for JSON (via `NetworkX `_) + Find Editor + Document 13 | * Add Support for GEXF (via `NetworkX `_) + Find Editor + Document 14 | * Add Support for GML (via `NetworkX `_) + Find Editor + Document 15 | * Forward ``False`` if Next Operation Explicitly Reference It 16 | * Add More Code Examples 17 | * Add More Unit Tests 18 | * Add Support for Python3k 19 | * Add Support for `IronPython `_ 20 | * Add Support for `Stackless Python `_ 21 | * Reduce Multiple ``locals_`` and ``globals_`` to Single Copy 22 | * Add Support for GPU? 23 | * Add Support for Grouping (e.g. ``[x -> y]@foobar`` will equal ``[x@foobar -> y@foobar]``) 24 | * `Python Plugin for Dia `_ to run Diagram within `Dia `_ 25 | * Plugin for Eclipse to run Workflow within `Eclipse `_ -------------------------------------------------------------------------------- /bin/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012-2013, Itzik Kotler 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # 14 | # * Neither the name of the author nor the names of its contributors may 15 | # be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 22 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /bin/_preamble.py: -------------------------------------------------------------------------------- 1 | # This makes sure that users don't have to set up their environment 2 | # specially in order to run the interpreter. 3 | 4 | # This helper is not intended to be packaged or installed, it is only 5 | # a developer convenience. By the time Pythonect is actually installed 6 | # somewhere, the environment should already be set up properly without 7 | # the help of this tool. 8 | 9 | 10 | import sys 11 | import os 12 | 13 | 14 | path = os.path.abspath(sys.argv[0]) 15 | 16 | 17 | while os.path.dirname(path) != path: 18 | 19 | if os.path.exists(os.path.join(path, 'pythonect', '__init__.py')): 20 | 21 | sys.path.insert(0, path) 22 | 23 | break 24 | 25 | path = os.path.dirname(path) 26 | -------------------------------------------------------------------------------- /bin/pythonect: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Copyright (c) 2012-2013, Itzik Kotler 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # 11 | # * Redistributions in binary form must reproduce the above copyright 12 | # notice, this list of conditions and the following disclaimer in the 13 | # documentation and/or other materials provided with the distribution. 14 | # 15 | # * Neither the name of the author nor the names of its contributors may 16 | # be used to endorse or promote products derived from this software without 17 | # specific prior written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 23 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | import sys 31 | 32 | try: 33 | 34 | import readline 35 | 36 | except ImportError: 37 | 38 | # Windows ... 39 | 40 | pass 41 | 42 | import code 43 | import codeop 44 | import argparse 45 | import logging 46 | import os 47 | import atexit 48 | import runpy 49 | import multiprocessing 50 | import pprint 51 | 52 | 53 | try: 54 | 55 | import _preamble 56 | 57 | except ImportError: 58 | 59 | sys.exc_clear() 60 | 61 | 62 | import pythonect 63 | import pythonect.internal.parsers 64 | 65 | 66 | # Pythonect Console 67 | 68 | class PythonectCompile(codeop.Compile): 69 | 70 | def __init__(self): 71 | 72 | codeop.Compile.__init__(self) 73 | 74 | def __call__(self, source, filename, symbol): 75 | 76 | if source[-1] == '\\': 77 | return None 78 | 79 | return source.replace('\\\n', '') 80 | 81 | 82 | class PythonectCommandCompiler(codeop.CommandCompiler): 83 | 84 | def __init__(self): 85 | 86 | codeop.CommandCompiler.__init__(self) 87 | 88 | self.compiler = PythonectCompile() 89 | 90 | 91 | class PythonectInteractiveConsole(code.InteractiveConsole): 92 | 93 | def __init__(self, locals=None, histfile=os.path.expanduser("~/.pythonect_history")): 94 | 95 | code.InteractiveConsole.__init__(self, locals) 96 | 97 | self.compile = PythonectCommandCompiler() 98 | 99 | self.init_history(histfile) 100 | 101 | def init_history(self, histfile): 102 | 103 | try: 104 | 105 | readline.read_history_file(histfile) 106 | 107 | except Exception: 108 | 109 | pass 110 | 111 | atexit.register(self.save_history, histfile) 112 | 113 | def save_history(self, histfile): 114 | 115 | try: 116 | 117 | readline.write_history_file(histfile) 118 | 119 | # i.e. NameError: name 'readline' is not defined ... 120 | 121 | except NameError: 122 | 123 | pass 124 | 125 | # This is a cut & paste from /usr/lib/python2.7/code.py 126 | # Except we're not calling `exec` statement 127 | 128 | def runcode(self, code_): 129 | 130 | try: 131 | 132 | return_value = pythonect.eval(code_, {}, self.locals) 133 | 134 | # Meaningful Return Value? 135 | 136 | if return_value is not None: 137 | 138 | # String? 139 | 140 | if isinstance(return_value, basestring): 141 | 142 | # Enclose in single quotes 143 | 144 | return_value = "'" + return_value + "'" 145 | 146 | self.write(str(return_value) + '\n') 147 | 148 | # Keep return_value for further reference or reset to None? 149 | 150 | if return_value is False or return_value is True: 151 | 152 | # Reset locals to None 153 | 154 | self.locals['_'] = None 155 | 156 | except SystemExit: 157 | 158 | raise 159 | 160 | except: 161 | 162 | self.showtraceback() 163 | 164 | else: 165 | 166 | if code.softspace(sys.stdout, 0): 167 | 168 | print 169 | 170 | 171 | def main(argv=sys.argv): 172 | 173 | locals_ = {} 174 | globals_ = {} 175 | 176 | verbose_levels = [logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG] 177 | 178 | # Pythonect's Banner (for -V, --version purposes) 179 | 180 | banner = "Pythonect %s" % pythonect.__version__ 181 | 182 | # Parse command-line arguments 183 | 184 | parser = argparse.ArgumentParser(prog='pythonect') 185 | 186 | parser.add_argument('script', metavar='file', nargs='?', type=argparse.FileType('rt'), help='program read from script file') 187 | parser.add_argument('arg', metavar='arg', nargs='*', help='arguments passed to program in sys.argv[1:]') 188 | parser.add_argument('--verbose', '-v', action='count', default=0) 189 | parser.add_argument('--version', '-V', action='version', version=banner) 190 | parser.add_argument('--interactive', '-i', action='store_true', default=False, help='inspect interactively after running script') 191 | parser.add_argument('--command', '-c', metavar='cmd', nargs='*', help='program passed in as string') 192 | parser.add_argument('--module', '-m', metavar='mod', action='store', help='run library module as a script') 193 | parser.add_argument('--max-threads-per-flow', '-mt', metavar='N', default=multiprocessing.cpu_count() + 1, type=int, action='store', help='max threads per flow') 194 | 195 | args = parser.parse_args(args=argv[1:]) 196 | 197 | # Setup logging level 198 | 199 | logging.basicConfig(level=verbose_levels[args.verbose % 4], format="%(levelname)s:%(message)s") 200 | 201 | logging.info('Interpreter Command line arguments:\n%s' % pprint.pformat(vars(args))) 202 | 203 | # Add current working directory to sys.path 204 | 205 | sys.path.insert(0, os.getcwd()) 206 | 207 | logging.info('Interpreter Initial sys.argv = %s' % sys.argv) 208 | 209 | # Argument Passing 210 | 211 | if args.arg: 212 | 213 | sys.argv = [sys.argv[0]] + args.arg 214 | 215 | logging.info('Interpreter Final sys.argv = %s' % sys.argv) 216 | 217 | # Module as script mode (i.e. python -m 'os') 218 | 219 | if args.module: 220 | 221 | logging.info('*** Entering Module Mode ***') 222 | 223 | locals_ = runpy.run_module(args.module) 224 | 225 | # Max threads per pipe 226 | 227 | locals_.update(__MAX_THREADS_PER_FLOW__=args.max_threads_per_flow) 228 | 229 | # Command line mode (i.e. ./pythonect -c "'Hello world' -> print") 230 | 231 | if args.command: 232 | 233 | logging.info('*** Entering Command Mode ***') 234 | 235 | pythonect.eval(args.command[0], globals_, locals_) 236 | 237 | # Script-mode (i.e. ./pythonect script or #!/usr/bin/env pythonect) 238 | 239 | if args.script: 240 | 241 | logging.info('*** Entering Script Mode ***') 242 | 243 | content = args.script.read() 244 | 245 | scriptname, scriptextension = os.path.splitext(args.script.name) 246 | 247 | logging.info('Script Filename = %s' % scriptname) 248 | 249 | if scriptextension: 250 | 251 | logging.info('Script Filename Extension = %s' % scriptextension) 252 | 253 | parsers = pythonect.internal.parsers.get_parsers(os.path.abspath(os.path.join(os.path.dirname(pythonect.internal.parsers.__file__), '..', 'parsers'))) 254 | 255 | logging.debug('Compiling a List of Parsers:\n%s' % pprint.pformat(parsers)) 256 | 257 | content = parsers[scriptextension[1:]].parse(content) 258 | 259 | logging.info('Using Parser %s to Parse `%s`' % (parsers[scriptextension[1:]], args.script.name)) 260 | 261 | if content is None: 262 | 263 | raise Exception("Unable to parse %s with %s" % (scriptname, parsers[scriptextension[1:]].__repr__())) 264 | 265 | else: 266 | 267 | logging.warning("Couldn't find %s Filename Extension! Guesstimating Parser..." % args.script.name) 268 | 269 | pythonect.eval(content, globals_, locals_) 270 | 271 | args.script.close() 272 | 273 | if not args.module and not args.command and not args.script: 274 | 275 | args.interactive = True 276 | 277 | else: 278 | 279 | banner = '' 280 | 281 | # Interactive-mode (i.e. ./pythonect) 282 | 283 | if args.interactive: 284 | 285 | logging.info('*** Entering Interactive Mode! ***\n\n') 286 | 287 | # Pythonect's Banner (for -V, --version purposes) 288 | 289 | banner = """Python %s\n[Pythonect %s] on %s\nType "help", "copyright", "credits" or "license" for more information.""" % (sys.version.split('\n')[0], pythonect.__version__, sys.platform) 290 | 291 | PythonectInteractiveConsole(locals_).interact(banner) 292 | 293 | return 0 294 | 295 | 296 | # Entry Point 297 | 298 | if __name__ == "__main__": 299 | 300 | try: 301 | 302 | sys.exit(main()) 303 | 304 | except ValueError as e: 305 | 306 | pass 307 | -------------------------------------------------------------------------------- /bin/test/foobar.py: -------------------------------------------------------------------------------- 1 | # This is a dummy Python code that will be used as a module for Pythonect Interpreter testing purposes 2 | 3 | if __name__ == "__main__": 4 | 5 | print "Goodbye, world" 6 | 7 | else: 8 | 9 | print "Hello, world" 10 | -------------------------------------------------------------------------------- /bin/test/helloworld.dia: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | #A4# 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | #"Hello, world"# 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | #print# 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /bin/test/helloworld.p2y: -------------------------------------------------------------------------------- 1 | 'Hello, world' -> print 2 | -------------------------------------------------------------------------------- /bin/test/test_interpreter.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012-2013, Itzik Kotler 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # 14 | # * Neither the name of the author nor the names of its contributors may 15 | # be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 22 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | try: 30 | 31 | # If < Python 2.7, use the backported unittest2 package 32 | 33 | import unittest2 as unittest 34 | 35 | except ImportError: 36 | 37 | # Probably > Python 2.7, use unittest 38 | 39 | import unittest 40 | 41 | 42 | import sys 43 | import re 44 | import copy 45 | import imp 46 | import shlex 47 | import os 48 | 49 | 50 | # Consts 51 | 52 | BASE_DIR = os.path.join(os.path.dirname(__file__), os.pardir) 53 | TEST_DIR = os.path.dirname(os.path.abspath(__file__)) 54 | 55 | 56 | # Local imports 57 | 58 | pythonect_interpreter = imp.load_source('pythonect_interpreter', BASE_DIR + os.sep + 'pythonect') 59 | 60 | 61 | def _not_buffered(): 62 | 63 | return hasattr(sys.stdout, "getvalue") is False 64 | 65 | 66 | class TestPythonectInterpreter(unittest.TestCase): 67 | 68 | @unittest.skipIf(_not_buffered(), 'sys.stdout is not buffered') 69 | def test_command_mode(self): 70 | 71 | pythonect_interpreter.main(argv=shlex.split("""pythonect -c '"Hello, world" -> print'""")) 72 | 73 | self.assertRegexpMatches(sys.stdout.getvalue().strip(), '.*Hello, world.*') 74 | 75 | @unittest.skipIf(_not_buffered(), 'sys.stdout is not buffered') 76 | def test_script_mode_p2y(self): 77 | 78 | pythonect_interpreter.main(argv=shlex.split('pythonect ' + TEST_DIR + os.sep + 'helloworld.p2y')) 79 | 80 | self.assertRegexpMatches(sys.stdout.getvalue().strip(), '.*Hello, world.*') 81 | 82 | @unittest.skipIf(_not_buffered(), 'sys.stdout is not buffered') 83 | def test_script_mode_dia(self): 84 | 85 | pythonect_interpreter.main(argv=shlex.split('pythonect ' + TEST_DIR + os.sep + 'helloworld.dia')) 86 | 87 | self.assertRegexpMatches(sys.stdout.getvalue().strip(), '.*Hello, world.*') 88 | 89 | @unittest.skipIf(_not_buffered(), 'sys.stdout is not buffered') 90 | def test_module_mode(self): 91 | 92 | pythonect_interpreter.main(argv=shlex.split('pythonect -m foobar')) 93 | 94 | self.assertRegexpMatches(sys.stdout.getvalue().strip(), '.*Hello, world.*') 95 | 96 | @unittest.skipIf(_not_buffered(), 'sys.stdout is not buffered') 97 | def test_maxthreads_cmd_option(self): 98 | 99 | pythonect_interpreter.main(argv=shlex.split('pythonect -mt 1 -c "[1,2,3,4,5,6,7,8,9] -> print"')) 100 | 101 | self.assertTrue(len(set(re.findall('Thread-[\d]', sys.stdout.getvalue().strip()))) == 1) 102 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 21 | 22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext 23 | 24 | help: 25 | @echo "Please use \`make ' where is one of" 26 | @echo " html to make standalone HTML files" 27 | @echo " dirhtml to make HTML files named index.html in directories" 28 | @echo " singlehtml to make a single large HTML file" 29 | @echo " pickle to make pickle files" 30 | @echo " json to make JSON files" 31 | @echo " htmlhelp to make HTML files and a HTML help project" 32 | @echo " qthelp to make HTML files and a qthelp project" 33 | @echo " devhelp to make HTML files and a Devhelp project" 34 | @echo " epub to make an epub" 35 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 36 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 37 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 38 | @echo " text to make text files" 39 | @echo " man to make manual pages" 40 | @echo " texinfo to make Texinfo files" 41 | @echo " info to make Texinfo files and run them through makeinfo" 42 | @echo " gettext to make PO message catalogs" 43 | @echo " changes to make an overview of all changed/added/deprecated items" 44 | @echo " xml to make Docutils-native XML files" 45 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 46 | @echo " linkcheck to check all external links for integrity" 47 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 48 | 49 | clean: 50 | rm -rf $(BUILDDIR)/* 51 | 52 | html: 53 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 54 | @echo 55 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 56 | 57 | dirhtml: 58 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 59 | @echo 60 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 61 | 62 | singlehtml: 63 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 64 | @echo 65 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 66 | 67 | pickle: 68 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 69 | @echo 70 | @echo "Build finished; now you can process the pickle files." 71 | 72 | json: 73 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 74 | @echo 75 | @echo "Build finished; now you can process the JSON files." 76 | 77 | htmlhelp: 78 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 79 | @echo 80 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 81 | ".hhp project file in $(BUILDDIR)/htmlhelp." 82 | 83 | qthelp: 84 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 85 | @echo 86 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 87 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 88 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Pythonect.qhcp" 89 | @echo "To view the help file:" 90 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Pythonect.qhc" 91 | 92 | devhelp: 93 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 94 | @echo 95 | @echo "Build finished." 96 | @echo "To view the help file:" 97 | @echo "# mkdir -p $$HOME/.local/share/devhelp/Pythonect" 98 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Pythonect" 99 | @echo "# devhelp" 100 | 101 | epub: 102 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 103 | @echo 104 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 105 | 106 | latex: 107 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 108 | @echo 109 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 110 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 111 | "(use \`make latexpdf' here to do that automatically)." 112 | 113 | latexpdf: 114 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 115 | @echo "Running LaTeX files through pdflatex..." 116 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 117 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 118 | 119 | latexpdfja: 120 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 121 | @echo "Running LaTeX files through platex and dvipdfmx..." 122 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 123 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 124 | 125 | text: 126 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 127 | @echo 128 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 129 | 130 | man: 131 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 132 | @echo 133 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 134 | 135 | texinfo: 136 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 137 | @echo 138 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 139 | @echo "Run \`make' in that directory to run these through makeinfo" \ 140 | "(use \`make info' here to do that automatically)." 141 | 142 | info: 143 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 144 | @echo "Running Texinfo files through makeinfo..." 145 | make -C $(BUILDDIR)/texinfo info 146 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 147 | 148 | gettext: 149 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 150 | @echo 151 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 152 | 153 | changes: 154 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 155 | @echo 156 | @echo "The overview file is in $(BUILDDIR)/changes." 157 | 158 | linkcheck: 159 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 160 | @echo 161 | @echo "Link check complete; look for any errors in the above output " \ 162 | "or in $(BUILDDIR)/linkcheck/output.txt." 163 | 164 | doctest: 165 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 166 | @echo "Testing of doctests in the sources finished, look at the " \ 167 | "results in $(BUILDDIR)/doctest/output.txt." 168 | 169 | xml: 170 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 171 | @echo 172 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 173 | 174 | pseudoxml: 175 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 176 | @echo 177 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 178 | -------------------------------------------------------------------------------- /doc/_static/123_sum_reduce.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikotler/pythonect/ac597f9c37b119bafc0e41e67e8a21f02e435752/doc/_static/123_sum_reduce.png -------------------------------------------------------------------------------- /doc/_static/123_to_print.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikotler/pythonect/ac597f9c37b119bafc0e41e67e8a21f02e435752/doc/_static/123_to_print.png -------------------------------------------------------------------------------- /doc/_static/dia_step_0.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikotler/pythonect/ac597f9c37b119bafc0e41e67e8a21f02e435752/doc/_static/dia_step_0.jpeg -------------------------------------------------------------------------------- /doc/_static/dia_step_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikotler/pythonect/ac597f9c37b119bafc0e41e67e8a21f02e435752/doc/_static/dia_step_0.png -------------------------------------------------------------------------------- /doc/_static/dia_step_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikotler/pythonect/ac597f9c37b119bafc0e41e67e8a21f02e435752/doc/_static/dia_step_1.png -------------------------------------------------------------------------------- /doc/_static/dia_step_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikotler/pythonect/ac597f9c37b119bafc0e41e67e8a21f02e435752/doc/_static/dia_step_2.png -------------------------------------------------------------------------------- /doc/_static/dia_step_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikotler/pythonect/ac597f9c37b119bafc0e41e67e8a21f02e435752/doc/_static/dia_step_3.png -------------------------------------------------------------------------------- /doc/_static/dia_step_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikotler/pythonect/ac597f9c37b119bafc0e41e67e8a21f02e435752/doc/_static/dia_step_4.png -------------------------------------------------------------------------------- /doc/_static/dia_step_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikotler/pythonect/ac597f9c37b119bafc0e41e67e8a21f02e435752/doc/_static/dia_step_5.png -------------------------------------------------------------------------------- /doc/_static/dia_step_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikotler/pythonect/ac597f9c37b119bafc0e41e67e8a21f02e435752/doc/_static/dia_step_6.png -------------------------------------------------------------------------------- /doc/_static/dia_step_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikotler/pythonect/ac597f9c37b119bafc0e41e67e8a21f02e435752/doc/_static/dia_step_7.png -------------------------------------------------------------------------------- /doc/_static/dia_step_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikotler/pythonect/ac597f9c37b119bafc0e41e67e8a21f02e435752/doc/_static/dia_step_8.png -------------------------------------------------------------------------------- /doc/_static/helloworld_1_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikotler/pythonect/ac597f9c37b119bafc0e41e67e8a21f02e435752/doc/_static/helloworld_1_2.png -------------------------------------------------------------------------------- /doc/_static/multiple_x_values.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikotler/pythonect/ac597f9c37b119bafc0e41e67e8a21f02e435752/doc/_static/multiple_x_values.png -------------------------------------------------------------------------------- /doc/_static/single_x_value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikotler/pythonect/ac597f9c37b119bafc0e41e67e8a21f02e435752/doc/_static/single_x_value.png -------------------------------------------------------------------------------- /doc/_templates/page.html: -------------------------------------------------------------------------------- 1 | {% extends "!page.html" %} 2 | {% block body %} 3 | {{ super() }} 4 |

Questions? Comments?

5 |
6 | 17 | 18 | comments powered by Disqus 19 | {% endblock %} 20 | {% block footer %} 21 | {{ super() }} 22 | 34 | {% endblock %} 35 | -------------------------------------------------------------------------------- /doc/api.rst: -------------------------------------------------------------------------------- 1 | :mod:`pythonect` --- Parse and execute Pythonect code 2 | ===================================================== 3 | 4 | .. module: pythonect 5 | :synopsis: Parse and execute Pythonect code 6 | 7 | This Python module provides the capability to parse and evaluate a string as Pythonect code 8 | 9 | .. autofunction:: pythonect.parse 10 | 11 | .. autofunction:: pythonect.eval 12 | -------------------------------------------------------------------------------- /doc/changelog.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../NEWS 2 | -------------------------------------------------------------------------------- /doc/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Pythonect documentation build configuration file, created by 4 | # sphinx-quickstart on Sat May 11 18:31:27 2013. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # Note that not all possible configuration values are present in this 9 | # autogenerated file. 10 | # 11 | # All configuration values have a default; values that are commented out 12 | # serve to show the default. 13 | 14 | import sys, os 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | sys.path.insert(0, os.path.abspath('..')) 20 | 21 | import pythonect 22 | 23 | # -- General configuration ----------------------------------------------------- 24 | 25 | # If your documentation needs a minimal Sphinx version, state it here. 26 | #needs_sphinx = '1.0' 27 | 28 | # Add any Sphinx extension module names here, as strings. They can be extensions 29 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 30 | extensions = ['sphinx.ext.autodoc', 'sphinx.ext.ifconfig'] 31 | 32 | # Add any paths that contain templates here, relative to this directory. 33 | templates_path = ['_templates'] 34 | 35 | # The suffix of source filenames. 36 | source_suffix = '.rst' 37 | 38 | # The encoding of source files. 39 | #source_encoding = 'utf-8-sig' 40 | 41 | # The master toctree document. 42 | master_doc = 'index' 43 | 44 | # General information about the project. 45 | project = u'Pythonect' 46 | copyright = u'2013, Itzik Kotler' 47 | 48 | # The version info for the project you're documenting, acts as replacement for 49 | # |version| and |release|, also used in various other places throughout the 50 | # built documents. 51 | # 52 | # The short X.Y version. 53 | version = '.'.join(pythonect.__version__.split('.')[:2]) 54 | # The full version, including alpha/beta/rc tags. 55 | release = pythonect.__version__ 56 | 57 | # The language for content autogenerated by Sphinx. Refer to documentation 58 | # for a list of supported languages. 59 | #language = None 60 | 61 | # There are two options for replacing |today|: either, you set today to some 62 | # non-false value, then it is used: 63 | #today = '' 64 | # Else, today_fmt is used as the format for a strftime call. 65 | #today_fmt = '%B %d, %Y' 66 | 67 | # List of patterns, relative to source directory, that match files and 68 | # directories to ignore when looking for source files. 69 | exclude_patterns = ['_build'] 70 | 71 | # The reST default role (used for this markup: `text`) to use for all documents. 72 | #default_role = None 73 | 74 | # If true, '()' will be appended to :func: etc. cross-reference text. 75 | #add_function_parentheses = True 76 | 77 | # If true, the current module name will be prepended to all description 78 | # unit titles (such as .. function::). 79 | #add_module_names = True 80 | 81 | # If true, sectionauthor and moduleauthor directives will be shown in the 82 | # output. They are ignored by default. 83 | #show_authors = False 84 | 85 | # The name of the Pygments (syntax highlighting) style to use. 86 | pygments_style = 'sphinx' 87 | 88 | # A list of ignored prefixes for module index sorting. 89 | #modindex_common_prefix = [] 90 | 91 | # If true, keep warnings as "system message" paragraphs in the built documents. 92 | #keep_warnings = False 93 | 94 | 95 | # -- Options for HTML output --------------------------------------------------- 96 | 97 | # The theme to use for HTML and HTML Help pages. See the documentation for 98 | # a list of builtin themes. 99 | html_theme = 'default' 100 | 101 | # Theme options are theme-specific and customize the look and feel of a theme 102 | # further. For a list of options available for each theme, see the 103 | # documentation. 104 | #html_theme_options = {} 105 | 106 | # Add any paths that contain custom themes here, relative to this directory. 107 | #html_theme_path = [] 108 | 109 | # The name for this set of Sphinx documents. If None, it defaults to 110 | # " v documentation". 111 | #html_title = None 112 | 113 | # A shorter title for the navigation bar. Default is the same as html_title. 114 | #html_short_title = None 115 | 116 | # The name of an image file (relative to this directory) to place at the top 117 | # of the sidebar. 118 | #html_logo = None 119 | 120 | # The name of an image file (within the static path) to use as favicon of the 121 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 122 | # pixels large. 123 | #html_favicon = None 124 | 125 | # Add any paths that contain custom static files (such as style sheets) here, 126 | # relative to this directory. They are copied after the builtin static files, 127 | # so a file named "default.css" will overwrite the builtin "default.css". 128 | html_static_path = ['_static'] 129 | 130 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 131 | # using the given strftime format. 132 | #html_last_updated_fmt = '%b %d, %Y' 133 | 134 | # If true, SmartyPants will be used to convert quotes and dashes to 135 | # typographically correct entities. 136 | #html_use_smartypants = True 137 | 138 | # Custom sidebar templates, maps document names to template names. 139 | #html_sidebars = {} 140 | 141 | # Additional templates that should be rendered to pages, maps page names to 142 | # template names. 143 | #html_additional_pages = {} 144 | 145 | # If false, no module index is generated. 146 | #html_domain_indices = True 147 | 148 | # If false, no index is generated. 149 | #html_use_index = True 150 | 151 | # If true, the index is split into individual pages for each letter. 152 | #html_split_index = False 153 | 154 | # If true, links to the reST sources are added to the pages. 155 | #html_show_sourcelink = True 156 | 157 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 158 | #html_show_sphinx = True 159 | 160 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 161 | #html_show_copyright = True 162 | 163 | # If true, an OpenSearch description file will be output, and all pages will 164 | # contain a tag referring to it. The value of this option must be the 165 | # base URL from which the finished HTML is served. 166 | #html_use_opensearch = '' 167 | 168 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 169 | #html_file_suffix = None 170 | 171 | # Output file base name for HTML help builder. 172 | htmlhelp_basename = 'Pythonectdoc' 173 | 174 | 175 | # -- Options for LaTeX output -------------------------------------------------- 176 | 177 | latex_elements = { 178 | # The paper size ('letterpaper' or 'a4paper'). 179 | #'papersize': 'letterpaper', 180 | 181 | # The font size ('10pt', '11pt' or '12pt'). 182 | #'pointsize': '10pt', 183 | 184 | # Additional stuff for the LaTeX preamble. 185 | #'preamble': '', 186 | } 187 | 188 | # Grouping the document tree into LaTeX files. List of tuples 189 | # (source start file, target name, title, author, documentclass [howto/manual]). 190 | latex_documents = [ 191 | ('index', 'Pythonect.tex', u'Pythonect Documentation', 192 | u'Itzik Kotler', 'manual'), 193 | ] 194 | 195 | # The name of an image file (relative to this directory) to place at the top of 196 | # the title page. 197 | #latex_logo = None 198 | 199 | # For "manual" documents, if this is true, then toplevel headings are parts, 200 | # not chapters. 201 | #latex_use_parts = False 202 | 203 | # If true, show page references after internal links. 204 | #latex_show_pagerefs = False 205 | 206 | # If true, show URL addresses after external links. 207 | #latex_show_urls = False 208 | 209 | # Documents to append as an appendix to all manuals. 210 | #latex_appendices = [] 211 | 212 | # If false, no module index is generated. 213 | #latex_domain_indices = True 214 | 215 | 216 | # -- Options for manual page output -------------------------------------------- 217 | 218 | # One entry per manual page. List of tuples 219 | # (source start file, name, description, authors, manual section). 220 | man_pages = [ 221 | ('index', 'pythonect', u'Pythonect Documentation', 222 | [u'Itzik Kotler'], 1) 223 | ] 224 | 225 | # If true, show URL addresses after external links. 226 | #man_show_urls = False 227 | 228 | 229 | # -- Options for Texinfo output ------------------------------------------------ 230 | 231 | # Grouping the document tree into Texinfo files. List of tuples 232 | # (source start file, target name, title, author, 233 | # dir menu entry, description, category) 234 | texinfo_documents = [ 235 | ('index', 'Pythonect', u'Pythonect Documentation', 236 | u'Itzik Kotler', 'Pythonect', 'One line description of project.', 237 | 'Miscellaneous'), 238 | ] 239 | 240 | # Documents to append as an appendix to all manuals. 241 | #texinfo_appendices = [] 242 | 243 | # If false, no module index is generated. 244 | #texinfo_domain_indices = True 245 | 246 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 247 | #texinfo_show_urls = 'footnote' 248 | 249 | # If true, do not generate a @detailmenu in the "Top" node's menu. 250 | #texinfo_no_detailmenu = False 251 | -------------------------------------------------------------------------------- /doc/foreword.rst: -------------------------------------------------------------------------------- 1 | Foreword 2 | ======== 3 | 4 | Read this before you get started with Pythonect. This hopefully answers some 5 | questions about the purpose and goals of the project, and when you should or 6 | should not be using it. 7 | 8 | What is Pythonect? 9 | ------------------ 10 | 11 | Pythonect is a new, experimental, general-purpose dataflow programming 12 | language based on Python. It provides both a visual programming language and a 13 | text-based scripting language. The text-based scripting language aims to 14 | combine the quick and intuitive feel of shell scripting, with the power of 15 | Python. The visual programming language is based on the idea of a diagram with 16 | "boxes and arrows". 17 | 18 | The Pythonect interpreter (and reference implementation) is a free and open 19 | source software written completely in Python, and is available under the BSD 20 | license. 21 | 22 | Why Pythonect? 23 | -------------- 24 | 25 | Pythonect, being a dataflow programming language, treats data as something 26 | that originates from a source, flows through a number of processing 27 | components, and arrives at some final destination. As such, it is most 28 | suitable for creating applications that are themselves focused on the "flow" 29 | of data. Perhaps the most readily available example of a dataflow-oriented 30 | applications comes from the realm of real-time signal processing, e.g. a video 31 | signal processor which perhaps starts with a video input, modifies it through 32 | a number of processing components (video filters), and finally outputs it to a 33 | video display. 34 | 35 | As with video, other domain problems (e.g. image processing, data analysis, 36 | rapid prototyping, and etc.) can be expressed as a network of different 37 | components that are connected by a number of communication channels. The 38 | benefits, and perhaps the greatest incentives, of expressing a domain problem 39 | this way is scalability and parallelism. The different components in the 40 | network can be maneuvered to create entirely unique dataflows without 41 | necessarily requiring the relationship to be hardcoded. Also, the design and 42 | concept of components make it easier to run on distributed systems and 43 | parallel processors. 44 | 45 | Continue to :ref:`installation` or :ref:`tutorial` 46 | -------------------------------------------------------------------------------- /doc/index.rst: -------------------------------------------------------------------------------- 1 | :orphan: 2 | 3 | Welcome to Pythonect 4 | ==================== 5 | 6 | Welcome to Pythonect's documentation. This documentation is divided into 7 | different parts. I recommend that you get started with :ref:`installation` and 8 | then head over to the :ref:`tutorial`. If you'd rather dive into the internals 9 | of Pythonect, check out the :ref:`api` documentation. 10 | 11 | Pythonect is dependent on one external library: the `NetworkX 12 | `_ graph library. This library is not documented 13 | here. If you want to dive into its documentation, check out the following 14 | link: `NetworkX Documentation `_ 15 | 16 | .. note:: 17 | This is the main documentation for the Pythonect project. The contents of 18 | this site are automatically generated via `Sphinx `_ based on the Python docstrings throughout the code and the 20 | reStructuredText documents in the `doc/ directory 21 | `_ of the git 22 | repository. If you find an error in the documentation, please report it in 23 | the bug tracker `here `__, 24 | or even better, submit a pull request! 25 | 26 | User's Guide 27 | ------------ 28 | 29 | This part of the documentation, which is mostly prose, begins with some 30 | background information about Pythonect, then focuses on step-by-step 31 | instructions for building applications with Pythonect. 32 | 33 | .. toctree:: 34 | :maxdepth: 2 35 | 36 | foreword 37 | installation 38 | tutorial/index 39 | 40 | .. _api: 41 | 42 | API Reference 43 | ------------- 44 | 45 | If you are looking for information on a specific function, class or method, 46 | this part of the documentation is for you. 47 | 48 | .. toctree:: 49 | :maxdepth: 2 50 | 51 | api 52 | 53 | Additional Notes 54 | ---------------- 55 | 56 | Design notes, legal information and changelog are here for the interested. 57 | 58 | .. toctree:: 59 | :maxdepth: 2 60 | 61 | changelog 62 | license -------------------------------------------------------------------------------- /doc/installation.rst: -------------------------------------------------------------------------------- 1 | .. _installation: 2 | 3 | Installation 4 | ============ 5 | 6 | Pythonect works with Python version 2.6 and greater, but it will not work 7 | (yet) with Python 3. Dependencies are listed in ``setup.py`` and will be 8 | installed automatically as part of any of the techniques listed below. 9 | 10 | .. _installation-pip: 11 | 12 | Using pip or easy_install 13 | ------------------------- 14 | 15 | Easiest way to install Pythonect is to use ``pip``: 16 | 17 | .. code-block:: bash 18 | 19 | pip install Pythonect 20 | 21 | And second to easiest is with ``easy_install``: 22 | 23 | .. code-block:: bash 24 | 25 | easy_install Pythonect 26 | 27 | .. note:: 28 | 29 | Using easy_install is discouraged. Why? `Read here `_. 30 | 31 | .. _installation-git: 32 | 33 | Using git repository 34 | -------------------- 35 | 36 | Regular development happens at our `GitHub repository 37 | `_. Grabbing the cutting edge version 38 | might give you some extra features or fix some newly discovered bugs. We 39 | recommend not installing from the git repo unless you are actively developing 40 | *Pythonect*. To clone the git repository and install it locally: 41 | 42 | .. code-block:: bash 43 | 44 | git clone git://github.com/ikotler/pythonect.git 45 | cd pythonect 46 | python setup.py install 47 | 48 | Alternatively, if you use pip, you can install directly from the git repository: 49 | 50 | .. code-block:: bash 51 | 52 | pip install \ 53 | git+git://github.com/ikotler/pythonect.git@master#egg=pythonect \ 54 | -r https://github.com/ikotler/pythonect/raw/master/doc/requirements.txt 55 | 56 | .. _installation-archives: 57 | 58 | Using archives (tarball) 59 | ------------------------ 60 | 61 | Visit our `PyPI Page `_ to grab the 62 | archives of both current and previous stable releases. After untarring, simply 63 | run ``python setup.py install`` to install it. -------------------------------------------------------------------------------- /doc/license.rst: -------------------------------------------------------------------------------- 1 | .. _license: 2 | 3 | License 4 | ======= 5 | 6 | Pythonect licensed under BSD 3-Clause:: 7 | 8 | Copyright (c) 2012-2013, Itzik Kotler 9 | All rights reserved. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | 14 | * Redistributions of source code must retain the above copyright 15 | notice, this list of conditions and the following disclaimer. 16 | 17 | * Redistributions in binary form must reproduce the above copyright 18 | notice, this list of conditions and the following disclaimer in the 19 | documentation and/or other materials provided with the distribution. 20 | 21 | * Neither the name of the author nor the names of its contributors may 22 | be used to endorse or promote products derived from this software without 23 | specific prior written permission. 24 | 25 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 26 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 27 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 28 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 29 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 30 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 32 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /doc/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | if "%SPHINXBUILD%" == "" ( 6 | set SPHINXBUILD=sphinx-build 7 | ) 8 | set BUILDDIR=_build 9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . 10 | set I18NSPHINXOPTS=%SPHINXOPTS% . 11 | if NOT "%PAPER%" == "" ( 12 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 13 | set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% 14 | ) 15 | 16 | if "%1" == "" goto help 17 | 18 | if "%1" == "help" ( 19 | :help 20 | echo.Please use `make ^` where ^ is one of 21 | echo. html to make standalone HTML files 22 | echo. dirhtml to make HTML files named index.html in directories 23 | echo. singlehtml to make a single large HTML file 24 | echo. pickle to make pickle files 25 | echo. json to make JSON files 26 | echo. htmlhelp to make HTML files and a HTML help project 27 | echo. qthelp to make HTML files and a qthelp project 28 | echo. devhelp to make HTML files and a Devhelp project 29 | echo. epub to make an epub 30 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 31 | echo. text to make text files 32 | echo. man to make manual pages 33 | echo. texinfo to make Texinfo files 34 | echo. gettext to make PO message catalogs 35 | echo. changes to make an overview over all changed/added/deprecated items 36 | echo. xml to make Docutils-native XML files 37 | echo. pseudoxml to make pseudoxml-XML files for display purposes 38 | echo. linkcheck to check all external links for integrity 39 | echo. doctest to run all doctests embedded in the documentation if enabled 40 | goto end 41 | ) 42 | 43 | if "%1" == "clean" ( 44 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i 45 | del /q /s %BUILDDIR%\* 46 | goto end 47 | ) 48 | 49 | 50 | %SPHINXBUILD% 2> nul 51 | if errorlevel 9009 ( 52 | echo. 53 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 54 | echo.installed, then set the SPHINXBUILD environment variable to point 55 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 56 | echo.may add the Sphinx directory to PATH. 57 | echo. 58 | echo.If you don't have Sphinx installed, grab it from 59 | echo.http://sphinx-doc.org/ 60 | exit /b 1 61 | ) 62 | 63 | if "%1" == "html" ( 64 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html 65 | if errorlevel 1 exit /b 1 66 | echo. 67 | echo.Build finished. The HTML pages are in %BUILDDIR%/html. 68 | goto end 69 | ) 70 | 71 | if "%1" == "dirhtml" ( 72 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml 73 | if errorlevel 1 exit /b 1 74 | echo. 75 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. 76 | goto end 77 | ) 78 | 79 | if "%1" == "singlehtml" ( 80 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml 81 | if errorlevel 1 exit /b 1 82 | echo. 83 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. 84 | goto end 85 | ) 86 | 87 | if "%1" == "pickle" ( 88 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle 89 | if errorlevel 1 exit /b 1 90 | echo. 91 | echo.Build finished; now you can process the pickle files. 92 | goto end 93 | ) 94 | 95 | if "%1" == "json" ( 96 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json 97 | if errorlevel 1 exit /b 1 98 | echo. 99 | echo.Build finished; now you can process the JSON files. 100 | goto end 101 | ) 102 | 103 | if "%1" == "htmlhelp" ( 104 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp 105 | if errorlevel 1 exit /b 1 106 | echo. 107 | echo.Build finished; now you can run HTML Help Workshop with the ^ 108 | .hhp project file in %BUILDDIR%/htmlhelp. 109 | goto end 110 | ) 111 | 112 | if "%1" == "qthelp" ( 113 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp 114 | if errorlevel 1 exit /b 1 115 | echo. 116 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 117 | .qhcp project file in %BUILDDIR%/qthelp, like this: 118 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Pythonect.qhcp 119 | echo.To view the help file: 120 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Pythonect.ghc 121 | goto end 122 | ) 123 | 124 | if "%1" == "devhelp" ( 125 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp 126 | if errorlevel 1 exit /b 1 127 | echo. 128 | echo.Build finished. 129 | goto end 130 | ) 131 | 132 | if "%1" == "epub" ( 133 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub 134 | if errorlevel 1 exit /b 1 135 | echo. 136 | echo.Build finished. The epub file is in %BUILDDIR%/epub. 137 | goto end 138 | ) 139 | 140 | if "%1" == "latex" ( 141 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 142 | if errorlevel 1 exit /b 1 143 | echo. 144 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. 145 | goto end 146 | ) 147 | 148 | if "%1" == "latexpdf" ( 149 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 150 | cd %BUILDDIR%/latex 151 | make all-pdf 152 | cd %BUILDDIR%/.. 153 | echo. 154 | echo.Build finished; the PDF files are in %BUILDDIR%/latex. 155 | goto end 156 | ) 157 | 158 | if "%1" == "latexpdfja" ( 159 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 160 | cd %BUILDDIR%/latex 161 | make all-pdf-ja 162 | cd %BUILDDIR%/.. 163 | echo. 164 | echo.Build finished; the PDF files are in %BUILDDIR%/latex. 165 | goto end 166 | ) 167 | 168 | if "%1" == "text" ( 169 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text 170 | if errorlevel 1 exit /b 1 171 | echo. 172 | echo.Build finished. The text files are in %BUILDDIR%/text. 173 | goto end 174 | ) 175 | 176 | if "%1" == "man" ( 177 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man 178 | if errorlevel 1 exit /b 1 179 | echo. 180 | echo.Build finished. The manual pages are in %BUILDDIR%/man. 181 | goto end 182 | ) 183 | 184 | if "%1" == "texinfo" ( 185 | %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo 186 | if errorlevel 1 exit /b 1 187 | echo. 188 | echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. 189 | goto end 190 | ) 191 | 192 | if "%1" == "gettext" ( 193 | %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale 194 | if errorlevel 1 exit /b 1 195 | echo. 196 | echo.Build finished. The message catalogs are in %BUILDDIR%/locale. 197 | goto end 198 | ) 199 | 200 | if "%1" == "changes" ( 201 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes 202 | if errorlevel 1 exit /b 1 203 | echo. 204 | echo.The overview file is in %BUILDDIR%/changes. 205 | goto end 206 | ) 207 | 208 | if "%1" == "linkcheck" ( 209 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck 210 | if errorlevel 1 exit /b 1 211 | echo. 212 | echo.Link check complete; look for any errors in the above output ^ 213 | or in %BUILDDIR%/linkcheck/output.txt. 214 | goto end 215 | ) 216 | 217 | if "%1" == "doctest" ( 218 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest 219 | if errorlevel 1 exit /b 1 220 | echo. 221 | echo.Testing of doctests in the sources finished, look at the ^ 222 | results in %BUILDDIR%/doctest/output.txt. 223 | goto end 224 | ) 225 | 226 | if "%1" == "xml" ( 227 | %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml 228 | if errorlevel 1 exit /b 1 229 | echo. 230 | echo.Build finished. The XML files are in %BUILDDIR%/xml. 231 | goto end 232 | ) 233 | 234 | if "%1" == "pseudoxml" ( 235 | %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml 236 | if errorlevel 1 exit /b 1 237 | echo. 238 | echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. 239 | goto end 240 | ) 241 | 242 | :end 243 | -------------------------------------------------------------------------------- /doc/requirements.txt: -------------------------------------------------------------------------------- 1 | # requirements.txt for Python's PIP (see: http://www.pip-installer.org/en/latest/requirements.html) 2 | networkx>=1.7 3 | -------------------------------------------------------------------------------- /doc/tutorial/controlflow.rst: -------------------------------------------------------------------------------- 1 | .. _tut-ctrlflowtools: 2 | 3 | ****************** 4 | Control Flow Tools 5 | ****************** 6 | 7 | Pythonect supports standard control flow tools, but with a twist! 8 | 9 | 10 | .. _tut-if: 11 | 12 | Using Boolean Values as ``if`` Statement 13 | ======================================== 14 | 15 | There's no ``if`` keyword in Pythonect, instead, boolean values are used to 16 | determine whether to terminate or continue the flow. 17 | 18 | 19 | .. _tut-if-true: 20 | 21 | :const:`True` as Pass-through 22 | ----------------------------- 23 | 24 | Whenever a Python expression or function returns :const:`True` the current 25 | value in the flow is pushed to the next operation. For example: 26 | :: 27 | 28 | 1 -> [_ < 2] -> print 29 | 30 | Will print :const:`1`, because the expression is evaluated to :const:`True` (i.e. 1 < 31 | 2). Another example: 32 | :: 33 | 34 | "Hello, world" -> _.startswith('Hello') -> print 35 | 36 | Will print ``"Hello, world"`` because ``startswith`` method returned :const:`True` 37 | (i.e. "Hello, world" string starts with "Hello" string). 38 | 39 | 40 | .. _tut-if-false: 41 | 42 | :const:`False` as Terminator 43 | ---------------------------- 44 | 45 | Whenever a Python expression or function returns :const:`False` the current 46 | flow terminates and returns False. For example: 47 | :: 48 | 49 | "Hello, world" -> _.startswith('ello') -> print 50 | 51 | This will not print anything and return :const:`False`. 52 | 53 | 54 | .. _tut_multi_as_all: 55 | 56 | Using Multithreading as ``elif`` and ``else`` 57 | --------------------------------------------- 58 | 59 | Since there's no ``if``, there's also no ``elif`` or ``else``, instead all 60 | possible flows are evaulated at once. For example: 61 | :: 62 | 63 | "Hello, world" -> [[_.startswith('Hello') -> print "1"], [[_ != 'foobar'] -> print "2" ]] 64 | 65 | Graphically (Visual programming wise), represented as: 66 | 67 | .. image:: ../_static/helloworld_1_2.png 68 | 69 | Both versions will print (each in its own thread, and not necessarily in that 70 | order): :const:`1` and :const:`2`. 71 | 72 | 73 | .. _tut-for: 74 | 75 | Using Iterable Object as ``for`` Statement 76 | ========================================== 77 | 78 | There's no ``for`` keyword, instead, every Iterable object is treated as a 79 | for-loop. For example: 80 | :: 81 | 82 | [1,2,3] -> print 83 | 84 | And 85 | :: 86 | 87 | (1,2,3) -> print 88 | 89 | Both, Graphically (Visual programming wise) represented as: 90 | 91 | .. image:: ../_static/123_to_print.png 92 | 93 | Will print :const:`1`, :const:`2`, and :const:`3` (not necessarily in that 94 | order). The same applies to generator functions (i.e. ``yield``) and Python 95 | classes that implement __iter__() method. 96 | 97 | The only exception are strings. Pythonect does not iterate Python strings by 98 | default. To iterate a string in Pythonect, use Python's built-in iter() 99 | function as follows: 100 | :: 101 | 102 | iter("abc") -> print 103 | 104 | The code above will print the letters: ``a``, ``b``, and ``c`` (not 105 | necessarily in that order). 106 | 107 | 108 | .. tut-dict-as-switch: 109 | 110 | Using Dictionary as ``switch`` Statement 111 | ======================================== 112 | 113 | There's no ``switch`` keyword in Pythonect, instead, every literal ``dict`` 114 | can be used as a ``switch``-like mechanism (without fallthrough). For example: 115 | :: 116 | 117 | 1 -> {1: 'One', 2: 'Two'} -> print 118 | 119 | Will print ``One``. While: 120 | :: 121 | 122 | 3 -> {1: 'One', 2: 'Two'} -> print 123 | 124 | Will will not print and return :const:`False` 125 | 126 | -------------------------------------------------------------------------------- /doc/tutorial/flow.rst: -------------------------------------------------------------------------------- 1 | .. _tut-flow: 2 | 3 | ********* 4 | Data Flow 5 | ********* 6 | 7 | Depending on the scripting interface, directing the flow can be represented by plain text or interconnected lines 8 | 9 | 10 | .. _tut-txtflow: 11 | 12 | Text-based Symbols 13 | ================== 14 | 15 | The text-based scripting language aims to combine the quick and intuitive feel of shell scripting. Adopting a *Unix Pipeline*-like syntax. 16 | 17 | 18 | ``|`` as Synchronous Forward 19 | ---------------------------- 20 | 21 | This operator pushs data to next operation and **do** block/wait for it 22 | finish. For example: 23 | :: 24 | 25 | [1,2,3,4] | print 26 | 27 | Will always print (each item in it's own thread and in this order): ``1``, ``2``, ``3``, ``4``. 28 | 29 | 30 | ``->`` as Asynchronous Forward 31 | ------------------------------ 32 | 33 | This operator pushs data to the next operation and **do not** block/wait for 34 | it to finish. For example: 35 | :: 36 | 37 | [1,2,3,4] -> print 38 | 39 | May print (each item in it's own thread): ``4``, ``3``, ``2``, ``1`` or ``2``, ``1``, ``3``, ``4`` or even ``1``, ``2``, ``3``, ``4``. 40 | 41 | 42 | .. tut-graphflow: 43 | 44 | "Boxes and Arrows" 45 | ================== 46 | 47 | Currently, in the Visual Programming Language, all lines are treated as asynchronous forward. -------------------------------------------------------------------------------- /doc/tutorial/helloworld.rst: -------------------------------------------------------------------------------- 1 | .. _tut-helloworld: 2 | 3 | Hello World Program 4 | =================== 5 | 6 | Pythonect provides both a visual programming language and a text-based 7 | scripting language. 8 | 9 | The following is an example Hello world program in both visual and text-based 10 | languages. Both versions consist of the same flow. 11 | 12 | 13 | .. _tut-visualexample: 14 | 15 | Visual Programming Version 16 | -------------------------- 17 | 18 | Pythonect supports multiple graph describing languages and diagram formats. 19 | For the Hello world example I will be using `Dia 20 | `_. 21 | 22 | :program:`Dia` is a free and open source general-purpose diagramming software. 23 | For instructions on how to download and install :program:`dia`, please visit `Dia Website 24 | `_ 25 | 26 | When you launch :program:`dia` you should see an empty :file:`Diagram1.dia` tab, like this: 27 | 28 | .. image:: ../_static/dia_step_0.png 29 | 30 | Start by clicking on the box (aka. Process/Auxliary Operation) shape to select it: 31 | 32 | .. image:: ../_static/dia_step_1.png 33 | 34 | Now, click anywhere on the grid, a box (aka. Process/Auxliary Operation) should appear. Enter the text ``"Hello, world"`` (with quotes) in it: 35 | 36 | .. image:: ../_static/dia_step_2.png 37 | 38 | Next, click again on the grid, another box should appear. Enter the text ``print`` (without quotes) in it: 39 | 40 | .. image:: ../_static/dia_step_3.png 41 | 42 | Let's connect the two boxes together. Start by clicking on the Line image to select it: 43 | 44 | .. image:: ../_static/dia_step_4.png 45 | 46 | Now, click on the ``"Hello, world"`` box (it should highlight the box in Red) and drag it to the ``print`` box: 47 | 48 | .. image:: ../_static/dia_step_5.png 49 | 50 | Like this: 51 | 52 | .. image:: ../_static/dia_step_6.png 53 | 54 | If successful, you should see something like this: 55 | 56 | .. image:: ../_static/dia_step_7.png 57 | 58 | To test that it's indeed connect, try dragging one of the boxes and see that the Line is following, like this: 59 | 60 | .. image:: ../_static/dia_step_8.png 61 | 62 | If indeed the Line is following, then it's time to save the diagram. Let's save it as :file:`HelloWorld.dia` and run it, as follows: 63 | :: 64 | 65 | $ pythonect HelloWorld.dia 66 | 67 | The output should be: 68 | :: 69 | 70 | : Hello, world 71 | 72 | 73 | .. tut-textexample: 74 | 75 | Text-based Programming Version 76 | ------------------------------ 77 | 78 | Open your favorite editor and type: 79 | :: 80 | 81 | "Hello, world" -> print 82 | 83 | Save it as :file:`HelloWorld.p2y` and run it as follows: 84 | :: 85 | $ pythonect HelloWorld.p2y 86 | 87 | The output should be: 88 | :: 89 | 90 | : Hello, world 91 | 92 | To break it down: ``"Hello, world"`` is a literal String, ``print`` is a Python function, and ``->`` is a text-based data flow operator. 93 | 94 | You can learn more about Pythonect's Data Flow Operators at the :ref:`tut-flow` section. -------------------------------------------------------------------------------- /doc/tutorial/index.rst: -------------------------------------------------------------------------------- 1 | .. _tutorial: 2 | 3 | ######## 4 | Tutorial 5 | ######## 6 | 7 | 8 | This tutorial does not attempt to be comprehensive and cover every single 9 | feature, or even every commonly used feature. Instead, it introduces many of 10 | Pythonect's most noteworthy features, and will give you a good idea of the 11 | language's flavor and style. 12 | 13 | Pythonect is based on Python and uses many of its features. If you are 14 | unfamiliar with Python, start with this `Python Tutorial 15 | `_. 16 | 17 | 18 | .. toctree:: 19 | :numbered: 20 | 21 | interpreter.rst 22 | helloworld.rst 23 | flow.rst 24 | vars.rst 25 | controlflow.rst 26 | power.rst -------------------------------------------------------------------------------- /doc/tutorial/interpreter.rst: -------------------------------------------------------------------------------- 1 | .. _tut-using: 2 | 3 | ******************************* 4 | Using the Pythonect Interpreter 5 | ******************************* 6 | 7 | Pythonect provides an interpreter named ``pythonect`` for evaluating Pythonect programs and expressions interactively. 8 | 9 | 10 | .. _tut-invoking: 11 | 12 | Invoking the Interpreter 13 | ======================== 14 | 15 | Using the Pythonect interpreter is quite easy. Once the interpreter is :ref:`installed `, you're ready to go. You can invoke the interpreter from the command line as follows: 16 | :: 17 | 18 | $ pythonect 19 | 20 | The interpreter prints its sign-on message and leaves you at its ``>>>`` prompt: 21 | :: 22 | 23 | Python 2.7.2 (default, Oct 11 2012, 20:14:37) 24 | [Pythonect 0.5.0.dev12] on darwin 25 | Type "help", "copyright", "credits" or "license" for more information. 26 | >>> 27 | 28 | In this interactive mode, you can evaluate arbitrary Pythonect expressions: 29 | :: 30 | 31 | >>> 1+1 32 | 2 33 | >>> "Hello, world" -> print 34 | : Hello, world 35 | 36 | To exit the interpreter, just type the ``quit`` command at the beginning of a line (on Unix systems, typing the end-of-file character :kbd:`Control-D` will do the same). 37 | 38 | Of course you can also run your scripts directly from the command line, as follows: 39 | :: 40 | $ pythonect myscript.p2y 41 | 42 | This executes the script in batch mode. Add the :option:`-i` option if you prefer to run the script in interactive mode: 43 | :: 44 | 45 | $ pythonect -i myscript.p2y 46 | 47 | A number of other command line options are available; try pythonect :option:`-h` for a list of those. 48 | 49 | 50 | .. _tut-interpenv: 51 | 52 | The Interpreter and Its Environment 53 | =================================== 54 | 55 | 56 | .. _tut-scripts: 57 | 58 | Executable Pythonect Scripts 59 | ---------------------------- 60 | 61 | On BSD'ish Unix systems, Pythonect scripts can be made directly executable, like 62 | shell scripts, by putting the line: 63 | :: 64 | 65 | #! /usr/bin/env pythonect 66 | 67 | (assuming that the interpreter is on the user's :envvar:`PATH`) at the 68 | beginning of the script and giving the file an executable mode. The ``#!`` 69 | must be the first two characters of the file. 70 | 71 | The script can be given an executable mode, or permission, using the 72 | :program:`chmod` command:: 73 | 74 | $ chmod +x myscript.p2y 75 | 76 | It can also accept arguments from the command line (these are available in Pythonect by accessing ``sys.argv``), as follows: 77 | :: 78 | 79 | $ cat calc.p2y 80 | #! /usr/bin/env pythonect 81 | int(sys.argv[1]) + int(sys.argv[2]) -> print 82 | 83 | $ pythonect calc.p2y 1 2 84 | : 3 85 | 86 | 87 | .. _tut-history: 88 | 89 | The :file:`.pythonect_history` File 90 | ----------------------------------- 91 | 92 | When running interactively, the Pythonect interpreter usually employs the GNU readline library to provide some useful command line editing facilities, as well as to save command history. The cursor up and down keys can then be used to walk through the command history, existing commands can be edited and resubmitted with the :kbd:`Enter` key, etc. The command history is saved in the :file:`.pythonect_history` file in your home directory between different invocations of the interpreter. -------------------------------------------------------------------------------- /doc/tutorial/power.rst: -------------------------------------------------------------------------------- 1 | .. _tut-powerfeatures: 2 | 3 | Power Features 4 | ============== 5 | 6 | This section groups a few of Pythonect power features that one day may get their own section 7 | 8 | 9 | Autoloader 10 | ----------- 11 | 12 | Pythonect includes an autoloader functionally. You can access any functions, 13 | attributes, etc. from a Python module without having to ``import`` it 14 | first. For example: 15 | :: 16 | 17 | "Hello, world" -> string.split | print 18 | 19 | Will print (in that order, and in different threads): ``Hello,`` and 20 | ``world``. Another example: 21 | :: 22 | 23 | sys.path -> print 24 | 25 | Will print (in no particular order) every directory in your :const:`PATH`, as represented in your sys.path. 26 | 27 | 28 | .. _tut-meta_amp: 29 | 30 | Using ``&`` to Spawn a New Process 31 | ---------------------------------- 32 | 33 | Pythonect uses threads by default, but you can switch to processes by using the metacharacter ``&``. For example: 34 | :: 35 | 36 | "Hello, world" -> print & 37 | 38 | This will print ``"Hello, world"`` from a new process. You can also mix and match: 39 | :: 40 | 41 | "Hello, world" -> [print, print &] 42 | 43 | This will print ``"Hello, world"`` twice, one from a new thread and the other from a new process. 44 | 45 | Notice that switch between thread and process is only valid for the duration of the function call/expression evaluation. 46 | 47 | 48 | .. _tut-meta_at: 49 | 50 | Using ``@`` to Remote Call 51 | -------------------------- 52 | 53 | Pythonect lets you call functions remotely, by using the metacharacter ``@``. To demonstrate this, you will need to use the following simple server (written in Python): 54 | :: 55 | 56 | from SimpleXMLRPCServer import SimpleXMLRPCServer 57 | from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler 58 | 59 | 60 | class RequestHandler(SimpleXMLRPCRequestHandler): 61 | rpc_paths = ('/RPC2',) 62 | 63 | 64 | def say_hello(x): 65 | return "Hello " + x + " and world" 66 | 67 | server = SimpleXMLRPCServer(("localhost", 8000), requestHandler=RequestHandler) 68 | server.register_function(say_hello) 69 | server.serve_forever() 70 | 71 | Save it as :file:`xmlrpc_srv.py` and run it. This code will run a Simple XML-RPC server that will export a function called ``say_hello``. 72 | 73 | Now, calling ``say_hello`` from Pythonect is as easy as: 74 | :: 75 | 76 | "foobar" -> say_hello@xmlrpc://localhost:8000 -> print 77 | 78 | This will print :const:`Hello foobar and world`. 79 | 80 | The destination hostname can also be the result of a function call, or an expression. For example: 81 | :: 82 | 83 | "foobar" -> say_hello@"xmlrpc://" + "localhost:8000" -> print 84 | 85 | Or: 86 | :: 87 | 88 | "foobar" -> say_hello@"xmlrpc://" + get_free_host() -> print 89 | 90 | Where ``get_free_host()`` is a fictional Python function that will return an available hostname from a list of hostnames. 91 | 92 | As a loopback, you can use :const:`None` as an hostname to make the call locally. For example: 93 | :: 94 | 95 | "Hello, world" -> print@None 96 | 97 | Is equal to: 98 | :: 99 | 100 | "Hello, world" -> print 101 | 102 | Both will print ``"Hello, world"`` locally. -------------------------------------------------------------------------------- /doc/tutorial/vars.rst: -------------------------------------------------------------------------------- 1 | .. _tut-vars: 2 | 3 | ********* 4 | Variables 5 | ********* 6 | 7 | 8 | .. _tut-assignment: 9 | 10 | Assignment Statement 11 | ==================== 12 | 13 | Pythonect supports standard Python types, but with a twist! 14 | 15 | .. _tut-onedim-vars: 16 | 17 | Variable ```` in Single Thread 18 | ------------------------------------ 19 | 20 | You can define a variable and set its value as follows: 21 | :: 22 | 23 | [x = 0] -> x -> print 24 | 25 | Graphically (Visual programming wise), this is represented as: 26 | 27 | .. image:: ../_static/single_x_value.png 28 | 29 | Both versions print :const:`0`. You can also change its value during the 30 | program runtime as follows: 31 | :: 32 | 33 | [x = 0] -> x -> print -> [x = 1] -> x -> print 34 | 35 | This will print :const:`0` and :const:`1`, in this order, and in the same 36 | thread. Of course you can assign and re-assign any legal Python value, for 37 | example: 38 | :: 39 | 40 | [x = 0] -> x -> print -> [x = "Hello, world"] -> x -> print 41 | 42 | Will print :const:`0`, and :const:`"Hello, world"` 43 | 44 | 45 | .. _tut-multidim-vars: 46 | 47 | Variable ```` in Multithreading 48 | ------------------------------------- 49 | 50 | You can define a variable and set it with multiple values at the same time 51 | (each value ``map()``\ 'ed to a different thread) as follows: 52 | :: 53 | 54 | [x = 0, x = 1, x = 2] -> x -> print 55 | 56 | Graphically (Visual programming wise), this is represented as: 57 | 58 | .. image:: ../_static/multiple_x_values.png 59 | 60 | Both versions will print, each in its own thread, and not necessarily in that 61 | order: :const:`0`, :const:`1`, :const:`2`. 62 | 63 | Of course you can assign any combinations of Python value and types, for 64 | example: 65 | :: 66 | 67 | [x = 1, x = 1, x = 0.34, x = "Hello, world"] -> x -> print 68 | 69 | This will print, each in its own thread, and not necessarily in that order: 70 | :const:`1`, :const:`1`, :const:`0.34`, and :const:`"Hello world"`. 71 | 72 | 73 | Predefined Variables 74 | ==================== 75 | 76 | Pythonect predefines two variables: ``_`` and ``_!`` 77 | 78 | .. _tut-curvalue: 79 | 80 | ``_`` as Current Value 81 | ---------------------- 82 | 83 | The variable underscore (i.e. ``_``) is predefined to be the current value on 84 | the flow, for example: 85 | :: 86 | 87 | 1 -> _ + 1 -> print 88 | 89 | Will print :const:`2`. As ``_`` will be equal :const:`1` after evaluating the 90 | :const:`1` expression. Another example is: 91 | :: 92 | 93 | ["To be", "Not to be"] -> print "To be, or not to be? " + _ 94 | 95 | This will print, each in its own thread, and not necessarily in that order: 96 | ``To be, or not to be? To be`` and ``To be, or not to be? Not to be`` 97 | 98 | 99 | .. _tut-allcurvalues: 100 | 101 | ``_!`` as All Current Values 102 | ---------------------------- 103 | 104 | The variable underscore question mark (i.e. ``_!``) is predefined to be the 105 | list of all the current values in the program (i.e. ``reduce()``'ed), for 106 | example: 107 | :: 108 | 109 | [1,2,3] -> sum(_!) -> print 110 | 111 | Graphically (Visual programming wise), this is represented as: 112 | 113 | .. image:: ../_static/123_sum_reduce.png 114 | 115 | Both versions will print :const:`6`. Notice how ``sum`` became a *reduce*-like 116 | function, when it accepted a list of :const:`1`, :const:`2`, :const:`3` and 117 | returned :const:`6`. Another example: 118 | :: 119 | 120 | "Hello, world" -> reversed -> reduce(lambda x,y: x+y, _!) -> print 121 | 122 | This will print ``"dlrow ,olleH"`` (i.e. ``"Hello, world"`` reversed) -------------------------------------------------------------------------------- /examples/hello.dia: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | #A4# 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | #'Hello, world'# 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | #print# 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /examples/hello.p2y: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env pythonect 2 | # 3 | # The canonical "Hello, world" example program 4 | # 5 | # >>> 'Hello, world' -> print 6 | # : Hello, world 7 | # 8 | 9 | 'Hello, world' -> print 10 | -------------------------------------------------------------------------------- /examples/repl.dia: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | #A4# 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | #raw_input('$ ')# 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | #eval# 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | #print# 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | -------------------------------------------------------------------------------- /pythonect/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012-2013, Itzik Kotler 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # 14 | # * Neither the name of the author nor the names of its contributors may 15 | # be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 22 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | """Parse and execute Pythonect code""" 30 | 31 | from _version import __version__ 32 | 33 | 34 | # API 35 | 36 | from internal.eval import eval, parse 37 | -------------------------------------------------------------------------------- /pythonect/_version.py: -------------------------------------------------------------------------------- 1 | __version__ = '0.6.0' 2 | -------------------------------------------------------------------------------- /pythonect/internal/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012-2013, Itzik Kotler 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # 14 | # * Neither the name of the author nor the names of its contributors may 15 | # be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 22 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /pythonect/internal/_graph.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012-2013, Itzik Kotler 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # 14 | # * Neither the name of the author nor the names of its contributors may 15 | # be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 22 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | import networkx 30 | import networkx.convert 31 | 32 | 33 | # Local imports 34 | 35 | import _ordereddict 36 | 37 | 38 | class Graph(networkx.DiGraph): 39 | 40 | def __init__(self, data=None, **attr): 41 | 42 | networkx.DiGraph.__init__(self, data, **attr) 43 | 44 | # Line #202 - 216 ; networkx/classes/digraph.py 45 | 46 | self.graph = _ordereddict.OrderedDict() # dictionary for graph attributes 47 | self.node = _ordereddict.OrderedDict() # dictionary for node attributes 48 | # We store two adjacency lists: 49 | # the predecessors of node n are stored in the dict self.pred 50 | # the successors of node n are stored in the dict self.succ=self.adj 51 | self.adj = _ordereddict.OrderedDict() # empty adjacency dictionary 52 | self.pred = _ordereddict.OrderedDict() # predecessor 53 | self.succ = self.adj # successor 54 | 55 | # attempt to load graph with data 56 | if data is not None: 57 | networkx.convert.to_networkx_graph(data, create_using=self) 58 | # load graph attributes (must be after convert) 59 | self.graph.update(attr) 60 | self.edge = self.adj 61 | -------------------------------------------------------------------------------- /pythonect/internal/_ordereddict.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012-2013, Itzik Kotler 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # 14 | # * Neither the name of the author nor the names of its contributors may 15 | # be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 22 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | try: 30 | 31 | # Python 2.7+ 32 | 33 | from collections import OrderedDict 34 | 35 | except Exception as e: 36 | 37 | # Python2.6 38 | 39 | from ordereddict import OrderedDict 40 | -------------------------------------------------------------------------------- /pythonect/internal/lang.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012-2013, Itzik Kotler 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # 14 | # * Neither the name of the author nor the names of its contributors may 15 | # be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 22 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | """This file content extends the Python's __builtins__""" 30 | 31 | import __builtin__ 32 | 33 | 34 | # Functions 35 | 36 | def print_(object_): 37 | 38 | import threading 39 | 40 | import sys 41 | 42 | # START OF CRITICAL SECTION 43 | 44 | __builtin__.__GIL__.acquire() 45 | 46 | try: 47 | 48 | import multiprocessing 49 | 50 | if multiprocessing.current_process().name == 'MainProcess': 51 | 52 | sys.stdout.write("<%s:%s> : %s\n" % (multiprocessing.current_process().name, threading.current_thread().name, object_)) 53 | 54 | else: 55 | 56 | sys.stdout.write(" : %s\n" % (multiprocessing.current_process().pid, object_)) 57 | 58 | except ImportError: 59 | 60 | sys.stdout.write("<%s> : %s\n" % (threading.current_thread().name, object_)) 61 | 62 | sys.stdout.flush() 63 | 64 | __builtin__.__GIL__.release() 65 | 66 | # END OF CRITICAL SECTION 67 | 68 | return None 69 | 70 | 71 | # Classes 72 | 73 | class expr(object): 74 | 75 | def __init__(self, expression): 76 | 77 | self.__expression = expression 78 | 79 | def __repr__(self): 80 | 81 | return self.__expression 82 | 83 | def __call__(self, globals_, locals_): 84 | 85 | import eval 86 | 87 | return eval.eval(self.__expression, globals_, locals_) 88 | 89 | 90 | class remotefunction(object): 91 | 92 | def __init__(self, name, host, *args, **kwargs): 93 | 94 | self.__name = name.strip() 95 | 96 | self.__host = host 97 | 98 | self.__remote_fcn = None 99 | 100 | self.__remote_fcn_args = args 101 | 102 | self.__remote_fcn_kwargs = kwargs 103 | 104 | self.__locals = None 105 | 106 | self.__globals = None 107 | 108 | def __repr__(self): 109 | 110 | if self.__remote_fcn: 111 | 112 | return repr(self.__remote_fcn) 113 | 114 | else: 115 | 116 | return "%s(%s,%s)@%s" % (self.__name, self.__remote_fcn_args, self.__remote_fcn_kwargs, self.__host) 117 | 118 | def evaluate_host(self, globals_, locals_): 119 | 120 | self.__locals = locals_ 121 | 122 | self.__globals = globals_ 123 | 124 | try: 125 | 126 | self.__host = eval(self.__host, globals_, locals_) 127 | 128 | except SyntaxError as e: 129 | 130 | # CONST? As it is 131 | 132 | pass 133 | 134 | def __call__(self, *args, **kwargs): 135 | 136 | call_args = args 137 | 138 | call_kwargs = kwargs 139 | 140 | if self.__remote_fcn_args or self.__remote_fcn_kwargs: 141 | 142 | call_args = self.__remote_fcn_args 143 | 144 | call_kwargs = self.__remote_fcn_kwargs 145 | 146 | # Pseudo Protocol 147 | 148 | if self.__host is None or self.__host.startswith('None'): 149 | 150 | self.__remote_fcn = eval(self.__name, self.__globals, self.__locals) 151 | 152 | # Python XML-RPC 153 | 154 | elif self.__host.startswith('xmlrpc://'): 155 | 156 | import xmlrpclib 157 | 158 | # xmlrpc:// = http://, xmlrpcs:// = https:// 159 | 160 | remote_srv = xmlrpclib.ServerProxy(self.__host.replace('xmlrpc', 'http', 1)) 161 | 162 | self.__remote_fcn = getattr(remote_srv, self.__name) 163 | 164 | return self.__remote_fcn(*call_args, **call_kwargs) 165 | -------------------------------------------------------------------------------- /pythonect/internal/parsers/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012-2013, Itzik Kotler 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # 14 | # * Neither the name of the author nor the names of its contributors may 15 | # be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 22 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | import glob 30 | import os 31 | import importlib 32 | import sys 33 | 34 | 35 | class PythonectInputFileFormatParser(object): 36 | 37 | def parse(self, source): 38 | 39 | raise NotImplementedError("Subclasses should implement this!") 40 | 41 | 42 | def get_parsers(parsers_path): 43 | 44 | parsers = {} 45 | 46 | # For each directory in parsers path 47 | 48 | for component_directory in parsers_path.split(os.path.pathsep): 49 | 50 | # Add component directory to path 51 | 52 | sys.path.insert(0, component_directory) 53 | 54 | components_list = glob.glob(component_directory + '/*.py') 55 | 56 | # For each *.py file in directory 57 | 58 | for component_file in components_list: 59 | 60 | component = os.path.splitext(os.path.basename(component_file))[0] 61 | 62 | try: 63 | 64 | current_module = importlib.import_module(component) 65 | 66 | for name in dir(current_module): 67 | 68 | if not name.startswith('_'): 69 | 70 | obj = getattr(current_module, name) 71 | 72 | try: 73 | 74 | if obj != PythonectInputFileFormatParser and issubclass(obj, PythonectInputFileFormatParser): 75 | 76 | for ext in obj.FILE_EXTS: 77 | 78 | parsers[ext] = obj() 79 | 80 | except TypeError: 81 | 82 | pass 83 | 84 | except Exception: 85 | 86 | pass 87 | 88 | return parsers 89 | -------------------------------------------------------------------------------- /pythonect/internal/parsers/dia.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012-2013, Itzik Kotler 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # 14 | # * Neither the name of the author nor the names of its contributors may 15 | # be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 22 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | import networkx 30 | import xml.sax 31 | import gzip 32 | import StringIO 33 | 34 | 35 | # Local imports 36 | 37 | import pythonect.internal.parsers 38 | import pythonect.internal._graph 39 | 40 | 41 | # Tested on dia-bin 0.97.2 42 | 43 | class _DiaParser(xml.sax.handler.ContentHandler): 44 | 45 | def __init__(self): 46 | 47 | xml.sax.handler.ContentHandler.__init__(self) 48 | 49 | self._in_dia_object = False 50 | 51 | self._in_dia_string = False 52 | 53 | self.node_name = None 54 | 55 | self.edge = [] 56 | 57 | self.node_value = {'OPERATOR': '->'} 58 | 59 | def startElement(self, name, attrs): 60 | 61 | if self._in_dia_object: 62 | 63 | if name == 'dia:string': 64 | 65 | self._in_dia_string = True 66 | 67 | if name == 'dia:connection': 68 | 69 | self.edge.append(attrs['to']) 70 | 71 | if len(self.edge) == 2: 72 | 73 | self._graph.add_edge(self.edge[0], self.edge[1]) 74 | 75 | self.edge = [] 76 | 77 | else: 78 | 79 | if name == 'dia:object': 80 | 81 | if self._graph is None: 82 | 83 | self._graph = pythonect.internal._graph.Graph() 84 | 85 | self._in_dia_object = True 86 | 87 | self.node_name = attrs['id'] 88 | 89 | self._graph.add_node(self.node_name) 90 | 91 | def endElement(self, name): 92 | 93 | if name == 'dia:object': 94 | 95 | self._graph.node[self.node_name].update(self.node_value) 96 | 97 | if self._graph.node[self.node_name].get('CONTENT', None) is None: 98 | 99 | self._graph.remove_node(self.node_name) 100 | 101 | self.node_name = None 102 | 103 | self.node_value = {'OPERATOR': '->'} 104 | 105 | self._in_dia_object = False 106 | 107 | if name == 'dia:string': 108 | 109 | self._in_dia_string = False 110 | 111 | def characters(self, content): 112 | 113 | if self._in_dia_string: 114 | 115 | # Strip leading and trailing '#' 116 | 117 | self.node_value.update({'CONTENT': content[1:-1]}) 118 | 119 | def endDocument(self): 120 | 121 | if self._graph is None: 122 | 123 | self._graph = pythonect.internal._graph.Graph() 124 | 125 | def parse(self, source): 126 | 127 | self._graph = None 128 | 129 | try: 130 | 131 | # Compressed? 132 | 133 | try: 134 | 135 | # UTF-8? 136 | 137 | try: 138 | 139 | source = source.encode('utf-8') 140 | 141 | except UnicodeDecodeError: 142 | 143 | pass 144 | 145 | source = gzip.GzipFile(fileobj=StringIO.StringIO(source), mode='rb').read() 146 | 147 | except IOError: 148 | 149 | pass 150 | 151 | xml.sax.parseString(source, self) 152 | 153 | # Delete 'OPERATOR' from tail nodes 154 | 155 | tail_nodes = [node for node, degree in self._graph.out_degree().items() if degree == 0] 156 | 157 | for node in tail_nodes: 158 | 159 | del self._graph.node[node]['OPERATOR'] 160 | 161 | except xml.sax._exceptions.SAXParseException: 162 | 163 | pass 164 | 165 | return self._graph 166 | 167 | 168 | class PythonectDiaParser(pythonect.internal.parsers.PythonectInputFileFormatParser): 169 | 170 | def parse(self, source): 171 | 172 | graph = _DiaParser().parse(source) 173 | 174 | return graph 175 | 176 | FILE_EXTS = ['dia'] 177 | -------------------------------------------------------------------------------- /pythonect/internal/parsers/p2y.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012-2013, Itzik Kotler 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # 14 | # * Neither the name of the author nor the names of its contributors may 15 | # be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 22 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | import networkx 30 | import tokenize 31 | import StringIO 32 | import re 33 | 34 | 35 | # Local imports 36 | 37 | import pythonect.internal.parsers 38 | import pythonect.internal._graph 39 | 40 | 41 | def _create_and_link(graph, new_node_name, new_node_kwargs): 42 | 43 | # Add Node 44 | 45 | graph.add_node(new_node_name, **new_node_kwargs) 46 | 47 | # Connect Any Tail Nodes to Node 48 | 49 | for tail_node in [node for node, degree in graph.out_degree().items() if degree == 0 and node != new_node_name]: 50 | 51 | graph.add_edge(tail_node, new_node_name) 52 | 53 | 54 | def _make_graph(code, node_prefix='', depth=0, in_brackets=False): 55 | 56 | meaningful_graph = False 57 | 58 | update_tail_nodes_operator = False 59 | 60 | create_node = False 61 | 62 | node_value = "" 63 | 64 | edge_value = "" 65 | 66 | previous_tokval = None 67 | 68 | in_literal_scope = 0 69 | 70 | graph = pythonect.internal._graph.Graph() 71 | 72 | tokens = tokenize.generate_tokens(StringIO.StringIO(code).readline) 73 | 74 | token_pos = -1 75 | 76 | seek = 0 77 | 78 | in_statement = False 79 | 80 | in_url = False 81 | 82 | graphs = [] 83 | 84 | for toknum, tokval, (srow, scol), (erow, ecol), line in tokens: 85 | 86 | extra_string = '' 87 | 88 | # print "[Row %d, Col %d]: Received (#%d) %s" % (srow, scol, toknum, tokval) 89 | 90 | # Skip over INDENT/NL 91 | 92 | if toknum in [tokenize.INDENT, tokenize.NL, tokenize.NEWLINE, tokenize.DEDENT]: 93 | 94 | continue 95 | 96 | token_pos = token_pos + 1 97 | 98 | # Fast Forward 99 | 100 | if seek > 0: 101 | 102 | seek = seek - 1 103 | 104 | continue 105 | 106 | if not in_url and ((toknum == tokenize.NAME and tokval != '_') or tokval == ':'): 107 | 108 | extra_string = ' ' 109 | 110 | node_value = node_value + tokval + extra_string 111 | 112 | # Within '(....)' or '{...}' ? 113 | 114 | if in_literal_scope: 115 | 116 | if tokval in ')}' or in_statement and tokval in ']': 117 | 118 | in_literal_scope = in_literal_scope - 1 119 | 120 | # i.e. ({ ... }) 121 | 122 | if tokval in '({' or in_statement and tokval in '[': 123 | 124 | in_literal_scope = in_literal_scope + 1 125 | 126 | continue 127 | 128 | # Start of '@xmlrpc://...' ? 129 | 130 | if tokval == '@': 131 | 132 | in_url = True 133 | 134 | continue 135 | 136 | # Not Within '@xmlrpc://...' ... 137 | 138 | if not in_url: 139 | 140 | # Start of Python Statement Scope? 141 | 142 | if tokval in [':', '=']: 143 | 144 | in_statement = True 145 | 146 | continue 147 | 148 | # Start of '(...)' or '{...}' ? 149 | 150 | if tokval in '({' or in_statement and tokval in '[': 151 | 152 | in_literal_scope = in_literal_scope + 1 153 | 154 | continue 155 | 156 | # '->' Operator? 157 | 158 | if tokval == '>' and previous_tokval == '-': 159 | 160 | meaningful_graph = True 161 | 162 | in_statement = False 163 | 164 | in_url = False 165 | 166 | edge_value = '->' 167 | 168 | # Trim trailing '->' 169 | 170 | node_value = node_value[:-2] 171 | 172 | if node_value: 173 | 174 | create_node = True 175 | 176 | else: 177 | 178 | update_tail_nodes_operator = True 179 | 180 | # '|' Operator? 181 | 182 | if tokval == '|': 183 | 184 | meaningful_graph = True 185 | 186 | in_url = False 187 | 188 | in_statement = False 189 | 190 | edge_value = '|' 191 | 192 | # Trim trailing '|' 193 | 194 | node_value = node_value[:-1] 195 | 196 | if node_value: 197 | 198 | create_node = True 199 | 200 | else: 201 | 202 | update_tail_nodes_operator = True 203 | 204 | # New Node? 205 | 206 | if create_node: 207 | 208 | create_node = False 209 | 210 | _create_and_link(graph, node_prefix + str(len(graphs)) + "." + str(len(graph.nodes())), {'CONTENT': node_value, 'OPERATOR': edge_value, 'TOKEN_TYPE': tokval}) 211 | 212 | node_value = "" 213 | 214 | # Update Tail Node(s) Operator? (i.e. [ A , B ] -> C ; -> is of 'A' and 'B') 215 | 216 | if update_tail_nodes_operator: 217 | 218 | update_tail_nodes_operator = False 219 | 220 | for tail_node in [node for node, degree in graph.out_degree().items() if degree == 0]: 221 | 222 | graph.node[tail_node].update({'OPERATOR': edge_value}) 223 | 224 | # Start of '[...]' 225 | 226 | if node_value == tokval == '[': 227 | 228 | # Supress '[' 229 | 230 | node_value = node_value[:-1] 231 | 232 | # Start New Graph 233 | 234 | (next_token_pos, ret_graph) = _make_graph(code[scol + 1:], node_prefix + str(len(graphs)) + "." + str(len(graph.nodes())) + '.', depth + 1, True) 235 | 236 | # ['1 2 3'.split()] 237 | 238 | if len(ret_graph.nodes()) == 1 and ret_graph.node[ret_graph.nodes()[0]]['CONTENT'].find('(') != -1: 239 | 240 | # AS IS 241 | 242 | node_value = '[' + ret_graph.node[ret_graph.nodes()[0]]['CONTENT'] + ']' 243 | 244 | # [1], [string.split], or [1, 2, 3, ..] 245 | 246 | else: 247 | 248 | in_nodes = [node for node, degree in ret_graph.in_degree().items() if degree == 0] 249 | 250 | out_nodes = [node for node, degree in graph.out_degree().items() if degree == 0] 251 | 252 | graph = networkx.union(graph, ret_graph) 253 | 254 | for in_node in in_nodes: 255 | 256 | for out_node in out_nodes: 257 | 258 | graph.add_edge(out_node, in_node) 259 | 260 | seek = next_token_pos 261 | 262 | if tokval == ']' and in_brackets: 263 | 264 | in_brackets = False 265 | 266 | # Trim trailing ']' 267 | 268 | node_value = node_value[:-1] 269 | 270 | if not meaningful_graph and not node_value: 271 | 272 | node_value = '[[' + ','.join([graph.node[node]['CONTENT'] for node in sorted(graph.nodes())]) + ']]' 273 | 274 | graph.clear() 275 | 276 | # Flush node_value 277 | 278 | if node_value: 279 | 280 | _create_and_link(graph, node_prefix + str(len(graphs)) + "." + str(len(graph.nodes())), {'CONTENT': node_value, 'TOKEN_TYPE': tokval}) 281 | 282 | node_value = "" 283 | 284 | # Merge graphs? (i.e. [ A -> B , C -> D ]) 285 | 286 | if graphs: 287 | 288 | graphs = [graph] + graphs 289 | 290 | graph = reduce(networkx.union, graphs) 291 | 292 | # End Graph 293 | 294 | return (token_pos + 1, graph) 295 | 296 | if tokval == ',': 297 | 298 | meaningful_graph = True 299 | 300 | # Flush node_value 301 | 302 | # Trim trailing ',' 303 | 304 | node_value = node_value[:-1] 305 | 306 | _create_and_link(graph, node_prefix + str(len(graphs)) + "." + str(len(graph.nodes())), {'CONTENT': node_value, 'TOKEN_TYPE': tokval}) 307 | 308 | node_value = "" 309 | 310 | # Replace graph 311 | 312 | graphs.append(graph) 313 | 314 | # New graph 315 | 316 | graph = pythonect.internal._graph.Graph() 317 | 318 | previous_tokval = tokval 319 | 320 | # EOF 321 | 322 | if node_value: 323 | 324 | _create_and_link(graph, node_prefix + str(len(graphs)) + "." + str(len(graph.nodes())), {'CONTENT': node_value, 'TOKEN_TYPE': tokval}) 325 | 326 | node_value = "" 327 | 328 | # Merge graphs? (i.e. [ A -> B , C -> D ]) 329 | 330 | if graphs: 331 | 332 | graphs = [graph] + graphs 333 | 334 | graph = reduce(networkx.union, graphs) 335 | 336 | # End Graph 337 | 338 | return (token_pos + 1, graph) 339 | 340 | 341 | class PythonectScriptParser(pythonect.internal.parsers.PythonectInputFileFormatParser): 342 | 343 | def parse(self, source): 344 | 345 | graph = None 346 | 347 | try: 348 | 349 | (ignored_ret, graph) = _make_graph(re.sub('#.*', '', source.strip())) 350 | 351 | except tokenize.TokenError: 352 | 353 | pass 354 | 355 | return graph 356 | 357 | FILE_EXTS = ['p2y'] 358 | -------------------------------------------------------------------------------- /pythonect/internal/parsers/test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikotler/pythonect/ac597f9c37b119bafc0e41e67e8a21f02e435752/pythonect/internal/parsers/test/__init__.py -------------------------------------------------------------------------------- /pythonect/internal/parsers/test/dia_examples/even_expr_atom_op_expr.dia: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | #A4# 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | #1# 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | #2# 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /pythonect/internal/parsers/test/dia_examples/expr_atom.dia: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | #A4# 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | #1# 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /pythonect/internal/parsers/test/dia_examples/odd_expr_atom_op_expr.dia: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | #A4# 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | #1# 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | #2# 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | #3# 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | -------------------------------------------------------------------------------- /pythonect/internal/parsers/test/dia_examples/odd_expr_atom_op_expr_gzipped.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikotler/pythonect/ac597f9c37b119bafc0e41e67e8a21f02e435752/pythonect/internal/parsers/test/dia_examples/odd_expr_atom_op_expr_gzipped.dia -------------------------------------------------------------------------------- /pythonect/internal/parsers/test/dia_examples/program_empty.dia: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | #A4# 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /pythonect/internal/parsers/test/dia_examples/program_expr_list.dia: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | #A4# 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | #1# 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | #2# 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /pythonect/internal/parsers/test/test_dia.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012-2013, Itzik Kotler 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # 14 | # * Neither the name of the author nor the names of its contributors may 15 | # be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 22 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | import unittest 30 | import networkx 31 | import os 32 | 33 | 34 | # Local imports 35 | 36 | import pythonect.internal.parsers.dia 37 | 38 | 39 | # Consts 40 | 41 | BASE_DIR = os.path.join(os.path.dirname(__file__), os.pardir) 42 | TEST_DIR = os.path.dirname(os.path.abspath(__file__)) 43 | 44 | 45 | class TestPythonectDiaParser(unittest.TestCase): 46 | 47 | def test_program_empty(self): 48 | 49 | g = networkx.DiGraph() 50 | 51 | self.assertEqual(len(pythonect.internal.parsers.dia.PythonectDiaParser().parse(open(TEST_DIR + os.sep + 'dia_examples' + os.sep + 'program_empty.dia').read()).nodes()) == len(g.nodes()), True) 52 | 53 | def test_expr_atom(self): 54 | 55 | g = networkx.DiGraph() 56 | 57 | g.add_node('1') 58 | 59 | self.assertEqual(len(pythonect.internal.parsers.dia.PythonectDiaParser().parse(open(TEST_DIR + os.sep + 'dia_examples' + os.sep + 'expr_atom.dia').read()).nodes()) == len(g.nodes()), True) 60 | 61 | def test_even_expr_atom_op_expr(self): 62 | 63 | g = networkx.DiGraph() 64 | 65 | g.add_node('1') 66 | 67 | g.add_node('2') 68 | 69 | g.add_edge('1', '2') 70 | 71 | self.assertEqual(len(pythonect.internal.parsers.dia.PythonectDiaParser().parse(open(TEST_DIR + os.sep + 'dia_examples' + os.sep + 'even_expr_atom_op_expr.dia').read()).edges()) == len(g.edges()), True) 72 | 73 | def test_odd_expr_atom_op_expr(self): 74 | 75 | g = networkx.DiGraph() 76 | 77 | g.add_node('1') 78 | 79 | g.add_node('2') 80 | 81 | g.add_node('3') 82 | 83 | g.add_edge('1', '2') 84 | 85 | g.add_edge('2', '3') 86 | 87 | self.assertEqual(len(pythonect.internal.parsers.dia.PythonectDiaParser().parse(open(TEST_DIR + os.sep + 'dia_examples' + os.sep + 'odd_expr_atom_op_expr.dia').read()).edges()) == len(g.edges()), True) 88 | 89 | def test_gzipped_odd_expr_atom_op_expr(self): 90 | 91 | g = networkx.DiGraph() 92 | 93 | g.add_node('1') 94 | 95 | g.add_node('2') 96 | 97 | g.add_node('3') 98 | 99 | g.add_edge('1', '2') 100 | 101 | g.add_edge('2', '3') 102 | 103 | self.assertEqual(len(pythonect.internal.parsers.dia.PythonectDiaParser().parse(open(TEST_DIR + os.sep + 'dia_examples' + os.sep + 'odd_expr_atom_op_expr_gzipped.dia').read()).edges()) == len(g.edges()), True) 104 | 105 | def test_program_expr_list(self): 106 | 107 | g = networkx.DiGraph() 108 | 109 | g.add_node('1') 110 | 111 | g.add_node('2') 112 | 113 | self.assertEqual(len(pythonect.internal.parsers.dia.PythonectDiaParser().parse(open(TEST_DIR + os.sep + 'dia_examples' + os.sep + 'program_expr_list.dia').read()).nodes()) == len(g.nodes()), True) 114 | -------------------------------------------------------------------------------- /pythonect/internal/parsers/test/test_p2y.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012-2013, Itzik Kotler 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # 14 | # * Neither the name of the author nor the names of its contributors may 15 | # be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 22 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | import unittest 30 | import networkx 31 | 32 | 33 | # Local imports 34 | 35 | import pythonect.internal.parsers.p2y 36 | 37 | 38 | class TestPythonectScriptParser(unittest.TestCase): 39 | 40 | def test_program_empty(self): 41 | 42 | g = networkx.DiGraph() 43 | 44 | self.assertEqual(len(pythonect.internal.parsers.p2y.PythonectScriptParser().parse('').nodes()) == len(g.nodes()), True) 45 | 46 | def test_expr_atom(self): 47 | 48 | g = networkx.DiGraph() 49 | 50 | g.add_node('1') 51 | 52 | self.assertEqual(len(pythonect.internal.parsers.p2y.PythonectScriptParser().parse('1').nodes()) == len(g.nodes()), True) 53 | 54 | def test_shebang_line_with_even_expr_atom_op_expr(self): 55 | 56 | g = networkx.DiGraph() 57 | 58 | g.add_node('1') 59 | 60 | g.add_node('2') 61 | 62 | g.add_edge('1', '2') 63 | 64 | self.assertEqual(len(pythonect.internal.parsers.p2y.PythonectScriptParser().parse('#! /usr/bin/env pythonect\n1 -> 1').edges()) == len(g.edges()), True) 65 | 66 | def test_even_expr_atom_op_expr(self): 67 | 68 | g = networkx.DiGraph() 69 | 70 | g.add_node('1') 71 | 72 | g.add_node('2') 73 | 74 | g.add_edge('1', '2') 75 | 76 | self.assertEqual(len(pythonect.internal.parsers.p2y.PythonectScriptParser().parse('1 -> 1').edges()) == len(g.edges()), True) 77 | 78 | def test_odd_expr_atom_op_expr(self): 79 | 80 | g = networkx.DiGraph() 81 | 82 | g.add_node('1') 83 | 84 | g.add_node('2') 85 | 86 | g.add_node('3') 87 | 88 | g.add_edge('1', '2') 89 | 90 | g.add_edge('2', '3') 91 | 92 | self.assertEqual(len(pythonect.internal.parsers.p2y.PythonectScriptParser().parse('1 -> 1 -> 1').edges()) == len(g.edges()), True) 93 | 94 | def test_program_expr_list(self): 95 | 96 | g = networkx.DiGraph() 97 | 98 | g.add_node('1') 99 | 100 | g.add_node('2') 101 | 102 | self.assertEqual(len(pythonect.internal.parsers.p2y.PythonectScriptParser().parse('1 , 2').nodes()) == len(g.nodes()), True) 103 | -------------------------------------------------------------------------------- /pythonect/internal/parsers/test/test_vdx07.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012-2013, Itzik Kotler 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # 14 | # * Neither the name of the author nor the names of its contributors may 15 | # be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 22 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | import unittest 30 | import networkx 31 | import os 32 | 33 | 34 | # Local imports 35 | 36 | import pythonect.internal.parsers.vdx 37 | 38 | 39 | # Consts 40 | 41 | BASE_DIR = os.path.join(os.path.dirname(__file__), os.pardir) 42 | TEST_DIR = os.path.dirname(os.path.abspath(__file__)) 43 | 44 | 45 | class TestPythonectVisioParser(unittest.TestCase): 46 | 47 | def test_program_empty(self): 48 | 49 | g = networkx.DiGraph() 50 | 51 | self.assertEqual(len(pythonect.internal.parsers.vdx.PythonectVisioParser().parse(open(TEST_DIR + os.sep + 'vdx07_examples' + os.sep + 'program_empty.vdx').read()).nodes()) == len(g.nodes()), True) 52 | 53 | def test_expr_atom(self): 54 | 55 | g = networkx.DiGraph() 56 | 57 | g.add_node('1') 58 | 59 | self.assertEqual(len(pythonect.internal.parsers.vdx.PythonectVisioParser().parse(open(TEST_DIR + os.sep + 'vdx07_examples' + os.sep + 'expr_atom.vdx').read()).nodes()) == len(g.nodes()), True) 60 | 61 | def test_even_expr_atom_op_expr(self): 62 | 63 | g = networkx.DiGraph() 64 | 65 | g.add_node('1') 66 | 67 | g.add_node('2') 68 | 69 | g.add_edge('1', '2') 70 | 71 | self.assertEqual(len(pythonect.internal.parsers.vdx.PythonectVisioParser().parse(open(TEST_DIR + os.sep + 'vdx07_examples' + os.sep + 'even_expr_atom_op_expr.vdx').read()).edges()) == len(g.edges()), True) 72 | 73 | def test_odd_expr_atom_op_expr(self): 74 | 75 | g = networkx.DiGraph() 76 | 77 | g.add_node('1') 78 | 79 | g.add_node('2') 80 | 81 | g.add_node('3') 82 | 83 | g.add_edge('1', '2') 84 | 85 | g.add_edge('2', '3') 86 | 87 | self.assertEqual(len(pythonect.internal.parsers.vdx.PythonectVisioParser().parse(open(TEST_DIR + os.sep + 'vdx07_examples' + os.sep + 'odd_expr_atom_op_expr.vdx').read()).edges()) == len(g.edges()), True) 88 | 89 | def test_program_expr_list(self): 90 | 91 | g = networkx.DiGraph() 92 | 93 | g.add_node('1') 94 | 95 | g.add_node('2') 96 | 97 | self.assertEqual(len(pythonect.internal.parsers.vdx.PythonectVisioParser().parse(open(TEST_DIR + os.sep + 'vdx07_examples' + os.sep + 'program_expr_list.vdx').read()).nodes()) == len(g.nodes()), True) 98 | -------------------------------------------------------------------------------- /pythonect/internal/parsers/test/test_vdx10.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012-2013, Itzik Kotler 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # 14 | # * Neither the name of the author nor the names of its contributors may 15 | # be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 22 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | import unittest 30 | import networkx 31 | import os 32 | 33 | 34 | # Local imports 35 | 36 | import pythonect.internal.parsers.vdx 37 | 38 | 39 | # Consts 40 | 41 | BASE_DIR = os.path.join(os.path.dirname(__file__), os.pardir) 42 | TEST_DIR = os.path.dirname(os.path.abspath(__file__)) 43 | 44 | 45 | class TestPythonectVisioParser(unittest.TestCase): 46 | 47 | def test_program_empty(self): 48 | 49 | g = networkx.DiGraph() 50 | 51 | self.assertEqual(len(pythonect.internal.parsers.vdx.PythonectVisioParser().parse(open(TEST_DIR + os.sep + 'vdx10_examples' + os.sep + 'program_empty.vdx').read()).nodes()) == len(g.nodes()), True) 52 | 53 | def test_expr_atom(self): 54 | 55 | g = networkx.DiGraph() 56 | 57 | g.add_node('1') 58 | 59 | self.assertEqual(len(pythonect.internal.parsers.vdx.PythonectVisioParser().parse(open(TEST_DIR + os.sep + 'vdx10_examples' + os.sep + 'expr_atom.vdx').read()).nodes()) == len(g.nodes()), True) 60 | 61 | def test_even_expr_atom_op_expr(self): 62 | 63 | g = networkx.DiGraph() 64 | 65 | g.add_node('1') 66 | 67 | g.add_node('2') 68 | 69 | g.add_edge('1', '2') 70 | 71 | self.assertEqual(len(pythonect.internal.parsers.vdx.PythonectVisioParser().parse(open(TEST_DIR + os.sep + 'vdx10_examples' + os.sep + 'even_expr_atom_op_expr.vdx').read()).edges()) == len(g.edges()), True) 72 | 73 | def test_odd_expr_atom_op_expr(self): 74 | 75 | g = networkx.DiGraph() 76 | 77 | g.add_node('1') 78 | 79 | g.add_node('2') 80 | 81 | g.add_node('3') 82 | 83 | g.add_edge('1', '2') 84 | 85 | g.add_edge('2', '3') 86 | 87 | self.assertEqual(len(pythonect.internal.parsers.vdx.PythonectVisioParser().parse(open(TEST_DIR + os.sep + 'vdx10_examples' + os.sep + 'odd_expr_atom_op_expr.vdx').read()).edges()) == len(g.edges()), True) 88 | 89 | def test_program_expr_list(self): 90 | 91 | g = networkx.DiGraph() 92 | 93 | g.add_node('1') 94 | 95 | g.add_node('2') 96 | 97 | self.assertEqual(len(pythonect.internal.parsers.vdx.PythonectVisioParser().parse(open(TEST_DIR + os.sep + 'vdx10_examples' + os.sep + 'program_expr_list.vdx').read()).nodes()) == len(g.nodes()), True) 98 | -------------------------------------------------------------------------------- /pythonect/internal/parsers/vdx.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012-2013, Itzik Kotler 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # 14 | # * Neither the name of the author nor the names of its contributors may 15 | # be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 22 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | import networkx 30 | import xml.sax 31 | 32 | 33 | # Local imports 34 | 35 | import pythonect.internal.parsers 36 | 37 | 38 | # Tested on dia-bin 0.97.2 39 | 40 | class _VisioParser(xml.sax.handler.ContentHandler): 41 | 42 | def __init__(self): 43 | 44 | xml.sax.handler.ContentHandler.__init__(self) 45 | 46 | self._in_shape_object = False 47 | 48 | self._in_text = False 49 | 50 | self.node_name = None 51 | 52 | self.edge = [] 53 | 54 | self.node_value = {'OPERATOR': '->'} 55 | 56 | def startElement(self, name, attrs): 57 | 58 | if self._in_shape_object: 59 | 60 | if name == 'Text': 61 | 62 | self._in_text = True 63 | 64 | else: 65 | 66 | if name == 'Connect': 67 | 68 | self.edge.append(attrs['ToSheet']) 69 | 70 | if len(self.edge) == 2: 71 | 72 | self._graph.add_edge(self.edge[0], self.edge[1]) 73 | 74 | self.edge = [] 75 | 76 | if name == 'Shape': 77 | 78 | if self._graph is None: 79 | 80 | self._graph = networkx.DiGraph() 81 | 82 | self._in_shape_object = True 83 | 84 | self.node_name = attrs['ID'] 85 | 86 | self._graph.add_node(self.node_name) 87 | 88 | def endElement(self, name): 89 | 90 | if name == 'Shape': 91 | 92 | self._graph.node[self.node_name].update(self.node_value) 93 | 94 | if self._graph.node[self.node_name].get('CONTENT', None) is None: 95 | 96 | self._graph.remove_node(self.node_name) 97 | 98 | self.node_name = None 99 | 100 | self.node_value = {'OPERATOR': '->'} 101 | 102 | self._in_shape_object = False 103 | 104 | if name == 'Text': 105 | 106 | self._in_text = False 107 | 108 | def characters(self, content): 109 | 110 | if self._in_text: 111 | 112 | if self.node_value.get('CONTENT', None) is None: 113 | 114 | if isinstance(content, unicode): 115 | 116 | # TODO: This is a hack to replace u'\u201cHello, world\u201d to "Hello, world" 117 | 118 | content = content.encode('ascii', 'replace').replace('?', '"') 119 | 120 | self.node_value.update({'CONTENT': content}) 121 | 122 | def endDocument(self): 123 | 124 | if self._graph is None: 125 | 126 | self._graph = networkx.DiGraph() 127 | 128 | def parse(self, source): 129 | 130 | self._graph = None 131 | 132 | try: 133 | 134 | xml.sax.parseString(source, self) 135 | 136 | # Delete 'OPERATOR' from tail nodes 137 | 138 | tail_nodes = [node for node, degree in self._graph.out_degree().items() if degree == 0] 139 | 140 | for node in tail_nodes: 141 | 142 | del self._graph.node[node]['OPERATOR'] 143 | 144 | except xml.sax._exceptions.SAXParseException: 145 | 146 | pass 147 | 148 | return self._graph 149 | 150 | 151 | class PythonectVisioParser(pythonect.internal.parsers.PythonectInputFileFormatParser): 152 | 153 | def parse(self, source): 154 | 155 | graph = _VisioParser().parse(source) 156 | 157 | return graph 158 | 159 | FILE_EXTS = ['vdx'] 160 | -------------------------------------------------------------------------------- /pythonect/test/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012-2013, Itzik Kotler 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # 14 | # * Neither the name of the author nor the names of its contributors may 15 | # be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 22 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /pythonect/test/eval_tst_gen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2012-2013, Itzik Kotler 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # 11 | # * Redistributions in binary form must reproduce the above copyright 12 | # notice, this list of conditions and the following disclaimer in the 13 | # documentation and/or other materials provided with the distribution. 14 | # 15 | # * Neither the name of the author nor the names of its contributors may 16 | # be used to endorse or promote products derived from this software without 17 | # specific prior written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 23 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | import sys 31 | import os 32 | 33 | 34 | # Add `internal` directory (i.e. ../) to sys.path 35 | 36 | sys.path.append(os.path.abspath('../')) 37 | 38 | 39 | # Local imports 40 | 41 | import internal.eval 42 | 43 | 44 | ATOM = [ 45 | ('literal_underscore', '_'), 46 | ('literal_true_expr', '1 == 1'), 47 | ('literal_false_expr', '1 != 1'), 48 | ('literal_int', '1'), 49 | ('literal_float', '0.5'), 50 | ('literal_string', '\"foobar\"'), 51 | ('literal_true', 'True'), 52 | ('literal_false', 'False'), 53 | ('literal_none', 'None'), 54 | ('import_stmt', 'import math'), 55 | ('assignment_stmt', 'x = 0'), 56 | ('python_expr', '1+1'), 57 | ('pythonect_expr', '$[1->1]') 58 | ] 59 | 60 | 61 | OPERATOR = [ 62 | (None, None), 63 | ('comma', ','), 64 | ('async', '->'), 65 | ('sync', '|') 66 | ] 67 | 68 | 69 | # ATOM OPERATOR ATOM OPERATOR ATOM 70 | 71 | MAX_DEPTH = 5 72 | 73 | 74 | def __type_wrapper(data): 75 | 76 | if isinstance(data, str): 77 | 78 | return '\'%s\'' % (data) 79 | 80 | return data 81 | 82 | 83 | def pythonect_expr_generator(name=[], expr=[], depth=0): 84 | 85 | for (type, value) in ATOM: 86 | 87 | name.append(type) 88 | 89 | expr.append(value) 90 | 91 | # ATOM AND OPERATOR 92 | 93 | if (depth + 2 < MAX_DEPTH): 94 | 95 | for (type, value) in OPERATOR: 96 | 97 | if type is None: 98 | 99 | yield (name, expr) 100 | 101 | continue 102 | 103 | name.append(type) 104 | 105 | expr.append(value) 106 | 107 | for (return_type, return_value) in pythonect_expr_generator([], [], depth + 2): 108 | 109 | yield(name + return_type, expr + return_value) 110 | 111 | name.pop() 112 | 113 | expr.pop() 114 | 115 | # ATOM 116 | 117 | else: 118 | 119 | yield (name, expr) 120 | 121 | name.pop() 122 | 123 | expr.pop() 124 | 125 | 126 | def main(): 127 | 128 | for (name, expr) in pythonect_expr_generator(): 129 | 130 | try: 131 | 132 | print '\tdef test_%s(self):\n\n\t\tself.assertEqual( internal.eval.eval(\'%s\', {}, {}) , %s )\n' % \ 133 | ('_'.join(name), ' '.join(expr), __type_wrapper(internal.eval.eval(' '.join(expr), {}, {}))) 134 | 135 | except Exception as e: 136 | 137 | print "%s raises Exception %s" % (' '.join(expr), str(e)) 138 | 139 | if __name__ == "__main__": 140 | 141 | sys.exit(main()) 142 | -------------------------------------------------------------------------------- /pythonect/test/test_xmlrpc_app.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012-2013, Itzik Kotler 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # * Redistributions of source code must retain the above copyright 8 | # notice, this list of conditions and the following disclaimer. 9 | # 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # 14 | # * Neither the name of the author nor the names of its contributors may 15 | # be used to endorse or promote products derived from this software without 16 | # specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 22 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | from SimpleXMLRPCServer import SimpleXMLRPCServer 30 | from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler 31 | 32 | from select import select 33 | import unittest 34 | import socket 35 | import threading 36 | import os 37 | import sys 38 | 39 | 40 | # Local imports 41 | 42 | import pythonect 43 | 44 | 45 | ## {{{ http://code.activestate.com/recipes/520583/ (r1) 46 | class XMLRPCServer(SimpleXMLRPCServer): 47 | """ 48 | A variant of SimpleXMLRPCServer that can be stopped. 49 | """ 50 | def __init__(self, *args, **kwargs): 51 | SimpleXMLRPCServer.__init__(self, *args, **kwargs) 52 | self.logRequests = 0 53 | self.closed = False 54 | 55 | def serve_until_stopped(self): 56 | self.socket.setblocking(0) 57 | while not self.closed: 58 | self.handle_request() 59 | 60 | def stop_serving(self): 61 | self.closed = True 62 | 63 | def get_request(self): 64 | inputObjects = [] 65 | while not inputObjects and not self.closed: 66 | inputObjects, outputObjects, errorObjects = \ 67 | select([self.socket], [], [], 0.2) 68 | try: 69 | return self.socket.accept() 70 | except socket.error: 71 | raise 72 | ## end of http://code.activestate.com/recipes/520583/ }}} 73 | 74 | 75 | # Global Variables 76 | 77 | thread = None 78 | server = None 79 | 80 | 81 | def setUpModule(): 82 | 83 | global thread 84 | 85 | global server 86 | 87 | # Restrict to a particular path. 88 | 89 | class RequestHandler(SimpleXMLRPCRequestHandler): 90 | rpc_paths = ('/RPC2',) 91 | 92 | # Create a stopable XMLRPC Server 93 | 94 | server = XMLRPCServer(("localhost", 8000), requestHandler=RequestHandler) 95 | 96 | server.register_introspection_functions() 97 | 98 | # Register a simple function 99 | def inc_function(x): 100 | return x + 1 101 | 102 | server.register_function(inc_function, 'inc') 103 | 104 | print "*** Starting XMLRPCServer on localhost:8000 with registered function \'inc\'" 105 | 106 | # Run the server's main loop (in a thread) 107 | 108 | thread = threading.Thread(target=server.serve_until_stopped) 109 | 110 | thread.start() 111 | 112 | server = server 113 | 114 | 115 | def tearDownModule(): 116 | 117 | print "*** Shutting down XMLRPCServer (localhost:8000)" 118 | 119 | server.stop_serving() 120 | 121 | thread.join(None) 122 | 123 | 124 | class TestPythonectRemoting(unittest.TestCase): 125 | 126 | def test_int_async_remotefunction_const_host(self): 127 | 128 | self.assertEqual(pythonect.eval('1 -> inc@xmlrpc://localhost:8000', {}, {}), 2) 129 | 130 | def test_int_sync_remotefunction_const_host(self): 131 | 132 | self.assertEqual(pythonect.eval('1 | inc@xmlrpc://localhost:8000', {}, {}), 2) 133 | 134 | def test_int_async_remotefunction_with_args_const_host(self): 135 | 136 | self.assertEqual(pythonect.eval('1 -> inc(1)@xmlrpc://localhost:8000', {}, {}), 2) 137 | 138 | def test_int_sync_remotefunction_with_args_const_host(self): 139 | 140 | self.assertEqual(pythonect.eval('1 | inc(1)@xmlrpc://localhost:8000', {}, {}), 2) 141 | 142 | def test_int_async_remotefunction_literal_expr(self): 143 | 144 | self.assertEqual(pythonect.eval('1 -> inc@"xmlrpc://" + "localhost:8000"', {}, {}), 2) 145 | 146 | def test_int_sync_remotefunction_literal_expr(self): 147 | 148 | self.assertEqual(pythonect.eval('1 | inc@"xmlrpc://" + "localhost:8000"', {}, {}), 2) 149 | 150 | def test_int_async_remotefunction_with_args_literal_expr(self): 151 | 152 | self.assertEqual(pythonect.eval('1 -> inc(1)@"xmlrpc://" + "localhost:8000"', {}, {}), 2) 153 | 154 | def test_int_sync_remotefunction_with_args_literal_expr(self): 155 | 156 | self.assertEqual(pythonect.eval('1 | inc(1)@"xmlrpc://" + "localhost:8000"', {}, {}), 2) 157 | 158 | def test_int_async_remotefunction_expr(self): 159 | 160 | self.assertEqual(pythonect.eval('[host = "localhost"] -> 1 -> inc@"xmlrpc://" + host + ":8000"', {}, {}), 2) 161 | 162 | def test_int_sync_remotefunction_expr(self): 163 | 164 | self.assertEqual(pythonect.eval('[host = "localhost"] -> 1 | inc@"xmlrpc://" + host + ":8000"', {}, {}), 2) 165 | 166 | def test_int_async_remotefunction_with_args_expr(self): 167 | 168 | self.assertEqual(pythonect.eval('[host = "localhost"] -> 1 -> inc(1)@"xmlrpc://" + host + ":8000"', {}, {}), 2) 169 | 170 | def test_int_sync_remotefunction_with_args_expr(self): 171 | 172 | self.assertEqual(pythonect.eval('[host = "localhost"] -> 1 | inc(1)@"xmlrpc://" + host + ":8000"', {}, {}), 2) 173 | 174 | # Standard XML-RPC does not support **kwargs 175 | 176 | # def test_int_async_remotefunction_with_kwargs(self): 177 | # self.assertEqual( pythonect.eval('1 -> inc(x=1)@xmlrpc://localhost:8000', {}, {}) , 2 ) 178 | 179 | # def test_int_sync_remotefunction_with_kwargs(self): 180 | # self.assertEqual( pythonect.eval('1 | inc(x=1)@xmlrpc://localhost:8000', {}, {}) , 2 ) 181 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [nosetests] 2 | verbosity=2 3 | detailed-errors=1 4 | with-id=1 5 | stop=1 6 | 7 | [pep8] 8 | ignore=E501 9 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2012-2013, Itzik Kotler 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # 11 | # * Redistributions in binary form must reproduce the above copyright 12 | # notice, this list of conditions and the following disclaimer in the 13 | # documentation and/or other materials provided with the distribution. 14 | # 15 | # * Neither the name of the author nor the names of its contributors may 16 | # be used to endorse or promote products derived from this software without 17 | # specific prior written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 23 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | try: 31 | 32 | import setuptools 33 | 34 | except ImportError: 35 | 36 | from distribute_setup import use_setuptools 37 | 38 | use_setuptools() 39 | 40 | import setuptools 41 | 42 | 43 | import sys 44 | 45 | 46 | # Functions 47 | 48 | def _safe_get_version(): 49 | 50 | tmp_globals = {} 51 | 52 | # Importing _version.py may raise ImportError due to missing dependencies 53 | 54 | execfile('pythonect/_version.py', tmp_globals) 55 | 56 | version = tmp_globals['__version__'] 57 | 58 | return version 59 | 60 | 61 | # Entry Point 62 | 63 | if __name__ == "__main__": 64 | 65 | dependencies = ['networkx>=1.7', 'nose'] 66 | 67 | major, minor = sys.version_info[:2] 68 | 69 | python_27 = (major > 2 or (major == 2 and minor >= 7)) 70 | 71 | # < Python 2.7 ? 72 | 73 | if not python_27: 74 | 75 | # Python 2.6 76 | 77 | dependencies = dependencies + ['ordereddict>=1.1', 'argparse', 'importlib', 'unittest2'] 78 | 79 | setupconf = dict( 80 | name='Pythonect', 81 | version=_safe_get_version(), 82 | author='Itzik Kotler', 83 | author_email='xorninja@gmail.com', 84 | url='http://www.pythonect.org/', 85 | license='BSD', 86 | description='A general-purpose dataflow programming language based on Python, written in Python', 87 | 88 | long_description=open('README.rst').read(), 89 | scripts=['bin/pythonect'], 90 | data_files=[('', ['LICENSE'])], 91 | packages=setuptools.find_packages(), 92 | 93 | classifiers=[ 94 | 'Development Status :: 4 - Beta', 95 | 'License :: OSI Approved :: BSD License', 96 | 'Operating System :: OS Independent', 97 | 'Programming Language :: Python', 98 | 'Programming Language :: Python :: 2.7', 99 | 'Programming Language :: Python :: 2.6', 100 | ], 101 | 102 | install_requires=dependencies, 103 | 104 | test_suite='nose.collector', 105 | 106 | zip_safe=False 107 | ) 108 | 109 | setuptools.setup(**setupconf) 110 | --------------------------------------------------------------------------------