Skip to content
Merged
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
23 changes: 23 additions & 0 deletions .readthedocs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# .readthedocs.yml
# Read the Docs configuration file
version: 2

build:
os: ubuntu-22.04
tools:
python: "3.12"

python:
install:
- requirements: docs/requirements.txt
- method: pip
path: .

sphinx:
configuration: docs/source/conf.py

# Optionally, set the documentation type
# formats:
# - html
# - pdf
# - epub
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ For more information to debug `pytest` test suites see
## Running GitHub actions locally using `act`

With `docker` (or `podman`) installed, [act](https://github.com/nektos/act) can be used to run
the CI jobs configured in [.actrc](.actrc):
the CI jobs configured in [`.actrc`](https://github.com/xenserver/python-libs/blob/master/.actrc):

- `act` uses `docker` (also mimicked by `podman-docker`) to run GitHub actions locally
- While `act` does not use the same GitHub runner images, they are similar.
Expand Down
57 changes: 57 additions & 0 deletions DOCUMENTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Documenting using Sphinx

This project uses **Google style docstrings** for Python code documentation. These docstrings are compatible with Sphinx (with the `sphinx.ext.napoleon` extension) and other documentation tools.

## Why Google Style Docstrings?

- Clear, readable format
- Widely supported by documentation generators
- Easy to maintain

## Example Google Style Docstring

```python
def add(a: int, b: int) -> int:
"""Add two integers.

Args:
a (int): First integer.
b (int): Second integer.

Returns:
int: The sum of `a` and `b`.

Raises:
ValueError: If either argument is not an integer.
"""
if not isinstance(a, int) or not isinstance(b, int):
raise ValueError("Arguments must be integers.")
return a + b
```

## Steps to Document Your Code

1. **Write Google style docstrings** for all public modules, classes, and functions.
2. **Include sections** such as `Args`, `Returns`, `Raises`, and `Examples` as needed.
3. **Keep docstrings concise and informative.**

## Benefits of using Sphinx

- Supports docstring formats – such as Google-style, NumPy-style, and reST.
- Autodoc extension – can automatically extract documentation from Python docstrings.
- Integration with Read the Docs – makes it easy to publish and host documentation online.
- Theme support – like Read the Docs theme or the modern Furo theme.

## Building the documentation

```bash
pip install -r docs/requirements.txt
make -C docs html
```

Open `docs/html/index.html` in a web browser.

## References

- [Google Python Style Guide](https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings)
- [Sphinx Napoleon Documentation](https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html)
53 changes: 10 additions & 43 deletions README-Unicode.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Python3 Unicode migration in the XCP package
# Unicode migration

## Problem

Expand Down Expand Up @@ -79,7 +79,7 @@ When this is known to be the case, `encoding="iso-8859-1` could be tried (not te
With the locale set to C (XAPI plugins have that), Python's default mode changes
between 3.6 and 3.7:

```py
```sh
for i in 3.{6,7,10,11};do echo -n "3.$i: ";
LC_ALL=C python3.$i -c 'import locale,sys;print(locale.getpreferredencoding())';done
3.6: ANSI_X3.4-1968
Expand All @@ -90,9 +90,12 @@ for i in 3.{6,7,10,11};do echo -n "3.$i: ";

This has the effect that in Python 3.6, the default codec for XAPI plugins is `ascii`:

```py
```sh
for i in 2.7 3.{6,7};do echo "$i:";
LC_ALL=C python$i -c 'open("/usr/share/hwdata/pci.ids").read()';done
```

```
2.7:
3.6:
Traceback (most recent call last):
Expand All @@ -111,54 +114,18 @@ While Python 3.7 and newer use UTF-8 mode by default, it does not set up an erro

As it happens, some older tools output ISO-8859-1 characters hard-coded and these aren't valid UTF-8 sequences, and even newer Python versions need error handlers to not fail:

```py
```sh
echo -e "\0262" # ISO-8859-1 for: "²"
python3 -c 'open(".text").read()'
```

```
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "<frozen codecs>", line 322, in decode
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb2 in position 0: invalid start byte
```

```py
pylint -d all -e unspecified-encoding --msg-template="{path} line {line} in {obj}()" xcp/ tests/
************* Module xcp.accessor
xcp/accessor.py line 165 in MountingAccessor.writeFile()
xcp/accessor.py line 240 in FileAccessor.writeFile()
************* Module xcp.bootloader
xcp/bootloader.py line 111 in Bootloader.readExtLinux()
xcp/bootloader.py line 219 in Bootloader.readGrub()
xcp/bootloader.py line 335 in Bootloader.readGrub2()
xcp/bootloader.py line 465 in Bootloader.writeExtLinux()
xcp/bootloader.py line 507 in Bootloader.writeGrub()
xcp/bootloader.py line 541 in Bootloader.writeGrub2()
************* Module xcp.cmd
xcp/cmd.py line 67 in OutputCache.fileContents()
************* Module xcp.dom0
xcp/dom0.py line 85 in default_memory()
************* Module xcp.environ
xcp/environ.py line 48 in readInventory()
************* Module xcp.logger
xcp/logger.py line 51 in openLog()
************* Module xcp.net.ifrename.dynamic
xcp/net/ifrename/dynamic.py line 95 in DynamicRules.load_and_parse()
xcp/net/ifrename/dynamic.py line 292 in DynamicRules.save()
************* Module xcp.net.ifrename.static
xcp/net/ifrename/static.py line 118 in StaticRules.load_and_parse()
xcp/net/ifrename/static.py line 330 in StaticRules.save()
************* Module tests.test_biosdevname
tests/test_biosdevname.py line 30 in TestDeviceNames.test()
tests/test_biosdevname.py line 32 in TestDeviceNames.test()
************* Module tests.test_bootloader
tests/test_bootloader.py line 32 in TestLinuxBootloader.setUp()
tests/test_bootloader.py line 34 in TestLinuxBootloader.setUp()
tests/test_bootloader.py line 36 in TestLinuxBootloader.setUp()
tests/test_bootloader.py line 38 in TestLinuxBootloader.setUp()
************* Module tests.test_pci
tests/test_pci.py line 96 in TestPCIIds.test_videoclass_by_mock_calls()
tests/test_pci.py line 110 in TestPCIIds.mock_lspci_using_open_testfile()
```

Of course, `xcp/net/ifrename` won't be affected but it would be good to fix the
warning for them as well in an intelligent way. See the proposal for that below.

Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ open a recent workflow run the latest and scroll down until you see the tables!

## Installation and setup of the development environment

For the installation of the general development dependencies, visit [CONTRIBUTING.md](CONTRIBUTING.md)
For the installation of the general development dependencies, visit [CONTRIBUTING.md]

## Static analysis using mypy, pylint, pyright and pytype

Expand Down Expand Up @@ -112,15 +112,15 @@ As proof, these examples show how the comment below triggers the checks:

mypy:

```py
```sh
$ mypy xcp/xmlunwrap.py
xcp/xmlunwrap.py:31: error: Name "Element" is not defined
xcp/xmlunwrap.py:38: error: Incompatible return value type (got "bytes", expected "str")
```

pyright (used by VS Code by default):

```py
```sh
$ pyright xcp/xmlunwrap.py|sed "s|$PWD/||"
...
pyright 1.1.295
Expand All @@ -141,7 +141,7 @@ See <https://github.com/xenserver/python-libs/pull/23> for the context of this e
## Guidelines

Charset encoding/string handling:
See [README-Unicode.md](README-Unicode.md) for details on Unicode support.
See [README-Unicode.md] for details on Unicode support.

## Users

Expand Down Expand Up @@ -174,7 +174,7 @@ See [README-Unicode.md](README-Unicode.md) for details on Unicode support.

Verification:

```ps
```py
# rpm -qf $(grep -r import /usr/libexec/ /usr/bin /etc/xapi.d/ /opt/xensource/|grep xcp|cut -d: -f1|grep -v Binary) --qf '%{name}\n'|sort -u|tee xcp-python-libs-importers.txt
host-upgrade-plugin
interface-rename
Expand Down
20 changes: 20 additions & 0 deletions docs/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
BUILDDIR = build

# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
4 changes: 4 additions & 0 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
sphinx
sphinx-autodoc-typehints
furo
myst_parser
7 changes: 7 additions & 0 deletions docs/source/accessor.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
xcp.accessor
=============

.. automodule:: xcp.accessor
:members:
:undoc-members:
:show-inheritance:
7 changes: 7 additions & 0 deletions docs/source/bootloader.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
xcp.bootloader
==============

.. automodule:: xcp.bootloader
:members:
:undoc-members:
:show-inheritance:
7 changes: 7 additions & 0 deletions docs/source/cmd.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
xcp.cmd
=======

.. automodule:: xcp.cmd
:members:
:undoc-members:
:show-inheritance:
7 changes: 7 additions & 0 deletions docs/source/compat.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
xcp.compat
==========

.. automodule:: xcp.compat
:members:
:undoc-members:
:show-inheritance:
57 changes: 57 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Configuration file for the Sphinx documentation builder.
# -- Path setup -------------------------------------------------------------
import logging
import os
import sys

# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# Add project root to sys.path for autodoc to find xcp modules and it allows
# to {include} the toplevel README.md files from their wrapper files here.
sys.path.insert(0, os.path.abspath("../.."))

# Add stubs directory to sys.path for stubs (xcp/bootloader.py needs a branding.py)
sys.path.insert(0, os.path.abspath("../../stubs"))

#
# To support Markdown-based documentation, Sphinx can use MyST-Parser.
# MyST-Parser is a Docutils bridge to markdown-it-py, a Python package
# for parsing the CommonMark Markdown flavor.
# See https://myst-parser.readthedocs.io/en/latest/ for details.
# Set the log level of markdown-it log categories to INFO to disable DEBUG
# logging and prevent flooding the logs with many 1000s of DEBUG messages:
#
logging.getLogger("markdown_it.rules_block").setLevel(logging.INFO)
logging.getLogger("markdown_it.rules_inline").setLevel(logging.INFO)
logging.getLogger("markdown_it").setLevel(logging.INFO)

# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information

project = "python-libs"
copyright = "2025, Citrix Inc."
author = "Citrix Inc."
from datetime import datetime

release = datetime.now().strftime("%Y.%m.%d-%H%M")

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

extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.viewcode",
"sphinx.ext.githubpages",
"myst_parser",
]

templates_path = ["_templates"]
exclude_patterns = []


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

html_theme = "furo"
html_static_path = ["_static"]
7 changes: 7 additions & 0 deletions docs/source/cpiofile.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
xcp.cpiofile
============

.. automodule:: xcp.cpiofile
:members:
:undoc-members:
:show-inheritance:
7 changes: 7 additions & 0 deletions docs/source/dmv.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
xcp.dmv
=======

.. automodule:: xcp.dmv
:members:
:undoc-members:
:show-inheritance:
7 changes: 7 additions & 0 deletions docs/source/dom0.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
xcp.dom0
========

.. automodule:: xcp.dom0
:members:
:undoc-members:
:show-inheritance:
7 changes: 7 additions & 0 deletions docs/source/environ.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
xcp.environ
===========

.. automodule:: xcp.environ
:members:
:undoc-members:
:show-inheritance:
2 changes: 2 additions & 0 deletions docs/source/include-toplevel-CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
```{include} ../../CONTRIBUTING.md
:parser: myst
2 changes: 2 additions & 0 deletions docs/source/include-toplevel-DOCUMENTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
```{include} ../../DOCUMENTING.md
:parser: myst
2 changes: 2 additions & 0 deletions docs/source/include-toplevel-README-Unicode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
```{include} ../../README-Unicode.md
:parser: myst
2 changes: 2 additions & 0 deletions docs/source/include-toplevel-README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
```{include} ../../README.md
:parser: myst
Loading
Loading