[tryton-debian-vcs] simpleeval branch debian updated. debian/0.9.3-1-6-g3bf8981

Mathias Behrle tryton-debian-vcs at alioth.debian.org
Wed Sep 6 09:58:13 UTC 2017


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

commit 3bf8981c71862e4e3b7f39ab1246cac26079e9c2
Author: Mathias Behrle <mathiasb at m9s.biz>
Date:   Wed Sep 6 11:27:58 2017 +0200

    Releasing debian version 0.9.5-1.
    
    Signed-off-by: Mathias Behrle <mathiasb at m9s.biz>

diff --git a/debian/changelog b/debian/changelog
index ccd99f1..5ebe96a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,14 @@
+simpleeval (0.9.5-1) unstable; urgency=medium
+
+  * Change the maintainer address to tryton-debian at lists.alioth.debian.org
+    (Closes: #865109).
+  * Use the preferred https URL format in the copyright file.
+  * Bump the Standards-Version to 4.0.1.
+  * Bump the Standards-Version to 4.1.0, no changes needed.
+  * Merging upstream version 0.9.5.
+
+ -- Mathias Behrle <mathiasb at m9s.biz>  Mon, 04 Sep 2017 16:23:10 +0200
+
 simpleeval (0.9.3-1) unstable; urgency=medium
 
   * Merging upstream version 0.9.3.
commit 28afdac4af8a7690a855b28a3e78678fc7f40186
Author: Mathias Behrle <mathiasb at m9s.biz>
Date:   Mon Sep 4 16:23:09 2017 +0200

    Merging upstream version 0.9.5.

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..ef70fef
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+*.pyc
+build
+dist
+MANIFEST
+.idea
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..2ce315b
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,20 @@
+language: python
+python:
+    - "2.7"
+    - "3.2"
+    - "3.3"
+    - "3.4"
+    - "3.5"
+    - "3.6"
+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..a71b854
--- /dev/null
+++ b/LICENCE
@@ -0,0 +1,21 @@
+simpleeval - Copyright (c) 2013-2017 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 9933cb5..0000000
--- a/PKG-INFO
+++ /dev/null
@@ -1,323 +0,0 @@
-Metadata-Version: 1.1
-Name: simpleeval
-Version: 0.9.3
-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.9.3
-Description: simpleeval (Simple Eval)
-        ========================
-        
-        .. 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, pull it in from PyPI (pip or easy_install), or
-        even just a single file you can dump into a project.
-        
-        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:
-        
-        .. code-block:: python
-        
-            from simpleeval import simple_eval
-        
-            simple_eval("21 + 21")
-        
-        returns ``42``.
-        
-        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.
-        
-        .. code-block:: python
-        
-            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:
-        
-        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``            |
-        +--------+------------------------------------+
-        | ``in`` | is something contained within      |
-        |        | something else.                    |
-        |        | ``"spam" in "my breakfast"``       |
-        |        | -> ``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):
-        
-        .. code-block:: python
-        
-            >>> 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:
-        
-        .. 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:
-        
-        .. code-block:: python
-        
-            >>> 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:
-        
-        .. 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
-        
-        .. code-block:: python
-        
-            >>> 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'.
-        
-        .. 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:
-        
-        
-        .. code-block:: python
-        
-            >>> 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):
-        
-        .. code-block:: python
-        
-            >>> s = SimpleEval()
-        
-            >>> s.eval("1 + 1")
-            2
-        
-            >>> s.eval('100 * 10')
-            1000
-            
-            # 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)
-        
-        .. code-block:: python
-        
-            def boo():
-                return 'Boo!'
-        
-            s = SimpleEval(functions={"boo": boo})
-        
-        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:
-        
-        .. code-block:: python
-        
-            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.
-        
-        Compound Types
-        --------------
-        
-        Compound types (``dict``, ``tuple``, ``list``, ``set``) in general just work if
-        you pass them in as named objects.  If you want to allow creation of these, the
-        ``EvalWithCompoundTypes`` class works.  Just replace any use of ``SimpleEval`` with
-        that.
-        
-        Other...
-        --------
-        
-        The library supports both python 2 and 3.
-        
-        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``.
-        
-        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!
-        
-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 d5f3179..f118bc0 100644
--- a/README.rst
+++ b/README.rst
@@ -159,12 +159,15 @@ 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
+Strings (and other Iterables) Safety
 ~~~~~~~~~~~~~
 
 There are also limits on string length (100000 characters,
 ``MAX_STRING_LENGTH``).  This can be changed if you wish.
 
+Related to this, if you try to create a silly long string/bytes/list, by doing
+``'i want to break free'.split() * 9999999999`` for instance, it will block you.
+
 If Expressions
 --------------
 
@@ -204,6 +207,33 @@ and even re-name them so that expressions can be shorter
     >>> simple_eval("d(100) + double(1)", functions={"d": double, "double":double})
     202
 
+If you don't provide your own ``functions`` dict, then the the following defaults
+are provided in the ``DEFAULT_FUNCTIONS`` dict:
+
++----------------+--------------------------------------------------+
+| ``randint(x)`` | Return a random ``int`` below ``x``              |
++----------------+--------------------------------------------------+
+| ``rand()``     | Return a random ``float`` between 0 and 1        |
++----------------+--------------------------------------------------+
+| ``int(x)``     | Convert ``x`` to an ``int``.                     |
++----------------+--------------------------------------------------+
+| ``float(x)``   | Convert ``x`` to a ``float``.                    |
++----------------+--------------------------------------------------+
+| ``str(x)``     | Convert ``x`` to a ``str`` (``unicode`` in py2)  |
++----------------+--------------------------------------------------+
+
+If you want to provide a list of functions, but want to keep these as well,
+then you can do a normal python ``.copy()`` & ``.update``:
+
+.. code-block:: python
+
+    >>> my_functions = simpleeval.DEFAULT_FUNCTIONS.copy()
+    >>> my_functions.update(
+            square=(lambda x:x*x),
+            double=(lambda x:x+x),
+        )
+    >>> simple_eval('square(randint(100))', functions=my_functions)
+
 Names
 -----
 
@@ -229,6 +259,8 @@ You can also hand the handling of names over to a function, if you prefer:
 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.
 
+The two default names that are provided are ``True`` and ``False``.  So if you want to provide your own names, but want ``True`` and ``False`` to keep working, either provide them yourself, or ``.copy()`` and ``.update`` the ``DEFAULT_NAMES``. (See functions example above).
+
 Creating an Evaluator Class
 ---------------------------
 
@@ -292,6 +324,25 @@ you pass them in as named objects.  If you want to allow creation of these, the
 ``EvalWithCompoundTypes`` class works.  Just replace any use of ``SimpleEval`` with
 that.
 
+Extending
+---------
+
+The ``SimpleEval`` class is pretty easy to extend.  For instance, to create a
+version that disallows method invocation on objects:
+
+.. code-block:: python
+
+    import ast
+    import simpleeval
+
+    class EvalNoMethods(simpleeval.SimpleEval):
+        def _eval_call(self, node):
+            if isinstance(node.func, ast.Attribute):
+                raise simpleeval.FeatureNotAvailable("No methods please, we're British")
+            return super(EvalNoMethods, self)._eval_call(node)
+
+and then use ``EvalNoMethods`` instead of the ``SimpleEval`` class.
+
 Other...
 --------
 
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 76afb03..860c0fc 100644
--- a/setup.py
+++ b/setup.py
@@ -1,5 +1,5 @@
 from setuptools import setup
-__version__ = '0.9.3'
+__version__ = '0.9.5'
 
 setup(
     name='simpleeval',
diff --git a/simpleeval.egg-info/PKG-INFO b/simpleeval.egg-info/PKG-INFO
deleted file mode 100644
index 9933cb5..0000000
--- a/simpleeval.egg-info/PKG-INFO
+++ /dev/null
@@ -1,323 +0,0 @@
-Metadata-Version: 1.1
-Name: simpleeval
-Version: 0.9.3
-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.9.3
-Description: simpleeval (Simple Eval)
-        ========================
-        
-        .. 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, pull it in from PyPI (pip or easy_install), or
-        even just a single file you can dump into a project.
-        
-        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:
-        
-        .. code-block:: python
-        
-            from simpleeval import simple_eval
-        
-            simple_eval("21 + 21")
-        
-        returns ``42``.
-        
-        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.
-        
-        .. code-block:: python
-        
-            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:
-        
-        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``            |
-        +--------+------------------------------------+
-        | ``in`` | is something contained within      |
-        |        | something else.                    |
-        |        | ``"spam" in "my breakfast"``       |
-        |        | -> ``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):
-        
-        .. code-block:: python
-        
-            >>> 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:
-        
-        .. 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:
-        
-        .. code-block:: python
-        
-            >>> 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:
-        
-        .. 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
-        
-        .. code-block:: python
-        
-            >>> 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'.
-        
-        .. 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:
-        
-        
-        .. code-block:: python
-        
-            >>> 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):
-        
-        .. code-block:: python
-        
-            >>> s = SimpleEval()
-        
-            >>> s.eval("1 + 1")
-            2
-        
-            >>> s.eval('100 * 10')
-            1000
-            
-            # 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)
-        
-        .. code-block:: python
-        
-            def boo():
-                return 'Boo!'
-        
-            s = SimpleEval(functions={"boo": boo})
-        
-        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:
-        
-        .. code-block:: python
-        
-            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.
-        
-        Compound Types
-        --------------
-        
-        Compound types (``dict``, ``tuple``, ``list``, ``set``) in general just work if
-        you pass them in as named objects.  If you want to allow creation of these, the
-        ``EvalWithCompoundTypes`` class works.  Just replace any use of ``SimpleEval`` with
-        that.
-        
-        Other...
-        --------
-        
-        The library supports both python 2 and 3.
-        
-        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``.
-        
-        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!
-        
-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 fc9dc91..79885de 100644
--- a/simpleeval.py
+++ b/simpleeval.py
@@ -1,4 +1,4 @@
-'''
+"""
 SimpleEval - (C) 2013-2017 Daniel Fairhead
 -------------------------------------
 
@@ -42,6 +42,7 @@ Contributors:
 - perkinslr (Logan Perkins) (.__globals__ or .func_ breakouts)
 - impala2 (Kirill Stepanov) (massive _eval refactor)
 - gk (ugik) (Other iterables than str can DOS too, and can be made)
+- daveisfera (Dave Johansen) 'not' Boolean op, Pycharm and pep8 fixes.
 
 -------------------------------------
 Usage:
@@ -79,7 +80,7 @@ well:
 >>> simple_eval("40 + two", names={"two": 2})
 42
 
-'''
+"""
 
 import ast
 import sys
@@ -100,12 +101,12 @@ PYTHON3 = sys.version_info[0] == 3
 
 
 class InvalidExpression(Exception):
-    ''' Generic Exception '''
+    """ Generic Exception """
     pass
 
 
 class FunctionNotDefined(InvalidExpression):
-    ''' sorry! That function isn't defined! '''
+    """ 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)
@@ -117,7 +118,7 @@ class FunctionNotDefined(InvalidExpression):
 
 
 class NameNotDefined(InvalidExpression):
-    ''' a name isn't defined. '''
+    """ a name isn't defined. """
     def __init__(self, name, expression):
         self.name = name
         self.message = "'{0}' is not defined for expression '{1}'".format(
@@ -129,7 +130,7 @@ class NameNotDefined(InvalidExpression):
 
 
 class AttributeDoesNotExist(InvalidExpression):
-    '''attribute does not exist'''
+    """attribute does not exist"""
     def __init__(self, attr, expression):
         self.message = \
             "Attribute '{0}' does not exist in expression '{1}'".format(
@@ -139,18 +140,18 @@ class AttributeDoesNotExist(InvalidExpression):
 
 
 class FeatureNotAvailable(InvalidExpression):
-    ''' What you're trying to do is not allowed. '''
+    """ 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! '''
+    """ Sorry! That number is too high. I don't want to spend the
+        next 10 years evaluating this expression! """
     pass
 
 
 class IterableTooLong(InvalidExpression):
-    ''' That iterable is **way** too long, baby. '''
+    """ That iterable is **way** too long, baby. """
     pass
 
 
@@ -159,12 +160,12 @@ class IterableTooLong(InvalidExpression):
 
 
 def random_int(top):
-    ''' return a random int below <top> '''
+    """ return a random int below <top> """
     return int(random() * top)
 
 
 def safe_power(a, b):  # pylint: disable=invalid-name
-    ''' a limited exponent/to-the-power-of function, for safety reasons '''
+    """ 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))
@@ -172,7 +173,7 @@ def safe_power(a, b):  # pylint: disable=invalid-name
 
 
 def safe_mult(a, b):  # pylint: disable=invalid-name
-    ''' limit the number of times an iterable can be repeated... '''
+    """ limit the number of times an iterable can be repeated... """
 
     if hasattr(a, '__len__') and b*len(a) > MAX_STRING_LENGTH:
         raise IterableTooLong('Sorry, I will not evalute something that long.')
@@ -183,7 +184,7 @@ def safe_mult(a, b):  # pylint: disable=invalid-name
 
 
 def safe_add(a, b):  # pylint: disable=invalid-name
-    ''' iterable length limit again '''
+    """ iterable length limit again """
     if hasattr(a, '__len__') and hasattr(b, '__len__'):
         if len(a) + len(b) > MAX_STRING_LENGTH:
             raise IterableTooLong("Sorry, adding those two together would"
@@ -200,6 +201,7 @@ DEFAULT_OPERATORS = {ast.Add: safe_add, ast.Sub: op.sub, ast.Mult: safe_mult,
                      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.Not: op.not_,
                      ast.USub: op.neg, ast.UAdd: op.pos,
                      ast.In: lambda x, y: op.contains(y, x),
                      ast.NotIn: lambda x, y: not op.contains(y, x),
@@ -216,17 +218,17 @@ DEFAULT_NAMES = {"True": True, "False": False}
 
 
 class SimpleEval(object):  # pylint: disable=too-few-public-methods
-    ''' A very simple expression parser.
+    """ A very simple expression parser.
         >>> s = SimpleEval()
         >>> s.eval("20 + 30 - ( 10 * 5)")
         0
-        '''
+        """
     expr = ""
 
     def __init__(self, operators=None, functions=None, names=None):
-        '''
+        """
             Create the evaluator instance.  Set up valid operators (+,-, etc)
-            functions (add, random, get_val, whatever) and names. '''
+            functions (add, random, get_val, whatever) and names. """
 
         if not operators:
             operators = DEFAULT_OPERATORS
@@ -250,7 +252,6 @@ class SimpleEval(object):  # pylint: disable=too-few-public-methods
             ast.IfExp: self._eval_ifexp,
             ast.Call: self._eval_call,
             ast.keyword: self._eval_keyword,
-            ast.Name: self._eval_name,
             ast.Subscript: self._eval_subscript,
             ast.Attribute: self._eval_attribute,
             ast.Index: self._eval_index,
@@ -262,8 +263,8 @@ class SimpleEval(object):  # pylint: disable=too-few-public-methods
             self.nodes[ast.NameConstant] = self._eval_nameconstant
 
     def eval(self, expr):
-        ''' evaluate an expresssion, using the operators, functions and
-            names previously set up. '''
+        """ evaluate an expresssion, using the operators, functions and
+            names previously set up. """
 
         # set a copy of the expression aside, so we can give nice errors...
 
@@ -273,7 +274,7 @@ class SimpleEval(object):  # pylint: disable=too-few-public-methods
         return self._eval(ast.parse(expr.strip()).body[0].value)
 
     def _eval(self, node):
-        ''' The internal evaluator used on each node in the parsed tree. '''
+        """ The internal evaluator used on each node in the parsed tree. """
 
         try:
             handler = self.nodes[type(node)]
@@ -283,17 +284,20 @@ class SimpleEval(object):  # pylint: disable=too-few-public-methods
 
         return handler(node)
 
-    def _eval_num(self, node):
+    @staticmethod
+    def _eval_num(node):
         return node.n
 
-    def _eval_str(self, node):
+    @staticmethod
+    def _eval_str(node):
         if len(node.s) > MAX_STRING_LENGTH:
             raise IterableTooLong("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
 
-    def _eval_nameconstant(self, node):
+    @staticmethod
+    def _eval_nameconstant(node):
         return node.value
 
     def _eval_unaryop(self, node):
@@ -305,6 +309,7 @@ class SimpleEval(object):  # pylint: disable=too-few-public-methods
 
     def _eval_boolop(self, node):
         if isinstance(node.op, ast.And):
+            vout = False
             for value in node.values:
                 vout = self._eval(value)
                 if not vout:
@@ -367,6 +372,9 @@ class SimpleEval(object):  # pylint: disable=too-few-public-methods
                                         ' evaluator'.format(node.id))
 
         except KeyError:
+            if node.id in self.functions:
+                return self.functions[node.id]
+
             raise NameNotDefined(node.id, self.expr)
 
     def _eval_subscript(self, node):
@@ -378,8 +386,6 @@ class SimpleEval(object):  # pylint: disable=too-few-public-methods
         except KeyError:
             raise
 
-        return self._eval(node.value)[self._eval(node.slice)]
-
     def _eval_attribute(self, node):
         for prefix in DISALLOW_PREFIXES:
             if node.attr.startswith(prefix):
@@ -417,13 +423,13 @@ class SimpleEval(object):  # pylint: disable=too-few-public-methods
 
 
 class EvalWithCompoundTypes(SimpleEval):
-    '''
+    """
         SimpleEval with additional Compound Types, and their respective
         function editions. (list, tuple, dict, set).
-    '''
+    """
 
-    def __init__(self, *args, **kwargs):
-        super(EvalWithCompoundTypes, self).__init__(*args, **kwargs)
+    def __init__(self, operators=None, functions=None, names=None):
+        super(EvalWithCompoundTypes, self).__init__(operators, functions, names)
 
         self.functions.update(
             list=list,
@@ -453,7 +459,7 @@ class EvalWithCompoundTypes(SimpleEval):
 
 
 def simple_eval(expr, operators=None, functions=None, names=None):
-    ''' Simply evaluate an expresssion '''
+    """ Simply evaluate an expresssion """
     s = SimpleEval(operators=operators,
                    functions=functions,
                    names=names)
diff --git a/test_simpleeval.py b/test_simpleeval.py
index ca07b6b..66eff7e 100644
--- a/test_simpleeval.py
+++ b/test_simpleeval.py
@@ -1,10 +1,10 @@
-'''
+"""
     Unit tests for simpleeval.
     --------------------------
 
     Most of this stuff is pretty basic.
 
-'''
+"""
 # pylint: disable=too-many-public-methods, missing-docstring
 
 import unittest
@@ -12,29 +12,29 @@ import operator
 import ast
 import simpleeval
 from simpleeval import (
-    SimpleEval, EvalWithCompoundTypes, NameNotDefined,
+    SimpleEval, EvalWithCompoundTypes, FeatureNotAvailable, FunctionNotDefined, NameNotDefined,
     InvalidExpression, AttributeDoesNotExist, simple_eval
 )
 
 
 class DRYTest(unittest.TestCase):
-    ''' Stuff we need to do every test, let's do here instead..
-        Don't Repeat Yourself. '''
+    """ Stuff we need to do every test, let's do here instead..
+        Don't Repeat Yourself. """
 
     def setUp(self):
-        ''' initialize a SimpleEval '''
+        """ initialize a SimpleEval """
         self.s = SimpleEval()
 
-    def t(self, expr, shouldbe): # pylint: disable=invalid-name
-        ''' test an evaluation of an expression against an expected answer '''
+    def t(self, expr, shouldbe):  # pylint: disable=invalid-name
+        """ test an evaluation of an expression against an expected answer """
         return self.assertEqual(self.s.eval(expr), shouldbe)
 
 
 class TestBasic(DRYTest):
-    ''' Simple expressions. '''
+    """ Simple expressions. """
 
     def test_maths_with_ints(self):
-        ''' simple maths expressions '''
+        """ simple maths expressions """
 
         self.t("21 + 21", 42)
         self.t("6*7", 42)
@@ -58,6 +58,12 @@ class TestBasic(DRYTest):
                ' or (out and position > 6 and -5)'
                ' or (not out and 15)', -10)
 
+    def test_not(self):
+        self.t('not False', True)
+        self.t('not True', False)
+        self.t('not 0', True)
+        self.t('not 1', False)
+
     def test_maths_with_floats(self):
         self.t("11.02 - 9.1", 1.92)
         self.t("29.1+39", 68.1)
@@ -91,7 +97,7 @@ class TestBasic(DRYTest):
         self.t("False < True", True)
 
     def test_if_else(self):
-        ''' x if y else z '''
+        """ x if y else z """
 
         # and test if/else expressions:
         self.t("'a' if 1 == 1 else 'b'", 'a')
@@ -101,15 +107,15 @@ class TestBasic(DRYTest):
         self.t("'a' if 4 < 1 else 'b' if 1 == 2 else 'c'", 'c')
 
     def test_default_conversions(self):
-        ''' conversion between types '''
+        """ conversion between types """
 
         self.t('int("20") + int(0.22*100)', 42)
         self.t('float("42")', 42.0)
         self.t('"Test Stuff!" + str(11)', "Test Stuff!11")
 
     def test_slicing(self):
-        self.s.operators[ast.Slice] = (operator.getslice \
-            if hasattr(operator, "getslice") else operator.getitem)
+        self.s.operators[ast.Slice] = (operator.getslice
+                                       if hasattr(operator, "getslice") else operator.getitem)
         self.t("'hello'[1]", "e")
         self.t("'hello'[:]", "hello")
         self.t("'hello'[:3]", "hel")
@@ -135,10 +141,10 @@ class TestBasic(DRYTest):
 
 
 class TestFunctions(DRYTest):
-    ''' Functions for expressions to play with '''
+    """ Functions for expressions to play with """
 
     def test_load_file(self):
-        ''' add in a function which loads data from an external file. '''
+        """ add in a function which loads data from an external file. """
 
         # write to the file:
 
@@ -148,9 +154,9 @@ class TestFunctions(DRYTest):
         # define the function we'll send to the eval'er
 
         def load_file(filename):
-            ''' load a file and return its contents '''
-            with open(filename) as f:
-                return f.read()
+            """ load a file and return its contents """
+            with open(filename) as f2:
+                return f2.read()
 
         # simple load:
 
@@ -171,7 +177,7 @@ class TestFunctions(DRYTest):
         self.t("int(read('file.txt'))", 42)
 
     def test_randoms(self):
-        ''' test the rand() and randint() functions '''
+        """ test the rand() and randint() functions """
 
         self.s.functions['type'] = type
 
@@ -234,24 +240,24 @@ class TestFunctions(DRYTest):
 
 
 class TestOperators(DRYTest):
-    ''' Test adding in new operators, removing them, make sure it works. '''
+    """ Test adding in new operators, removing them, make sure it works. """
     pass
 
 
 class TestTryingToBreakOut(DRYTest):
-    ''' Test various weird methods to break the security sandbox... '''
+    """ Test various weird methods to break the security sandbox... """
 
     def test_import(self):
-        ''' usual suspect. import '''
+        """ usual suspect. import """
         # cannot import things:
         with self.assertRaises(AttributeError):
             self.t("import sys", None)
 
     def test_long_running(self):
-        ''' exponent operations can take a long time. '''
+        """ exponent operations can take a long time. """
         old_max = simpleeval.MAX_POWER
 
-        self.t("9**9**5", 9**9**5)
+        self.t("9**9**5", 9 ** 9 ** 5)
 
         with self.assertRaises(simpleeval.NumberTooHigh):
             self.t("9**9**8", 0)
@@ -274,7 +280,6 @@ class TestTryingToBreakOut(DRYTest):
                 self.t('(1).from_bytes(("123123123123123123123123").encode()*999999, "big")', 0)
 
     def test_string_length(self):
-
         with self.assertRaises(simpleeval.IterableTooLong):
             self.t("50000*'text'", 0)
 
@@ -298,14 +303,14 @@ class TestTryingToBreakOut(DRYTest):
             self.t("'stuff'*100000", 100000 * 'stuff')
 
         with self.assertRaises(simpleeval.IterableTooLong):
-            self.t("'" + (10000 * "stuff") +"'*100", 0)
+            self.t("'" + (10000 * "stuff") + "'*100", 0)
 
         with self.assertRaises(simpleeval.IterableTooLong):
             self.t("'" + (50000 * "stuff") + "'", 0)
 
     def test_bytes_array_test(self):
         self.t("'20000000000000000000'.encode() * 5000",
-                '20000000000000000000'.encode() * 5000)
+               '20000000000000000000'.encode() * 5000)
 
         with self.assertRaises(simpleeval.IterableTooLong):
             self.t("'123121323123131231223'.encode() * 5000", 20)
@@ -317,7 +322,7 @@ class TestTryingToBreakOut(DRYTest):
             self.t("('spam spam spam' * 5000).split() * 5000", None)
 
     def test_python_stuff(self):
-        ''' other various pythony things. '''
+        """ other various pythony things. """
         # it only evaluates the first statement:
         self.t("a = 11; x = 21; x + x", 11)
 
@@ -327,7 +332,7 @@ class TestTryingToBreakOut(DRYTest):
             self.t("[x for x in (1, 2, 3)]", (1, 2, 3))
 
     def test_function_globals_breakout(self):
-        ''' by accessing function.__globals__ or func_... '''
+        """ by accessing function.__globals__ or func_... """
         # thanks perkinslr.
 
         self.s.functions['x'] = lambda y: y + y
@@ -337,10 +342,12 @@ class TestTryingToBreakOut(DRYTest):
             self.t('x.__globals__', None)
 
         class EscapeArtist(object):
-            def trapdoor(self):
+            @staticmethod
+            def trapdoor():
                 return 42
 
-            def _quasi_private(self):
+            @staticmethod
+            def _quasi_private():
                 return 84
 
         self.s.names['houdini'] = EscapeArtist()
@@ -372,7 +379,7 @@ class TestTryingToBreakOut(DRYTest):
 
 
 class TestCompoundTypes(DRYTest):
-    ''' Test the compound-types edition of the library '''
+    """ Test the compound-types edition of the library """
 
     def setUp(self):
         self.s = EvalWithCompoundTypes()
@@ -431,12 +438,33 @@ class TestCompoundTypes(DRYTest):
         self.t('2 in {1,2,3,4}', True)
         self.t('22 not in {1,2,3,4}', True)
 
+    def test_not(self):
+        self.t('not []', True)
+        self.t('not [0]', False)
+        self.t('not {}', True)
+        self.t('not {0: 1}', False)
+        self.t('not {0}', False)
+
+    def test_use_func(self):
+        self.s = EvalWithCompoundTypes(functions={"map": map, "str": str})
+        self.t('list(map(str, [-1, 0, 1]))', ['-1', '0', '1'])
+        with self.assertRaises(NameNotDefined):
+            self.s.eval('list(map(bad, [-1, 0, 1]))')
+
+        with self.assertRaises(FunctionNotDefined):
+            self.s.eval('dir(str)')
+        with self.assertRaises(FeatureNotAvailable):
+            self.s.eval('str.__dict__')
+
+        self.s = EvalWithCompoundTypes(functions={"dir": dir, "str": str})
+        self.t('dir(str)', dir(str))
+
 
 class TestNames(DRYTest):
-    ''' 'names', what other languages call variables... '''
+    """ 'names', what other languages call variables... """
 
     def test_none(self):
-        ''' what to do when names isn't defined, or is 'none' '''
+        """ what to do when names isn't defined, or is 'none' """
         with self.assertRaises(NameNotDefined):
             self.t("a == 2", None)
 
@@ -456,7 +484,7 @@ class TestNames(DRYTest):
             self.t('a.b.d**2', 42)
 
     def test_dict(self):
-        ''' using a normal dict for names lookup '''
+        """ using a normal dict for names lookup """
 
         self.s.names = {'a': 42}
         self.t("a + a", 84)
@@ -521,9 +549,11 @@ class TestNames(DRYTest):
             self.assertEqual(self.s.names['a']['d'], 11)
 
     def test_object(self):
-        ''' using an object for name lookup '''
+        """ using an object for name lookup """
+
         class TestObject(object):
-           def method_thing(self):
+            @staticmethod
+            def method_thing():
                 return 42
 
         o = TestObject()
@@ -544,10 +574,10 @@ class TestNames(DRYTest):
             self.t('o.d', None)
 
     def test_func(self):
-        ''' using a function for 'names lookup' '''
+        """ using a function for 'names lookup' """
 
-        def resolver(node):  # pylint: disable=unused-argument
-            ''' all names now equal 1024! '''
+        def resolver(_):
+            """ all names now equal 1024! """
             return 1024
 
         self.s.names = resolver
@@ -558,7 +588,7 @@ class TestNames(DRYTest):
         # the function can do stuff with the value it's sent:
 
         def my_name(node):
-            ''' all names equal their textual name, twice. '''
+            """ all names equal their textual name, twice. """
             return node.id + node.id
 
         self.s.names = my_name
@@ -566,20 +596,21 @@ class TestNames(DRYTest):
         self.t("a", "aa")
 
     def test_from_doc(self):
-        ''' the 'name first letter as value' example from the docs '''
+        """ the 'name first letter as value' example from the docs """
 
         def name_handler(node):
-            ''' return the alphabet number of the first letter of
-                the name's textual name '''
-            return ord(node.id[0].lower())-96
+            """ return the alphabet number of the first letter of
+                the name's textual name """
+            return ord(node.id[0].lower()) - 96
 
         self.s.names = name_handler
         self.t('a', 1)
         self.t('a + b', 3)
 
 
-class Test_whitespace(DRYTest):
-    ''' test that incorrect whitespace (preceding/trailing) doesn't matter. '''
+class TestWhitespace(DRYTest):
+    """ test that incorrect whitespace (preceding/trailing) doesn't matter. """
+
     def test_no_whitespace(self):
         self.t('200 + 200', 400)
 
@@ -599,8 +630,9 @@ class Test_whitespace(DRYTest):
         self.t("  \t 200 + 200  ", 400)
 
 
-class Test_simple_eval(unittest.TestCase):
-    ''' test the 'simple_eval' wrapper function '''
+class TestSimpleEval(unittest.TestCase):
+    """ test the 'simple_eval' wrapper function """
+
     def test_basic_run(self):
         self.assertEqual(simple_eval('6*7'), 42)
 
@@ -609,5 +641,28 @@ class Test_simple_eval(unittest.TestCase):
         self.assertEqual(simple_eval('randint(200) < 200 and rand() > 0'), True)
 
 
+class TestExtendingClass(unittest.TestCase):
+    """
+        It should be pretty easy to extend / inherit from the SimpleEval class,
+        to further lock things down, or unlock stuff, or whatever.
+    """
+
+    def test_methods_forbidden(self):
+        # Example from README
+        class EvalNoMethods(simpleeval.SimpleEval):
+            def _eval_call(self, node):
+                if isinstance(node.func, ast.Attribute):
+                    raise simpleeval.FeatureNotAvailable("No methods please, we're British")
+                return super(EvalNoMethods, self)._eval_call(node)
+
+        e = EvalNoMethods()
+
+        self.assertEqual(e.eval('"stuff happens"'), "stuff happens")
+        self.assertEqual(e.eval('22 + 20'), 42)
+
+        with self.assertRaises(simpleeval.FeatureNotAvailable):
+            e.eval('"  blah  ".strip()')
+
+
 if __name__ == '__main__':
     unittest.main()
commit cb0c53570c0f84ef748b630bad1459ace291f6a9
Author: Mathias Behrle <mathiasb at m9s.biz>
Date:   Mon Sep 4 16:20:07 2017 +0200

    Bump the Standards-Version to 4.1.0, no changes needed.

diff --git a/debian/control b/debian/control
index 2c9993d..7d897cf 100644
--- a/debian/control
+++ b/debian/control
@@ -10,7 +10,7 @@ Build-Depends:
  python-setuptools,
  python3,
  python3-setuptools,
-Standards-Version: 4.0.1
+Standards-Version: 4.1.0
 Homepage: https://github.com/danthedeckie/simpleeval
 Vcs-Browser: https://anonscm.debian.org/cgit/tryton/simpleeval.git
 Vcs-Git: https://anonscm.debian.org/cgit/tryton/simpleeval.git
-- 
simpleeval



More information about the tryton-debian-vcs mailing list