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

Added class attribute Patcher.patch_path #130

Merged
merged 2 commits into from
Oct 9, 2016

Conversation

mrbean-bremen
Copy link
Member

- can be set to False to avoid patching 'path' (see pytest-dev#53)
- added optional argument to TestCase constructor to set it
@mrbean-bremen
Copy link
Member Author

@jmcgeheeiv: Please check if this sufficient for #53.

Copy link
Contributor

@jmcgeheeiv jmcgeheeiv left a comment

Choose a reason for hiding this comment

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

This needs a test. Perhaps instead of creating an actual file, you could simply set sys.modules['path'] = None and test whether Patcher changes it.

"""Creates the test class instance and the stubber used to stub out file system related modules.

Args:
methodName: the name of the test method (as in unittest.TestCase)
additional_skip_names: names of modules inside of which no module replacement shall be done
(additionally to the hard-coded list: 'os', 'glob', 'path', 'tempfile', 'io')
path_path: if set to False, 'path' modules will not be stubbed out, and 'path' will be
Copy link
Contributor

@jmcgeheeiv jmcgeheeiv Oct 8, 2016

Choose a reason for hiding this comment

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

patch_path, not path_path

"""Creates the test class instance and the stubber used to stub out file system related modules.

Args:
methodName: the name of the test method (as in unittest.TestCase)
additional_skip_names: names of modules inside of which no module replacement shall be done
(additionally to the hard-coded list: 'os', 'glob', 'path', 'tempfile', 'io')
path_path: if set to False, 'path' modules will not be stubbed out, and 'path' will be
Copy link
Contributor

@jmcgeheeiv jmcgeheeiv Oct 8, 2016

Choose a reason for hiding this comment

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

The usage of patch_path is rather obscure, so let's explain the hell out of it:

            patch_path: if False, modules named 'path' will not be patched with the fake 'os.path' module.
               Set this to False when you need to import some other module named 'path', for example,
                   from my_module import path
               Irrespective of patch_path, module 'os.path' is still correctly faked if imported the usual way
               using 'import os' or 'import os.path'.

Repeat this explanation in the docstring for Patcher.

@@ -88,6 +90,9 @@ def __init__(self, methodName='runTest'):
super(TestCase, self).__init__(methodName)
if additional_skip_names is not None:
Patcher.SKIPNAMES.update(additional_skip_names)
if not patch_path:
Patcher.patch_path = True
Patcher.SKIPNAMES.remove('path')
Copy link
Contributor

@jmcgeheeiv jmcgeheeiv Oct 8, 2016

Choose a reason for hiding this comment

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

Reaching inside Patcher like this breaks encapsulation for Patcher. Make patch_path an optional argument to Patcher, thus hiding the implementation details within Patcher.

Then again, using instance methods like __init__() to change class attributes like Patcher.SKIPNAMES means that one instance can change the behavior of other Patcher instances. This is bad.

For backward compatability, we must retain class attribute Patcher.SKIPNAMES, so perhaps add an instance attribute self.skipnames = set(self.SKIPNAMES), then conditionally discard 'path' from self.skipnames.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, I didn't like this either. I will have another go at this tomorrow, if I find the time, or next week.

@@ -178,7 +189,7 @@ def _findModules(self):
continue
if 'os' in module.__dict__:
self._osModules.add(module)
if 'path' in module.__dict__:
if self.patch_path and 'path' in module.__dict__:
Copy link
Contributor

@jmcgeheeiv jmcgeheeiv Oct 8, 2016

Choose a reason for hiding this comment

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

Redundant. Is attribute patch_path is needed at all?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is the actual check for the replacement of the path module - the removal from SKIPNAMES may or may not be needed additionally.

@@ -88,6 +90,9 @@ def __init__(self, methodName='runTest'):
super(TestCase, self).__init__(methodName)
if additional_skip_names is not None:
Patcher.SKIPNAMES.update(additional_skip_names)
if not patch_path:
Patcher.patch_path = True
Patcher.SKIPNAMES.remove('path')
Copy link
Contributor

@jmcgeheeiv jmcgeheeiv Oct 8, 2016

Choose a reason for hiding this comment

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

Use set.discard() so that repeated removals will not raise an exception.

@@ -134,6 +139,12 @@ class Patcher(object):
# it appears that adding 'py', 'pytest', '_pytest' to SKIPNAMES will help
SKIPNAMES = set(['os', 'path', 'tempfile', 'io'])

# To avoid stubbing out path because another top=level module named path is present
Copy link
Contributor

@jmcgeheeiv jmcgeheeiv Oct 8, 2016

Choose a reason for hiding this comment

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

I incorporated this excellent explanation into the patch_path docstring above.

- use instance instead of class attributes
- enhanced documentation
- added test
@mrbean-bremen
Copy link
Member Author

@jmcgeheeiv: Please check if the changes and the test are ok,

@jmcgeheeiv jmcgeheeiv merged commit b4380f5 into pytest-dev:master Oct 9, 2016
@jmcgeheeiv
Copy link
Contributor

jmcgeheeiv commented Oct 9, 2016

Fixed #53.

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.

None yet

2 participants