Skip to content

Commit

Permalink
Enable more Ruff rules
Browse files Browse the repository at this point in the history
  • Loading branch information
jace committed May 22, 2024
1 parent 410b8c4 commit 33f5122
Show file tree
Hide file tree
Showing 12 changed files with 60 additions and 57 deletions.
11 changes: 10 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -233,13 +233,17 @@ select = [
"EXE", # flake8-executable
"F", # pyflakes
"FA", # flake8-future-annotations
"FLY", # flynt
"G", # flake8-logging-format
"I", # isort
"INP", # flake8-no-pep420
"INT", # flake8-gettext
"ISC", # flake8-implicit-str-concat
"N", # pep8-naming
"PERF", # Perflint
"PGH", # pygrep-hooks
"PIE", # flake8-pie
"PL", # pylint
"PT", # flake8-pytest-style
"PYI", # flake8-pyi
"RET", # flake8-return
Expand Down Expand Up @@ -274,6 +278,10 @@ ignore = [
"EM101", # Allow Exception("string")
"EM102", # Allow Exception(f"string")
"ISC001", # Allow implicitly concatenated string literals (required for formatter)
"PLR2004", # Too many false positives
"PLR0912", # Some functions are complex
"PLR0913", # Some functions need many arguments
"PLR0915", # Some functions are complex
"RUF012", # Allow mutable ClassVar without annotation (conflicts with SQLAlchemy)
"SLOT000", # Don't require `__slots__` for subclasses of str
]
Expand All @@ -288,10 +296,11 @@ allowed-confusables = ["‘", "’", "–"]
[tool.ruff.lint.extend-per-file-ignores]
"__init__.py" = ["E402"] # Allow non-top-level imports
"tests/**.py" = [
"S101", # Allow assert
"ARG001", # Context manager fixtures may not be used within a test
"ANN001", # Args don't need types (usually fixtures)
"N802", # Fixture returning a class may be named per class name convention
"N803", # Args don't require naming convention (fixture could be a class)
"S101", # Allow assert
]

[tool.ruff.lint.isort]
Expand Down
2 changes: 1 addition & 1 deletion src/coaster/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ def wrapper(*args: Any, **kwargs: Any) -> Any:
for engine in self._engines:
try:
return getattr(engine, name)(*args, **kwargs)
except itsdangerous.BadSignature as exc:
except itsdangerous.BadSignature as exc: # noqa: PERF203
saved_exc = exc
# We've run out of engines and all of them reported BadSignature.
# If there were no engines, the sentinel RuntimeError exception is used
Expand Down
21 changes: 10 additions & 11 deletions src/coaster/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ def formatException(self, ei: _SysExcInfoType) -> str: # noqa: N802
for attr, value in list(frame.f_locals.items()):
idvalue = id(value)
if idvalue in value_cache:
value = RepeatValueIndicator(value_cache[idvalue])
value = RepeatValueIndicator(value_cache[idvalue]) # noqa: PLW2901
else:
value_cache[idvalue] = f"{frame.f_code.co_name}.{attr}"
print(f"\t{attr:>20} = ", end=' ', file=sio)
Expand Down Expand Up @@ -529,17 +529,16 @@ def init_app(app: SansIoApp, _warning_stacklevel: int = 2) -> None:
backupCount=app.config.get('LOG_FILE_ROTATE_COUNT', 7),
utc=app.config.get('LOG_FILE_ROTATE_UTC', False),
)
elif sys.platform in ('linux', 'darwin'):
# WatchedFileHandler cannot be used on Windows. Also skip on unknown
# platforms, falling back to a regular FileHandler
file_handler = logging.handlers.WatchedFileHandler(
error_log_file, delay=error_log_file_delay
)
else:
if sys.platform in ('linux', 'darwin'):
# WatchedFileHandler cannot be used on Windows. Also skip on unknown
# platforms, falling back to a regular FileHandler
file_handler = logging.handlers.WatchedFileHandler(
error_log_file, delay=error_log_file_delay
)
else:
file_handler = logging.FileHandler(
error_log_file, delay=error_log_file_delay
)
file_handler = logging.FileHandler(
error_log_file, delay=error_log_file_delay
)
file_handler.setFormatter(formatter)
file_handler.setLevel(app.config.get('LOG_FILE_LEVEL', logging.WARNING))
logger.addHandler(file_handler)
Expand Down
2 changes: 1 addition & 1 deletion src/coaster/sqlalchemy/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ def url_for(self, action: str = 'view', **kwargs) -> str:
# 2. ('**entity', 'name') --> kwargs['entity'].name
if attr[0].startswith('**'):
item = kwargs.pop(attr[0][2:])
attr = attr[1:]
attr = attr[1:] # noqa: PLW2901
else:
item = self
for subattr in attr:
Expand Down
6 changes: 3 additions & 3 deletions src/coaster/sqlalchemy/roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -1811,7 +1811,7 @@ def _configure_roles(_mapper: Any, cls: type[RoleMixin]) -> None:
):
# If we have a synonym, replace the attr with the referred attr, but
# process it under the synonym name
attr = getattr(cls, attr.original_property.name)
attr = getattr(cls, attr.original_property.name) # noqa: PLW2901

if isinstance(attr, abc.Hashable) and attr in __cache__:
data = __cache__[attr]
Expand Down Expand Up @@ -1868,7 +1868,7 @@ def _configure_roles(_mapper: Any, cls: type[RoleMixin]) -> None:
for lhs, rhs in offer_map.items():
for role in rhs:
reverse_offer_map.setdefault(role, set()).add(lhs)
roles = set(reverse_offer_map.keys())
roles = set(reverse_offer_map.keys()) # noqa: PLW2901
elif isinstance(roles, set):
offer_map = None
reverse_offer_map = None
Expand All @@ -1892,7 +1892,7 @@ def _configure_roles(_mapper: Any, cls: type[RoleMixin]) -> None:
and isinstance(actor_attr, str)
and '.' in actor_attr
):
dotted_name, actor_attr = actor_attr.rsplit('.', 1)
dotted_name, actor_attr = actor_attr.rsplit('.', 1) # noqa: PLW2901
dotted_name = name + '.' + dotted_name
else:
dotted_name = name
Expand Down
16 changes: 7 additions & 9 deletions src/coaster/utils/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,12 +251,11 @@ def subloop(
and not (skip_pre and tag == 'pre')
):
blocks.append('')
elif not blocks:
if text:
blocks.append(text)
else:
if not blocks:
if text:
blocks.append(text)
else:
blocks[-1] += text
blocks[-1] += text

if len(element) > 0 and not (skip_pre and tag == 'pre'):
for child in element[:-1]:
Expand All @@ -275,11 +274,10 @@ def subloop(
if not blocks:
if tail:
blocks.append(tail)
elif tag == 'br' and tail:
blocks[-1] += '\n' + tail
else:
if tag == 'br' and tail:
blocks[-1] += '\n' + tail
else:
blocks[-1] += tail
blocks[-1] += tail

subloop(None, doc)
# Replace   with ' '
Expand Down
2 changes: 1 addition & 1 deletion src/coaster/views/classview.py
Original file line number Diff line number Diff line change
Expand Up @@ -935,7 +935,7 @@ def __init_subclass__(cls) -> None:
# Copy ViewMethod instances into subclasses. We know an attr
# with the same name doesn't exist in the subclass because it
# was processed first in the MRO and added to the processed set.
attr = attr.copy()
attr = attr.copy() # noqa: PLW2901
setattr(cls, name, attr)
attr.__set_name__(cls, name)
view_names.add(name)
Expand Down
25 changes: 11 additions & 14 deletions src/coaster/views/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,19 +224,16 @@ def process_kwargs(
if is_list:
if has_gettype:
kwargs[name] = values.getlist(name, type=filt)
elif filt:
kwargs[name] = [filt(_v) for _v in values[name]]
else:
if filt:
kwargs[name] = [filt(_v) for _v in values[name]]
else:
kwargs[name] = values[name]
kwargs[name] = values[name]
elif has_gettype:
kwargs[name] = values.get(name, type=filt)
elif filt:
kwargs[name] = filt(values[name])
else:
if has_gettype:
kwargs[name] = values.get(name, type=filt)
else:
if filt:
kwargs[name] = filt(values[name])
else:
kwargs[name] = values[name]
kwargs[name] = values[name]
except ValueError as exc:
raise RequestValueError(str(exc)) from exc
return kwargs
Expand Down Expand Up @@ -429,7 +426,7 @@ def loader(kwargs: dict[str, Any]) -> dict[str, Any]:
result: dict[str, Any] = {}
for models, attributes, parameter in chain:
if not isinstance(models, (list, tuple)):
models = (models,)
models = (models,) # noqa: PLW2901
item = None
url_check = False
url_check_paramvalues: dict[str, tuple[Union[str, Callable], Any]] = {}
Expand Down Expand Up @@ -502,7 +499,7 @@ def loader(kwargs: dict[str, Any]) -> dict[str, Any]:
location = location + '?' + request.query_string.decode()
raise Redirect(location, code=302)
if parameter.startswith('g.') and g:
parameter = parameter[2:]
parameter = parameter[2:] # noqa: PLW2901
setattr(g, parameter, item)
result[parameter] = item
if permission_required and (
Expand Down Expand Up @@ -540,7 +537,7 @@ def _best_mimetype_match(
available_list: list[str], accept_mimetypes: MIMEAccept, default: str
) -> str:
for acceptable_mimetype, _quality in accept_mimetypes:
acceptable_mimetype = acceptable_mimetype.lower()
acceptable_mimetype = acceptable_mimetype.lower() # noqa: PLW2901
for available_mimetype in available_list:
if acceptable_mimetype == available_mimetype.lower():
return available_mimetype
Expand Down
2 changes: 1 addition & 1 deletion tests/coaster_tests/app_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ def test_logging_handler(self) -> None:
for handler in self.another_app.logger.handlers:
try:
raise Exception # pylint: disable=broad-exception-raised
except Exception: # noqa: BLE001 # pylint: disable=broad-except
except Exception: # noqa: BLE001,PERF203 # pylint: disable=broad-except
formatter = handler.formatter
if isinstance(formatter, LocalVarFormatter):
formatter.formatException(sys.exc_info())
Expand Down
2 changes: 1 addition & 1 deletion tests/coaster_tests/sqlalchemy_registry_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def all_registry_hosts(
def registry_member() -> Callable:
"""Test registry member function."""

def member(pos=None, kwparam=None) -> None: # noqa: ARG001
def member(pos=None, kwparam=None) -> None:
pass

return member
Expand Down
4 changes: 2 additions & 2 deletions tests/coaster_tests/statemanager_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ def test_transition_data_name_invalid(self) -> None:
with pytest.raises(TypeError):

@state.transition(None, state.DRAFT, name='invalid_data_field')
def name_test(self) -> None: # noqa: ARG001
def name_test(self) -> None:
pass

def test_duplicate_transition(self) -> None:
Expand All @@ -687,7 +687,7 @@ def test_duplicate_transition(self) -> None:

@state.transition(state.DRAFT, state.PENDING)
@state.transition(state.PENDING, state.PUBLISHED)
def dupe_decorator(self) -> None: # noqa: ARG001
def dupe_decorator(self) -> None:
pass

state.transitions.remove('dupe_decorator')
Expand Down
24 changes: 12 additions & 12 deletions tests/coaster_tests/views_loadmodels_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def return_siteadmin_perms() -> set[str]:
)
def t_container(
container: Container,
kwargs: dict[str, str], # noqa: ARG001
kwargs: dict[str, str],
) -> Container:
return container

Expand All @@ -117,7 +117,7 @@ def t_single_model_in_loadmodels(user: User) -> User:
(NamedDocument, {'name': 'document', 'container': 'container'}, 'document'),
)
def t_named_document(
container: Container, # noqa: ARG001
container: Container,
document: NamedDocument,
) -> NamedDocument:
return document
Expand All @@ -132,7 +132,7 @@ def t_named_document(
),
)
def t_redirect_document(
container: Container, # noqa: ARG001
container: Container,
document: NamedDocument,
) -> NamedDocument:
return document
Expand All @@ -143,7 +143,7 @@ def t_redirect_document(
(ScopedNamedDocument, {'name': 'document', 'container': 'container'}, 'document'),
)
def t_scoped_named_document(
container: Container, # noqa: ARG001
container: Container,
document: ScopedNamedDocument,
) -> ScopedNamedDocument:
return document
Expand All @@ -155,7 +155,7 @@ def t_scoped_named_document(
urlcheck=['url_name'],
)
def t_id_named_document(
container: Container, # noqa: ARG001
container: Container,
document: IdNamedDocument,
) -> IdNamedDocument:
return document
Expand All @@ -170,7 +170,7 @@ def t_id_named_document(
),
)
def t_scoped_id_document(
container: Container, # noqa: ARG001
container: Container,
document: ScopedIdDocument,
) -> ScopedIdDocument:
return document
Expand All @@ -186,7 +186,7 @@ def t_scoped_id_document(
urlcheck=['url_name'],
)
def t_scoped_id_named_document(
container: Container, # noqa: ARG001
container: Container,
document: ScopedIdNamedDocument,
) -> ScopedIdNamedDocument:
return document
Expand All @@ -201,7 +201,7 @@ def t_scoped_id_named_document(
),
)
def t_callable_document(
document: ParentDocument, # noqa: ARG001
document: ParentDocument,
child: ChildDocument,
) -> ChildDocument:
return child
Expand All @@ -212,7 +212,7 @@ def t_callable_document(
(ChildDocument, {'id': 'child', 'parent': 'document.middle'}, 'child'),
)
def t_dotted_document(
document: ParentDocument, # noqa: ARG001
document: ParentDocument,
child: ChildDocument,
) -> ChildDocument:
return child
Expand All @@ -224,7 +224,7 @@ def t_dotted_document(
permission='view',
)
def t_dotted_document_view(
document: ParentDocument, # noqa: ARG001
document: ParentDocument,
child: ChildDocument,
) -> ChildDocument:
return child
Expand All @@ -236,7 +236,7 @@ def t_dotted_document_view(
permission='edit',
)
def t_dotted_document_edit(
document: ParentDocument, # noqa: ARG001
document: ParentDocument,
child: ChildDocument,
) -> ChildDocument:
return child
Expand All @@ -248,7 +248,7 @@ def t_dotted_document_edit(
permission='delete',
)
def t_dotted_document_delete(
document: ParentDocument, # noqa: ARG001
document: ParentDocument,
child: ChildDocument,
) -> ChildDocument:
return child
Expand Down

0 comments on commit 33f5122

Please sign in to comment.