Skip to content

Commit

Permalink
Merge branch 'main' into __update_pip__
Browse files Browse the repository at this point in the history
  • Loading branch information
JeanChristopheMorinPerso authored Jan 19, 2025
2 parents cbe6f4a + 2928d20 commit 92b1d9e
Show file tree
Hide file tree
Showing 52 changed files with 2,822 additions and 444 deletions.
16 changes: 16 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[run]
branch = True
source_pkgs=rez_pip

[paths]
; Map files to src/ so that codecov is happy and can find the right paths.
source =
src
.nox/**/site-packages

[report]
exclude_also =
def __dir__
if TYPE_CHECKING:
if typing\.TYPE_CHECKING:
\.\.\.
5 changes: 5 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto

# Denote all files that are truly binary and should not be modified.
*.patch binary
8 changes: 5 additions & 3 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: test

on:
push:
branches: [main]
paths-ignore:
- .github/workflows/update_pip.yaml
- 'docs/**'
Expand All @@ -26,10 +27,10 @@ jobs:

strategy:
matrix:
python: ['3.7', '3.8', '3.9', '3.10', '3.11']
python: ['3.8', '3.9', '3.10', '3.11']
# Ping macos to 13 so that we get intel CPUs.
# TODO: Make our tests support arm64.
os: ['ubuntu-latest', 'windows-latest', 'macos-13']
os: ['ubuntu-latest', 'windows-latest', 'macos-latest']
fail-fast: false

steps:
Expand All @@ -42,9 +43,10 @@ jobs:
run: pipx run nox --error-on-missing-interpreter -s test-${{ matrix.python }}

- name: Codecov upload
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v5
with:
files: 'coverage.xml'
disable_search: true
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,4 @@ tests/data/rez_repo/
tests/data/_tmp_download/
docs/bin/
.idea/
/patches
2 changes: 1 addition & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
sphinx ~= 7.3
sphinx ~= 8.1
furo
sphinx-autobuild
sphinx-inline-tabs
Expand Down
27 changes: 27 additions & 0 deletions docs/source/api.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
===
API
===

.. warning:: The API is only meant to be used by plugins authors.

.. autoclass:: rez_pip.pip.T

.. autoclass:: rez_pip.pip.DownloadInfo
:members:

.. autoclass:: rez_pip.pip.Metadata
:members:
:undoc-members:

.. autoclass:: rez_pip.pip.PackageInfo
:members:

.. autoclass:: rez_pip.pip.PackageGroup
:members:
:show-inheritance:

.. autoclass:: rez_pip.pip.DownloadedArtifact
:members:

.. autoclass:: rez_pip.plugins.CleanupAction
:members:
178 changes: 175 additions & 3 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,20 @@
# https://www.sphinx-doc.org/en/master/usage/configuration.html

import re
import inspect
import argparse
import importlib

import docutils.nodes
import sphinx.transforms
import sphinx.util.nodes
import sphinx.application
import sphinx.ext.autodoc
import sphinx.util.docutils
import docutils.statemachine

import rez_pip.cli
import rez_pip.plugins

# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
Expand All @@ -25,6 +31,7 @@

extensions = [
# first-party extensions
"sphinx.ext.todo",
"sphinx.ext.autodoc",
"sphinx.ext.extlinks",
"sphinx.ext.intersphinx",
Expand Down Expand Up @@ -55,21 +62,34 @@
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-the-linkcheck-builder

linkcheck_allowed_redirects = {
r"https://github.com/JeanChristopheMorinPerso/rez-pip/issues/\d+": "https://github.com/JeanChristopheMorinPerso/rez-pip/pull/\d+"
r"https://github.com/JeanChristopheMorinPerso/rez-pip/issues/\d+": r"https://github.com/JeanChristopheMorinPerso/rez-pip/pull/\d+"
}


# -- Options for sphinx.ext.intersphinx_mapping ------------------------------
# https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html

intersphinx_mapping = {
"python": ("https://docs.python.org/3", None),
"rez": ("https://rez.readthedocs.io/en/stable/", None),
}

# Force usage of :external:
intersphinx_disabled_reftypes = ["*"]
# intersphinx_disabled_reftypes = ["*"]


# -- Options for sphinx.ext.autodoc ------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html

# autodoc_typehints = "description"
autodoc_typehints_format = "short"
autodoc_member_order = "bysource"

# -- Options for sphinx.ext.todo --------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/extensions/todo.html

todo_include_todos = True

# -- Custom ------------------------------------------------------------------
# Custom stuff

Expand Down Expand Up @@ -194,7 +214,7 @@ def run(self) -> list[docutils.nodes.Node]:

# Add links to rez docs for known settings.
help_str = re.sub(
"(.* \(default: configured )([a-zA-Z_]+)(.*)$",
r"(.* \(default: configured )([a-zA-Z_]+)(.*)$",
r"\g<1> :external:data:`\g<2>`\g<3>",
help_str,
)
Expand Down Expand Up @@ -235,6 +255,158 @@ def run(self) -> list[docutils.nodes.Node]:
return node.children


class RezAutoPlugins(sphinx.util.docutils.SphinxDirective):
"""
Special rez-pip-autoplugins directive. This is quite similar to "autosummary" in some ways.
"""

required_arguments = 0
optional_arguments = 0

def run(self) -> list[docutils.nodes.Node]:
# Create the node.
node = docutils.nodes.section()
node.document = self.state.document

rst = docutils.statemachine.ViewList()

# Add rezconfig as a dependency to the current document. The document
# will be rebuilt if rezconfig changes.
self.env.note_dependency(rez_pip.plugins.__file__)
self.env.note_dependency(__file__)

path, lineNumber = self.get_source_info()

document = []
for plugin, hooks in rez_pip.plugins._getHookImplementations().items():
hooks = [f":func:`{hook}`" for hook in hooks]
document.append(f"* {plugin.split('.')[-1]}: {', '.join(hooks)}")

document = "\n".join(document)

# Add each line to the view list.
for index, line in enumerate(document.split("\n")):
# Note to future people that will look at this.
# "line" has to be a single line! It can't be a line like "this\nthat".
rst.append(line, path, lineNumber + index)

# Finally, convert the rst into the appropriate docutils/sphinx nodes.
sphinx.util.nodes.nested_parse_with_titles(self.state, rst, node)

# Return the generated nodes.
return node.children


class RezPipAutoPluginHooks(sphinx.util.docutils.SphinxDirective):
"""
Special rez-pip-autopluginhooks directive. This is quite similar to "autosummary" in some ways.
"""

required_arguments = 1
optional_arguments = 0

def run(self) -> list[docutils.nodes.Node]:
# Create the node.
node = docutils.nodes.section()
node.document = self.state.document

rst = docutils.statemachine.ViewList()

# Add rezconfig as a dependency to the current document. The document
# will be rebuilt if rezconfig changes.
self.env.note_dependency(rez_pip.plugins.__file__)
self.env.note_dependency(__file__)

path, lineNumber = self.get_source_info()

fullyQualifiedClassName = self.arguments[0]
module, klassname = fullyQualifiedClassName.rsplit(".", 1)

mod = importlib.import_module(module)
klass = getattr(mod, klassname)

methods = [
method
for method in inspect.getmembers(klass, predicate=inspect.isfunction)
if not method[0].startswith("_")
]

document = []
for method in sorted(methods, key=lambda x: x[1].__code__.co_firstlineno):
document.append(f".. autohook:: {module}.{klassname}.{method[0]}")

document = "\n".join(document)

# Add each line to the view list.
for index, line in enumerate(document.split("\n")):
# Note to future people that will look at this.
# "line" has to be a single line! It can't be a line like "this\nthat".
rst.append(line, path, lineNumber + index)

# Finally, convert the rst into the appropriate docutils/sphinx nodes.
sphinx.util.nodes.nested_parse_with_titles(self.state, rst, node)

# Return the generated nodes.
return node.children


def autodoc_process_signature(
app: sphinx.application.Sphinx,
what: str,
name: str,
obj,
options: dict,
signature: str,
return_annotation,
):
signature = signature.replace(
"rez_pip.compat.importlib_metadata", "~importlib.metadata"
)

return signature, return_annotation


class HookDocumenter(sphinx.ext.autodoc.FunctionDocumenter):
"""
Custom autohook directive to document our hooks.
It allows us to easily document the hooks from the rez_pip.plugins.PluginSpec
class without exposing the class and module name.
"""

objtype = "hook" # auto + hook
directivetype = "function" # generated reST directive

def format_signature(self, **kwargs) -> str:
"""
Format the signature and remove self. We really don't want to expose
the class and module name or the fact that we are documenting methods.
"""
sig = super().format_signature(**kwargs)
sig = re.sub(r"\(self(,\s)?", "(", sig)

# Also force short names for our own types
sig = sig.replace("rez_pip.", "~rez_pip.")

return sig

def add_directive_header(self, sig):
modname = self.modname
# Hacky, but it does the job. This should remove the module name from the directive
# created by autodoc.
self.modname = ""

data = super().add_directive_header(sig)

# We need to restore it because autodoc does lots of things with the module name.
self.modname = modname
return data


def setup(app: sphinx.application.Sphinx):
app.add_directive("rez-autoargparse", RezAutoArgparseDirective)
app.add_directive("rez-pip-autoplugins", RezAutoPlugins)
app.add_directive("rez-pip-autopluginhooks", RezPipAutoPluginHooks)
app.add_transform(ReplaceGHRefs)

app.connect("autodoc-process-signature", autodoc_process_signature)
app.add_autodocumenter(HookDocumenter)
27 changes: 25 additions & 2 deletions docs/source/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,31 @@ FAQ

List of commonly asked questions.

Why does the rez package created by rez-pip creates a variant per platform?
===========================================================================
Which packages does it support?
===============================

It technically supports all packages available on PyPI that are distributed as wheels.
Packages that only provide an sdist are not supported.

We say "technically" because there are some exceptions. Some packages on PyPI rely
on DSOs (shared libraries, i.e. ``.so``/``.DLL``/``.dylib`` files) that are not available on
all platforms. This is normal and is supported for most packages. However, there are some
packages that rely on methods like adding paths using :func:`os.add_dll_directory` or
hardcoded paths.

Some others rely on `path configuration (.pth) files <https://docs.python.org/3/library/site.html>`_.

When a package relies on these methods, rez-pip will successfully install it, but
the package might not function correctly (either partly or entirely).

The :doc:`plugin system <plugins>` was created to handled these cases. You can use plugins
to modify the package metatada, patch source files, add/remove files, etc.

``rez-pip`` comes with some :ref:`built-in plugins <plugins:built-in plugins>` for packages that are popular
in our communities and are known to be "broken" when installed with ``rez-pip``.

Why does the rez package created by rez-pip create a variant per platform?
==========================================================================

Sometimes rez-pip creates rez packages that have variants for the platform and arch on which they were installed,
and sometimes it even creates variants for Python versions. Bellow are the scenarios
Expand Down
3 changes: 3 additions & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Features
create per python version variants when installing a package that has console scripts.
* Better output logs.
* Implemented as an out-of-tree plugin, which means faster development cycle and more frequent releases.
* :doc:`Plugin system <plugins>` that allows for easy extensibility (experimental).
* Maintained by the rez maintainers.

Prerequisites
Expand Down Expand Up @@ -69,5 +70,7 @@ automatically created by the `install.py <https://github.com/AcademySoftwareFoun
command
transition
metadata
plugins
api
faq
changelog
Loading

0 comments on commit 92b1d9e

Please sign in to comment.