Simplify retrieval of cache and config directories#11398
Simplify retrieval of cache and config directories#11398timhoffm merged 3 commits intomatplotlib:masterfrom
Conversation
efiring
left a comment
There was a problem hiding this comment.
I haven't actually tested all this for functionality, but it looks plausible, and the reduction in LOC is nice. Readability needs improvement, even though it will require a few lines of comment and docstring.
| """ | ||
| return a callable function that wraps func and reports its | ||
| output through logger | ||
| def _logged_cached(fmt, func=None): |
There was a problem hiding this comment.
This needs a docstring to explain what it does.
| output through logger | ||
| def _logged_cached(fmt, func=None): | ||
| if func is None: | ||
| return functools.partial(_logged_cached, fmt) |
There was a problem hiding this comment.
I think this needs a comment to explain what it is doing, and how. I read the functools.partial doc, but I'm still completely baffled by these lines. I dimly recollect that you already explained something like this somewhere else, but if so, it didn't stick in my brain.
There was a problem hiding this comment.
Would lambda func: _logged_cached(fmt, func) look better for you? That's basically the same thing.
Or I can even implement the decorator using more nested functions, but I think the flatter pattern is usually preferred.
There was a problem hiding this comment.
It's probably fine the way it is; I'm just looking for a hopefully short comment that will explain it. I suspect the conceptual difficulty comes from the fact that the simpler and more common use of decorators is without arguments. What your usage is doing is first executing the _logged_cashed(fmt) to yield the real decorator function object that gets applied to the func that follows it. That real decorator remembers and can use fmt, and is a function that takes only one argument, which is now 'func', as expected for a decorator. A key point is that the initial function execution to yield the real decorator occurs before the application by the @.
Maybe insert a comment:
if func is None:
# Return the decorator function object.
....Or maybe that is overkill. I think I understand it now, and will probably recognize it in the future; I actually like it. It's just a question of whether a short comment will save someone else some time in understanding how this works. I'm not sure.
There was a problem hiding this comment.
Added a short comment (and at another place where I used the same pattern: cbook._define_aliases).
lib/matplotlib/__init__.py
Outdated
| path = os.path.join(path, '.config') | ||
| return path | ||
| return (os.environ.get('XDG_CONFIG_HOME') | ||
| or (Path(get_home(), ".config") |
There was a problem hiding this comment.
Is there a reason for returning a string in the first case and a Path object in the second? Or is it just that for the way the output is used it doesn't matter, and you like using pathlib instead of os.path?
There was a problem hiding this comment.
It's true that it doesn't matter, but I changed it to return str every time -- there's no reason to be inconsistent.
lib/matplotlib/__init__.py
Outdated
| if sys.platform.startswith(('linux', 'freebsd')) and xdg_base | ||
| else Path(get_home(), ".matplotlib") | ||
| if get_home() | ||
| else None) |
There was a problem hiding this comment.
These chained "one-line" ternaries take a little getting used to... but maybe they are OK in the end.
There was a problem hiding this comment.
I don't find this particularly easy to read either, and I'm not sure what the advantage is other than saving a couple of lines of code.
There was a problem hiding this comment.
Flattened this one. Left the one for _get_xdg_foo_dir as I think they're still more readable(?)
| from matplotlib.testing.exceptions import ImageComparisonFailure | ||
| from matplotlib import _png | ||
| from matplotlib import _get_cachedir | ||
| from matplotlib import _png, cbook |
44aaa1b to
868eeb1
Compare
1. In get_home, we shouldn't check for $TMP, but instead let this case
fall through to _create_config_or_cache_dir.
2. When checking for $XDG_{CONFIG,CACHE}_HOME and $MPLCONFIGDIR,
consider empty strings as equivalent to unset (which is standard
behavior, e.g. one could write `XDG_CONFIG_HOME= python ...` and
expect things to behave as if `XDG_CONFIG_HOME` was indeed unset).
3. The logic in _get_config_or_cache_dir can greatly simplified: try to
create a candidate, generating it on the way if necessary; if it
cannot be created or is not writable, fallback to a temporary
directory.
798f837 to
18da838
Compare
PR Summary
fall through to _create_config_or_cache_dir.
consider empty strings as equivalent to unset (which is standard
behavior, e.g. one could write
XDG_CONFIG_HOME= python ...andexpect things to behave as if
XDG_CONFIG_HOMEwas indeed unset).create a candidate, generating it on the way if necessary; if it
cannot be created or is not writable, fallback to a temporary
directory.
PR Checklist