Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compile tests of invalid options #39

Merged
merged 11 commits into from
Mar 3, 2017
Merged

Compile tests of invalid options #39

merged 11 commits into from
Mar 3, 2017

Conversation

loechel
Copy link
Member

@loechel loechel commented Feb 5, 2017

No description provided.

@loechel loechel requested a review from icemac February 5, 2017 18:10
Copy link
Member

@stephan-hof stephan-hof left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general the pull request looks good to me.

Another thing where I'm not sure of is this dont_inherit flag on the various functions in compile.py.
If set to True the compile function inherits the future imports from the compile.py module. Right now there are no future imports in this file so even if set to True the flag has no effect at all.

I also think that inheriting the future imports from compile.py is rarely needed by the user of this functions. Since he has no control what is enabled or not, because it is hardcoded in compile.py (if there were any).
So I would vote for removing this flag from the public API at all.

@@ -629,7 +629,8 @@ def visit_UnaryOp(self, node):
"""

"""
self.not_allowed(node)
return self.node_contents_visit(node)
# self.not_allowed(node)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this unnecessary comment out ? I thought this is what version control is for ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be fixed

@@ -647,7 +648,8 @@ def visit_Not(self, node):
"""

"""
self.not_allowed(node)
return self.node_contents_visit(node)
# self.not_allowed(node)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this unnecessary comment out ? I thought this is what version control is for ?

from RestrictedPython import compile_restricted
from RestrictedPython import CompileResult
from RestrictedPython._compat import IS_PY2
from tests import c_eval
from tests import c_exec
from tests import e_eval
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please explain why you moved from relative import to absolute import ?

To be honest, I don't like code in __init__.py at all.
What about moving all the code from __init__.py into a helpers.py and then use a relative import
from .helpers import c_eval.
I guess there are better names than `helpers.py', I used that one to express the idea.
What do you think ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do generally prefer absolute imports as this support readability and to understand where things come from.

The init.py is something we should avoid in total, it is directly derecommended in the pytest goog practice guide: http://doc.pytest.org/en/latest/goodpractices.html#choosing-a-test-layout-import-rules But without a init.py there is no namespace to import from.

regarding helpers I would also prefer that, but suggest utils.py or utilities.py.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@loechel @stephan-hof I put these functions into __init__.py because they are temporary. When we delete the old implementation we will delete them, too. (As I understand we will delete the old implementation before merging the Python3 branch to master.)

from RestrictedPython import RestrictingNodeTransformer
from RestrictedPython._compat import IS_PY2
from RestrictedPython._compat import IS_PY3
from RestrictedPython.Guards import guarded_iter_unpack_sequence
from RestrictedPython.Guards import guarded_unpack_sequence
from tests import c_exec
from tests import e_eval
from tests import e_exec
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the suggestion from above it would be from ..helpers import c_exec

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I liked the relative import here as it makes clear that the code is in __init__.py which is not so clear to me when using tests. But as this is only temporary I do not mind.

# mode='function',
# flags=flags,
# dont_inherit=dont_inherit,
# policy=policy)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please explain why you kept this artefact inside a comment ?


],
setup_requires=[
'pytest-runner',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be moved to test_requires. Why is pytest-runner needed to run setup.py ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It just follows the documentation of pytest: http://doc.pytest.org/en/latest/goodpractices.html#integrating-with-setuptools-python-setup-py-test-pytest-runner

In some way, the extras_require test section is also redundant with test_requires

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah thank you for the link. Looks like it is needed to make something like this working: python setup.py test.
I was asking, because for me it looks like that when RestrictedPython is installed also pytest-runner gets installed (correct me if I'm wrong). So when RestrictedPython is a dependency of another package (for example Zope2), then pytest-runner gets also installed, even if its only used for tests !
From my point of view stuff which gets installed outside of testing should be as minimal as possible.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A, ok, I think that is a common misunderstanding of setuptools and dependency declaration in Python Eggs.
http://setuptools.readthedocs.io/en/latest/setuptools.html#declaring-dependencies
describe that only install_requires and extra_requires are used, if declared by external packages or pip install. Also only those are reflected in the *.egg-info/requires.txt file.
setup_requires is only evaluated if

python setup.py install

or

python setup.py develop 

is used (--> see http://setuptools.readthedocs.io/en/latest/setuptools.html#new-and-changed-setup-keywords setup_requires).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, thanks for the heads up.
On the pypi page https://pypi.python.org/pypi/pytest-runner they have also a section called

Considerations
Conditional Requirement

to avoid downloading if setup.py is called outside of tests. I'll play around with this at the weekend.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@loechel To my understanding buildout does something like python setup.py install so it will install pytest-runner in projects where RestrictedPython is a dependency. (I have seen this behaviour on other packages which used setup_requires.)

@stephan-hof https://pypi.python.org/pypi/pytest-runner#conditional-requirement looks promising but I did not yet use it anywhere.

@loechel
Copy link
Member Author

loechel commented Feb 28, 2017

@stephan-hof thanks for the review.
The flags and dont_inherit params are something I would like to keep, If I do understand https://docs.python.org/3.6/library/functions.html#compile correct, additional future imports could be added or the inheritance of calling this function is injected.

I could agree that that might be something that we don't want in context of RestrictedPython, but we do want to give the User a drop in Replacement of compile, so that

compile(<source>, filename="<inline>", mode="exec", ...) 

and

from RestrictedPython import compile_restricted as compile
compile(<source>, filename="<inline>", mode="exec", ...) 

works equivalent.

@stephan-hof
Copy link
Member

I get your point, but then the functions in compile.py have to change.
Currently this inheritance is not compatible.
Let's assume the following code in module called test.py

from __future__ import print_function
from RestrictedPython import compile_restricted as compile
compile(<source>, filename="<inline>", mode="exec", ...) 

Even if dont_inhert=False the future is not recognized in the compile_restricted function.
When compile_restricted is called it uses the futures from compile.py not from test.py
See:https://github.com/python/cpython/blob/2.7/Python/ceval.c#L4159

If this inheriting should be compatible with the original compile function something like this needs to be done.

parent_flags = sys._getframe(1).f_code.co_flags
parent_flags = parent_flags & PyCF_MASK
flags = flags | parent_flags

and then call compile with flags=flags and dont_inhert=True to avoid using future flags from compile.py.

Right now the users of RestrictedPython don't need this feature of future inheriting so I would leave it out. Typically the <source> comes from a different component anyway so inheriting the flags where restricted_compile is called could lead to surprising effects.

@stephan-hof
Copy link
Member

@loechel I just realized that the discussion regarding the dont_inherit flag has nothing to do with the current pull request (sorry). I have seen this while looking through the changes so I brought it up.

I still think we should should have the discussion (other opinions are more than welcome), but this should not block merging this pull request.

@loechel
Copy link
Member Author

loechel commented Mar 2, 2017

@stephan-hof I did try to make a reminder on the documentation (93d634b) that we have to look at it.

could somebody ( @stephan-hof or @icemac ) approve this pull request so that it could be merged

Copy link
Member

@stephan-hof stephan-hof left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me

@loechel loechel merged commit 70eca19 into Python3_update Mar 3, 2017
@loechel loechel deleted the compile_tests branch March 3, 2017 14:18
Copy link
Member

@icemac icemac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I am a bit late with my review but I eventually made it through and have some questions.

omit =
src/RestrictedPython/tests
src/RestrictedPython/tests/*.py
tests/*.py
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the tests should have 100 % coverage, too.

@@ -49,7 +49,7 @@

# General information about the project.
project = u'RestrictedPython'
copyright = u'2016, Zope Foundation'
copyright = u'2017, Zope Foundation and Contributors'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be '2016, 2017'.


],
setup_requires=[
'pytest-runner',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@loechel To my understanding buildout does something like python setup.py install so it will install pytest-runner in projects where RestrictedPython is a dependency. (I have seen this behaviour on other packages which used setup_requires.)

@stephan-hof https://pypi.python.org/pypi/pytest-runner#conditional-requirement looks promising but I did not yet use it anywhere.

@@ -57,9 +64,6 @@ def read(*rnames):
'release': [
'zest.releaser',
],
'test': [
'pytest',
],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will break RestrictedPython [test�] when used in buildout. (Do we need it?)
If I remember correctly buildout is not able to handle test_requires. So maybe we should have both using the same list of packages.


def test__limited_range_range_overflow():
with pytest.raises(ValueError):
_limited_range(0, 5000, 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this could be a custom exception derived from ValueError in future to tell the user a bit more about the actual error.

It would be nice here to assert the error text, too.

from RestrictedPython import RestrictingNodeTransformer
from RestrictedPython._compat import IS_PY2
from RestrictedPython._compat import IS_PY3
from RestrictedPython.Guards import guarded_iter_unpack_sequence
from RestrictedPython.Guards import guarded_unpack_sequence
from tests import c_exec
from tests import e_eval
from tests import e_exec
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I liked the relative import here as it makes clear that the code is in __init__.py which is not so clear to me when using tests. But as this is only temporary I do not mind.

@@ -19,14 +19,15 @@ extras =
develop
test
commands =
py.test --cov=src --cov-report=xml {posargs}
py.test --cov=src --cov-report=xml --html=report-{envname}.html --self-contained-html {posargs}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need a n HTML report for each Python environment? What are you trying to achieve?

setenv =
COVERAGE_FILE=.coverage.{envname}
deps =
pytest
pytest-cov
pytest-remove-stale-bytecode
pytest-mock
pytest-html
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are you trying to achieve with this new dependency?

"""
self.not_allowed(node)
return self.node_contents_visit(node)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was only forbidden because there was no test for this method.
Did you write a test for it?

"""
self.not_allowed(node)
return self.node_contents_visit(node)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dito.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants