-
Notifications
You must be signed in to change notification settings - Fork 8
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
New plugin version for tox 4 #42
Conversation
parser.add_argument( | ||
"--print-deps-to", | ||
"--print-deps-to-file", | ||
action="store", | ||
type=argparse.FileType("w"), | ||
metavar="FILE", | ||
default=False, | ||
help="Don't run tests, only print the dependencies to the given file " | ||
+ "(use `-` for stdout)", | ||
) | ||
parser.add_argument( | ||
"--print-extras-to", | ||
"--print-extras-to-file", | ||
action="store", | ||
type=argparse.FileType("w"), | ||
metavar="FILE", | ||
default=False, | ||
help="Don't run tests, only print the names of the required extras to the given file " | ||
+ "(use `-` for stdout)", |
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 sounds to me like would live better as a subcommand rather than a flag. You can still support this for backwards compatibility via the legacy shims, so you'd need to register these flags for the legacy parser too https://github.com/tox-dev/tox/blob/rewrite/src/tox/session/cmd/legacy.py
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.
Do I understand it correctly that when registered for legacy parsers, you have to call tox le --print-deps-to -
instead of the old tox --print-deps-to -
? That's a way we can use to support the old API but it not 100% identical.
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.
If you don't specify a sub-command the legacy endpoint defaults, so in this sense it's backwards compatible...
src/tox_current_env/hooks4.py
Outdated
super().__init__(create_args) | ||
|
||
# As soon as this environment has enough info to do its job, | ||
# do it and nothing more. | ||
|
||
if self.options.print_deps_to: | ||
print( | ||
*self.core["requires"], | ||
*self.conf["deps"].lines(), | ||
sep="\n", | ||
file=self.options.print_deps_to, | ||
) | ||
self.options.print_deps_to.flush() | ||
|
||
if self.options.print_extras_to: | ||
if "extras" not in self.conf: | ||
# Unfortunately, if there is skipsdist/no_package or skip_install | ||
# in the config, this section is not parsed at all so we have to | ||
# do it here manually to be able to read its content. | ||
self.conf.add_config( | ||
keys=["extras"], | ||
of_type=Set[str], | ||
default=set(), | ||
desc="extras to install of the target package", | ||
) | ||
print( | ||
*self.conf["extras"], | ||
sep="\n", | ||
file=self.options.print_extras_to, | ||
) | ||
self.options.print_extras_to.flush() | ||
|
||
# We are done | ||
sys.exit(0) |
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 is incorrect. This should be a new sub-command. We don't support calling sys.exit, and this will likely be a no-op when called with -p.
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.
If you don't want to make it a subcommand a better alternative would be to set commands to empty array via a memory loader and then do this within https://tox.wiki/en/rewrite/plugins.html#tox.plugin.spec.tox_before_run_commands
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'll probably do both things. We want to keep the stable API so I clear the list of commands and do this in the tox_before_run_commands
and I'll also prepare new subcommand. We can then deprecate the old CLI options and stay with subcommands only.
Thanks for the valuable feedback! We have to discuss some parts in the team because we use this plugin in |
Thing to double-check: If |
After a few more hours of testing, I think I have the final version. I'm testing it with all packages from Fedora where Failed builds are mostly caused by broken or insufficient dependencies. setuptools_scm fails because expects a different output from tox. I had to:
I'd like to implement the same logic using subcommands which will be backward incompatible but ready to use when we'll have tox4 everywhere. But the core of the logic here is ready for review. I'm not sure it makes sense to invest time in making tests ready for the new version given the fact that the outputs might change and we are still in alpha. |
Let's circle back in a few weeks, I have one big refactor in the works, before cutting a beta release. |
Maybe this needs to be reported as a tox regression? |
Oh, not the real setuptools_scm from Fedora, but the one with internal checks for our macros. We can adapt that later. All is 🌈 🦄 |
src/tox_current_env/hooks4.py
Outdated
f"{sys.version_info.major}.{sys.version_info.minor}", | ||
): | ||
os.symlink(sys.executable, Path(self.tempdir.name) / f"python{suffix}") | ||
os.environ["PATH"] = ":".join((os.environ["PATH"], str(self.tempdir.name))) |
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.
Do we need to change the actual os.environ
? Is there no tox internal environ/path to change?
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.
There is an internal one but to change it it'd IMO need to override some more classes in the hierarchy and create our own executor which would change the path before it creates its instance. Do you think it's worth it?
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've accomplished this without altering os.environ. See the last commit. The problem, however, is that the new PATH is not propagated to all new processes so tox runs the correct Python (via the symlink in the temp directory) but if I have another python subprocesses in my tests, those will not see the altered PATH. Therefore I'd keep the old behavior and restore the original PATH in the _teardown method. What do you think?
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 that propagating that path to all-new subprocesses is a must, but setting it vis os.environ won't propagate it either, will it? It is a matter of how is the inner subprocess invoked. Or what am I not getting? How does request.env
work? Could you give me an example where the inner subprocess does not respect request.env
but respects the os.enviorn
value set from our code?
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.
And if we indeed end up manipulating os.environ
I think we should maximally limit the scope of that by e.g. using a context manager in <ExecutorClass>.call()
implementation rather than setting it globally when we build the instance.
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.
Manipulating the os.environ is definitely not right, for one would break parallel mode.
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.
My bad, it was a problem in my testing environment. The current way propagates the PATH to the subprocesses correctly.
Manipulating the os.environ is definitely not right, for one would break parallel mode.
Our plugin causes tests to run only in one environment. @hroncok why should we care about parallel mode?
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.
If you only intend to use it for Fedora sure. But perhaps other people might want to use this for different use cases to use the host Python interpreter where this might be required. It really depends on how you want to scope this project.
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.
Even in Fedora, we might be able to run multiple tox environments in parallel.
There are some changes I need to accommodate here but the fixes should be pretty easy so I'm gonna start with testing soon. https://github.com/tox-dev/tox/blob/rewrite/docs/changelog.rst#v400b1-2022-02-05 |
So, make the plugin compatible with the latest release was quite easy but now we have a strange bug. With this very simple config:
If I use current env to actually run tests, it runs only specified environment:
But when I want it to print out the dependencies, it runs all the environments which produces this:
I did a test and it seems that all environments are initialized even only one is specified to run. That's problem for our implementation not just because of the mentioned bug but also because our @gaborbernat is this correct and expected behavior and we should adapt to it or is it a bug? |
This is expected, but something I'm not happy with, and actually would love some input on it. However, could not find a better way to solve it. The problem at hand is that if someone specifies the following command [tox]
wheel_build_env = alpha
[testenv]
package = wheel
wheel_build_env = alpha The only way to know that alpha is a valid target is to build all environments and then check that was not defined something other than run environment. Just reading the configuration file is not enough because the packaging environment is generated dynamically by reading the config flags; therefore to find out if a tox environment is a valid target we must build all tox environments upfront. This is what we do currently, but this does have the overhead of constructing a lot of environments we will end up not using (can make tox invocations slow when you have a lot of environments defined). Also does mean that all tox plugins environment build creation should be a NOOP. Busy work should be done inside the run environment section. The only other alternative I could think of was to make everything lazy but end up with a non stable behaviour, as in consider the following configuration: [testenv:magic]
package = wheel
wheel_build_env = alpha
|
I've squashed some. And I was hit by the xdist pip cache problem, so I added a workaround. I like where this stands now. Let me check the following things:
|
I see several options to handle the TOX_TESTENV_PASSENV situation:
In Fedora's WDYT? |
I see several of the tests missing.
|
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 have a few questions 🤔
|
||
# No options used - switch back to the standard runner | ||
# Workaround for: https://github.com/tox-dev/tox/issues/2264 | ||
opt.default_runner = "virtualenv" |
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 has been fixed upstream so can be removed?
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 issue was closed but I don't see any indication it was fixed. I understood the close more or less as "this is how it works". Did I get that wrong?
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.
What about tox-dev/tox#2305 that's linked in the issue?
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 must have missed that one. We need to check.
env_conf.loaders.insert(0, empty_commands) | ||
|
||
|
||
class Installer: |
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.
You should inherit from tox abc installer rather than define your own...
out, | ||
err, | ||
): | ||
request.env["PATH"] = ":".join( |
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 seems like a bad approach to me, why not set this via set_env instead? This works but is ugly and not used as intended 🤔 Also does not work on Windows?
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.
FWIW We don't support Windows. If Windows user supply PRs we gladly review them but that's it.
# Unfortunately, if there is skipsdist/no_package or skip_install | ||
# in the config, this section is not parsed at all so we have to | ||
# do it here manually to be able to read its content. | ||
self.conf.add_config( |
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.
Why do you need this if skipsdist/no_package?
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.
Because we need to get the information if specified. I guess defining extras together with skipsdist/no_package is invalid -- does it raise an error?
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.
Because we need to get the information if specified. I g
Why?
I guess defining extras together with skipsdist/no_package is invalid -- does it raise an error?
It's not invalid, but there's no package involved in these cases, so there's no target to find extras for?
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.
Becasu the purpose of the --print-extras-to
option is to get the list of extras so we can gather the requirements for tests and install them via dnf in rpm build environment.
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.
Becasu the purpose of the
--print-extras-to
option is to get the list of extras so we can gather the requirements for tests and install them via dnf in rpm build environment.
It sounds like you want to execute a tox deps -e py310
that would print the dependencies, taking into consideration the extras specified for the env.
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.
Pep-621 projects can be determined without building a wheel, but otherwise you'd need to build wheel or use the metadata hook to determine extras, no?
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 is exactly why we just want the list of extras from tox. We are building the wheel/metadata elsewhere differently and will use the list of extras extracted from tox. I.e. we don't want tox to build the wheel/metadata and provide the specific dependencies, we just need the list of extras specified in the config.
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.
For that, you could use:
tox c -k extras
and parse it within an INI parser?
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 way, you would not miss changes to the extra parse we're adding, e.g. tox-dev/tox#2668; and is the more supported way of reading tox configuration.
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.
Yes, that seems possible, unless the tox configuration changes. Whether or not the extras are normalized does not matter to us, we normalize them anyway.
return sys.platform | ||
|
||
|
||
class PrintEnv(CurrentEnv): |
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.
What is this trying to achieve?
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 environment or the inheritance?
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 entire class 🤔 not sure what's its goal is.
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 goal of this class is to provide an implementation for options that print information about deps and extras rather thane execute tests.
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 it would be better served by a deps
sub-command 😊 as part of the core.
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 we could deprecate this option then, but for now, we need to maintain compatible behavior between the tox plugin for tox 3 and 4. (In the above thread I continue to discuss how to use this option at all.)
Initial implementation of the plugin for the new tox version 4. It works for me but I have tested it only for one simple project yet.
Notes, questions:
--print-*
options because there is no summary and congratulations.ToDo:
%tox
macro in FedoraFixes #41