[tryton-debian-vcs] simpleeval branch upstream updated. upstream/0.8.7-1-g0b2f046

Mathias Behrle tryton-debian-vcs at alioth.debian.org
Thu Dec 1 22:40:48 UTC 2016


The following commit has been merged in the upstream branch:
https://alioth.debian.org/plugins/scmgit/cgi-bin/gitweb.cgi/?p=tryton/simpleeval.git;a=commitdiff;h=upstream/0.8.7-1-g0b2f046

commit 0b2f046823582609e80ff2411407624b9ba51f53
Author: Mathias Behrle <mathiasb at m9s.biz>
Date:   Thu Dec 1 23:20:12 2016 +0100

    Adding upstream version 0.9.1.
    
    Signed-off-by: Mathias Behrle <mathiasb at m9s.biz>

diff --git a/.coveragerc b/.coveragerc
new file mode 100644
index 0000000..3aad258
--- /dev/null
+++ b/.coveragerc
@@ -0,0 +1,3 @@
+[run]
+branch = True
+omit = /home/travis/virtualenv/*
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b00a4fa
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+*.pyc
+build
+dist
+MANIFEST
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..09fdbaf
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,19 @@
+language: python
+python:
+    - "2.7"
+    - "3.2"
+    - "3.3"
+    - "3.4"
+    - "3.5"
+install:
+ - pip install nose
+ - pip install coveralls
+ # coverage no longer supports python 3.2...
+ # - pip install coverage
+ - if [ "$TRAVIS_PYTHON_VERSION" == "3.2" ]; then travis_retry pip install coverage==3.7.1; fi
+ - if [ "$TRAVIS_PYTHON_VERSION" != "3.2" ]; then travis_retry pip install coverage; fi
+script:
+ - nosetests
+ - coverage run -m nose
+after_success:
+ - coveralls
diff --git a/LICENCE b/LICENCE
new file mode 100644
index 0000000..40e7560
--- /dev/null
+++ b/LICENCE
@@ -0,0 +1,21 @@
+simpleeval - Copyright (c) 2013 Daniel Fairhead
+
+(MIT Licence)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/PKG-INFO b/PKG-INFO
deleted file mode 100644
index d505fd3..0000000
--- a/PKG-INFO
+++ /dev/null
@@ -1,239 +0,0 @@
-Metadata-Version: 1.1
-Name: simpleeval
-Version: 0.8.7
-Summary: A simple, safe single expression evaluator library.
-Home-page: https://github.com/danthedeckie/simpleeval
-Author: Daniel Fairhead
-Author-email: danthedeckie at gmail.com
-License: UNKNOWN
-Download-URL: https://github.com/danthedeckie/simpleeval/tarball/0.8.7
-Description: simpleeval (Simple Eval)
-        ========================
-        
-        A quick single file library for easily adding evaluatable expressions into python
-        projects.  Say you want to allow a user to set an alarm volume, which could depend
-        on the time of day, alarm level, how many previous alarms had gone off, and if there
-        is music playing at the time.
-        
-        Or if you want to allow simple formulae in a web application, but don't want to
-        give full eval() access, or don't want to run in javascript on the client side.
-        
-        It's deliberately very simple, just a single file you can dump into a project, or import
-        from pypi (pip or easy_install).
-        
-        Internally, it's using the amazing python ``ast`` module to parse the expression, which
-        allows very fine control of what is and isn't allowed.  It should be completely safe in terms
-        of what operations can be performed by the expression.
-        
-        The only issue I know to be aware of is that you can create an expression which
-        takes a long time to evaluate, or which evaluating requires an awful lot of memory,
-        which leaves the potential for DOS attacks.  There is basic protection against this,
-        and you can lock it down further if you desire. (see the `Operators` section below)
-        
-        You should be aware of this when deploying in a public setting.
-        
-        The defaults are pretty locked down and basic, and it's very easy to add whatever
-        extra specific functionality you need (your own functions, variable/name lookup, etc).
-        
-        Basic Usage
-        -----------
-        
-        To get very simple evaluating: ::
-        
-            from simpleeval import simple_eval
-        
-            simple_eval("21 + 21")
-        
-        returns ``42``.
-        
-        Expressions can be as complex and convoluted as you want: ::
-        
-            simple_eval("21 + 19 / 7 + (8 % 3) ** 9")
-        
-        returns ``535.714285714``.
-        
-        You can add your own functions in as well. ::
-        
-            simple_eval("square(11)", functions={"square": lambda x: x*x})
-        
-        returns ``121``.
-        
-        For more details of working with functions, read further down.
-        
-        Note:
-        ~~~~~
-        all further examples use ``>>>`` to designate python code, as if you are using the python interactive
-        prompt.
-        
-        Operators
-        ---------
-        You can add operators yourself, using the ``operators`` argument, but these are the defaults:
-        
-         +----+------------------------------------+
-         | \+ | add two things. ``x + y``          |
-         |    | ``1 + 1`` -> ``2``                 |
-         +----+------------------------------------+
-         | \- | subtract two things ``x - y``      |
-         |    | ``100 - 1`` -> ``99``              |
-         +----+------------------------------------+
-         | \/ | divide one thing by another        |
-         |    | ``x / y``                          |
-         |    | ``100/10`` -> ``10``               |
-         +----+------------------------------------+
-         | \* | multiple one thing by another      |
-         |    | ``x * y``                          |
-         |    | ``10 * 10`` -> ``100``             |
-         +----+------------------------------------+
-         |\*\*| 'to the power of' ``x**y``         |
-         |    | ``2 ** 10`` -> ``1024``            |
-         +----+------------------------------------+
-         | \% | modulus. (remainder)  ``x % y``    |
-         |    | ``15 % 4`` -> ``3``                |
-         +----+------------------------------------+
-         | == | equals  ``x == y``                 |
-         |    | ``15 == 4`` -> ``False``           |
-         +----+------------------------------------+
-         | <  | Less than. ``x < y``               |
-         |    | ``1 < 4`` -> ``True``              |
-         +----+------------------------------------+
-         | >  | Greater than. ``x > y``            |
-         |    | ``1 > 4`` -> ``False``             |
-         +----+------------------------------------+
-         | <= | Less than or Equal to. ``x <= y``  |
-         |    | ``1 < 4`` -> ``True``              |
-         +----+------------------------------------+
-         | >= | Greater or Equal to ``x >= 21``    |
-         |    | ``1 >= 4`` -> ``False``            |
-         +----+------------------------------------+
-        
-        
-        The ``^`` operator is notably missing - not because it's hard, but because it is often mistaken for
-        a exponent operator, not the bitwise operation that it is in python.  It's trivial to add back in again
-        if you wish (using the class based evaluator explained below): ::
-        
-            >>> import ast
-            >>> import operator
-        
-            >>> s = SimpleEval()
-            >>> s.operators[ast.BitXor] = operator.xor
-        
-            >>> s.eval("2 ^ 10")
-            8
-        
-        Limited Power
-        ~~~~~~~~~~~~~
-        
-        Also note, the ``**`` operator has been locked down by default to have a maximum input value
-        of ``4000000``, which makes it somewhat harder to make expressions which go on for ever.  You
-        can change this limit by changing the ``simpleeval.POWER_MAX`` module level value to whatever
-        is an appropriate value for you (and the hardware that you're running on) or if you want to
-        completely remove all limitations, you can set the ``s.operators[ast.Pow] = operator.pow`` or make
-        your own function.
-        
-        On my computer, ``9**9**5`` evaluates almost instantly, but ``9**9**6`` takes over 30 seconds.
-        Since ``9**7`` is ``4782969``, and so over the ``POWER_MAX`` limit, it throws a
-        ``NumberTooHigh`` exception for you. (Otherwise it would go on for hours, or until the computer
-        runs out of memory)
-        
-        String Safety
-        ~~~~~~~~~~~~~
-        
-        There are also limits on string length (100000 characters, ``MAX_STRING_LENGTH``).
-        This can be changed if you wish.
-        
-        If Expressions
-        --------------
-        
-        You can use python style ``if x then y else z`` type expressions: ::
-        
-            >>> simple_eval("'equal' if x == y else 'not equal'",
-                            names={"x": 1, "y": 2})
-            'not equal'
-        
-        which, of course, can be nested: ::
-        
-            >>> simple_eval("'a' if 1 == 2 else 'b' if 2 == 3 else 'c'")
-            'c'
-            
-        
-        Functions
-        ---------
-        
-        You can define functions which you'd like the expresssions to have access to: ::
-        
-            >>> simple_eval("double(21)", functions={"double": lambda x:x*2})
-            42
-        
-        You can define "real" functions to pass in rather than lambdas, of course too, and even re-name them so that expressions can be shorter ::
-        
-            >>> def double(x):
-                    return x * 2
-            >>> simple_eval("d(100) + double(1)", functions={"d": double, "double":double})
-            202
-        
-        Names
-        -----
-         
-        Sometimes it's useful to have variables available, which in python terminology are called 'names'. ::
-        
-            >>> simple_eval("a + b", names={"a": 11, "b": 100})
-            111
-        
-        You can also hand the handling of names over to a function, if you prefer: ::
-        
-            >>> def name_handler(node):
-                    return ord(node.id[0].lower(a))-96
-        
-            >>> simple_eval('a + b', names=name_handler)
-            3
-        
-        That was a bit of a silly example, but you could use this for pulling values from a database or file, say, or doing some kind of caching system.
-        
-        Creating an Evaluator Class
-        ---------------------------
-        
-        Rather than creating a new evaluator each time, if you are doing a lot of evaluations,
-        you can create a SimpleEval object, and pass it expressions each time (which should be a bit quicker, and certainly more convenient for some use cases): ::
-        
-            s = SimpleEval()
-            s.eval("1 + 1")
-            # and so on...
-        
-        You can assign / edit the various options of the ``SimpleEval`` object if you want to.
-        Either assign them during creation (like the ``simple_eval`` function) ::
-        
-            s = SimpleEval(functions={"boo": boo})
-        
-        or edit them after creation: ::
-        
-            s.names['fortytwo'] = 42
-        
-        this actually means you can modify names (or functions) with functions, if you really feel so inclined: ::
-        
-            s = SimpleEval()
-            def set_val(name, value):
-                s.names[name.value] = value.value
-                return value.value
-        
-            s.functions = {'set': set_val}
-        
-            s.eval("set('age', 111)")
-        
-        Say.  This would allow a certain level of 'scriptyness' if you had these evaluations happening as callbacks in a program.  Although you really are reaching the end of what this library is intended for at this stage.
-        
-        Other...
-        --------
-        
-        The library supports both python 2 and 3 using the 2to3 converter.
-        
-        Please read the ``test_simpleeval.py`` file for other potential gotchas or details.  I'm very happy to accept pull requests, suggestions, or other issues.  Enjoy!
-        
-        .. image:: https://coveralls.io/repos/danthedeckie/simpleeval/badge.png :target: https://coveralls.io/r/danthedeckie/simpleeval 
-        
-Keywords: eval,simple,expression,parse,ast
-Platform: UNKNOWN
-Classifier: Development Status :: 4 - Beta
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: MIT License
-Classifier: Topic :: Software Development :: Libraries :: Python Modules
-Classifier: Programming Language :: Python
diff --git a/README.rst b/README.rst
index 266f0b6..7b78c5b 100644
--- a/README.rst
+++ b/README.rst
@@ -1,35 +1,52 @@
 simpleeval (Simple Eval)
 ========================
 
-A quick single file library for easily adding evaluatable expressions into python
-projects.  Say you want to allow a user to set an alarm volume, which could depend
-on the time of day, alarm level, how many previous alarms had gone off, and if there
-is music playing at the time.
+.. image:: https://travis-ci.org/danthedeckie/simpleeval.svg?branch=master
+   :target: https://travis-ci.org/danthedeckie/simpleeval
+   :alt: Build Status
+   
+.. image:: https://coveralls.io/repos/github/danthedeckie/simpleeval/badge.svg?branch=master
+   :target: https://coveralls.io/r/danthedeckie/simpleeval?branch=master
+   :alt: Coverage Status
+
+.. image:: https://badge.fury.io/py/simpleeval.svg
+   :target: https://badge.fury.io/py/simpleeval
+   :alt: PyPI Version
+
+A quick single file library for easily adding evaluatable expressions into
+python projects.  Say you want to allow a user to set an alarm volume, which
+could depend on the time of day, alarm level, how many previous alarms had gone
+off, and if there is music playing at the time.
 
 Or if you want to allow simple formulae in a web application, but don't want to
 give full eval() access, or don't want to run in javascript on the client side.
 
-It's deliberately very simple, just a single file you can dump into a project, or import
-from pypi (pip or easy_install).
+It's deliberately very simple, just a single file you can dump into a project,
+or import from pypi (pip or easy_install).
 
-Internally, it's using the amazing python ``ast`` module to parse the expression, which
-allows very fine control of what is and isn't allowed.  It should be completely safe in terms
-of what operations can be performed by the expression.
+Internally, it's using the amazing python ``ast`` module to parse the
+expression, which allows very fine control of what is and isn't allowed.  It
+should be completely safe in terms of what operations can be performed by the
+expression.
 
 The only issue I know to be aware of is that you can create an expression which
-takes a long time to evaluate, or which evaluating requires an awful lot of memory,
-which leaves the potential for DOS attacks.  There is basic protection against this,
-and you can lock it down further if you desire. (see the `Operators` section below)
+takes a long time to evaluate, or which evaluating requires an awful lot of
+memory, which leaves the potential for DOS attacks.  There is basic protection
+against this, and you can lock it down further if you desire. (see the
+`Operators` section below)
 
 You should be aware of this when deploying in a public setting.
 
-The defaults are pretty locked down and basic, and it's very easy to add whatever
-extra specific functionality you need (your own functions, variable/name lookup, etc).
+The defaults are pretty locked down and basic, and it's very easy to add
+whatever extra specific functionality you need (your own functions,
+variable/name lookup, etc).
 
 Basic Usage
 -----------
 
-To get very simple evaluating: ::
+To get very simple evaluating:
+
+.. code-block:: python
 
     from simpleeval import simple_eval
 
@@ -37,13 +54,17 @@ To get very simple evaluating: ::
 
 returns ``42``.
 
-Expressions can be as complex and convoluted as you want: ::
+Expressions can be as complex and convoluted as you want:
+
+.. code-block:: python
 
     simple_eval("21 + 19 / 7 + (8 % 3) ** 9")
 
 returns ``535.714285714``.
 
-You can add your own functions in as well. ::
+You can add your own functions in as well.
+
+.. code-block:: python
 
     simple_eval("square(11)", functions={"square": lambda x: x*x})
 
@@ -53,12 +74,13 @@ For more details of working with functions, read further down.
 
 Note:
 ~~~~~
-all further examples use ``>>>`` to designate python code, as if you are using the python interactive
-prompt.
+all further examples use ``>>>`` to designate python code, as if you are using
+the python interactive prompt.
 
 Operators
 ---------
-You can add operators yourself, using the ``operators`` argument, but these are the defaults:
+You can add operators yourself, using the ``operators`` argument, but these are
+the defaults:
 
  +----+------------------------------------+
  | \+ | add two things. ``x + y``          |
@@ -98,9 +120,12 @@ You can add operators yourself, using the ``operators`` argument, but these are
  +----+------------------------------------+
 
 
-The ``^`` operator is notably missing - not because it's hard, but because it is often mistaken for
-a exponent operator, not the bitwise operation that it is in python.  It's trivial to add back in again
-if you wish (using the class based evaluator explained below): ::
+The ``^`` operator is notably missing - not because it's hard, but because it
+is often mistaken for a exponent operator, not the bitwise operation that it is
+in python.  It's trivial to add back in again if you wish (using the class
+based evaluator explained below):
+
+.. code-block:: python
 
     >>> import ast
     >>> import operator
@@ -114,34 +139,39 @@ if you wish (using the class based evaluator explained below): ::
 Limited Power
 ~~~~~~~~~~~~~
 
-Also note, the ``**`` operator has been locked down by default to have a maximum input value
-of ``4000000``, which makes it somewhat harder to make expressions which go on for ever.  You
-can change this limit by changing the ``simpleeval.POWER_MAX`` module level value to whatever
-is an appropriate value for you (and the hardware that you're running on) or if you want to
-completely remove all limitations, you can set the ``s.operators[ast.Pow] = operator.pow`` or make
-your own function.
+Also note, the ``**`` operator has been locked down by default to have a
+maximum input value of ``4000000``, which makes it somewhat harder to make
+expressions which go on for ever.  You can change this limit by changing the
+``simpleeval.POWER_MAX`` module level value to whatever is an appropriate value
+for you (and the hardware that you're running on) or if you want to completely
+remove all limitations, you can set the ``s.operators[ast.Pow] = operator.pow``
+or make your own function.
 
-On my computer, ``9**9**5`` evaluates almost instantly, but ``9**9**6`` takes over 30 seconds.
-Since ``9**7`` is ``4782969``, and so over the ``POWER_MAX`` limit, it throws a
-``NumberTooHigh`` exception for you. (Otherwise it would go on for hours, or until the computer
-runs out of memory)
+On my computer, ``9**9**5`` evaluates almost instantly, but ``9**9**6`` takes
+over 30 seconds.  Since ``9**7`` is ``4782969``, and so over the ``POWER_MAX``
+limit, it throws a ``NumberTooHigh`` exception for you. (Otherwise it would go
+on for hours, or until the computer runs out of memory)
 
 String Safety
 ~~~~~~~~~~~~~
 
-There are also limits on string length (100000 characters, ``MAX_STRING_LENGTH``).
-This can be changed if you wish.
+There are also limits on string length (100000 characters,
+``MAX_STRING_LENGTH``).  This can be changed if you wish.
 
 If Expressions
 --------------
 
-You can use python style ``if x then y else z`` type expressions: ::
+You can use python style ``if x then y else z`` type expressions:
+
+.. code-block:: python
 
     >>> simple_eval("'equal' if x == y else 'not equal'",
                     names={"x": 1, "y": 2})
     'not equal'
 
-which, of course, can be nested: ::
+which, of course, can be nested:
+
+.. code-block:: python
 
     >>> simple_eval("'a' if 1 == 2 else 'b' if 2 == 3 else 'c'")
     'c'
@@ -150,12 +180,17 @@ which, of course, can be nested: ::
 Functions
 ---------
 
-You can define functions which you'd like the expresssions to have access to: ::
+You can define functions which you'd like the expresssions to have access to:
+
+.. code-block:: python
 
     >>> simple_eval("double(21)", functions={"double": lambda x:x*2})
     42
 
-You can define "real" functions to pass in rather than lambdas, of course too, and even re-name them so that expressions can be shorter ::
+You can define "real" functions to pass in rather than lambdas, of course too,
+and even re-name them so that expressions can be shorter
+
+.. code-block:: python
 
     >>> def double(x):
             return x * 2
@@ -164,13 +199,19 @@ You can define "real" functions to pass in rather than lambdas, of course too, a
 
 Names
 -----
- 
-Sometimes it's useful to have variables available, which in python terminology are called 'names'. ::
+
+Sometimes it's useful to have variables available, which in python terminology
+are called 'names'.
+
+.. code-block:: python
 
     >>> simple_eval("a + b", names={"a": 11, "b": 100})
     111
 
-You can also hand the handling of names over to a function, if you prefer: ::
+You can also hand the handling of names over to a function, if you prefer:
+
+
+.. code-block:: python
 
     >>> def name_handler(node):
             return ord(node.id[0].lower(a))-96
@@ -178,28 +219,41 @@ You can also hand the handling of names over to a function, if you prefer: ::
     >>> simple_eval('a + b', names=name_handler)
     3
 
-That was a bit of a silly example, but you could use this for pulling values from a database or file, say, or doing some kind of caching system.
+That was a bit of a silly example, but you could use this for pulling values
+from a database or file, say, or doing some kind of caching system.
 
 Creating an Evaluator Class
 ---------------------------
 
-Rather than creating a new evaluator each time, if you are doing a lot of evaluations,
-you can create a SimpleEval object, and pass it expressions each time (which should be a bit quicker, and certainly more convenient for some use cases): ::
+Rather than creating a new evaluator each time, if you are doing a lot of
+evaluations, you can create a SimpleEval object, and pass it expressions each
+time (which should be a bit quicker, and certainly more convenient for some use
+cases):
+
+.. code-block:: python
 
     s = SimpleEval()
     s.eval("1 + 1")
     # and so on...
 
-You can assign / edit the various options of the ``SimpleEval`` object if you want to.
-Either assign them during creation (like the ``simple_eval`` function) ::
+You can assign / edit the various options of the ``SimpleEval`` object if you
+want to.  Either assign them during creation (like the ``simple_eval``
+function)
+
+.. code-block:: python
 
     s = SimpleEval(functions={"boo": boo})
 
-or edit them after creation: ::
+or edit them after creation:
+
+.. code-block:: python
 
     s.names['fortytwo'] = 42
 
-this actually means you can modify names (or functions) with functions, if you really feel so inclined: ::
+this actually means you can modify names (or functions) with functions, if you
+really feel so inclined:
+
+.. code-block:: python
 
     s = SimpleEval()
     def set_val(name, value):
@@ -210,13 +264,19 @@ this actually means you can modify names (or functions) with functions, if you r
 
     s.eval("set('age', 111)")
 
-Say.  This would allow a certain level of 'scriptyness' if you had these evaluations happening as callbacks in a program.  Although you really are reaching the end of what this library is intended for at this stage.
+Say.  This would allow a certain level of 'scriptyness' if you had these
+evaluations happening as callbacks in a program.  Although you really are
+reaching the end of what this library is intended for at this stage.
 
 Other...
 --------
 
-The library supports both python 2 and 3 using the 2to3 converter.
+The library supports both python 2 and 3.
 
-Please read the ``test_simpleeval.py`` file for other potential gotchas or details.  I'm very happy to accept pull requests, suggestions, or other issues.  Enjoy!
+Object attributes that start with ``_`` or ``func_`` are disallowed by default.
+If you really need that (BE CAREFUL!), then modify the module global
+``simpleeval.DISALLOW_PREFIXES``.
 
-.. image:: https://coveralls.io/repos/danthedeckie/simpleeval/badge.png :target: https://coveralls.io/r/danthedeckie/simpleeval 
+Please read the ``test_simpleeval.py`` file for other potential gotchas or
+details.  I'm very happy to accept pull requests, suggestions, or other issues.
+Enjoy!
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 861a9f5..0000000
--- a/setup.cfg
+++ /dev/null
@@ -1,5 +0,0 @@
-[egg_info]
-tag_build = 
-tag_date = 0
-tag_svn_revision = 0
-
diff --git a/setup.py b/setup.py
index 0e71ef7..7f0d069 100644
--- a/setup.py
+++ b/setup.py
@@ -1,5 +1,5 @@
 from setuptools import setup
-__version__ = '0.8.7'
+__version__ = '0.9.1'
 
 setup(
     name = 'simpleeval',
diff --git a/simpleeval.egg-info/PKG-INFO b/simpleeval.egg-info/PKG-INFO
deleted file mode 100644
index d505fd3..0000000
--- a/simpleeval.egg-info/PKG-INFO
+++ /dev/null
@@ -1,239 +0,0 @@
-Metadata-Version: 1.1
-Name: simpleeval
-Version: 0.8.7
-Summary: A simple, safe single expression evaluator library.
-Home-page: https://github.com/danthedeckie/simpleeval
-Author: Daniel Fairhead
-Author-email: danthedeckie at gmail.com
-License: UNKNOWN
-Download-URL: https://github.com/danthedeckie/simpleeval/tarball/0.8.7
-Description: simpleeval (Simple Eval)
-        ========================
-        
-        A quick single file library for easily adding evaluatable expressions into python
-        projects.  Say you want to allow a user to set an alarm volume, which could depend
-        on the time of day, alarm level, how many previous alarms had gone off, and if there
-        is music playing at the time.
-        
-        Or if you want to allow simple formulae in a web application, but don't want to
-        give full eval() access, or don't want to run in javascript on the client side.
-        
-        It's deliberately very simple, just a single file you can dump into a project, or import
-        from pypi (pip or easy_install).
-        
-        Internally, it's using the amazing python ``ast`` module to parse the expression, which
-        allows very fine control of what is and isn't allowed.  It should be completely safe in terms
-        of what operations can be performed by the expression.
-        
-        The only issue I know to be aware of is that you can create an expression which
-        takes a long time to evaluate, or which evaluating requires an awful lot of memory,
-        which leaves the potential for DOS attacks.  There is basic protection against this,
-        and you can lock it down further if you desire. (see the `Operators` section below)
-        
-        You should be aware of this when deploying in a public setting.
-        
-        The defaults are pretty locked down and basic, and it's very easy to add whatever
-        extra specific functionality you need (your own functions, variable/name lookup, etc).
-        
-        Basic Usage
-        -----------
-        
-        To get very simple evaluating: ::
-        
-            from simpleeval import simple_eval
-        
-            simple_eval("21 + 21")
-        
-        returns ``42``.
-        
-        Expressions can be as complex and convoluted as you want: ::
-        
-            simple_eval("21 + 19 / 7 + (8 % 3) ** 9")
-        
-        returns ``535.714285714``.
-        
-        You can add your own functions in as well. ::
-        
-            simple_eval("square(11)", functions={"square": lambda x: x*x})
-        
-        returns ``121``.
-        
-        For more details of working with functions, read further down.
-        
-        Note:
-        ~~~~~
-        all further examples use ``>>>`` to designate python code, as if you are using the python interactive
-        prompt.
-        
-        Operators
-        ---------
-        You can add operators yourself, using the ``operators`` argument, but these are the defaults:
-        
-         +----+------------------------------------+
-         | \+ | add two things. ``x + y``          |
-         |    | ``1 + 1`` -> ``2``                 |
-         +----+------------------------------------+
-         | \- | subtract two things ``x - y``      |
-         |    | ``100 - 1`` -> ``99``              |
-         +----+------------------------------------+
-         | \/ | divide one thing by another        |
-         |    | ``x / y``                          |
-         |    | ``100/10`` -> ``10``               |
-         +----+------------------------------------+
-         | \* | multiple one thing by another      |
-         |    | ``x * y``                          |
-         |    | ``10 * 10`` -> ``100``             |
-         +----+------------------------------------+
-         |\*\*| 'to the power of' ``x**y``         |
-         |    | ``2 ** 10`` -> ``1024``            |
-         +----+------------------------------------+
-         | \% | modulus. (remainder)  ``x % y``    |
-         |    | ``15 % 4`` -> ``3``                |
-         +----+------------------------------------+
-         | == | equals  ``x == y``                 |
-         |    | ``15 == 4`` -> ``False``           |
-         +----+------------------------------------+
-         | <  | Less than. ``x < y``               |
-         |    | ``1 < 4`` -> ``True``              |
-         +----+------------------------------------+
-         | >  | Greater than. ``x > y``            |
-         |    | ``1 > 4`` -> ``False``             |
-         +----+------------------------------------+
-         | <= | Less than or Equal to. ``x <= y``  |
-         |    | ``1 < 4`` -> ``True``              |
-         +----+------------------------------------+
-         | >= | Greater or Equal to ``x >= 21``    |
-         |    | ``1 >= 4`` -> ``False``            |
-         +----+------------------------------------+
-        
-        
-        The ``^`` operator is notably missing - not because it's hard, but because it is often mistaken for
-        a exponent operator, not the bitwise operation that it is in python.  It's trivial to add back in again
-        if you wish (using the class based evaluator explained below): ::
-        
-            >>> import ast
-            >>> import operator
-        
-            >>> s = SimpleEval()
-            >>> s.operators[ast.BitXor] = operator.xor
-        
-            >>> s.eval("2 ^ 10")
-            8
-        
-        Limited Power
-        ~~~~~~~~~~~~~
-        
-        Also note, the ``**`` operator has been locked down by default to have a maximum input value
-        of ``4000000``, which makes it somewhat harder to make expressions which go on for ever.  You
-        can change this limit by changing the ``simpleeval.POWER_MAX`` module level value to whatever
-        is an appropriate value for you (and the hardware that you're running on) or if you want to
-        completely remove all limitations, you can set the ``s.operators[ast.Pow] = operator.pow`` or make
-        your own function.
-        
-        On my computer, ``9**9**5`` evaluates almost instantly, but ``9**9**6`` takes over 30 seconds.
-        Since ``9**7`` is ``4782969``, and so over the ``POWER_MAX`` limit, it throws a
-        ``NumberTooHigh`` exception for you. (Otherwise it would go on for hours, or until the computer
-        runs out of memory)
-        
-        String Safety
-        ~~~~~~~~~~~~~
-        
-        There are also limits on string length (100000 characters, ``MAX_STRING_LENGTH``).
-        This can be changed if you wish.
-        
-        If Expressions
-        --------------
-        
-        You can use python style ``if x then y else z`` type expressions: ::
-        
-            >>> simple_eval("'equal' if x == y else 'not equal'",
-                            names={"x": 1, "y": 2})
-            'not equal'
-        
-        which, of course, can be nested: ::
-        
-            >>> simple_eval("'a' if 1 == 2 else 'b' if 2 == 3 else 'c'")
-            'c'
-            
-        
-        Functions
-        ---------
-        
-        You can define functions which you'd like the expresssions to have access to: ::
-        
-            >>> simple_eval("double(21)", functions={"double": lambda x:x*2})
-            42
-        
-        You can define "real" functions to pass in rather than lambdas, of course too, and even re-name them so that expressions can be shorter ::
-        
-            >>> def double(x):
-                    return x * 2
-            >>> simple_eval("d(100) + double(1)", functions={"d": double, "double":double})
-            202
-        
-        Names
-        -----
-         
-        Sometimes it's useful to have variables available, which in python terminology are called 'names'. ::
-        
-            >>> simple_eval("a + b", names={"a": 11, "b": 100})
-            111
-        
-        You can also hand the handling of names over to a function, if you prefer: ::
-        
-            >>> def name_handler(node):
-                    return ord(node.id[0].lower(a))-96
-        
-            >>> simple_eval('a + b', names=name_handler)
-            3
-        
-        That was a bit of a silly example, but you could use this for pulling values from a database or file, say, or doing some kind of caching system.
-        
-        Creating an Evaluator Class
-        ---------------------------
-        
-        Rather than creating a new evaluator each time, if you are doing a lot of evaluations,
-        you can create a SimpleEval object, and pass it expressions each time (which should be a bit quicker, and certainly more convenient for some use cases): ::
-        
-            s = SimpleEval()
-            s.eval("1 + 1")
-            # and so on...
-        
-        You can assign / edit the various options of the ``SimpleEval`` object if you want to.
-        Either assign them during creation (like the ``simple_eval`` function) ::
-        
-            s = SimpleEval(functions={"boo": boo})
-        
-        or edit them after creation: ::
-        
-            s.names['fortytwo'] = 42
-        
-        this actually means you can modify names (or functions) with functions, if you really feel so inclined: ::
-        
-            s = SimpleEval()
-            def set_val(name, value):
-                s.names[name.value] = value.value
-                return value.value
-        
-            s.functions = {'set': set_val}
-        
-            s.eval("set('age', 111)")
-        
-        Say.  This would allow a certain level of 'scriptyness' if you had these evaluations happening as callbacks in a program.  Although you really are reaching the end of what this library is intended for at this stage.
-        
-        Other...
-        --------
-        
-        The library supports both python 2 and 3 using the 2to3 converter.
-        
-        Please read the ``test_simpleeval.py`` file for other potential gotchas or details.  I'm very happy to accept pull requests, suggestions, or other issues.  Enjoy!
-        
-        .. image:: https://coveralls.io/repos/danthedeckie/simpleeval/badge.png :target: https://coveralls.io/r/danthedeckie/simpleeval 
-        
-Keywords: eval,simple,expression,parse,ast
-Platform: UNKNOWN
-Classifier: Development Status :: 4 - Beta
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: MIT License
-Classifier: Topic :: Software Development :: Libraries :: Python Modules
-Classifier: Programming Language :: Python
diff --git a/simpleeval.egg-info/SOURCES.txt b/simpleeval.egg-info/SOURCES.txt
deleted file mode 100644
index e0716d8..0000000
--- a/simpleeval.egg-info/SOURCES.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-MANIFEST.in
-README.rst
-setup.py
-simpleeval.py
-test_simpleeval.py
-simpleeval.egg-info/PKG-INFO
-simpleeval.egg-info/SOURCES.txt
-simpleeval.egg-info/dependency_links.txt
-simpleeval.egg-info/top_level.txt
\ No newline at end of file
diff --git a/simpleeval.egg-info/dependency_links.txt b/simpleeval.egg-info/dependency_links.txt
deleted file mode 100644
index 8b13789..0000000
--- a/simpleeval.egg-info/dependency_links.txt
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/simpleeval.egg-info/top_level.txt b/simpleeval.egg-info/top_level.txt
deleted file mode 100644
index 49a7c04..0000000
--- a/simpleeval.egg-info/top_level.txt
+++ /dev/null
@@ -1 +0,0 @@
-simpleeval
diff --git a/simpleeval.py b/simpleeval.py
index 81e4193..010748d 100644
--- a/simpleeval.py
+++ b/simpleeval.py
@@ -1,5 +1,5 @@
 '''
-SimpleEval - (C) 2013/2015 Daniel Fairhead
+SimpleEval - (C) 2013-2016 Daniel Fairhead
 -------------------------------------
 
 An short, easy to use, safe and reasonably extensible expression evaluator.
@@ -39,6 +39,7 @@ Contributors:
 - dratchkov (David R) (nested dicts)
 - marky1991 (Mark Young) (slicing)
 - T045T (Nils Berg) (!=, py3kstr, obj.attributes)
+- perkinslr (Logan Perkins) (.__globals__ or .func_ breakouts)
 
 -------------------------------------
 Usage:
@@ -87,74 +88,88 @@ from random import random
 # Module wide 'globals'
 
 MAX_STRING_LENGTH = 100000
-MAX_POWER = 4000000 # highest exponent
+MAX_POWER = 4000000  # highest exponent
+DISALLOW_PREFIXES = ['_', 'func_']
+
 PYTHON3 = sys.version_info[0] == 3
 
 ########################################
 # Exceptions:
 
+
 class InvalidExpression(Exception):
     ''' Generic Exception '''
     pass
 
+
 class FunctionNotDefined(InvalidExpression):
     ''' sorry! That function isn't defined! '''
     def __init__(self, func_name, expression):
         self.message = "Function '{0}' not defined," \
-                       " for expression '{1}'.".format( func_name, expression)
+                       " for expression '{1}'.".format(func_name, expression)
         self.func_name = func_name
         self.expression = expression
 
         # pylint: disable=bad-super-call
         super(InvalidExpression, self).__init__(self.message)
 
+
 class NameNotDefined(InvalidExpression):
     ''' a name isn't defined. '''
     def __init__(self, name, expression):
         self.message = "'{0}' is not defined for expression '{1}'".format(
-                            name, expression)
+            name, expression)
         self.name = name
         self.expression = expression
 
         # pylint: disable=bad-super-call
         super(InvalidExpression, self).__init__(self.message)
 
+
 class AttributeDoesNotExist(InvalidExpression):
     '''attribute does not exist'''
     def __init__(self, attr, expression):
-        self.message = "Attribute '{0}' does not exist in expression '{1}'".format(
-            attr, expression)
+        self.message = \
+            "Attribute '{0}' does not exist in expression '{1}'".format(
+                attr, expression)
         self.attr = attr
         self.expression = expression
- 
+
+
 class FeatureNotAvailable(InvalidExpression):
     ''' What you're trying to do is not allowed. '''
     pass
 
+
 class NumberTooHigh(InvalidExpression):
     ''' Sorry! That number is too high. I don't want to spend the
         next 10 years evaluating this expression! '''
     pass
 
+
 class StringTooLong(InvalidExpression):
     ''' That string is **way** too long, baby. '''
     pass
 
+
 ########################################
 # Default simple functions to include:
 
+
 def random_int(top):
     ''' return a random int below <top> '''
     return int(random() * top)
 
-def safe_power(a, b): # pylint: disable=invalid-name
+
+def safe_power(a, b):  # pylint: disable=invalid-name
     ''' a limited exponent/to-the-power-of function, for safety reasons '''
     if abs(a) > MAX_POWER or abs(b) > MAX_POWER:
         raise NumberTooHigh("Sorry! I don't want to evaluate {0} ** {1}"
                             .format(a, b))
     return a ** b
 
-def safe_mult(a, b): # pylint: disable=invalid-name
+
+def safe_mult(a, b):  # pylint: disable=invalid-name
     ''' limit the number of times a string can be repeated... '''
     if isinstance(a, str) or isinstance(b, str):
         if isinstance(a, int) and a*len(b) > MAX_STRING_LENGTH:
@@ -164,7 +179,8 @@ def safe_mult(a, b): # pylint: disable=invalid-name
 
     return a * b
 
-def safe_add(a, b): # pylint: disable=invalid-name
+
+def safe_add(a, b):  # pylint: disable=invalid-name
     ''' string length limit again '''
     if isinstance(a, str) and isinstance(b, str):
         if len(a) + len(b) > MAX_STRING_LENGTH:
@@ -178,19 +194,22 @@ def safe_add(a, b): # pylint: disable=invalid-name
 
 DEFAULT_OPERATORS = {ast.Add: safe_add, ast.Sub: op.sub, ast.Mult: safe_mult,
                      ast.Div: op.truediv, ast.Pow: safe_power, ast.Mod: op.mod,
-                     ast.Eq: op.eq, ast.NotEq: op.ne, ast.Gt: op.gt, ast.Lt: op.lt,
+                     ast.Eq: op.eq, ast.NotEq: op.ne,
+                     ast.Gt: op.gt, ast.Lt: op.lt,
                      ast.GtE: op.ge, ast.LtE: op.le, ast.USub: op.neg,
                      ast.UAdd: op.pos}
 
 DEFAULT_FUNCTIONS = {"rand": random, "randint": random_int,
-                     "int": int, "float": float, "str": str if PYTHON3 else unicode}
+                     "int": int, "float": float,
+                     "str": str if PYTHON3 else unicode}
 
 DEFAULT_NAMES = {"True": True, "False": False}
 
 ########################################
 # And the actual evaluator:
 
-class SimpleEval(object): # pylint: disable=too-few-public-methods
+
+class SimpleEval(object):  # pylint: disable=too-few-public-methods
     ''' A very simple expression parser.
         >>> s = SimpleEval()
         >>> s.eval("20 + 30 - ( 10 * 5)")
@@ -223,62 +242,83 @@ class SimpleEval(object): # pylint: disable=too-few-public-methods
         self.expr = expr
 
         # and evaluate:
-        return self._eval(ast.parse(expr).body[0].value)
+        return self._eval(ast.parse(expr.strip()).body[0].value)
 
     # pylint: disable=too-many-return-statements, too-many-branches
     def _eval(self, node):
-        ''' The internal eval function used on each node in the parsed tree. '''
+        ''' The internal evaluator used on each node in the parsed tree. '''
 
         # literals:
 
-        if isinstance(node, ast.Num): # <number>
+        if isinstance(node, ast.Num):  # <number>
             return node.n
-        elif isinstance(node, ast.Str): # <string>
+        elif isinstance(node, ast.Str):  # <string>
             if len(node.s) > MAX_STRING_LENGTH:
                 raise StringTooLong("String Literal in statement is too long!"
                                     " ({0}, when {1} is max)".format(
-                                    len(node.s), MAX_STRING_LENGTH))
+                                        len(node.s), MAX_STRING_LENGTH))
             return node.s
 
         # python 3 compatibility:
 
         elif (hasattr(ast, 'NameConstant') and
-                isinstance(node, ast.NameConstant)): # <bool>
+              isinstance(node, ast.NameConstant)):  # <bool>
             return node.value
 
         # operators, functions, etc:
 
-        elif isinstance(node, ast.UnaryOp): # - and + etc.
+        elif isinstance(node, ast.UnaryOp):  # - and + etc.
             return self.operators[type(node.op)](self._eval(node.operand))
-        elif isinstance(node, ast.BinOp): # <left> <operator> <right>
+        elif isinstance(node, ast.BinOp):  # <left> <operator> <right>
             return self.operators[type(node.op)](self._eval(node.left),
-                                       self._eval(node.right))
-        elif isinstance(node, ast.BoolOp): # and & or...
+                                                 self._eval(node.right))
+        elif isinstance(node, ast.BoolOp):  # and & or...
             if isinstance(node.op, ast.And):
-                return all((self._eval(v) for v in node.values))
+                for value in node.values:
+                    vout = self._eval(value)
+                    if not vout:
+                        return False
+                return vout
             elif isinstance(node.op, ast.Or):
-                return any((self._eval(v) for v in node.values))
-        elif isinstance(node, ast.Compare): # 1 < 2, a == b...
-            return self.operators[type(node.ops[0])](self._eval(node.left),
-                                                     self._eval(node.comparators[0]))
-        elif isinstance(node, ast.IfExp): # x if y else z
+                for value in node.values:
+                    vout = self._eval(value)
+                    if vout:
+                        return vout
+                return False
+
+        elif isinstance(node, ast.Compare):  # 1 < 2, a == b...
+            left = self._eval(node.left)
+            for operation, comp in zip(node.ops, node.comparators):
+                right = self._eval(comp)
+                if self.operators[type(operation)](left, right):
+                    left = right  # Hi Dr. Seuss...
+                else:
+                    return False
+            return True
+
+        elif isinstance(node, ast.IfExp):  # x if y else z
             return self._eval(node.body) if self._eval(node.test) \
                                          else self._eval(node.orelse)
-        elif isinstance(node, ast.Call): # function...
+        elif isinstance(node, ast.Call):  # function...
             try:
-                return self.functions[node.func.id](*(self._eval(a)
-                                                      for a in node.args))
+                if isinstance(node.func, ast.Name):
+                    return self.functions[node.func.id](*(self._eval(a)
+                                                          for a in node.args))
+                elif isinstance(node.func, ast.Attribute):
+                    return self._eval(node.func)(*(self._eval(a)
+                                                   for a in node.args))
             except KeyError:
                 raise FunctionNotDefined(node.func.id, self.expr)
 
         # variables/names:
 
-        elif isinstance(node, ast.Name): # a, b, c...
+        elif isinstance(node, ast.Name):  # a, b, c...
             try:
-                #This happens at least for slicing
-                #This is a safe thing to do because it is impossible
-                #that there is a true exression assigning to none
-                #(the compiler rejects it, so you can't even pass that to ast.parse)
+                # This happens at least for slicing
+                # This is a safe thing to do because it is impossible
+                # that there is a true exression assigning to none
+                # (the compiler rejects it, so you can't even pass that
+                # to ast.parse)
                 if node.id == "None":
                     return None
                 elif isinstance(self.names, dict):
@@ -286,17 +326,25 @@ class SimpleEval(object): # pylint: disable=too-few-public-methods
                 elif callable(self.names):
                     return self.names(node)
                 else:
-                    raise InvalidExpression('Trying to use name (variable) "{0}"'
-                                            ' when no "names" defined for'
-                                            ' evaluator'.format(node.id))
+                    raise InvalidExpression(
+                        'Trying to use name (variable) "{0}"'
+                        ' when no "names" defined for'
+                        ' evaluator'.format(node.id))
 
             except KeyError:
                 raise NameNotDefined(node.id, self.expr)
 
-        elif isinstance(node, ast.Subscript): # b[1]
+        elif isinstance(node, ast.Subscript):  # b[1]
             return self._eval(node.value)[self._eval(node.slice)]
 
-        elif isinstance(node, ast.Attribute): # a.b.c
+        elif isinstance(node, ast.Attribute):  # a.b.c
+            for prefix in DISALLOW_PREFIXES:
+                if node.attr.startswith(prefix):
+                    raise FeatureNotAvailable(
+                        "Sorry, access to __attributes "
+                        " or func_ attributes is not available. "
+                        "({0})".format(node.attr))
+
             try:
                 return self._eval(node.value)[node.attr]
             except (KeyError, TypeError):
@@ -324,7 +372,8 @@ class SimpleEval(object): # pylint: disable=too-few-public-methods
             return slice(lower, upper, step)
         else:
             raise FeatureNotAvailable("Sorry, {0} is not available in this "
-                                      "evaluator".format(type(node).__name__ ))
+                                      "evaluator".format(type(node).__name__))
+
 
 def simple_eval(expr, operators=None, functions=None, names=None):
     ''' Simply evaluate an expresssion '''
diff --git a/test_simpleeval.py b/test_simpleeval.py
index ec1689a..2fe6d30 100644
--- a/test_simpleeval.py
+++ b/test_simpleeval.py
@@ -40,10 +40,16 @@ class TestBasic(DRYTest):
     def test_bools_and_or(self):
         self.t('True and False', False)
         self.t('True or False', True)
-        self.t('1 - 1 or 21', True)
-        self.t('1 - 1 and 11', False)
+        self.t('1 - 1 or 21', 21)
+        self.t('1 - 1 and 11', 0)
         self.t('110 == 100 + 10 and True', True)
         self.t('110 != 100 + 10 and True', False)
+        self.t('False or 42', 42)
+
+        self.s.names = {'out': True, 'position': 3}
+        self.t('(out and position <=6 and -10)'
+                ' or (out and position > 6 and -5)'
+                ' or (not out and 15)', -10)
 
     def test_maths_with_floats(self):
         self.t("11.02 - 9.1", 1.92)
@@ -63,6 +69,13 @@ class TestBasic(DRYTest):
         self.t("1 >= 12", False)
         self.t("1.09 <= 1967392", True)
 
+        self.t('1 < 2 < 3 < 4', 1 < 2 < 3 < 4)
+        self.t('1 < 2 > 3 < 4', 1 < 2  > 3 < 4)
+
+        self.t('1<2<1+1', 1<2<1+1)
+        self.t('1 == 1 == 2', 1 == 1 == 2)
+        self.t('1 == 1 < 2', 1 == 1 < 2)
+
     def test_mixed_comparisons(self):
         self.t("1 > 0.999999", True)
         self.t("1 == True", True)  # Note ==, not 'is'.
@@ -226,6 +239,48 @@ class TestTryingToBreakOut(DRYTest):
         with self.assertRaises(simpleeval.FeatureNotAvailable):
             self.t("[x for x in (1, 2, 3)]", (1, 2, 3))
 
+
+    def test_function_globals_breakout(self):
+        ''' by accessing function.__globals__ or func_... '''
+        # thanks perkinslr.
+
+        self.s.functions['x'] = lambda y:y+y
+        self.t('x(100)', 200)
+
+        with self.assertRaises(simpleeval.FeatureNotAvailable):
+            self.t('x.__globals__', None)
+
+        class EscapeArtist(object):
+            def trapdoor(self):
+                return 42
+
+            def _quasi_private(self):
+                return 84
+
+        self.s.names['houdini'] = EscapeArtist()
+
+        with self.assertRaises(simpleeval.FeatureNotAvailable):
+            self.t('houdini.trapdoor.__globals__', 0)
+
+        with self.assertRaises(simpleeval.FeatureNotAvailable):
+            self.t('houdini.trapdoor.func_globals', 0)
+
+        with self.assertRaises(simpleeval.FeatureNotAvailable):
+            self.t('houdini._quasi_private()', 0)
+
+        # and test for changing '_' to '__':
+
+        dis = simpleeval.DISALLOW_PREFIXES
+        simpleeval.DISALLOW_PREFIXES = ['func_']
+
+        self.t('houdini._quasi_private()', 84)
+
+        # and return things to normal
+
+        simpleeval.DISALLOW_PREFIXES = dis
+
+
+
 class TestNames(DRYTest):
     ''' 'names', what other languages call variables... '''
 
@@ -316,9 +371,11 @@ class TestNames(DRYTest):
             self.assertEqual(self.s.names['a']['d'], 11)
 
     def test_object(self):
-        ''' using an object for name lookp '''
+        ''' using an object for name lookup '''
         class TestObject(object):
-            pass
+           def method_thing(self):
+                return 42
+
         o = TestObject()
         o.a = 23
         o.b = 42
@@ -330,6 +387,9 @@ class TestNames(DRYTest):
         self.t('o', o)
         self.t('o.a', 23)
         self.t('o.b + o.c.d', 9043)
+
+        self.t('o.method_thing()', 42)
+
         with self.assertRaises(AttributeDoesNotExist):
             self.t('o.d', None)
 
@@ -367,6 +427,29 @@ class TestNames(DRYTest):
         self.t('a', 1)
         self.t('a + b', 3)
 
+
+class Test_whitespace(DRYTest):
+    ''' test that incorrect whitespace (preceding/trailing) doesn't matter. '''
+    def test_no_whitespace(self):
+        self.t('200 + 200', 400)
+
+    def test_trailing(self):
+        self.t('200 + 200       ', 400)
+
+    def test_preciding_whitespace(self):
+        self.t('    200 + 200', 400)
+
+    def test_preceding_tab_whitespace(self):
+        self.t("\t200 + 200", 400)
+
+    def test_preceding_mixed_whitespace(self):
+        self.t("  \t 200 + 200", 400)
+
+    def test_both_ends_whitespace(self):
+        self.t("  \t 200 + 200  ", 400)
+
+
+
 class Test_simple_eval(unittest.TestCase):
     ''' test the 'simple_eval' wrapper function '''
     def test_basic_run(self):
-- 
simpleeval



More information about the tryton-debian-vcs mailing list