Skip to content

Commit

Permalink
tweak and update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
newville committed Mar 3, 2024
1 parent 390eafc commit 3644880
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 57 deletions.
2 changes: 1 addition & 1 deletion doc/api.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.. _asteval_api:

========================
asteval reference
Asteval Reference
========================

.. _numpy: https://numpy.org
Expand Down
6 changes: 3 additions & 3 deletions doc/basics.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
================
Using asteval
Using Asteval
================

This chapter gives a quick overview of asteval, showing basic usage and the
Expand Down Expand Up @@ -133,15 +133,15 @@ comprehensions
================

list, dict, and set comprehension are supported, acting just as they do in
Python. Generators, yield, and async programmming are not currently supported.
Python. Generators, yield, and async programming are not currently supported.


printing
===============

For printing, asteval emulates Python's native :func:`print` function. You
can change where output is sent with the ``writer`` argument when creating
the interpreter, or supreess printing all together with the ``no_print``
the interpreter, or suppress printing all together with the ``no_print``
option. By default, outputs are sent to :py:data:`sys.stdout`.


Expand Down
2 changes: 1 addition & 1 deletion doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,6 @@ malicious attacks.
:maxdepth: 2

installation
motivation
basics
api
motivation
44 changes: 22 additions & 22 deletions doc/installation.rst
Original file line number Diff line number Diff line change
@@ -1,41 +1,43 @@
====================================
Downloading and Installation
Installing Asteval
====================================

.. _numpy: https://numpy.org/
.. _numpy_financial: https://numpy.org/numpy-financial/
.. _github: https://github.com/lmfit/asteval
.. _PyPI: https://pypi.org/project/asteval/

Requirements
~~~~~~~~~~~~~~~

Asteval is a pure Python module. For Python 3.8 and higher, there are no
required dependencies outside of the standard library. If `numpy`_ and
`numpy_financial` are available, Asteval will make use of these libraries. The
test suite requires the `pytest` and `coverage` modules, and building the
documentation requires `sphinx`.
Asteval is a pure Python module. The latest stable version is |release|, which
supports Python 3.8 through 3.12.

The latest stable version of asteval is |release|.
Installing `asteval` requires `setuptools` and `setuptools_scm`. No other
libraries outside of the standard library are required. If `numpy`_ and
`numpy_financial`_ are available, `asteval` will make use of these libraries.
Running the test suite requires the `pytest`, `coverage`, and `pytest-cov`
modules, deployment uses `build` and `twine`, and building the documentation
requires `sphinx`.

Python 3.8 through 3.12 are tested on Windows, MacOS, and Linux, with and
without `numpy`_ installed. Older Python versions have generally been
supported by `asteval` until they are well past the end of security fixes. That
is, while `asteval` is no longer tested with Python 3.7, the latest release may
continue to work with that version.

Versions 0.9.30 and later support Python 3.8 through 3.11 and are and are
automatically tested with these on Windows, MacOS, and Linux, with and without
`numpy`_ installed. Python versions have generally been supported by `asteval`
until they are well past the end of security fixes - there are no immediate
plans to drop support for Python 3.7, though we are no longer test with it.
Support for new versions of the Python 3 series is not guaranteed until some
time after the official release of that version, as we may not start testing
until late in the "beta" period of development. Historically, the delay has
not been too long, though `asteval` may not support newly introduced language
features.

At this writing (Asteval 0.9.32, March, 2024), testing is done with Python 3.8
through 3.12, with and without numpy installed.

Download and Installation
Installing with `pip`
~~~~~~~~~~~~~~~~~~~~~~~~~~~

The latest stable version of asteval is |release| and is available at
`PyPI`_ or as a conda package. You should be able to install asteval
The latest stable version of `asteval` is |release| and is available at
`PyPI`_ or as a conda package. You should be able to install `asteval`
with::

pip install asteval
Expand All @@ -53,16 +55,14 @@ The latest development version can be found at the `github`_ repository, and clo
git clone https://github.com/lmfit/asteval.git


Installation
~~~~~~~~~~~~~~~~~

Installation from source on any platform is::
Installation from the source tree on any platform is can then be done with::

pip install .

License
~~~~~~~~~~~~~

The ASTEVAL code is distribution under the following license:
The `asteval` code and documentation is distribution under the following
license:

.. literalinclude:: ../LICENSE
61 changes: 31 additions & 30 deletions doc/motivation.rst
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
.. _lmfit: https://github.com/lmfit/lmfit-py
.. _xraylarch: https://github.com/xraypy/xraylarch

########################
Motivation for asteval
########################
====================================
Motivation for Asteval
====================================

The asteval module allows you to evaluate a large subset of the Python language
from within a python program, without using :py:func:`eval`. It is, in effect,
Expand Down Expand Up @@ -111,33 +111,34 @@ calculation, and so a reasonable looking calculation such as::
can take a noticeable amount of CPU time - if it does not, changing ``1e8`` to
``9e13`` almost certainly will. As another example, consider the expression
``x**y**z``. For values ``x=y=z=5``, the run time will be well under 0.001
seconds. For ``x=y=z=8``, run time will still be under 1 sec. Changing to ``x=8,
y=9, z=9``, will cause the statement to take several seconds. With ``x=y=z=9``,
executing that statement may take more than 1 hour on some machines. It is not
hard to come up with short program that would run for hundreds of years, which
probably exceeds anyones threshold for an acceptable run-time. There simply is
not a good way to predict how long any code will take to run from the text of
the code itself: run time cannot be determined lexically. To be clear, for
this exponentiation example, asteval will raise a runtime error, telling you
that an exponent > 10,000 is not allowed. But that happens at runtime, after
the value of the exponent has been evaluated, it does not happen by looking at
the text of the code. And, there is no limit on the size of arrays that can be
created because a check would have to done at runtime. There are countless
other "clever ways" to have very long run times that cannot be readily
predicted from the text.

The exponential example also demonstrates there is not a good way to check for
a long-running calculation within a single Python process. That calculation is
not stuck within the Python interpreter, but in C code (no doubt the ``pow()``
function) called by the Python interpreter itself. That call will not return
from the C library to the Python interpreter or allow other threads to run
until that call is done. That means that from within a single process, there
would not be a reliable way to tell asteval (or really, even Python) when a
calculation has taken too long: Denial of Service is hard to detect before it
happens, and even challenging to detect while it is happening. The only
reliable way to li`mit run time is at the level of the operating system, with a
second process watching the execution time of the asteval process and either
try to interrupt it or kill it.
seconds. For ``x=y=z=8``, run time will still be under 1 sec. Changing to
``x=8, y=9, z=9``, will cause the statement to take several seconds. With
``x=y=z=9``, executing that statement may take more than 1 hour on some
machines. It is not hard to come up with short program that would run for
hundreds of years, which probably exceeds anyones threshold for an acceptable
run-time. There simply is not a good way to predict how long any code will
take to run from the text of the code itself: run time cannot be determined
lexically. To be clear, for this exponentiation example, asteval will raise a
runtime error, telling you that an exponent > 10,000 is not allowed. Several
other attempts are made to prevent long-running operations. But these checks
happen at runtime (that is, after the value of the exponent has been
evaluated), it does not happen by looking at the text of the code. Very large
arrays and lists can be created that might approach memory limits. There are
countless other "clever ways" to have very long run times that cannot be
readily predicted from the text.

The exponential example also highlights the issue that there is not a good way
to check for a long-running calculation within a single Python process. That
calculation is not stuck within the Python interpreter, but in C code (no doubt
the ``pow()`` function) called by the Python interpreter itself. That call
will not return from the C library to the Python interpreter or allow other
threads to run until that call is done. That means that from within a single
process, there would not be a reliable way to tell asteval (or really, even
Python) when a calculation has taken too long: Denial of Service is hard to
detect before it happens, and even challenging to detect while it is happening.
The only reliable way to limit run time is at the level of the operating
system, with a second process watching the execution time of the asteval
process and either try to interrupt it or kill it.

For a limited range of problems, you can try to avoid asteval taking too
long. For example, you may try to limit the *recursion limit* when
Expand Down

0 comments on commit 3644880

Please sign in to comment.