-
Notifications
You must be signed in to change notification settings - Fork 29
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
Import shared code from ansiblelint #5
Conversation
return Version(version) | ||
|
||
|
||
if ansible_collections_path() in os.environ: |
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.
It's best not to have any import-time code execution. You could use __getattr__()
to make it on-access 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.
If you are talking about https://www.python.org/dev/peps/pep-0562/ that is py37+, so not usable for us.
I am aware of this issue and I plan to refector the library to use a manager that can return property. That would be very useful for other bits inside too. Still, for the moment I will keep the original implementation in this PR.
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's a backport: https://pypi.org/project/pep562/
|
||
def _update_env(varname: str, value: List[str], default: str = "") -> None: | ||
"""Update colon based environment variable if needed. by appending.""" | ||
if value: |
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.
Use a guard expression here.
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.
Excuse my ignorance but could you show me how it should look like? (maybe even include a link an article).
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.
Guard expressions are simple conditionals that interrupt the control flow early. Like "if X: return" or "if Y: continue/break" (for loops).
Typically, when you have something like:
if True:
a huge
indented block
of code
you could dedent that block of code if you just invert that if-conditional expression:
if not True:
return
a huge
indented block
of code
And so this refactoring approach is called "guard expression". It allows you have less highly nested code.
raise RuntimeError(f"Unexpected data read for {key}: {val}") | ||
return val | ||
else: | ||
raise RuntimeError("Unknown data type.") |
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.
Sounds like a LookupError
would be more appropriate here.
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 prefer to keep it like this as it assures that errors are nicely displayed by the consumers. Other exceptions may produce undesired stacktraces. We can debate that later but is better to avoid breaking the current "api".
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 exception is too generic. It's almost the same as just using raise Exception
. You just don't do this.
Besides, you're leaking the implementation details from other abstraction layers.
Normally, you need to communicate exceptions that make sense for this function and not some wrapper that may or may not be there.
Ideally, you have to raise precise narrow exceptions and convert them to other exceptions at outer levels when it makes sense. It's something the caller has enough context to decide upon, not a low-level lib deep in the call stack.
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 want compat with the old API, this could be an optional layer in this repo that some project may temporarily opt-in but it's mustn't be the default because you're shadowing what's happening. Otherwise, you make a dependency on the CLI of other projects while the dependency direction should be different. We shouldn't have cyclic deps.
|
||
for path in paths: | ||
collpath = os.path.join(path, 'ansible_collections', ns, coll) | ||
if os.path.exists(collpath): |
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 loop has a huge potential of using guard expressions
aa9cef3
to
e8ae0cb
Compare
This change should move all the shared code from ansiblelint and allow removed of molecule on ansible-lint. Both with import the code from us.
- change implementation to raise KeyError by default for missing keys - allow setting a default value, including None Follow-Up: #5 (comment)
- change implementation to raise KeyError by default for missing keys - allow setting a default value, including None Follow-Up: #5 (comment)
- change implementation to raise KeyError by default for missing keys - allow setting a default value, including None Follow-Up: #5 (comment)
- change implementation to raise KeyError by default for missing keys - allow setting a default value, including None Follow-Up: #5 (comment)
This change should move all the shared code from ansiblelint and allow removal of molecule dependency on ansible-lint.
Both molecule and ansible-lint with import the code from ansible-compat.
Fixes: #4