├── .gitignore ├── AUTHORS ├── LICENSE ├── Makefile ├── README.rst ├── ast.txt ├── doc ├── Makefile ├── conf.py ├── index.rst └── src │ ├── builtins.rst │ ├── examples.rst │ └── py2js.rst ├── examples ├── Makefile ├── gol.py ├── triangulation.py └── ui.py ├── library ├── 05-init.js ├── 10-builtin.js ├── 20-type-iter.js ├── 21-type-slice.js ├── 22-type-tuple.js ├── 23-type-list.js ├── 24-type-dict.js ├── 25-type-str.js ├── 40-python-functions.js ├── 41-python-classes.js ├── 50-object.js ├── 60-sprintf.js ├── 70-module.js ├── 71-ie-fix.js ├── 72-notimplemented.js ├── 73-module-sys.js ├── 74-module-path.js ├── 75-module-builtins.js └── 76-module-init.js ├── py2js ├── __init__.py ├── decorator.py └── formater.py ├── pyjs.py ├── pylint.conf ├── run_tests.py ├── test_results.txt ├── tests ├── algorithms │ ├── sqrt.py │ └── triangulation.py ├── basic │ ├── assign_slice.py │ ├── augassign.py │ ├── augassign2.py │ ├── binaryops.py │ ├── break.py │ ├── class.py │ ├── class2.py │ ├── class3.py │ ├── class4.py │ ├── class5.py │ ├── class6.py │ ├── closure.py │ ├── continue.py │ ├── default.py │ ├── del_array.py │ ├── del_attr.py │ ├── del_dict.py │ ├── del_global.py │ ├── del_local.py │ ├── del_slice.py │ ├── dictionary.py │ ├── dictionary2.py │ ├── docstring.py │ ├── embedding.py │ ├── fib.py │ ├── float2int.py │ ├── for_in.py │ ├── for_step.py │ ├── for_xrange.py │ ├── generator.py │ ├── globalvar.py │ ├── helloworld.py │ ├── ifs.py │ ├── keys.py │ ├── kwargs.py │ ├── kwargs2.py │ ├── lambda.py │ ├── list.py │ ├── list2.py │ ├── listcomp2.py │ ├── literals.py │ ├── logicalops.py │ ├── loops.py │ ├── multiassign.py │ ├── nestedclass.py │ ├── none.py │ ├── oo.py │ ├── oo_attributes.py │ ├── oo_diamond.py │ ├── oo_inherit.py │ ├── oo_inherit2.py │ ├── oo_inherit3.py │ ├── oo_inherit_simple.py │ ├── oo_inherit_simple2.py │ ├── oo_static_inherit.py │ ├── oo_super.py │ ├── pass.py │ ├── print.py │ ├── raise.py │ ├── scope.py │ ├── str1.py │ ├── sumcomp.py │ ├── super.py │ ├── trueorfalse.py │ ├── try.py │ ├── tuple.py │ ├── tuple2.py │ ├── valueerror.py │ ├── vargs.py │ ├── vars.py │ ├── vars2.py │ └── while.py ├── convert_tabs_spaces.py ├── errors │ ├── decorator.py │ ├── modules │ │ └── __init__.py │ └── py_collision.py ├── functions │ ├── and.py │ ├── append.py │ ├── aug.py │ ├── bitand.py │ ├── bitor.py │ ├── bitxor.py │ ├── divfloor.py │ ├── float.py │ ├── floatdiv.py │ ├── gtge.py │ ├── in.py │ ├── int.py │ ├── isinstance.py │ ├── len.py │ ├── lshift.py │ ├── ltle.py │ ├── ne.py │ ├── or.py │ ├── pop.py │ ├── rshift.py │ ├── sort.py │ ├── sort23.py │ ├── sort_cmp.py │ ├── str.py │ ├── ubitcomp.py │ ├── uminus.py │ └── uplus.py ├── libraries │ └── xmlwriter.py ├── lists │ ├── extend.py │ ├── filter.py │ ├── in.py │ ├── insert.py │ ├── map.py │ ├── max.py │ ├── min.py │ ├── reduce.py │ ├── reverse.py │ ├── subclass.py │ ├── subclass2.py │ ├── subclass3.py │ ├── sum.py │ ├── sum2.py │ ├── xrange.py │ └── zip.py ├── modules │ ├── classname.py │ ├── from_import.py │ ├── import.py │ ├── import_alias.py │ ├── import_class.py │ ├── import_diamond.py │ ├── import_global.py │ ├── import_multi.py │ ├── imported │ │ ├── __init__.py │ │ ├── alias_classes.py │ │ ├── alias_fns.py │ │ ├── modulea.py │ │ ├── moduleb.py │ │ ├── modulec.py │ │ ├── moduled.py │ │ └── submodules │ │ │ ├── __init__.py │ │ │ └── submodulea.py │ ├── module_name.py │ ├── modules │ │ ├── __init__.py │ │ ├── diamond1.py │ │ ├── diamond2.py │ │ ├── klasses.py │ │ ├── moda.py │ │ ├── module_name.py │ │ └── submodules │ │ │ ├── __init__.py │ │ │ ├── diamondbase.py │ │ │ └── module_name.py │ └── rng.py ├── strings │ ├── count.py │ ├── find.py │ ├── join.py │ ├── lstrip0.py │ ├── lstrip1.py │ ├── replace.py │ ├── rfind.py │ ├── rstrip0.py │ ├── rstrip1.py │ ├── split.py │ ├── splitlines.py │ ├── string_format_combined_simple.py │ ├── string_format_d.py │ ├── string_format_d_simple.py │ ├── string_format_efg.py │ ├── string_format_f_simple.py │ ├── string_format_i.py │ ├── string_format_o.py │ ├── string_format_s_simple.py │ ├── string_format_u.py │ ├── string_format_x.py │ ├── strings_in_strings.py │ ├── strip.py │ ├── strip1.py │ ├── ulcase.py │ ├── ulcase1.py │ └── zipstring.py ├── test_builtins.js └── test_compile_js.py └── testtools ├── __init__.py ├── env_tests.py ├── known_to_fail.py ├── runner.py ├── tests.py ├── util.py └── writer.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[co] 2 | .*.swp 3 | py-builtins.js 4 | tests/*/*.out 5 | tests/*/*.diff 6 | tests/*/*.err 7 | tests/*/*.py.js 8 | tests/*.err 9 | tests/*.out 10 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Original developer: 2 | 3 | Mateusz Paprocki 4 | 5 | Currently active developers: 6 | 7 | Christian Iversen (compiler design, semantics, interfacing) 8 | Samuel Ytterbrink (deep python magic, interfacing) 9 | Ondrej Certik (compiler design, standard library) 10 | 11 | People who contributed by sending at least one patch: 12 | 13 | Baniel 14 | Jonathan Fine 15 | Pablo Angulo 16 | 17 | Tests were taken from js4py written by Jonathan Fine. 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010, 2011 Qsnake Development Team 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | all: 3 | @cat library/*.js > py-builtins.js 4 | $(MAKE) -C examples generate 5 | 6 | clean: 7 | @rm -fv py-builtins.js library/*~ *.pyc 8 | $(MAKE) -C examples clean 9 | 10 | examples: 11 | $(MAKE) -C examples generate -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | py2js 2 | ===== 3 | 4 | Python to JavaScript translator. 5 | 6 | Webpage: http://qsnake.github.com/py2js/html/ 7 | 8 | Mailinglist: http://groups.google.com/group/py2js 9 | 10 | Installation 11 | ------------ 12 | 13 | Execute the following:: 14 | 15 | git clone git://github.com/qsnake/py2js.git 16 | cd py2js 17 | make 18 | 19 | Examples 20 | -------- 21 | 22 | firefox examples/gol.html 23 | 24 | And the game of life should show in the browser. If it doesn't, it's a bug. You 25 | can generate that file using 26 | 27 | python examples/gol.py > examples/gol.html 28 | 29 | Tests 30 | ----- 31 | 32 | ./run_tests.py 33 | 34 | Will run all tests, that are supposed to work. If any test fails, it's a bug. 35 | 36 | ./run_tests.py -a 37 | 38 | Will run all tests including those that are known to fail (currently). It 39 | should be understandable from the output. 40 | 41 | ./run_tests.py -x 42 | or 43 | ./run_tests.py --no-error 44 | 45 | Will run tests but ignore if an error is raised by the test. This is not 46 | affecting the error generated by the test files in the tests directory. 47 | 48 | For more flags then described here 49 | 50 | ./run_tests.py -h 51 | 52 | 53 | License 54 | ------- 55 | 56 | MIT, see the LICENSE file for exact details. 57 | -------------------------------------------------------------------------------- /ast.txt: -------------------------------------------------------------------------------- 1 | Python grammar, the AST classes contain those arguments as properties. 2 | 3 | module Python version "$Revision: 62047 $" 4 | { 5 | mod = Module(stmt* body) 6 | | Interactive(stmt* body) 7 | | Expression(expr body) 8 | 9 | stmt = FunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list) 10 | | ClassDef(identifier name, expr* bases, stmt* body, expr *decorator_list) 11 | | Return(expr? value) 12 | 13 | | Delete(expr* targets) 14 | | Assign(expr* targets, expr value) 15 | | AugAssign(expr target, operator op, expr value) 16 | 17 | | Print(expr? dest, expr* values, int nl) 18 | 19 | | For(expr target, expr iter, stmt* body, stmt* orelse) 20 | | While(expr test, stmt* body, stmt* orelse) 21 | | If(expr test, stmt* body, stmt* orelse) 22 | | With(expr context_expr, expr? optional_vars, stmt* body) 23 | 24 | | Raise(expr? type, expr? inst, expr? tback) 25 | | TryExcept(stmt* body, excepthandler* handlers, stmt* orelse) 26 | | TryFinally(stmt* body, stmt* finalbody) 27 | | Assert(expr test, expr? msg) 28 | 29 | | Import(alias* names) 30 | | ImportFrom(identifier module, alias* names, int? level) 31 | 32 | | Exec(expr body, expr? globals, expr? locals) 33 | 34 | | Global(identifier* names) 35 | | Expr(expr value) 36 | | Pass | Break | Continue 37 | 38 | expr = BoolOp(boolop op, expr* values) 39 | | BinOp(expr left, operator op, expr right) 40 | | UnaryOp(unaryop op, expr operand) 41 | | Lambda(arguments args, expr body) 42 | | IfExp(expr test, expr body, expr orelse) 43 | | Dict(expr* keys, expr* values) 44 | | ListComp(expr elt, comprehension* generators) 45 | | GeneratorExp(expr elt, comprehension* generators) 46 | | Yield(expr? value) 47 | | Compare(expr left, cmpop* ops, expr* comparators) 48 | | Call(expr func, expr* args, keyword* keywords, expr? starargs, expr? kwargs) 49 | | Repr(expr value) 50 | | Num(object n) 51 | | Str(string s) 52 | 53 | | Attribute(expr value, identifier attr, expr_context ctx) 54 | | Subscript(expr value, slice slice, expr_context ctx) 55 | | Name(identifier id, expr_context ctx) 56 | | List(expr* elts, expr_context ctx) 57 | | Tuple(expr* elts, expr_context ctx) 58 | 59 | expr_context = Load | Store | Del | AugLoad | AugStore | Param 60 | 61 | slice = Ellipsis 62 | | Slice(expr? lower, expr? upper, expr? step) 63 | | ExtSlice(slice* dims) 64 | | Index(expr value) 65 | 66 | boolop = And | Or 67 | 68 | operator = Add | Sub | Mult | Div | Mod | Pow | LShift | RShift | BitOr | BitXor | BitAnd | FloorDiv 69 | 70 | unaryop = Invert | Not | UAdd | USub 71 | 72 | cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn 73 | 74 | comprehension = (expr target, expr iter, expr* ifs) 75 | 76 | excepthandler = ExceptHandler(expr? type, expr? name, stmt* body) 77 | 78 | arguments = (expr* args, identifier? vararg, identifier? kwarg, expr* defaults) 79 | keyword = (identifier arg, expr value) 80 | 81 | alias = (identifier name, identifier? asname) 82 | } 83 | -------------------------------------------------------------------------------- /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 | # Internal variables. 11 | PAPEROPT_a4 = -D latex_paper_size=a4 12 | PAPEROPT_letter = -D latex_paper_size=letter 13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 14 | 15 | .PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest 16 | 17 | help: 18 | @echo "Please use \`make ' where is one of" 19 | @echo " html to make standalone HTML files" 20 | @echo " dirhtml to make HTML files named index.html in directories" 21 | @echo " pickle to make pickle files" 22 | @echo " json to make JSON files" 23 | @echo " htmlhelp to make HTML files and a HTML help project" 24 | @echo " qthelp to make HTML files and a qthelp project" 25 | @echo " devhelp to make HTML files and a Devhelp project" 26 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 27 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 28 | @echo " changes to make an overview of all changed/added/deprecated items" 29 | @echo " linkcheck to check all external links for integrity" 30 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 31 | 32 | clean: 33 | -rm -rf $(BUILDDIR)/* 34 | 35 | html: 36 | @mkdir -p _static 37 | @cp -r ../examples _static/ 38 | @cp -r ../math.js _static/ 39 | @cp -r ../py-builtins.js _static/ 40 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 41 | @echo 42 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 43 | 44 | dirhtml: 45 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 46 | @echo 47 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 48 | 49 | pickle: 50 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 51 | @echo 52 | @echo "Build finished; now you can process the pickle files." 53 | 54 | json: 55 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 56 | @echo 57 | @echo "Build finished; now you can process the JSON files." 58 | 59 | htmlhelp: 60 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 61 | @echo 62 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 63 | ".hhp project file in $(BUILDDIR)/htmlhelp." 64 | 65 | qthelp: 66 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 67 | @echo 68 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 69 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 70 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/py2js.qhcp" 71 | @echo "To view the help file:" 72 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/py2js.qhc" 73 | 74 | devhelp: 75 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) _build/devhelp 76 | @echo 77 | @echo "Build finished." 78 | @echo "To view the help file:" 79 | @echo "# mkdir -p $$HOME/.local/share/devhelp/py2js" 80 | @echo "# ln -s _build/devhelp $$HOME/.local/share/devhelp/py2js" 81 | @echo "# devhelp" 82 | 83 | latex: 84 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 85 | @echo 86 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 87 | @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ 88 | "run these through (pdf)latex." 89 | 90 | latexpdf: latex 91 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex 92 | @echo "Running LaTeX files through pdflatex..." 93 | make -C _build/latex all-pdf 94 | @echo "pdflatex finished; the PDF files are in _build/latex." 95 | 96 | changes: 97 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 98 | @echo 99 | @echo "The overview file is in $(BUILDDIR)/changes." 100 | 101 | linkcheck: 102 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 103 | @echo 104 | @echo "Link check complete; look for any errors in the above output " \ 105 | "or in $(BUILDDIR)/linkcheck/output.txt." 106 | 107 | doctest: 108 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 109 | @echo "Testing of doctests in the sources finished, look at the " \ 110 | "results in $(BUILDDIR)/doctest/output.txt." 111 | -------------------------------------------------------------------------------- /doc/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # py2js documentation build configuration file, created by 4 | # sphinx-quickstart on Tue Apr 27 13:05:04 2010. 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.append(os.path.abspath('.')) 20 | 21 | # -- General configuration ----------------------------------------------------- 22 | 23 | # Add any Sphinx extension module names here, as strings. They can be extensions 24 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 25 | extensions = [] 26 | 27 | # Add any paths that contain templates here, relative to this directory. 28 | templates_path = ['_templates'] 29 | 30 | # The suffix of source filenames. 31 | source_suffix = '.rst' 32 | 33 | # The encoding of source files. 34 | #source_encoding = 'utf-8-sig' 35 | 36 | # The master toctree document. 37 | master_doc = 'index' 38 | 39 | # General information about the project. 40 | project = u'py2js' 41 | copyright = u'2010, hp-FEM group at UNR' 42 | 43 | # The version info for the project you're documenting, acts as replacement for 44 | # |version| and |release|, also used in various other places throughout the 45 | # built documents. 46 | # 47 | # The short X.Y version. 48 | version = '0.1' 49 | # The full version, including alpha/beta/rc tags. 50 | release = '0.1' 51 | 52 | # The language for content autogenerated by Sphinx. Refer to documentation 53 | # for a list of supported languages. 54 | #language = None 55 | 56 | # There are two options for replacing |today|: either, you set today to some 57 | # non-false value, then it is used: 58 | #today = '' 59 | # Else, today_fmt is used as the format for a strftime call. 60 | #today_fmt = '%B %d, %Y' 61 | 62 | # List of documents that shouldn't be included in the build. 63 | #unused_docs = [] 64 | 65 | # List of directories, relative to source directory, that shouldn't be searched 66 | # for source files. 67 | exclude_trees = ['_build'] 68 | 69 | # The reST default role (used for this markup: `text`) to use for all documents. 70 | #default_role = None 71 | 72 | # If true, '()' will be appended to :func: etc. cross-reference text. 73 | #add_function_parentheses = True 74 | 75 | # If true, the current module name will be prepended to all description 76 | # unit titles (such as .. function::). 77 | #add_module_names = True 78 | 79 | # If true, sectionauthor and moduleauthor directives will be shown in the 80 | # output. They are ignored by default. 81 | #show_authors = False 82 | 83 | # The name of the Pygments (syntax highlighting) style to use. 84 | pygments_style = 'sphinx' 85 | 86 | # A list of ignored prefixes for module index sorting. 87 | #modindex_common_prefix = [] 88 | 89 | 90 | # -- Options for HTML output --------------------------------------------------- 91 | 92 | # The theme to use for HTML and HTML Help pages. Major themes that come with 93 | # Sphinx are currently 'default' and 'sphinxdoc'. 94 | html_theme = 'default' 95 | 96 | # Theme options are theme-specific and customize the look and feel of a theme 97 | # further. For a list of options available for each theme, see the 98 | # documentation. 99 | #html_theme_options = {} 100 | 101 | # Add any paths that contain custom themes here, relative to this directory. 102 | #html_theme_path = [] 103 | 104 | # The name for this set of Sphinx documents. If None, it defaults to 105 | # " v documentation". 106 | #html_title = None 107 | 108 | # A shorter title for the navigation bar. Default is the same as html_title. 109 | #html_short_title = None 110 | 111 | # The name of an image file (relative to this directory) to place at the top 112 | # of the sidebar. 113 | #html_logo = None 114 | 115 | # The name of an image file (within the static path) to use as favicon of the 116 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 117 | # pixels large. 118 | #html_favicon = None 119 | 120 | # Add any paths that contain custom static files (such as style sheets) here, 121 | # relative to this directory. They are copied after the builtin static files, 122 | # so a file named "default.css" will overwrite the builtin "default.css". 123 | html_static_path = ['_static'] 124 | 125 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 126 | # using the given strftime format. 127 | #html_last_updated_fmt = '%b %d, %Y' 128 | 129 | # If true, SmartyPants will be used to convert quotes and dashes to 130 | # typographically correct entities. 131 | #html_use_smartypants = True 132 | 133 | # Custom sidebar templates, maps document names to template names. 134 | #html_sidebars = {} 135 | 136 | # Additional templates that should be rendered to pages, maps page names to 137 | # template names. 138 | #html_additional_pages = {} 139 | 140 | # If false, no module index is generated. 141 | #html_use_modindex = True 142 | 143 | # If false, no index is generated. 144 | #html_use_index = True 145 | 146 | # If true, the index is split into individual pages for each letter. 147 | #html_split_index = False 148 | 149 | # If true, links to the reST sources are added to the pages. 150 | #html_show_sourcelink = True 151 | 152 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 153 | #html_show_sphinx = True 154 | 155 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 156 | #html_show_copyright = True 157 | 158 | # If true, an OpenSearch description file will be output, and all pages will 159 | # contain a tag referring to it. The value of this option must be the 160 | # base URL from which the finished HTML is served. 161 | #html_use_opensearch = '' 162 | 163 | # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). 164 | #html_file_suffix = '' 165 | 166 | # Output file base name for HTML help builder. 167 | htmlhelp_basename = 'py2jsdoc' 168 | 169 | 170 | # -- Options for LaTeX output -------------------------------------------------- 171 | 172 | # The paper size ('letter' or 'a4'). 173 | #latex_paper_size = 'letter' 174 | 175 | # The font size ('10pt', '11pt' or '12pt'). 176 | #latex_font_size = '10pt' 177 | 178 | # Grouping the document tree into LaTeX files. List of tuples 179 | # (source start file, target name, title, author, documentclass [howto/manual]). 180 | latex_documents = [ 181 | ('index', 'py2js.tex', u'py2js Documentation', 182 | u'hp-FEM group at UNR', 'manual'), 183 | ] 184 | 185 | # The name of an image file (relative to this directory) to place at the top of 186 | # the title page. 187 | #latex_logo = None 188 | 189 | # For "manual" documents, if this is true, then toplevel headings are parts, 190 | # not chapters. 191 | #latex_use_parts = False 192 | 193 | # Additional stuff for the LaTeX preamble. 194 | #latex_preamble = '' 195 | 196 | # Documents to append as an appendix to all manuals. 197 | #latex_appendices = [] 198 | 199 | # If false, no module index is generated. 200 | #latex_use_modindex = True 201 | -------------------------------------------------------------------------------- /doc/index.rst: -------------------------------------------------------------------------------- 1 | .. py2js documentation master file, created by 2 | sphinx-quickstart on Tue Apr 27 13:05:04 2010. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to py2js 7 | ================ 8 | 9 | py2js is a Python to JavaScript translator. 10 | 11 | **Webpage**: http://qsnake.github.com/py2js/html/ 12 | 13 | **Download** using git: ``git clone git://github.com/qsnake/py2js.git``, 14 | other options: http://github.com/qsnake/py2js 15 | 16 | **Mailinglist**: http://groups.google.com/group/py2js 17 | 18 | Get it touch with us on the mailinglist if you have any questions. 19 | 20 | It consists of two parts. The ``builtins.js`` library, which is a standalone 21 | JavaScript library implementing Python types and builtin functions, and the 22 | ``py2js.py`` script that translates almost any Python code into JavaScript (that 23 | depends on ``builtins.js``). 24 | 25 | Contents: 26 | 27 | .. toctree:: 28 | :maxdepth: 2 29 | 30 | src/builtins.rst 31 | src/py2js.rst 32 | src/examples.rst 33 | 34 | Indices and tables 35 | ================== 36 | 37 | * :ref:`genindex` 38 | * :ref:`modindex` 39 | * :ref:`search` 40 | 41 | -------------------------------------------------------------------------------- /doc/src/builtins.rst: -------------------------------------------------------------------------------- 1 | Builtins.js 2 | =========== 3 | 4 | JavaScript library that implements Python types and Python builtin functions. 5 | 6 | The goal of this library is to implement all Python builtin types and functions 7 | as a small standalone JS library, that anyone can use in their JS projects. 8 | Using this library, one can write a JS code that behaves pretty much like 9 | Python (e.g. for loops using iterators, lists, dicts, slicing, ...), except of 10 | course that sometimes you need to use quite verbose syntax, e.g. 11 | ``f.__getitem__(slice(1, null))`` instead of ``f[1:]``. It is then a matter of 12 | a good Python to JavaScript translator to convert the Python syntax to JS with 13 | the help of this library. 14 | 15 | See the file `tests/test_builtins.js `_ for 16 | thorough tests that you can use as examples how to use the library. Below you 17 | can find a brief documentation with a few examples to get some idea what this 18 | library can do for you. 19 | 20 | Types 21 | ----- 22 | 23 | It currently implements the following types: 24 | 25 | **iter** 26 | :: 27 | 28 | js> f = list([1, 4, 3]) 29 | [1, 4, 3] 30 | js> i = iter(f) 31 | 32 | js> i.next() 33 | 1 34 | js> i.next() 35 | 4 36 | js> i.next() 37 | 3 38 | js> i.next() 39 | uncaught exception: StopIteration: no more items 40 | 41 | 42 | **tuple** 43 | :: 44 | 45 | js> f = tuple([1, 4, 3]) 46 | (1, 4, 3) 47 | js> f 48 | (1, 4, 3) 49 | 50 | **list** 51 | :: 52 | 53 | js> f = list([1, 4, 3]) 54 | [1, 4, 3] 55 | js> f.append(4) 56 | js> f 57 | [1, 4, 3, 4] 58 | 59 | **dict** 60 | :: 61 | 62 | js> f = dict({1: 4, 3: 5}) 63 | {1: 4, 3: 5} 64 | js> f.__getitem__(3) 65 | 5 66 | 67 | 68 | **slice** 69 | :: 70 | 71 | js> f = tuple([1, 4, 3]) 72 | (1, 4, 3) 73 | js> f.__getitem__(slice(1, null)) 74 | (4, 3) 75 | js> f.__getitem__(slice(0, 1)) 76 | (1,) 77 | 78 | 79 | 80 | Builtin functions 81 | ----------------- 82 | 83 | * assert 84 | * hasattr 85 | * getattr 86 | * setattr 87 | * hash 88 | * len 89 | * str 90 | * range 91 | * map 92 | * zip 93 | * isinstance 94 | * float 95 | 96 | Examples:: 97 | 98 | js> range(5) 99 | [0, 1, 2, 3, 4] 100 | js> len(range(5)) 101 | 5 102 | js> hash(tuple([1, 3])) 103 | 221750528 104 | 105 | 106 | Exceptions 107 | ---------- 108 | 109 | * NotImplementedError 110 | * ZeroDivisionError 111 | * AssertionError 112 | * AttributeError 113 | * RuntimeError 114 | * ImportError 115 | * TypeError 116 | * ValueError 117 | * NameError 118 | * IndexError 119 | * KeyError 120 | * StopIteration 121 | 122 | -------------------------------------------------------------------------------- /doc/src/examples.rst: -------------------------------------------------------------------------------- 1 | Examples 2 | ======== 3 | 4 | All examples are in the ``examples`` directory. 5 | 6 | Game of Life 7 | ------------ 8 | 9 | **online**: `gol.html <../_static/examples/gol.html>`_ 10 | **source**: `examples/gol.py `_ 11 | 12 | Uses the HTML5 Canvas to draw the game of life. 13 | 14 | ExtJS Demo 15 | ---------- 16 | 17 | **online**: `ui.html <../_static/examples/ui.html>`_ 18 | **source**: `examples/ui.py `_ 19 | 20 | Shows how to call the `ExtJS `_ library from Python to 21 | create a nice GUI in the browser. 22 | 23 | Triangulation Demo 24 | ------------------ 25 | 26 | **online**: `triangulation.html <../_static/examples/triangulation.html>`_ 27 | **source**: `examples/triangulation.py `_ 28 | 29 | Shows a real life example of a Python script that triangulates a domain, 30 | together with a simple canvas plotting. You can see that the Python output and 31 | JavaScript output is identical. 32 | -------------------------------------------------------------------------------- /doc/src/py2js.rst: -------------------------------------------------------------------------------- 1 | py2js.py 2 | ======== 3 | 4 | Python to JavaScript translator. 5 | 6 | It uses Python ASTs to take any Python code and translate it to JS. The 7 | generated JS code depends on the ``builtins.js`` library. Thanks to this clean 8 | separation, the py2js itself is a very small script, that does a fairly direct 9 | translation from Python to JS. 10 | 11 | The best way to learn py2js is to take some example from the examples/ 12 | directory and start modifying it to do what you need. 13 | 14 | Usage 15 | ----- 16 | 17 | You can use it by decorating any function/class by the ``JavaScript`` 18 | decorator, e.g. this code:: 19 | 20 | @JavaScript 21 | class TestClass(object): 22 | def __init__(self): 23 | alert('TestClass created') 24 | self.reset() 25 | 26 | def reset(self): 27 | self.value = 0 28 | 29 | def inc(self): 30 | alert(self.value) 31 | self.value += 1 32 | 33 | print str(TestClass) 34 | 35 | prints:: 36 | 37 | function TestClass() { 38 | return new _TestClass(); 39 | } 40 | function _TestClass() { 41 | this.__init__(); 42 | } 43 | _TestClass.__name__ = 'TestClass' 44 | _TestClass.prototype.__class__ = _TestClass 45 | _TestClass.prototype.__init__ = function() { 46 | alert("TestClass created"); 47 | this.reset(); 48 | } 49 | _TestClass.prototype.reset = function() { 50 | this.value = 0; 51 | } 52 | _TestClass.prototype.inc = function() { 53 | alert(this.value); 54 | this.value += 1; 55 | } 56 | 57 | Alternatively, an equivalent way is to use ``JavaScript()`` as a function:: 58 | 59 | class TestClass(object): 60 | def __init__(self): 61 | alert('TestClass created') 62 | self.reset() 63 | 64 | def reset(self): 65 | self.value = 0 66 | 67 | def inc(self): 68 | alert(self.value) 69 | self.value += 1 70 | 71 | print str(JavaScript(TestClass)) 72 | 73 | Another Example 74 | --------------- 75 | 76 | The goal of py2js is to eventually translate any Python code. For example:: 77 | 78 | @JavaScript 79 | def test(): 80 | a = [] 81 | for i in range(10): 82 | a.append(i) 83 | return a[3:] 84 | 85 | translates into:: 86 | 87 | function test() { 88 | a = list([]); 89 | var __dummy0__ = iter(range(10)); 90 | var __dummy1__ = false; 91 | while (1) { 92 | var i; 93 | try { 94 | i = __dummy0__.next(); 95 | } catch (__dummy2__) { 96 | if (isinstance(__dummy2__, py.StopIteration)) { 97 | __dummy1__ = true; 98 | break; 99 | } else { 100 | throw __dummy2__; 101 | } 102 | } 103 | a.append(i); 104 | } 105 | return a.__getitem__(slice(3, null)); 106 | } 107 | -------------------------------------------------------------------------------- /examples/Makefile: -------------------------------------------------------------------------------- 1 | 2 | generate: gol.html triangulation.html ui.html 3 | 4 | %.html: %.py 5 | @echo "Compiling [$<]" 6 | @PYTHONPATH=.. python $< > $@ 7 | 8 | clean: 9 | @rm -fv *.html *~ 10 | -------------------------------------------------------------------------------- /examples/gol.py: -------------------------------------------------------------------------------- 1 | from py2js.decorator import JavaScript 2 | 3 | @JavaScript 4 | def StartGoL(): 5 | setattr(window, 'gol', GoL()) 6 | 7 | @JavaScript 8 | class GoL(object): 9 | def __init__(self): 10 | self.width = 75 11 | self.height = 75 12 | self.canvas = document.getElementById(js('canvas')).getContext(js('2d')) 13 | setattr(self.canvas, 'fillStyle', js('rgb(0, 0, 0)')) 14 | self.grid = list(range(self.width*self.height)) 15 | for i in range(self.width*self.height): 16 | self.grid[i] = Math.random() > 0.5 17 | setInterval(js('window.gol.iter()'), 250) 18 | self.draw() 19 | def get(self, x, y): 20 | return self.grid[((x + self.width) % self.width) + ((y + self.height) % self.height) * self.width] 21 | def iter(self): 22 | toDie = [] 23 | toLive = [] 24 | for x in range(0, self.width): 25 | for y in range(0, self.height): 26 | count = 0 27 | if self.get(x-1, y-1): 28 | count += 1 29 | if self.get(x, y-1): 30 | count += 1 31 | if self.get(x+1, y-1): 32 | count += 1 33 | if self.get(x-1, y): 34 | count += 1 35 | if self.get(x+1, y): 36 | count += 1 37 | if self.get(x-1, y+1): 38 | count += 1 39 | if self.get(x, y+1): 40 | count += 1 41 | if self.get(x+1, y+1): 42 | count += 1 43 | 44 | if self.get(x, y): 45 | if count < 2: 46 | toDie.append(x + y*self.width) 47 | elif count > 3: 48 | toDie.append(x + y*self.width) 49 | else: 50 | if count == 3: 51 | toLive.append(x + y*self.width) 52 | 53 | for i in range(len(toDie)): 54 | self.grid[toDie[i]] = False 55 | for i in range(len(toLive)): 56 | self.grid[toLive[i]] = True 57 | 58 | self.draw() 59 | def draw(self): 60 | i = 0 61 | for x in range(0, self.width*10, 10): 62 | for y in range(0, self.height*10, 10): 63 | if self.grid[i]: 64 | self.canvas.fillRect(x, y, x+10, y+10) 65 | else: 66 | self.canvas.clearRect(x, y, x+10, y+10) 67 | i += 1 68 | 69 | 70 | def main(): 71 | print """ 72 | 73 | 74 | 75 | 78 | 79 | 80 | 81 | 82 | """ % (str(StartGoL)+"\n"+str(GoL)) 83 | 84 | 85 | if __name__ == "__main__": 86 | main() 87 | -------------------------------------------------------------------------------- /examples/triangulation.py: -------------------------------------------------------------------------------- 1 | from py2js.decorator import JavaScript 2 | 3 | from math import sqrt 4 | 5 | @JavaScript 6 | def is_on_the_left(c, a, b, pts_list): 7 | ax, ay = pts_list[a] 8 | bx, by = pts_list[b] 9 | cx, cy = pts_list[c] 10 | ux = float(bx - ax) 11 | uy = float(by - ay) 12 | vx = float(cx - ax) 13 | vy = float(cy - ay) 14 | return (ux*vy - uy*vx > 0) 15 | 16 | @JavaScript 17 | def criterion(a, b, c, pts_list): 18 | ax, ay = pts_list[a] 19 | bx, by = pts_list[b] 20 | cx, cy = pts_list[c] 21 | ux = float(ax - cx) 22 | uy = float(ay - cy) 23 | vx = float(bx - cx) 24 | vy = float(by - cy) 25 | len_u = sqrt(ux*ux + uy*uy) 26 | len_v = sqrt(vx*vx + vy*vy) 27 | return (ux*vx + uy*vy)/(len_u*len_v) 28 | 29 | @JavaScript 30 | def find_third_point(a, b, pts_list, edges): 31 | """ 32 | Take a boundary edge (a,b), and in the list of points 33 | find a point 'c' that lies on the left of ab and maximizes 34 | the angle acb 35 | """ 36 | found = 0 37 | minimum = 10**8 #this is dirty 38 | c_index = -1 39 | pt_index = -1 40 | for c_point in pts_list: 41 | c_index += 1 42 | if c_index != a and c_index != b and is_on_the_left(c_index, a, b, pts_list): 43 | edge_intersects = \ 44 | edge_intersects_edges((a, c_index), pts_list, edges) or \ 45 | edge_intersects_edges((b, c_index), pts_list, edges) 46 | if not edge_intersects: 47 | crit = criterion(a, b, c_index, pts_list) 48 | if crit < minimum: 49 | minimum = crit 50 | pt_index = c_index 51 | found = 1 52 | if found == 0: 53 | raise TriangulationError("ERROR: Optimal point not found in find_third_point().") 54 | return pt_index 55 | 56 | @JavaScript 57 | def lies_inside(c, bdy_edges): 58 | for edge in bdy_edges: 59 | a,b = edge 60 | if c == a or c == b: return False 61 | return True 62 | 63 | @JavaScript 64 | def is_boundary_edge(a, b, bdy_edges): 65 | """ 66 | Checks whether edge (a, b) is in the list of boundary edges 67 | """ 68 | for edge in bdy_edges: 69 | a0, b0 = edge 70 | if a == a0 and b == b0: 71 | return True 72 | return False 73 | 74 | @JavaScript 75 | def triangulate_af(pts_list, bdy_edges): 76 | """ 77 | Create a triangulation using the advancing front method. 78 | """ 79 | # create empty list of elements 80 | elems = [] 81 | bdy_edges = bdy_edges[:] 82 | # main loop 83 | while len(bdy_edges) > 0: 84 | # take the last item from the list of bdy edges (and remove it) 85 | a,b = bdy_edges.pop() 86 | c = find_third_point(a, b, pts_list, bdy_edges) 87 | elems.append((a,b,c)) 88 | if is_boundary_edge(c, a, bdy_edges): 89 | bdy_edges.remove((c,a)) 90 | else: 91 | bdy_edges.append((a,c)) 92 | if is_boundary_edge(b, c, bdy_edges): 93 | bdy_edges.remove((b,c)) 94 | else: 95 | bdy_edges.append((c,b)) 96 | return elems 97 | 98 | @JavaScript 99 | def ccw(A, B, C): 100 | return (C[1]-A[1])*(B[0]-A[0]) > (B[1]-A[1])*(C[0]-A[0]) 101 | 102 | @JavaScript 103 | def intersect(A, B, C, D): 104 | return ccw(A, C, D) != ccw(B, C, D) and ccw(A, B, C) != ccw(A, B, D) 105 | 106 | @JavaScript 107 | def two_edges_intersect(nodes, e1, e2): 108 | """ 109 | Checks whether the two edges intersect. 110 | 111 | It assumes that e1 and e2 are tuples of (a_id, b_id) of ids into the nodes. 112 | """ 113 | A = nodes[e1[0]] 114 | B = nodes[e1[1]] 115 | C = nodes[e2[0]] 116 | D = nodes[e2[1]] 117 | return intersect(A, B, C, D) 118 | 119 | @JavaScript 120 | def edge_intersects_edges(e1, nodes, edges): 121 | """ 122 | Returns True if 'e1' intersects any edge from 'edges'. 123 | """ 124 | for i in range(len(edges)): 125 | e2 = edges[i] 126 | if e1[1] == e2[0] or e1[0] == e2[1]: 127 | continue 128 | if two_edges_intersect(nodes, e1, e2): 129 | return True 130 | return False 131 | 132 | @JavaScript 133 | def start_triag(): 134 | js_pre = document.getElementById(js('js_pre')) 135 | setattr(js_pre, 'textContent', js("start")) 136 | canvas = document.getElementById(js('canvas')).getContext(js('2d')) 137 | canvas.fillText(js("Mesh"), 100, 10) 138 | setattr(js_pre, 'textContent', js("triag")) 139 | setattr(js_pre, 'textContent', example1()) 140 | nodes, edges, elems = example2() 141 | scale = 50 142 | x0 = 3 143 | setattr(canvas, 'strokeStyle', js('rgb(0, 0, 255)')) 144 | for el in elems: 145 | canvas.beginPath() 146 | x, y = nodes[el[0]] 147 | canvas.moveTo(x*scale+x0, 200-y*scale) 148 | x, y = nodes[el[1]] 149 | canvas.lineTo(x*scale+x0, 200-y*scale) 150 | x, y = nodes[el[2]] 151 | canvas.lineTo(x*scale+x0, 200-y*scale) 152 | x, y = nodes[el[0]] 153 | canvas.lineTo(x*scale+x0, 200-y*scale) 154 | canvas.stroke() 155 | setattr(canvas, 'strokeStyle', js('rgb(0, 255, 0)')) 156 | canvas.beginPath() 157 | x, y = nodes[0] 158 | canvas.moveTo(x*scale+x0, 200-y*scale) 159 | for n in nodes: 160 | x, y = n 161 | canvas.lineTo(x*scale+x0, 200-y*scale) 162 | x, y = nodes[0] 163 | canvas.lineTo(x*scale+x0, 200-y*scale) 164 | canvas.stroke() 165 | 166 | @JavaScript 167 | def example1(): 168 | nodes, edges, elems = example2() 169 | result = str(nodes) + "\n" + str(edges) + "\n" + str(elems) 170 | return result 171 | 172 | @JavaScript 173 | def example2(): 174 | nodes = [ 175 | (0, 0), 176 | (1, 0), 177 | (2, 1), 178 | (2, 2), 179 | (1, 2), 180 | (0.5, 1.5), 181 | (0, 1), 182 | ] 183 | edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 0)] 184 | elems = triangulate_af(nodes, edges) 185 | return nodes, edges, elems 186 | 187 | 188 | def main(): 189 | funcs = [ 190 | is_on_the_left, 191 | criterion, 192 | find_third_point, 193 | lies_inside, 194 | is_boundary_edge, 195 | triangulate_af, 196 | ccw, 197 | intersect, 198 | two_edges_intersect, 199 | edge_intersects_edges, 200 | example1, 201 | example2, 202 | start_triag, 203 | ] 204 | js = "" 205 | for f in funcs: 206 | js += str(f) + "\n" 207 | py_result = example1() 208 | 209 | print """ 210 | 211 | 216 | 217 | 220 | 221 | 222 |

Triangulation Demo

223 | Python output:
224 |
%s
225 | JavaScript output:
226 |

227 |     Canvas:
228 | 229 |
230 | End of page. 231 | 232 | """ % (js, py_result) 233 | 234 | 235 | if __name__ == "__main__": 236 | main() 237 | -------------------------------------------------------------------------------- /library/05-init.js: -------------------------------------------------------------------------------- 1 | /* Python built-ins for JavaScript 2 | 3 | Useful links: 4 | 5 | * https://developer.mozilla.org/En/SpiderMonkey/Introduction_to_the_JavaScript_shell 6 | 7 | */ 8 | 9 | var py_builtins = {}; 10 | 11 | py_builtins.__python3__ = false; 12 | 13 | /* A reference to the global object */ 14 | 15 | var _global_this = this; 16 | 17 | /* JavaScript helper functions */ 18 | 19 | function defined(obj) { 20 | return typeof(obj) != 'undefined'; 21 | } 22 | 23 | function assert(cond, msg) { 24 | if (!cond) { 25 | throw new py_builtins.AssertionError(msg); 26 | } 27 | } 28 | 29 | function iterate(seq, func) { 30 | while (true) { 31 | try { 32 | func(seq.next()); 33 | } catch (exc) { 34 | if (isinstance(exc, py_builtins.StopIteration)) { 35 | break; 36 | } else { 37 | throw exc; 38 | } 39 | } 40 | } 41 | } 42 | 43 | function copy(iterator) { 44 | var items = []; 45 | 46 | iterate(iterator, function(item) { 47 | items.push(item); 48 | }); 49 | 50 | return items; 51 | } 52 | 53 | function _new(cls, arg) { 54 | return new cls(arg); 55 | } 56 | 57 | function js(obj) { 58 | /* 59 | Converts (recursively) a Python object to a javascript builtin object. 60 | 61 | In particular: 62 | 63 | tuple -> Array 64 | list -> Array 65 | dict -> Object 66 | 67 | It uses the obj._js_() if it is defined, otherwise it just returns the 68 | same object. It is the responsibility of _js_() to convert recursively 69 | the object itself. 70 | */ 71 | if ((obj != null) && defined(obj._js_)) 72 | return obj._js_(); 73 | else 74 | return obj; 75 | } 76 | 77 | -------------------------------------------------------------------------------- /library/10-builtin.js: -------------------------------------------------------------------------------- 1 | /* Python built-in exceptions */ 2 | 3 | py_builtins.__exceptions__ = [ 4 | 'NotImplementedError', 5 | 'ZeroDivisionError', 6 | 'AssertionError', 7 | 'AttributeError', 8 | 'RuntimeError', 9 | 'ImportError', 10 | 'TypeError', 11 | 'ValueError', 12 | 'NameError', 13 | 'IndexError', 14 | 'KeyError', 15 | 'StopIteration' 16 | ]; 17 | 18 | for (var i in py_builtins.__exceptions__) { 19 | var name = py_builtins.__exceptions__[i]; 20 | 21 | py_builtins[name] = function() { 22 | return function(message) { 23 | this.message = defined(message) ? message : ""; 24 | }; 25 | }(); 26 | 27 | py_builtins[name].__name__ = name; 28 | py_builtins[name].prototype.__class__ = py_builtins[name]; 29 | 30 | py_builtins[name].prototype.__str__ = function() { 31 | return str(js(this.__class__.__name__) + ": " + js(this.message)); 32 | }; 33 | 34 | py_builtins[name].prototype.toString = function() { 35 | return js(this.__str__()); 36 | }; 37 | } 38 | 39 | /* Python built-in functions */ 40 | 41 | function hasattr(obj, name) { 42 | return defined(obj[name]); 43 | } 44 | 45 | function getattr(obj, name, value) { 46 | var _value = obj[name]; 47 | 48 | if (defined(_value)) { 49 | return _value; 50 | } else { 51 | if (defined(value)) { 52 | return value; 53 | } else { 54 | throw new py_builtins.AttributeError(obj, name); 55 | } 56 | } 57 | } 58 | 59 | function setattr(obj, name, value) { 60 | obj[name] = value; 61 | } 62 | 63 | function hash(obj) { 64 | if (hasattr(obj, '__hash__')) { 65 | return obj.__hash__(); 66 | } else if (typeof(obj) == 'number') { 67 | return obj == -1 ? -2 : obj; 68 | } else { 69 | throw new py_builtins.AttributeError(obj, '__hash__'); 70 | } 71 | } 72 | 73 | function len(obj) { 74 | if (hasattr(obj, '__len__')) { 75 | return obj.__len__(); 76 | } else { 77 | throw new py_builtins.AttributeError(obj, '__name__'); 78 | } 79 | } 80 | 81 | function range(start, end, step) { 82 | if (!defined(end)) { 83 | end = start; 84 | start = 0; 85 | } 86 | 87 | if (!defined(step)) { 88 | step = 1; 89 | } 90 | 91 | var seq = []; 92 | 93 | for (var i = start; i < end; i += step) { 94 | seq.push(i); 95 | } 96 | 97 | if (py_builtins.__python3__) 98 | return iter(seq); 99 | else 100 | return list(seq); 101 | } 102 | 103 | function xrange(start, end, step) { 104 | return iter(range(start, end, step)); 105 | } 106 | 107 | function map() { 108 | if (arguments.length < 2) { 109 | throw new py_builtins.TypeError("map() requires at least two args"); 110 | } 111 | 112 | if (arguments.length > 2) { 113 | throw new py_builtins.NotImplementedError("only one sequence allowed in map()"); 114 | } 115 | 116 | var func = arguments[0]; 117 | var seq = iter(arguments[1]); 118 | 119 | var items = list(); 120 | 121 | iterate(seq, function(item) { 122 | items.append(func(item)); 123 | }); 124 | 125 | if (py_builtins.__python3__) 126 | return iter(items); 127 | else 128 | return items; 129 | } 130 | 131 | function zip() { 132 | if (!arguments.length) { 133 | return list(); 134 | } 135 | 136 | var iters = list(); 137 | var i; 138 | 139 | for (i = 0; i < arguments.length; i++) { 140 | iters.append(iter(arguments[i])); 141 | } 142 | 143 | var items = list(); 144 | 145 | while (true) { 146 | var item = list(); 147 | 148 | for (i = 0; i < arguments.length; i++) { 149 | try { 150 | var value = iters.__getitem__(i).next(); 151 | } catch (exc) { 152 | if (isinstance(exc, py_builtins.StopIteration)) { 153 | return items; 154 | } else { 155 | throw exc; 156 | } 157 | } 158 | 159 | item.append(value); 160 | } 161 | 162 | items.append(tuple(item)); 163 | } 164 | } 165 | 166 | function isinstance(obj, cls) { 167 | if (cls instanceof _tuple) { 168 | var length = cls.__len__(); 169 | 170 | if (length == 0) { 171 | return false; 172 | } 173 | 174 | for (var i = 0; i < length; i++) { 175 | var _cls = cls.__getitem__(i); 176 | 177 | if (isinstance(obj, _cls)) { 178 | return true; 179 | } 180 | } 181 | 182 | return false; 183 | } else { 184 | if (defined(obj.__class__) && defined(cls.__name__)) { 185 | return obj.__class__ == cls; 186 | } else { 187 | return obj instanceof cls; 188 | } 189 | } 190 | } 191 | 192 | py_builtins.bool = function(a) { 193 | if ((a != null) && defined(a.__bool__)) 194 | return a.__bool__(); 195 | else { 196 | if (a) 197 | return true; 198 | else 199 | return false; 200 | } 201 | }; 202 | 203 | py_builtins.eq = function(a, b) { 204 | if ((a != null) && defined(a.__eq__)) 205 | return a.__eq__(b); 206 | else if ((b != null) && defined(b.__eq__)) 207 | return b.__eq__(a); 208 | else 209 | return a == b; 210 | }; 211 | 212 | py_builtins._int = function(value) { 213 | return value; 214 | }; 215 | 216 | py_builtins._float = function(value) { 217 | return value; 218 | }; 219 | 220 | py_builtins.max = function(list) { 221 | if (len(list) == 0) 222 | throw new py_builtins.ValueError("max() arg is an empty sequence"); 223 | else { 224 | var result = null; 225 | 226 | iterate(iter(list), function(item) { 227 | if ((result == null) || (item > result)) 228 | result = item; 229 | }); 230 | 231 | return result; 232 | } 233 | }; 234 | 235 | py_builtins.min = function(list) { 236 | if (len(list) == 0) 237 | throw new py_builtins.ValueError("min() arg is an empty sequence"); 238 | else { 239 | var result = null; 240 | 241 | iterate(iter(list), function(item) { 242 | if ((result == null) || (item < result)) 243 | result = item; 244 | }); 245 | 246 | return result; 247 | } 248 | }; 249 | 250 | py_builtins.sum = function(list) { 251 | var result = 0; 252 | 253 | iterate(iter(list), function(item) { 254 | result += item; 255 | }); 256 | 257 | return result; 258 | }; 259 | 260 | py_builtins.print = function(s) { 261 | if (typeof(console) != "undefined" && defined(console.log)) 262 | console.log(js(str(s))); 263 | else { 264 | if (arguments.length <= 1) { 265 | if (defined(s)) 266 | print(s); 267 | else 268 | print(""); 269 | } else { 270 | var args = tuple(to_array(arguments)); 271 | print(str(" ").join(args)); 272 | } 273 | } 274 | }; 275 | 276 | -------------------------------------------------------------------------------- /library/20-type-iter.js: -------------------------------------------------------------------------------- 1 | /* Python 'iter' type */ 2 | 3 | function iter(obj) { 4 | if (obj instanceof Array) { 5 | return new _iter(obj); 6 | } else if (typeof(obj) === "string") { 7 | return iter(obj.split("")); 8 | } else if (obj.__class__ == _iter) { 9 | return obj; 10 | } else if (defined(obj.__iter__)) { 11 | return obj.__iter__(); 12 | } else { 13 | throw new py_builtins.TypeError("object is not iterable"); 14 | } 15 | } 16 | 17 | function _iter(seq) { 18 | this.__init__(seq); 19 | } 20 | 21 | _iter.__name__ = 'iter'; 22 | _iter.prototype.__class__ = _iter; 23 | 24 | _iter.prototype.__init__ = function(seq) { 25 | this._seq = seq; 26 | this._index = 0; 27 | }; 28 | 29 | _iter.prototype.__str__ = function () { 30 | return str(""); 31 | }; 32 | 33 | _iter.prototype.toString = function () { 34 | return js(this.__str__()); 35 | }; 36 | 37 | _iter.prototype.next = function() { 38 | var value = this._seq[this._index++]; 39 | 40 | if (defined(value)) { 41 | return value; 42 | } else { 43 | throw new py_builtins.StopIteration('no more items'); 44 | } 45 | }; 46 | 47 | -------------------------------------------------------------------------------- /library/21-type-slice.js: -------------------------------------------------------------------------------- 1 | /* Python 'slice' object */ 2 | 3 | function slice(start, stop, step) { 4 | return new _slice(start, stop, step); 5 | } 6 | 7 | function _slice(start, stop, step) { 8 | this.__init__(start, stop, step); 9 | } 10 | 11 | _slice.__name__ = 'slice'; 12 | _slice.prototype.__class__ = _slice; 13 | 14 | _slice.prototype.__init__ = function(start, stop, step) { 15 | if (!defined(stop) && !defined(step)) 16 | { 17 | stop = start; 18 | start = null; 19 | } 20 | if (!start && start != 0) start = null; 21 | if (!defined(stop)) stop = null; 22 | if (!defined(step)) step = null; 23 | this.start = start; 24 | this.stop = stop; 25 | this.step = step; 26 | }; 27 | 28 | _slice.prototype.__str__ = function() { 29 | return str("slice(" + this.start + ", " + this.stop + ", " + this.step + ")"); 30 | }; 31 | 32 | _slice.prototype.indices = function(n) { 33 | var start = this.start; 34 | if (start == null) 35 | start = 0; 36 | if (start > n) 37 | start = n; 38 | if (start < 0) 39 | start = n+start; 40 | var stop = this.stop; 41 | if (stop > n) 42 | stop = n; 43 | if (stop == null) 44 | stop = n; 45 | if (stop < 0) 46 | stop = n+stop; 47 | var step = this.step; 48 | if (step == null) 49 | step = 1; 50 | return tuple([start, stop, step]); 51 | }; 52 | 53 | -------------------------------------------------------------------------------- /library/22-type-tuple.js: -------------------------------------------------------------------------------- 1 | /* Python 'tuple' type */ 2 | 3 | function tuple(seq) { 4 | if (arguments.length <= 1) { 5 | return new _tuple(seq); 6 | } else { 7 | throw new py_builtins.TypeError("tuple() takes at most 1 argument (" + arguments.length + " given)"); 8 | } 9 | } 10 | 11 | function _tuple(seq) { 12 | this.__init__(seq); 13 | } 14 | 15 | _tuple.__name__ = 'tuple'; 16 | _tuple.prototype.__class__ = _tuple; 17 | 18 | _tuple.prototype.__init__ = function(seq) { 19 | if (!defined(seq)) { 20 | this._items = []; 21 | this._len = 0; 22 | } else { 23 | this._items = copy(iter(seq)); 24 | this._len = -1; 25 | } 26 | }; 27 | 28 | _tuple.prototype.__str__ = function () { 29 | if (this.__len__() == 1) { 30 | return str("(" + this._items[0] + ",)"); 31 | } else { 32 | return str("(" + this._items.join(", ") + ")"); 33 | } 34 | }; 35 | 36 | _tuple.prototype.__eq__ = function (other) { 37 | if (other.__class__ == this.__class__) { 38 | if (len(this) != len(other)) 39 | return false; 40 | for (var i = 0; i < len(this); i++) { 41 | // TODO: use __eq__ here as well: 42 | if (this._items[i] != other._items[i]) 43 | return false; 44 | } 45 | return true; 46 | // This doesn't take into account hash collisions: 47 | //return hash(this) == hash(other) 48 | } else 49 | return false; 50 | }; 51 | 52 | _tuple.prototype.toString = function () { 53 | return js(this.__str__()); 54 | }; 55 | 56 | _tuple.prototype._js_ = function () { 57 | var items = []; 58 | 59 | iterate(iter(this), function(item) { 60 | items.push(js(item)); 61 | }); 62 | 63 | return items; 64 | }; 65 | 66 | _tuple.prototype.__hash__ = function () { 67 | var value = 0x345678; 68 | var length = this.__len__(); 69 | 70 | for (var index in this._items) { 71 | value = ((1000003*value) & 0xFFFFFFFF) ^ hash(this._items[index]); 72 | value = value ^ length; 73 | } 74 | 75 | if (value == -1) { 76 | value = -2; 77 | } 78 | 79 | return value; 80 | }; 81 | 82 | _tuple.prototype.__len__ = function() { 83 | if (this._len == -1) { 84 | var count = 0; 85 | 86 | for (var index in this._items) { 87 | count += 1; 88 | } 89 | 90 | this._len = count; 91 | return count; 92 | } else 93 | return this._len; 94 | }; 95 | 96 | _tuple.prototype.__iter__ = function() { 97 | return new _iter(this._items); 98 | }; 99 | 100 | _tuple.prototype.__contains__ = function(item) { 101 | for (var index in this._items) { 102 | if (py_builtins.eq(item, this._items[index])) { 103 | return true; 104 | } 105 | } 106 | 107 | return false; 108 | }; 109 | 110 | _tuple.prototype.__getitem__ = function(index) { 111 | var seq; 112 | if (isinstance(index, _slice)) { 113 | var s = index; 114 | var inds = s.indices(len(this)); 115 | var start = inds.__getitem__(0); 116 | var stop = inds.__getitem__(1); 117 | var step = inds.__getitem__(2); 118 | seq = []; 119 | for (var i = start; i < stop; i += step) { 120 | seq.push(this.__getitem__(i)); 121 | } 122 | return new this.__class__(seq); 123 | } else if ((index >= 0) && (index < len(this))) 124 | return this._items[index]; 125 | else if ((index < 0) && (index >= -len(this))) 126 | return this._items[index+len(this)]; 127 | else 128 | throw new py_builtins.IndexError("list assignment index out of range"); 129 | }; 130 | 131 | _tuple.prototype.__setitem__ = function(index, value) { 132 | throw new py_builtins.TypeError("'tuple' object doesn't support item assignment"); 133 | }; 134 | 135 | _tuple.prototype.__delitem__ = function(index) { 136 | throw new py_builtins.TypeError("'tuple' object doesn't support item deletion"); 137 | }; 138 | 139 | _tuple.prototype.count = function(value) { 140 | var count = 0; 141 | 142 | for (var index in this._items) { 143 | if (value == this._items[index]) { 144 | count += 1; 145 | } 146 | } 147 | 148 | return count; 149 | }; 150 | 151 | _tuple.prototype.index = function(value, start, end) { 152 | if (!defined(start)) { 153 | start = 0; 154 | } 155 | 156 | for (var i = start; !defined(end) || (start < end); i++) { 157 | var _value = this._items[i]; 158 | 159 | if (!defined(_value)) { 160 | break; 161 | } 162 | 163 | if (_value == value) { 164 | return i; 165 | } 166 | } 167 | 168 | throw new py_builtins.ValueError("tuple.index(x): x not in list"); 169 | }; 170 | 171 | -------------------------------------------------------------------------------- /library/23-type-list.js: -------------------------------------------------------------------------------- 1 | /* Python 'list' type */ 2 | 3 | function list(seq) { 4 | if (arguments.length <= 1) { 5 | return new _list(seq); 6 | } else { 7 | throw new py_builtins.TypeError("list() takes at most 1 argument (" + arguments.length + " given)"); 8 | } 9 | } 10 | 11 | function _list(seq) { 12 | this.__init__(seq); 13 | } 14 | 15 | _list.__name__ = 'list'; 16 | _list.prototype.__class__ = _list; 17 | 18 | _list.prototype.__init__ = _tuple.prototype.__init__; 19 | 20 | _list.prototype.__str__ = function () { 21 | return str("[" + this._items.join(", ") + "]"); 22 | }; 23 | 24 | _list.prototype.__eq__ = _tuple.prototype.__eq__; 25 | 26 | _list.prototype.toString = _tuple.prototype.toString; 27 | 28 | _list.prototype._js_ = _tuple.prototype._js_; 29 | 30 | _list.prototype.__len__ = _tuple.prototype.__len__; 31 | 32 | _list.prototype.__iter__ = _tuple.prototype.__iter__; 33 | 34 | _list.prototype.__contains__ = _tuple.prototype.__contains__; 35 | 36 | _list.prototype.__getitem__ = _tuple.prototype.__getitem__; 37 | 38 | _list.prototype.__setitem__ = function(index, value) { 39 | if ((index >= 0) && (index < len(this))) 40 | this._items[index] = value; 41 | else if ((index < 0) && (index >= -len(this))) 42 | this._items[index+len(this)] = value; 43 | else 44 | throw new py_builtins.IndexError("list assignment index out of range"); 45 | }; 46 | _list.prototype.__setslice__ = function(lower, upper, value) { 47 | var it = list(value)._items; 48 | if ( lower < len(this) && upper < len(this)){ 49 | this._items = this._items.slice(0,lower).concat(it).concat(this._items.slice(upper,len(this))); 50 | this._len = -1; 51 | } 52 | }; 53 | 54 | _list.prototype.__delitem__ = function(index) { 55 | if ((index >= 0) && (index < len(this))) { 56 | var a = this._items.slice(0, index); 57 | var b = this._items.slice(index+1, len(this)); 58 | this._items = a.concat(b); 59 | this._len = -1; 60 | } else 61 | throw new py_builtins.IndexError("list assignment index out of range"); 62 | }; 63 | 64 | _list.prototype.count = _tuple.prototype.count; 65 | 66 | _list.prototype.index = function(value, start, end) { 67 | if (!defined(start)) { 68 | start = 0; 69 | } 70 | 71 | for (var i = start; !defined(end) || (start < end); i++) { 72 | var _value = this._items[i]; 73 | 74 | if (!defined(_value)) { 75 | break; 76 | } 77 | 78 | if (_value == value) { 79 | return i; 80 | } 81 | 82 | if (defined(_value.__eq__)) { 83 | if (_value.__eq__(value)) 84 | return i; 85 | } 86 | } 87 | 88 | throw new py_builtins.ValueError("list.index(x): x not in list"); 89 | }; 90 | 91 | _list.prototype.remove = function(value) { 92 | this.__delitem__(this.index(value)); 93 | }; 94 | 95 | _list.prototype.append = function(value) { 96 | this._items.push(value); 97 | this._len = -1; 98 | }; 99 | 100 | _list.prototype.extend = function(l) { 101 | var items; 102 | items = this._items; 103 | iterate(iter(l), function(item) { 104 | items.push(item); 105 | }); 106 | this._len = -1; 107 | }; 108 | 109 | _list.prototype.pop = function() { 110 | if (len(this) > 0) { 111 | this._len = -1; 112 | return this._items.pop(); 113 | } else 114 | throw new py_builtins.IndexError("pop from empty list"); 115 | }; 116 | 117 | _list.prototype.sort = function() { 118 | this._items.sort(); 119 | }; 120 | 121 | _list.prototype.insert = function(index, x) { 122 | var a = this._items.slice(0, index) 123 | var b = this._items.slice(index, len(this)) 124 | this._items = a.concat([x], b) 125 | this._len = -1; 126 | } 127 | 128 | _list.prototype.reverse = function() { 129 | var new_list = list([]); 130 | iterate(iter(this), function(item) { 131 | new_list.insert(0, item); 132 | }); 133 | this._items = new_list._items; 134 | } 135 | 136 | -------------------------------------------------------------------------------- /library/24-type-dict.js: -------------------------------------------------------------------------------- 1 | /* Python 'dict' type */ 2 | 3 | function dict(args) { 4 | return new _dict(args); 5 | } 6 | 7 | function _dict(args) { 8 | this.__init__(args); 9 | } 10 | 11 | _dict.__name__ = 'dict'; 12 | _dict.prototype.__class__ = _dict; 13 | 14 | _dict.prototype.__init__ = function(args) { 15 | var items; 16 | var key; 17 | var value; 18 | 19 | if (defined(args)) { 20 | if (defined(args.__iter__)) { 21 | items = {}; 22 | iterate(iter(args), function(item) { 23 | key = js(item.__getitem__(0)); 24 | value = item.__getitem__(1); 25 | items[key] = value; 26 | }); 27 | this._items = items; 28 | } 29 | else 30 | this._items = args; 31 | } else { 32 | this._items = {}; 33 | } 34 | }; 35 | 36 | _dict.prototype.__str__ = function () { 37 | var strings = []; 38 | 39 | for (var key in this._items) { 40 | strings.push(js(str(key)) + ": " + js(str(this._items[key]))); 41 | } 42 | 43 | return str("{" + strings.join(", ") + "}"); 44 | }; 45 | 46 | _dict.prototype.toString = function () { 47 | return js(this.__str__()); 48 | }; 49 | 50 | _dict.prototype._js_ = function () { 51 | var items = {}; 52 | 53 | var _this_dict = this; // so that we can access it from within the closure: 54 | iterate(iter(this), function(key) { 55 | items[key] = js(_this_dict.__getitem__(key)); 56 | }); 57 | 58 | return items; 59 | }; 60 | 61 | _dict.prototype.__hash__ = function () { 62 | throw new py_builtins.TypeError("unhashable type: 'dict'"); 63 | }; 64 | 65 | _dict.prototype.__len__ = function() { 66 | var count = 0; 67 | 68 | for (var key in this._items) { 69 | count += 1; 70 | } 71 | 72 | return count; 73 | }; 74 | 75 | _dict.prototype.__iter__ = function() { 76 | return new _iter(this.keys()); 77 | }; 78 | 79 | _dict.prototype.__contains__ = function(key) { 80 | return defined(this._items[key]); 81 | }; 82 | 83 | _dict.prototype.__getitem__ = function(key) { 84 | var value = this._items[key]; 85 | 86 | if (defined(value)) { 87 | return value; 88 | } else { 89 | throw new py_builtins.KeyError(str(key)); 90 | } 91 | }; 92 | 93 | _dict.prototype.__setitem__ = function(key, value) { 94 | this._items[key] = value; 95 | }; 96 | 97 | _dict.prototype.__delitem__ = function(key) { 98 | if (this.__contains__(key)) { 99 | delete this._items[key]; 100 | } else { 101 | throw new py_builtins.KeyError(str(key)); 102 | } 103 | }; 104 | 105 | _dict.prototype.get = function(key, value) { 106 | var _value = this._items[key]; 107 | 108 | if (defined(_value)) { 109 | return _value; 110 | } else { 111 | if (defined(value)) { 112 | return value; 113 | } else { 114 | return null; 115 | } 116 | } 117 | }; 118 | 119 | _dict.prototype.items = function() { 120 | var items = []; 121 | 122 | for (var key in this._items) { 123 | items.push([key, this._items[key]]); 124 | } 125 | 126 | return items; 127 | }; 128 | 129 | _dict.prototype.keys = function() { 130 | var keys = []; 131 | 132 | for (var key in this._items) { 133 | keys.push(key); 134 | } 135 | 136 | return keys; 137 | }; 138 | 139 | _dict.prototype.values = function() { 140 | var values = []; 141 | 142 | for (var key in this._items) { 143 | values.push(this._items[key]); 144 | } 145 | 146 | return values; 147 | }; 148 | 149 | _dict.prototype.update = function(other) { 150 | for (var key in other) { 151 | this._items[key] = other[key]; 152 | } 153 | }; 154 | 155 | _dict.prototype.clear = function() { 156 | for (var key in this._items) { 157 | delete this._items[key]; 158 | } 159 | }; 160 | 161 | _dict.prototype.pop = function(key, value) { 162 | var _value = this._items[key]; 163 | 164 | if (defined(_value)) { 165 | delete this._items[key]; 166 | } else { 167 | if (defined(value)) { 168 | _value = value; 169 | } else { 170 | throw new py_builtins.KeyError(str(key)); 171 | } 172 | } 173 | 174 | return _value; 175 | }; 176 | 177 | _dict.prototype.popitem = function() { 178 | var _key; 179 | 180 | for (var key in this._items) { 181 | _key = key; 182 | break; 183 | } 184 | 185 | if (defined(key)) { 186 | return [_key, this._items[_key]]; 187 | } else { 188 | throw new py_builtins.KeyError("popitem(): dictionary is empty"); 189 | } 190 | }; 191 | 192 | -------------------------------------------------------------------------------- /library/25-type-str.js: -------------------------------------------------------------------------------- 1 | /* Python 'str' type */ 2 | 3 | function str(s) { 4 | return new _str(s); 5 | } 6 | 7 | function _str(s) { 8 | this.__init__(s); 9 | } 10 | 11 | _str.__name__ = 'str'; 12 | _str.prototype.__class__ = _str; 13 | 14 | _str.prototype.__init__ = function(s) { 15 | if (!defined(s)) { 16 | this._obj = ''; 17 | } else { 18 | if (typeof(s) === "string") { 19 | this._obj = s; 20 | } else if (defined(s.toString)) { 21 | this._obj = s.toString(); 22 | } else if (defined(s.__str__)) { 23 | this._obj = js(s.__str__()); 24 | } else 25 | this._obj = js(s); 26 | } 27 | }; 28 | 29 | _str.prototype.__str__ = function () { 30 | return this; 31 | }; 32 | 33 | _str.prototype.__eq__ = function (other) { 34 | if (other.__class__ == this.__class__) { 35 | if (len(this) != len(other)) 36 | return false; 37 | for (var i = 0; i < len(this); i++) { 38 | if (this._obj[i] != other._obj[i]) 39 | return false; 40 | } 41 | return true; 42 | } else 43 | return false; 44 | }; 45 | 46 | _str.prototype.toString = function () { 47 | return js(this.__str__()); 48 | }; 49 | 50 | _str.prototype._js_ = function () { 51 | return this._obj; 52 | }; 53 | 54 | _str.prototype.__hash__ = function () { 55 | var value = 0x345678; 56 | var length = this.__len__(); 57 | 58 | for (var index in this._obj) { 59 | value = ((1000003*value) & 0xFFFFFFFF) ^ hash(this._obj[index]); 60 | value = value ^ length; 61 | } 62 | 63 | if (value == -1) { 64 | value = -2; 65 | } 66 | 67 | return value; 68 | }; 69 | 70 | _str.prototype.__len__ = function() { 71 | return this._obj.length; 72 | }; 73 | 74 | _str.prototype.__iter__ = function() { 75 | return iter(this._obj); 76 | }; 77 | 78 | _str.prototype.__bool__ = function() { 79 | return py_builtins.bool(this._obj); 80 | }; 81 | 82 | _str.prototype.__eq__ = function(s) { 83 | if (typeof(s) === "string") 84 | return this._obj == s; 85 | else if (isinstance(s, _str)) 86 | return this._obj == s._obj; 87 | else 88 | return false; 89 | }; 90 | 91 | _str.prototype.__contains__ = function(item) { 92 | for (var index in this._obj) { 93 | if (item == this._obj[index]) { 94 | return true; 95 | } 96 | } 97 | 98 | return false; 99 | }; 100 | 101 | _str.prototype.__getitem__ = function(index) { 102 | 103 | var seq; 104 | if (isinstance(index, _slice)) { 105 | var s = index; 106 | var inds = s.indices(len(this)); 107 | var start = inds.__getitem__(0); 108 | var stop = inds.__getitem__(1); 109 | var step = inds.__getitem__(2); 110 | seq = ""; 111 | for (var i = start; i < stop; i += step) { 112 | seq = seq + js(this.__getitem__(i)); 113 | } 114 | return new this.__class__(seq); 115 | } else if ((index >= 0) && (index < len(this))) 116 | return this._obj[index]; 117 | else if ((index < 0) && (index >= -len(this))) 118 | return this._obj[index+len(this)]; 119 | else 120 | throw new py_builtins.IndexError("string index out of range"); 121 | }; 122 | 123 | _str.prototype.__setitem__ = function(index, value) { 124 | throw new py_builtins.TypeError("'str' object doesn't support item assignment"); 125 | }; 126 | 127 | _str.prototype.__delitem__ = function(index) { 128 | throw new py_builtins.TypeError("'str' object doesn't support item deletion"); 129 | }; 130 | 131 | _str.prototype.count = function(str, start, end) { 132 | if (!defined(start)) 133 | start = 0; 134 | if (!defined(end)) 135 | end = null; 136 | var count = 0; 137 | s = this.__getitem__(slice(start, end)); 138 | idx = s.find(str); 139 | while (idx != -1) { 140 | count += 1; 141 | s = s.__getitem__(slice(idx+1, null)); 142 | idx = s.find(str); 143 | } 144 | return count; 145 | }; 146 | 147 | _str.prototype.index = function(value, start, end) { 148 | if (!defined(start)) { 149 | start = 0; 150 | } 151 | 152 | for (var i = start; !defined(end) || (start < end); i++) { 153 | var _value = this._obj[i]; 154 | 155 | if (!defined(_value)) { 156 | break; 157 | } 158 | 159 | if (_value == value) { 160 | return i; 161 | } 162 | } 163 | 164 | throw new py_builtins.ValueError("substring not found"); 165 | }; 166 | 167 | _str.prototype.find = function(s) { 168 | return this._obj.search(s); 169 | }; 170 | 171 | _str.prototype.rfind = function(s) { 172 | rev = function(s) { 173 | var a = list(str(s)); 174 | a.reverse(); 175 | a = str("").join(a); 176 | return a; 177 | } 178 | var a = rev(this); 179 | var b = rev(s); 180 | var r = a.find(b); 181 | if (r == -1) 182 | return r; 183 | return len(this)-len(b)-r 184 | }; 185 | 186 | _str.prototype.join = function(s) { 187 | return str(js(s).join(js(this))); 188 | }; 189 | 190 | _str.prototype.replace = function(old, _new, count) { 191 | old = js(old); 192 | _new = js(_new); 193 | var old_s; 194 | var new_s; 195 | 196 | if (defined(count)) 197 | count = js(count); 198 | else 199 | count = -1; 200 | old_s = ""; 201 | new_s = this._obj; 202 | while ((count != 0) && (new_s != old_s)) { 203 | old_s = new_s; 204 | new_s = new_s.replace(old, _new); 205 | count -= 1; 206 | } 207 | return str(new_s); 208 | }; 209 | 210 | _str.prototype.lstrip = function(chars) { 211 | if (len(this) == 0) 212 | return this; 213 | if (defined(chars)) 214 | chars = tuple(chars); 215 | else 216 | chars = tuple(["\n", "\t", " "]); 217 | var i = 0; 218 | while ((i < len(this)) && (chars.__contains__(this.__getitem__(i)))) { 219 | i += 1; 220 | } 221 | return this.__getitem__(slice(i, null)); 222 | }; 223 | 224 | _str.prototype.rstrip = function(chars) { 225 | if (len(this) == 0) 226 | return this 227 | if (defined(chars)) 228 | chars = tuple(chars); 229 | else 230 | chars = tuple(["\n", "\t", " "]); 231 | var i = len(this)-1; 232 | while ((i >= 0) && (chars.__contains__(this.__getitem__(i)))) { 233 | i -= 1; 234 | } 235 | return this.__getitem__(slice(i+1)); 236 | }; 237 | 238 | _str.prototype.strip = function(chars) { 239 | return this.lstrip(chars).rstrip(chars); 240 | }; 241 | 242 | _str.prototype.split = function(sep) { 243 | if (defined(sep)) { 244 | var r = list(this._obj.split(sep)); 245 | var r_new = list([]); 246 | iterate(iter(r), function(item) { 247 | r_new.append(str(item)); 248 | }); 249 | return r_new; 250 | } 251 | else { 252 | var r_new = list([]); 253 | iterate(iter(this.split(" ")), function(item) { 254 | if (len(item) > 0) 255 | r_new.append(item); 256 | }); 257 | return r_new; 258 | } 259 | }; 260 | 261 | _str.prototype.splitlines = function() { 262 | return this.split("\n"); 263 | }; 264 | 265 | _str.prototype.lower = function() { 266 | return str(this._obj.toLowerCase()); 267 | }; 268 | 269 | _str.prototype.upper = function() { 270 | return str(this._obj.toUpperCase()); 271 | }; 272 | 273 | -------------------------------------------------------------------------------- /library/41-python-classes.js: -------------------------------------------------------------------------------- 1 | // vim: sw=4 sts=4 2 | /** 3 | Copyright 2010 Jared Forsyth 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the "Software"), to deal in the Software without 8 | restriction, including without limitation the rights to use, 9 | copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | OTHER DEALINGS IN THE SOFTWARE. 25 | 26 | **/ 27 | 28 | /** python-style classes in javascript!! **/ 29 | 30 | var to_array = function to_array(a){return Array.prototype.slice.call(a,0);}; 31 | 32 | function instancemethod(cls, fn) { 33 | var meta = function $_instancemethod() { 34 | /* 35 | if (!__builtins__.isinstance(arguments[0], cls)) 36 | throw new Error('TypeError: unbound method '+fn.__name__+'() must be called with '+cls.__name__+' instance as the first argument'); 37 | */ 38 | return fn.apply(null, arguments); 39 | } 40 | meta.__name__ = fn.__name__?fn.__name__:fn.name; 41 | meta.__type__ = instancemethod; 42 | meta.__wraps__ = fn; 43 | fn.__wrapper__ = meta; 44 | meta.__str__ = function str(){ 45 | return ''; 46 | }; 47 | meta.im_class = cls; 48 | meta.im_func = fn; 49 | meta.im_self = null; 50 | meta.__get__ = function $_get(self, cls) { 51 | cls = cls||self.__class__; 52 | /* 53 | if (!__builtins__.isinstance(self, cls)) 54 | throw new Error('idk what just happened... invalid self while binding instancemethod'); 55 | */ 56 | var m2 = function() { 57 | return fn.apply(this, [self].concat(to_array(arguments))); 58 | }; 59 | m2.__name__ = meta.__name__; 60 | m2.__class__ = cls; 61 | m2.__type__ = instancemethod; 62 | m2.__wraps__ = fn; 63 | fn.__wraper__ = fn; 64 | m2.__str__ = function(){ 65 | return ''; 66 | }; 67 | m2.im_class = cls; 68 | m2.im_func = fn; 69 | m2.im_self = self; 70 | m2.args = function $_args(pos, kwd) { 71 | if (pos.__class__) 72 | pos = __builtins__.tuple([self]).__add__(pos); 73 | else 74 | pos = [self].concat(pos); 75 | return fn.args(pos, kwd); 76 | }; 77 | m2.args.__name__ = meta.__name__; 78 | return m2; 79 | }; 80 | return meta; 81 | } 82 | 83 | function _set_name(fn, name) { 84 | fn.__name__ = name; 85 | while(fn = fn.__wraps__) 86 | fn.__name__ = name; 87 | } 88 | 89 | var type = $m(function type(name, bases, namespace) { 90 | var cls = function $_type() { 91 | var self = {}; 92 | self.__init__ = instancemethod(cls, function(){}).__get__(self); 93 | self.__class__ = cls; 94 | self.__type__ = 'instance'; 95 | 96 | for (var attr in cls) { 97 | if (['__type__','__class__'].indexOf(attr)!==-1) 98 | continue; 99 | var val = cls[attr]; 100 | if (val && val.__type__ == instancemethod && !val.im_self) { 101 | self[attr] = val.__get__(self, cls); 102 | _set_name(self[attr], attr); 103 | } else 104 | self[attr] = val; 105 | } 106 | self.__init__.apply(null, arguments); 107 | self._old_toString = self.toString; 108 | if (self.__str__) 109 | self.toString = function(){ return self.__str__()._data; }; 110 | return self; 111 | }; 112 | var ts = cls.toString; 113 | var __setattr__ = $m(function class_setattr(key, val) { 114 | if (val && val.__type__ === 'function' || 115 | (val && !val.__type__ && typeof(val)==='function')) { 116 | cls[key] = instancemethod(cls, val); 117 | } else if (val && val.__type__ === classmethod) { 118 | cls[key] = val.__get__(cls); 119 | } else if (val && val.__type__ === staticmethod) { 120 | cls[key] = val.__get__(cls); 121 | } else if (val && val.__type__ === instancemethod) { 122 | cls[key] = instancemethod(cls, val.im_func); 123 | } else 124 | cls[key] = val; 125 | }); 126 | for (var i=0;i';}; 151 | return clsm; 152 | } 153 | /* 154 | function __classmethod(cls, val){ 155 | var fn = function() { 156 | return val.apply(this, [cls].concat(to_array(arguments))); 157 | }; 158 | if (val.args) { 159 | fn.args = function(pos, kwd) { 160 | return val.args([cls].concat(pos), kwd); 161 | }; 162 | } 163 | fn.__type__ = 'classmethod'; 164 | fn.__wraps__ = val; 165 | return fn; 166 | } 167 | 168 | // decorators 169 | function classmethod(method){ 170 | method.__cls_classmethod = true; 171 | return method; 172 | } 173 | */ 174 | function staticmethod(method){ 175 | var obj = {}; 176 | obj.__type__ = staticmethod; 177 | obj.__get__ = function(){return method;} 178 | obj.__str__ = function(){return '';}; 179 | return obj; 180 | } 181 | 182 | var Class = type; 183 | 184 | -------------------------------------------------------------------------------- /library/50-object.js: -------------------------------------------------------------------------------- 1 | function object(){ 2 | /* object constructor */ 3 | } 4 | 5 | object.__name__ = 'object'; 6 | 7 | object.prototype.__class__ = object; 8 | 9 | object.prototype.__mro__ = []; 10 | 11 | object.prototype.__inherited__ = {}; 12 | 13 | object.prototype.__init__ = function() { 14 | /* object constructor */ 15 | }; 16 | 17 | object.prototype.__getattr__ = function (key) { 18 | return this[key]; 19 | }; 20 | 21 | object.prototype.__setattr__ = function (key, value) { 22 | this[key] = value; 23 | }; 24 | 25 | var extend = function(cls, base_list) { 26 | var _mro = mro(cls,base_list); 27 | cls.prototype.__mro__ = _mro; 28 | //properties not defined in the original definition 29 | cls.prototype.__inherited__ = {}; 30 | for (var i = 1; i < _mro.length; i++){ 31 | base = _mro[i]; 32 | for(var property in base.prototype){ 33 | if(!(property in cls.prototype) && !(property in base.prototype.__inherited__)){ 34 | cls.prototype[property] = base.prototype[property]; 35 | cls.prototype.__inherited__[property] = base.prototype[property]; 36 | } 37 | } 38 | } 39 | //static properties not defined in the original definition 40 | cls.__inherited__ = {}; 41 | for (var i = 1; i < _mro.length; i++){ 42 | base = _mro[i]; 43 | for(var property in base){ 44 | if(!(property in cls) && !(property in base.__inherited__)){ 45 | cls[property] = base[property]; 46 | cls.__inherited__[property] = base[property]; 47 | } 48 | } 49 | } 50 | } 51 | 52 | var mro = function(cls, base_list) { 53 | var order = []; 54 | if (cls === object) { 55 | return [object]; 56 | }else if(base_list.length === 1 && base_list[0]===object) { 57 | return [cls, object]; 58 | } 59 | 60 | var orderlists = []; 61 | for (var i = 0; i < base_list.length; i++){ 62 | orderlists[i] = base_list[i].prototype.__mro__.slice(0); 63 | } 64 | orderlists[orderlists.length] = [cls].concat(base_list); 65 | while (orderlists.length > 0) { 66 | candidate_found = false; 67 | for (var i = 0; i < orderlists.length; i++){ 68 | candidatelist = orderlists[i] 69 | candidate = candidatelist[0]; 70 | if(mro_not_blocking(candidate,orderlists)){ 71 | /**good candidate */ 72 | candidate_found = true; 73 | break; 74 | } 75 | } 76 | if(!candidate_found || order.indexOf(candidate)>-1){ 77 | throw Exception; 78 | } 79 | order[order.length] = candidate; 80 | for (var i = orderlists.length-1; i >= 0; i--){ 81 | if(orderlists[i][0] === candidate){ 82 | orderlists[i].splice(0,1); 83 | if(orderlists[i].length === 0){ 84 | orderlists.splice(i,1); 85 | } 86 | } 87 | } 88 | } 89 | return order; 90 | } 91 | 92 | var mro_not_blocking = function(candidate, orderlists) { 93 | for(var j = 0; j < orderlists.length; j++){ 94 | if(orderlists[j].indexOf(candidate)>0){ 95 | return false; 96 | } 97 | } 98 | return true; 99 | } 100 | 101 | var _super = function(cls,instance){ 102 | super_instance = {}; 103 | _mro = instance.__mro__; 104 | cls_name = cls.__name__; 105 | function make_caller(base, property){ 106 | var f = function(){ 107 | base.prototype[property].apply(instance,arguments); 108 | } 109 | return f; 110 | } 111 | 112 | var k = 0; 113 | while((_mro[k].__name__ !== cls_name) && k<_mro.length){ 114 | k = k + 1; 115 | } 116 | if(k === _mro.length){ 117 | cls_name = cls.__name__; 118 | throw new py_builtins.AttributeError(instance, cls_name);} 119 | k = k + 1; 120 | for (var i = k; i < _mro.length; i++){ 121 | base = _mro[i]; 122 | for(var property in base.prototype){ 123 | if(!(property in super_instance)){ 124 | try{ 125 | super_instance[property] = make_caller(base,property); 126 | }catch(e){ 127 | super_instance[property] = base.prototype[property]; 128 | } 129 | } 130 | } 131 | } 132 | //TODO: super of static methods and class attributes 133 | return super_instance; 134 | } 135 | 136 | -------------------------------------------------------------------------------- /library/60-sprintf.js: -------------------------------------------------------------------------------- 1 | /** 2 | sprintf() for JavaScript 0.7-beta1 3 | http://www.diveintojavascript.com/projects/javascript-sprintf 4 | 5 | Copyright (c) Alexandru Marasteanu 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | * Neither the name of sprintf() for JavaScript nor the 16 | names of its contributors may be used to endorse or promote products 17 | derived from this software without 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 Alexandru Marasteanu 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 | 31 | Changelog: 32 | 2010.09.06 - 0.7-beta1 33 | - features: vsprintf, support for named placeholders 34 | - enhancements: format cache, reduced global namespace pollution 35 | 36 | 2010.05.22 - 0.6: 37 | - reverted to 0.4 and fixed the bug regarding the sign of the number 0 38 | Note: 39 | Thanks to Raphael Pigulla (http://www.n3rd.org/) 40 | who warned me about a bug in 0.5, I discovered that the last update was 41 | a regress. I appologize for that. 42 | 43 | 2010.05.09 - 0.5: 44 | - bug fix: 0 is now preceeded with a + sign 45 | - bug fix: the sign was not at the right position on padded results (Kamal Abdali) 46 | - switched from GPL to BSD license 47 | 48 | 2007.10.21 - 0.4: 49 | - unit test and patch (David Baird) 50 | 51 | 2007.09.17 - 0.3: 52 | - bug fix: no longer throws exception on empty paramenters (Hans Pufal) 53 | 54 | 2007.09.11 - 0.2: 55 | - feature: added argument swapping 56 | 57 | 2007.04.03 - 0.1: 58 | - initial release 59 | **/ 60 | 61 | var sprintf = (function() { 62 | function get_type(variable) { 63 | return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase(); 64 | } 65 | function str_repeat(input, multiplier) { 66 | for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */} 67 | return output.join(''); 68 | } 69 | 70 | var str_format = function() { 71 | if (!str_format.cache.hasOwnProperty(arguments[0])) { 72 | str_format.cache[arguments[0]] = str_format.parse(arguments[0]); 73 | } 74 | return str_format.format.call(null, str_format.cache[arguments[0]], arguments); 75 | }; 76 | 77 | str_format.format = function(parse_tree, argv) { 78 | var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length; 79 | for (i = 0; i < tree_length; i++) { 80 | node_type = get_type(parse_tree[i]); 81 | if (node_type === 'string') { 82 | output.push(parse_tree[i]); 83 | } 84 | else if (node_type === 'array') { 85 | match = parse_tree[i]; // convenience purposes only 86 | if (match[2]) { // keyword argument 87 | arg = argv[cursor]; 88 | for (k = 0; k < match[2].length; k++) { 89 | if (!arg.hasOwnProperty(match[2][k])) { 90 | throw(sprintf('[sprintf] property "%s" does not exist', match[2][k])); 91 | } 92 | arg = arg[match[2][k]]; 93 | } 94 | } 95 | else if (match[1]) { // positional argument (explicit) 96 | arg = argv[match[1]]; 97 | } 98 | else { // positional argument (implicit) 99 | arg = argv[cursor++]; 100 | } 101 | 102 | if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) { 103 | throw(sprintf('[sprintf] expecting number but found %s', get_type(arg))); 104 | } 105 | switch (match[8]) { 106 | case 'b': arg = arg.toString(2); break; 107 | case 'c': arg = String.fromCharCode(arg); break; 108 | case 'd': arg = parseInt(arg, 10); break; 109 | case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break; 110 | case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break; 111 | case 'o': arg = arg.toString(8); break; 112 | case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break; 113 | case 'u': arg = Math.abs(arg); break; 114 | case 'x': arg = arg.toString(16); break; 115 | case 'X': arg = arg.toString(16).toUpperCase(); break; 116 | } 117 | arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg); 118 | pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' '; 119 | pad_length = match[6] - String(arg).length; 120 | pad = match[6] ? str_repeat(pad_character, pad_length) : ''; 121 | output.push(match[5] ? arg + pad : pad + arg); 122 | } 123 | } 124 | return output.join(''); 125 | }; 126 | 127 | str_format.cache = {}; 128 | 129 | str_format.parse = function(fmt) { 130 | var _fmt = fmt, match = [], parse_tree = [], arg_names = 0; 131 | while (_fmt) { 132 | if ((match = /^[^\x25]+/.exec(_fmt)) !== null) { 133 | parse_tree.push(match[0]); 134 | } 135 | else if ((match = /^\x25{2}/.exec(_fmt)) !== null) { 136 | parse_tree.push('%'); 137 | } 138 | else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) { 139 | if (match[2]) { 140 | arg_names |= 1; 141 | var field_list = [], replacement_field = match[2], field_match = []; 142 | if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { 143 | field_list.push(field_match[1]); 144 | while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') { 145 | if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { 146 | field_list.push(field_match[1]); 147 | } 148 | else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) { 149 | field_list.push(field_match[1]); 150 | } 151 | else { 152 | throw('[sprintf] huh?'); 153 | } 154 | } 155 | } 156 | else { 157 | throw('[sprintf] huh?'); 158 | } 159 | match[2] = field_list; 160 | } 161 | else { 162 | arg_names |= 2; 163 | } 164 | if (arg_names === 3) { 165 | throw('[sprintf] mixing positional and named placeholders is not (yet) supported'); 166 | } 167 | parse_tree.push(match); 168 | } 169 | else { 170 | throw('[sprintf] huh?'); 171 | } 172 | _fmt = _fmt.substring(match[0].length); 173 | } 174 | return parse_tree; 175 | }; 176 | 177 | return str_format; 178 | })(); 179 | 180 | var vsprintf = function(fmt, argv) { 181 | argv.unshift(fmt); 182 | return sprintf.apply(null, argv); 183 | }; 184 | 185 | -------------------------------------------------------------------------------- /library/70-module.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2010 Jared Forsyth 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated documentation 6 | files (the "Software"), to deal in the Software without 7 | restriction, including without limitation the rights to use, 8 | copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | **/ 26 | 27 | /** general module loading... not spectacular, I know; it gets better when you 28 | * add sys and __builtins__ 29 | **/ 30 | 31 | var __module_cache = {}; 32 | function module(filename, fn) { 33 | var that = {}; 34 | that.__file__ = filename; 35 | that.__init__ = fn; 36 | that.load = $m({'mod':null}, function load_module(name, mod) { 37 | if (mod === null) mod = {}; 38 | mod.__name__ = name; 39 | if (__builtins__) mod.__name__ = __builtins__.str(name); 40 | mod.__file__ = that.__file__; 41 | if (__builtins__) mod.__file__ = __builtins__.str(that.__file__); 42 | mod.__dict__ = mod; 43 | that._module = mod; 44 | fn(mod); 45 | return mod; 46 | }); 47 | __module_cache[that.__file__] = that; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /library/71-ie-fix.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2010 Jared Forsyth 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated documentation 6 | files (the "Software"), to deal in the Software without 7 | restriction, including without limitation the rights to use, 8 | copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | **/ 26 | 27 | // dumb IE fix 28 | if (!Array.prototype.indexOf) 29 | { 30 | Array.prototype.indexOf = function(elt /*, from*/) 31 | { 32 | var len = this.length >>> 0; 33 | 34 | var from = Number(arguments[1]) || 0; 35 | from = (from < 0) 36 | ? Math.ceil(from) 37 | : Math.floor(from); 38 | if (from < 0) 39 | from += len; 40 | 41 | for (; from < len; from++) 42 | { 43 | if (from in this && 44 | this[from] === elt) 45 | return from; 46 | } 47 | return -1; 48 | }; 49 | } 50 | 51 | //include slice method 52 | if (!Array.slice) 53 | { 54 | Array.slice= function(){ 55 | array_like = arguments[0]; 56 | start = arguments[1]; 57 | end = arguments[2]; 58 | arr=[]; 59 | if(end === undefined){ 60 | for(var i = start; i < array_like.length; i++){ 61 | arr[i-start] = array_like[i]; 62 | } 63 | }else{ 64 | for(var i = start; i < end; i++){ 65 | arr[i-start] = array_like[i]; 66 | } 67 | } 68 | return arr; 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /library/72-notimplemented.js: -------------------------------------------------------------------------------- 1 | /** 2 | Now you can import stuff...just like in python. 3 | **/ 4 | 5 | var __not_implemented__ = function __not_implemented__(name) { 6 | return function not_implemented() { 7 | if (arguments.callee.__name__) 8 | name = arguments.callee.__name__; 9 | $b.raise($b.NotImplementedError("the builtin function "+name+" is not implemented yet. You should help out and add it =)")); 10 | }; 11 | }; 12 | 13 | -------------------------------------------------------------------------------- /library/73-module-sys.js: -------------------------------------------------------------------------------- 1 | module('/sys.py', function sys_module(_) { 2 | _.__doc__ = "The PJs module responsible for system stuff"; 3 | _.modules = {'sys':_}; // sys and __builtin__ won't be listed 4 | // it doesn't make sense for them to be 5 | // reloadable. 6 | _.path = ['.', '']; 7 | _.exit = $m({'code':0}, function exit(code) { 8 | _.raise("SystemExit: sys.exit() was called with code "+code); 9 | }); 10 | }); 11 | 12 | -------------------------------------------------------------------------------- /library/74-module-path.js: -------------------------------------------------------------------------------- 1 | module('/os/path.py', function os_path_module(_) { 2 | _.__doc__ = "a module for dealing with paths"; 3 | _.join = $m({}, true, function join(first, args) { 4 | first = $b.js(first); 5 | args = $b.js(args); 6 | var path = first; 7 | for (var i=0;i 0 && comps[i-1] && comps[i-1] != '..') { 46 | comps = comps.slice(0, i-1).concat(comps.slice(i+1)); 47 | i -= 1; 48 | } else if (comps[i] == '' && i > 0 && comps[i-1] != '') { 49 | comps = comps.slice(0, i).concat(comps.slice(i+1)); 50 | } else 51 | i += 1 52 | } 53 | if (!prefix && !comps) 54 | comps.push('.'); 55 | return $b.str(prefix + comps.join('/')); 56 | }); 57 | }); 58 | 59 | -------------------------------------------------------------------------------- /library/76-module-init.js: -------------------------------------------------------------------------------- 1 | 2 | __module_cache['/sys.py'].load('sys'); // must be loaded for importing to work. 3 | __module_cache['/os/path.py'].load('os.path'); 4 | var __builtins__ = __module_cache['/__builtin__.py'].load('__builtin__'); 5 | var __import__ = __builtins__.__import__; // should I make this global? 6 | var $b = __builtins__; 7 | 8 | var $def = $m; 9 | -------------------------------------------------------------------------------- /py2js/decorator.py: -------------------------------------------------------------------------------- 1 | from py2js import convert_py2js 2 | import inspect 3 | 4 | class JavaScript(object): 5 | """ 6 | Decorator that you can use to convert methods to JavaScript. 7 | 8 | For example this code:: 9 | 10 | @JavaScript 11 | class TestClass(object): 12 | def __init__(self): 13 | alert('TestClass created') 14 | self.reset() 15 | 16 | def reset(self): 17 | self.value = 0 18 | 19 | def inc(self): 20 | alert(self.value) 21 | self.value += 1 22 | 23 | print str(TestClass) 24 | 25 | prints:: 26 | 27 | function TestClass() { 28 | return new _TestClass(); 29 | } 30 | function _TestClass() { 31 | this.__init__(); 32 | } 33 | _TestClass.__name__ = 'TestClass' 34 | _TestClass.prototype.__class__ = _TestClass 35 | _TestClass.prototype.__init__ = function() { 36 | alert("TestClass created"); 37 | this.reset(); 38 | } 39 | _TestClass.prototype.reset = function() { 40 | this.value = 0; 41 | } 42 | _TestClass.prototype.inc = function() { 43 | alert(this.value); 44 | this.value += 1; 45 | } 46 | 47 | Alternatively, an equivalent way is to use JavaScript() as a function: 48 | 49 | class TestClass(object): 50 | def __init__(self): 51 | alert('TestClass created') 52 | self.reset() 53 | 54 | def reset(self): 55 | self.value = 0 56 | 57 | def inc(self): 58 | alert(self.value) 59 | self.value += 1 60 | 61 | print str(JavaScript(TestClass)) 62 | 63 | If you want to call the original function/class as Python, use the 64 | following syntax:: 65 | 66 | js = JavaScript(TestClass) 67 | test_class = js() # Python instance of TestClass() will be created 68 | js_class = str(js) # A string with the JS code 69 | 70 | """ 71 | 72 | def __init__(self, obj): 73 | self._obj = obj 74 | obj_source = inspect.getsource(obj) 75 | self._js = convert_py2js(obj_source) 76 | 77 | def __str__(self): 78 | return self._js 79 | 80 | def __call__(self, *args, **kwargs): 81 | return self._obj(*args, **kwargs) 82 | 83 | -------------------------------------------------------------------------------- /py2js/formater.py: -------------------------------------------------------------------------------- 1 | """ A formater module that keeps trac of indentation 2 | """ 3 | class Formater(object): 4 | """ 5 | A very simple code formater that handles efficient concatenation and indentation of lines. 6 | """ 7 | 8 | def __init__(self, indent_string=" "): 9 | self.__buffer = [] 10 | self.__indentation = 0 11 | self.__indent_string = indent_string 12 | self.__indent_temp = "" 13 | self.__string_buffer = "" 14 | 15 | def dedent(self): 16 | """ 17 | Subtracts one indentation level. 18 | """ 19 | self.__indentation -= 1 20 | self.__indent_temp = self.__indent_string*self.__indentation 21 | 22 | def indent(self): 23 | """ 24 | Adds one indentation level. 25 | """ 26 | self.__indentation += 1 27 | self.__indent_temp = self.__indent_string*self.__indentation 28 | 29 | def write(self, text, indent=True, newline=True): 30 | """ 31 | Writes the string text to the buffer with indentation and a newline if not specified otherwise. 32 | """ 33 | if indent: 34 | self.__buffer.append(self.__indent_temp) 35 | self.__buffer.append(text) 36 | if newline: 37 | self.__buffer.append("\n") 38 | 39 | def read(self, size=None): 40 | """ 41 | Returns a string representation of the buffer. 42 | """ 43 | if size == None: 44 | text = self.__string_buffer + "".join(self.__buffer) 45 | self.__buffer = [] 46 | self.__string_buffer = "" 47 | return text 48 | else: 49 | if len(self.__string_buffer) < size: 50 | self.__string_buffer += "".join(self.__buffer) 51 | self.__buffer = [] 52 | if len(self.__string_buffer) < size: 53 | text, self.__string_buffer = self.__string_buffer, "" 54 | return text 55 | else: 56 | text, self.__string_buffer = self.__string_buffer[:size], \ 57 | self.__string_buffer[size:] 58 | return text 59 | else: 60 | text, self.__string_buffer = self.__string_buffer[:size], \ 61 | self.__string_buffer[size:] 62 | return text 63 | 64 | -------------------------------------------------------------------------------- /pyjs.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | import sys 4 | import os.path 5 | from optparse import OptionParser 6 | from py2js import convert_py2js 7 | 8 | def main(): 9 | parser = OptionParser(usage="%prog [options] filename", 10 | description="Python to JavaScript compiler.") 11 | 12 | parser.add_option("--output", 13 | action="store", 14 | dest="output", 15 | help="write output to OUTPUT") 16 | 17 | parser.add_option("--include-builtins", 18 | action="store_true", 19 | dest="include_builtins", 20 | default=False, 21 | help="include py-builtins.js library in the output") 22 | 23 | options, args = parser.parse_args() 24 | if len(args) == 1: 25 | filename = args[0] 26 | 27 | if options.output: 28 | output = open(options.output, "w") 29 | else: 30 | output = sys.stdout 31 | 32 | if options.include_builtins: 33 | if os.path.dirname(__file__): 34 | builtins = open(os.path.join(os.path.dirname(__file__), 35 | "py-builtins.js")).read() 36 | else: 37 | builtins = open("py-builtins.js").read() 38 | output.write(builtins) 39 | 40 | s = open(filename).read() #unsafe for large files! 41 | output.write(convert_py2js(s)) 42 | else: 43 | parser.print_help() 44 | 45 | if __name__ == '__main__': 46 | main() 47 | -------------------------------------------------------------------------------- /pylint.conf: -------------------------------------------------------------------------------- 1 | [MASTER] 2 | 3 | # Specify a configuration file. 4 | #rcfile= 5 | 6 | # Python code to execute, usually for sys.path manipulation such as 7 | # pygtk.require(). 8 | #init-hook= 9 | 10 | # Profiled execution. 11 | profile=no 12 | 13 | # Add to the black list. It should be a base name, not a 14 | # path. You may set this option multiple times. 15 | ignore=CVS 16 | 17 | # Pickle collected data for later comparisons. 18 | persistent=yes 19 | 20 | # List of plugins (as comma separated values of python modules names) to load, 21 | # usually to register additional checkers. 22 | load-plugins= 23 | 24 | 25 | [MESSAGES CONTROL] 26 | 27 | # Enable the message, report, category or checker with the given id(s). You can 28 | # either give multiple identifier separated by comma (,) or put this option 29 | # multiple time. 30 | #enable= 31 | 32 | # Disable the message, report, category or checker with the given id(s). You 33 | # can either give multiple identifier separated by comma (,) or put this option 34 | # multiple time (only on the command line, not in the configuration file where 35 | # it should appear only once). 36 | disable=E0202, W0404, W0142 37 | 38 | 39 | [REPORTS] 40 | 41 | # Set the output format. Available formats are text, parseable, colorized, msvs 42 | # (visual studio) and html 43 | output-format=text 44 | 45 | # Include message's id in output 46 | include-ids=yes 47 | 48 | # Put messages in a separate file for each module / package specified on the 49 | # command line instead of printing them on stdout. Reports (if any) will be 50 | # written in a file name "pylint_global.[txt|html]". 51 | files-output=no 52 | 53 | # Tells whether to display a full report or only the messages 54 | reports=yes 55 | 56 | # Python expression which should return a note less than 10 (10 is the highest 57 | # note). You have access to the variables errors warning, statement which 58 | # respectively contain the number of errors / warnings messages and the total 59 | # number of statements analyzed. This is used by the global evaluation report 60 | # (RP0004). 61 | evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) 62 | 63 | # Add a comment according to your evaluation note. This is used by the global 64 | # evaluation report (RP0004). 65 | comment=no 66 | 67 | 68 | [BASIC] 69 | 70 | # Required attributes for module, separated by a comma 71 | required-attributes= 72 | 73 | # List of builtins function names that should not be used, separated by a comma 74 | bad-functions=map,filter,apply,input 75 | 76 | # Regular expression which should only match correct module names 77 | module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ 78 | 79 | # Regular expression which should only match correct module level names 80 | const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ 81 | 82 | # Regular expression which should only match correct class names 83 | class-rgx=[A-Z_][a-zA-Z0-9]+$ 84 | 85 | # Regular expression which should only match correct function names 86 | function-rgx=([a-z_][a-z0-9_]{2,30}$)|([a-z_]*([A-Z0-9_][a-z0-9_]*)*$) 87 | 88 | # Regular expression which should only match correct method names 89 | method-rgx=([a-z_][a-z0-9_]{2,30}$)|([a-z_]*([A-Z0-9_][a-z0-9_]*)*$) 90 | 91 | # Regular expression which should only match correct instance attribute names 92 | attr-rgx=[a-z_][a-z0-9_]{2,30}$ 93 | 94 | # Regular expression which should only match correct argument names 95 | argument-rgx=[a-z_][a-z0-9_]{2,30}$ 96 | 97 | # Regular expression which should only match correct variable names 98 | variable-rgx=[a-z_][a-z0-9_]{2,30}$ 99 | 100 | # Regular expression which should only match correct list comprehension / 101 | # generator expression variable names 102 | inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ 103 | 104 | # Good variable names which should always be accepted, separated by a comma 105 | good-names=i,j,k,ex,Run,_ 106 | 107 | # Bad variable names which should always be refused, separated by a comma 108 | bad-names=foo,bar,baz,toto,tutu,tata 109 | 110 | # Regular expression which should only match functions or classes name which do 111 | # not require a docstring 112 | no-docstring-rgx=__.*__ 113 | 114 | 115 | [FORMAT] 116 | 117 | # Maximum number of characters on a single line. 118 | max-line-length=80 119 | 120 | # Maximum number of lines in a module 121 | max-module-lines=1000 122 | 123 | # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 124 | # tab). 125 | indent-string=' ' 126 | 127 | 128 | [MISCELLANEOUS] 129 | 130 | # List of note tags to take in consideration, separated by a comma. 131 | notes=FIXME,XXX,TODO 132 | 133 | 134 | [SIMILARITIES] 135 | 136 | # Minimum lines number of a similarity. 137 | min-similarity-lines=4 138 | 139 | # Ignore comments when computing similarities. 140 | ignore-comments=yes 141 | 142 | # Ignore docstrings when computing similarities. 143 | ignore-docstrings=yes 144 | 145 | 146 | [TYPECHECK] 147 | 148 | # Tells whether missing members accessed in mixin class should be ignored. A 149 | # mixin class is detected if its name ends with "mixin" (case insensitive). 150 | ignore-mixin-members=yes 151 | 152 | # List of classes names for which member attributes should not be checked 153 | # (useful for classes with attributes dynamically set). 154 | ignored-classes=SQLObject 155 | 156 | # When zope mode is activated, add a predefined set of Zope acquired attributes 157 | # to generated-members. 158 | zope=no 159 | 160 | # List of members which are set dynamically and missed by pylint inference 161 | # system, and so shouldn't trigger E0201 when accessed. 162 | generated-members=REQUEST,acl_users,aq_parent 163 | 164 | 165 | [VARIABLES] 166 | 167 | # Tells whether we should check for unused import in __init__ files. 168 | init-import=no 169 | 170 | # A regular expression matching the beginning of the name of dummy variables 171 | # (i.e. not used). 172 | dummy-variables-rgx=_|dummy 173 | 174 | # List of additional names supposed to be defined in builtins. Remember that 175 | # you should avoid to define new builtins when possible. 176 | additional-builtins= 177 | 178 | 179 | [CLASSES] 180 | 181 | # List of interface methods to ignore, separated by a comma. This is used for 182 | # instance to not check methods defines in Zope's Interface base class. 183 | ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by 184 | 185 | # List of method names used to declare (i.e. assign) instance attributes. 186 | defining-attr-methods=__init__,__new__,setUp 187 | 188 | 189 | [DESIGN] 190 | 191 | # Maximum number of arguments for function / method 192 | max-args=5 193 | 194 | # Argument names that match this expression will be ignored. Default to name 195 | # with leading underscore 196 | ignored-argument-names=_.* 197 | 198 | # Maximum number of locals for function / method body 199 | max-locals=15 200 | 201 | # Maximum number of return / yield for function / method body 202 | max-returns=6 203 | 204 | # Maximum number of branch for function / method body 205 | max-branchs=12 206 | 207 | # Maximum number of statements in function / method body 208 | max-statements=50 209 | 210 | # Maximum number of parents for a class (see R0901). 211 | max-parents=7 212 | 213 | # Maximum number of attributes for a class (see R0902). 214 | max-attributes=7 215 | 216 | # Minimum number of public methods for a class (see R0903). 217 | min-public-methods=0 218 | 219 | # Maximum number of public methods for a class (see R0904). 220 | max-public-methods=80 221 | 222 | 223 | [IMPORTS] 224 | 225 | # Deprecated modules which should not be used, separated by a comma 226 | deprecated-modules=regsub,string,TERMIOS,Bastion,rexec 227 | 228 | # Create a graph of every (i.e. internal and external) dependencies in the 229 | # given file (report RP0402 must not be disabled) 230 | import-graph= 231 | 232 | # Create a graph of external dependencies in the given file (report RP0402 must 233 | # not be disabled) 234 | ext-import-graph= 235 | 236 | # Create a graph of internal dependencies in the given file (report RP0402 must 237 | # not be disabled) 238 | int-import-graph= 239 | -------------------------------------------------------------------------------- /run_tests.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/python 2 | 3 | import optparse 4 | import testtools.runner 5 | import testtools.util 6 | import testtools.tests 7 | 8 | def main(): 9 | option_parser = optparse.OptionParser( 10 | usage="%prog [options] [filenames]", 11 | description="py2js unittests script." 12 | ) 13 | option_parser.add_option( 14 | "-a", 15 | "--run-all", 16 | action="store_true", 17 | dest="run_all", 18 | default=False, 19 | help="run all tests (including the known-to-fail)" 20 | ) 21 | option_parser.add_option( 22 | "-x", 23 | "--no-error", 24 | action="store_true", 25 | dest="no_error", 26 | default=False, 27 | help="ignores error( don't display them after tests)" 28 | ) 29 | options, args = option_parser.parse_args() 30 | runner = testtools.runner.Py2JsTestRunner(verbosity=2) 31 | results = None 32 | if options.run_all: 33 | results = runner.run(testtools.tests.ALL) 34 | elif args: 35 | results = runner.run(testtools.tests.get_tests(args)) 36 | else: 37 | results = runner.run(testtools.tests.NOT_KNOWN_TO_FAIL) 38 | if not options.no_error and results.errors: 39 | print 40 | print "errors:" 41 | print " (use -x to skip this part)" 42 | for test, error in results.errors: 43 | print 44 | print "*", str(test), "*" 45 | print error 46 | 47 | if __name__ == "__main__": 48 | main() 49 | -------------------------------------------------------------------------------- /tests/algorithms/sqrt.py: -------------------------------------------------------------------------------- 1 | def abs(x): 2 | if x > 0: 3 | return x 4 | else: 5 | return -x 6 | 7 | def sqrt(x): 8 | eps = 1e-10 9 | x = float(x) 10 | r = x/2 11 | residual = r**2 - x 12 | while abs(residual) > eps: 13 | r_d = -residual/(2*r) 14 | r += r_d 15 | residual = r**2 - x 16 | return r 17 | 18 | def p(x): 19 | prec = 11 20 | l = list(iter(str(x)))[:prec] 21 | if not "." in l: 22 | l.append(".") 23 | l.append("0") 24 | while len(l) < prec: 25 | l.append("0") 26 | s = "" 27 | for c in l: 28 | s += c 29 | return s 30 | 31 | print p(sqrt(1)) 32 | print p(sqrt(2)) 33 | print p(sqrt(3)) 34 | print p(sqrt(4)) 35 | print p(sqrt(5)) 36 | print p(sqrt(6)) 37 | print p(sqrt(7000)) 38 | -------------------------------------------------------------------------------- /tests/algorithms/triangulation.py: -------------------------------------------------------------------------------- 1 | def abs(x): 2 | if x > 0: 3 | return x 4 | else: 5 | return -x 6 | 7 | def sqrt(x): 8 | eps = 1e-10 9 | x = float(x) 10 | r = x/2 11 | residual = r**2 - x 12 | while abs(residual) > eps: 13 | r_d = -residual/(2*r) 14 | r += r_d 15 | residual = r**2 - x 16 | return r 17 | 18 | def is_on_the_left(c, a, b, pts_list): 19 | ax, ay = pts_list[a] 20 | bx, by = pts_list[b] 21 | cx, cy = pts_list[c] 22 | ux = float(bx - ax) 23 | uy = float(by - ay) 24 | vx = float(cx - ax) 25 | vy = float(cy - ay) 26 | return (ux*vy - uy*vx > 0) 27 | 28 | def criterion(a, b, c, pts_list): 29 | ax, ay = pts_list[a] 30 | bx, by = pts_list[b] 31 | cx, cy = pts_list[c] 32 | ux = float(ax - cx) 33 | uy = float(ay - cy) 34 | vx = float(bx - cx) 35 | vy = float(by - cy) 36 | len_u = sqrt(ux*ux + uy*uy) 37 | len_v = sqrt(vx*vx + vy*vy) 38 | return (ux*vx + uy*vy)/(len_u*len_v) 39 | 40 | def find_third_point(a, b, pts_list, edges): 41 | """ 42 | Take a boundary edge (a,b), and in the list of points 43 | find a point 'c' that lies on the left of ab and maximizes 44 | the angle acb 45 | """ 46 | found = 0 47 | minimum = 10**8 #this is dirty 48 | c_index = -1 49 | pt_index = -1 50 | for c_point in pts_list: 51 | c_index += 1 52 | if c_index != a and c_index != b and is_on_the_left(c_index, a, b, pts_list): 53 | edge_intersects = \ 54 | edge_intersects_edges((a, c_index), pts_list, edges) or \ 55 | edge_intersects_edges((b, c_index), pts_list, edges) 56 | if not edge_intersects: 57 | crit = criterion(a, b, c_index, pts_list) 58 | if crit < minimum: 59 | minimum = crit 60 | pt_index = c_index 61 | found = 1 62 | if found == 0: 63 | raise TriangulationError("ERROR: Optimal point not found in find_third_point().") 64 | return pt_index 65 | 66 | def lies_inside(c, bdy_edges): 67 | for edge in bdy_edges: 68 | a,b = edge 69 | if c == a or c == b: return False 70 | return True 71 | 72 | def is_boundary_edge(a, b, bdy_edges): 73 | """ 74 | Checks whether edge (a, b) is in the list of boundary edges 75 | """ 76 | for edge in bdy_edges: 77 | a0, b0 = edge 78 | if a == a0 and b == b0: 79 | return True 80 | return False 81 | 82 | def triangulate_af(pts_list, bdy_edges): 83 | """ 84 | Create a triangulation using the advancing front method. 85 | """ 86 | # create empty list of elements 87 | elems = [] 88 | bdy_edges = bdy_edges[:] 89 | # main loop 90 | while bdy_edges != []: 91 | # take the last item from the list of bdy edges (and remove it) 92 | a,b = bdy_edges.pop() 93 | c = find_third_point(a, b, pts_list, bdy_edges) 94 | elems.append((a,b,c)) 95 | if is_boundary_edge(c, a, bdy_edges): 96 | bdy_edges.remove((c,a)) 97 | else: 98 | bdy_edges.append((a,c)) 99 | if is_boundary_edge(b, c, bdy_edges): 100 | bdy_edges.remove((b,c)) 101 | else: 102 | bdy_edges.append((c,b)) 103 | return elems 104 | 105 | def ccw(A, B, C): 106 | return (C[1]-A[1])*(B[0]-A[0]) > (B[1]-A[1])*(C[0]-A[0]) 107 | 108 | def intersect(A, B, C, D): 109 | return ccw(A, C, D) != ccw(B, C, D) and ccw(A, B, C) != ccw(A, B, D) 110 | 111 | def two_edges_intersect(nodes, e1, e2): 112 | """ 113 | Checks whether the two edges intersect. 114 | 115 | It assumes that e1 and e2 are tuples of (a_id, b_id) of ids into the nodes. 116 | """ 117 | A = nodes[e1[0]] 118 | B = nodes[e1[1]] 119 | C = nodes[e2[0]] 120 | D = nodes[e2[1]] 121 | return intersect(A, B, C, D) 122 | 123 | def any_edges_intersect(nodes, edges): 124 | """ 125 | Returns True if any two edges intersect. 126 | """ 127 | for i in range(len(edges)): 128 | for j in range(i+1, len(edges)): 129 | e1 = edges[i] 130 | e2 = edges[j] 131 | if e1[1] == e2[0] or e1[0] == e2[1]: 132 | continue 133 | if two_edges_intersect(nodes, e1, e2): 134 | return True 135 | return False 136 | 137 | def edge_intersects_edges(e1, nodes, edges): 138 | """ 139 | Returns True if "e1" intersects any edge from "edges". 140 | """ 141 | for i in range(len(edges)): 142 | e2 = edges[i] 143 | if e1[1] == e2[0] or e1[0] == e2[1]: 144 | continue 145 | if two_edges_intersect(nodes, e1, e2): 146 | return True 147 | return False 148 | 149 | def example1(): 150 | nodes = [ 151 | (0, 0), 152 | (1, 0), 153 | (1, 1), 154 | (0, 1), 155 | ] 156 | edges = [(0, 1), (1, 2), (2, 3), (3, 0)] 157 | elems = triangulate_af(nodes, edges) 158 | return nodes, edges, elems 159 | 160 | def example2(): 161 | nodes = [ 162 | (0, 0), 163 | (1, 0), 164 | (2, 1), 165 | (2, 2), 166 | (1, 2), 167 | (0.5, 1.5), 168 | (0, 1), 169 | ] 170 | edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 0)] 171 | elems = triangulate_af(nodes, edges) 172 | return nodes, edges, elems 173 | 174 | nodes, edges, elems = example1() 175 | print nodes 176 | print edges 177 | print elems 178 | if not any_edges_intersect(nodes, edges): 179 | print "ok" 180 | 181 | print 182 | nodes, edges, elems = example2() 183 | print nodes 184 | print edges 185 | print elems 186 | if not any_edges_intersect(nodes, edges): 187 | print "ok" 188 | -------------------------------------------------------------------------------- /tests/basic/assign_slice.py: -------------------------------------------------------------------------------- 1 | 2 | a = [1,2,3,4,5,6,7] 3 | 4 | a[4:6] = ['a','b'] 5 | 6 | def show(x): 7 | print "----" 8 | for x in a: 9 | print x 10 | 11 | show(a) 12 | 13 | 14 | a[2:4] = ['z'] 15 | 16 | show(a) 17 | 18 | a[0:2] = ['abc','def','abc','def'] 19 | 20 | show(a) 21 | -------------------------------------------------------------------------------- /tests/basic/augassign.py: -------------------------------------------------------------------------------- 1 | 2 | a = 1 3 | a += 1 4 | print a 5 | a += 3 6 | print a 7 | a -= 2 8 | print a 9 | -------------------------------------------------------------------------------- /tests/basic/augassign2.py: -------------------------------------------------------------------------------- 1 | def f1(x): 2 | return x 3 | 4 | def f2(x): 5 | return x + 5 6 | 7 | def f3(x): 8 | a = x + 1 9 | return a - 5 10 | 11 | def f3b(x): 12 | a = x + 1 13 | a -= 5 14 | return a 15 | 16 | def f3c(x): 17 | a = float(x) + 1 18 | a /= 5 19 | return a 20 | 21 | def f3d(x): 22 | a = x + 1 23 | a *= 5 24 | return a 25 | 26 | def f3e(x): 27 | a = x + 1 28 | a += 5 29 | return a 30 | 31 | def f4(x): 32 | if x: 33 | return 5 34 | else: 35 | return 6 36 | 37 | def f5(x): 38 | a = 1 39 | if x: 40 | a = a + 1 41 | else: 42 | a = a - 1 43 | return a 44 | 45 | print f1(3) 46 | print f2(3) 47 | print f3(3) 48 | print f3b(3) 49 | print f3c(3) 50 | print f3d(3) 51 | print f3e(3) 52 | print f4(True) 53 | print f4(False) 54 | print f5(True) 55 | print f5(False) 56 | -------------------------------------------------------------------------------- /tests/basic/binaryops.py: -------------------------------------------------------------------------------- 1 | 2 | x = 1 3 | y = 2 4 | z = 3 5 | 6 | print 10 % z 7 | print y*x 8 | print y-z 9 | print y+x+z 10 | print 10 / 2 11 | print 10 ** 2 12 | -------------------------------------------------------------------------------- /tests/basic/break.py: -------------------------------------------------------------------------------- 1 | 2 | x = 0 3 | 4 | while True: 5 | x = x + 1 6 | print x 7 | if x > 10: 8 | break 9 | -------------------------------------------------------------------------------- /tests/basic/class.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class foobar(object): 4 | 5 | x = 1 6 | 7 | def __init__(self): 8 | self.foovar = 1 9 | 10 | def foo(self,x): 11 | self.foovar = self.foovar + x 12 | 13 | def bar(self): 14 | print self.foovar 15 | 16 | f = foobar() 17 | f.bar() 18 | f.foo(1) 19 | f.foo(2) 20 | f.bar() 21 | f.bar() 22 | f.foo(-1) 23 | f.bar() 24 | f.foo(7) 25 | f.bar() 26 | 27 | 28 | -------------------------------------------------------------------------------- /tests/basic/class2.py: -------------------------------------------------------------------------------- 1 | class Class1(object): 2 | 3 | def __init__(self): 4 | pass 5 | 6 | def test1(self): 7 | return 5 8 | 9 | class Class2(object): 10 | 11 | def test1(self): 12 | return 6 13 | 14 | class Class3(object): 15 | 16 | def test1(self, x): 17 | return self.test2(x)-1 18 | 19 | def test2(self, x): 20 | return 2*x 21 | 22 | a = Class1() 23 | print a.test1() 24 | 25 | a = Class2() 26 | print a.test1() 27 | 28 | a = Class3() 29 | print a.test1(3) 30 | print a.test2(3) 31 | -------------------------------------------------------------------------------- /tests/basic/class3.py: -------------------------------------------------------------------------------- 1 | class A(object): 2 | v = 1 3 | 4 | a = A() 5 | XX = A 6 | x = XX() 7 | print x.v 8 | -------------------------------------------------------------------------------- /tests/basic/class4.py: -------------------------------------------------------------------------------- 1 | def create(cls): 2 | return cls() 3 | 4 | class A(object): 5 | def m(self): 6 | print "A.m()" 7 | 8 | a = A() 9 | a.m() 10 | 11 | b = create(A) 12 | b.m() 13 | -------------------------------------------------------------------------------- /tests/basic/class5.py: -------------------------------------------------------------------------------- 1 | def create(cls): 2 | return cls() 3 | 4 | class A: 5 | def m(self): 6 | print "A.m()" 7 | 8 | a = A() 9 | a.m() 10 | 11 | b = create(A) 12 | b.m() 13 | -------------------------------------------------------------------------------- /tests/basic/class6.py: -------------------------------------------------------------------------------- 1 | def create(cls): 2 | return cls() 3 | 4 | class A: 5 | def __init__(self): 6 | self.msg = "A.m()" 7 | def m(self): 8 | print self.msg 9 | 10 | a = A() 11 | a.m() 12 | 13 | b = create(A) 14 | b.m() 15 | -------------------------------------------------------------------------------- /tests/basic/closure.py: -------------------------------------------------------------------------------- 1 | 2 | def factory(x): 3 | 4 | def fn(): 5 | return x 6 | 7 | return fn 8 | 9 | a1 = factory("foo") 10 | a2 = factory("bar") 11 | print a1() 12 | print a2() 13 | -------------------------------------------------------------------------------- /tests/basic/continue.py: -------------------------------------------------------------------------------- 1 | 2 | for x in xrange(0,20): 3 | if x > 10 and x < 17: 4 | continue 5 | print x 6 | -------------------------------------------------------------------------------- /tests/basic/default.py: -------------------------------------------------------------------------------- 1 | g = 99 2 | 3 | def f(a, b=1, c="default c", d=g): 4 | print a 5 | print b 6 | print c 7 | print d 8 | 9 | f(0) 10 | f(0, 77) 11 | f(0, 77, "hello") 12 | -------------------------------------------------------------------------------- /tests/basic/del_array.py: -------------------------------------------------------------------------------- 1 | 2 | mylist = [1,2,3,4,5] 3 | 4 | del mylist[3] 5 | 6 | for x in xrange(0,len(mylist)): 7 | print mylist[x] 8 | -------------------------------------------------------------------------------- /tests/basic/del_attr.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class spam: 4 | 5 | def __init__(self): 6 | self.eggs = 0 7 | 8 | def addegg(self): 9 | try: 10 | if self.eggs: 11 | self.eggs += 1 12 | else: 13 | self.eggs = 1 14 | except: 15 | self.eggs = 1 16 | 17 | def printit(self): 18 | try: 19 | if self.eggs: 20 | print self.eggs 21 | else: 22 | print "no eggs" 23 | except: 24 | print "no eggs" 25 | 26 | 27 | s = spam() 28 | s.addegg() 29 | s.addegg() 30 | s.printit() 31 | s.addegg() 32 | s.printit() 33 | del s.eggs 34 | s.printit() 35 | s.addegg() 36 | s.addegg() 37 | s.printit() 38 | -------------------------------------------------------------------------------- /tests/basic/del_dict.py: -------------------------------------------------------------------------------- 1 | 2 | mydict = {} 3 | 4 | mydict["abc"] = "def" 5 | mydict["def"] = "abc" 6 | mydict["xyz"] = "rst" 7 | 8 | print mydict["abc"] 9 | print mydict["def"] 10 | print mydict["xyz"] 11 | 12 | del mydict["def"] 13 | 14 | if "abc" in mydict: 15 | print "abc in mydict" 16 | else: 17 | print "abc not in mydict" 18 | 19 | if "def" in mydict: 20 | print "def in mydict" 21 | else: 22 | print "def not in mydict" 23 | 24 | if "xyz" in mydict: 25 | print "xyz in mydict" 26 | else: 27 | print "xyz not in mydict" 28 | -------------------------------------------------------------------------------- /tests/basic/del_global.py: -------------------------------------------------------------------------------- 1 | 2 | x = 1 3 | 4 | def foo(): 5 | global x 6 | del x 7 | 8 | print x 9 | 10 | foo() 11 | 12 | try: 13 | print x 14 | except: 15 | print "x is gone" 16 | -------------------------------------------------------------------------------- /tests/basic/del_local.py: -------------------------------------------------------------------------------- 1 | 2 | x = "ABC" 3 | 4 | print x 5 | 6 | del x 7 | 8 | try: 9 | print x 10 | except: 11 | print "x is gone" 12 | -------------------------------------------------------------------------------- /tests/basic/del_slice.py: -------------------------------------------------------------------------------- 1 | 2 | mylist = [1,2,3,4,5] 3 | 4 | del mylist[1:3] 5 | 6 | for x in xrange(0,len(mylist)): 7 | print mylist[x] 8 | -------------------------------------------------------------------------------- /tests/basic/dictionary.py: -------------------------------------------------------------------------------- 1 | 2 | foo = { 'a':'b', 'c':'d' } 3 | 4 | print foo['a'] 5 | print foo['c'] 6 | 7 | if 'a' in foo: 8 | print "a in foo" 9 | -------------------------------------------------------------------------------- /tests/basic/dictionary2.py: -------------------------------------------------------------------------------- 1 | def dict1(): 2 | a = {1: 3, "s": 4} 3 | return len(a) 4 | 5 | def dict2(): 6 | a = {1: 3, "s": 4} 7 | b = a[1] + a["s"] 8 | return b 9 | 10 | def dict3(): 11 | a = {} 12 | a[1] = 3 13 | a["s"] = 4 14 | b = a[1] + a["s"] 15 | return b 16 | 17 | print dict1() 18 | print dict2() 19 | print dict3() 20 | -------------------------------------------------------------------------------- /tests/basic/docstring.py: -------------------------------------------------------------------------------- 1 | 2 | class myclass(object): 3 | 4 | """This is a class that really says something""" 5 | 6 | def __init__(self,msg): 7 | self.msg = msg 8 | 9 | def saysomething(self): 10 | print self.msg 11 | 12 | m = myclass("hello") 13 | 14 | m.saysomething() 15 | -------------------------------------------------------------------------------- /tests/basic/embedding.py: -------------------------------------------------------------------------------- 1 | """py2js-verbatim: 2 | function foo(x) { 3 | print(x); 4 | } 5 | """ 6 | 7 | """py2js-skip-begin""" 8 | def foo(x): 9 | print x 10 | """py2js-skip-end""" 11 | 12 | foo('bar') 13 | -------------------------------------------------------------------------------- /tests/basic/fib.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | def fib(x): 5 | if x == 1: 6 | return x 7 | else: 8 | return x*fib(x-1) 9 | 10 | print fib(4) 11 | -------------------------------------------------------------------------------- /tests/basic/float2int.py: -------------------------------------------------------------------------------- 1 | 2 | for f in [123.456,1.1,-0.00045,-1.45,1.5,1022423.22]: 3 | i = int(f) 4 | print i 5 | -------------------------------------------------------------------------------- /tests/basic/for_in.py: -------------------------------------------------------------------------------- 1 | # iterating over a list 2 | a = [1,2,3,4,5] 3 | for x in a: 4 | print x 5 | 6 | # iterating over a tuple 7 | a = ('cats','dogs','squirrels') 8 | for x in a: 9 | print x 10 | 11 | # iterating over a dictionary 12 | # sort order in python is undefined, so need to sort the results 13 | # explictly before comparing output 14 | 15 | a = {'a':1,'b':2,'c':3 } 16 | 17 | keys = [] 18 | for x in a: 19 | keys.append(x) 20 | 21 | keys.sort() 22 | for k in keys: 23 | print k 24 | 25 | # iterating over a string 26 | a = 'defabc' 27 | for x in a: 28 | print x 29 | 30 | -------------------------------------------------------------------------------- /tests/basic/for_step.py: -------------------------------------------------------------------------------- 1 | 2 | for x in xrange(19,342,13): 3 | print x 4 | -------------------------------------------------------------------------------- /tests/basic/for_xrange.py: -------------------------------------------------------------------------------- 1 | 2 | for x in xrange(1,10): 3 | print x 4 | -------------------------------------------------------------------------------- /tests/basic/generator.py: -------------------------------------------------------------------------------- 1 | 2 | class generator: 3 | 4 | class iterator: 5 | def __init__(self,parent): 6 | self.parent = parent 7 | self.value = parent.min 8 | 9 | def next(self): 10 | val = self.value 11 | if val > self.parent.max: 12 | raise StopIteration 13 | self.value += 1 14 | return val 15 | 16 | def __init__(self,min,max): 17 | self.min = min 18 | self.max = max 19 | 20 | def __iter__(self): 21 | return self.iterator(self) 22 | 23 | g = generator(5,10) 24 | for v in g: 25 | print v 26 | -------------------------------------------------------------------------------- /tests/basic/globalvar.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | a = "spam" 4 | b = "eggs" 5 | 6 | print a 7 | print b 8 | -------------------------------------------------------------------------------- /tests/basic/helloworld.py: -------------------------------------------------------------------------------- 1 | 2 | print('hello') 3 | print('hello world') 4 | -------------------------------------------------------------------------------- /tests/basic/ifs.py: -------------------------------------------------------------------------------- 1 | def ifs1(x): 2 | a = 1 3 | if x: 4 | a = a + 1 5 | a *= 2 6 | else: 7 | a = a - 1 8 | a *= 4 9 | return a 10 | 11 | def ifs2(x): 12 | a = 1 13 | if x > 0: 14 | a = a + 1 15 | a *= 2 16 | else: 17 | a = a - 1 18 | a *= 4 19 | return a 20 | 21 | def ifs3(x): 22 | a = 1 23 | if x > 0: 24 | if x > 10: 25 | a = 3 26 | else: 27 | a = 4 28 | a = 5 29 | return a 30 | 31 | def ifs4(x): 32 | a = 1 33 | if x > 0: 34 | if x > 10: 35 | a = 3 36 | else: 37 | a = 4 38 | else: 39 | a = 5 40 | return a 41 | 42 | print ifs1(True) 43 | print ifs1(False) 44 | print ifs2(1) 45 | print ifs2(-1) 46 | print ifs3(1) 47 | print ifs3(20) 48 | print ifs3(-1) 49 | print ifs4(1) 50 | print ifs4(20) 51 | print ifs4(-1) 52 | -------------------------------------------------------------------------------- /tests/basic/keys.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | x = { 'foo':'bar','aaa':'bbb','xyz':'zyx','spam':'eggs' } 4 | 5 | s = x.keys() 6 | s.sort() 7 | for k in s: 8 | print k + " -> " + x[k] 9 | -------------------------------------------------------------------------------- /tests/basic/kwargs.py: -------------------------------------------------------------------------------- 1 | def myfunc(a, b, *c, **d): 2 | print a 3 | print b 4 | for i in c: 5 | print i 6 | keys = d.keys() 7 | keys.sort() 8 | for i in keys: 9 | print i 10 | print d[i] 11 | 12 | myfunc(1, 2, bar='a', foo='c') 13 | print 14 | myfunc(1, 2, 3, 4, bar='a', foo='c') 15 | -------------------------------------------------------------------------------- /tests/basic/kwargs2.py: -------------------------------------------------------------------------------- 1 | def myfunc(a, b=3, c=4): 2 | print a 3 | print b 4 | print c 5 | print 6 | 7 | myfunc(1) 8 | myfunc(1, 2) 9 | myfunc(1, 2, 3) 10 | myfunc(1, c=3, b=4) 11 | myfunc(1, b=4) 12 | -------------------------------------------------------------------------------- /tests/basic/lambda.py: -------------------------------------------------------------------------------- 1 | 2 | y = lambda x:x*x 3 | 4 | print y(4) 5 | 6 | -------------------------------------------------------------------------------- /tests/basic/list.py: -------------------------------------------------------------------------------- 1 | 2 | x = [1,2,3,'a','b','c'] 3 | y = x[2:4] 4 | print x[0] 5 | print x[3] 6 | print y[0] 7 | print y[1] 8 | -------------------------------------------------------------------------------- /tests/basic/list2.py: -------------------------------------------------------------------------------- 1 | def list1(n): 2 | a = [] 3 | a.append(1) 4 | a.append(2) 5 | a.append(3) 6 | a.append(n) 7 | return a[0] + a[1] + a[2] + a[3] 8 | 9 | def list2(): 10 | a = list(range(5)) 11 | return str(a) 12 | 13 | def list3(): 14 | a = list(range(5)) 15 | a[0] = 5 16 | a[4] = 0 17 | return str(a) 18 | 19 | def list4(): 20 | a = [8, 9, 10, 11, 12, 13, 14] 21 | return a[2:4] 22 | 23 | def list5(): 24 | a = [8, 9, 10, 11, 12, 13, 14] 25 | return a[:4] 26 | 27 | def list6(): 28 | a = [8, 9, 10, 11, 12, 13, 14] 29 | return a[1:6:2] 30 | 31 | def list7(): 32 | a = [8, 9, 10, 11, 12, 13, 14] 33 | return a[:] 34 | 35 | def list8(): 36 | a = [8, 9, 10, 11, 12, 13, 14] 37 | return a[4:] 38 | 39 | print list1(4) 40 | print list1(5) 41 | print list2() 42 | print list3() 43 | print list4() 44 | print list5() 45 | print list6() 46 | print list7() 47 | print list8() 48 | -------------------------------------------------------------------------------- /tests/basic/listcomp2.py: -------------------------------------------------------------------------------- 1 | 2 | for (x,y,z) in [(x,y,z) for x in xrange(0,3) for y in xrange(0,4) for z in xrange(0,5)]: 3 | if x < y < z: 4 | print x,y,z,"x y - incorrect" 9 | else: 10 | print "not x > y - correct" 11 | 12 | if y >= y2: 13 | print "y >= y2 - correct" 14 | else: 15 | print "not y >= y2 - incorrect" 16 | 17 | if z > x: 18 | print "z > x - correct" 19 | else: 20 | print "not z > x - incorrect" 21 | 22 | if y >= z: 23 | print "y >= z - incorrect" 24 | else: 25 | print "not y >= x - correct" 26 | 27 | -------------------------------------------------------------------------------- /tests/functions/in.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | a = { 1:'aaa', 'b':2 } 4 | 5 | if 2 in a: 6 | print "2 in a - incorrect" 7 | 8 | if 'b' in a: 9 | print "b in a - correct" 10 | 11 | if 1 in a: 12 | print "1 in a - correct" 13 | 14 | if 3 not in a: 15 | print "3 not in a - correct" 16 | 17 | if 'x' not in a: 18 | print "x not in a - correct" 19 | -------------------------------------------------------------------------------- /tests/functions/int.py: -------------------------------------------------------------------------------- 1 | 2 | x = '123' 3 | y = int(x) 4 | print y 5 | -------------------------------------------------------------------------------- /tests/functions/isinstance.py: -------------------------------------------------------------------------------- 1 | 2 | class Spam(object): 3 | 4 | def __init__(self,value): 5 | self.value = value 6 | 7 | class Eggs(object): 8 | 9 | def __init__(self,value): 10 | self.value = value 11 | 12 | s = Spam(1) 13 | e = Eggs(2) 14 | 15 | if isinstance(s,Spam): 16 | print "s is Spam - correct" 17 | 18 | if isinstance(s,Eggs): 19 | print "s is Eggs - incorrect" 20 | 21 | if isinstance(e,Spam): 22 | print "e is Spam - incorrect" 23 | 24 | if isinstance(e,Eggs): 25 | print "e is Eggs - correct" 26 | 27 | -------------------------------------------------------------------------------- /tests/functions/len.py: -------------------------------------------------------------------------------- 1 | 2 | mylist = [1,2,3] 3 | 4 | print len(mylist) 5 | -------------------------------------------------------------------------------- /tests/functions/lshift.py: -------------------------------------------------------------------------------- 1 | 2 | x = 10 3 | y = x << 3 4 | x <<= 3 5 | print x,y 6 | -------------------------------------------------------------------------------- /tests/functions/ltle.py: -------------------------------------------------------------------------------- 1 | 2 | x = 123 3 | y = 233 4 | y2 = 233 5 | z = 892 6 | 7 | if x < y: 8 | print "x < y - correct" 9 | else: 10 | print "not x < y - incorrect" 11 | 12 | if y <= y2: 13 | print "y <= y2 - correct" 14 | else: 15 | print "not y <= y2 - incorrect" 16 | 17 | if z < x: 18 | print "z < x - incorrect" 19 | else: 20 | print "not z < x - correct" 21 | 22 | if y <= z: 23 | print "y <= z - correct" 24 | else: 25 | print "not y <= x - incorrect" 26 | 27 | -------------------------------------------------------------------------------- /tests/functions/ne.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | for (x,y) in [(1,2),('aaa','bbb'),(4,4),('a','a')]: 4 | if x <> y: 5 | print str(x)+" <> "+str(y) 6 | else: 7 | print "not: " + str(x)+" <> "+str(y) 8 | 9 | 10 | -------------------------------------------------------------------------------- /tests/functions/or.py: -------------------------------------------------------------------------------- 1 | 2 | tests = [(False,False),(False,True),(True,False),(True,True),(True,None),(False,None),(None,True),(None,False)] 3 | 4 | def pp(v): 5 | if v == False: 6 | return "F" 7 | if v == True: 8 | return "T" 9 | return "?" 10 | 11 | for t in tests: 12 | (b1,b2) = t 13 | print pp(b1) + " OR " + pp(b2) + "=" + pp(b1 or b2) 14 | -------------------------------------------------------------------------------- /tests/functions/pop.py: -------------------------------------------------------------------------------- 1 | 2 | a = [1,2,3,4] 3 | 4 | print a.pop() 5 | 6 | -------------------------------------------------------------------------------- /tests/functions/rshift.py: -------------------------------------------------------------------------------- 1 | 2 | x = 345 3 | y = x >> 7 4 | x >>= 7 5 | print x,y 6 | -------------------------------------------------------------------------------- /tests/functions/sort.py: -------------------------------------------------------------------------------- 1 | 2 | l = [3,2,1] 3 | 4 | l.sort() 5 | 6 | print l[0] 7 | print l[1] 8 | print l[2] 9 | -------------------------------------------------------------------------------- /tests/functions/sort23.py: -------------------------------------------------------------------------------- 1 | 2 | def getkey(x): 3 | if x < 5: 4 | return x + 10 5 | else: 6 | return x 7 | 8 | def revcmp(a,b): 9 | if b 0: 52 | XmlWriter.indent(writer,indent) 53 | writer.write("<"+self.tag) 54 | for k in self.attributes: 55 | writer.write(" "+k+'="'+self.attributes[k]+'"') 56 | if len(self.children) == 0: 57 | writer.write(" />") 58 | return 59 | writer.write(">") 60 | for c in self.children: 61 | c.write(writer,indent+1) 62 | if not self.hastext: 63 | XmlWriter.indent(writer,indent) 64 | writer.write("") 65 | 66 | @staticmethod 67 | def indent(writer,indent): 68 | writer.write("\n") 69 | for x in xrange(0,indent): 70 | writer.write(" ") 71 | 72 | def createRoot(self,tag): 73 | self.root = self.Element(tag) 74 | return self.root 75 | 76 | def write(self,writer): 77 | self.root.write(writer,0) 78 | 79 | 80 | if __name__ == '__main__': 81 | w = XmlWriter() 82 | r = w.createRoot("foo") 83 | r1 = r.addElement("r1") 84 | r1.addAttribute("spam","eggs") 85 | r2 = r1.addElement("r2") 86 | r2.addAttribute("eggs","spam") 87 | r2.addTextNode("This is some text") 88 | s = StringWriter() 89 | w.write(s) 90 | print s.getContents() 91 | 92 | -------------------------------------------------------------------------------- /tests/lists/extend.py: -------------------------------------------------------------------------------- 1 | 2 | list1 = [1,2,'f',44] 3 | list2 = ['a',99,77] 4 | 5 | list3 = list1[:] 6 | list3.extend(list2) 7 | 8 | for item in list3: 9 | print item 10 | -------------------------------------------------------------------------------- /tests/lists/filter.py: -------------------------------------------------------------------------------- 1 | 2 | l = [1,2,3,4,5,6,7,8,8] 3 | 4 | l2 = filter(lambda x:x>4,l) 5 | 6 | for v in l2: 7 | print v 8 | 9 | 10 | -------------------------------------------------------------------------------- /tests/lists/in.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | l = ['a','b','c'] 4 | 5 | def intest(item,list): 6 | if item in list: 7 | print str(item) + ' is in list' 8 | else: 9 | print str(item) + ' is not in list' 10 | 11 | 12 | intest('a',l) 13 | intest('b',l) 14 | intest(99,l) 15 | intest(0,l) 16 | intest('z',l) 17 | intest('c',l) 18 | 19 | 20 | -------------------------------------------------------------------------------- /tests/lists/insert.py: -------------------------------------------------------------------------------- 1 | a = [] 2 | a.insert(0, 1) 3 | print a 4 | a.insert(0, 2) 5 | print a 6 | a.insert(0, 3) 7 | print a 8 | a.insert(1, 4) 9 | print a 10 | a.insert(2, 5) 11 | print a 12 | a.insert(5, 6) 13 | print a 14 | -------------------------------------------------------------------------------- /tests/lists/map.py: -------------------------------------------------------------------------------- 1 | 2 | def foo(x): 3 | return x*x 4 | 5 | y = [1,2,3,4,5] 6 | 7 | z = map(foo,y) 8 | for val in z: 9 | print val 10 | -------------------------------------------------------------------------------- /tests/lists/max.py: -------------------------------------------------------------------------------- 1 | 2 | l = [4,7,3,4,2,1] 3 | 4 | v = max(l) 5 | 6 | print v 7 | -------------------------------------------------------------------------------- /tests/lists/min.py: -------------------------------------------------------------------------------- 1 | 2 | l = [4,7,3,4,2,1] 3 | 4 | v = min(l) 5 | 6 | print v 7 | -------------------------------------------------------------------------------- /tests/lists/reduce.py: -------------------------------------------------------------------------------- 1 | 2 | def foo(x,y): 3 | return x*y 4 | 5 | y = [1,2,3,4,5] 6 | 7 | z = reduce(foo,y,10) 8 | print z 9 | z = reduce(foo,y) 10 | print z 11 | -------------------------------------------------------------------------------- /tests/lists/reverse.py: -------------------------------------------------------------------------------- 1 | a = [1, 2, 3, 4] 2 | a.reverse() 3 | print a 4 | -------------------------------------------------------------------------------- /tests/lists/subclass.py: -------------------------------------------------------------------------------- 1 | class A(list): 2 | 3 | def my_append(self, a): 4 | self.append(a) 5 | 6 | a = A() 7 | print a 8 | a.append(5) 9 | print a 10 | a.append(6) 11 | print a 12 | a.remove(5) 13 | print a 14 | -------------------------------------------------------------------------------- /tests/lists/subclass2.py: -------------------------------------------------------------------------------- 1 | class List(object): 2 | 3 | def __init__(self, l=[]): 4 | self._list = list(l) 5 | 6 | def append(self, x): 7 | self._list.append(x) 8 | 9 | def remove(self, x): 10 | self._list.remove(x) 11 | 12 | def __str__(self): 13 | return str(self._list) 14 | 15 | class A(List): 16 | 17 | def my_append(self, a): 18 | self.append(a) 19 | 20 | a = A() 21 | print a 22 | a.append(5) 23 | print a 24 | a.append(6) 25 | print a 26 | a.remove(5) 27 | print a 28 | -------------------------------------------------------------------------------- /tests/lists/subclass3.py: -------------------------------------------------------------------------------- 1 | class List(object): 2 | 3 | def __init__(self, l=[]): 4 | self._list = list(l) 5 | 6 | def append(self, x): 7 | self._list.append(x) 8 | 9 | def remove(self, x): 10 | self._list.remove(x) 11 | 12 | def __str__(self): 13 | return str(self._list) 14 | 15 | class Layer(List): 16 | pass 17 | 18 | l1 = Layer() 19 | l1.append(1) 20 | l1.append(2) 21 | l2 = list() 22 | l2.append(3) 23 | l2.append(4) 24 | print l1 25 | print l2 26 | -------------------------------------------------------------------------------- /tests/lists/sum.py: -------------------------------------------------------------------------------- 1 | 2 | s = [1,2,3,4,5] 3 | t = sum(s) 4 | u = sum([x*x for x in s]) 5 | print t,u 6 | -------------------------------------------------------------------------------- /tests/lists/sum2.py: -------------------------------------------------------------------------------- 1 | s = [1,2,3,4,5] 2 | print sum(s) 3 | 4 | print sum([1, 8, 11]) 5 | 6 | print sum((1, 8, 11)) 7 | -------------------------------------------------------------------------------- /tests/lists/xrange.py: -------------------------------------------------------------------------------- 1 | 2 | xr = xrange(20,40) 3 | 4 | for x in xr: 5 | print x 6 | -------------------------------------------------------------------------------- /tests/lists/zip.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | l1 = [1,2,3,4,5] 4 | l2 = [5,4,3,2,1] 5 | l3 = [4,4,4,4] 6 | 7 | l4 = zip(l1,l2,l3) 8 | 9 | for item in l4: 10 | print "---" 11 | for val in item: 12 | print val 13 | -------------------------------------------------------------------------------- /tests/modules/classname.py: -------------------------------------------------------------------------------- 1 | 2 | from modules.moda import ModA 3 | 4 | m = ModA('hello') 5 | m.describe() 6 | 7 | mc = m.clone() 8 | mc.describe() 9 | -------------------------------------------------------------------------------- /tests/modules/from_import.py: -------------------------------------------------------------------------------- 1 | 2 | from imported.modulea import modulea_fn 3 | from imported.moduleb import moduleb_fn as modb_fn 4 | from imported.modulec import * 5 | 6 | modulea_fn() 7 | modb_fn() 8 | foo() 9 | -------------------------------------------------------------------------------- /tests/modules/import.py: -------------------------------------------------------------------------------- 1 | 2 | from imported.modulea import * 3 | import imported.moduleb 4 | 5 | modulea_fn() 6 | imported.moduleb.moduleb_fn() 7 | 8 | ma = modulea_class() 9 | print ma.msg(1) 10 | 11 | mb = imported.moduleb.moduleb_class() 12 | print mb.msg(2) 13 | -------------------------------------------------------------------------------- /tests/modules/import_alias.py: -------------------------------------------------------------------------------- 1 | 2 | from imported.alias_fns import foo as bar 3 | from imported.alias_classes import spam as eggs 4 | 5 | # call imported function 6 | bar() 7 | 8 | # call imported class 9 | e = eggs() 10 | e.msg() 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/modules/import_class.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | import modules.klasses 4 | 5 | k = modules.klasses.klass() 6 | 7 | k.sayhello() 8 | modules.klasses.klass.sayhello() 9 | 10 | -------------------------------------------------------------------------------- /tests/modules/import_diamond.py: -------------------------------------------------------------------------------- 1 | 2 | import modules.diamond1 3 | import modules.diamond2 4 | 5 | modules.diamond1.run() 6 | modules.diamond2.run() 7 | 8 | -------------------------------------------------------------------------------- /tests/modules/import_global.py: -------------------------------------------------------------------------------- 1 | 2 | import imported.moduleb 3 | import imported.moduled 4 | 5 | imported.moduleb.moduleb_fn() 6 | imported.moduled.moduled_fn() 7 | -------------------------------------------------------------------------------- /tests/modules/import_multi.py: -------------------------------------------------------------------------------- 1 | 2 | import imported.modulec 3 | 4 | def foo(): 5 | print "foo" 6 | imported.modulec.foo() 7 | 8 | foo() 9 | -------------------------------------------------------------------------------- /tests/modules/imported/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsnake/py2js/6cda2b1d3cf281a5ca92c18b08ac9fa1c389cbea/tests/modules/imported/__init__.py -------------------------------------------------------------------------------- /tests/modules/imported/alias_classes.py: -------------------------------------------------------------------------------- 1 | 2 | class spam: 3 | 4 | def __init__(self): 5 | self.msgtxt = "this is spam" 6 | 7 | def msg(self): 8 | print self.msgtxt 9 | 10 | if __name__ == '__main__': 11 | s = spam() 12 | s.msg() 13 | -------------------------------------------------------------------------------- /tests/modules/imported/alias_fns.py: -------------------------------------------------------------------------------- 1 | 2 | def foo(): 3 | print "this is foo" 4 | 5 | 6 | -------------------------------------------------------------------------------- /tests/modules/imported/modulea.py: -------------------------------------------------------------------------------- 1 | 2 | def modulea_fn(): 3 | 4 | print "import_modulea.modulea_fn()" 5 | 6 | class modulea_class(object): 7 | 8 | def __init__(self): 9 | pass 10 | 11 | def msg(self,val): 12 | return "modulea_class:"+str(val) 13 | -------------------------------------------------------------------------------- /tests/modules/imported/moduleb.py: -------------------------------------------------------------------------------- 1 | 2 | def foo(): 3 | print "foo" 4 | 5 | def moduleb_fn(): 6 | print "import_moduleb.moduleb_fn()" 7 | 8 | class moduleb_class(object): 9 | 10 | def __init__(self): 11 | pass 12 | 13 | def msg(self,val): 14 | return "moduleb_class:"+str(val) 15 | -------------------------------------------------------------------------------- /tests/modules/imported/modulec.py: -------------------------------------------------------------------------------- 1 | 2 | import submodules.submodulea 3 | 4 | def foo(): 5 | print "imported.modulec.foo()" 6 | submodules.submodulea.foo() 7 | -------------------------------------------------------------------------------- /tests/modules/imported/moduled.py: -------------------------------------------------------------------------------- 1 | 2 | import imported.modulea 3 | 4 | def moduled_fn(): 5 | print "import_moduled.moduled_fn()" 6 | print "calling module a now..." 7 | imported.modulea.modulea_fn() 8 | -------------------------------------------------------------------------------- /tests/modules/imported/submodules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsnake/py2js/6cda2b1d3cf281a5ca92c18b08ac9fa1c389cbea/tests/modules/imported/submodules/__init__.py -------------------------------------------------------------------------------- /tests/modules/imported/submodules/submodulea.py: -------------------------------------------------------------------------------- 1 | 2 | def foo(): 3 | print "imported.modules.submodules.modulea.foo()" 4 | -------------------------------------------------------------------------------- /tests/modules/module_name.py: -------------------------------------------------------------------------------- 1 | 2 | import modules.module_name 3 | 4 | print "1st level module __name__:"+__name__ 5 | -------------------------------------------------------------------------------- /tests/modules/modules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsnake/py2js/6cda2b1d3cf281a5ca92c18b08ac9fa1c389cbea/tests/modules/modules/__init__.py -------------------------------------------------------------------------------- /tests/modules/modules/diamond1.py: -------------------------------------------------------------------------------- 1 | 2 | import submodules.diamondbase 3 | 4 | def run(): 5 | print "calling diamond1.run()" 6 | submodules.diamondbase.run() 7 | -------------------------------------------------------------------------------- /tests/modules/modules/diamond2.py: -------------------------------------------------------------------------------- 1 | 2 | import submodules.diamondbase 3 | 4 | def run(): 5 | print "Calling diamond2.run()" 6 | submodules.diamondbase.run() 7 | -------------------------------------------------------------------------------- /tests/modules/modules/klasses.py: -------------------------------------------------------------------------------- 1 | 2 | class baseklass(object): 3 | 4 | @staticmethod 5 | def sayhello(): 6 | print "baseklass says hello" 7 | 8 | class klass(baseklass): 9 | 10 | pass 11 | 12 | 13 | if __name__ == '__main__': 14 | 15 | k = klass() 16 | k.sayhello() 17 | klass.sayhello() 18 | baseklass.sayhello() 19 | -------------------------------------------------------------------------------- /tests/modules/modules/moda.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class ModA: 4 | 5 | def __init__(self,val): 6 | self.val = val 7 | 8 | def clone(self): 9 | return ModA(self.val) 10 | 11 | def describe(self): 12 | print self.val 13 | -------------------------------------------------------------------------------- /tests/modules/modules/module_name.py: -------------------------------------------------------------------------------- 1 | 2 | import submodules.module_name 3 | 4 | print "2nd level module __name__:"+__name__ 5 | -------------------------------------------------------------------------------- /tests/modules/modules/submodules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsnake/py2js/6cda2b1d3cf281a5ca92c18b08ac9fa1c389cbea/tests/modules/modules/submodules/__init__.py -------------------------------------------------------------------------------- /tests/modules/modules/submodules/diamondbase.py: -------------------------------------------------------------------------------- 1 | 2 | counter = 0 3 | 4 | def run(): 5 | global counter 6 | counter += 1 7 | print "diamondbase called " + str(counter) + " time(s)" 8 | -------------------------------------------------------------------------------- /tests/modules/modules/submodules/module_name.py: -------------------------------------------------------------------------------- 1 | 2 | print "3rd level module __name__:"+__name__ 3 | -------------------------------------------------------------------------------- /tests/modules/rng.py: -------------------------------------------------------------------------------- 1 | 2 | from mtrandom import * 3 | 4 | def float2str(v,dp): 5 | s = str(v) 6 | dotpos = s.find(".") 7 | if dotpos >= 0: 8 | return s[:dotpos+dp+1] 9 | return s 10 | 11 | class RNG: 12 | def __init__(self): 13 | init = [0x123, 0x234, 0x345, 0x456] 14 | self.r = MersenneTwister() 15 | self.r.init_by_array(init,4) 16 | 17 | def next(self): 18 | return self.r.genrand_res53() 19 | 20 | if __name__ == "__main__": 21 | r = RNG() 22 | print float2str(r.next(),9) 23 | print float2str(r.next(),9) 24 | print float2str(r.next(),9) 25 | 26 | -------------------------------------------------------------------------------- /tests/strings/count.py: -------------------------------------------------------------------------------- 1 | 2 | txt = "the quick brown fox jumped over the lazy dogthe" 3 | 4 | c = txt.count("the") 5 | print c 6 | c = txt.count("the",0,-20) 7 | print c 8 | c = txt.count("the",3) 9 | print c 10 | c = txt.count("the",4,15) 11 | print c 12 | c = txt.count("the",1,len(txt)) 13 | print c 14 | c = txt.count("the",4,len(txt)-1) 15 | print c 16 | -------------------------------------------------------------------------------- /tests/strings/find.py: -------------------------------------------------------------------------------- 1 | 2 | s = "the quick brown fox" 3 | i = s.find("quick") 4 | print str(i) 5 | i = s.find("dog") 6 | print str(i) 7 | i = s.find("the") 8 | print str(i) 9 | -------------------------------------------------------------------------------- /tests/strings/join.py: -------------------------------------------------------------------------------- 1 | a = ["a", "b", "c"] 2 | print "".join(a) 3 | print " ".join(a) 4 | print "x".join(a) 5 | print "x ".join(a) 6 | -------------------------------------------------------------------------------- /tests/strings/lstrip0.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | s1 = "\n\nabc\n\n\n" 4 | s2 = "\t abc\n\t \n" 5 | s3 = " abc " 6 | 7 | for s in [s1,s2,s3]: 8 | print "original("+s+")" 9 | print "strip("+s.lstrip()+")" 10 | -------------------------------------------------------------------------------- /tests/strings/lstrip1.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | s = "abcxyz" 4 | 5 | print "original("+s+")" 6 | print "strip("+s.lstrip("cba")+")" 7 | -------------------------------------------------------------------------------- /tests/strings/replace.py: -------------------------------------------------------------------------------- 1 | 2 | txt = "the quick brown fox jumped over thethe lazy dog" 3 | 4 | txt2 = txt.replace("the","a") 5 | 6 | print txt 7 | print txt2 8 | 9 | print txt.replace("the", "a", 0) 10 | print txt.replace("the", "a", 1) 11 | print txt.replace("the", "a", 2) 12 | print txt.replace("the", "a", 3) 13 | print txt.replace("the", "a", 4) 14 | print txt.replace("the", "a", 50) 15 | -------------------------------------------------------------------------------- /tests/strings/rfind.py: -------------------------------------------------------------------------------- 1 | 2 | s = "the quick brown quick the fox" 3 | i = s.rfind("quick") 4 | print str(i) 5 | i = s.rfind("dog") 6 | print str(i) 7 | i = s.rfind("the") 8 | print str(i) 9 | -------------------------------------------------------------------------------- /tests/strings/rstrip0.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | s1 = "abc\n\n\n" 4 | s2 = "abc\n\t \n" 5 | s3 = "abc " 6 | 7 | for s in [s1,s2,s3]: 8 | print "original("+s+")" 9 | print "strip("+s.rstrip()+")" 10 | -------------------------------------------------------------------------------- /tests/strings/rstrip1.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | s = "abcxyz" 4 | 5 | print "original("+s+")" 6 | print "strip("+s.rstrip("yzx")+")" 7 | -------------------------------------------------------------------------------- /tests/strings/split.py: -------------------------------------------------------------------------------- 1 | 2 | s="the quick brown fox jumped over the lazy dog" 3 | t = s.split(" ") 4 | for v in t: 5 | print v 6 | r = s.split("e") 7 | for v in r: 8 | print v 9 | x = s.split() 10 | for v in x: 11 | print v 12 | 13 | # 2-arg version of split not supported 14 | # y = s.split(" ",7) 15 | # for v in y: 16 | # print v 17 | -------------------------------------------------------------------------------- /tests/strings/splitlines.py: -------------------------------------------------------------------------------- 1 | 2 | txt = """ 3 | aaa 4 | 5 | bcfdss 6 | 7 | sdsd 8 | wqarwqr 9 | 10 | 11 | werewr""" 12 | 13 | lines = txt.splitlines() 14 | 15 | for line in lines: 16 | print line 17 | -------------------------------------------------------------------------------- /tests/strings/string_format_combined_simple.py: -------------------------------------------------------------------------------- 1 | a = "well" 2 | b = "seems to work" 3 | c = "something else" 4 | d = 10 5 | f = 15 6 | 7 | s = "%s: %d, %s: %d, %s: %d" % (a, d, b, f, c, d) 8 | print s 9 | -------------------------------------------------------------------------------- /tests/strings/string_format_d.py: -------------------------------------------------------------------------------- 1 | 2 | a = 1.123456 3 | b = 10 4 | c = -30 5 | d = 34 6 | e = 123.456 7 | f = 19892122 8 | 9 | # form 0 10 | s = "b=%d" % b 11 | print s 12 | 13 | # form 1 14 | s = "b,c,d=%d+%d+%d" % (b,c,d) 15 | print s 16 | 17 | # form 2 18 | s = "b=%(b)0d and c=%(c)d and d=%(d)d" % { 'b':b,'c':c,'d':d } 19 | print s 20 | 21 | # width,flags 22 | s = "e=%020d e=%+d e=%20d e=%-20d (e=%- 20d)" % (e,e,e,e,e) 23 | print s 24 | -------------------------------------------------------------------------------- /tests/strings/string_format_d_simple.py: -------------------------------------------------------------------------------- 1 | 2 | a = 1.123456 3 | b = 10 4 | c = -30 5 | d = 34 6 | e = 123.456 7 | f = 19892122 8 | 9 | # form 0 10 | s = "b=%d" % b 11 | print s 12 | 13 | # form 1 14 | s = "b,c,d=%d+%d+%d" % (b,c,d) 15 | print s 16 | 17 | # form 2 18 | #s = "b=%(b)0d and c=%(c)d and d=%(d)d" % { 'b':b,'c':c,'d':d } 19 | print s 20 | 21 | # width,flags 22 | #s = "e=%020d e=%+d e=%20d e=%-20d (e=%- 20d)" % (e,e,e,e,e) 23 | print s 24 | -------------------------------------------------------------------------------- /tests/strings/string_format_efg.py: -------------------------------------------------------------------------------- 1 | 2 | a = 1.123456 3 | b = 0.000000000324324 4 | c = 18347894.213123 5 | d = 0.0 6 | e = -1324323.456 7 | f = -0.000000000019892122 8 | 9 | vars = [a,b,c,d,e,f] 10 | codes = ['e','E','f','F','g','G'] 11 | 12 | fmts = ["a=%e","a=%10.5e","a=%+10.5e","a=%#e"] 13 | 14 | for code in codes: 15 | for fmt in fmts: 16 | fmt = fmt.replace('e',code) 17 | for v in vars: 18 | print fmt + ":", fmt % v 19 | -------------------------------------------------------------------------------- /tests/strings/string_format_f_simple.py: -------------------------------------------------------------------------------- 1 | a = 1.123456 2 | b = 10 3 | c = -30 4 | d = 34 5 | e = 123.456789 6 | f = 892122.129899 7 | 8 | # form 0 9 | s = "b=%f" % a 10 | print s 11 | 12 | # form 1 13 | s = "b,c,d=%f+%f+%f" % (a, e, f) 14 | print s 15 | -------------------------------------------------------------------------------- /tests/strings/string_format_i.py: -------------------------------------------------------------------------------- 1 | 2 | a = 1.123456 3 | b = 10 4 | c = -30 5 | d = 34 6 | e = 123.456 7 | f = 19892122 8 | 9 | # form 0 10 | s = "b=%i" % b 11 | print s 12 | 13 | # form 1 14 | s = "b,c,d=%i+%i+%i" % (b,c,d) 15 | print s 16 | 17 | # form 2 18 | s = "b=%(b)i and c=%(c)i and d=%(d)i" % { 'b':b,'c':c,'d':d } 19 | print s 20 | 21 | # width,flags 22 | s = "e=%020i e=%+i e=%20i e=%-20i (e=%- 20i)" % (e,e,e,e,e) 23 | print s 24 | -------------------------------------------------------------------------------- /tests/strings/string_format_o.py: -------------------------------------------------------------------------------- 1 | 2 | vals = [0,10,-30,173247,123,19892122] 3 | 4 | formats = ['%o','%020o', '%-20o', '%#o', '+%o', '+%#o'] 5 | 6 | for val in vals: 7 | for fmt in formats: 8 | print fmt+":", fmt % val 9 | -------------------------------------------------------------------------------- /tests/strings/string_format_s_simple.py: -------------------------------------------------------------------------------- 1 | a = "well" 2 | b = "seems to work" 3 | c = "something else" 4 | 5 | # form 0 6 | s = "b=%s" % a 7 | print s 8 | 9 | # form 1 10 | s = "b,c,d=%s+%s+%s" % (a, b, c) 11 | print s 12 | -------------------------------------------------------------------------------- /tests/strings/string_format_u.py: -------------------------------------------------------------------------------- 1 | 2 | a = 1.123456 3 | b = 10 4 | c = -30 5 | d = 34 6 | e = 123.456 7 | f = 19892122 8 | 9 | # form 0 10 | s = "b=%u" % b 11 | print s 12 | 13 | # form 1 14 | s = "b,c,d=%u+%u+%u" % (b,c,d) 15 | print s 16 | 17 | # form 2 18 | s = "b=%(b)0u and c=%(c)u and d=%(d)u" % { 'b':b,'c':c,'d':d } 19 | print s 20 | 21 | # width,flags 22 | s = "e=%020u e=%+u e=%20u e=%-20u (e=%- 20u)" % (e,e,e,e,e) 23 | print s 24 | -------------------------------------------------------------------------------- /tests/strings/string_format_x.py: -------------------------------------------------------------------------------- 1 | 2 | vals = [0,10,-30,173247,123,19892122] 3 | 4 | formats = ['%x','%020x','%X', '%020X', '%-20x', '%#x'] 5 | 6 | for val in vals: 7 | for fmt in formats: 8 | print fmt+":", fmt % val 9 | -------------------------------------------------------------------------------- /tests/strings/strings_in_strings.py: -------------------------------------------------------------------------------- 1 | print """"Hello World!" <- should 'mess' up '''thing'''?""" 2 | 3 | # Test other strings: 4 | print b"\\x00" 5 | print u"\\u0000" 6 | -------------------------------------------------------------------------------- /tests/strings/strip.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | s1 = "\n\nabc\n\n\n" 4 | s2 = "\t abc\n\t \n" 5 | s3 = " abc " 6 | 7 | for s in [s1,s2,s3]: 8 | print "original("+s+")" 9 | print "strip("+s.strip()+")" 10 | -------------------------------------------------------------------------------- /tests/strings/strip1.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | s = "yxabcxyz" 4 | 5 | print "original("+s+")" 6 | print "strip("+s.strip("yzx")+")" 7 | -------------------------------------------------------------------------------- /tests/strings/ulcase.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | str = "aBcddEzUh" 4 | 5 | print str 6 | str = str.upper() 7 | print str 8 | str = str.lower() 9 | print str 10 | -------------------------------------------------------------------------------- /tests/strings/ulcase1.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | a = "aBcddEzUh" 4 | 5 | print a 6 | a = a.upper() 7 | print a 8 | a = a.lower() 9 | print a 10 | -------------------------------------------------------------------------------- /tests/strings/zipstring.py: -------------------------------------------------------------------------------- 1 | 2 | s1 = "hello" 3 | s2 = "world" 4 | s3 = "abcd" 5 | 6 | s4 = zip(s1,s2,s3) 7 | 8 | for item in s4: 9 | print "----" 10 | for val in item: 11 | print val 12 | -------------------------------------------------------------------------------- /tests/test_compile_js.py: -------------------------------------------------------------------------------- 1 | """ 2 | This test only tests that Python code can be compiled using the py2js. 3 | 4 | It doesn't test if the resulting javascript makes any sense. 5 | """ 6 | 7 | def is_on_the_left(c, a, b, pts_list): 8 | ax, ay = pts_list[a] 9 | bx, by = pts_list[b] 10 | cx, cy = pts_list[c] 11 | ux = float(bx - ax) 12 | uy = float(by - ay) 13 | vx = float(cx - ax) 14 | vy = float(cy - ay) 15 | return (ux*vy - uy*vx > 0) 16 | 17 | def criterion(a, b, c, pts_list): 18 | ax, ay = pts_list[a] 19 | bx, by = pts_list[b] 20 | cx, cy = pts_list[c] 21 | ux = float(ax - cx) 22 | uy = float(ay - cy) 23 | vx = float(bx - cx) 24 | vy = float(by - cy) 25 | len_u = sqrt(ux*ux + uy*uy) 26 | len_v = sqrt(vx*vx + vy*vy) 27 | return (ux*vx + uy*vy)/(len_u*len_v) 28 | 29 | def find_third_point(a, b, pts_list, edges): 30 | """ 31 | Take a boundary edge (a,b), and in the list of points 32 | find a point 'c' that lies on the left of ab and maximizes 33 | the angle acb 34 | """ 35 | found = 0 36 | minimum = exp(100) #this is dirty 37 | c_index = -1 38 | pt_index = -1 39 | for c_point in pts_list: 40 | c_index += 1 41 | if c_index != a and c_index != b and is_on_the_left(c_index, a, b, pts_list): 42 | edge_intersects = \ 43 | edge_intersects_edges((a, c_index), pts_list, edges) or \ 44 | edge_intersects_edges((b, c_index), pts_list, edges) 45 | if not edge_intersects: 46 | crit = criterion(a, b, c_index, pts_list) 47 | if crit < minimum: 48 | minimum = crit 49 | pt_index = c_index 50 | found = 1 51 | if found == 0: 52 | raise TriangulationError("ERROR: Optimal point not found in find_third_point().") 53 | return pt_index 54 | 55 | def lies_inside(c, bdy_edges): 56 | for edge in bdy_edges: 57 | a,b = edge 58 | if c == a or c == b: return False 59 | return True 60 | 61 | def is_boundary_edge(a, b, bdy_edges): 62 | """ 63 | Checks whether edge (a, b) is in the list of boundary edges 64 | """ 65 | for edge in bdy_edges: 66 | a0, b0 = edge 67 | if a == a0 and b == b0: 68 | return True 69 | return False 70 | 71 | def triangulate_af(pts_list, bdy_edges): 72 | """ 73 | Create a triangulation using the advancing front method. 74 | """ 75 | # create empty list of elements 76 | elems = [] 77 | bdy_edges = bdy_edges[:] 78 | # main loop 79 | while bdy_edges != []: 80 | # take the last item from the list of bdy edges (and remove it) 81 | a,b = bdy_edges.pop() 82 | c = find_third_point(a, b, pts_list, bdy_edges) 83 | elems.append((a,b,c)) 84 | if is_boundary_edge(c, a, bdy_edges): 85 | bdy_edges.remove((c,a)) 86 | else: 87 | bdy_edges.append((a,c)) 88 | if is_boundary_edge(b, c, bdy_edges): 89 | bdy_edges.remove((b,c)) 90 | else: 91 | bdy_edges.append((c,b)) 92 | return elems 93 | 94 | class TestClass(object): 95 | def __init__(self): 96 | alert('TestClass created') 97 | self.reset() 98 | 99 | def reset(self): 100 | self.value = 0 101 | 102 | def inc(self): 103 | alert(self.value) 104 | self.value += 1 105 | 106 | class TestClass(object): 107 | count = 0 108 | def __init__(self): 109 | pass 110 | def next(self): 111 | self.count += 1 112 | def test(self): 113 | alert(self.count) 114 | 115 | def onCountClick(event): 116 | window.testObj.next() 117 | window.testObj.test() 118 | 119 | def helloWorld(): 120 | window.testObj = TestClass.new() 121 | 122 | pushButton = YAHOO.widget.Button.new( 123 | { 124 | 'label' : 'Hello, World!', 125 | 'id' : 'pushButton', 126 | 'container' : 'pushButtons' 127 | } 128 | ) 129 | pushButton.on('click', onButtonClick) 130 | pushButton2 = YAHOO.widget.Button.new( 131 | { 132 | 'label' : 'Hello, Dude!', 133 | 'id' : 'pushButton2', 134 | 'container' : 'pushButtons', 135 | 'onclick' : { 136 | 'fn' : onButtonClick, 137 | 'obj' : 'Dude' 138 | } 139 | } 140 | ) 141 | 142 | i = 1 143 | while i <= 3: 144 | YAHOO.widget.Button.new( 145 | { 146 | 'label' : 'Hello ' + i + '!', 147 | 'id' : 'pushButtonIter' + i, 148 | 'container' : 'pushButtons', 149 | 'onclick' : { 150 | 'fn' : onButtonClick, 151 | 'obj' : 'Person #' + i 152 | } 153 | } 154 | ) 155 | i += 1 156 | 157 | YAHOO.widget.Button.new( 158 | { 159 | 'label' : 'Count', 160 | 'id' : 'pushButtonCount', 161 | 'container' : 'pushButtons', 162 | 'onclick' : { 163 | 'fn' : onCountClick 164 | } 165 | } 166 | ) 167 | 168 | def onButtonClick(event, target='World'): 169 | if target == 'World': 170 | target = 'Big Blue World' 171 | alert('Hello, ' + target + '!') 172 | 173 | def StartGoL(): 174 | window.gol = GoL.new() 175 | 176 | class GoL(object): 177 | def __init__(self): 178 | self.width = 75 179 | self.height = 75 180 | self.canvas = document.getElementById('canvas').getContext('2d') 181 | self.canvas.fillStyle = 'rgb(0, 0, 0)' 182 | self.grid = Array.new(self.width*self.height) 183 | for i in range(self.width*self.height): 184 | self.grid[i] = Math.random() > 0.5 185 | setInterval('window.gol.iter()', 250) 186 | self.draw() 187 | def get(self, x, y): 188 | return self.grid[((x + self.width) % self.width) + ((y + self.height) % self.height) * self.width] 189 | def iter(self): 190 | toDie = Array.new(0) 191 | toLive = Array.new(0) 192 | for x in range(0, self.width): 193 | for y in range(0, self.height): 194 | count = 0 195 | if self.get(x-1, y-1): 196 | count += 1 197 | if self.get(x, y-1): 198 | count += 1 199 | if self.get(x+1, y-1): 200 | count += 1 201 | if self.get(x-1, y): 202 | count += 1 203 | if self.get(x+1, y): 204 | count += 1 205 | if self.get(x-1, y+1): 206 | count += 1 207 | if self.get(x, y+1): 208 | count += 1 209 | if self.get(x+1, y+1): 210 | count += 1 211 | 212 | if self.get(x, y): 213 | if count < 2: 214 | toDie[toDie.length] = x + y*self.width 215 | elif count > 3: 216 | toDie[toDie.length] = x + y*self.width 217 | else: 218 | if count == 3: 219 | toLive[toLive.length] = x + y*self.width 220 | 221 | for i in range(toDie.length): 222 | self.grid[toDie[i]] = False 223 | for i in range(toLive.length): 224 | self.grid[toLive[i]] = True 225 | 226 | self.draw() 227 | def draw(self): 228 | i = 0 229 | for x in range(0, self.width*10, 10): 230 | for y in range(0, self.height*10, 10): 231 | if self.grid[i]: 232 | self.canvas.fillRect(x, y, x+10, y+10) 233 | else: 234 | self.canvas.clearRect(x, y, x+10, y+10) 235 | i += 1 236 | -------------------------------------------------------------------------------- /testtools/__init__.py: -------------------------------------------------------------------------------- 1 | """Everything that is python and has to do with tests goes in here.""" 2 | -------------------------------------------------------------------------------- /testtools/env_tests.py: -------------------------------------------------------------------------------- 1 | """\ 2 | Includes tests that check the setup for the tests. 3 | If the library is compiled and if there is a js interpreter. 4 | """ 5 | import os 6 | import sys 7 | if sys.version_info < (2, 7): 8 | import unittest2 as unittest 9 | else: 10 | import unittest 11 | import tempfile 12 | class EnviromentTest(unittest.TestCase): 13 | "Test case that makes sure that the environment is up and working" 14 | def reportProgres(self): 15 | """Should be overloaded by the test result class""" 16 | 17 | def stop(self): 18 | """Should be overloaded by the test result class""" 19 | 20 | def runTest(self): 21 | """The actual test goes here.""" 22 | if os.system( 23 | "js --help > %s" % 24 | os.path.join( 25 | tempfile.gettempdir(), 26 | tempfile.gettempprefix() 27 | ) 28 | ): 29 | self.stop() 30 | raise RuntimeError("""Can't find the "js" command.""") 31 | self.reportProgres() 32 | if not os.path.exists("py-builtins.js"): 33 | self.stop() 34 | raise RuntimeError("""Can't find the "py-builtins.js" command.""") 35 | self.reportProgres() 36 | 37 | def __str__(self): 38 | return 'Looking for "js" and "py-builtins" [2]: ' 39 | 40 | 41 | -------------------------------------------------------------------------------- /testtools/known_to_fail.py: -------------------------------------------------------------------------------- 1 | """lists all the tests that are known to fail""" 2 | KNOWN_TO_FAIL = [ 3 | "tests/basic/nestedclass.py", 4 | "tests/basic/super.py", 5 | "tests/basic/kwargs.py", 6 | "tests/basic/float2int.py", 7 | "tests/basic/oo_inherit.py", 8 | "tests/basic/listcomp2.py", 9 | "tests/basic/del_dict.py", 10 | "tests/basic/del_local.py", 11 | "tests/basic/sumcomp.py", 12 | "tests/basic/del_array.py", 13 | "tests/basic/valueerror.py", 14 | "tests/basic/lambda.py", 15 | "tests/basic/try.py", 16 | "tests/basic/vargs.py", 17 | "tests/basic/del_attr.py", 18 | "tests/basic/del_global.py", 19 | "tests/basic/del_slice.py", 20 | "tests/basic/generator.py", 21 | "tests/basic/raise.py", 22 | 23 | "tests/functions/sort_cmp.py", 24 | "tests/functions/ne.py", 25 | "tests/functions/aug.py", 26 | "tests/functions/floatdiv.py", 27 | "tests/functions/sort23.py", 28 | 29 | "tests/errors/decorator.py", 30 | 31 | "tests/lists/filter.py", 32 | "tests/lists/reduce.py", 33 | "tests/lists/sum.py", 34 | "tests/lists/subclass.py", 35 | 36 | "tests/libraries/xmlwriter.py", 37 | 38 | "tests/modules/classname.py", 39 | "tests/modules/from_import.py", 40 | "tests/modules/import.py", 41 | "tests/modules/import_alias.py", 42 | "tests/modules/import_class.py", 43 | "tests/modules/import_diamond.py", 44 | "tests/modules/import_global.py", 45 | "tests/modules/import_multi.py", 46 | "tests/modules/module_name.py", 47 | "tests/modules/rng.py", 48 | 49 | "tests/strings/string_format_d.py", 50 | "tests/strings/string_format_efg.py", 51 | "tests/strings/string_format_i.py", 52 | "tests/strings/string_format_o.py", 53 | "tests/strings/string_format_u.py", 54 | "tests/strings/string_format_x.py", 55 | "tests/strings/ulcase.py", 56 | ] 57 | 58 | 59 | -------------------------------------------------------------------------------- /testtools/runner.py: -------------------------------------------------------------------------------- 1 | """\ 2 | The special runners that look for progress in a test and have nicer output than 3 | the original.""" 4 | import sys 5 | if sys.version_info < (2, 7): 6 | import unittest2 as unittest 7 | else: 8 | import unittest 9 | 10 | class Py2JsTestResult(unittest.TestResult): 11 | """Test result class, handling all the results reported by the tests""" 12 | 13 | def __init__(self, *a, **k): 14 | import testtools.writer 15 | super(Py2JsTestResult, self).__init__(*a, **k) 16 | self.__writer = testtools.writer.Writer(a[0]) 17 | self.__faild = False 18 | self.__color = "" 19 | self.__state = "" 20 | 21 | def startTest(self, test): 22 | super(Py2JsTestResult, self).startTest(test) 23 | test.reportProgres = self.addProgress 24 | test.stop = self.stop 25 | self.__writer.write(str(test)) 26 | self.__state = "[Error]" 27 | self.__color = "Red" 28 | 29 | def stopTest(self, test): 30 | super(Py2JsTestResult, self).stopTest(test) 31 | self.__writer.write(self.__state, align="right", color=self.__color) 32 | 33 | def addProgress(self): 34 | """Part of tests done""" 35 | self.__writer.write(".") 36 | 37 | def addSuccess(self, test): 38 | super(Py2JsTestResult, self).addSuccess(test) 39 | self.__color = "Green" 40 | self.__state = "[OK]" 41 | 42 | def addUnexpectedSuccess(self, test): 43 | super(Py2JsTestResult, self).addUnexpectedSuccess(test) 44 | self.__color = "Green" 45 | self.__state = "should fail but [OK]" 46 | 47 | def addExpectedFailure(self, test, err): 48 | super(Py2JsTestResult, self).addExpectedFailure(test, err) 49 | self.__color = "Purple" 50 | self.__state = "known to [FAIL]" 51 | 52 | def addFailure(self, test, err): 53 | super(Py2JsTestResult, self).addFailure(test, err) 54 | self.__color = "Red" 55 | self.__state = "[FAIL]" 56 | 57 | def stopTestRun(self): 58 | super(Py2JsTestResult, self).stopTestRun() 59 | self.__writer.write("\n") 60 | 61 | class Py2JsTestRunner(unittest.TextTestRunner): 62 | """Test runner with Py2JsTestResult as result class""" 63 | resultclass = Py2JsTestResult 64 | 65 | -------------------------------------------------------------------------------- /testtools/tests.py: -------------------------------------------------------------------------------- 1 | """module which finds tests from the test directory and converts them to 2 | the unittest framework classes.""" 3 | 4 | import testtools.env_tests as env_tests 5 | import testtools.known_to_fail as known_to_fail 6 | import testtools.util as util 7 | import unittest 8 | import glob 9 | import os 10 | 11 | def create_cases(): 12 | """Helper function to find all tests in the test folders 13 | and wrapping them into the correct test class""" 14 | 15 | test_cases = unittest.TestSuite() 16 | test_cases.addTest( 17 | unittest.TestLoader().loadTestsFromTestCase( 18 | env_tests.EnviromentTest 19 | ) 20 | ) 21 | 22 | failing_test_cases = unittest.TestSuite() 23 | 24 | test_paths = glob.glob("tests/test_*.py") 25 | test_paths.sort() 26 | for test_path in test_paths: 27 | test_cases.addTest( 28 | unittest.TestLoader().loadTestsFromTestCase( 29 | util.compile_file_test(test_path, os.path.basename(test_path)) 30 | ) 31 | ) 32 | 33 | test_paths = glob.glob("tests/test_*.js") 34 | test_paths.sort() 35 | for test_path in test_paths: 36 | test_cases.addTest( 37 | unittest.TestLoader().loadTestsFromTestCase( 38 | util.run_with_stdlib(test_path, os.path.basename(test_path)) 39 | ) 40 | ) 41 | 42 | test_paths = glob.glob("tests/*/*.py") 43 | test_paths.sort() 44 | for test_path in test_paths: 45 | if ( 46 | test_path.replace("\\","/") not 47 | in known_to_fail.KNOWN_TO_FAIL 48 | ): 49 | test_cases.addTest( 50 | unittest.TestLoader().loadTestsFromTestCase( 51 | util.compile_and_run_file_test( 52 | test_path, 53 | os.path.basename(test_path) 54 | ) 55 | ) 56 | ) 57 | else: 58 | failing_test_cases.addTest( 59 | unittest.TestLoader().loadTestsFromTestCase( 60 | util.compile_and_run_file_failing_test( 61 | test_path, 62 | os.path.basename(test_path) 63 | ) 64 | ) 65 | ) 66 | return test_cases , failing_test_cases 67 | 68 | NOT_KNOWN_TO_FAIL, KNOWN_TO_FAIL = create_cases() 69 | ALL = unittest.TestSuite((NOT_KNOWN_TO_FAIL, KNOWN_TO_FAIL)) 70 | 71 | def get_tests(names): 72 | """filters out all tests that don't exist in names and 73 | adds them to a new test suite""" 74 | def flatten(itr): 75 | """tries to flatten out a suite to the individual tests""" 76 | import itertools 77 | try: 78 | return itertools.chain.from_iterable(flatten(item) for item in iter) 79 | except TypeError: 80 | return itertools.chain(*itr) 81 | 82 | return_suite = unittest.TestSuite() 83 | return_suite.addTest( 84 | unittest.TestLoader().loadTestsFromTestCase( 85 | env_tests.EnviromentTest 86 | ) 87 | ) 88 | for suite in flatten(iter(ALL)): 89 | test_name = str(suite._tests[0]) 90 | if any(True for name in names if name in test_name): 91 | return_suite.addTest(suite) 92 | return return_suite 93 | 94 | def load_tests(_loader, standard_tests, _search_pattern): 95 | """function called by the unittest framework to find tests in a module""" 96 | suite = standard_tests 97 | suite.addTests(ALL) 98 | return suite 99 | -------------------------------------------------------------------------------- /testtools/util.py: -------------------------------------------------------------------------------- 1 | """ 2 | Module that defines Tool functions and test runners/result for use with 3 | the unittest library. 4 | """ 5 | import sys 6 | if sys.version_info < (2, 7): 7 | import unittest2 as unittest 8 | else: 9 | import unittest 10 | import os 11 | import posixpath 12 | 13 | def get_posix_path(path): 14 | """translates path to a posix path""" 15 | heads = [] 16 | tail = path 17 | while tail != '': 18 | tail, head = os.path.split(tail) 19 | heads.append(head) 20 | return posixpath.join(*heads[::-1]) 21 | 22 | def run_with_stdlib(file_path, file_name=None): 23 | """Creates a test that runs a js file with the stdlib.""" 24 | file_name = file_name if file_name else file_path 25 | 26 | class TestStdLib(unittest.TestCase): 27 | """Tests js code with the stdlib""" 28 | templ = { 29 | "js_path": file_path, 30 | "js_unix_path": get_posix_path(file_path), 31 | "js_out_path": file_path + ".out", 32 | "js_error": file_path + ".err", 33 | "name": file_name, 34 | } 35 | def reportProgres(self): 36 | """Should be overloaded by the test result class.""" 37 | 38 | def runTest(self): 39 | """The actual test goes here.""" 40 | cmd = ( 41 | 'js -f "py-builtins.js" ' 42 | '-f "%(js_path)s" > "%(js_out_path)s" 2> "%(js_error)s"' 43 | )% self.templ 44 | self.assertEqual(0, os.system(cmd)) 45 | self.reportProgres() 46 | def __str__(self): 47 | return "%(js_unix_path)s [1]: " % self.templ 48 | 49 | return TestStdLib 50 | 51 | def compile_file_test(file_path, file_name=None): 52 | """Creates a test that tests if a file can be compiled by python""" 53 | file_name = file_name if file_name else file_path 54 | 55 | class CompileFile(unittest.TestCase): 56 | """Test if a file can be compiled by python.""" 57 | 58 | templ = { 59 | "py_path": file_path, 60 | "py_unix_path": get_posix_path(file_path), 61 | "py_out_path": file_path + ".out", 62 | "py_error": file_path + ".err", 63 | "name": file_name, 64 | } 65 | def reportProgres(self): 66 | """Should be overloaded by the test result class""" 67 | 68 | def runTest(self): 69 | """The actual test goes here.""" 70 | commands = ( 71 | ( 72 | 'python "%(py_path)s" > ' 73 | '"%(py_out_path)s" 2> "%(py_error)s"' 74 | ) % self.templ, 75 | ) 76 | for cmd in commands: 77 | self.assertEqual(0, os.system(cmd)) 78 | self.reportProgres() 79 | def __str__(self): 80 | return "%(py_unix_path)s [1]: " % self.templ 81 | return CompileFile 82 | 83 | 84 | 85 | 86 | def compile_and_run_file_test(file_path, file_name=None): 87 | """Creates a test that compiles and runs the python file as js""" 88 | file_name = file_name if file_name else file_path 89 | 90 | class CompileAndRunFile(unittest.TestCase): 91 | """Tests that a file can be compiled and run as js""" 92 | templ = { 93 | "py_path": file_path, 94 | "py_unix_path": get_posix_path(file_path), 95 | "py_out_path": file_path + ".out", 96 | "js_path": file_path + ".js", 97 | "js_out_path": file_path + ".js.out", 98 | "py_error": file_path + ".err", 99 | "js_error": file_path + "js.err", 100 | "compiler_error": file_path + ".comp.err", 101 | "name": file_name, 102 | } 103 | def reportProgres(self): 104 | """Should be overloaded by the test result class""" 105 | 106 | def runTest(self): 107 | """The actual test goes here.""" 108 | python_command = ( 109 | 'python "%(py_path)s" > "%(py_out_path)s" 2> ' 110 | '"%(py_error)s"' 111 | ) % self.templ 112 | compile_command = ( 113 | 'python pyjs.py --include-builtins ' 114 | '"%(py_path)s" > "%(js_path)s" 2> ' 115 | '"%(compiler_error)s"' 116 | ) % self.templ 117 | javascript_command = ( 118 | 'js -f "%(js_path)s" > "%(js_out_path)s" 2> ' 119 | '"%(js_error)s"' 120 | ) % self.templ 121 | commands = ( 122 | python_command, 123 | compile_command, 124 | javascript_command 125 | ) 126 | for cmd in commands: 127 | self.assertEqual(0, os.system(cmd)) 128 | self.reportProgres() 129 | self.assertEqual( 130 | file(self.templ["py_out_path"]).readlines(), 131 | file(self.templ["js_out_path"]).readlines() 132 | ) 133 | self.reportProgres() 134 | 135 | def __str__(self): 136 | return "%(py_unix_path)s [4]: " % self.templ 137 | 138 | return CompileAndRunFile 139 | 140 | def compile_and_run_file_failing_test(*a, **k): 141 | """Turn a test to a failing test""" 142 | _class = compile_and_run_file_test(*a, **k) 143 | 144 | class FailingTest(_class): 145 | """Failing test""" 146 | @unittest.expectedFailure 147 | def runTest(self): 148 | return super(FailingTest, self).runTest() 149 | 150 | return FailingTest 151 | 152 | -------------------------------------------------------------------------------- /testtools/writer.py: -------------------------------------------------------------------------------- 1 | """module with the Writer class that helps write colorful output""" 2 | 3 | class Writer(object): 4 | "Class which helps to print in color and with alignment and width" 5 | 6 | color_templates = ( 7 | ("Black" , "0;30"), 8 | ("Red" , "0;31"), 9 | ("Green" , "0;32"), 10 | ("Brown" , "0;33"), 11 | ("Blue" , "0;34"), 12 | ("Purple" , "0;35"), 13 | ("Cyan" , "0;36"), 14 | ("LightGray" , "0;37"), 15 | ("DarkGray" , "1;30"), 16 | ("LightRed" , "1;31"), 17 | ("LightGreen" , "1;32"), 18 | ("Yellow" , "1;33"), 19 | ("LightBlue" , "1;34"), 20 | ("LightPurple" , "1;35"), 21 | ("LightCyan" , "1;36"), 22 | ("White" , "1;37"), ) 23 | 24 | colors = dict(color_templates) 25 | 26 | c_normal = '\033[0m' 27 | 28 | c_color = '\033[%sm' 29 | 30 | def __init__(self, in_file = None): 31 | import sys 32 | self._line_wrap = False 33 | self._write_pos = 0 34 | self._file = in_file or sys.stdout 35 | #self._file = sys.stdout 36 | if not (hasattr(self._file, 'isatty') and self._file.isatty()): 37 | # the stdout is not a terminal, this for example happens if the 38 | # output is piped to less, e.g. "bin/test | less". In this case, 39 | # the terminal control sequences would be printed verbatim, so 40 | # don't use any colors. 41 | self.write = self.normal_write 42 | elif sys.platform != "win32": 43 | # We are on *nix system we can use ansi 44 | self.write = self.ansi_write 45 | else: 46 | try: 47 | import colorama 48 | colorama.init(wrap=False) 49 | self._file = colorama.AnsiToWin32(self._file).stream 50 | self.write = self.ansi_write 51 | except ImportError: 52 | self.write = self.normal_write 53 | 54 | def write(self, text, color="", align="left", width=80): 55 | """ 56 | Prints a text on the screen. 57 | 58 | It uses file.write(), so no readline library is necessary. 59 | 60 | color ... choose from the colors below, "" means default color 61 | align ... left/right, left is a normal print, right is aligned on the 62 | right hand side of the screen, filled with " " if necessary 63 | width ... the screen width 64 | """ 65 | 66 | def normal_write(self, text, color="", align="left", width=80): 67 | "Ignores color but uses alignment and width" 68 | _color = color 69 | if align == "right": 70 | if self._write_pos + len(text) > width: 71 | # we don't fit on the current line, create a new line 72 | self.write("\n") 73 | self.write(" " * (width - self._write_pos - len(text))) 74 | 75 | if self._line_wrap: 76 | if text != "" and text[0] != "\n": 77 | self._file.write("\n") 78 | 79 | self._file.write(text) 80 | self._file.flush() 81 | 82 | next_new_line = text.rfind("\n") 83 | 84 | if next_new_line == -1: 85 | self._write_pos += len(text) 86 | else: 87 | self._write_pos = len(text) - next_new_line - 1 88 | self._line_wrap = self._write_pos >= width 89 | self._write_pos %= width 90 | 91 | 92 | def ansi_write(self, text, color="", align="left", width=80): 93 | "Writes with color, alignment and width" 94 | try: 95 | return self.normal_write( 96 | text=( 97 | "%s%s%s" % ( 98 | self.c_color % self.colors[color], 99 | text, 100 | self.c_normal 101 | ) 102 | if color in self.colors 103 | else text 104 | ), 105 | color=color, 106 | align=align, 107 | width=width 108 | ) 109 | except AssertionError: 110 | return self.normal_write( 111 | text=text, 112 | color=color, 113 | align=align, 114 | width=width 115 | ) 116 | --------------------------------------------------------------------------------