Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,7 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

.vscode/*
src/sphinx-contribs/_version.py
_build/*
59 changes: 59 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Config for pre-commit CI https://pre-commit.ci/
# Common tasks
#
# - Run on all files: pre-commit run --all-files
# - Register git hooks: pre-commit install --install-hooks
# - Run a specific hook on all files: pre-commit run codespell --all-files
ci:
autofix_commit_msg: |
[pre-commit.ci] Automatic linting and formatting fixes
autofix_prs: true
autoupdate_commit_msg: "[pre-commit.ci] pre-commit autoupdate hooks"
autoupdate_schedule: monthly

# Fix the node version to avoid a GLIBC error
# ref: https://stackoverflow.com/questions/71939099/bitbucket-pipeline-error-installing-pre-commit-ts-lint/71940852#71940852
default_language_version:
node: 16.14.2

repos:
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.7.1
hooks:
- id: prettier
# Exclude the HTML, since it doesn't understand Jinja2
# exclude also the webpack.config.js file has it embed complete url dificult to prettify
# exclude the pytest-regressions folder tests/test_ally
exclude: .+\.html|webpack\.config\.js|tests/test_a11y/

- repo: https://github.com/psf/black
rev: 22.12.0
hooks:
- id: black

# - repo: https://github.com/charliermarsh/ruff-pre-commit
# rev: "v0.0.215"
# hooks:
# - id: ruff

- repo: https://github.com/asottile/pyupgrade
rev: v3.3.1
hooks:
- id: pyupgrade
args: [--py37-plus]

# - repo: https://github.com/Riverside-Healthcare/djLint
# rev: v1.19.7
# hooks:
# - id: djlint-jinja
# types_or: ["html"]

# - repo: https://github.com/PyCQA/doc8
# rev: v1.1.1
# hooks:
# - id: doc8

# - repo: "https://github.com/kynan/nbstripout"
# rev: "0.5.0"
# hooks:
# - id: nbstripout
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# sphinx-page-contributors

A sphinx extension to add contributors to a page.
Empty file added development.md
Empty file.
31 changes: 31 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Sphinx docs config

import sphinx_contribs

project = "Sphinx Contributor Extension"
copyright = "2024, pyOpenSci Community"
author = "pyOpenSci Community"
release = "0.1"

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

extensions = [
"sphinx_contribs",
"myst_parser",
]

templates_path = ["_templates"]
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]


# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output

html_theme = "pydata_sphinx_theme"
html_static_path = ["_static"]

# Settings for sphinx-contribs ext
repo_name = "pyopensci/python-package-guide"

# html_theme_options = {navigation_with_keys: False}
8 changes: 8 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Welcome to sphinx-contribs's documentation!

This is actually working!! Right now it's pulling contribs however
from a online GitHub repo. And i think we want this to work on the repo
in the current envt potentially? i'm not sure

but right now its grabbing repo contribs for index.md from our online
packaging guide index.md file.
39 changes: 39 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
[build-system]
requires = ["hatchling", "hatch-vcs"]
build-backend = "hatchling.build"

[project]
name = "sphinx_contribs"
version = "0.1"
#dynamic = ["version"]
description = 'A package that gets contributors via commits to each page'
readme = "README.md"
requires-python = ">=3.10"
license = "MIT"
keywords = []
authors = [
{ name = "pyOpenSci Community", email = "[email protected]" },
]
classifiers = [
"Development Status :: 4 - Beta",
"Programming Language :: Python",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
]
dependencies = ["sphinx>=3.0", "pygithub"]

[project.urls]
Documentation = "https://github.com/pyopensci/sphinx-contribs#readme"
Issues = "https://github.com/pyopensci/sphinx-contribs/issues"
Source = "https://github.com/pyopensci/sphinx-page-contribs"

# [tool.hatch]
# version.source = "vcs"
# build.hooks.vcs.version-file = "src/sphinx-contribs/_version.py"

# Setup the extension as a hook
# [tool.hatch.metadata.hooks]
# sphinx-contribs = "sphinx_contribs.contribs:setup"
19 changes: 19 additions & 0 deletions src/sphinx_contribs/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from sphinx.application import Sphinx

from .contribs import fetch_unique_committers


def setup(app: Sphinx):
"""The setup function for Sphinx. This connects the sphinx processing to
the functions in this module.

Parameters
----------
app : Sphinx
_description_
"""

app.add_config_value("repo_name", "default/repo", "env")
app.connect("source-read", fetch_unique_committers)
# app.connect("html-page-context", add_committers_to_context)
# app.add_config_value("ignore_files", [], "env")
17 changes: 17 additions & 0 deletions src/sphinx_contribs/_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# file generated by setuptools_scm
# don't change, don't track in version control
TYPE_CHECKING = False
if TYPE_CHECKING:
from typing import Tuple, Union

VERSION_TUPLE = Tuple[Union[int, str], ...]
else:
VERSION_TUPLE = object

version: str
__version__: str
__version_tuple__: VERSION_TUPLE
version_tuple: VERSION_TUPLE

__version__ = version = "0.1.dev3+g44342dc"
__version_tuple__ = version_tuple = (0, 1, "dev3", "g44342dc")
192 changes: 192 additions & 0 deletions src/sphinx_contribs/contribs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
"""Currently using mamba envt: contributors for pygithub

This is the mkdocs plugin
https://github.com/byrnereese/mkdocs-git-committers-plugin/blob/master/mkdocs_git_committers_plugin/plugin.py

# Install extension
pip install -e .
# Build docs
sphinx-build -b html . _build/html

https://www.sphinx-doc.org/en/master/development/tutorials/helloworld.html

For this to work, setup your GITHUB token in your zsh, bashprofile envt

Right now this is slow as it will process all commits for each file.
Instead we probably want to create some sort of cache that has a history of
what has been processed. so it them only processes the most recent commits
and files.

we also want to allow it to ignore some files (which could be a sphinx conf.py
setting)
"""

import os

from github import Github

print("Loading contributors extension.")

GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")

github = Github(GITHUB_TOKEN)


def fetch_unique_committers(app, docname, source):
"""
Fetch the unique committers for a given document and store the data in the
Sphinx environment.

This function is called by Sphinx for each document due to the connection
established
in the setup function to the 'source-read' event. It fetches the committers
for the document
based on its GitHub commit history.

Parameters
----------
app : Sphinx application object
The Sphinx application context which provides access to Sphinx's
configurations and methods.
docname : str
The name of the document being processed, which corresponds to the
file name without the extension.
source : list
The list containing the source content of the document. The list has a
single element, which is a string.
"""

# if docname in app.config.ignore_files:
# return

repo_name = app.config.repo_name
repo = github.get_repo(repo_name)
file_path = f"{docname}.md"
print("Fetching committers for:", file_path)
# Pass GITHUB_TOKEN to this function properly
unique_committers = get_unique_committers(GITHUB_TOKEN, repo, file_path)
print("Committers are", unique_committers)
# Store committers in the environment to be used later in the build
if not hasattr(app.env, "committers_data"):
app.env.committers_data = {}

app.env.committers_data[docname] = unique_committers

# Append to markdown file instead as a test???
committer_list = "\n".join(
[
f"- {committer['name']} ([@{committer['login']}]({committer['profile_url']}))"
for committer in unique_committers
]
)
markdown_contributors = f"\n\n## Contributors\n{committer_list}\n"

# Append this markdown to the original document source
source[0] += markdown_contributors


def add_committers_to_context(app, pagename, templatename, context, doctree):
"""
Add committer data to the HTML page context if available.

This function is connected to the 'html-page-context' event in Sphinx.
It's called before rendering
the HTML page, allowing the injection of additional data into the page
context.

Parameters
----------
app : Sphinx application object
The Sphinx application context.
pagename : str
The name of the page being rendered.
templatename : str
The name of the template being used.
context : dict
The context dictionary that the template will use. You can add
additional data to this dictionary.
doctree : document tree node
The doctree of the page, which can be used to extract additional
metadata or content if needed.
"""

if hasattr(app.env, "committers_data") and pagename in app.env.committers_data:
context["committers"] = app.env.committers_data[pagename]


def get_unique_committers(github_token, repo, file_path):
commits = repo.get_commits(path=file_path)
unique_committers = set()

for commit in commits:
if commit.author:
unique_committers.add(commit.author.login)

committers_info = []
for login in unique_committers:
user = github.get_user(login)
committers_info.append(
{
"login": user.login,
"name": user.name,
"avatar_url": user.avatar_url,
"profile_url": f"https://github.com/{login}",
}
)

return committers_info


# def list_markdown_files(repo):
# """
# List all Markdown files in the repository.
# NOTE: this will also return readme and other files that we may not want
# to consider.
# """
# markdown_files = []
# contents = repo.get_contents("") # Start at the root directory
# while contents:
# file_content = contents.pop(0)
# if file_content.type == "dir":
# contents.extend(
# repo.get_contents(file_content.path)
# ) # Add directory contents to list
# elif file_content.path.endswith(".md"):
# markdown_files.append(file_content.path)
# return markdown_files


# def get_unique_committers(github_token, repo_name, file_path):
# # Here this will be getting a repo online. but generally this
# # will be run as the docs are built in CI or locally. so
# # this approach doesnt make sense to me.

# commits = repo.get_commits(path=file_path)
# unique_committers = set()

# for commit in commits:
# if commit.author:
# unique_committers.add(commit.author.login)

# committers_info = []
# for login in unique_committers:
# user = github.get_user(login)
# committers_info.append(
# {
# "login": user.login,
# "name": user.name,
# "avatar_url": user.avatar_url,
# "profile_url": f"https://github.com/{login}",
# }
# )

# return committers_info


# md_files = list_markdown_files(repo)

# # Process each markdown file and get contributors
# people = {}
# for gh_file in md_files:
# print("Processing: ", gh_file)
# people[gh_file] = get_unique_committers(GITHUB_TOKEN, REPO_NAME, gh_file)