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鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add more ruff rules, remove flake8 and black #5039
Conversation
ALPHA = "螒" | ||
BETA = "螔" | ||
ALPHA = "A" | ||
BETA = "B" |
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.
Replacing sneaky Unicode Greek letters with their ASCII equivalents; could also have done a # noqa: RUF01
if we wanted to keep them as-is.
nautobot/core/models/__init__.py
Outdated
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.
flake8-django rules didn't like the order we were declaring Meta
and get_absolute_url()
in BaseModel - surprisingly most of our other models got this "right" already.
nautobot/core/runner/importer.py
Outdated
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.
Removing some sketchy code that really isn't even necessary - it was attempting to "pre-validate" the settings file before actually importing it, but if the settings file is invalid, we still get a perfectly clear error without the removed code.
nautobot/core/tests/test_cli.py
Outdated
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.
Very old code that was not properly implemented for discovery by unittest; I made a few attempts at fixing it to actually run but couldn't get it working properly.
nautobot/extras/models/jobs.py
Outdated
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 appreciate eyes on the TODOs in this file.
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 agree with the TODOs. We shouldn't make these changes now but since django_celery_results is using the JobResult
model we should make sure that changing these fields doesn't break that module.
@@ -305,7 +305,7 @@ def delete(self, *args, **kwargs): | |||
return super().delete(*args, **kwargs) | |||
except ProtectedError as err: | |||
# This will be either IPAddress or Prefix. | |||
protected_instance = tuple(err.protected_objects)[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.
While the justification for this rule makes sense I don't like how difficult it is to read this line. Maybe eventually my brain will learn to associate next(iter(list))
with grabbing the first element of list
..
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.
Agreed - this is one I considered disabling when I ran across it, because the replacement syntax is definitely non-obvious.
Can you add the ruff extension to the |
@@ -127,7 +127,7 @@ def _handle_changed_object(sender, instance, raw=False, **kwargs): | |||
|
|||
# Housekeeping: 0.1% chance of clearing out expired ObjectChanges | |||
changelog_retention = get_settings_or_config("CHANGELOG_RETENTION") | |||
if changelog_retention and random.randint(1, 1000) == 1: | |||
if changelog_retention and secrets.randbelow(1000) == 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.
Looks like the performance impact is minimal (default for timeit is 10k iterations)
>>> timeit.timeit(setup="import random", stmt="random.randint(1, 1000)")
1.0842244539999228
>>> timeit.timeit(setup="import secrets", stmt="secrets.randbelow(1000)")
2.6048511999979382
>>> timeit.timeit(setup="import random", stmt="random.randint(1, 1000)")
1.0478729710011976
>>> timeit.timeit(setup="import secrets", stmt="secrets.randbelow(1000)")
1.6280573209987779
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.
Thank you for checking me on this!
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.
Hopefully this particular code is not long for this world in any case... :-)
Co-authored-by: Gary Snider <75227981+gsnider2195@users.noreply.github.com>
@@ -12,11 +12,6 @@ | |||
from .settings import load_settings, create_module | |||
|
|||
|
|||
def execfile(afile, globalz=None, localz=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.
Can you add some context to the PR for the changes made in this file?
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 did in #5039 (comment), looks like file-level comments don't carry over in the GitHub UI when the file changes. :-/
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 see now. Do we still get a valid error with an invalid EXTRA_INSTALLED_APPS
or EXTRA_MIDDLEWARE
without this 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.
Invalid would be like the wrong data type (dict instead of list, that sort of thing)? I'd tested earlier with a syntax error in the nautobot_config.py and that seemed fine, but I'm open to doing additional 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.
Wrong data type, or a non-existent python library (for EXTRA_INSTALLED_APPS
). Just want to make sure you captured the EXTRA_
settings that this custom importer is providing.
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.
With EXTRA_INSTALLED_APPS = ["hello world"]
:
nautobot-nautobot-1 | Traceback (most recent call last):
nautobot-nautobot-1 | File "/usr/local/bin/nautobot-server", line 6, in <module>
nautobot-nautobot-1 | sys.exit(main())
nautobot-nautobot-1 | File "/source/nautobot/core/cli/__init__.py", line 53, in main
nautobot-nautobot-1 | run_app(
nautobot-nautobot-1 | File "/source/nautobot/core/runner/runner.py", line 297, in run_app
nautobot-nautobot-1 | management.execute_from_command_line([runner_name, command, *command_args])
nautobot-nautobot-1 | File "/usr/local/lib/python3.8/site-packages/django/core/management/__init__.py", line 419, in execute_from_command_line
nautobot-nautobot-1 | utility.execute()
nautobot-nautobot-1 | File "/usr/local/lib/python3.8/site-packages/django/core/management/__init__.py", line 395, in execute
nautobot-nautobot-1 | django.setup()
nautobot-nautobot-1 | File "/usr/local/lib/python3.8/site-packages/django/__init__.py", line 24, in setup
nautobot-nautobot-1 | apps.populate(settings.INSTALLED_APPS)
nautobot-nautobot-1 | File "/usr/local/lib/python3.8/site-packages/django/apps/registry.py", line 91, in populate
nautobot-nautobot-1 | app_config = AppConfig.create(entry)
nautobot-nautobot-1 | File "/usr/local/lib/python3.8/site-packages/django/apps/config.py", line 224, in create
nautobot-nautobot-1 | import_module(entry)
nautobot-nautobot-1 | File "/usr/local/lib/python3.8/importlib/__init__.py", line 127, in import_module
nautobot-nautobot-1 | return _bootstrap._gcd_import(name[level:], package, level)
nautobot-nautobot-1 | File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
nautobot-nautobot-1 | File "<frozen importlib._bootstrap>", line 991, in _find_and_load
nautobot-nautobot-1 | File "<frozen importlib._bootstrap>", line 973, in _find_and_load_unlocked
nautobot-nautobot-1 | ModuleNotFoundError: No module named 'hello world'
With EXTRA_INSTALLED_APPS = {"hello": "world"}
:
nautobot-nautobot-1 | Traceback (most recent call last):
nautobot-nautobot-1 | File "/usr/local/bin/nautobot-server", line 6, in <module>
nautobot-nautobot-1 | sys.exit(main())
nautobot-nautobot-1 | File "/source/nautobot/core/cli/__init__.py", line 53, in main
nautobot-nautobot-1 | run_app(
nautobot-nautobot-1 | File "/source/nautobot/core/runner/runner.py", line 297, in run_app
nautobot-nautobot-1 | management.execute_from_command_line([runner_name, command, *command_args])
nautobot-nautobot-1 | File "/usr/local/lib/python3.8/site-packages/django/core/management/__init__.py", line 419, in execute_from_command_line
nautobot-nautobot-1 | utility.execute()
nautobot-nautobot-1 | File "/usr/local/lib/python3.8/site-packages/django/core/management/__init__.py", line 395, in execute
nautobot-nautobot-1 | django.setup()
nautobot-nautobot-1 | File "/usr/local/lib/python3.8/site-packages/django/__init__.py", line 24, in setup
nautobot-nautobot-1 | apps.populate(settings.INSTALLED_APPS)
nautobot-nautobot-1 | File "/usr/local/lib/python3.8/site-packages/django/apps/registry.py", line 91, in populate
nautobot-nautobot-1 | app_config = AppConfig.create(entry)
nautobot-nautobot-1 | File "/usr/local/lib/python3.8/site-packages/django/apps/config.py", line 224, in create
nautobot-nautobot-1 | import_module(entry)
nautobot-nautobot-1 | File "/usr/local/lib/python3.8/importlib/__init__.py", line 127, in import_module
nautobot-nautobot-1 | return _bootstrap._gcd_import(name[level:], package, level)
nautobot-nautobot-1 | File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
nautobot-nautobot-1 | File "<frozen importlib._bootstrap>", line 991, in _find_and_load
nautobot-nautobot-1 | File "<frozen importlib._bootstrap>", line 973, in _find_and_load_unlocked
nautobot-nautobot-1 | ModuleNotFoundError: No module named 'hello'
Looks like the same stack trace I get in develop
in both cases -- which makes sense as I think about it, since all the removed code was doing was checking whether the config file could be imported, not whether it's actually semantically valid.
With a syntax error in the config file, develop
gives:
nautobot-nautobot-1 | Traceback (most recent call last):
nautobot-nautobot-1 | File "/source/nautobot/core/runner/importer.py", line 72, in validate
nautobot-nautobot-1 | execfile(self.config_path, {"__file__": self.config_path})
nautobot-nautobot-1 | File "/source/nautobot/core/runner/importer.py", line 17, in execfile
nautobot-nautobot-1 | exec(fh.read(), globalz, localz)
nautobot-nautobot-1 | File "<string>", line 74
nautobot-nautobot-1 | EXTRA_INSTALLED_APPS = {
nautobot-nautobot-1 | ^
nautobot-nautobot-1 | SyntaxError: unexpected EOF while parsing
nautobot-nautobot-1 |
nautobot-nautobot-1 | During handling of the above exception, another exception occurred:
nautobot-nautobot-1 |
nautobot-nautobot-1 | Traceback (most recent call last):
nautobot-nautobot-1 | File "/usr/local/bin/nautobot-server", line 6, in <module>
nautobot-nautobot-1 | sys.exit(main())
nautobot-nautobot-1 | File "/source/nautobot/core/cli/__init__.py", line 53, in main
nautobot-nautobot-1 | run_app(
nautobot-nautobot-1 | File "/source/nautobot/core/runner/runner.py", line 292, in run_app
nautobot-nautobot-1 | configure_app(config_path=config_path, **kwargs)
nautobot-nautobot-1 | File "/source/nautobot/core/runner/runner.py", line 131, in configure_app
nautobot-nautobot-1 | importer.install(
nautobot-nautobot-1 | File "/source/nautobot/core/runner/importer.py", line 37, in install
nautobot-nautobot-1 | sys.meta_path.insert(0, LoganImporter(name, config_path, default_settings, **kwargs))
nautobot-nautobot-1 | File "/source/nautobot/core/runner/importer.py", line 63, in __init__
nautobot-nautobot-1 | self.validate()
nautobot-nautobot-1 | File "/source/nautobot/core/runner/importer.py", line 75, in validate
nautobot-nautobot-1 | raise ConfigurationError(str(e), exc_info[2])
nautobot-nautobot-1 | nautobot.core.runner.importer.ConfigurationError: ('unexpected EOF while parsing (<string>, line 74)', <traceback object at 0x7fd1a1519340>)
while this branch instead gives:
nautobot-nautobot-1 | Traceback (most recent call last):
nautobot-nautobot-1 | File "/usr/local/bin/nautobot-server", line 6, in <module>
nautobot-nautobot-1 | sys.exit(main())
nautobot-nautobot-1 | File "/source/nautobot/core/cli/__init__.py", line 53, in main
nautobot-nautobot-1 | run_app(
nautobot-nautobot-1 | File "/source/nautobot/core/runner/runner.py", line 292, in run_app
nautobot-nautobot-1 | configure_app(config_path=config_path, **kwargs)
nautobot-nautobot-1 | File "/source/nautobot/core/runner/runner.py", line 145, in configure_app
nautobot-nautobot-1 | hasattr(settings, "INSTALLED_APPS")
nautobot-nautobot-1 | File "/usr/local/lib/python3.8/site-packages/django/conf/__init__.py", line 82, in __getattr__
nautobot-nautobot-1 | self._setup(name)
nautobot-nautobot-1 | File "/usr/local/lib/python3.8/site-packages/django/conf/__init__.py", line 69, in _setup
nautobot-nautobot-1 | self._wrapped = Settings(settings_module)
nautobot-nautobot-1 | File "/usr/local/lib/python3.8/site-packages/django/conf/__init__.py", line 170, in __init__
nautobot-nautobot-1 | mod = importlib.import_module(self.SETTINGS_MODULE)
nautobot-nautobot-1 | File "/usr/local/lib/python3.8/importlib/__init__.py", line 127, in import_module
nautobot-nautobot-1 | return _bootstrap._gcd_import(name[level:], package, level)
nautobot-nautobot-1 | File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
nautobot-nautobot-1 | File "<frozen importlib._bootstrap>", line 991, in _find_and_load
nautobot-nautobot-1 | File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
nautobot-nautobot-1 | File "<frozen importlib._bootstrap>", line 655, in _load_unlocked
nautobot-nautobot-1 | File "<frozen importlib._bootstrap>", line 618, in _load_backward_compatible
nautobot-nautobot-1 | File "/source/nautobot/core/runner/importer.py", line 115, in load_module
nautobot-nautobot-1 | load_settings(self.config_path, allow_extras=self.allow_extras, settings=settings_mod)
nautobot-nautobot-1 | File "/source/nautobot/core/runner/settings.py", line 47, in load_settings
nautobot-nautobot-1 | spec.loader.exec_module(conf)
nautobot-nautobot-1 | File "<frozen importlib._bootstrap_external>", line 839, in exec_module
nautobot-nautobot-1 | File "<frozen importlib._bootstrap_external>", line 976, in get_code
nautobot-nautobot-1 | File "<frozen importlib._bootstrap_external>", line 906, in source_to_code
nautobot-nautobot-1 | File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
nautobot-nautobot-1 | File "/opt/nautobot/nautobot_config.py", line 78
nautobot-nautobot-1 | EXTRA_INSTALLED_APPS = {
nautobot-nautobot-1 | ^
nautobot-nautobot-1 | SyntaxError: unexpected EOF while parsing
which I actually think is an improvement?
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.
Agreed that it's an improvement. I'm happy with it, thanks for testing that out.
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 like some more background on the changes made in nautobot/core/runner/importer.py
but otherwise I think this is a big performance improvement and I don't see any loss of functionality from flake8/black. Great stuff!
Closes: n/a
What's Changed
ruff
development dependency to~0.1.10
(latest as of today)ruff format
toinvoke ruff
task (before we were only doingruff check
;ruff format
replacesblack
)black
andflake8
as development dependencies as they're fully replaced byruff
now.black
andflake8
steps from CI.DJ
Ruff rules (flake8-django
) and addressed all warnings raised.PIE
Ruff rules except forPIE808
(flake8-pie
) and addressed all warnings raised.range(0, n)
as it's technically redundant with simplyrange(n)
, but personally I prefer the clarity of the former style.RUF
Ruff native rules except forRUF012
(which results in a lot of noise, see also RUF012 triggers many false positives (are they really? they are correct) in some projects聽astral-sh/ruff#5243) and addressed all warnings raised.S
Ruff rules (flake8-bandit
) and addressed all warnings raised.If this gets accepted and merged, I can open a sequel PR to remove
isort
(which is included as a dev dependency, but not actually run by our CI presently) and enable its equivalent rules in ruff; I've already done the work locally but it results in a lot more diffs and I wanted to keep this PR from being too unmanageable to review. 馃榾TODO