Compare commits

..

4 commits

9 changed files with 33 additions and 119 deletions

View file

@ -1,21 +0,0 @@
image: python:3.6
services:
- postgres:latest
variables:
GIT_SUBMODULE_STRATEGY: normal
PIP_CACHE_DIR: $CI_PROJECT_DIR/.cache/pip
PIPENV_CACHE_DIR: $CI_PROJECT_DIR/.cache/pipenv
POSTGRES_HOST: postgres
POSTGRES_DB: nice_marmot
POSTGRES_USER: runner
POSTGRES_PASSWORD: ''
cache:
paths:
- .cache
test:
script:
- pip install pipenv
- pipenv sync --dev
- pipenv run pytest

View file

@ -1,41 +0,0 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: check-ast
- id: check-builtin-literals
- id: check-case-conflict
- id: check-docstring-first
- id: check-executables-have-shebangs
- id: check-json
- id: check-merge-conflict
- id: check-symlinks
- id: check-toml
- id: check-vcs-permalinks
- id: check-yaml
- id: destroyed-symlinks
- id: end-of-file-fixer
- id: fix-byte-order-marker
- id: mixed-line-ending
args:
- --fix=lf
- id: trailing-whitespace
- repo: https://github.com/psf/black
rev: 23.7.0
hooks:
- id: black
language_version: python3.11
- repo: local
hooks:
- id: pytest
name: Check pytest unit tests pass
entry: poetry run pytest
pass_filenames: false
language: system
types: [python]
- id: mypy
name: Check mypy static types match
entry: poetry run mypy . --ignore-missing-imports
pass_filenames: false
language: system
types: [python]

View file

@ -1,3 +0,0 @@
requirements:
- Pipfile
- Pipfile.lock

View file

@ -1,16 +0,0 @@
language: python
cache:
directories:
- $PIP_CACHE_DIR
- $PIPENV_CACHE_DIR
env:
global:
- PIP_CACHE_DIR=$HOME/.cache/pip
- PIPENV_CACHE_DIR=$HOME/.cache/pipenv
python:
- '3.6'
install:
- pip install pipenv
- pipenv install --dev
script:
- pipenv run pytest

View file

@ -1,4 +0,0 @@
# vim: set ft=yaml :
host: 00dani.dev
port: 443
cname: dev.00dani.me

View file

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2017 - 2018 Danielle McLean Copyright (c) 2017 - 2024 Danielle McLean
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View file

@ -1,35 +1,32 @@
from django.core.paginator import Paginator from typing import Callable
from django.core.paginator import Page, Paginator
from django.shortcuts import redirect from django.shortcuts import redirect
from lemoncurry.middleware import ResponseException from lemoncurry.middleware import ResponseException
def paginate(queryset, reverse, page): def paginate(queryset, reverse: Callable[[int], str], page: int | None) -> Page:
class Page: def redirect_to_page(i: int):
def __init__(self, i): raise ResponseException(redirect(reverse(i)))
self.i = i
@property def reversible(p: Page) -> Page:
def url(self): p.reverse = reverse
return reverse(self.i) return p
@property
def current(self):
return self.i == entries.number
# If the first page was requested, redirect to the clean version of the URL
# with no page suffix.
if page == 1:
raise ResponseException(redirect(Page(1).url))
paginator = Paginator(queryset, 10) paginator = Paginator(queryset, 10)
entries = paginator.page(page or 1)
entries.pages = tuple(Page(i) for i in paginator.page_range) # If no page number was specified, return page one.
if page is None:
return reversible(paginator.page(1))
if entries.has_previous(): # If the first page was explicitly requested, or the page number was negative, redirect to page one with no URL suffix.
entries.prev = Page(entries.previous_page_number()) if page <= 1:
if entries.has_next(): redirect_to_page(1)
entries.next = Page(entries.next_page_number())
return entries # If the page requested is larger than the last page, then redirect to the last page.
if page > paginator.num_pages:
redirect_to_page(paginator.num_pages)
# Just return the current page! Hooray!
return reversible(paginator.page(page))

View file

@ -110,29 +110,29 @@
<nav> <nav>
<ul class="pagination"> <ul class="pagination">
{% if entries.prev %} {% if entries.has_previous() %}
<li class="page-item"> <li class="page-item">
<a class="page-link" rel="prev" href="{{ entries.prev.url }}"> <a class="page-link" rel="prev" href="{{ entries.reverse(entries.previous_page_number()) }}">
<i class="fas fa-step-backward" aria-hidden="true"></i> <span class="sr-only">previous page</span> <i class="fas fa-step-backward" aria-hidden="true"></i> <span class="sr-only">previous page</span>
</a> </a>
</li> </li>
{% endif %} {% endif %}
{% for page in entries.pages %} {% for i in entries.paginator.page_range %}
{% if page.current %} {% if i == entries.number %}
<li class="page-item active"> <li class="page-item active">
<span class="page-link">{{ page.i }} <span class="sr-only">(current page)</span></span> <span class="page-link">{{ i }} <span class="sr-only">(current page)</span></span>
</li> </li>
{% else %} {% else %}
<li class="page-item"> <li class="page-item">
<a class="page-link" href="{{ page.url }}">{{ page.i }}</a> <a class="page-link" href="{{ entries.reverse(i) }}">{{ i }}</a>
</li> </li>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% if entries.next %} {% if entries.has_next() %}
<li class="page-item"> <li class="page-item">
<a class="page-link" rel="next" href="{{ entries.next.url }}"> <a class="page-link" rel="next" href="{{ entries.reverse(entries.next_page_number()) }}">
<i class="fas fa-step-forward" aria-hidden="true"></i> <span class="sr-only">next page</span> <i class="fas fa-step-forward" aria-hidden="true"></i> <span class="sr-only">next page</span>
</a> </a>
</li> </li>

View file

@ -53,7 +53,6 @@ dependencies = [
"greenlet", "greenlet",
] ]
[tool.pdm]
[tool.pdm.dev-dependencies] [tool.pdm.dev-dependencies]
dev = [ dev = [
"mypy", "mypy",
@ -71,6 +70,9 @@ dev = [
[tool.pdm.build] [tool.pdm.build]
includes = [] includes = []
[tool.ruff.lint]
select = ["E4", "E7", "E9", "F", "I"]
[build-system] [build-system]
requires = ["pdm-backend"] requires = ["pdm-backend"]
build-backend = "pdm.backend" build-backend = "pdm.backend"