diff --git a/.gitignore b/.gitignore
index 591fb98475304d03c5db75648a2cf04042d0dd5f..d74435d42cb30219f553e79083e16326a174d5f8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,7 +19,8 @@ doc/api/
 dist/
 .gitlab-ci-local/
 cache/
+_citools/
+_work/
 .cache/
 .pytest_cache/
 .mypy_cache/
-venv/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 275b47fd42a9f5a10ef6df9fa3c41546aff2da07..33ba40b6553c65c38298a4cdb2d22005bc7ea7fa 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -3,5 +3,5 @@
 # SPDX-License-Identifier: BSD-3-Clause
 
 include:
-  - project: bob/dev-profile
+  - project: software/dev-profile
     file: /gitlab/python.yml
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index b66bb6104d64095ea70f24d82852a1471effba0b..1f5fe1063f48c63d0dd3782ca4fffd41db08ebd8 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -6,23 +6,23 @@
 # See https://pre-commit.com/hooks.html for more hooks
 repos:
   - repo: https://github.com/psf/black
-    rev: 22.10.0
+    rev: 23.1.0
     hooks:
       - id: black
   - repo: https://github.com/pycqa/docformatter
-    rev: v1.5.0
+    rev: v1.6.0.rc1
     hooks:
       - id: docformatter
   - repo: https://github.com/pycqa/isort
-    rev: 5.10.1
+    rev: 5.12.0
     hooks:
       - id: isort
   - repo: https://github.com/pycqa/flake8
-    rev: 5.0.4
+    rev: 6.0.0
     hooks:
       - id: flake8
   - repo: https://github.com/pre-commit/mirrors-mypy
-    rev: v0.991
+    rev: v1.0.0
     hooks:
     - id: mypy
       args: [
@@ -32,12 +32,12 @@ repos:
         --ignore-missing-imports,
       ]
   - repo: https://github.com/asottile/pyupgrade
-    rev: v3.2.2
+    rev: v3.3.1
     hooks:
     - id: pyupgrade
       args: [--py38-plus]
   - repo: https://github.com/pre-commit/pre-commit-hooks
-    rev: v4.3.0
+    rev: v4.4.0
     hooks:
       - id: check-ast
       - id: check-added-large-files
@@ -50,6 +50,6 @@ repos:
       - id: end-of-file-fixer
       - id: debug-statements
   - repo: https://github.com/fsfe/reuse-tool
-    rev: v1.0.0
+    rev: v1.1.2
     hooks:
       - id: reuse
diff --git a/pyproject.toml b/pyproject.toml
index 30f3ca4d85742d6eff6e17b95488d42f473acb9f..ecaecfd3e01ed212f22d750951ca1d4c8aa89c37 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -14,8 +14,7 @@ description = "Automatic links direct project dependencies to the intersphinx ca
 dynamic = ["readme"]
 license = {text = "BSD 3-Clause License"}
 authors = [
-  {name = "Andre Anjos"},
-  {email = "andre.anjos@idiap.ch"},
+  {name = "Andre Anjos", email = "andre.anjos@idiap.ch"},
 ]
 classifiers = [
     "Framework :: Sphinx :: Extension",
diff --git a/src/auto_intersphinx/__init__.py b/src/auto_intersphinx/__init__.py
index 5640780bfcfa434a5a901f0fa21b497788158139..312a11d56e0a1e4c521b2dda9ca77a56505c282d 100644
--- a/src/auto_intersphinx/__init__.py
+++ b/src/auto_intersphinx/__init__.py
@@ -44,7 +44,6 @@ def oneliner(s: str) -> str:
 
         A single line with all text.
     """
-
     return inspect.cleandoc(s).replace("\n", " ")
 
 
@@ -64,7 +63,6 @@ def rewrap(s: str) -> str:
 
         An 80-column wrapped multiline string
     """
-
     return "\n".join(textwrap.wrap(oneliner(s), width=80))
 
 
@@ -146,7 +144,6 @@ def populate_intersphinx_mapping(app: Sphinx, config: Config) -> None:
 
         config: Sphinx configuration
     """
-
     m = config.intersphinx_mapping
 
     builtin_catalog = Catalog()
@@ -307,7 +304,6 @@ def setup(app: Sphinx) -> dict[str, typing.Any]:
     extensions to be loaded, the loading relative order of this
     extension, and configuration options with their own defaults.
     """
-
     # we need intersphinx
     app.setup_extension("sphinx.ext.intersphinx")
 
diff --git a/src/auto_intersphinx/catalog.py b/src/auto_intersphinx/catalog.py
index a57cb16435d20ec83421a3743023a7d67cdb6ad4..a7ac671b38f92eca06f257d85b4a398c42e8de09 100644
--- a/src/auto_intersphinx/catalog.py
+++ b/src/auto_intersphinx/catalog.py
@@ -31,19 +31,18 @@ PackageDictionaryType = dict[str, dict[str, str]]
 BUILTIN_CATALOG = importlib.resources.files(__package__).joinpath(
     "catalog.json"
 )
-"""Base name for the catalog file distributed with this package"""
+"""Base name for the catalog file distributed with this package."""
 
 
 PEP440_RE = re.compile(
     r"^\s*" + packaging.version.VERSION_PATTERN + r"\s*$",
     re.VERBOSE | re.IGNORECASE,
 )
-"""Regular expression for matching PEP-440 version numbers"""
+"""Regular expression for matching PEP-440 version numbers."""
 
 
 def _ensure_webdir(addr: str) -> str:
     """Ensures the web-address ends in a /, and contains ``objects.inv``"""
-
     if addr.endswith(".html"):
         addr = addr[: addr.rfind("/")]
     if not addr.endswith("/"):
@@ -59,7 +58,6 @@ def _ensure_webdir(addr: str) -> str:
 
 def _reorder_versions(vdict: dict[str, str]) -> dict[str, str]:
     """Re-orders version dictionary by decreasing version."""
-
     # nota bene: new dicts preserve insertion order
     retval: dict[str, str] = {}
 
@@ -100,7 +98,6 @@ def docurls_from_environment(package: str) -> dict[str, str]:
         A dictionary, that maps the version of the documentation found on PyPI
         to the URL.
     """
-
     try:
         md = importlib.metadata.metadata(package)
         if md.get_all("Project-URL") is None:
@@ -136,7 +133,6 @@ def docurls_from_rtd(package: str) -> dict[str, str]:
         for the given package on RTD.  If the package's documentation is not
         available on RTD, returns an empty dictionary.
     """
-
     try:
         url = f"https://readthedocs.org/projects/{package}/versions/"
         logger.debug(f"Reaching for `{url}'...")
@@ -159,6 +155,19 @@ def docurls_from_rtd(package: str) -> dict[str, str]:
     return {}
 
 
+def _get_json(url: str) -> dict | None:
+    try:
+        logger.debug(f"Reaching for `{url}'...")
+        r = requests.get(url)
+        if r.ok:
+            return r.json()
+
+    except requests.exceptions.RequestException:
+        pass
+
+    return None
+
+
 def docurls_from_pypi(package: str, max_entries: int) -> dict[str, str]:
     """Checks PyPI for documentation pointers for a given package.
 
@@ -184,20 +193,6 @@ def docurls_from_pypi(package: str, max_entries: int) -> dict[str, str]:
         A dictionary, that maps the version of the documentation found on PyPI
         to the URL.
     """
-
-    def _get_json(url: str) -> dict | None:
-        try:
-
-            logger.debug(f"Reaching for `{url}'...")
-            r = requests.get(url)
-            if r.ok:
-                return r.json()
-
-        except requests.exceptions.RequestException:
-            pass
-
-        return None
-
     versions: dict[str, str] = {}
     data = _get_json(f"https://pypi.org/pypi/{package}/json")
     if data is None:
@@ -270,7 +265,6 @@ class Catalog(collections.abc.MutableMapping):
 
     def load(self, path: pathlib.Path) -> None:
         """Loads and replaces contents with those from the file."""
-
         with path.open("rt") as f:
             logger.debug(f"Loading package catalog from {str(path)}...")
             self._data = json.load(f)
@@ -278,13 +272,11 @@ class Catalog(collections.abc.MutableMapping):
 
     def loads(self, contents: str) -> None:
         """Loads and replaces contents with those from the string."""
-
         self._data = json.loads(contents)
         logger.debug(f"Loaded {len(self)} entries from string")
 
     def dump(self, path: pathlib.Path) -> None:
         """Loads and replaces contents with those from the file."""
-
         if path.exists():
             backup = path.with_suffix(path.suffix + "~")
             logger.debug(f"Backing up: {str(path)} -> {str(backup)}...")
@@ -299,7 +291,6 @@ class Catalog(collections.abc.MutableMapping):
 
     def dumps(self) -> str:
         """Loads and replaces contents with those from the string."""
-
         return json.dumps(self._data, indent=2)
 
     def reset(self) -> None:
@@ -327,7 +318,6 @@ class Catalog(collections.abc.MutableMapping):
 
     def _ensure_defaults(self, pkg: str) -> None:
         """Ensures a standardised setup for a package entry."""
-
         self.setdefault(pkg, {"versions": {}, "sources": {}})
         self[pkg].setdefault("versions", {})
         self[pkg].setdefault("sources", {})
@@ -395,7 +385,6 @@ class Catalog(collections.abc.MutableMapping):
             The dictionary of values for the current package, as obtained from
             readthedocs.org, and potentially merged with the existing one.
         """
-
         self._ensure_defaults(pkg)
 
         name = name or pkg
@@ -512,9 +501,7 @@ class Catalog(collections.abc.MutableMapping):
         """
 
         for pkg in pkgs:
-
             for action in order:
-
                 if action == "environment":
                     name = names.get(action, {}).get(pkg, pkg)
                     if name is not None:
@@ -543,7 +530,6 @@ class Catalog(collections.abc.MutableMapping):
 
     def self_update(self) -> None:
         """Runs a self-update procedure, by re-looking up known sources."""
-
         # organises the names as expected by update_versions()
         names: dict[str, dict[str, str]] = dict(
             environment={}, readthedocs={}, pypi={}
@@ -575,7 +561,6 @@ def _string2version(v: str) -> packaging.version.Version | None:
 
         Either ``None``, or the version object with the parsed version.
     """
-
     v = v.replace(".x", "")
     try:
         return packaging.version.Version(v)
@@ -605,7 +590,6 @@ def _prepare_versions(versions: dict[str, str]) -> dict[str, str]:
 
         A dictionary with keys that correspond to parsed versions and aliases.
     """
-
     if not versions:
         return versions
 
@@ -678,15 +662,18 @@ class LookupCatalog:
         """Internally creates all possible aliases for package names and
         versions.
 
-        This method will expand the catalog package names and version numbers
-        so that the user can refer to these using environment, readthedocs.org
-        or pypi.org names for packages, and PEP-440 compatible strings for
+        This method will expand the catalog package names and version
+        numbers
+        so that the user can refer to these using environment,
+        readthedocs.org
+        or pypi.org names for packages, and PEP-440 compatible strings
+        for
         version names during the lookup.
 
-        The catalog associated to this lookup is not modified in this process.
+        The catalog associated to this lookup is not modified in this
+        process.
         All augmentations are built-into the object instance.
         """
-
         self._version_map: dict[str, dict[str, str]] = {}
         self._package_map: dict[str, str] = {}
         for pkg in self._catalog.keys():
@@ -721,7 +708,6 @@ class LookupCatalog:
             If a match is found, returns the URL for the documentation.
             Otherwise, returns the ``default`` value.
         """
-
         if pkg not in self._package_map:
             return default
         if version not in self._version_map[pkg]:
diff --git a/src/auto_intersphinx/check_packages.py b/src/auto_intersphinx/check_packages.py
index 97a315fb0970b86c9b365be904ddb985adbbf19a..6b5f8c9797de77d5510e0b076a785da56a91033d 100644
--- a/src/auto_intersphinx/check_packages.py
+++ b/src/auto_intersphinx/check_packages.py
@@ -22,7 +22,6 @@ from .update_catalog import setup_verbosity
 
 def _main(args) -> None:
     """Main function, that actually executes the check-package command."""
-
     setup_verbosity(args.verbose)
 
     builtin_catalog = Catalog()
@@ -37,7 +36,6 @@ def _main(args) -> None:
         user_catalog.load(args.user)
 
     for p in args.packages:
-
         if p in user_catalog:
             print(f"Found {p} in user catalog:")
             print(
@@ -88,7 +86,6 @@ def _main(args) -> None:
 
 def add_parser(subparsers) -> argparse.ArgumentParser:
     """Just sets up the parser for this CLI."""
-
     prog = "auto-intersphinx check-packages"
 
     parser = subparsers.add_parser(
diff --git a/src/auto_intersphinx/cli.py b/src/auto_intersphinx/cli.py
index 28c9d59d0cd81d1ff2713f2af9db9e0ea4751d3a..2cc96c1c9353361524a6a896123d69ea63500d28 100644
--- a/src/auto_intersphinx/cli.py
+++ b/src/auto_intersphinx/cli.py
@@ -10,7 +10,6 @@ import sys
 
 def make_parser() -> argparse.ArgumentParser:
     """Creates the main parser."""
-
     parser = argparse.ArgumentParser(
         prog=sys.argv[0],
         description="Commands to handle sphinx catalogs.",
diff --git a/src/auto_intersphinx/dump_objects.py b/src/auto_intersphinx/dump_objects.py
index 9cb82a308cb21a5ae461ada99bc84cb8dbea4db3..2c0e8442a92e2727afad7f879cbd326e882868b8 100644
--- a/src/auto_intersphinx/dump_objects.py
+++ b/src/auto_intersphinx/dump_objects.py
@@ -16,7 +16,6 @@ logger = logging.getLogger(__name__)
 
 def _main(args) -> None:
     """Main function, that actually executes the dump-objects command."""
-
     setup_verbosity(args.verbose)
 
     from sphinx.ext import intersphinx
@@ -28,7 +27,6 @@ def _main(args) -> None:
 
 def add_parser(subparsers) -> argparse.ArgumentParser:
     """Just sets up the parser for this CLI."""
-
     prog = "auto-intersphinx dump-objects"
 
     parser = subparsers.add_parser(
diff --git a/src/auto_intersphinx/update_catalog.py b/src/auto_intersphinx/update_catalog.py
index 95be815be5d94008aa87f0320b089b630eb32e89..842a5a783a987bcb31ed6b02524cd175fe321fca 100644
--- a/src/auto_intersphinx/update_catalog.py
+++ b/src/auto_intersphinx/update_catalog.py
@@ -24,7 +24,6 @@ logger = logging.getLogger(__name__)
 
 def _parse_requirements(contents: str) -> list[str]:
     """Parses a pip-requirements file and extracts package lists."""
-
     lines = contents.split()
     lines = [k.strip() for k in lines if not k.strip().startswith("#")]
     split_re = re.compile(r"[=\s]+")
@@ -33,7 +32,6 @@ def _parse_requirements(contents: str) -> list[str]:
 
 def setup_verbosity(verbose: int) -> None:
     """Sets up logger verbosity."""
-
     import logging as builtin_logging
 
     package_logger = builtin_logging.getLogger("sphinx." + __package__)
@@ -56,7 +54,6 @@ def setup_verbosity(verbose: int) -> None:
 
 def _main(args) -> None:
     """Main function, that actually executes the update-catalog command."""
-
     setup_verbosity(args.verbose)
 
     catalog = Catalog()
@@ -78,7 +75,6 @@ def _main(args) -> None:
 
     package_list = []
     for pkg in args.packages:
-
         if pkg.startswith("http"):
             logger.info(f"Retrieving package list from `{pkg}'...")
             r = requests.get(pkg)
@@ -112,7 +108,6 @@ def _main(args) -> None:
 
 def add_parser(subparsers) -> argparse.ArgumentParser:
     """Just sets up the parser for this CLI."""
-
     prog = "auto-intersphinx update-catalog"
 
     parser = subparsers.add_parser(
diff --git a/tests/conftest.py b/tests/conftest.py
index 71032b8f36351dbea0b8471f22cc624da2a61912..ba675dcc3bc755ed5b6bed3fc44c555deb2580e4 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -10,5 +10,4 @@ from pytest import fixture
 @fixture
 def datadir(request) -> pathlib.Path:
     """Returns the directory in which the test is sitting."""
-
     return pathlib.Path(request.module.__file__).parents[0] / "data"