From fdc331fcfda90d45d7d3c455fe1a9484144cc96c Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 4 Sep 2023 15:53:29 +0200 Subject: [PATCH 1/5] Add pre-commit configuration --- .pre-commit-config.yaml | 52 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..6366604 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,52 @@ +exclude: ".venv|__pycache__|tests/dev/|tests/fixtures/" +fail_fast: false +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: check-added-large-files + args: ["--maxkb=500"] + - id: check-ast + - id: check-builtin-literals + - id: check-case-conflict + - id: check-toml + - id: check-yaml + - id: detect-private-key + - id: end-of-file-fixer + - id: fix-byte-order-marker + - id: fix-encoding-pragma + args: [--remove] + - id: name-tests-test + args: [--pytest-test-first] + - id: trailing-whitespace + args: [--markdown-linebreak-ext=md] + + - repo: https://github.com/asottile/pyupgrade + rev: v3.10.1 + hooks: + - id: pyupgrade + args: + - "--py38-plus" + + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: "v0.0.287" + hooks: + - id: ruff + args: ["--fix-only", "--target-version=py38"] + + - repo: https://github.com/psf/black + rev: 23.7.0 + hooks: + - id: black + args: ["--target-version=py38"] + + - repo: https://github.com/pycqa/isort + rev: 5.12.0 + hooks: + - id: isort + args: ["--profile", "black", "--filter-files"] + +ci: + autoupdate_schedule: quarterly + skip: [] + submodules: false From e528324c1e100abfe974f43be6c6241afc26bbd7 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 4 Sep 2023 15:56:34 +0200 Subject: [PATCH 2/5] Add pre-commit as dev dependency --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 28754d3..5f3203d 100644 --- a/setup.py +++ b/setup.py @@ -68,3 +68,4 @@ def load_requirements(requirements_files: Union[Path, list[Path]]) -> list: ] } ) + \ No newline at end of file From c8a983f173adc3b835434606a99ec3d5473198c3 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 4 Sep 2023 15:57:47 +0200 Subject: [PATCH 3/5] Apply git hooks to existing code base --- .gitignore | 2 +- LICENSE | 2 +- mkdocs_git_committers_plugin_2/exclude.py | 2 +- mkdocs_git_committers_plugin_2/plugin.py | 141 +++++++++++++--------- setup.py | 7 +- 5 files changed, 89 insertions(+), 65 deletions(-) diff --git a/.gitignore b/.gitignore index 642307f..9c0aec4 100644 --- a/.gitignore +++ b/.gitignore @@ -114,4 +114,4 @@ venv.bak/ dmypy.json # Pyre type checker -.pyre/ \ No newline at end of file +.pyre/ diff --git a/LICENSE b/LICENSE index b7dedcc..098ebb9 100644 --- a/LICENSE +++ b/LICENSE @@ -16,4 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +SOFTWARE. diff --git a/mkdocs_git_committers_plugin_2/exclude.py b/mkdocs_git_committers_plugin_2/exclude.py index 9edf811..2d4ff7e 100644 --- a/mkdocs_git_committers_plugin_2/exclude.py +++ b/mkdocs_git_committers_plugin_2/exclude.py @@ -2,8 +2,8 @@ Module to assist exclude certain files being processed by plugin. Inspired by https://github.com/apenwarr/mkdocs-exclude """ -import os import fnmatch +import os from typing import List diff --git a/mkdocs_git_committers_plugin_2/plugin.py b/mkdocs_git_committers_plugin_2/plugin.py index b960a7c..c28f56d 100644 --- a/mkdocs_git_committers_plugin_2/plugin.py +++ b/mkdocs_git_committers_plugin_2/plugin.py @@ -1,77 +1,78 @@ -import os -import sys +import json import logging -from pprint import pprint +import os +import re +import time +from datetime import datetime from timeit import default_timer as timer -from datetime import datetime, timedelta -from mkdocs import utils as mkdocs_utils -from mkdocs.config import config_options, Config +import requests +from bs4 import BeautifulSoup as bs +from git import Commit, Repo +from mkdocs.config import config_options from mkdocs.plugins import BasePlugin - -from git import Repo, Commit -import requests, json from requests.exceptions import HTTPError -import time -import hashlib -import re -from bs4 import BeautifulSoup as bs from mkdocs_git_committers_plugin_2.exclude import exclude LOG = logging.getLogger("mkdocs.plugins." + __name__) -class GitCommittersPlugin(BasePlugin): +class GitCommittersPlugin(BasePlugin): config_scheme = ( - ('enterprise_hostname', config_options.Type(str, default='')), - ('repository', config_options.Type(str, default='')), - ('branch', config_options.Type(str, default='master')), - ('docs_path', config_options.Type(str, default='docs/')), - ('enabled', config_options.Type(bool, default=True)), - ('cache_dir', config_options.Type(str, default='.cache/plugin/git-committers')), + ("enterprise_hostname", config_options.Type(str, default="")), + ("repository", config_options.Type(str, default="")), + ("branch", config_options.Type(str, default="master")), + ("docs_path", config_options.Type(str, default="docs/")), + ("enabled", config_options.Type(bool, default=True)), + ("cache_dir", config_options.Type(str, default=".cache/plugin/git-committers")), ("exclude", config_options.Type(list, default=[])), ) def __init__(self): self.total_time = 0 - self.branch = 'master' + self.branch = "master" self.enabled = True self.authors = dict() self.cache_page_authors = dict() self.exclude = list() - self.cache_date = '' + self.cache_date = "" def on_config(self, config): - self.enabled = self.config['enabled'] + self.enabled = self.config["enabled"] if not self.enabled: LOG.info("git-committers plugin DISABLED") return config LOG.info("git-committers plugin ENABLED") - if not self.config['repository']: + if not self.config["repository"]: LOG.error("git-committers plugin: repository not specified") return config - if self.config['enterprise_hostname'] and self.config['enterprise_hostname'] != '': - self.githuburl = "https://" + self.config['enterprise_hostname'] + "/" + if ( + self.config["enterprise_hostname"] + and self.config["enterprise_hostname"] != "" + ): + self.githuburl = "https://" + self.config["enterprise_hostname"] + "/" else: self.githuburl = "https://github.com/" self.localrepo = Repo(".") - self.branch = self.config['branch'] - self.excluded_pages = self.config['exclude'] + self.branch = self.config["branch"] + self.excluded_pages = self.config["exclude"] return config def list_contributors(self, path): - if exclude(path.lstrip(self.config['docs_path']), self.excluded_pages): + if exclude(path.lstrip(self.config["docs_path"]), self.excluded_pages): return None, None - + last_commit_date = "" path = path.replace("\\", "/") for c in Commit.iter_items(self.localrepo, self.localrepo.head, path): if not last_commit_date: # Use the last commit and get the date - last_commit_date = time.strftime("%Y-%m-%d", time.gmtime(c.authored_date)) + last_commit_date = time.strftime( + "%Y-%m-%d", time.gmtime(c.authored_date) + ) # File not committed yet if last_commit_date == "": @@ -80,68 +81,92 @@ def list_contributors(self, path): # Try to leverage the cache if path in self.cache_page_authors: - if self.cache_date and time.strptime(last_commit_date, "%Y-%m-%d") < time.strptime(self.cache_date, "%Y-%m-%d"): - return self.cache_page_authors[path]['authors'], self.cache_page_authors[path]['last_commit_date'] - - url_contribs = self.githuburl + self.config['repository'] + "/contributors-list/" + self.config['branch'] + "/" + path + if self.cache_date and time.strptime( + last_commit_date, "%Y-%m-%d" + ) < time.strptime(self.cache_date, "%Y-%m-%d"): + return ( + self.cache_page_authors[path]["authors"], + self.cache_page_authors[path]["last_commit_date"], + ) + + url_contribs = ( + self.githuburl + + self.config["repository"] + + "/contributors-list/" + + self.config["branch"] + + "/" + + path + ) LOG.info("git-committers: fetching contributors for " + path) LOG.debug(" from " + url_contribs) - authors=[] + authors = [] try: response = requests.get(url_contribs) response.raise_for_status() except HTTPError as http_err: - LOG.error(f'git-committers: HTTP error occurred: {http_err}\n(404 is normal if file is not on GitHub yet or Git submodule)') + LOG.error( + f"git-committers: HTTP error occurred: {http_err}\n(404 is normal if file is not on GitHub yet or Git submodule)" + ) except Exception as err: - LOG.error(f'git-committers: Other error occurred: {err}') + LOG.error(f"git-committers: Other error occurred: {err}") else: html = response.text # Parse the HTML soup = bs(html, "lxml") - lis = soup.find_all('li') + lis = soup.find_all("li") for li in lis: - a_tags = li.find_all('a') - login = a_tags[0]['href'].replace("/", "") + a_tags = li.find_all("a") + login = a_tags[0]["href"].replace("/", "") url = self.githuburl + login name = login - img_tags = li.find_all('img') - avatar = img_tags[0]['src'] - avatar = re.sub(r'\?.*$', '', avatar) - authors.append({'login':login, 'name': name, 'url': url, 'avatar': avatar}) + img_tags = li.find_all("img") + avatar = img_tags[0]["src"] + avatar = re.sub(r"\?.*$", "", avatar) + authors.append( + {"login": login, "name": name, "url": url, "avatar": avatar} + ) # Update global cache_page_authors - self.cache_page_authors[path] = {'last_commit_date': last_commit_date, 'authors': authors} + self.cache_page_authors[path] = { + "last_commit_date": last_commit_date, + "authors": authors, + } return authors, last_commit_date def on_page_context(self, context, page, config, nav): - context['committers'] = [] + context["committers"] = [] if not self.enabled: return context start = timer() - git_path = self.config['docs_path'] + page.file.src_path + git_path = self.config["docs_path"] + page.file.src_path authors, last_commit_date = self.list_contributors(git_path) if authors: - context['committers'] = authors + context["committers"] = authors if last_commit_date: - context['last_commit_date'] = last_commit_date + context["last_commit_date"] = last_commit_date end = timer() - self.total_time += (end - start) + self.total_time += end - start return context def on_post_build(self, config): LOG.info("git-committers: saving page authors cache file") - json_data = json.dumps({'cache_date': datetime.now().strftime("%Y-%m-%d"), 'page_authors': self.cache_page_authors}) - os.makedirs(self.config['cache_dir'], exist_ok=True) - f = open(self.config['cache_dir'] + "/page-authors.json", "w") + json_data = json.dumps( + { + "cache_date": datetime.now().strftime("%Y-%m-%d"), + "page_authors": self.cache_page_authors, + } + ) + os.makedirs(self.config["cache_dir"], exist_ok=True) + f = open(self.config["cache_dir"] + "/page-authors.json", "w") f.write(json_data) f.close() def on_pre_build(self, config): - if os.path.exists(self.config['cache_dir'] + "/page-authors.json"): + if os.path.exists(self.config["cache_dir"] + "/page-authors.json"): LOG.info("git-committers: found page authors cache file - loading it") - f = open(self.config['cache_dir'] + "/page-authors.json", "r") + f = open(self.config["cache_dir"] + "/page-authors.json") cache = json.loads(f.read()) - self.cache_date = cache['cache_date'] - self.cache_page_authors = cache['page_authors'] + self.cache_date = cache["cache_date"] + self.cache_page_authors = cache["page_authors"] f.close() diff --git a/setup.py b/setup.py index 5f3203d..da05848 100644 --- a/setup.py +++ b/setup.py @@ -63,9 +63,8 @@ def load_requirements(requirements_files: Union[Path, list[Path]]) -> list: ], packages=find_packages(), entry_points={ - 'mkdocs.plugins': [ - 'git-committers = mkdocs_git_committers_plugin_2.plugin:GitCommittersPlugin' + "mkdocs.plugins": [ + "git-committers = mkdocs_git_committers_plugin_2.plugin:GitCommittersPlugin" ] - } + }, ) - \ No newline at end of file From 54678aa4feb7ad0b5f3b885faf24e5492f611ac8 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Mon, 4 Sep 2023 15:58:23 +0200 Subject: [PATCH 4/5] Fix built-in type constructor --- mkdocs_git_committers_plugin_2/plugin.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mkdocs_git_committers_plugin_2/plugin.py b/mkdocs_git_committers_plugin_2/plugin.py index c28f56d..e2145f7 100644 --- a/mkdocs_git_committers_plugin_2/plugin.py +++ b/mkdocs_git_committers_plugin_2/plugin.py @@ -33,9 +33,9 @@ def __init__(self): self.total_time = 0 self.branch = "master" self.enabled = True - self.authors = dict() - self.cache_page_authors = dict() - self.exclude = list() + self.authors = {} + self.cache_page_authors = {} + self.exclude = [] self.cache_date = "" def on_config(self, config): From f64f236c055351096dede02caff4a0d74930e1d6 Mon Sep 17 00:00:00 2001 From: GeoJulien Date: Sat, 9 Sep 2023 16:07:51 +0200 Subject: [PATCH 5/5] Apply git hooks --- setup.py | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/setup.py b/setup.py index da05848..be26ec3 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ from pathlib import Path from typing import Union -from setuptools import setup, find_packages +from setuptools import find_packages, setup # The directory containing this file HERE = Path(__file__).parent @@ -9,6 +9,7 @@ # The text of the README file README = (HERE / "README.md").read_text() + def load_requirements(requirements_files: Union[Path, list[Path]]) -> list: """Helper to load requirements list from a path or a list of paths. @@ -36,30 +37,31 @@ def load_requirements(requirements_files: Union[Path, list[Path]]) -> list: return out_requirements + setup( - name='mkdocs-git-committers-plugin-2', - version='1.2.0', - description='An MkDocs plugin to create a list of contributors on the page. The git-committers plugin will seed the template context with a list of github committers and other useful GIT info such as last modified date', + name="mkdocs-git-committers-plugin-2", + version="1.2.0", + description="An MkDocs plugin to create a list of contributors on the page. The git-committers plugin will seed the template context with a list of github committers and other useful GIT info such as last modified date", long_description=README, long_description_content_type="text/markdown", - keywords='mkdocs pdf github', - url='https://github.com/ojacques/mkdocs-git-committers-plugin-2/', - author='Byrne Reese, Olivier Jacques', - author_email='byrne@majordojo.com, ojacques2@gmail.com', - license='MIT', - python_requires='>=3.8,<4', + keywords="mkdocs pdf github", + url="https://github.com/ojacques/mkdocs-git-committers-plugin-2/", + author="Byrne Reese, Olivier Jacques", + author_email="byrne@majordojo.com, ojacques2@gmail.com", + license="MIT", + python_requires=">=3.8,<4", install_requires=load_requirements(HERE / "requirements.txt"), classifiers=[ - 'Development Status :: 4 - Beta', - 'Intended Audience :: Developers', - 'Intended Audience :: Information Technology', - 'License :: OSI Approved :: MIT License', - 'Programming Language :: Python', - 'Programming Language :: Python :: 3 :: Only', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10', - 'Programming Language :: Python :: 3.11' + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Intended Audience :: Information Technology", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", ], packages=find_packages(), entry_points={