Skip to content

Commit 51cb71f

Browse files
davegaeddertclaude
andauthored
Upgrade ruff to 0.16.4 and ty to 0.0.74 (#103)
Co-authored-by: Claude <noreply@anthropic.com>
1 parent e4f3897 commit 51cb71f

35 files changed

Lines changed: 146 additions & 144 deletions

File tree

plain-admin/plain/admin/cards/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,6 @@ def get_current_filter(self) -> str:
102102
def get_filters(self) -> list[str] | Enum | None:
103103
if isinstance(self.filters, list):
104104
# Avoid mutating the class attribute
105-
return self.filters.copy() # type: ignore
105+
return self.filters.copy()
106106
else:
107107
return self.filters

plain-admin/plain/admin/views/viewsets.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def get_views(cls) -> list[type[View]]:
2727
DeleteView.parent_view_class = DetailView
2828

2929
# Now iterate all inner view classes
30-
views = []
30+
views: list[type[View]] = []
3131

3232
for attr in cls.__dict__.values():
3333
if isinstance(attr, type) and issubclass(attr, View):

plain-auth/plain/auth/test.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,23 @@ def login_client(client: Client, user: Any) -> None:
2626
login(request, user)
2727
session = get_request_session(request)
2828
session.save()
29+
assert session.session_key is not None
2930
session_cookie = settings.SESSION_COOKIE_NAME
3031
client.cookies[session_cookie] = session.session_key
31-
cookie_data = {
32+
cookie_data: dict[str, Any] = {
3233
"max-age": None,
3334
"path": "/",
3435
"domain": settings.SESSION_COOKIE_DOMAIN,
3536
"secure": settings.SESSION_COOKIE_SECURE or None,
3637
"expires": None,
3738
}
38-
client.cookies[session_cookie].update(cookie_data)
39+
# Morsel.update() is typed for str-only values, but these cookie
40+
# attributes are legitimately None (unset). Set them one at a time
41+
# through __setitem__, which is typed for Any and keeps Morsel's own
42+
# reserved-key validation (unlike bypassing update() with dict.update()).
43+
morsel = client.cookies[session_cookie]
44+
for key, value in cookie_data.items():
45+
morsel[key] = value
3946

4047

4148
def logout_client(client: Client) -> None:

plain-passwords/plain/passwords/models.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
2424
)
2525
super().__init__(*args, **kwargs)
2626

27-
def deconstruct(self) -> tuple[str | None, str, list[Any], dict[str, Any]]:
27+
def deconstruct(self) -> tuple[str, str, list[Any], dict[str, Any]]:
2828
name, path, args, kwargs = super().deconstruct()
2929
if kwargs.get("max_length") == 128:
3030
del kwargs["max_length"]
@@ -36,7 +36,6 @@ def pre_save(self, model_instance: postgres.Model, add: bool) -> str | None:
3636
if value and not self._is_hashed(value):
3737
value = hash_password(value)
3838
# Set the hashed value back on the instance immediately too
39-
assert self.name is not None
4039
setattr(model_instance, self.name, value)
4140

4241
return value

plain-postgres/plain/postgres/base.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,6 @@ def _insert_row(self) -> None:
494494
)
495495
if results:
496496
for value, field in zip(results[0], returning_fields):
497-
assert field.name is not None
498497
setattr(self, field.name, value)
499498

500499
def _update_row(self, fields: Iterable[str] | None) -> None:
@@ -578,7 +577,6 @@ def delete(self) -> int:
578577
with transaction.mark_for_rollback_on_error():
579578
count = self._model_meta.base_queryset.filter(id=self.id)._raw_delete()
580579
id_field = self._model_meta.get_forward_field("id")
581-
assert id_field.name is not None
582580
setattr(self, id_field.name, None)
583581
# Only the id is cleared -- every other field value survives so callers
584582
# can still reference a deleted row (correlate it, log it, check it's
@@ -707,6 +705,8 @@ def clean_fields(self, exclude: set[str] | None = None) -> None:
707705

708706
errors = {}
709707
for f in self._model_meta.fields:
708+
# See __init__ above: meta.fields is always ColumnField.
709+
assert isinstance(f, ColumnField)
710710
if f.name in exclude:
711711
continue
712712
# Skip validation for empty fields with required=False. The developer
@@ -1089,9 +1089,9 @@ def _check_ordering(cls) -> list[PreflightResult]:
10891089
meta = cls._model_meta
10901090
valid_fields = set(
10911091
chain.from_iterable(
1092-
(f.name,)
1093-
if not (f.auto_created and not f.concrete)
1094-
else (f.field.related_query_name(),)
1092+
(f.field.related_query_name(),)
1093+
if isinstance(f, ForeignObjectRel)
1094+
else (f.name,)
10951095
for f in chain(meta.fields, meta.related_objects)
10961096
)
10971097
)

plain-postgres/plain/postgres/constraints.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

33
from types import NoneType
4-
from typing import TYPE_CHECKING, Any, cast
4+
from typing import TYPE_CHECKING, Any
55

66
from plain.exceptions import ValidationError
77
from plain.postgres.constants import LOOKUP_SEP
@@ -454,7 +454,7 @@ def _unique_error_message(
454454
field_names[-1] = f"and {field_names[-1]}"
455455
# Comma-join when more than two, otherwise just space-join.
456456
sep = ", " if len(field_names) > 2 else " "
457-
params["field_label"] = sep.join(cast(list[str], field_names))
457+
params["field_label"] = sep.join(field_names)
458458

459459
# Use the first field's message format.
460460
message = meta.get_forward_field(unique_check[0]).unique_error_message

plain-postgres/plain/postgres/convergence/analysis.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -635,8 +635,6 @@ def _compare_columns(
635635
if f.primary_key:
636636
pk_suffix = f.db_type_suffix() or ""
637637

638-
# Fields reached via local_fields are always contributed (name set).
639-
assert f.name is not None
640638
statuses.append(
641639
ColumnStatus(
642640
name=f.column,

plain-postgres/plain/postgres/fields/base.py

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,9 @@ class Field[T](RegisterLookupMixin):
110110
cast_db_type_sql: str | None = None
111111

112112
# Instance attributes set during field lifecycle
113-
# Set by __init__
114-
name: str | None
113+
# Set by __init__; becomes the real field name once contributed to a
114+
# model class (set_attributes_from_name, called by contribute_to_class)
115+
name: str
115116
# Set by set_attributes_from_name (called by contribute_to_class)
116117
column: str
117118
concrete: bool
@@ -134,7 +135,7 @@ class Field[T](RegisterLookupMixin):
134135
non_migration_attrs: tuple[str, ...] = ()
135136

136137
def __init__(self) -> None:
137-
self.name = None # Set by set_attributes_from_name
138+
self.name = "" # Set by set_attributes_from_name
138139
self.primary_key = False
139140
self.auto_created = False
140141

@@ -151,8 +152,8 @@ def __str__(self) -> str:
151152
def __repr__(self) -> str:
152153
"""Display the module, class, and name of the field."""
153154
path = f"{self.__class__.__module__}.{self.__class__.__qualname__}"
154-
name = getattr(self, "name", None)
155-
if name is not None:
155+
name = getattr(self, "name", "")
156+
if name:
156157
return f"<{path}: {name}>"
157158
return f"<{path}>"
158159

@@ -164,7 +165,6 @@ def _check_field_name(self) -> list[PreflightResult]:
164165
Check if field name is valid, i.e. 1) does not end with an
165166
underscore, 2) does not contain "__" and 3) is not "id".
166167
"""
167-
assert self.name is not None, "Field name must be set before checking"
168168
if self.name.endswith("_"):
169169
return [
170170
PreflightResult(
@@ -215,7 +215,7 @@ def select_format(
215215
"""
216216
return sql, params
217217

218-
def deconstruct(self) -> tuple[str | None, str, list[Any], dict[str, Any]]:
218+
def deconstruct(self) -> tuple[str, str, list[Any], dict[str, Any]]:
219219
"""
220220
Return enough information to recreate the field as a 4-tuple:
221221
@@ -259,7 +259,6 @@ def deconstruct(self) -> tuple[str | None, str, list[Any], dict[str, Any]]:
259259
cls_name = self.__class__.__qualname__
260260
if getattr(_postgres_root, cls_name, None) is self.__class__:
261261
path = f"plain.postgres.{cls_name}"
262-
# Note: self.name can be None during migration state rendering when fields are cloned
263262
return (self.name, path, [], keywords)
264263

265264
def clone(self) -> Self:
@@ -305,7 +304,6 @@ def __reduce__(
305304
# values - so, this is very close to normal pickle.
306305
state = self.__dict__.copy()
307306
return _empty, (self.__class__,), state
308-
assert self.name is not None
309307
options = model.model_options
310308
return _load_field, (
311309
options.package_label,
@@ -394,7 +392,6 @@ def contribute_to_class(self, cls: type[Model], name: str) -> None:
394392
# Field is its own descriptor; make sure it is set on the class so
395393
# attribute access hits __get__/__set__.
396394
if self.column:
397-
assert self.name is not None
398395
setattr(cls, self.name, self)
399396

400397
# Descriptor protocol implementation
@@ -422,7 +419,6 @@ def __get__(self, instance: Model | None, owner: type[Model]) -> Self | T:
422419
return self
423420

424421
# Instance access - get value from instance dict
425-
assert self.name is not None
426422
data = instance.__dict__
427423
field_name = self.name
428424

@@ -472,7 +468,6 @@ def __set__(self, instance: Model, value: T) -> None:
472468
stored = self.to_python(value)
473469

474470
# Store in instance dict
475-
assert self.name is not None
476471
instance.__dict__[self.name] = stored
477472

478473
def __delete__(self, instance: Model) -> None:
@@ -481,7 +476,6 @@ def __delete__(self, instance: Model) -> None:
481476
482477
Removes the value from instance.__dict__.
483478
"""
484-
assert self.name is not None
485479
try:
486480
del instance.__dict__[self.name]
487481
except KeyError:
@@ -491,7 +485,6 @@ def __delete__(self, instance: Model) -> None:
491485

492486
def pre_save(self, model_instance: Model, add: bool) -> T | None:
493487
"""Return field's value just before saving."""
494-
assert self.name is not None
495488
return getattr(model_instance, self.name)
496489

497490
def get_prep_value(self, value: Any) -> Any:
@@ -544,12 +537,10 @@ def has_db_default(self) -> bool:
544537
return self.get_db_default_expression() is not None
545538

546539
def save_form_data(self, instance: Model, data: Any) -> None:
547-
assert self.name is not None
548540
setattr(instance, self.name, data)
549541

550542
def value_from_object(self, obj: Model) -> T | None:
551543
"""Return the value of this field in the given model instance."""
552-
assert self.name is not None
553544
return getattr(obj, self.name)
554545

555546

@@ -653,7 +644,7 @@ def get_default(self) -> Any:
653644
return None
654645
return self._default_empty_value
655646

656-
def deconstruct(self) -> tuple[str | None, str, list[Any], dict[str, Any]]:
647+
def deconstruct(self) -> tuple[str, str, list[Any], dict[str, Any]]:
657648
name, path, args, kwargs = super().deconstruct()
658649
if self.required is not True:
659650
kwargs["required"] = self.required
@@ -750,7 +741,7 @@ def get_default(self) -> Any:
750741
# shared state across instances.
751742
return copy.deepcopy(self.default)
752743

753-
def deconstruct(self) -> tuple[str | None, str, list[Any], dict[str, Any]]:
744+
def deconstruct(self) -> tuple[str, str, list[Any], dict[str, Any]]:
754745
name, path, args, kwargs = super().deconstruct()
755746
if self.default is not NOT_PROVIDED:
756747
kwargs["default"] = self.default
@@ -891,7 +882,7 @@ def validate(self, value: Any, model_instance: Model) -> None:
891882
)
892883
super().validate(value, model_instance)
893884

894-
def deconstruct(self) -> tuple[str | None, str, list[Any], dict[str, Any]]:
885+
def deconstruct(self) -> tuple[str, str, list[Any], dict[str, Any]]:
895886
name, path, args, kwargs = super().deconstruct()
896887
if self.choices is not None:
897888
choices = self.choices

plain-postgres/plain/postgres/fields/binary.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def __init__(
4141
if self.max_length is not None:
4242
self.validators.append(MaxLengthValidator(self.max_length))
4343

44-
def deconstruct(self) -> tuple[str | None, str, list[Any], dict[str, Any]]:
44+
def deconstruct(self) -> tuple[str, str, list[Any], dict[str, Any]]:
4545
name, path, args, kwargs = super().deconstruct()
4646
if self.max_length is not None:
4747
kwargs["max_length"] = self.max_length

plain-postgres/plain/postgres/fields/encrypted.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
InvalidToken = None # ty: ignore[invalid-assignment]
1515
MultiFernet = None # ty: ignore[invalid-assignment]
1616
hashes = None # ty: ignore[invalid-assignment]
17-
PBKDF2HMAC = None # ty: ignore[invalid-assignment]
17+
PBKDF2HMAC = None
1818

1919
from plain.postgres.lookups import Exact, IsNull
2020
from plain.runtime import settings

0 commit comments

Comments
 (0)