chore: Fix breaking changes from updated dependencies

Description

Abstract

Update tests and lint to follow the breaking changes introduced by the upgrade of some dependencies

Motivation

It was a choice to not pin any dependencies but from time to time, major versions are released that can break things.

Rationale

List of the updated dependencies that needed some changes on our side:

  • isort

    • removed not_skip=__init__.py, now by default

    • removed default_section=THIRDPARTY, now by default

    • removed non-existing group “DRF”

    • removed –apply, now by default

    • added . as first argument to isort to scan the whole project

  • flake8-imports

    • removed because not updated following isort update, and redundant with isort itself

  • flake8-mypy

    • removed because redundant with mypy itself

  • pytest-bdd

    • added target_fixture now that the given decorator is not a fixture anymore

    • renamed namespace and repository functions decorated by given to have different names than the imported fixtures

  • pydriller

    • adapted git_to_sphinx.py (how “reverse” order is used, and how to access some internal variables)

  • sphinx

    • ask napoleon sphinx extension to put attributes in a var section and not as attribute anymore, and hide all attributes. Without this, sphinx throws a warning and in the CI job we chose to consider warnings as errors (this was the only way I found for this)

Info

Hash

7c6dfe01ac4ffbaac21d5d3836d5fda9c8391cf7

Date

2020-09-25 22:54:00 +0200

Parents
  • Merge branch ‘feature/twidi/fix-commits-in-doc’ into develop [841496f6]2019-08-16 00:22:32 +0200

Children
  • Merge branch ‘feature/twidi/enhance-source-doc’ into develop [60b07af0]2020-09-26 13:10:58 +0200

  • style(docs): Add comments to doc custom css [e31a0e11]2020-09-25 23:36:21 +0200

Branches
Tags

(No tags)

Changes

Makefile

Type

Modified

Stats

+2 -2

@@ -97,7 +97,7 @@ mypy:  ## Run the mypy tool
 .PHONY: check-isort
 check-isort:  ## Run the isort tool in check mode only (won't modify files)
     @echo "$(BOLD)Checking isort(RESET)"
-    @isort --check-only 2>&1
+    @isort . --check-only 2>&1

 .PHONY: check-black
 check-black:  ## Run the black tool in check mode only (won't modify files)
@@ -121,7 +121,7 @@ pretty: isort black
 .PHONY: isort
 isort:  ## Run the isort tool and update files that need to
     @echo "$(BOLD)Running isort$(RESET)"
-    @isort --atomic --apply
+    @isort . --atomic

 .PHONY: black
 black:  ## Run the black tool and update files that need to

README.rst

Type

Modified

Stats

+1 -7

@@ -189,12 +189,6 @@ But we still use lint checkers:
   `flake8-docstrings <https://pypi.org/project/flake8-docstrings/>`_
     A simple module that adds an extension for the fantastic `pydocstyle <http://www.pydocstyle.org>`_ tool to flake8.

-  `flake8-imports <https://pypi.org/project/flake8-imports/>`_
-    Flake8 extension to run isort check over the source files.
-
-  `flake8-mypy <https://pypi.org/project/flake8-mypy/>`_
-    A plugin for Flake8 integrating `mypy <http://mypy-lang.org/>`_.
-
   To run `flake8`::

     make flake8
@@ -220,7 +214,7 @@ The checks are enforced by `flake8-docstrings`_ for basic docstring presentation

 I'll try to use `python typing <https://docs.python.org/3/library/typing.html>`_ while avoiding making things too much complicated. So expect some `# type: ignore` comments here and there, notably on decorators.

-The types will be checked by `mypy`_.
+The types will be checked by `mypy <https://mypy.readthedocs.io/>`_.

 So, code documentation is important (take that, Django). But it is clearly not enough.

docs/_static/css/custom.css

Type

Modified

Stats

+8 -0

@@ -53,3 +53,11 @@
 .wy-menu-vertical li.toctree-l13>a{
     padding-left: 14.663em !important;
 }
+
+/* Hide class attributes because they are duplicate of the class vars found by napoleon plugins
+and those vars are more detailed.
+Side effect: If attributes are not defined in docstrings, they won't appear at all.
+ */
+dl.class > dd > dl.field-list ~ dl.attribute {
+    display: None;
+}

docs/conf.py

Type

Modified

Stats

+2 -0

@@ -92,6 +92,8 @@ html_use_old_search_snippets = True

 # -- Run apidoc when building the documentation-------------------------------

+napoleon_use_ivar = True
+

 def run_apidoc(_):
     """Run apidoc on the marsha project and store source doc in ``source`` dir."""

docs/git_to_sphinx.py

Type

Modified

Stats

+20 -27

@@ -96,7 +96,7 @@ class GitRepository(GitRepositoryBase):
         if repo.head.is_detached:
             for branch in repo.branches:
                 if branch.commit.hexsha == repo.head.commit.hexsha:
-                    self.main_branch = branch.name
+                    self._conf.set_value("main_branch", branch.name)
         else:
             super()._discover_main_branch(repo)

@@ -104,25 +104,22 @@ class GitRepository(GitRepositoryBase):
     def repo(self):
         return super().repo

-    def get_list_tags(self, reverse_order=False):
+    def get_list_tags(self):
         for tag in sorted(
             self.repo.tags,
             key=lambda t: t.commit.committed_datetime,
-            reverse=not reverse_order,
+            reverse=True,
         ):
             yield tag

-    def get_list_branches(self, reverse_order=False):
+    def get_list_branches(self):
         for branch in sorted(
             self.repo.branches,
             key=lambda t: t.commit.committed_datetime,
-            reverse=not reverse_order,
+            reverse=True,
         ):
             yield branch

-    def get_list_commits(self, branch=None, reverse_order=False):
-        return super().get_list_commits(branch=branch, reverse_order=reverse_order)
-
     def get_list_tree(self, node, parent_path=""):
         for child in node:
             path = os.path.join(parent_path, child.name)
@@ -135,17 +132,11 @@ class GitRepository(GitRepositoryBase):


 class RepositoryMining(RepositoryMiningBase):
-    def _sanity_check_repos(self, path_to_repo):
-        if not isinstance(path_to_repo, str):
-            raise Exception("The path to the repo has to be of type 'string'")
-
     def get_git_repo(self):
-        path_repo = self._path_to_repo[0]
+        path_repo = self._conf.get("path_to_repos")[0]

-        if self._isremote(path_repo):
-            # save in `self` to avoid premature destruction of the tmp directory
-            self.tmp_folder = tempfile.TemporaryDirectory()
-            path_repo = self._clone_remote_repos(self.tmp_folder.name, path_repo)
+        if self._is_remote(path_repo):
+            path_repo = self._clone_remote_repo(self._clone_folder(), path_repo)

         git_repo = GitRepository(path_repo)

@@ -195,24 +186,23 @@ class RepositoryMining(RepositoryMiningBase):
         return git_repo

     def __init__(self, path_to_repo):
-        super().__init__(path_to_repo=path_to_repo, reversed_order=True)
+        super().__init__(path_to_repo=path_to_repo, order="reverse")
+
+        if not isinstance(self._conf.get("path_to_repo"), str):
+            raise Exception("The path to the repo has to be of type 'string'")

         self.git_repo = self.get_git_repo()

     def traverse_tags(self):
-        for tag in self.git_repo.get_list_tags(reverse_order=not self._reversed_order):
+        for tag in self.git_repo.get_list_tags():
             yield tag

     def traverse_branches(self):
-        for branch in self.git_repo.get_list_branches(
-            reverse_order=not self._reversed_order
-        ):
+        for branch in self.git_repo.get_list_branches():
             yield branch

     def traverse_commits(self, revision=None):
-        for commit in self.git_repo.get_list_commits(
-            branch=revision, reverse_order=not self._reversed_order
-        ):
+        for commit in self.git_repo.get_list_commits(rev=revision, reverse=False):
             yield commit

     def traverse_tree(self):
@@ -954,7 +944,8 @@ def render(location, basepath=BASEPATH, clean=True):
     print("  - branches...", end="")
     branches = list(repo.traverse_branches())
     render_to_files(
-        render_branches_pages(branches, repo.git_repo.main_branch), basepath=basepath
+        render_branches_pages(branches, repo.git_repo._conf.get("main_branch")),
+        basepath=basepath,
     )
     print("\r  - branches [ok]")
     print("  - tags...", end="")
@@ -974,7 +965,9 @@ def render(location, basepath=BASEPATH, clean=True):
         print(f"  - {branch.name}...", end="")
         commits = [branch.commit] + list(branch.commit.iter_parents())
         render_to_files(
-            render_branch_pages(branch, commits, repo.git_repo.main_branch),
+            render_branch_pages(
+                branch, commits, repo.git_repo._conf.get("main_branch")
+            ),
             basepath=basepath,
         )
         for commit in commits:

isshub/domain/contexts/code_repository/entities/namespace/__init__.py

Type

Modified

Stats

+3 -3

@@ -21,7 +21,7 @@ class NamespaceKind(enum.Enum):

 @validated()  # type: ignore
 class _Namespace(BaseModelWithId):
-    """A namespace can contain namespace and repositories.
+    """A namespace can contain namespaces and repositories.

     Notes
     -----
@@ -51,7 +51,7 @@ class _Namespace(BaseModelWithId):

 @validated()  # type: ignore
 class Namespace(_Namespace):
-    """A namespace can contain namespace and repositories.
+    """A namespace can contain namespaces and repositories.

     Attributes
     ----------
@@ -59,7 +59,7 @@ class Namespace(_Namespace):
         The unique identifier of the namespace
     name : str
         The name of the namespace. Unique in its parent namespace.
-    namespace : Optional[str]
+    namespace : Optional[Namespace]
         Where the namespace can be found.
     kind : NamespaceKind
         The kind of namespace.

isshub/domain/contexts/code_repository/entities/namespace/tests/test_describe.py

Type

Modified

Stats

+2 -2

@@ -56,8 +56,8 @@ def test_namespace_description_is_a_string(value, exception):
 scenarios("../features/describe.feature")


-@given("a Namespace")
-def namespace(namespace_factory):
+@given("a Namespace", target_fixture="namespace")
+def a_namespace(namespace_factory):
     return namespace_factory()

isshub/domain/contexts/code_repository/entities/repository/tests/test_describe.py

Type

Modified

Stats

+2 -2

@@ -40,8 +40,8 @@ def test_repository_namespace_is_a_namespace(value, exception):
 scenarios("../features/describe.feature")


-@given("a Repository")
-def repository(repository_factory):
+@given("a Repository", target_fixture="repository")
+def a_repository(repository_factory):
     return repository_factory()

setup.cfg

Type

Modified

Stats

+1 -5

@@ -54,8 +54,6 @@ lint=
     flake8-comprehensions
     flake8-docstrings
     flake8-formatter-abspath
-    flake8-imports
-    flake8-mypy
     gitpython
     isort
     pycodestyle
@@ -156,7 +154,6 @@ exclude_lines =

 [isort]
 combine_as_imports=1
-default_section=THIRDPARTY
 include_trailing_comma=true
 indent='    '
 known_thirdparty_python=factory,pytest,pytest_bdd
@@ -164,6 +161,5 @@ known_first_party=isshub
 line_length=88
 lines_after_imports=2
 multi_line_output=3
-not_skip = __init__.py
-sections=FUTURE,STDLIB,THIRDPARTY_PYTHON,DRF,THIRDPARTY,FIRSTPARTY,LOCALFOLDER
+sections=FUTURE,STDLIB,THIRDPARTY_PYTHON,THIRDPARTY,FIRSTPARTY,LOCALFOLDER
 use_parentheses=1