Repository navigation
Conversation
65a5cdb to
ceb1f4b
Compare
ceb1f4b to
511f10d
Compare
511f10d to
da57261
Compare
akx
left a comment
There was a problem hiding this comment.
This would require tests -- oh and what happens if this finds a pyproject.toml that doesn't have tool.babel?
|
Thanks for the review, I'll spruce up the PR a bit. 🙂 |
a39395c to
af58d33
Compare
max-moser
left a comment
There was a problem hiding this comment.
I've touched up the PR a bit to address your feedback (especially the case when the section is missing from pyproject.toml) and generally touched up the implementation a little bit (with type hints and such).
There's now a test case for the config parsing itself, and one for the extract_messages CLI command that basically emulates what another test did, but with the config coming from pyproject.toml instead of CLI args.
akx
left a comment
There was a problem hiding this comment.
Thanks! Some comments -- this is looking pretty good.
I think we might want a BABEL_NO_PYPROJECT_TOML escape hatch for now?
| """ | ||
| Fixture to create ``${data_dir}/pyproject.toml`` and clean it after the test. | ||
| """ | ||
| pyproject_toml = (pathlib.Path(data_dir) / "pyproject.toml") | ||
| pyproject_toml.touch() | ||
| yield pyproject_toml | ||
| pyproject_toml.unlink() |
There was a problem hiding this comment.
This will cause race conditions when tests are being run in parallel with e.g. pytest-xdist.
See e.g. the pot_file fixture that uses tmp_path - could we do something like that here?
There was a problem hiding this comment.
Hmm... Yeah, I haven't considered running multiple test suites in parallel, only sequentially.
With the current "simply search up the FS hierarchy" strategy as is, I think we're out of luck since any test run would pick up the pyproject.toml.
I'll investigate a mechanism to specify an pyproject.toml file explicitly for pybabel to use; that should then make use of the tmp_path simple.
Maybe that could be combined with your suggestion of BABEL_NO_PYPROJECT_TOML, slightly renamed?
E.g. as an environment variable BABEL_PYPROJECT_TOML that lets the user specify the file to use explicitly, and bails out e.g. if set to 0 or similar?
There was a problem hiding this comment.
It's fine for now, I think. You can just add a # TODO: this will not work in pytest-xdist so we remember it later.
There was a problem hiding this comment.
Ehh, I went ahead and just implemented the combined "alternative search path"/escape hatch via an env var for now.
An alternative would be to add a new optparse option in CommandLineInterface.run()?
It looks like the first bunch of argument parsing happens before we ever touch the pyproject.toml config, and could thus use it to skip it?
The benefit here would be that basically it's documented for free.
The downside is that it's harder to remove later on because that's a much more prominent spot that people may come to rely on.
WDYT?
|
|
||
| def test_parse_pyproject_toml_config_without_pyproject_toml_file(tmp_path): | ||
| """ | ||
| Test that trying to parse the config from a missing ``pyproject.toml`` doesn't crash. |
There was a problem hiding this comment.
This too could fail in the esoteric case that someone has a stray pyproject.toml somewhere in their tmp hierarchy... but maybe we'll take that chance.
2ed7648 to
f3ffa42
Compare
akx
left a comment
There was a problem hiding this comment.
Some comments -- not sure if you're still actively pushing here rn :)
6d4fc79 to
326d912
Compare
326d912 to
44946e2
Compare
|
Done pushing now :) |
b2df682 to
247344d
Compare
akx
left a comment
There was a problem hiding this comment.
Non-exhaustive review, some notes.. 😅
| except ConfigurationError: | ||
| self.log.error("Unable to parse configuration from pyproject.toml!") |
There was a problem hiding this comment.
| except ConfigurationError: | |
| self.log.error("Unable to parse configuration from pyproject.toml!") | |
| except ConfigurationError as ce: | |
| self.log.error("Unable to parse configuration: %s", ce) |
would probably be more useful for users.
There was a problem hiding this comment.
Ah yeah right, I mixed up error() with exception() regarding the exception being printed:
In [6]: try:
...: raise Exception("asdf")
...: except Exception as e:
...: logging.exception("hello")
...:
ERROR:root:hello
Traceback (most recent call last):
File "<ipython-input-6-0b066f494d6a>", line 2, in <module>
raise Exception("asdf")
Exception: asdf
In [7]: try:
...: raise Exception("asdf")
...: except Exception as e:
...: logging.error("hello")
...:
ERROR:root:helloPossibly exception() with the printing of the stack trace would be even handier for tracking down the issue, though likely scarier for non-tech users.
Going with the formatted string in error() for now.
| print(f" {name:<{cmd_width}} {description}") | ||
|
|
||
| def _parse_pyproject_toml_config(self, cmdinst) -> dict: | ||
| pyproject_toml_path_override = os.getenv("BABEL_PYPROJECT_TOML", None) |
There was a problem hiding this comment.
Is this meant to be the TOML filename, or the directory? I think we're handling it as a directory right now.
There was a problem hiding this comment.
Yes right, if somebody specifies a file then it won't be matched in the first iteration of the search.
If the desired file is called pyproject.toml, it will still be found (effectively checking the path.parent / "pyproject.toml"), but if it has a different name (e.g. anothername.toml), that won't be picked up:
In [3]: find_pyproject_toml(Path(".."))
In [4]: find_pyproject_toml(Path("."))
Out[4]: PosixPath('/home/mmoser/git/babel/pyproject.toml')
In [5]: find_pyproject_toml(Path("pyproject.toml"))
Out[5]: PosixPath('/home/mmoser/git/babel/pyproject.toml')
In [6]: find_pyproject_toml(Path("anothername.toml"))
Out[6]: PosixPath('/home/mmoser/git/babel/pyproject.toml')Given that the filename for pyproject.toml is kind of fixed here, I don't think that latter case matters, though.
Would you prefer another name for the env var?
As a side note, checking this, I actually found that a path.resolve() was missing to make path.parent work as expected:
In [7]: Path(".").parent
Out[7]: PosixPath('.')
In [8]: Path(".").parent.parent
Out[8]: PosixPath('.')
In [9]: Path(".").resolve().parent.parent
Out[9]: PosixPath('/home/mmoser')| name = long.strip("=") | ||
| default = getattr(cmdinst, name.replace("-", "_")) | ||
| normalized_name = name.replace("-", "_") | ||
| default = toml_config.get(normalized_name) or getattr(cmdinst, normalized_name) |
If present, use a "pyproject.toml" file for default configuration of `pybabel` commands. Co-authored-by: Aarni Koskela <akx@iki.fi>
The environment variable `BABEL_PYPROJECT_TOML` can be used to set an alternative search path for a "pyproject.toml" file for configuration parsing by setting it to a path. If set to "skip" or "none", the config parsing from pyproject.toml will be disabled altogether. Co-authored-by: Aarni Koskela <akx@iki.fi>
If the user explicitly specified a path for searching pyproject.toml, we assume that they know what they're doing, and we crash loudly.
247344d to
0476dce
Compare
I believe this should close #777
This PR adds support of
pyproject.tomlas a source for default configuration values for the various CLI commands (compile,extract,init,update).The configuration will be read from
pyproject.toml, under the[tool.babel.<command_name>]table, where<command_name>is one ofcompile_catalog,extract_messages,init_catalog,update_catalog(taken fromfrontend_setuptools).The motivation for this PR here is that I've recently migrated most of the
inveniosoftwarepackages fromsetuptoolstohatchlingand we included the old configuration fromsetup.cfginpyproject.toml, only to find thatpybabeldoesn't actually read any command config frompyproject.toml😅(Luckily for us that was only a minor issue in one package that we fixed otherwise)
The mechanism for finding
pyproject.tomlis similar to that used in other tools, likeisort.I could also imagine adding a global CLI flag for disabling reading
pyproject.tomlaltogether, or for letting users specify another TOML config file instead.The parsed values are inserted as default values for the
optparseparser, so user-provided CLI flags should still take precedence.Please let me know if this goes in an acceptable direction, then I can polish up the implementation a bit 🙂