-
-
Notifications
You must be signed in to change notification settings - Fork 504
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
Add pre and post commands #1000
Conversation
@@ -532,6 +542,31 @@ def tox_runtest(venv, redirect): | |||
return True # Return non-None to indicate plugin has completed | |||
|
|||
|
|||
@tox.hookimpl | |||
def tox_runtest_pre(venv): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these should be separate hooks for maximum compatibility with previous plugins implementing these (otherwise this is an added responsibility that every existing plugin that implements tox_runtest_pre
now needs to also do!)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only added responsibility we're implying here is that the venv.status
should be still zero after tox_runtest_pre
. I don't think anyone modified that until now 🤔 So what other responsibilities am I missing? (would prefer not to add new hooks, to pollute our hook namespace even more).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah ok, these aren't firstresult=True
(they maybe should be? hard to say) nevermind this then
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
only the commands are first result 👍 the setup and teardown (pre and post) are not. And makes sense as while we don't want users to execute the command evaluation multiple times; we do want to allow them to setup/teardown their plugin.
78dff35
to
d1d646f
Compare
jfc codecov SETTLE DOWN 😆 |
Codecov Report
@@ Coverage Diff @@
## master #1000 +/- ##
==========================================
- Coverage 69.78% 69.57% -0.22%
==========================================
Files 14 14
Lines 3406 3435 +29
Branches 453 458 +5
==========================================
+ Hits 2377 2390 +13
- Misses 965 980 +15
- Partials 64 65 +1
Continue to review full report at Codecov.
|
cd53fb7
to
08d9d5c
Compare
@asottile While trying to write tests for this and making them pass discovered two feature request that helped me understand what's happening
And two user affecting bugs:
And two internal bugs (thing happened to work by chance, but not by design):
As such this PR became a sort of longer one. However due to the iterative nature of these would be troublesome to split it up. As such I would appreciate to review and merge it as one. |
src/tox/_pytestplugin.py
Outdated
@@ -69,7 +69,7 @@ def cmd(request, capfd, monkeypatch): | |||
request.addfinalizer(py.path.local().chdir) | |||
|
|||
def run(*argv): | |||
key = str(b"PYTHONPATH") | |||
key = b"PYTHONPATH" if six.PY2 else "PYTHONPATH" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"native" string can just be str("PYTHONPATH")
-- though as written is just as explicit and correct
src/tox/_pytestplugin.py
Outdated
@@ -69,7 +69,7 @@ def cmd(request, capfd, monkeypatch): | |||
request.addfinalizer(py.path.local().chdir) | |||
|
|||
def run(*argv): | |||
key = str(b"PYTHONPATH") | |||
key = b"PYTHONPATH" if six.PY2 else "PYTHONPATH" | |||
python_paths = (i for i in (str(os.getcwd()), os.getenv(key)) if i) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, I can't think of a situation where getcwd()
returns non-native string -- I suspect the str(...)
call here is superfluous
try: | ||
ret = res._popen(cmd, **kwargs) | ||
except tox.exception.InvocationError as exception: # pragma: no cover | ||
ret = exception # pragma: no cover |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p3: this no cover comment shouldn't be necessary since the except
block itself is no-covered
|
||
# need to start with an empty (but existing) source distribution folder | ||
if config.distdir.exists(): | ||
config.distdir.remove(rec=1, ignore_errors=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
potential race here (exists check finishes, other process creates), though I suspect it doesn't matter -- though could this just be config.distdir.remove(rec=1, ignore_errors=True)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that was my first solution, until the test started failing; seems rec=1 is only active if the folder exists because of https://github.com/pytest-dev/py/blob/master/py/_path/local.py#L204. Long story short you can only delete if already exists...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤦♂️ :man_gesturing_no: 😭
else: | ||
self.verbosity1(" {}$ {} ".format(popen.cwd, cmd)) | ||
self.verbosity1(" {}$ {} ".format(popen.cwd, cmd_args_shell)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh nice, this is the shlex fix in the output?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah should be 👍
src/tox/venv.py
Outdated
@@ -35,13 +35,13 @@ def writeconfig(self, path): | |||
lines.append("{} {}".format(*dep)) | |||
path.ensure() | |||
path.write("\n".join(lines)) | |||
return lines |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(perhaps I'm not seeing it) is this return value used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indeed not needed 👍
src/tox/venv.py
Outdated
else self.deps == other.deps | ||
) | ||
) | ||
def matches(self, other, deps_matches_subset=False, provide_reason=False): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this function (if annotated) would be Union[Tuple[bool, str], bool]
-- does it make sense to instead have two functions: one without the reason and one with the reason?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to avoid duplication of the logic though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah yeah you can just do:
def whatever_with_reason(...):
return True, 'reason'
def whatever_without_reason(...):
ret, _ = whatever_with_reason(**kwargs)
return ret
or something like that 🤷♂️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, my idea was that only makes the code more type correct; which is not really needed until we implement type annotations (probably once we drop Python 2 and 3.4).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah yeah I guess I didn't put my justifcation, my bad!
It would also be nice so we don't have a boolean trap parameter -- especially until there's enforced keyword-only-arguments in python3 they're a pretty easy pit to fall into in python where you accidentally pass too many positional arguments and it splats over a defaulted keyword argument
name = output.strip() | ||
args = [self.envconfig.envpython, "-c", "import sys; print(sys.path)"] | ||
name = next( | ||
(i for i in output.split("\n") if i and not i.startswith("pydev debugger:")), "" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this left over from a debugging session?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More like a small fixup 👍 Ideally people should be able to run the test suite in debug mode too with pydev (both eclipse and Pycharm). For that to work this is needed.
@@ -107,7 +107,6 @@ branch = true | |||
[coverage:report] | |||
skip_covered = True | |||
show_missing = True | |||
exclude_lines = if __name__ == ["']__main__["']: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah yeah here's what I usually put here:
Made PR feedback; not all should be ok. |
Resolves #167.
Resolves #1003.
Resolves #1004.
Fixup for #987 and #851.
PS. Once we resolve and merge this we'll release
3.4.0
.