diff --git a/.constraints/py3.10.txt b/.constraints/py3.10.txt
index d56f8056..a37e6cee 100644
--- a/.constraints/py3.10.txt
+++ b/.constraints/py3.10.txt
@@ -203,7 +203,6 @@ tox==4.15.1
 traitlets==5.14.3
 typepy==1.3.2
 types-docutils==0.21.0.20240423
-types-pkg-resources==0.1.3
 types-python-dateutil==2.9.0.20240316
 types-pyyaml==6.0.12.20240311
 types-setuptools==70.0.0.20240524
diff --git a/.constraints/py3.11.txt b/.constraints/py3.11.txt
index 84b76013..d6b486db 100644
--- a/.constraints/py3.11.txt
+++ b/.constraints/py3.11.txt
@@ -201,7 +201,6 @@ tox==4.15.1
 traitlets==5.14.3
 typepy==1.3.2
 types-docutils==0.21.0.20240423
-types-pkg-resources==0.1.3
 types-python-dateutil==2.9.0.20240316
 types-pyyaml==6.0.12.20240311
 types-setuptools==70.0.0.20240524
diff --git a/.constraints/py3.12.txt b/.constraints/py3.12.txt
index 9bdc97b7..e2aa7c42 100644
--- a/.constraints/py3.12.txt
+++ b/.constraints/py3.12.txt
@@ -201,7 +201,6 @@ tox==4.15.1
 traitlets==5.14.3
 typepy==1.3.2
 types-docutils==0.21.0.20240423
-types-pkg-resources==0.1.3
 types-python-dateutil==2.9.0.20240316
 types-pyyaml==6.0.12.20240311
 types-setuptools==70.0.0.20240524
diff --git a/.constraints/py3.7.txt b/.constraints/py3.7.txt
deleted file mode 100644
index f3dd8bff..00000000
--- a/.constraints/py3.7.txt
+++ /dev/null
@@ -1,226 +0,0 @@
-# This file was autogenerated by uv via the following command:
-#    uv pip compile pyproject.toml -o .constraints/py3.7.txt --all-extras --no-annotate --python-version=3.7 --no-emit-package setuptools
-accessible-pygments==0.0.4
-aiofiles==22.1.0
-aiosqlite==0.19.0
-alabaster==0.7.13
-anyio==3.7.1
-argon2-cffi==23.1.0
-argon2-cffi-bindings==21.2.0
-arrow==1.2.3
-attrs==23.2.0
-babel==2.14.0
-backcall==0.2.0
-beautifulsoup4==4.12.3
-black==23.3.0
-bleach==6.0.0
-cached-property==1.5.2
-cachetools==5.3.3
-cattrs==23.1.2
-certifi==2024.6.2
-cffi==1.15.1
-cfgv==3.3.1
-chardet==5.2.0
-charset-normalizer==3.3.2
-click==8.1.7
-colorama==0.4.6
-comm==0.1.4
-coverage==7.2.7
-cryptography==42.0.8
-cycler==0.11.0
-dataproperty==1.0.1
-debugpy==1.7.0
-decorator==5.1.1
-defusedxml==0.7.1
-deprecated==1.2.14
-distlib==0.3.8
-docstring-to-markdown==0.15
-docutils==0.17.1
-dominate==2.9.1
-entrypoints==0.4
-exceptiongroup==1.2.1
-execnet==2.0.2
-fastjsonschema==2.20.0
-feynman==2.1.0
-filelock==3.12.2
-fonttools==4.38.0
-fqdn==1.5.1
-gitdb==4.0.11
-gitpython==3.1.43
-greenlet==3.0.3
-identify==2.5.24
-idna==3.7
-imagesize==1.4.1
-importlib-metadata==6.7.0
-importlib-resources==5.12.0
-iniconfig==2.0.0
-ipykernel==6.16.2
-ipython==7.34.0
-ipython-genutils==0.2.0
-ipywidgets==8.1.3
-isoduration==20.11.0
-isort==5.11.5
-jedi==0.18.2
-jinja2==3.1.4
-json5==0.9.16
-jsonpointer==3.0.0
-jsonschema==4.17.3
-jupyter==1.0.0
-jupyter-cache==0.5.0
-jupyter-client==7.4.9
-jupyter-console==6.6.3
-jupyter-core==4.12.0
-jupyter-events==0.6.3
-jupyter-lsp==1.5.1
-jupyter-server==1.24.0
-jupyter-server-fileid==0.9.2
-jupyter-server-mathjax==0.2.6
-jupyter-server-ydoc==0.8.0
-jupyter-ydoc==0.2.5
-jupyterlab==3.6.7
-jupyterlab-code-formatter==2.2.1
-jupyterlab-git==0.44.0
-jupyterlab-lsp==3.10.2
-jupyterlab-myst==1.2.0
-jupyterlab-pygments==0.2.2
-jupyterlab-server==2.24.0
-jupyterlab-widgets==3.0.11
-kiwisolver==1.4.5
-latexcodec==3.0.0
-livereload==2.6.3
-lsprotocol==2023.0.1
-markdown-it-py==2.2.0
-markupsafe==2.1.5
-matplotlib==3.5.3
-matplotlib-inline==0.1.6
-mbstrdecoder==1.1.3
-mdit-py-plugins==0.3.5
-mdurl==0.1.2
-mistune==3.0.2
-mpmath==1.3.0
-mypy==1.4.1
-mypy-extensions==1.0.0
-myst-nb==0.17.2
-myst-parser==0.18.1
-nbclassic==1.1.0
-nbclient==0.5.13
-nbconvert==7.6.0
-nbdime==3.2.1
-nbformat==5.8.0
-nbmake==1.3.0
-nest-asyncio==1.6.0
-nodeenv==1.9.1
-notebook==6.5.7
-notebook-shim==0.2.4
-numpy==1.21.6
-packaging==24.0
-pandocfilters==1.5.1
-parso==0.8.4
-pathspec==0.11.2
-pathvalidate==3.2.0
-pexpect==4.9.0
-pickleshare==0.7.5
-pillow==9.5.0
-pkgutil-resolve-name==1.3.10
-platformdirs==4.0.0
-pluggy==1.2.0
-pre-commit==2.21.0
-prometheus-client==0.17.1
-prompt-toolkit==3.0.47
-psutil==6.0.0
-ptyprocess==0.7.0
-pybtex==0.24.0
-pybtex-docutils==1.0.3
-pycparser==2.21
-pydantic==1.10.16
-pydata-sphinx-theme==0.13.3
-pygithub==2.3.0
-pygments==2.17.2
-pyjwt==2.8.0
-pynacl==1.5.0
-pyparsing==3.1.2
-pyproject-api==1.5.3
-pyrsistent==0.19.3
-pytablewriter==1.2.0
-pytest==7.4.4
-pytest-cov==4.1.0
-pytest-xdist==3.5.0
-python-dateutil==2.9.0.post0
-python-gitlab==3.15.0
-python-json-logger==2.0.7
-python-lsp-jsonrpc==1.0.0
-python-lsp-ruff==1.6.0
-python-lsp-server==1.7.4
-pytoolconfig==1.3.0
-pytz==2024.1
-pyyaml==6.0.1
-pyzmq==26.0.3
-qtconsole==5.4.4
-qtpy==2.4.1
-requests==2.31.0
-requests-toolbelt==1.0.0
-rfc3339-validator==0.1.4
-rfc3986-validator==0.1.1
-rope==1.9.0
-ruff==0.1.15
-send2trash==1.8.3
-six==1.16.0
-smmap==5.0.1
-sniffio==1.3.1
-snowballstemmer==2.2.0
-soupsieve==2.4.1
-sphinx==5.3.0
-sphinx-api-relink==0.0.9
-sphinx-autobuild==2021.3.14
-sphinx-book-theme==1.0.1
-sphinx-codeautolink==0.15.2
-sphinx-comments==0.0.3
-sphinx-copybutton==0.5.2
-sphinx-design==0.4.1
-sphinx-hep-pdgref==0.2.0
-sphinx-pybtex-etal-style==0.0.2
-sphinx-thebe==0.2.1
-sphinx-togglebutton==0.3.2
-sphinxcontrib-applehelp==1.0.2
-sphinxcontrib-bibtex==2.6.2
-sphinxcontrib-devhelp==1.0.2
-sphinxcontrib-htmlhelp==2.0.0
-sphinxcontrib-jsmath==1.0.1
-sphinxcontrib-qthelp==1.0.3
-sphinxcontrib-serializinghtml==1.1.5
-sqlalchemy==1.4.52
-sympy==1.10.1
-tabledata==1.3.3
-tabulate==0.9.0
-tcolorpy==0.1.6
-terminado==0.17.1
-tinycss2==1.2.1
-tomli==2.0.1
-tornado==6.2
-tox==4.8.0
-traitlets==5.9.0
-typed-ast==1.5.5
-typepy==1.3.2
-types-docutils==0.20.0.3
-types-pkg-resources==0.1.3
-types-python-dateutil==2.8.19.14
-types-pyyaml==6.0.12.12
-types-setuptools==69.0.0.0
-typing-extensions==4.7.1
-ujson==5.7.0
-uri-template==1.3.0
-urllib3==2.0.7
-virtualenv==20.26.2
-wcwidth==0.2.13
-webcolors==1.13
-webencodings==0.5.1
-websocket-client==1.6.1
-wheel==0.42.0
-widgetsnbextension==4.0.11
-wrapt==1.16.0
-y-py==0.6.2
-ypy-websocket==0.8.4
-zipp==3.15.0
-
-# The following packages were excluded from the output:
-# setuptools
diff --git a/.constraints/py3.8.txt b/.constraints/py3.8.txt
index 853db0f8..34531395 100644
--- a/.constraints/py3.8.txt
+++ b/.constraints/py3.8.txt
@@ -207,7 +207,6 @@ tox==4.15.1
 traitlets==5.14.3
 typepy==1.3.2
 types-docutils==0.21.0.20240423
-types-pkg-resources==0.1.3
 types-python-dateutil==2.9.0.20240316
 types-pyyaml==6.0.12.20240311
 types-setuptools==70.0.0.20240524
diff --git a/.constraints/py3.9.txt b/.constraints/py3.9.txt
index 45a49cb2..214c6d66 100644
--- a/.constraints/py3.9.txt
+++ b/.constraints/py3.9.txt
@@ -204,7 +204,6 @@ tox==4.15.1
 traitlets==5.14.3
 typepy==1.3.2
 types-docutils==0.21.0.20240423
-types-pkg-resources==0.1.3
 types-python-dateutil==2.9.0.20240316
 types-pyyaml==6.0.12.20240311
 types-setuptools==70.0.0.20240524
diff --git a/pyproject.toml b/pyproject.toml
index f0c163b0..1b35a7f6 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -18,7 +18,6 @@ classifiers = [
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.11",
     "Programming Language :: Python :: 3.12",
-    "Programming Language :: Python :: 3.7",
     "Programming Language :: Python :: 3.8",
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python",
@@ -49,7 +48,7 @@ keywords = [
 license = {file = "LICENSE"}
 maintainers = [{email = "compwa-admin@ep1.rub.de"}]
 name = "PWA-pages"
-requires-python = ">=3.7"
+requires-python = ">=3.8"
 
 [project.optional-dependencies]
 dev = [
@@ -109,7 +108,6 @@ types = [
     "sphinx-api-relink >=0.0.8",
     "types-PyYAML",
     "types-docutils",
-    "types-pkg-resources",
     "types-python-dateutil",
     "types-setuptools",
 ]
@@ -234,7 +232,7 @@ src = [
     "src",
     "tests",
 ]
-target-version = "py37"
+target-version = "py38"
 
 [tool.ruff.format]
 docstring-code-format = true
diff --git a/src/pwa_pages/repo/_github.py b/src/pwa_pages/repo/_github.py
index 0347206d..d868c14d 100644
--- a/src/pwa_pages/repo/_github.py
+++ b/src/pwa_pages/repo/_github.py
@@ -15,7 +15,7 @@
     from github.Commit import Commit
 
 
-@lru_cache()
+@lru_cache
 def get_github_repo(url: str) -> GithubRepository:
     github = __get_github()
     repo_name = extract_github_repo_name(url)
@@ -25,7 +25,7 @@ def get_github_repo(url: str) -> GithubRepository:
     return github.get_repo(repo_name)
 
 
-@lru_cache()
+@lru_cache
 def extract_github_repo_name(url: str) -> str:
     github_url = "https://github.com"
     match = re.match(rf"^{github_url}/([^/]+)/([^/]+).*$", url)
@@ -34,7 +34,7 @@ def extract_github_repo_name(url: str) -> str:
     return f"{match[1]}/{match[2]}"
 
 
-@lru_cache()
+@lru_cache
 def get_first_commit_date(repo: GithubRepository) -> datetime:
     commits = repo.get_commits().reversed
     first_commit: Commit = commits[0]
@@ -45,7 +45,7 @@ def get_first_commit_date(repo: GithubRepository) -> datetime:
     return parse_date(timestamp)
 
 
-@lru_cache()
+@lru_cache
 def get_latest_commit_date(repo: GithubRepository) -> datetime:
     default_branch = repo.default_branch
     latest_commit = repo.get_commit(default_branch)
@@ -66,7 +66,7 @@ def get_last_modified(repo: GithubRepository) -> datetime:
     return parse_date(repo.last_modified)
 
 
-@lru_cache()
+@lru_cache
 def get_languages(repo: GithubRepository) -> dict[str, float]:
     languages = repo.get_languages()
     total_lines = sum(languages.values())
@@ -75,7 +75,7 @@ def get_languages(repo: GithubRepository) -> dict[str, float]:
     }
 
 
-@lru_cache()
+@lru_cache
 def __get_github(token: str | None = None) -> Github:
     if token is None:
         token = os.environ.get("GITHUB_TOKEN")
diff --git a/src/pwa_pages/repo/_gitlab.py b/src/pwa_pages/repo/_gitlab.py
index 2b7b3c6c..64dbd620 100644
--- a/src/pwa_pages/repo/_gitlab.py
+++ b/src/pwa_pages/repo/_gitlab.py
@@ -14,7 +14,7 @@
     from gitlab.v4.objects import ProjectCommitManager
 
 
-@lru_cache()
+@lru_cache
 def get_gitlab_repo(server_url: str, project_path: str) -> GitlabProject:
     gitlab = __get_gitlab(server_url)
     return gitlab.projects.get(project_path)
@@ -29,7 +29,7 @@ def split_gitlab_repo_url(url: str) -> tuple[str, str] | None:
     return server_url, project_path
 
 
-@lru_cache()
+@lru_cache
 def get_first_commit_date(repo: GitlabProject) -> datetime:
     commits: ProjectCommitManager = repo.commits
     all_commits = commits.list(all=True)
@@ -39,7 +39,7 @@ def get_first_commit_date(repo: GitlabProject) -> datetime:
     return parse_date(commit_info["created_at"])
 
 
-@lru_cache()
+@lru_cache
 def get_latest_commit_date(repo: GitlabProject) -> datetime:
     default_branch = repo.attributes["default_branch"]
     commits: ProjectCommitManager = repo.commits
@@ -53,6 +53,6 @@ def get_last_modified(repo: GitlabProject) -> datetime:
     return parse_date(date_str)
 
 
-@lru_cache()
+@lru_cache
 def __get_gitlab(url: str) -> Gitlab:
     return Gitlab(url)