diff --git a/doc/api.rst b/doc/api.rst index 4688345..23edcf7 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -1,7 +1,7 @@ .. _asteval_api: ======================== -asteval reference +Asteval Reference ======================== .. _numpy: https://numpy.org diff --git a/doc/basics.rst b/doc/basics.rst index a70d9ab..0dcce9f 100644 --- a/doc/basics.rst +++ b/doc/basics.rst @@ -1,5 +1,5 @@ ================ -Using asteval +Using Asteval ================ This chapter gives a quick overview of asteval, showing basic usage and the @@ -133,7 +133,7 @@ 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 @@ -141,7 +141,7 @@ 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`. diff --git a/doc/index.rst b/doc/index.rst index a9d1eba..ccc8390 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -68,6 +68,6 @@ malicious attacks. :maxdepth: 2 installation - motivation basics api + motivation diff --git a/doc/installation.rst b/doc/installation.rst index 980d23a..103c0da 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -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 @@ -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 diff --git a/doc/motivation.rst b/doc/motivation.rst index dadc3d5..c79f9b6 100644 --- a/doc/motivation.rst +++ b/doc/motivation.rst @@ -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, @@ -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