Skip to content

Commit

Permalink
apply requested changes on docs
Browse files Browse the repository at this point in the history
  • Loading branch information
loechel committed Feb 21, 2017
1 parent edd5682 commit 1aa3e30
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 37 deletions.
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ RestrictedPython

RestrictedPython is a defined subset of the Python language which allows to provide a program input into a trusted environment.

For full documentation please see docs/index.
For full documentation please see http://restrictedpython.readthedocs.io/en/python3_update/ or local docs/index.
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
extensions = [
'sphinx.ext.intersphinx',
'sphinx.ext.todo',
'sphinx.ext.doctest',
]

# Add any paths that contain templates here, relative to this directory.
Expand Down
6 changes: 0 additions & 6 deletions docs/contributing/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,3 @@ Contributing
============

Contributing to RestrictedPython 4+


* `Trello Board`_


.. _`Trello Board`: https://trello.com/b/pKaXJIlT/restrictedpython
4 changes: 0 additions & 4 deletions docs/roadmap/index.rst
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
Roadmap for RestrictedPython
============================

A few of the action items currently worked on is on our `Trello Board`_.

.. _`Trello Board`: https://trello.com/b/pKaXJIlT/restrictedpython

RestrictedPython 4.0
--------------------

Expand Down
47 changes: 38 additions & 9 deletions docs/usage/basic_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,53 @@ The general workflow to execute Python code that is loaded within a Python progr
exec(byte_code)
do_something()
.. doctest::
:hide:

>>> source_code = """
... def do_something():
... pass
... """
>>> byte_code = compile(source_code, filename='<inline code>', mode='exec')
>>> exec(byte_code)
>>> do_something()


With RestrictedPython that workflow should be as straight forward as possible:

.. code:: Python
from RestrictedPython import compile_restricted as compile
from RestrictedPython import compile_restricted
source_code = """
def do_something():
pass
"""
byte_code = compile(source_code, filename='<inline code>', mode='exec')
byte_code = compile_restricted(source_code, filename='<inline code>', mode='exec')
exec(byte_code)
do_something()
With that simple addition:
.. doctest::
:hide:

>>> from RestrictedPython import compile_restricted
>>> source_code = """
... def do_something():
... pass
... """
>>> byte_code = compile_restricted(source_code, filename='<inline code>', mode='exec')
>>> exec(byte_code)
>>> do_something()

You might also use the replacement import:

.. code:: Python
from RestrictedPython import compile_restricted as compile
it uses a predefined policy that checks and modify the source code and checks against a restricted subset of the Python language.
``compile_restricted`` uses a predefined policy that checks and modify the source code and checks against a restricted subset of the Python language.
The compiled source code is still executed against the full available set of library modules and methods.

The Python :py:func:`exec` takes three parameters:
Expand All @@ -55,7 +80,7 @@ Providing defined dictionaries for ``exec()`` should be used in context of Restr
exec(byte_code, { ... }, { ... })
Typically there is a defined set of allowed modules, methods and constants used in that context.
RestrictedPython provides three predefined built-ins for that:
RestrictedPython provides three predefined built-ins for that (see :ref:`predefined_builtins` for details):

* ``safe_builtins``
* ``limited_builtins``
Expand All @@ -65,15 +90,19 @@ So you normally end up using:

.. code:: Python
from RestrictedPython import ..._builtins
from RestrictedPython import compile_restricted as compile
#from RestrictedPython import ..._builtins

This comment has been minimized.

Copy link
@icemac

icemac Mar 1, 2017

Member

@loechel Please remove this line with the comment sign.

from RestrictedPython import safe_builtins
from RestrictedPython import limited_builtins
from RestrictedPython import utilities_builtins
from RestrictedPython import compile_restricted
source_code = """<demo code>"""
try:
byte_code = compile(source_code, filename='<name>', mode='exec')
byte_code = compile_restricted(source_code, filename='<name>', mode='exec')
used_builtins = ..._builtins + { <additionl elems> }
#used_builtins = ..._builtins + { <additionl elems> } # Whitelisting additional elements

This comment has been minimized.

Copy link
@icemac

icemac Mar 1, 2017

Member

same here

used_builtins = safe_builtins
exec(byte_code, used_buildins, None)
except SyntaxError as e:
...
Expand Down
37 changes: 28 additions & 9 deletions docs/usage/framework_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ RestrictedPython provides four specialized compile_restricted methods:
* ``compile_restricted_single``
* ``compile_restricted_function``

Those four methods return a tuple with four elements:
Those four methods return a named tuple (``CompileResult``) with four elements:

* ``byte_code`` <code> object or ``None`` if ``errors`` is not empty
* ``code`` ``<code>`` object or ``None`` if ``errors`` is not empty
* ``errors`` a tuple with error messages
* ``warnings`` a list with warnings
* ``used_names`` a set / dictionary with collected used names of library calls
Expand All @@ -31,15 +31,18 @@ Modifying the builtins is straight forward, it is just a dictionary containing a
Modification is normally removing elements from existing builtins or adding allowed elements by copying from globals.

For frameworks it could possibly also be useful to change handling of specific Python language elements.
For that use case RestrictedPython provide the possibility to pass an own policy.
A policy is basically a special ``NodeTransformer`` that could be instantiated with three params for ``errors``, ``warnings`` and ``used_names``, it should be a subclass of RestrictingNodeTransformer (that subclassing will maybe later be enforced).
For that use case RestrictedPython provides the possibility to pass an own policy.

A policy is basically a special ``NodeTransformer`` that could be instantiated with three params for ``errors``, ``warnings`` and ``used_names``, it should be a subclass of RestrictedPython.RestrictingNodeTransformer.

.. todo::

write doctests for following code

.. code:: Python
OwnRestrictingNodeTransformer(errors=[], warnings=[], used_names=[])
One special case (defined to unblock ports of Zope Packages to Python 3) is to actually use RestrictedPython in an unrestricted mode, by providing a Null-Policy (aka ``None``).

All ``compile_restricted*`` methods do have a optional parameter ``policy``, where a specific policy could be provided.

.. code:: Python
Expand All @@ -48,14 +51,30 @@ All ``compile_restricted*`` methods do have a optional parameter ``policy``, whe
policy = OwnRestrictingNodeTransformer
byte_code = compile(source_code, filename='<inline code>', mode='exec', policy=policy)
byte_code = compile_restricted(source_code, filename='<inline code>', mode='exec', policy=policy)
exec(byte_code, { ... }, { ... })
The Special case "unrestricted RestrictedPython" would be:
One special case "unrestricted RestrictedPython" (defined to unblock ports of Zope Packages to Python 3) is to actually use RestrictedPython in an unrestricted mode, by providing a Null-Policy (aka ``None``).
That special case would be written as:

.. code:: Python
source_code = """<demo code>"""
byte_code = compile(source_code, filename='<inline code>', mode='exec', policy=None)
byte_code = compile_restricted(source_code, filename='<inline code>', mode='exec', policy=None)
exec(byte_code, globals(), None)
.. doctest::
:hide:

>>> from RestrictedPython import compile_restricted
>>>
>>> source_code = """
... def do_something():
... pass
...
... do_something()
... """
>>>
>>> byte_code = compile_restricted(source_code, filename='<inline code>', mode='exec', policy=None)
>>> exec(byte_code, globals(), None)
32 changes: 27 additions & 5 deletions docs/usage/policy.rst
Original file line number Diff line number Diff line change
@@ -1,13 +1,35 @@
.. _policy_builtins:

Policies & builtins
-------------------

.. todo::

Should be described in detail.
Especially the difference between builtins and a policy which is a NodeTransformer.


RestrictedPython provides a way to define Policies, by redefining restricted versions of ``print``, ``getattr``, ``setattr``, ``import``, etc..
As shortcuts it offers three stripped down versions of Pythons ``__builtins__``:

.. _predefined_builtins:

Predefined builtins
...................

.. todo::

Describe more in details

* ``safe_builtins`` a safe set of builtin modules and functions,
* ``limited_builtins`` which provides restricted sequence types,
* ``utilities_builtins`` which provides access for standard modules math, random, string and for sets.

Guards
......

Also RestrictedPython provides a way to define Policies, by redefining restricted versions of ``print``, ``getattr``, ``setattr``, ``import``, etc..
As shortcutes it offers three stripped down versions of Pythons ``__builtins__``:
.. todo::

* ``safe_builtins`` (by Guards.py)
* ``limited_builtins`` (by Limits.py), which provides restriced sequence types
* ``utilities_builtins`` (by Utilities.py), which provides access for standard modules math, random, string and for sets.
Describe Guards and predefined guard methods in details

There is also a guard function for making attributes immutable --> ``full_write_guard`` (write and delete protected)
2 changes: 0 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ def read(*rnames):
description='RestrictedPython provides a restricted execution '
'environment for Python, e.g. for running untrusted code.',
long_description=(read('README.rst') + '\n' +
read('docs', 'install', 'index.rst') + '\n' +
read('docs', 'usage', 'basic_usage.rst') + '\n' +
read('docs', 'CHANGES.rst')),
classifiers=[
'License :: OSI Approved :: Zope Public License',
Expand Down
3 changes: 2 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ envlist =
py35,
py36,
pypy,
docs,
coverage-report,
isort,
docs,
skip_missing_interpreters = False

[testenv]
Expand Down Expand Up @@ -74,6 +74,7 @@ commands = flake8 --doctests src tests setup.py
basepython = python2.7
commands =
sphinx-build -b html -d build/docs/doctrees docs build/docs/html
sphinx-build -b doctest docs build/docs/doctrees
deps =
.[docs]
Sphinx

0 comments on commit 1aa3e30

Please sign in to comment.