-
Notifications
You must be signed in to change notification settings - Fork 437
Add tox replacement #1558
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 tox replacement #1558
Conversation
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.
from a high level, I like it.
Like we discussed before, this style syntax feels more verbose looking than the normal tox redis_contrib_py{27,35,36,37,38}-redis{21,20,32,34,35}
env definition but think it is much more clear what is going on, less jumping around a massive file.
I think any other nit-picks I had (not specified) will be solved when this is it's own module/package.
riot.py
Outdated
pkgs=[ | ||
("django-pylibmc", [">=0.6,<0.7"]), | ||
("django-redis", [">=4.5,<4.6"]), | ||
("pylibmc", [""]), |
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 wonder if we should alias "latest" -> ""
would it make it more clear to read?
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.
or just latest = ""
-> ("pylibmc", [latest])
. Either way I think we're in agreement that "" is kinda subtle.
riot.py
Outdated
"""Return the command string used to execute `cmd` in virtual env located | ||
at `venv_path`. | ||
""" | ||
return "source %s/bin/activate && %s" % (venv_path, cmd) |
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 probably don't have to call source
. If you read through activate
majority of it is setting up deactivate
, and then setting a few environment variables:
export VIRTUAL_ENV=<path_to_venv>
export PATH=<venv>/bin:$PATH
unset PYTHONHOME
And that is in.
In fact, you can generally get by just calling from <venv>/bin/<cmd>
directly without modifying any env variables and it'll work as expected.
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.
Calling source .../bin/activate
is probably the right thing to 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.
Ok so I'm a bit surprised by this but it looks definitely good.
I think it needs a few more iteration and polish, but this is a really good starting point to do something cool.
We might want to polish the architecture a bit, using a few classes here and there — and maybe some docstrings.
.circleci/config.yml
Outdated
default: "" | ||
steps: | ||
- checkout | ||
- run: pip3 install virtualenv # TODO: this can be baked into the image |
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.
Though the image is not updated that often, so it might be better to have the latest virtualenv
deployed each time.
- run_tox_scenario: | ||
pattern: '^py..-profile' | ||
- run_test: | ||
pattern: "profiling" |
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.
detail, but you don't need the ""
I think
riot.py
Outdated
|
||
|
||
# It's easier to read `Suite`, `Case` rather than AttrDict or dict. | ||
CaseInstance = Case = Suite = AttrDict |
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.
Having custom classes such as:
class Case(AttrDict): pass
Is going to be a little bit better when introspecting or debugging.
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.
yepyepyep definitely, a lot of the functions laying around are really "methods" as well. This is purely just a result of iterating a ton and not wanting to deal with class boilerplate 🙂
riot.py
Outdated
|
||
ref: https://www.python.org/dev/peps/pep-0508/ | ||
""" | ||
return "%s%s" % (libname, version) |
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.
return "%s%s" % (libname, version) | |
return f"{libname}{version}" |
;)
riot.py
Outdated
def get_env_str(envs: t.List[t.Tuple]): | ||
return " ".join("%s=%s" % (k, v) for k, v in envs) |
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.
def get_env_str(envs: t.List[t.Tuple]): | |
return " ".join("%s=%s" % (k, v) for k, v in envs) | |
def get_env_str(envs: t.List[t.Tuple]): | |
return " ".join(f"{k}={v}" for k, v in envs) |
riot.py
Outdated
yield case, env_cfg, py, pkg_cfg | ||
|
||
|
||
def suites_iter(suites, pattern, py=None): |
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 feel like that this could be a little more organized by using classes.
riot.py
Outdated
# Copy the base venv to use for this case. | ||
logger.info("Copying base virtualenv '%s' into case virtual env '%s'.", base_venv, venv) | ||
try: | ||
run_cmd(["cp", "-r", base_venv, venv], stdout=subprocess.PIPE) |
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'd use shutil.copytree
instead?
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.
Originally had it but it won't allow you to overwrite a directory if it already exists.
riot.py
Outdated
s = "%s %s: %s python%s %s" % (status_char, r.case.suite.name, env_str, r.case.py, r.pkgstr) | ||
print(s, file=out) | ||
|
||
if any(True for r in results if r.code != 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.
if any(True for r in results if r.code != 0): | |
if any(r.code != 0 for r in results): |
242c390
to
43e6f58
Compare
Tox is slow and the configuration language is unwieldy with our use case.
This PR introduces a custom solution that aims to provide a better specified and more optimized solution for running our matrix of tests.
Preliminary results (without pre-generating and sharing base virtual envs, which could save about 2m in the best case):
tracer
: 33m 8s -> 6m 41s (79.8% reduction)django
: 45m 34s -> 18m 38s (59.1% reduction)redis
22m 9s -> 4m 55s (77.8% reduction)Configuration Example (Django)
Equivalent in tox:
Configuration Example (Profiling)
Configuration is done in Python.
equivalent tox configuration: