From e85cd0e3a6aeaf5b0ffbc88679dadf2098171bfe Mon Sep 17 00:00:00 2001 From: Roberto Prevato Date: Mon, 3 Oct 2022 21:07:12 +0200 Subject: [PATCH] Improve contribs :shield: --- CHANGELOG.md | 14 +++++++--- neoteroi/contribs/__init__.py | 1 + neoteroi/contribs/domain.py | 1 + neoteroi/contribs/git.py | 34 +++++++++++++++++++---- neoteroi/contribs/html.py | 5 ++-- neoteroi/markdown/commands.py | 52 ----------------------------------- setup.py | 3 +- styles/contribs.scss | 4 +-- styles/timeline.scss | 2 ++ 9 files changed, 48 insertions(+), 68 deletions(-) delete mode 100644 neoteroi/markdown/commands.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f68ab8..0f53f3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,14 +5,20 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.0] - 2022-10-03 +- Corrects bug in the `contributors` plugin, causing failures in certain CI/CD + solutions and improves its safety and performance (removes `shell=True`!) +- Adds option to apply a class to specific contributors, for simpler styling +- Minor improvements to styles + ## [0.0.9] - 2022-10-02 - Improves the `contributors` plugin: - - Adds the possibility to exclude contributor information (for example to not display - contributions from bots). + contributions from bots) - - Adds the possibility to merge contributors' information - for cases in which the same person commits using two different email addresses. -- - Adds the possibility to display an element with the count of contributors. -- Resolves a small issue in pip package resolution. + for cases in which the same person commits using two different email addresses +- - Adds the possibility to display an element with the count of contributors +- Resolves a small issue in pip package resolution ## [0.0.8] - 2022-10-01 - Improves the Gantt extension: diff --git a/neoteroi/contribs/__init__.py b/neoteroi/contribs/__init__.py index a70965a..83f5e8c 100644 --- a/neoteroi/contribs/__init__.py +++ b/neoteroi/contribs/__init__.py @@ -84,6 +84,7 @@ def _get_contributors(self, page_file: File) -> List[Contributor]: ) if contributor_info: contributor.image = contributor_info.get("image") + contributor.key = contributor_info.get("key") if contributor_info.get("ignore"): # ignore the contributor's information (can be useful for bots) diff --git a/neoteroi/contribs/domain.py b/neoteroi/contribs/domain.py index 27354a7..27d6028 100644 --- a/neoteroi/contribs/domain.py +++ b/neoteroi/contribs/domain.py @@ -11,6 +11,7 @@ class Contributor: email: str count: int = -1 image: Optional[str] = None + key: Optional[str] = None class ContributionsReader(ABC): diff --git a/neoteroi/contribs/git.py b/neoteroi/contribs/git.py index e46df18..00d0ccb 100644 --- a/neoteroi/contribs/git.py +++ b/neoteroi/contribs/git.py @@ -1,4 +1,5 @@ import re +import subprocess from datetime import datetime from pathlib import Path from typing import Iterable, List, Tuple @@ -6,13 +7,18 @@ from dateutil.parser import parse as parse_date from neoteroi.contribs.domain import ContributionsReader, Contributor -from neoteroi.markdown.commands import Command class GitContributionsReader(ContributionsReader): _name_email_rx = re.compile(r"(?P[\w\s]+)\s<(?P[^\>]+)>") + def _decode(self, value: bytes) -> str: + try: + return value.decode("utf8") + except UnicodeDecodeError: + return value.decode("ISO-8859-1") + def _parse_name_and_email(self, name_and_email) -> Tuple[str, str]: match = self._name_email_rx.search(name_and_email) if match: @@ -33,14 +39,30 @@ def get_contributors(self, file_path: Path) -> List[Contributor]: Obtains the list of contributors for a file with the given path, using the Git CLI. """ - command = Command(f'git shortlog --summary --numbered --email "{file_path}"') + in_process = subprocess.Popen( + ["git", "log", "--pretty=short"], stdout=subprocess.PIPE + ) + result = self._decode( + subprocess.check_output( + [ + "git", + "shortlog", + "--summary", + "--numbered", + "--email", + str(file_path), + ], + stdin=in_process.stdout, + ) + ) - result = command.execute() return list(self.parse_committers(result)) def get_last_commit_date(self, file_path: Path) -> datetime: """Reads the last commit on a file.""" - command = Command(f'git log -1 --pretty="format:%ci" "{file_path}"') - - result = command.execute() + result = self._decode( + subprocess.check_output( + ["git", "log", "-1", "--pretty=format:%ci", str(file_path)] + ) + ) return parse_date(result) diff --git a/neoteroi/contribs/html.py b/neoteroi/contribs/html.py index 42d8270..8c6d2c7 100644 --- a/neoteroi/contribs/html.py +++ b/neoteroi/contribs/html.py @@ -33,7 +33,7 @@ def contribution_stats_to_element( if options.show_last_modified_time: last_modified_time = etree.SubElement( element, - "em", + "p", {"class": "nt-mod-time"}, ) if options.last_modified_label: @@ -56,7 +56,8 @@ def contribution_stats_to_element( sorted(contributors, key=lambda item: item.count, reverse=True) ): props = { - "class": "nt-contributor", + "class": "nt-contributor" + + (f" {contributor.key}" if contributor.key else ""), "title": ( f"{contributor.name} <{contributor.email}> ({contributor.count})" ), diff --git a/neoteroi/markdown/commands.py b/neoteroi/markdown/commands.py deleted file mode 100644 index 0a85286..0000000 --- a/neoteroi/markdown/commands.py +++ /dev/null @@ -1,52 +0,0 @@ -import logging -import subprocess - -logger = logging.getLogger("MARKDOWN") - - -class Command: - def __init__(self, command: str): - self._command = None - self.command = command - - @property - def command(self): - if not self._command: - raise TypeError("Missing command") - return self._command - - @command.setter - def command(self, value): - self._command = value - - def execute(self) -> str: - logger.debug(f"\nNeoteroi Contrib; executing command:\n {self.command}\n") - p = subprocess.Popen( - self.command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE - ) - if p.stdout is None: - raise TypeError("Missing subprocess stdout") - - output = p.stdout.read() - error_output = p.stderr.read() if p.stderr else None - - try: - output = output.decode("utf8") - except UnicodeDecodeError: - output = output.decode("ISO-8859-1") - - if error_output: - raise RuntimeError( - f"Process failed with return code: " - f"{p.returncode}.\nOutput: {output}" - ) - - if p.returncode is not None and p.returncode != 0: - raise RuntimeError( - f"Process failed with return code: " - f"{p.returncode}.\nOutput: {output}" - ) - - if output: - logger.debug(f"Neoteroi Contrib; got output:\n {output}\n") - return output diff --git a/setup.py b/setup.py index 56ce237..8d422e0 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ def readme(): setup( name="neoteroi-mkdocs", - version="0.0.9", + version="0.1.0", description="Plugins for MkDocs and Python Markdown", long_description=readme(), long_description_content_type="text/markdown", @@ -16,7 +16,6 @@ def readme(): "Development Status :: 4 - Beta", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", diff --git a/styles/contribs.scss b/styles/contribs.scss index da5d081..216000f 100644 --- a/styles/contribs.scss +++ b/styles/contribs.scss @@ -35,14 +35,14 @@ $dot-size: 40px; .nt-initials { text-transform: uppercase; - font-size: 24px; + font-size: 20px; text-align: center; width: $dot-size; height: $dot-size; display: inline-block; vertical-align: middle; position: relative; - top: 2px; + top: 4px; color: inherit; font-weight: bold; } diff --git a/styles/timeline.scss b/styles/timeline.scss index e8d77b1..6f2c982 100644 --- a/styles/timeline.scss +++ b/styles/timeline.scss @@ -304,6 +304,8 @@ .icon { color: white; + position: relative; + top: 1px; } }