diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..d3865fd --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,67 @@ +default_language_version: + python: python3.12 +repos: + # Apply a consistent format to pyproject.toml files. + # https://pyproject-fmt.readthedocs.io/en/latest/ + - repo: https://github.com/tox-dev/pyproject-fmt + rev: "1.7.0" + hooks: + - id: pyproject-fmt + + # Automatically add trailing commas to calls and literals. + - repo: https://github.com/asottile/add-trailing-comma + rev: v3.1.0 + hooks: + - id: add-trailing-comma + + # Some out-of-the-box hooks for pre-commit. + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: check-added-large-files + - id: check-ast + - id: check-builtin-literals + - id: check-case-conflict + - id: check-docstring-first + - id: check-executables-have-shebangs + - id: check-merge-conflict + - id: check-shebang-scripts-are-executable + - id: check-symlinks + - id: check-toml + - id: check-vcs-permalinks + - id: check-xml + - id: check-yaml + - id: debug-statements + - id: end-of-file-fixer + - id: mixed-line-ending + - id: name-tests-test + args: [--django] + - id: trailing-whitespace + + # Automatically upgrade your Django project code + - repo: https://github.com/adamchainz/django-upgrade + rev: "1.16.0" + hooks: + - id: django-upgrade + args: [--target-version, "5.0"] + + # Run Pyupgrade on all Python files. This will upgrade the code to Python 3.12. + - repo: https://github.com/asottile/pyupgrade + rev: v3.15.1 + hooks: + - id: pyupgrade + args: ["--py312-plus"] + + # An extremely fast Python linter and formatter. + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.3.2 + hooks: + - id: ruff-format + - id: ruff + args: ["--fix", "--exit-non-zero-on-fix"] + + # Static checker for GitHub Actions workflow files. + - repo: https://github.com/rhysd/actionlint + rev: v1.6.27 + hooks: + - id: actionlint diff --git a/feedvault/add_feeds.py b/feedvault/add_feeds.py index e5ec665..7bb8e96 100644 --- a/feedvault/add_feeds.py +++ b/feedvault/add_feeds.py @@ -149,7 +149,7 @@ def struct_time_to_datetime(struct_time: struct_time | None) -> datetime.datetim if struct_time == "Mon, 01 Jan 0001 00:00:00 +0000": return None - dt: datetime.datetime = datetime.datetime.fromtimestamp(mktime(struct_time), tz=datetime.timezone.utc) + dt: datetime.datetime = datetime.datetime.fromtimestamp(mktime(struct_time), tz=datetime.UTC) if not dt: logger.error("Error converting struct_time to datetime: %s", struct_time) return None diff --git a/feedvault/sitemaps.py b/feedvault/sitemaps.py index a1587b0..da5bd3a 100644 --- a/feedvault/sitemaps.py +++ b/feedvault/sitemaps.py @@ -10,10 +10,10 @@ class StaticViewSitemap(Sitemap): changefreq: str = "daily" priority: float = 0.5 - def items(self: StaticViewSitemap) -> list[str]: # noqa: PLR6301 + def items(self: StaticViewSitemap) -> list[str]: """Return all the items in the sitemap.""" return ["feeds:index", "feeds:feeds", "feeds:domains"] - def location(self: StaticViewSitemap, item: str) -> str: # noqa: PLR6301 + def location(self: StaticViewSitemap, item: str) -> str: """Return the location of the item.""" return reverse(item) diff --git a/feedvault/views.py b/feedvault/views.py index aebe606..b371180 100644 --- a/feedvault/views.py +++ b/feedvault/views.py @@ -338,7 +338,7 @@ class APIFeedView(View): class APIEntriesView(View): """API Entries view.""" - def get(self, request: HttpRequest) -> HttpResponse: + def get(self: APIEntriesView, request: HttpRequest) -> HttpResponse: """Get all entries with pagination.""" # Retrieve all entries entries_list = Entry.objects.all() @@ -390,7 +390,7 @@ class APIEntriesView(View): class APIEntryView(View): """API Entry view.""" - def get(self, request: HttpRequest, entry_id: int) -> HttpResponse: # noqa: ARG002 + def get(self: APIEntryView, request: HttpRequest, entry_id: int) -> HttpResponse: # noqa: ARG002 """Get a single entry.""" entry = get_object_or_404(Entry, id=entry_id) return JsonResponse(model_to_dict(entry), safe=False) @@ -399,7 +399,7 @@ class APIEntryView(View): class APIFeedEntriesView(View): """API Feed Entries view.""" - def get(self, request: HttpRequest, feed_id: int) -> HttpResponse: + def get(self: APIFeedEntriesView, request: HttpRequest, feed_id: int) -> HttpResponse: """Get all entries for a single feed with pagination.""" # Retrieve all entries for a single feed entries_list = Entry.objects.filter(feed_id=feed_id) @@ -451,7 +451,7 @@ class APIFeedEntriesView(View): class DomainsView(View): """All domains.""" - def get(self, request: HttpRequest) -> HttpResponse: + def get(self: DomainsView, request: HttpRequest) -> HttpResponse: """Load the domains page.""" domains = Domain.objects.all() template = loader.get_template(template_name="domains.html") @@ -469,7 +469,7 @@ class DomainsView(View): class DomainView(View): """A single domain.""" - def get(self, request: HttpRequest, domain_id: int) -> HttpResponse: + def get(self: DomainView, request: HttpRequest, domain_id: int) -> HttpResponse: """Load the domain page.""" domain = get_object_or_404(Domain, id=domain_id) feeds = Feed.objects.filter(domain=domain).order_by("-created_at")[:100] diff --git a/pyproject.toml b/pyproject.toml index b29eefa..a2a4ec3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,8 +17,10 @@ ruff = "^0.3.0" djlint = "^1.34.1" [build-system] -requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" +requires = [ + "poetry-core", +] [tool.ruff] exclude = ["migrations"] @@ -28,17 +30,18 @@ preview = true line-length = 120 lint.select = ["ALL"] lint.ignore = [ - "CPY001", # Missing copyright notice at top of file - "ERA001", # Found commented-out code - "FIX002", # Line contains TODO - "D100", # Checks for undocumented public module definitions. - "D101", # Checks for undocumented public class definitions. - "D102", # Checks for undocumented public method definitions. - "D104", # Missing docstring in public package. - "D105", # Missing docstring in magic method. - "D106", # Checks for undocumented public class definitions, for nested classes. - "COM812", # Checks for the absence of trailing commas. - "ISC001", # Checks for implicitly concatenated strings on a single line. + "CPY001", # Missing copyright notice at top of file + "ERA001", # Found commented-out code + "FIX002", # Line contains TODO + "D100", # Checks for undocumented public module definitions. + "D101", # Checks for undocumented public class definitions. + "D102", # Checks for undocumented public method definitions. + "D104", # Missing docstring in public package. + "D105", # Missing docstring in magic method. + "D106", # Checks for undocumented public class definitions, for nested classes. + "COM812", # Checks for the absence of trailing commas. + "ISC001", # Checks for implicitly concatenated strings on a single line. + "PLR6301", # Checks for the presence of unused self parameter in methods definitions. ] [tool.ruff.lint.pydocstyle]