Skip to content

Commit

Permalink
Down to 'Found 51 errors in 12 files (checked 27 source files)'
Browse files Browse the repository at this point in the history
  • Loading branch information
jieter committed Dec 21, 2024
1 parent 0f7e5be commit 7d3f81a
Show file tree
Hide file tree
Showing 19 changed files with 185 additions and 80 deletions.
5 changes: 5 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,8 @@ repos:
- id: pyupgrade
args: [--py39-plus]

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.14.0
hooks:
- id: mypy
args: ["django_tables2"]
13 changes: 9 additions & 4 deletions django_tables2/columns/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class Library:
def __init__(self):
self.columns = []

def register(self, column: "Column"):
def register(self, column: "type[Column]"):
if not hasattr(column, "from_field"):
raise ImproperlyConfigured(f"{column.__class__.__name__} is not a subclass of Column")
self.columns.append(column)
Expand Down Expand Up @@ -73,7 +73,7 @@ class LinkTransform:

def __init__(
self,
url: Union[callable, None] = None,
url: Union[Callable, None] = None,
accessor: Union[str, Accessor, None] = None,
attrs: Union[dict, None] = None,
reverse_args: Union[list, tuple, None] = None,
Expand Down Expand Up @@ -259,7 +259,7 @@ class Blog(models.Model):

# Tracks each time a Column instance is created. Used to retain column order.
creation_counter = 0
empty_values = (None, "")
empty_values: tuple[Any, ...] = (None, "")

# by default, contents are not wrapped in an <a>-tag.
link = None
Expand Down Expand Up @@ -358,7 +358,7 @@ def footer(self, bound_column: "BoundColumn", table: "Table") -> Union[str, None

return ""

def render(self, value: Any) -> Any:
def render(self, value: Any, **kwargs) -> "Union[SafeString, str]":
"""
Return the content for a specific cell.
Expand Down Expand Up @@ -418,6 +418,7 @@ def from_field(cls, field, **kwargs) -> "Union[Column, None]":
# column if this class was asked directly.
if cls is Column:
return cls(**kwargs)
return None


class BoundColumn:
Expand All @@ -440,6 +441,10 @@ class SimpleTable(tables.Table):
"""

render: Callable
order: Callable
value: Callable

def __init__(self, table: "Table", column: Column, name: str):
self._table = table
self.column = column
Expand Down
22 changes: 14 additions & 8 deletions django_tables2/columns/booleancolumn.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
from typing import Union
from typing import TYPE_CHECKING, Any, Union

from django.db import models
from django.utils.html import escape, format_html
from django.utils.safestring import SafeString

from ..utils import AttributeDict
from .base import Column, library
from .base import BoundColumn, Column, library

if TYPE_CHECKING:
from django.db.models import Field
from django.utils.safestring import SafeString


@library.register
Expand Down Expand Up @@ -33,7 +36,7 @@ def __init__(self, null=False, yesno="✔,✘", **kwargs):
kwargs["empty_values"] = ()
super().__init__(**kwargs)

def _get_bool_value(self, record, value, bound_column) -> bool:
def _get_bool_value(self, record: Any, value: Any, bound_column: BoundColumn) -> bool:
# If record is a model, we need to check if it has choices defined.
if hasattr(record, "_meta"):
field = bound_column.accessor.get_field(record)
Expand All @@ -45,7 +48,7 @@ def _get_bool_value(self, record, value, bound_column) -> bool:

return bool(value)

def render(self, value, record, bound_column) -> SafeString:
def render(self, value: Any, record: Any, bound_column: BoundColumn) -> "SafeString":
value = self._get_bool_value(record, value, bound_column)
text = self.yesno[int(not value)]
attrs = {"class": str(value).lower()}
Expand All @@ -60,9 +63,12 @@ def value(self, record, value, bound_column) -> str:
return str(self._get_bool_value(record, value, bound_column))

@classmethod
def from_field(cls, field, **kwargs) -> "Union[BooleanColumn, None]":
if isinstance(field, models.NullBooleanField):
return cls(null=True, **kwargs)
def from_field(cls, field: "Field", **kwargs) -> "Union[BooleanColumn, None]":
if NullBooleanField := getattr(models, "NullBooleanField", None):
if isinstance(field, NullBooleanField):
return cls(null=True, **kwargs)

if isinstance(field, models.BooleanField):
return cls(null=getattr(field, "null", False), **kwargs)

return None
12 changes: 8 additions & 4 deletions django_tables2/columns/datecolumn.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from typing import Union
from typing import TYPE_CHECKING, Union

from django.db import models

from .base import library
from .templatecolumn import TemplateColumn

if TYPE_CHECKING:
from django.db.models import Field


@library.register
class DateColumn(TemplateColumn):
Expand All @@ -21,10 +24,11 @@ class DateColumn(TemplateColumn):
def __init__(self, format: Union[str, None] = None, short: bool = True, *args, **kwargs):
if format is None:
format = "SHORT_DATE_FORMAT" if short else "DATE_FORMAT"
template = '{{ value|date:"%s"|default:default }}' % format
super().__init__(template_code=template, *args, **kwargs)
kwargs["template_code"] = '{{ value|date:"%s"|default:default }}' % format
super().__init__(*args, **kwargs)

@classmethod
def from_field(cls, field, **kwargs) -> "Union[DateColumn, None]":
def from_field(cls, field: "Field", **kwargs) -> "Union[DateColumn, None]":
if isinstance(field, models.DateField):
return cls(**kwargs)
return None
8 changes: 6 additions & 2 deletions django_tables2/columns/datetimecolumn.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from typing import Union
from typing import TYPE_CHECKING, Union

from django.db import models

from .base import library
from .templatecolumn import TemplateColumn

if TYPE_CHECKING:
from django.db.models.fields import Field


@library.register
class DateTimeColumn(TemplateColumn):
Expand All @@ -25,6 +28,7 @@ def __init__(self, format: Union[str, None] = None, short: bool = True, *args, *
super().__init__(template_code=template, *args, **kwargs)

@classmethod
def from_field(cls, field, **kwargs) -> "Union[DateTimeColumn, None]":
def from_field(cls, field: "Field", **kwargs) -> "Union[DateTimeColumn, None]":
if isinstance(field, models.DateTimeField):
return cls(**kwargs)
return None
8 changes: 6 additions & 2 deletions django_tables2/columns/emailcolumn.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from typing import Union
from typing import TYPE_CHECKING, Union

from django.db import models

from .base import library
from .linkcolumn import BaseLinkColumn

if TYPE_CHECKING:
from django.db.models import Field


@library.register
class EmailColumn(BaseLinkColumn):
Expand Down Expand Up @@ -37,6 +40,7 @@ def get_url(self, value) -> str:
return f"mailto:{value}"

@classmethod
def from_field(cls, field, **kwargs) -> "Union[EmailColumn, None]":
def from_field(cls, field: "Field", **kwargs) -> "Union[EmailColumn, None]":
if isinstance(field, models.EmailField):
return cls(**kwargs)
return None
13 changes: 8 additions & 5 deletions django_tables2/columns/filecolumn.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import os
from typing import Union
from typing import TYPE_CHECKING, Union

from django.db import models
from django.utils.html import format_html
Expand All @@ -9,6 +9,9 @@
from .base import library
from .linkcolumn import BaseLinkColumn

if TYPE_CHECKING:
from django.db.models import Field


@library.register
class FileColumn(BaseLinkColumn):
Expand Down Expand Up @@ -52,13 +55,12 @@ def text_value(self, record, value):
return os.path.basename(value.name)
return super().text_value(record, value)

def render(self, record, value) -> SafeString:
def render(self, record, value) -> "SafeString":
attrs = AttributeDict(self.attrs.get("span", {}))
classes = [c for c in attrs.get("class", "").split(" ") if c]

exists = None
storage = getattr(value, "storage", None)
if storage:
if storage := getattr(value, "storage", None):
# we'll assume value is a `django.db.models.fields.files.FieldFile`
if self.verify_exists:
exists = storage.exists(value.name)
Expand All @@ -82,6 +84,7 @@ def render(self, record, value) -> SafeString:
)

@classmethod
def from_field(cls, field, **kwargs) -> "Union[FileColumn, None]":
def from_field(cls, field: "Field", **kwargs) -> "Union[FileColumn, None]":
if isinstance(field, models.FileField):
return cls(**kwargs)
return None
16 changes: 12 additions & 4 deletions django_tables2/columns/jsoncolumn.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import json
from typing import Union
from typing import TYPE_CHECKING, Union

from django.db.models import JSONField
from django.utils.html import format_html
Expand All @@ -9,11 +9,14 @@
from .base import library
from .linkcolumn import BaseLinkColumn

if TYPE_CHECKING:
from django.db.models import Field

try:
from django.contrib.postgres.fields import HStoreField
except ImportError:
# psycopg is not available, cannot import from django.contrib.postgres.
HStoreField = object()
HStoreField = None # type: ignore


@library.register
Expand Down Expand Up @@ -48,6 +51,11 @@ def render(self, record, value) -> SafeString:
)

@classmethod
def from_field(cls, field, **kwargs) -> "Union[JSONColumn, None]":
if isinstance(field, (JSONField, HStoreField)):
def from_field(cls, field: "Field", **kwargs) -> "Union[JSONColumn, None]":
if (
isinstance(field, JSONField)
or HStoreField is not None
and isinstance(field, HStoreField)
):
return cls(**kwargs)
return None
25 changes: 20 additions & 5 deletions django_tables2/columns/templatecolumn.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
from typing import TYPE_CHECKING, Any, Union

from django.template import Context, Template
from django.template.loader import get_template
from django.utils.html import strip_tags
from django.utils.safestring import SafeString

from .base import Column, library
from .base import BoundColumn, Column, library

if TYPE_CHECKING:
from django.utils.safestring import SafeString

from ..tables import Table


@library.register
Expand Down Expand Up @@ -41,7 +47,13 @@ class ExampleTable(tables.Table):

empty_values = ()

def __init__(self, template_code=None, template_name=None, extra_context=None, **extra):
def __init__(
self,
template_code: Union[str, None] = None,
template_name: Union[str, None] = None,
extra_context: Union[dict, None] = None,
**extra
):
super().__init__(**extra)
self.template_code = template_code
self.template_name = template_name
Expand All @@ -50,7 +62,9 @@ def __init__(self, template_code=None, template_name=None, extra_context=None, *
if not self.template_code and not self.template_name:
raise ValueError("A template must be provided")

def render(self, record, table, value, bound_column, **kwargs) -> SafeString:
def render(
self, record, table: "Table", value: Any, bound_column: BoundColumn, **kwargs
) -> "Union[SafeString, str]":
# If the table is being rendered using `render_table`, it hackily
# attaches the context to the table as a gift to `TemplateColumn`.
context = getattr(table, "context", Context())
Expand All @@ -65,8 +79,9 @@ def render(self, record, table, value, bound_column, **kwargs) -> SafeString:
with context.update(additional_context):
if self.template_code:
return Template(self.template_code).render(context)
else:
elif self.template_name:
return get_template(self.template_name).render(context.flatten())
return ""

def value(self, **kwargs) -> str:
"""
Expand Down
12 changes: 8 additions & 4 deletions django_tables2/columns/timecolumn.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from typing import Union
from typing import TYPE_CHECKING, Union

from django.db import models

from .base import library
from .templatecolumn import TemplateColumn

if TYPE_CHECKING:
from django.db.models import Field


@library.register
class TimeColumn(TemplateColumn):
Expand All @@ -19,10 +22,11 @@ class TimeColumn(TemplateColumn):
def __init__(self, format: Union[str, None] = None, *args, **kwargs):
if format is None:
format = "TIME_FORMAT"
template = '{{ value|date:"%s"|default:default }}' % format
super().__init__(template_code=template, *args, **kwargs)
kwargs["template_code"] = '{{ value|date:"%s"|default:default }}' % format
super().__init__(*args, **kwargs)

@classmethod
def from_field(cls, field, **kwargs) -> "Union[TimeColumn, None]":
def from_field(cls, field: "Field", **kwargs) -> "Union[TimeColumn, None]":
if isinstance(field, models.TimeField):
return cls(**kwargs)
return None
1 change: 1 addition & 0 deletions django_tables2/columns/urlcolumn.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ def get_url(self, value: str) -> str:
def from_field(cls, field, **kwargs) -> "Union[URLColumn, None]":
if isinstance(field, models.URLField):
return cls(**kwargs)
return None
13 changes: 10 additions & 3 deletions django_tables2/config.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
from typing import TYPE_CHECKING, Union

from django.core.paginator import EmptyPage, PageNotAnInteger

if TYPE_CHECKING:
from django.http import HttpRequest

from .tables import Table


class RequestConfig:
"""
Expand All @@ -26,11 +33,11 @@ class RequestConfig:
"""

def __init__(self, request, paginate=True):
def __init__(self, request: "HttpRequest", paginate: Union[bool, dict, tuple, list] = True):
self.request = request
self.paginate = paginate

def configure(self, table):
def configure(self, table: "Table"):
"""
Configure a table using information from the request.
Expand All @@ -43,7 +50,7 @@ def configure(self, table):
if order_by:
table.order_by = order_by
if self.paginate:
if hasattr(self.paginate, "items"):
if isinstance(self.paginate, (dict, tuple, list)):
kwargs = dict(self.paginate)
else:
kwargs = {}
Expand Down
Loading

0 comments on commit 7d3f81a

Please sign in to comment.