simpleeval 1.0.2__tar.gz → 1.0.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- simpleeval-1.0.4/.v2/lib/python3.13/site-packages/docutils/parsers/rst/include/README.rst +17 -0
- simpleeval-1.0.4/.v2/lib/python3.13/site-packages/docutils/writers/s5_html/themes/README.rst +6 -0
- simpleeval-1.0.4/.v2/lib/python3.13/site-packages/pip/_vendor/README.rst +180 -0
- {simpleeval-1.0.2 → simpleeval-1.0.4/.v314/lib/python3.14/site-packages}/simpleeval.py +8 -8
- simpleeval-1.0.4/LICENCE +21 -0
- {simpleeval-1.0.2 → simpleeval-1.0.4}/PKG-INFO +56 -8
- {simpleeval-1.0.2 → simpleeval-1.0.4}/README.rst +54 -6
- {simpleeval-1.0.2 → simpleeval-1.0.4}/pyproject.toml +7 -2
- simpleeval-1.0.4/simpleeval.py +931 -0
- {simpleeval-1.0.2 → simpleeval-1.0.4}/test_simpleeval.py +79 -8
- {simpleeval-1.0.2 → simpleeval-1.0.4}/.gitignore +0 -0
- {simpleeval-1.0.2 → simpleeval-1.0.4/.v314/lib/python3.14/site-packages/simpleeval-1.0.3.dist-info/licenses}/LICENCE +0 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
============================================
|
|
2
|
+
``docutils/parsers/rst/include`` Directory
|
|
3
|
+
============================================
|
|
4
|
+
|
|
5
|
+
This directory contains standard data files intended for inclusion in
|
|
6
|
+
reStructuredText documents. To access these files, use the "include"
|
|
7
|
+
directive with the special syntax for standard "include" data files,
|
|
8
|
+
angle brackets around the file name::
|
|
9
|
+
|
|
10
|
+
.. include:: <isonum.txt>
|
|
11
|
+
|
|
12
|
+
See the documentation for the `"include" directive`__ and
|
|
13
|
+
`reStructuredText Standard Definition Files`__ for
|
|
14
|
+
details.
|
|
15
|
+
|
|
16
|
+
__ https://docutils.sourceforge.io/docs/ref/rst/directives.html#include
|
|
17
|
+
__ https://docutils.sourceforge.io/docs/ref/rst/definitions.html
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
Except where otherwise noted, all files in this
|
|
2
|
+
directory have been released into the Public Domain.
|
|
3
|
+
|
|
4
|
+
These files are based on files from S5 1.1, released into the Public
|
|
5
|
+
Domain by Eric Meyer. For further details, please see
|
|
6
|
+
http://www.meyerweb.com/eric/tools/s5/credits.html.
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
================
|
|
2
|
+
Vendoring Policy
|
|
3
|
+
================
|
|
4
|
+
|
|
5
|
+
* Vendored libraries **MUST** not be modified except as required to
|
|
6
|
+
successfully vendor them.
|
|
7
|
+
* Vendored libraries **MUST** be released copies of libraries available on
|
|
8
|
+
PyPI.
|
|
9
|
+
* Vendored libraries **MUST** be available under a license that allows
|
|
10
|
+
them to be integrated into ``pip``, which is released under the MIT license.
|
|
11
|
+
* Vendored libraries **MUST** be accompanied with LICENSE files.
|
|
12
|
+
* The versions of libraries vendored in pip **MUST** be reflected in
|
|
13
|
+
``pip/_vendor/vendor.txt``.
|
|
14
|
+
* Vendored libraries **MUST** function without any build steps such as ``2to3``
|
|
15
|
+
or compilation of C code, practically this limits to single source 2.x/3.x and
|
|
16
|
+
pure Python.
|
|
17
|
+
* Any modifications made to libraries **MUST** be noted in
|
|
18
|
+
``pip/_vendor/README.rst`` and their corresponding patches **MUST** be
|
|
19
|
+
included ``tools/vendoring/patches``.
|
|
20
|
+
* Vendored libraries should have corresponding ``vendored()`` entries in
|
|
21
|
+
``pip/_vendor/__init__.py``.
|
|
22
|
+
|
|
23
|
+
Rationale
|
|
24
|
+
=========
|
|
25
|
+
|
|
26
|
+
Historically pip has not had any dependencies except for ``setuptools`` itself,
|
|
27
|
+
choosing instead to implement any functionality it needed to prevent needing
|
|
28
|
+
a dependency. However, starting with pip 1.5, we began to replace code that was
|
|
29
|
+
implemented inside of pip with reusable libraries from PyPI. This brought the
|
|
30
|
+
typical benefits of reusing libraries instead of reinventing the wheel like
|
|
31
|
+
higher quality and more battle tested code, centralization of bug fixes
|
|
32
|
+
(particularly security sensitive ones), and better/more features for less work.
|
|
33
|
+
|
|
34
|
+
However, there are several issues with having dependencies in the traditional
|
|
35
|
+
way (via ``install_requires``) for pip. These issues are:
|
|
36
|
+
|
|
37
|
+
**Fragility**
|
|
38
|
+
When pip depends on another library to function then if for whatever reason
|
|
39
|
+
that library either isn't installed or an incompatible version is installed
|
|
40
|
+
then pip ceases to function. This is of course true for all Python
|
|
41
|
+
applications, however for every application *except* for pip the way you fix
|
|
42
|
+
it is by re-running pip. Obviously, when pip can't run, you can't use pip to
|
|
43
|
+
fix pip, so you're left having to manually resolve dependencies and
|
|
44
|
+
installing them by hand.
|
|
45
|
+
|
|
46
|
+
**Making other libraries uninstallable**
|
|
47
|
+
One of pip's current dependencies is the ``requests`` library, for which pip
|
|
48
|
+
requires a fairly recent version to run. If pip depended on ``requests`` in
|
|
49
|
+
the traditional manner, then we'd either have to maintain compatibility with
|
|
50
|
+
every ``requests`` version that has ever existed (and ever will), OR allow
|
|
51
|
+
pip to render certain versions of ``requests`` uninstallable. (The second
|
|
52
|
+
issue, although technically true for any Python application, is magnified by
|
|
53
|
+
pip's ubiquity; pip is installed by default in Python, in ``pyvenv``, and in
|
|
54
|
+
``virtualenv``.)
|
|
55
|
+
|
|
56
|
+
**Security**
|
|
57
|
+
This might seem puzzling at first glance, since vendoring has a tendency to
|
|
58
|
+
complicate updating dependencies for security updates, and that holds true
|
|
59
|
+
for pip. However, given the *other* reasons for avoiding dependencies, the
|
|
60
|
+
alternative is for pip to reinvent the wheel itself. This is what pip did
|
|
61
|
+
historically. It forced pip to re-implement its own HTTPS verification
|
|
62
|
+
routines as a workaround for the Python standard library's lack of SSL
|
|
63
|
+
validation, which resulted in similar bugs in the validation routine in
|
|
64
|
+
``requests`` and ``urllib3``, except that they had to be discovered and
|
|
65
|
+
fixed independently. Even though we're vendoring, reusing libraries keeps
|
|
66
|
+
pip more secure by relying on the great work of our dependencies, *and*
|
|
67
|
+
allowing for faster, easier security fixes by simply pulling in newer
|
|
68
|
+
versions of dependencies.
|
|
69
|
+
|
|
70
|
+
**Bootstrapping**
|
|
71
|
+
Currently most popular methods of installing pip rely on pip's
|
|
72
|
+
self-contained nature to install pip itself. These tools work by bundling a
|
|
73
|
+
copy of pip, adding it to ``sys.path``, and then executing that copy of pip.
|
|
74
|
+
This is done instead of implementing a "mini installer" (to reduce
|
|
75
|
+
duplication); pip already knows how to install a Python package, and is far
|
|
76
|
+
more battle-tested than any "mini installer" could ever possibly be.
|
|
77
|
+
|
|
78
|
+
Many downstream redistributors have policies against this kind of bundling, and
|
|
79
|
+
instead opt to patch the software they distribute to debundle it and make it
|
|
80
|
+
rely on the global versions of the software that they already have packaged
|
|
81
|
+
(which may have its own patches applied to it). We (the pip team) would prefer
|
|
82
|
+
it if pip was *not* debundled in this manner due to the above reasons and
|
|
83
|
+
instead we would prefer it if pip would be left intact as it is now.
|
|
84
|
+
|
|
85
|
+
In the longer term, if someone has a *portable* solution to the above problems,
|
|
86
|
+
other than the bundling method we currently use, that doesn't add additional
|
|
87
|
+
problems that are unreasonable then we would be happy to consider, and possibly
|
|
88
|
+
switch to said method. This solution must function correctly across all of the
|
|
89
|
+
situation that we expect pip to be used and not mandate some external mechanism
|
|
90
|
+
such as OS packages.
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
Modifications
|
|
94
|
+
=============
|
|
95
|
+
|
|
96
|
+
* ``setuptools`` is completely stripped to only keep ``pkg_resources``.
|
|
97
|
+
* ``pkg_resources`` has been modified to import its dependencies from
|
|
98
|
+
``pip._vendor``, and to use the vendored copy of ``platformdirs``
|
|
99
|
+
rather than ``appdirs``.
|
|
100
|
+
* ``packaging`` has been modified to import its dependencies from
|
|
101
|
+
``pip._vendor``.
|
|
102
|
+
* ``CacheControl`` has been modified to import its dependencies from
|
|
103
|
+
``pip._vendor``.
|
|
104
|
+
* ``requests`` has been modified to import its other dependencies from
|
|
105
|
+
``pip._vendor`` and to *not* load ``simplejson`` (all platforms) and
|
|
106
|
+
``pyopenssl`` (Windows).
|
|
107
|
+
* ``platformdirs`` has been modified to import its submodules from ``pip._vendor.platformdirs``.
|
|
108
|
+
|
|
109
|
+
Automatic Vendoring
|
|
110
|
+
===================
|
|
111
|
+
|
|
112
|
+
Vendoring is automated via the `vendoring <https://pypi.org/project/vendoring/>`_ tool from the content of
|
|
113
|
+
``pip/_vendor/vendor.txt`` and the different patches in
|
|
114
|
+
``tools/vendoring/patches``.
|
|
115
|
+
Launch it via ``vendoring sync . -v`` (requires ``vendoring>=0.2.2``).
|
|
116
|
+
Tool configuration is done via ``pyproject.toml``.
|
|
117
|
+
|
|
118
|
+
To update the vendored library versions, we have a session defined in ``nox``.
|
|
119
|
+
The command to upgrade everything is::
|
|
120
|
+
|
|
121
|
+
nox -s vendoring -- --upgrade-all --skip urllib3 --skip setuptools
|
|
122
|
+
|
|
123
|
+
At the time of writing (April 2025) we do not upgrade ``urllib3`` because the
|
|
124
|
+
next version is a major upgrade and will be handled as an independent PR. We also
|
|
125
|
+
do not upgrade ``setuptools``, because we only rely on ``pkg_resources``, and
|
|
126
|
+
tracking every ``setuptools`` change is unnecessary for our needs.
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
Managing Local Patches
|
|
130
|
+
======================
|
|
131
|
+
|
|
132
|
+
The ``vendoring`` tool automatically applies our local patches, but updating,
|
|
133
|
+
the patches sometimes no longer apply cleanly. In that case, the update will
|
|
134
|
+
fail. To resolve this, take the following steps:
|
|
135
|
+
|
|
136
|
+
1. Revert any incomplete changes in the revendoring branch, to ensure you have
|
|
137
|
+
a clean starting point.
|
|
138
|
+
2. Run the revendoring of the library with a problem again: ``nox -s vendoring
|
|
139
|
+
-- --upgrade <library_name>``.
|
|
140
|
+
3. This will fail again, but you will have the original source in your working
|
|
141
|
+
directory. Review the existing patch against the source, and modify the patch
|
|
142
|
+
to reflect the new version of the source. If you ``git add`` the changes the
|
|
143
|
+
vendoring made, you can modify the source to reflect the patch file and then
|
|
144
|
+
generate a new patch with ``git diff``.
|
|
145
|
+
4. Now, revert everything *except* the patch file changes. Leave the modified
|
|
146
|
+
patch file unstaged but saved in the working tree.
|
|
147
|
+
5. Re-run the vendoring. This time, it should pick up the changed patch file
|
|
148
|
+
and apply it cleanly. The patch file changes will be committed along with the
|
|
149
|
+
revendoring, so the new commit should be ready to test and publish as a PR.
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
Debundling
|
|
153
|
+
==========
|
|
154
|
+
|
|
155
|
+
As mentioned in the rationale, we, the pip team, would prefer it if pip was not
|
|
156
|
+
debundled (other than optionally ``pip/_vendor/requests/cacert.pem``) and that
|
|
157
|
+
pip was left intact. However, if you insist on doing so, we have a
|
|
158
|
+
semi-supported method (that we don't test in our CI) and requires a bit of
|
|
159
|
+
extra work on your end in order to solve the problems described above.
|
|
160
|
+
|
|
161
|
+
1. Delete everything in ``pip/_vendor/`` **except** for
|
|
162
|
+
``pip/_vendor/__init__.py`` and ``pip/_vendor/vendor.txt``.
|
|
163
|
+
2. Generate wheels for each of pip's dependencies (and any of their
|
|
164
|
+
dependencies) using your patched copies of these libraries. These must be
|
|
165
|
+
placed somewhere on the filesystem that pip can access (``pip/_vendor`` is
|
|
166
|
+
the default assumption).
|
|
167
|
+
3. Modify ``pip/_vendor/__init__.py`` so that the ``DEBUNDLED`` variable is
|
|
168
|
+
``True``.
|
|
169
|
+
4. Upon installation, the ``INSTALLER`` file in pip's own ``dist-info``
|
|
170
|
+
directory should be set to something other than ``pip``, so that pip
|
|
171
|
+
can detect that it wasn't installed using itself.
|
|
172
|
+
5. *(optional)* If you've placed the wheels in a location other than
|
|
173
|
+
``pip/_vendor/``, then modify ``pip/_vendor/__init__.py`` so that the
|
|
174
|
+
``WHEEL_DIR`` variable points to the location you've placed them.
|
|
175
|
+
6. *(optional)* Update the ``pip_self_version_check`` logic to use the
|
|
176
|
+
appropriate logic for determining the latest available version of pip and
|
|
177
|
+
prompt the user with the correct upgrade message.
|
|
178
|
+
|
|
179
|
+
Note that partial debundling is **NOT** supported. You need to prepare wheels
|
|
180
|
+
for all dependencies for successful debundling.
|
|
@@ -129,7 +129,7 @@ DISALLOW_METHODS = [
|
|
|
129
129
|
]
|
|
130
130
|
|
|
131
131
|
# Disallow functions:
|
|
132
|
-
# This, strictly speaking, is not necessary. These /should/ never be
|
|
132
|
+
# This, strictly speaking, is not necessary. These /should/ never be accessible anyway,
|
|
133
133
|
# if DISALLOW_PREFIXES and DISALLOW_METHODS are all right. This is here to try and help
|
|
134
134
|
# people not be stupid. Allowing these functions opens up all sorts of holes - if any of
|
|
135
135
|
# their functionality is required, then please wrap them up in a safe container. And think
|
|
@@ -254,9 +254,9 @@ def safe_mult(a, b): # pylint: disable=invalid-name
|
|
|
254
254
|
"""limit the number of times an iterable can be repeated..."""
|
|
255
255
|
|
|
256
256
|
if hasattr(a, "__len__") and b * len(a) > MAX_STRING_LENGTH:
|
|
257
|
-
raise IterableTooLong("Sorry, I will not
|
|
257
|
+
raise IterableTooLong("Sorry, I will not evaluate something that long.")
|
|
258
258
|
if hasattr(b, "__len__") and a * len(b) > MAX_STRING_LENGTH:
|
|
259
|
-
raise IterableTooLong("Sorry, I will not
|
|
259
|
+
raise IterableTooLong("Sorry, I will not evaluate something that long.")
|
|
260
260
|
|
|
261
261
|
return a * b
|
|
262
262
|
|
|
@@ -386,13 +386,13 @@ class SimpleEval(object): # pylint: disable=too-few-public-methods
|
|
|
386
386
|
warnings.simplefilter("ignore")
|
|
387
387
|
# py3.12 deprecated ast.Num, ast.Str, ast.NameConstant
|
|
388
388
|
# https://docs.python.org/3.12/whatsnew/3.12.html#deprecated
|
|
389
|
-
if Num := getattr(ast, "Num"):
|
|
389
|
+
if Num := getattr(ast, "Num", None):
|
|
390
390
|
self.nodes[Num] = self._eval_num
|
|
391
391
|
|
|
392
|
-
if Str := getattr(ast, "Str"):
|
|
392
|
+
if Str := getattr(ast, "Str", None):
|
|
393
393
|
self.nodes[Str] = self._eval_str
|
|
394
394
|
|
|
395
|
-
if NameConstant := getattr(ast, "NameConstant"):
|
|
395
|
+
if NameConstant := getattr(ast, "NameConstant", None):
|
|
396
396
|
self.nodes[NameConstant] = self._eval_constant
|
|
397
397
|
|
|
398
398
|
# Defaults:
|
|
@@ -424,7 +424,7 @@ class SimpleEval(object): # pylint: disable=too-few-public-methods
|
|
|
424
424
|
return parsed.body[0]
|
|
425
425
|
|
|
426
426
|
def eval(self, expr, previously_parsed=None):
|
|
427
|
-
"""evaluate an
|
|
427
|
+
"""evaluate an expression, using the operators, functions and
|
|
428
428
|
names previously set up."""
|
|
429
429
|
|
|
430
430
|
# set a copy of the expression aside, so we can give nice errors...
|
|
@@ -763,6 +763,6 @@ class EvalWithCompoundTypes(SimpleEval):
|
|
|
763
763
|
|
|
764
764
|
|
|
765
765
|
def simple_eval(expr, operators=None, functions=None, names=None):
|
|
766
|
-
"""Simply evaluate an
|
|
766
|
+
"""Simply evaluate an expression"""
|
|
767
767
|
s = SimpleEval(operators=operators, functions=functions, names=names)
|
|
768
768
|
return s.eval(expr)
|
simpleeval-1.0.4/LICENCE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
simpleeval - Copyright (c) 2013-2026 Daniel Fairhead
|
|
2
|
+
|
|
3
|
+
(MIT Licence)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: simpleeval
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.4
|
|
4
4
|
Summary: A simple, safe single expression evaluator library.
|
|
5
5
|
Project-URL: Source code, https://github.com/danthedeckie/simpleeval
|
|
6
6
|
Author-email: Daniel Fairhead <danthedeckie@gmail.com>
|
|
7
7
|
Maintainer-email: Daniel Fairhead <danthedeckie@gmail.com>
|
|
8
|
-
License
|
|
8
|
+
License: MIT
|
|
9
9
|
Keywords: ast,eval,expression,parse,simple
|
|
10
10
|
Classifier: Development Status :: 5 - Production/Stable
|
|
11
11
|
Classifier: Intended Audience :: Developers
|
|
@@ -239,7 +239,7 @@ which, of course, can be nested:
|
|
|
239
239
|
Functions
|
|
240
240
|
---------
|
|
241
241
|
|
|
242
|
-
You can define functions which you'd like the
|
|
242
|
+
You can define functions which you'd like the expressions to have access to:
|
|
243
243
|
|
|
244
244
|
.. code-block:: pycon
|
|
245
245
|
|
|
@@ -356,7 +356,7 @@ cases):
|
|
|
356
356
|
# and so on...
|
|
357
357
|
|
|
358
358
|
One useful feature of using the ``SimpleEval`` object is that you can parse an expression
|
|
359
|
-
once, and then evaluate it
|
|
359
|
+
once, and then evaluate it multiple times using different ``names``:
|
|
360
360
|
|
|
361
361
|
.. code-block:: python
|
|
362
362
|
|
|
@@ -449,10 +449,8 @@ version that disallows method invocation on objects:
|
|
|
449
449
|
|
|
450
450
|
and then use ``EvalNoMethods`` instead of the ``SimpleEval`` class.
|
|
451
451
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
The library supports Python 3.9 and higher.
|
|
452
|
+
Limiting Attribute Access
|
|
453
|
+
-------------------------
|
|
456
454
|
|
|
457
455
|
Object attributes that start with ``_`` or ``func_`` are disallowed by default.
|
|
458
456
|
If you really need that (BE CAREFUL!), then modify the module global
|
|
@@ -462,6 +460,51 @@ A few builtin functions are listed in ``simpleeval.DISALLOW_FUNCTIONS``. ``type
|
|
|
462
460
|
If you need to give access to this kind of functionality to your expressions, then be very
|
|
463
461
|
careful. You'd be better wrapping the functions in your own safe wrappers.
|
|
464
462
|
|
|
463
|
+
There is an additional layer of protection you can add in by passing in ``allowed_attrs``, which
|
|
464
|
+
makes all attribute access based opt-in rather than opt-out - which is a lot safer design:
|
|
465
|
+
|
|
466
|
+
.. code-block:: pycon
|
|
467
|
+
|
|
468
|
+
>>> simpleeval("' hello '.strip()", allowed_attrs={})
|
|
469
|
+
|
|
470
|
+
will throw FeatureNotAvailable - as we've now disabled all attribute access. You can enable some
|
|
471
|
+
reasonably sensible defaults with BASIC_ALLOWED_ATTRS:
|
|
472
|
+
|
|
473
|
+
.. code-block:: pycon
|
|
474
|
+
|
|
475
|
+
>>> from simpleeval import simpleeval, BASIC_ALLOWED_ATTRS
|
|
476
|
+
>>> simpleeval("' hello '.strip()", allowed_attrs=BASIC_ALLOWED_ATTRS)
|
|
477
|
+
|
|
478
|
+
is fine - ``strip()`` should be safe on strings.
|
|
479
|
+
|
|
480
|
+
It is recommended to add ``allowed_attrs=BASIC_ALLOWED_ATTRS`` whenever possible, and it will
|
|
481
|
+
be the default for 2.x.
|
|
482
|
+
|
|
483
|
+
You can add your own classes & limit access to attrs:
|
|
484
|
+
|
|
485
|
+
.. code-block:: pycon
|
|
486
|
+
|
|
487
|
+
>>> from simpleeval import simpleeval, BASIC_ALLOWED_ATTRS
|
|
488
|
+
>>> class Foo:
|
|
489
|
+
>>> bar = 42
|
|
490
|
+
>>> hidden = "secret"
|
|
491
|
+
>>>
|
|
492
|
+
>>> our_attributes = BASIC_ALLOWED_ATTRS.copy()
|
|
493
|
+
>>> our_attributes[Foo] = {'bar'}
|
|
494
|
+
>>> simpleeval("foo.bar", names={"foo": Foo()}, allowed_attrs=our_attributes)
|
|
495
|
+
42
|
|
496
|
+
|
|
497
|
+
>>> simpleeval("foo.hidden", names={"foo": Foo()}, allowed_attrs=our_attributes)
|
|
498
|
+
simpleeval.FeatureNotAvailable: Sorry, 'hidden' access not allowed on 'Foo'
|
|
499
|
+
|
|
500
|
+
will now allow access to `foo.bar` but not allow anything else.
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
Other...
|
|
504
|
+
--------
|
|
505
|
+
|
|
506
|
+
The library supports Python 3.9 and higher.
|
|
507
|
+
|
|
465
508
|
The initial idea came from J.F. Sebastian on Stack Overflow
|
|
466
509
|
( http://stackoverflow.com/a/9558001/1973500 ) with modifications and many improvements,
|
|
467
510
|
see the head of the main file for contributors list.
|
|
@@ -498,3 +541,8 @@ BEWARE
|
|
|
498
541
|
I've done the best I can with this library - but there's no warranty, no guarantee, nada. A lot of
|
|
499
542
|
very clever people think the whole idea of trying to sandbox CPython is impossible. Read the code
|
|
500
543
|
yourself, and use it at your own risk.
|
|
544
|
+
|
|
545
|
+
The sandboxing / safety features of simpleeval *only apply to the expression* that is passed in to
|
|
546
|
+
be evaluated, and rely on the python interpreter working as normal. If you have monkey-patched
|
|
547
|
+
the interpreter, or pass in objects/classes/functions with unsafe code in them, simpleeval cannot
|
|
548
|
+
protect you.
|
|
@@ -222,7 +222,7 @@ which, of course, can be nested:
|
|
|
222
222
|
Functions
|
|
223
223
|
---------
|
|
224
224
|
|
|
225
|
-
You can define functions which you'd like the
|
|
225
|
+
You can define functions which you'd like the expressions to have access to:
|
|
226
226
|
|
|
227
227
|
.. code-block:: pycon
|
|
228
228
|
|
|
@@ -339,7 +339,7 @@ cases):
|
|
|
339
339
|
# and so on...
|
|
340
340
|
|
|
341
341
|
One useful feature of using the ``SimpleEval`` object is that you can parse an expression
|
|
342
|
-
once, and then evaluate it
|
|
342
|
+
once, and then evaluate it multiple times using different ``names``:
|
|
343
343
|
|
|
344
344
|
.. code-block:: python
|
|
345
345
|
|
|
@@ -432,10 +432,8 @@ version that disallows method invocation on objects:
|
|
|
432
432
|
|
|
433
433
|
and then use ``EvalNoMethods`` instead of the ``SimpleEval`` class.
|
|
434
434
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
The library supports Python 3.9 and higher.
|
|
435
|
+
Limiting Attribute Access
|
|
436
|
+
-------------------------
|
|
439
437
|
|
|
440
438
|
Object attributes that start with ``_`` or ``func_`` are disallowed by default.
|
|
441
439
|
If you really need that (BE CAREFUL!), then modify the module global
|
|
@@ -445,6 +443,51 @@ A few builtin functions are listed in ``simpleeval.DISALLOW_FUNCTIONS``. ``type
|
|
|
445
443
|
If you need to give access to this kind of functionality to your expressions, then be very
|
|
446
444
|
careful. You'd be better wrapping the functions in your own safe wrappers.
|
|
447
445
|
|
|
446
|
+
There is an additional layer of protection you can add in by passing in ``allowed_attrs``, which
|
|
447
|
+
makes all attribute access based opt-in rather than opt-out - which is a lot safer design:
|
|
448
|
+
|
|
449
|
+
.. code-block:: pycon
|
|
450
|
+
|
|
451
|
+
>>> simpleeval("' hello '.strip()", allowed_attrs={})
|
|
452
|
+
|
|
453
|
+
will throw FeatureNotAvailable - as we've now disabled all attribute access. You can enable some
|
|
454
|
+
reasonably sensible defaults with BASIC_ALLOWED_ATTRS:
|
|
455
|
+
|
|
456
|
+
.. code-block:: pycon
|
|
457
|
+
|
|
458
|
+
>>> from simpleeval import simpleeval, BASIC_ALLOWED_ATTRS
|
|
459
|
+
>>> simpleeval("' hello '.strip()", allowed_attrs=BASIC_ALLOWED_ATTRS)
|
|
460
|
+
|
|
461
|
+
is fine - ``strip()`` should be safe on strings.
|
|
462
|
+
|
|
463
|
+
It is recommended to add ``allowed_attrs=BASIC_ALLOWED_ATTRS`` whenever possible, and it will
|
|
464
|
+
be the default for 2.x.
|
|
465
|
+
|
|
466
|
+
You can add your own classes & limit access to attrs:
|
|
467
|
+
|
|
468
|
+
.. code-block:: pycon
|
|
469
|
+
|
|
470
|
+
>>> from simpleeval import simpleeval, BASIC_ALLOWED_ATTRS
|
|
471
|
+
>>> class Foo:
|
|
472
|
+
>>> bar = 42
|
|
473
|
+
>>> hidden = "secret"
|
|
474
|
+
>>>
|
|
475
|
+
>>> our_attributes = BASIC_ALLOWED_ATTRS.copy()
|
|
476
|
+
>>> our_attributes[Foo] = {'bar'}
|
|
477
|
+
>>> simpleeval("foo.bar", names={"foo": Foo()}, allowed_attrs=our_attributes)
|
|
478
|
+
42
|
|
479
|
+
|
|
480
|
+
>>> simpleeval("foo.hidden", names={"foo": Foo()}, allowed_attrs=our_attributes)
|
|
481
|
+
simpleeval.FeatureNotAvailable: Sorry, 'hidden' access not allowed on 'Foo'
|
|
482
|
+
|
|
483
|
+
will now allow access to `foo.bar` but not allow anything else.
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
Other...
|
|
487
|
+
--------
|
|
488
|
+
|
|
489
|
+
The library supports Python 3.9 and higher.
|
|
490
|
+
|
|
448
491
|
The initial idea came from J.F. Sebastian on Stack Overflow
|
|
449
492
|
( http://stackoverflow.com/a/9558001/1973500 ) with modifications and many improvements,
|
|
450
493
|
see the head of the main file for contributors list.
|
|
@@ -481,3 +524,8 @@ BEWARE
|
|
|
481
524
|
I've done the best I can with this library - but there's no warranty, no guarantee, nada. A lot of
|
|
482
525
|
very clever people think the whole idea of trying to sandbox CPython is impossible. Read the code
|
|
483
526
|
yourself, and use it at your own risk.
|
|
527
|
+
|
|
528
|
+
The sandboxing / safety features of simpleeval *only apply to the expression* that is passed in to
|
|
529
|
+
be evaluated, and rely on the python interpreter working as normal. If you have monkey-patched
|
|
530
|
+
the interpreter, or pass in objects/classes/functions with unsafe code in them, simpleeval cannot
|
|
531
|
+
protect you.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "simpleeval"
|
|
3
|
-
version = "1.0.
|
|
3
|
+
version = "1.0.4"
|
|
4
4
|
requires-python = ">=3.9"
|
|
5
5
|
readme = "README.rst"
|
|
6
6
|
description = "A simple, safe single expression evaluator library."
|
|
7
|
-
|
|
7
|
+
license = "MIT"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name = "Daniel Fairhead", email = "danthedeckie@gmail.com" }
|
|
10
10
|
]
|
|
@@ -41,10 +41,15 @@ include = [
|
|
|
41
41
|
"README.rst",
|
|
42
42
|
"LICENCE",
|
|
43
43
|
]
|
|
44
|
+
core-metadata-version = "2.3"
|
|
44
45
|
|
|
45
46
|
[tool.hatch.version]
|
|
46
47
|
path = "simpleeval.py"
|
|
47
48
|
|
|
49
|
+
[tool.hatch.build.targets.wheel]
|
|
50
|
+
packages = ["simpleeval.py"]
|
|
51
|
+
core-metadata-version = "2.3"
|
|
52
|
+
|
|
48
53
|
[tool.hatch.envs.hatch-test]
|
|
49
54
|
default-args = ["test_simpleeval.py"]
|
|
50
55
|
|