Skip to content

Commit

Permalink
Enabled more lint rules, notably flake8-pytest (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
zsimic authored Mar 5, 2024
1 parent b4b9c59 commit b4f1d78
Show file tree
Hide file tree
Showing 36 changed files with 286 additions and 333 deletions.
29 changes: 14 additions & 15 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,21 @@ extend-select = [
"INT", # flake8-gettext
"PGH", # pygrep-hooks
"PIE", # flake8-pie
# "PT", # flake8-pytest
# "PYI", # flake8-pyi
# "Q", # flake8-quotes
# "RSE", # flake8-raise
"PT", # flake8-pytest
"PYI", # flake8-pyi
"Q", # flake8-quotes
"RSE", # flake8-raise
# "RET", # flake8-return
## "RUF", # ruff-specific
## "S", # flake8-bandit
## "SIM", # flake8-simplify
## "SLF", # flake8-self
# "SLOT", # flake8-slots
# "T10", # flake8-debugger
# "TID", # flake8-tidy-imports
# "TCH", # flake8-type-checking
## "TD", # flake8-todos
## "TRY", # tryceratops
# "W", # pycodestyle warnings
"RUF", # ruff-specific
# "SIM", # flake8-simplify
# "SLF", # flake8-self
"SLOT", # flake8-slots
"T10", # flake8-debugger
"TID", # flake8-tidy-imports
"TCH", # flake8-type-checking
"TD", # flake8-todos
# "TRY", # tryceratops
"W", # pycodestyle warnings
]

[tool.ruff.lint.isort]
Expand Down
4 changes: 3 additions & 1 deletion src/runez/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def cmd_import_speed():

table = PrettyTable("Module,-X cumulative,Elapsed,Vs fastest,Note", border=args.border)
table.header[3].align = "center"
mid = _get_mid(times) or 0
mid = _get_mid(times)
for t in sorted(times):
if t.cumulative is None:
c = e = f = None
Expand Down Expand Up @@ -201,6 +201,8 @@ def _get_mid(times):
times = sorted(times, key=lambda x: -x.elapsed) # Don't fail if no elapsed available
return times[int(len(times) / 2)].elapsed

return 0


def main():
runez.cli.run_cmds()
Expand Down
2 changes: 1 addition & 1 deletion src/runez/ascii.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def af_dotrot3(cls):
@classmethod
def af_fill(cls):
"""Bar growing/shrinking vertically, then horizontally"""
return AsciiFrames([" "] + cls.symmetrical(list("▁▂▃▄▅▆▇█")) + [" "] + cls.symmetrical(list("▏▎▍▌▋▊▉")))
return AsciiFrames([" ", cls.symmetrical(list("▁▂▃▄▅▆▇█")), " ", cls.symmetrical(list("▏▎▍▌▋▊▉"))])

@classmethod
def af_fill2(cls):
Expand Down
10 changes: 3 additions & 7 deletions src/runez/click.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,11 +288,7 @@ def decorator(f):

attrs.setdefault("required", False)
if not name.startswith("-"):
if negatable:
name = "--%s/--no-%s" % (name, name)

else:
name = "--%s" % name
name = f"--{name}/--no-{name}" if negatable else f"--{name}"

return click.option(name, *args, **attrs)(f)

Expand Down Expand Up @@ -376,7 +372,7 @@ def protected_main(main, debug_stacktrace=False, no_stacktrace=None):
def _auto_complete_callback(attrs, func):
if not attrs.get("expose_value", True) and attrs.get("callback") is None:

def _callback(ctx, param, value):
def _callback(_ctx, _param, value):
value = func(value)
return value

Expand Down Expand Up @@ -408,7 +404,7 @@ def _add_dict(self, config, name, values):
config.add(provider)
return values

def __call__(self, ctx, param, value):
def __call__(self, _ctx, _param, value):
c = runez.config.Configuration()
self._add_dict(c, self.name, self._get_values(value))

Expand Down
12 changes: 2 additions & 10 deletions src/runez/colors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,16 +175,8 @@ def __call__(self, text, size=None):
>>> runez.blue("foo")
'foo'
"""
if size:
text = short(text, size=size)

else:
text = stringified(text)

if not text:
return ""

return self.rendered(text)
text = short(text, size=size) if size else stringified(text)
return self.rendered(text) if text else ""

def rendered(self, text):
return text
Expand Down
2 changes: 1 addition & 1 deletion src/runez/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def add(self, provider, front=False):
front (bool): If True, add provider to front of list
"""
if not isinstance(provider, ConfigProvider):
raise ValueError("Invalid config provider '%s'" % provider)
raise TypeError("Invalid config provider '%s'" % provider)

i = self.provider_id_slot(provider)
if i is not None:
Expand Down
30 changes: 6 additions & 24 deletions src/runez/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Example:
from runez.conftest import cli, isolated_log_setup, temp_folder
from runez.conftest import cli, temp_folder
"""

import logging
Expand Down Expand Up @@ -65,9 +65,6 @@ def _raise(*_, **__):
if isinstance(exc, str):
raise Exception(exc)

if isinstance(exc, type) and issubclass(exc, BaseException):
raise exc()

raise exc

return _raise
Expand All @@ -85,7 +82,7 @@ def patch_env(monkeypatch, clear=True, uppercase=True, **values):
values = {k.upper(): v for k, v in values.items()}

if clear:
for k in os.environ.keys():
for k in os.environ:
if k not in values:
monkeypatch.delenv(k)

Expand Down Expand Up @@ -149,7 +146,7 @@ def __exit__(self, *_):
os.chdir(self.old_cwd)


@pytest.fixture
@pytest.fixture()
def cli():
"""Convenience fixture for click CLI testing.
Expand All @@ -173,40 +170,25 @@ def test_help(cli):
yield ClickRunner(context=context)


# This just allows to get auto-complete to work in PyCharm
cli = cli # type: ClickRunner

# Comes in handy for click apps with only one main entry point
cli.default_main = None

# Can be customized by users, wraps cli (fixture) runs in given context
cli.context = TempFolder


@pytest.fixture
def isolated_log_setup():
"""Log settings restored"""
with IsolatedLogSetup() as tmp:
yield tmp


@pytest.fixture
@pytest.fixture()
def logged():
with CaptureOutput(seed_logging=True) as logged:
yield logged


@pytest.fixture
@pytest.fixture()
def temp_folder():
with TempFolder() as tmp:
yield tmp


# This just allows to get auto-complete to work in PyCharm
logged = logged # type: TrackedOutput
temp_folder = temp_folder # type: str


class WrappedHandler(_pytest.logging.LogCaptureHandler):
"""pytest aggressively imposes its own capture, this allows to impose our capture where applicable"""

Expand Down Expand Up @@ -263,7 +245,7 @@ class ClickRunner:

args: list = None # Arguments used in last run()
exit_code: int = None # Exit code of last run()
logged: TrackedOutput = None # Captured log from last run()
logged: TrackedOutput # Captured log from last run()
main: callable = None # Optional, override default_main for this runner instance
trace: bool = None # Optional, enable trace logging for this runner instance

Expand Down
18 changes: 9 additions & 9 deletions src/runez/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import pathlib
import re
from collections import defaultdict
from typing import ClassVar

from runez.system import _R, flattened, joined, stringified

Expand Down Expand Up @@ -228,9 +229,9 @@ def identifiers(text):
class Pluralizer:
"""Quick heuristic to pluralize most common english words"""

letter_based = {"s": "ses", "x": "xes", "y": "ies"}
suffix_based = {"ch": "ches", "fe": "ves", "man": "men", "sh": "shes"}
word_based = {"child": "children", "person": "people"}
letter_based: ClassVar = {"s": "ses", "x": "xes", "y": "ies"}
suffix_based: ClassVar = {"ch": "ches", "fe": "ves", "man": "men", "sh": "shes"}
word_based: ClassVar = {"child": "children", "person": "people"}

@classmethod
def find_letter_based(cls, singular):
Expand Down Expand Up @@ -362,13 +363,12 @@ def _int_from_text(text, base=None, default=None):
return int(text, base=base)

except ValueError:
if base is None:
if len(text) >= 3 and text[0] == "0":
if text[1] == "o":
return _int_from_text(text, base=8, default=default)
if base is None and len(text) >= 3 and text[0] == "0":
if text[1] == "o":
return _int_from_text(text, base=8, default=default)

if text[1] == "x":
return _int_from_text(text, base=16, default=default)
if text[1] == "x":
return _int_from_text(text, base=16, default=default)

return default

Expand Down
11 changes: 6 additions & 5 deletions src/runez/date.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import datetime
import time
from typing import ClassVar

from runez.convert import _float_from_text
from runez.system import _R, stringified, UNSET
Expand All @@ -23,9 +24,9 @@ class timezone(datetime.tzinfo):
Supported timezone are simply: UTC, and explicit offsets like +01:00
"""

__singletons = {} # Cached timezone objects per offset
__singletons: ClassVar = {} # Cached timezone objects per offset

def __new__(cls, offset, name=None):
def __new__(cls, offset, *_):
existing = cls.__singletons.get(offset)
if existing is None:
existing = super().__new__(cls)
Expand Down Expand Up @@ -56,13 +57,13 @@ def __eq__(self, other):
if isinstance(other, datetime.tzinfo):
return self.offset == other.utcoffset(datetime.datetime.now(tz=UTC))

def utcoffset(self, dt):
def utcoffset(self, *_):
return self.offset

def tzname(self, dt):
def tzname(self, *_):
return self.name

def dst(self, dt):
def dst(self, *_):
return self.offset


Expand Down
3 changes: 2 additions & 1 deletion src/runez/heartbeat.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import threading
import time
from typing import ClassVar, List

from runez.system import LOG, ltattr

Expand Down Expand Up @@ -70,7 +71,7 @@ class Heartbeat:
- refreshing data from a remote server
"""

tasks = [] # type: list # of task, to be periodically called
tasks: ClassVar[List[HeartbeatTask]] = [] # of task, to be periodically called

_lock = threading.Lock()
_thread = None # Background daemon thread used to periodically execute the tasks
Expand Down
8 changes: 4 additions & 4 deletions src/runez/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import sys
import urllib.parse
from pathlib import Path
from typing import ClassVar

from runez.file import checksum, decompress, delete, ensure_folder, TempFolder, to_path
from runez.system import _R, abort, DEV, find_caller, joined, short, stringified, SYS_INFO, UNSET
Expand Down Expand Up @@ -60,7 +61,7 @@ class CacheWrapper:
"""

base_location = "~/.cache/{program_name}"
cachable_methods = {"GET": True, "POST": True} # By default, cache only these REST methods
cachable_methods = ("GET", "POST") # By default, cache only these REST methods
default_expire = "1h" # 1 hour
size_limit = "2g" # 2 GB

Expand Down Expand Up @@ -109,7 +110,6 @@ def __init__(self, cache_backend, base_location, default_expire, size_limit):
size_limit (int | None): Max size in bytes for this cache
"""
self.base_location = base_location
self.cachable_methods = dict(self.cachable_methods)
self.default_expire = _R.lc.rm.to_seconds(default_expire)
self.size_limit = _R.lc.rm.to_bytesize(size_limit)
self.cache_backend = cache_backend
Expand Down Expand Up @@ -138,7 +138,7 @@ def is_cachable_method(self, method):
Returns:
(bool): True if this REST method call should be cached
"""
return self.cachable_methods.get(method)
return method in self.cachable_methods

def delete(self, cache_key):
"""
Expand Down Expand Up @@ -394,7 +394,7 @@ def response_for_url(self, method, url):


class MockCentral:
_stacks = {}
_stacks: ClassVar = {}

@classmethod
def get_stack(cls, handler, key):
Expand Down
23 changes: 15 additions & 8 deletions src/runez/program.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,14 +149,21 @@ def userid(self):

def parent_list(self, follow=True):
"""
Args:
follow (bool): If True, try and follow special processes like tmux
Returns:
(list[PsInfo]): List of parent processes
Parameters
----------
follow: bool
If True, try and follow special processes like tmux
Returns
-------
list[PsInfo]
List of parent processes
"""
p = self.followed_parent if follow else self.parent
return [p] + p.parent_list(follow=follow) if p else []
if not p:
return []

return [p, *p.parent_list(follow=follow)]


def auto_shellify(args):
Expand Down Expand Up @@ -341,7 +348,7 @@ def run(

fatal = False # pragma: no cover, non-fatal mode in background process (there is no more console etc to report anything)

with _WrappedArgs([full_path] + args) as wrapped_args:
with _WrappedArgs([full_path, *args]) as wrapped_args:
try:
p, out, err = _run_popen(wrapped_args, popen_args, passthrough, fatal, stdout, stderr)
result.output = decode(out, strip=strip)
Expand Down Expand Up @@ -730,7 +737,7 @@ def __enter__(self):
with open(wrapper, "wt") as fh:
fh.write('exec "$@"\n')

args = ["/bin/sh", wrapper] + args
args = ["/bin/sh", wrapper, *args]

return args

Expand Down
Loading

0 comments on commit b4f1d78

Please sign in to comment.