Dev/automate documentation build (#1357)

* some test about building docs

* indendation error

* typo -

* forgot to get package hdf5

* had to add shinx and doxygen as well

* oke created environmnet file

* typo

* dont use conda

* dont use conda

* cannot upload artefact commit to gh-pages

* correct copy

* mmh

* try with tokem

* set write permisison

* script to update main_index for versioned documentation

* rename main_index to index

* use absolute path in python script

* update main_index upon a release

* extract release type from version

* copy release notes

* updated links from devdoc to slsDetectorPackage, handling .md for new versions

* changed page source

* updated documentation link in README

* add guideline for Package Versioning to documentation also used as a test

* typo in workflow

* why didnt it copy?

* copied from build instead of docs

* change back - trigger for push

* only trigger for pull_requests and releases

* removed conda environment file

* automatically update documentation paths in release notes

* only keep templated README.md

* added README and updated links

* update Release notes template manually

* generate release notes script not needed anymore

* modified readme to reflect dependencies insides build from source

* subheadings in dependencies

---------

Co-authored-by: Dhanya Thattil <dhanya.thattil@psi.ch>
This commit is contained in:
2026-02-23 14:21:44 +01:00
committed by GitHub
parent f8723eb0d8
commit f4658ab094
74 changed files with 6248 additions and 109 deletions

View File

@@ -0,0 +1,122 @@
name: Build and upload Documentation
on:
workflow_dispatch:
pull_request:
branches:
- developer
- main
release:
types:
- published
env:
BUILD_TYPE: RELEASE
permissions:
contents: write # Required to push to gh-pages branch
pages: write # Required for GitHub Pages deployment
id-token: write # Required for GitHub Pages deployment
jobs:
build-and-deploy:
strategy:
matrix:
patform: [ubuntu-latest]
python-version: ["3.12"]
runs-on: ${{ matrix.patform }}
defaults:
run:
shell: "bash -l {0}"
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch all history for proper git operations
token: ${{ secrets.GITHUB_TOKEN }} # Use the default token
# Extract release version (if triggered by release)
- name: Get Release Version
id: version
run: |
if [ "${{ github.event_name }}" == "release" ]; then
VERSION="${{ github.event.release.tag_name }}"
echo "version=${VERSION}" >> $GITHUB_OUTPUT
else
echo "version=developer" >> $GITHUB_OUTPUT
fi
- name: Install System Packages
uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: libhdf5-dev doxygen
version: 1.0
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: 3.12
cache: 'pip'
- name: Install Python Packages
run: pip install sphinx sphinx_rtd_theme breathe pyyaml jinja2
- name: Build Documentation
run: |
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DSLS_BUILD_DOCS=ON -DSLS_USE_HDF5=ON -DSLS_USE_PYTHON=ON ..
make -j4
make docs
# Update main index if this is a release
- name: Update version index
if: github.event_name == 'release'
run: |
python docs/main_index/render_main_index.py \
--version "${{ steps.version.outputs.version }}" \
--date "$(date +'%d.%m.%Y')"
- name: Checkout gh-pages
uses: actions/checkout@v4
with:
ref: gh-pages
path: gh-pages
- name: Copy documentation and Release notes to versioned folder
if: github.event_name == 'release' || (github.event_name == 'pull_request' && github.event.pull_request.merged == true)
run: |
VERSION="${{ steps.version.outputs.version }}"
mkdir -p "gh-pages/${VERSION}"
cp -r build/docs/html/. "gh-pages/${VERSION}/"
cp docs/main_index/index.html gh-pages/index.html
cp docs/main_index/index.html gh-pages/_sources/index.html.txt
if [ "${{ github.event_name }}" == "release" ]; then
cp RELEASE.md "gh-pages/releases/RELEASE_v${VERSION}.md"
fi
- name: Commit and Push changes to gh-pages
if: github.event_name == 'release' || (github.event_name == 'pull_request' && github.event.pull_request.merged == true)
run: |
cd gh-pages
git config --global user.name 'github-actions'
git config --global user.email 'github-actions@github.com'
git add .
git commit -m "Update Documentation for ${{ steps.version.outputs.version }}"
git remote set-url origin https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git
git push origin gh-pages
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,6 +1,6 @@
name: Native CMake Build
on: [push, pull_request]
on: [push, pull_request]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
@@ -46,3 +46,8 @@ jobs:

99
README.md Executable file → Normal file
View File

@@ -1,10 +1,5 @@
## Dependencies
Before building from source make sure that you have the [dependencies](https://slsdetectorgroup.github.io/devdoc/dependencies.html) installed. If installing using conda, conda will manage the dependencies. Avoid also installing dependency packages with pip.
## Documentaion
Detailed documentation including installation can be found in the [software wiki](https://slsdetectorgroup.github.io/devdoc/index.html).
List of releases can be found on the [official site](https://www.psi.ch/en/lxn/software-releases).
## Documentation
Detailed documentation for every release including installation can be found in the [Documentation](https://slsdetectorgroup.github.io/slsDetectorPackage/index.html).
Firmware compatiblity can be found in [firmware page](https://github.com/slsdetectorgroup/slsDetectorFirmware)
@@ -16,7 +11,7 @@ The slsDetectorPackage provides core detector software implemented in C++, along
2. **Pip**: Install only the Python extension module, either by downloading the pre-built library from PyPI or by building the extension locally from source. Available only from v9.2.0 onwards.
3. **Build from source**: Compile the entire package yourself, including both the C++ core and the Python bindings, for maximum control and customization. However, make sure that you have the dependencies installed. If installing using conda, conda will manage the dependencies. Avoid installing packages with pip and conda simultaneously.
3. **Build from source**: Compile the entire package yourself, including both the C++ core and the Python bindings, for maximum control and customization. However, make sure that you have the dependencies installed. If installing using conda, conda will manage the [Dependencies](#31-dependencies). Avoid installing packages with pip and conda simultaneously.
### 1. Install pre-built binaries using conda (Recommended)
Conda is not only useful to manage python environments but can also
@@ -72,19 +67,81 @@ pip install .
## 3. Build from source
### 3.1. Download Source Code from github
### 3.1. Dependencies
While we value few dependencies some libraries are required in order to not have to reinvent the wheel. Due to the state of package management in C++ we decided to bundle some of them with our source code. These are found in the libs/ directory.
#### Core
To use the basic building blocks, meaning sls_detector_get/put and the shared libraries these are needed:
* Linux, preferably recent kernel (currently no cross platform support)
* CMake >= 3.14
* C++17 compatible compiler. (We test with gcc and clang)
> **Note:** For v9.x.x of slsDetectorPackage and older, C++11 compatible compiler.
#### Python bindings
* Python >= 3.8
* pybind11 2.13.6 (packaged in libs)
> **Note:** Refer [pybind11 notes](#4-pybind-and-zeromq).
#### ZeroMQ
* Zeromq 4.3.4 (packaged in libs)
> **Note:** Refer [zeromq notes](#4-pybind-and-zeromq).
#### GUI
* Qt 5.9
* Qwt 6.1.5 (packaged in libs)
#### Moench executables
* libtiff
#### Documentation
The documentation is built with
* Doxygen (to extract C++ classes etc.)
* Breathe (Sphinx plugin to handle doxygen xml)
* Sphinx with sphinx_rtd_theme
#### Packaged in libs/
* catch2 (unit testing)
* rapidjson (streaming from receiver)
* pybind11 (python bindings)
* qwt (gui plotting)
* libzmq (streaming to/from receiver)
### 3.2. Download Source Code from github
```
git clone https://github.com/slsdetectorgroup/slsDetectorPackage.git --branch 7.0.0
```
> **Note:** For v6.x.x of slsDetectorPackage and older, refer [pybind11 notes on cloning](#Pybind-and-Zeromq).
> **Note:** For v6.x.x of slsDetectorPackage and older, refer [pybind11 notes on cloning](#4-pybind-and-zeromq).
### 3.2. Build from source
### 3.3. Build from source
One can either build using cmake or use the in-built cmk.sh script.
### 3.2.1. Build using CMake
### 3.3.1. Build using CMake
```
# outside slsDetecorPackage folder
@@ -122,9 +179,9 @@ ccmake ..
| -DSLS_USE_HDF5=ON | HDF5 |
| -DSLS_USE_SIMULATOR=ON | Simulator |
> **Note:** For v7.x.x of slsDetectorPackage and older, refer [zeromq notes for cmake option to hint library location](#Pybind-and-Zeromq).
> **Note:** For v7.x.x of slsDetectorPackage and older, refer [zeromq notes for cmake option to hint library location](#4-pybind-and-zeromq).
### 3.2.2. Build using in-built cmk.sh script
### 3.3.2. Build using in-built cmk.sh script
```
The binaries are generated in slsDetectorPackage/build/bin directory.
@@ -167,9 +224,9 @@ Usage: $0 [-b] [-c] [-d <HDF5 directory>] [-e] [-g] [-h] [-i]
./cmk.sh -r #only receiver
```
> **Note:** For v7.x.x of slsDetectorPackage and older, refer [zeromq notes for cmk script option to hint library location](#Pybind-and-Zeromq).
> **Note:** For v7.x.x of slsDetectorPackage and older, refer [zeromq notes for cmk script option to hint library location](#4-pybind-and-zeromq).
### 3.3. Build on old distributions using conda
### 3.4. Build on old distributions using conda
If your linux distribution doesn't come with a C++17 compiler (gcc>8) then
it's possible to install a newer gcc using conda and build the slsDetectorPackage
@@ -186,10 +243,10 @@ cmake ../slsDetectorPackage -DCMAKE_PREFIX_PATH=$CONDA_PREFIX
make -j12
```
> **Note:** For v7.x.x of slsDetectorPackage and older, refer [zeromq notes for dependencies for conda](#Pybind-and-Zeromq).
> **Note:** For v7.x.x of slsDetectorPackage and older, refer [zeromq notes for dependencies for conda](#4-pybind-and-zeromq).
### 3.4. Build slsDetectorGui (Qt5)
### 3.5. Build slsDetectorGui (Qt5)
1. Using pre-built binary on conda
```
@@ -238,11 +295,11 @@ cd slsDetectorPackage
./cmk.sh -cbgj9
```
> **Note:** For v7.x.x of slsDetectorPackage and older, refer [zeromq notes for dependencies for conda](#Pybind-and-Zeromq).
> **Note:** For v7.x.x of slsDetectorPackage and older, refer [zeromq notes for dependencies for conda](#4-pybind-and-zeromq).
### 3.5. Build documentation from package
### 3.6. Build documentation from package
The documentation for the slsDetectorPackage is build using a combination
of Doxygen, Sphinx and Breathe. The easiest way to install the dependencies
of Doxygen, Sphinx and Breathe. The easiest w(#4-pybind-and-zeromq)ay to install the dependencies
is to use conda
```

View File

@@ -1,7 +1,7 @@
SLS Detector Package Major Release x.x.x released on xx.xx.202x
SLS Detector Package {{RELEASE_TYPE}} Release {{VERSION}} released on {{DATE}}
===============================================================
This document describes the differences between vx.x.x and v10.0.0
This document describes the differences between v{{VERSION}} and v{{PREVIOUS_VERSION}}
@@ -64,7 +64,7 @@ added patternstart to python (ctb, xilinx_ctb , mythen3), only the detector clas
Using command 'update'
Instructions available at
https://slsdetectorgroup.github.io/devdoc/serverupgrade.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/serverupgrade.html
@@ -104,7 +104,7 @@ added patternstart to python (ctb, xilinx_ctb , mythen3), only the detector clas
Instructions available at
https://slsdetectorgroup.github.io/devdoc/firmware.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/firmware.html
@@ -133,9 +133,9 @@ added patternstart to python (ctb, xilinx_ctb , mythen3), only the detector clas
Commands: udpatekernel, kernelversion
Instructions available at
https://slsdetectorgroup.github.io/devdoc/commandline.html
https://slsdetectorgroup.github.io/devdoc/detector.html
https://slsdetectorgroup.github.io/devdoc/pydetector.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/commandline.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/detector.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/pydetector.html
@@ -153,78 +153,78 @@ added patternstart to python (ctb, xilinx_ctb , mythen3), only the detector clas
-------------
Installation:
https://slsdetectorgroup.github.io/devdoc/installation.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/installation.html
Quick Start Guide:
https://slsdetectorgroup.github.io/devdoc/quick_start_guide.html
https://slsdetectorgroup.github.io//{{VERSION}}/quick_start_guide.html
Firmware Upgrade:
https://slsdetectorgroup.github.io/devdoc/firmware.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/firmware.html
Detector Server upgrade:
https://slsdetectorgroup.github.io/devdoc/serverupgrade.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/serverupgrade.html
Detector Simulators:
https://slsdetectorgroup.github.io/devdoc/virtualserver.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/virtualserver.html
Consuming slsDetectorPackage:
https://slsdetectorgroup.github.io/devdoc/consuming.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/consuming.html
Software Architecture
https://slsdetectorgroup.github.io/devdoc/softwarearchitecture.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/softwarearchitecture.html
Set up commands in config file
https://slsdetectorgroup.github.io/devdoc/configcommands.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/configcommands.html
Image Size and Output Characteristics
https://slsdetectorgroup.github.io/devdoc/dataformat.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/dataformat.html
API Examples:
https://github.com/slsdetectorgroup/api-examples
Command Line Documentation:
https://slsdetectorgroup.github.io/devdoc/commandline.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/commandline.html
C++ API Documentation:
https://slsdetectorgroup.github.io/devdoc/detector.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/detector.html
C++ API Example:
https://slsdetectorgroup.github.io/devdoc/examples.html#
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/examples.html#
Python API Documentation:
https://slsdetectorgroup.github.io/devdoc/pygettingstarted.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/pygettingstarted.html
Python API Example:
https://slsdetectorgroup.github.io/devdoc/pyexamples.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/pyexamples.html
Receivers (including custom receiver):
https://slsdetectorgroup.github.io/devdoc/receivers.html
https://slsdetectorgroup.github.io/devdoc/slsreceiver.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/receivers.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/slsreceiver.html
Detector UDP Header:
https://slsdetectorgroup.github.io/devdoc/udpheader.html
https://slsdetectorgroup.github.io/devdoc/udpdetspec.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/udpheader.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/udpdetspec.html
Output Data:
https://slsdetectorgroup.github.io/devdoc/dataformat.html
https://slsdetectorgroup.github.io/devdoc/fileformat.html
https://slsdetectorgroup.github.io/devdoc/slsreceiverheaderformat.html
https://slsdetectorgroup.github.io/devdoc/masterfileattributes.html
https://slsdetectorgroup.github.io/devdoc/binaryfileformat.html
https://slsdetectorgroup.github.io/devdoc/hdf5fileformat.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/dataformat.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/fileformat.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/slsreceiverheaderformat.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/masterfileattributes.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/binaryfileformat.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/hdf5fileformat.html
slsReceiver Zmq Format:
https://slsdetectorgroup.github.io/devdoc/slsreceiver.html#zmq-json-header-format
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/slsreceiver.html#zmq-json-header-format
TroubleShooting:
https://slsdetectorgroup.github.io/devdoc/troubleshooting.html
https://slsdetectorgroup.github.io/devdoc/troubleshooting.html#receiver-pc-tuning-options
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/troubleshooting.html
https://slsdetectorgroup.github.io/slsDetectorPackage/{{VERSION}}/troubleshooting.html#receiver-pc-tuning-options
Further Documentation:
https://www.psi.ch/en/detectors/documentation
Info on Releases:
https://www.psi.ch/en/detectors/software
https://slsdetectorgroup.github.io/slsDetectorPackage/index.html
Support

View File

@@ -71,6 +71,7 @@ set(SPHINX_SOURCE_FILES
src/dataformat.rst
src/softwarearchitecture.rst
src/configcommands.rst
src/Versioning.rst
)
foreach(filename ${SPHINX_SOURCE_FILES})

View File

@@ -0,0 +1,123 @@
/* Compatability shim for jQuery and underscores.js.
*
* Copyright Sphinx contributors
* Released under the two clause BSD licence
*/
/**
* small helper function to urldecode strings
*
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL
*/
jQuery.urldecode = function(x) {
if (!x) {
return x
}
return decodeURIComponent(x.replace(/\+/g, ' '));
};
/**
* small helper function to urlencode strings
*/
jQuery.urlencode = encodeURIComponent;
/**
* This function returns the parsed url parameters of the
* current request. Multiple values per key are supported,
* it will always return arrays of strings for the value parts.
*/
jQuery.getQueryParameters = function(s) {
if (typeof s === 'undefined')
s = document.location.search;
var parts = s.substr(s.indexOf('?') + 1).split('&');
var result = {};
for (var i = 0; i < parts.length; i++) {
var tmp = parts[i].split('=', 2);
var key = jQuery.urldecode(tmp[0]);
var value = jQuery.urldecode(tmp[1]);
if (key in result)
result[key].push(value);
else
result[key] = [value];
}
return result;
};
/**
* highlight a given string on a jquery object by wrapping it in
* span elements with the given class name.
*/
jQuery.fn.highlightText = function(text, className) {
function highlight(node, addItems) {
if (node.nodeType === 3) {
var val = node.nodeValue;
var pos = val.toLowerCase().indexOf(text);
if (pos >= 0 &&
!jQuery(node.parentNode).hasClass(className) &&
!jQuery(node.parentNode).hasClass("nohighlight")) {
var span;
var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
if (isInSVG) {
span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
} else {
span = document.createElement("span");
span.className = className;
}
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
node.parentNode.insertBefore(span, node.parentNode.insertBefore(
document.createTextNode(val.substr(pos + text.length)),
node.nextSibling));
node.nodeValue = val.substr(0, pos);
if (isInSVG) {
var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
var bbox = node.parentElement.getBBox();
rect.x.baseVal.value = bbox.x;
rect.y.baseVal.value = bbox.y;
rect.width.baseVal.value = bbox.width;
rect.height.baseVal.value = bbox.height;
rect.setAttribute('class', className);
addItems.push({
"parent": node.parentNode,
"target": rect});
}
}
}
else if (!jQuery(node).is("button, select, textarea")) {
jQuery.each(node.childNodes, function() {
highlight(this, addItems);
});
}
}
var addItems = [];
var result = this.each(function() {
highlight(this, addItems);
});
for (var i = 0; i < addItems.length; ++i) {
jQuery(addItems[i].parent).before(addItems[i].target);
}
return result;
};
/*
* backward compatibility for jQuery.browser
* This will be supported until firefox bug is fixed.
*/
if (!jQuery.browser) {
jQuery.uaMatch = function(ua) {
ua = ua.toLowerCase();
var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
/(webkit)[ \/]([\w.]+)/.exec(ua) ||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
/(msie) ([\w.]+)/.exec(ua) ||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
[];
return {
browser: match[ 1 ] || "",
version: match[ 2 ] || "0"
};
};
jQuery.browser = {};
jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
}

View File

@@ -0,0 +1,906 @@
/*
* Sphinx stylesheet -- basic theme.
*/
/* -- main layout ----------------------------------------------------------- */
div.clearer {
clear: both;
}
div.section::after {
display: block;
content: '';
clear: left;
}
/* -- relbar ---------------------------------------------------------------- */
div.related {
width: 100%;
font-size: 90%;
}
div.related h3 {
display: none;
}
div.related ul {
margin: 0;
padding: 0 0 0 10px;
list-style: none;
}
div.related li {
display: inline;
}
div.related li.right {
float: right;
margin-right: 5px;
}
/* -- sidebar --------------------------------------------------------------- */
div.sphinxsidebarwrapper {
padding: 10px 5px 0 10px;
}
div.sphinxsidebar {
float: left;
width: 230px;
margin-left: -100%;
font-size: 90%;
word-wrap: break-word;
overflow-wrap : break-word;
}
div.sphinxsidebar ul {
list-style: none;
}
div.sphinxsidebar ul ul,
div.sphinxsidebar ul.want-points {
margin-left: 20px;
list-style: square;
}
div.sphinxsidebar ul ul {
margin-top: 0;
margin-bottom: 0;
}
div.sphinxsidebar form {
margin-top: 10px;
}
div.sphinxsidebar input {
border: 1px solid #98dbcc;
font-family: sans-serif;
font-size: 1em;
}
div.sphinxsidebar #searchbox form.search {
overflow: hidden;
}
div.sphinxsidebar #searchbox input[type="text"] {
float: left;
width: 80%;
padding: 0.25em;
box-sizing: border-box;
}
div.sphinxsidebar #searchbox input[type="submit"] {
float: left;
width: 20%;
border-left: none;
padding: 0.25em;
box-sizing: border-box;
}
img {
border: 0;
max-width: 100%;
}
/* -- search page ----------------------------------------------------------- */
ul.search {
margin-top: 10px;
}
ul.search li {
padding: 5px 0;
}
ul.search li a {
font-weight: bold;
}
ul.search li p.context {
color: #888;
margin: 2px 0 0 30px;
text-align: left;
}
ul.keywordmatches li.goodmatch a {
font-weight: bold;
}
/* -- index page ------------------------------------------------------------ */
table.contentstable {
width: 90%;
margin-left: auto;
margin-right: auto;
}
table.contentstable p.biglink {
line-height: 150%;
}
a.biglink {
font-size: 1.3em;
}
span.linkdescr {
font-style: italic;
padding-top: 5px;
font-size: 90%;
}
/* -- general index --------------------------------------------------------- */
table.indextable {
width: 100%;
}
table.indextable td {
text-align: left;
vertical-align: top;
}
table.indextable ul {
margin-top: 0;
margin-bottom: 0;
list-style-type: none;
}
table.indextable > tbody > tr > td > ul {
padding-left: 0em;
}
table.indextable tr.pcap {
height: 10px;
}
table.indextable tr.cap {
margin-top: 10px;
background-color: #f2f2f2;
}
img.toggler {
margin-right: 3px;
margin-top: 3px;
cursor: pointer;
}
div.modindex-jumpbox {
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
margin: 1em 0 1em 0;
padding: 0.4em;
}
div.genindex-jumpbox {
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
margin: 1em 0 1em 0;
padding: 0.4em;
}
/* -- domain module index --------------------------------------------------- */
table.modindextable td {
padding: 2px;
border-collapse: collapse;
}
/* -- general body styles --------------------------------------------------- */
div.body {
min-width: 360px;
max-width: 800px;
}
div.body p, div.body dd, div.body li, div.body blockquote {
-moz-hyphens: auto;
-ms-hyphens: auto;
-webkit-hyphens: auto;
hyphens: auto;
}
a.headerlink {
visibility: hidden;
}
a:visited {
color: #551A8B;
}
h1:hover > a.headerlink,
h2:hover > a.headerlink,
h3:hover > a.headerlink,
h4:hover > a.headerlink,
h5:hover > a.headerlink,
h6:hover > a.headerlink,
dt:hover > a.headerlink,
caption:hover > a.headerlink,
p.caption:hover > a.headerlink,
div.code-block-caption:hover > a.headerlink {
visibility: visible;
}
div.body p.caption {
text-align: inherit;
}
div.body td {
text-align: left;
}
.first {
margin-top: 0 !important;
}
p.rubric {
margin-top: 30px;
font-weight: bold;
}
img.align-left, figure.align-left, .figure.align-left, object.align-left {
clear: left;
float: left;
margin-right: 1em;
}
img.align-right, figure.align-right, .figure.align-right, object.align-right {
clear: right;
float: right;
margin-left: 1em;
}
img.align-center, figure.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
img.align-default, figure.align-default, .figure.align-default {
display: block;
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left;
}
.align-center {
text-align: center;
}
.align-default {
text-align: center;
}
.align-right {
text-align: right;
}
/* -- sidebars -------------------------------------------------------------- */
div.sidebar,
aside.sidebar {
margin: 0 0 0.5em 1em;
border: 1px solid #ddb;
padding: 7px;
background-color: #ffe;
width: 40%;
float: right;
clear: right;
overflow-x: auto;
}
p.sidebar-title {
font-weight: bold;
}
nav.contents,
aside.topic,
div.admonition, div.topic, blockquote {
clear: left;
}
/* -- topics ---------------------------------------------------------------- */
nav.contents,
aside.topic,
div.topic {
border: 1px solid #ccc;
padding: 7px;
margin: 10px 0 10px 0;
}
p.topic-title {
font-size: 1.1em;
font-weight: bold;
margin-top: 10px;
}
/* -- admonitions ----------------------------------------------------------- */
div.admonition {
margin-top: 10px;
margin-bottom: 10px;
padding: 7px;
}
div.admonition dt {
font-weight: bold;
}
p.admonition-title {
margin: 0px 10px 5px 0px;
font-weight: bold;
}
div.body p.centered {
text-align: center;
margin-top: 25px;
}
/* -- content of sidebars/topics/admonitions -------------------------------- */
div.sidebar > :last-child,
aside.sidebar > :last-child,
nav.contents > :last-child,
aside.topic > :last-child,
div.topic > :last-child,
div.admonition > :last-child {
margin-bottom: 0;
}
div.sidebar::after,
aside.sidebar::after,
nav.contents::after,
aside.topic::after,
div.topic::after,
div.admonition::after,
blockquote::after {
display: block;
content: '';
clear: both;
}
/* -- tables ---------------------------------------------------------------- */
table.docutils {
margin-top: 10px;
margin-bottom: 10px;
border: 0;
border-collapse: collapse;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
table.align-default {
margin-left: auto;
margin-right: auto;
}
table caption span.caption-number {
font-style: italic;
}
table caption span.caption-text {
}
table.docutils td, table.docutils th {
padding: 1px 8px 1px 5px;
border-top: 0;
border-left: 0;
border-right: 0;
border-bottom: 1px solid #aaa;
}
th {
text-align: left;
padding-right: 5px;
}
table.citation {
border-left: solid 1px gray;
margin-left: 1px;
}
table.citation td {
border-bottom: none;
}
th > :first-child,
td > :first-child {
margin-top: 0px;
}
th > :last-child,
td > :last-child {
margin-bottom: 0px;
}
/* -- figures --------------------------------------------------------------- */
div.figure, figure {
margin: 0.5em;
padding: 0.5em;
}
div.figure p.caption, figcaption {
padding: 0.3em;
}
div.figure p.caption span.caption-number,
figcaption span.caption-number {
font-style: italic;
}
div.figure p.caption span.caption-text,
figcaption span.caption-text {
}
/* -- field list styles ----------------------------------------------------- */
table.field-list td, table.field-list th {
border: 0 !important;
}
.field-list ul {
margin: 0;
padding-left: 1em;
}
.field-list p {
margin: 0;
}
.field-name {
-moz-hyphens: manual;
-ms-hyphens: manual;
-webkit-hyphens: manual;
hyphens: manual;
}
/* -- hlist styles ---------------------------------------------------------- */
table.hlist {
margin: 1em 0;
}
table.hlist td {
vertical-align: top;
}
/* -- object description styles --------------------------------------------- */
.sig {
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
}
.sig-name, code.descname {
background-color: transparent;
font-weight: bold;
}
.sig-name {
font-size: 1.1em;
}
code.descname {
font-size: 1.2em;
}
.sig-prename, code.descclassname {
background-color: transparent;
}
.optional {
font-size: 1.3em;
}
.sig-paren {
font-size: larger;
}
.sig-param.n {
font-style: italic;
}
/* C++ specific styling */
.sig-inline.c-texpr,
.sig-inline.cpp-texpr {
font-family: unset;
}
.sig.c .k, .sig.c .kt,
.sig.cpp .k, .sig.cpp .kt {
color: #0033B3;
}
.sig.c .m,
.sig.cpp .m {
color: #1750EB;
}
.sig.c .s, .sig.c .sc,
.sig.cpp .s, .sig.cpp .sc {
color: #067D17;
}
/* -- other body styles ----------------------------------------------------- */
ol.arabic {
list-style: decimal;
}
ol.loweralpha {
list-style: lower-alpha;
}
ol.upperalpha {
list-style: upper-alpha;
}
ol.lowerroman {
list-style: lower-roman;
}
ol.upperroman {
list-style: upper-roman;
}
:not(li) > ol > li:first-child > :first-child,
:not(li) > ul > li:first-child > :first-child {
margin-top: 0px;
}
:not(li) > ol > li:last-child > :last-child,
:not(li) > ul > li:last-child > :last-child {
margin-bottom: 0px;
}
ol.simple ol p,
ol.simple ul p,
ul.simple ol p,
ul.simple ul p {
margin-top: 0;
}
ol.simple > li:not(:first-child) > p,
ul.simple > li:not(:first-child) > p {
margin-top: 0;
}
ol.simple p,
ul.simple p {
margin-bottom: 0;
}
aside.footnote > span,
div.citation > span {
float: left;
}
aside.footnote > span:last-of-type,
div.citation > span:last-of-type {
padding-right: 0.5em;
}
aside.footnote > p {
margin-left: 2em;
}
div.citation > p {
margin-left: 4em;
}
aside.footnote > p:last-of-type,
div.citation > p:last-of-type {
margin-bottom: 0em;
}
aside.footnote > p:last-of-type:after,
div.citation > p:last-of-type:after {
content: "";
clear: both;
}
dl.field-list {
display: grid;
grid-template-columns: fit-content(30%) auto;
}
dl.field-list > dt {
font-weight: bold;
word-break: break-word;
padding-left: 0.5em;
padding-right: 5px;
}
dl.field-list > dd {
padding-left: 0.5em;
margin-top: 0em;
margin-left: 0em;
margin-bottom: 0em;
}
dl {
margin-bottom: 15px;
}
dd > :first-child {
margin-top: 0px;
}
dd ul, dd table {
margin-bottom: 10px;
}
dd {
margin-top: 3px;
margin-bottom: 10px;
margin-left: 30px;
}
.sig dd {
margin-top: 0px;
margin-bottom: 0px;
}
.sig dl {
margin-top: 0px;
margin-bottom: 0px;
}
dl > dd:last-child,
dl > dd:last-child > :last-child {
margin-bottom: 0;
}
dt:target, span.highlighted {
background-color: #fbe54e;
}
rect.highlighted {
fill: #fbe54e;
}
dl.glossary dt {
font-weight: bold;
font-size: 1.1em;
}
.versionmodified {
font-style: italic;
}
.system-message {
background-color: #fda;
padding: 5px;
border: 3px solid red;
}
.footnote:target {
background-color: #ffa;
}
.line-block {
display: block;
margin-top: 1em;
margin-bottom: 1em;
}
.line-block .line-block {
margin-top: 0;
margin-bottom: 0;
margin-left: 1.5em;
}
.guilabel, .menuselection {
font-family: sans-serif;
}
.accelerator {
text-decoration: underline;
}
.classifier {
font-style: oblique;
}
.classifier:before {
font-style: normal;
margin: 0 0.5em;
content: ":";
display: inline-block;
}
abbr, acronym {
border-bottom: dotted 1px;
cursor: help;
}
/* -- code displays --------------------------------------------------------- */
pre {
overflow: auto;
overflow-y: hidden; /* fixes display issues on Chrome browsers */
}
pre, div[class*="highlight-"] {
clear: both;
}
span.pre {
-moz-hyphens: none;
-ms-hyphens: none;
-webkit-hyphens: none;
hyphens: none;
white-space: nowrap;
}
div[class*="highlight-"] {
margin: 1em 0;
}
td.linenos pre {
border: 0;
background-color: transparent;
color: #aaa;
}
table.highlighttable {
display: block;
}
table.highlighttable tbody {
display: block;
}
table.highlighttable tr {
display: flex;
}
table.highlighttable td {
margin: 0;
padding: 0;
}
table.highlighttable td.linenos {
padding-right: 0.5em;
}
table.highlighttable td.code {
flex: 1;
overflow: hidden;
}
.highlight .hll {
display: block;
}
div.highlight pre,
table.highlighttable pre {
margin: 0;
}
div.code-block-caption + div {
margin-top: 0;
}
div.code-block-caption {
margin-top: 1em;
padding: 2px 5px;
font-size: small;
}
div.code-block-caption code {
background-color: transparent;
}
table.highlighttable td.linenos,
span.linenos,
div.highlight span.gp { /* gp: Generic.Prompt */
user-select: none;
-webkit-user-select: text; /* Safari fallback only */
-webkit-user-select: none; /* Chrome/Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE10+ */
}
div.code-block-caption span.caption-number {
padding: 0.1em 0.3em;
font-style: italic;
}
div.code-block-caption span.caption-text {
}
div.literal-block-wrapper {
margin: 1em 0;
}
code.xref, a code {
background-color: transparent;
font-weight: bold;
}
h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
background-color: transparent;
}
.viewcode-link {
float: right;
}
.viewcode-back {
float: right;
font-family: sans-serif;
}
div.viewcode-block:target {
margin: -1px -10px;
padding: 0 10px;
}
/* -- math display ---------------------------------------------------------- */
img.math {
vertical-align: middle;
}
div.body div.math p {
text-align: center;
}
span.eqno {
float: right;
}
span.eqno a.headerlink {
position: absolute;
z-index: 1;
}
div.math:hover a.headerlink {
visibility: visible;
}
/* -- printout stylesheet --------------------------------------------------- */
@media print {
div.document,
div.documentwrapper,
div.bodywrapper {
margin: 0 !important;
width: 100%;
}
div.sphinxsidebar,
div.related,
div.footer,
#top-link {
display: none;
}
}

View File

@@ -0,0 +1 @@
.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions .rst-other-versions .rtd-current-item{font-weight:700}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}#flyout-search-form{padding:6px}

View File

@@ -0,0 +1,4 @@
/* override table no-wrap */
.wy-table-responsive table td, .wy-table-responsive table th {
white-space: normal;
}

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 434 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,149 @@
/*
* Base JavaScript utilities for all Sphinx HTML documentation.
*/
"use strict";
const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([
"TEXTAREA",
"INPUT",
"SELECT",
"BUTTON",
]);
const _ready = (callback) => {
if (document.readyState !== "loading") {
callback();
} else {
document.addEventListener("DOMContentLoaded", callback);
}
};
/**
* Small JavaScript module for the documentation.
*/
const Documentation = {
init: () => {
Documentation.initDomainIndexTable();
Documentation.initOnKeyListeners();
},
/**
* i18n support
*/
TRANSLATIONS: {},
PLURAL_EXPR: (n) => (n === 1 ? 0 : 1),
LOCALE: "unknown",
// gettext and ngettext don't access this so that the functions
// can safely bound to a different name (_ = Documentation.gettext)
gettext: (string) => {
const translated = Documentation.TRANSLATIONS[string];
switch (typeof translated) {
case "undefined":
return string; // no translation
case "string":
return translated; // translation exists
default:
return translated[0]; // (singular, plural) translation tuple exists
}
},
ngettext: (singular, plural, n) => {
const translated = Documentation.TRANSLATIONS[singular];
if (typeof translated !== "undefined")
return translated[Documentation.PLURAL_EXPR(n)];
return n === 1 ? singular : plural;
},
addTranslations: (catalog) => {
Object.assign(Documentation.TRANSLATIONS, catalog.messages);
Documentation.PLURAL_EXPR = new Function(
"n",
`return (${catalog.plural_expr})`
);
Documentation.LOCALE = catalog.locale;
},
/**
* helper function to focus on search bar
*/
focusSearchBar: () => {
document.querySelectorAll("input[name=q]")[0]?.focus();
},
/**
* Initialise the domain index toggle buttons
*/
initDomainIndexTable: () => {
const toggler = (el) => {
const idNumber = el.id.substr(7);
const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`);
if (el.src.substr(-9) === "minus.png") {
el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`;
toggledRows.forEach((el) => (el.style.display = "none"));
} else {
el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`;
toggledRows.forEach((el) => (el.style.display = ""));
}
};
const togglerElements = document.querySelectorAll("img.toggler");
togglerElements.forEach((el) =>
el.addEventListener("click", (event) => toggler(event.currentTarget))
);
togglerElements.forEach((el) => (el.style.display = ""));
if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler);
},
initOnKeyListeners: () => {
// only install a listener if it is really needed
if (
!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS &&
!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS
)
return;
document.addEventListener("keydown", (event) => {
// bail for input elements
if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return;
// bail with special keys
if (event.altKey || event.ctrlKey || event.metaKey) return;
if (!event.shiftKey) {
switch (event.key) {
case "ArrowLeft":
if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
const prevLink = document.querySelector('link[rel="prev"]');
if (prevLink && prevLink.href) {
window.location.href = prevLink.href;
event.preventDefault();
}
break;
case "ArrowRight":
if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
const nextLink = document.querySelector('link[rel="next"]');
if (nextLink && nextLink.href) {
window.location.href = nextLink.href;
event.preventDefault();
}
break;
}
}
// some keyboard layouts may need Shift to get /
switch (event.key) {
case "/":
if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break;
Documentation.focusSearchBar();
event.preventDefault();
}
});
},
};
// quick alias for translations
const _ = Documentation.gettext;
_ready(Documentation.init);

View File

@@ -0,0 +1,13 @@
const DOCUMENTATION_OPTIONS = {
VERSION: '',
LANGUAGE: 'en',
COLLAPSE_INDEX: false,
BUILDER: 'html',
FILE_SUFFIX: '.html',
LINK_SUFFIX: '.html',
HAS_SOURCE: true,
SOURCELINK_SUFFIX: '.txt',
NAVIGATION_WITH_KEYS: false,
SHOW_SEARCH_SUMMARY: true,
ENABLE_SEARCH_SHORTCUTS: true,
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

2
docs/main_index/_static/jquery.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=4)}({4:function(e,t,r){}});

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,224 @@
const themeFlyoutDisplay = "hidden";
const themeVersionSelector = "True";
const themeLanguageSelector = "True";
if (themeFlyoutDisplay === "attached") {
function renderLanguages(config) {
if (!config.projects.translations.length) {
return "";
}
const languagesHTML = `
<dl>
<dt>Languages</dt>
${config.projects.translations
.map(
(translation) => `
<dd ${translation.slug == config.projects.current.slug ? 'class="rtd-current-item"' : ""}>
<a href="${translation.urls.documentation}">${translation.language.code}</a>
</dd>
`,
)
.join("\n")}
</dl>
`;
return languagesHTML;
}
function renderVersions(config) {
if (!config.versions.active.length) {
return "";
}
const versionsHTML = `
<dl>
<dt>Versions</dt>
${config.versions.active
.map(
(version) => `
<dd ${version.slug === config.versions.current.slug ? 'class="rtd-current-item"' : ""}>
<a href="${version.urls.documentation}">${version.slug}</a>
</dd>
`,
)
.join("\n")}
</dl>
`;
return versionsHTML;
}
function renderDownloads(config) {
if (!Object.keys(config.versions.current.downloads).length) {
return "";
}
const downloadsNameDisplay = {
pdf: "PDF",
epub: "Epub",
htmlzip: "HTML",
};
const downloadsHTML = `
<dl>
<dt>Downloads</dt>
${Object.entries(config.versions.current.downloads)
.map(
([name, url]) => `
<dd>
<a href="${url}">${downloadsNameDisplay[name]}</a>
</dd>
`,
)
.join("\n")}
</dl>
`;
return downloadsHTML;
}
document.addEventListener("readthedocs-addons-data-ready", function (event) {
const config = event.detail.data();
const flyout = `
<div class="rst-versions" data-toggle="rst-versions" role="note">
<span class="rst-current-version" data-toggle="rst-current-version">
<span class="fa fa-book"> Read the Docs</span>
v: ${config.versions.current.slug}
<span class="fa fa-caret-down"></span>
</span>
<div class="rst-other-versions">
<div class="injected">
${renderLanguages(config)}
${renderVersions(config)}
${renderDownloads(config)}
<dl>
<dt>On Read the Docs</dt>
<dd>
<a href="${config.projects.current.urls.home}">Project Home</a>
</dd>
<dd>
<a href="${config.projects.current.urls.builds}">Builds</a>
</dd>
<dd>
<a href="${config.projects.current.urls.downloads}">Downloads</a>
</dd>
</dl>
<dl>
<dt>Search</dt>
<dd>
<form id="flyout-search-form">
<input
class="wy-form"
type="text"
name="q"
aria-label="Search docs"
placeholder="Search docs"
/>
</form>
</dd>
</dl>
<hr />
<small>
<span>Hosted by <a href="https://about.readthedocs.org/?utm_source=&utm_content=flyout">Read the Docs</a></span>
</small>
</div>
</div>
`;
// Inject the generated flyout into the body HTML element.
document.body.insertAdjacentHTML("beforeend", flyout);
// Trigger the Read the Docs Addons Search modal when clicking on the "Search docs" input from inside the flyout.
document
.querySelector("#flyout-search-form")
.addEventListener("focusin", () => {
const event = new CustomEvent("readthedocs-search-show");
document.dispatchEvent(event);
});
})
}
if (themeLanguageSelector || themeVersionSelector) {
function onSelectorSwitch(event) {
const option = event.target.selectedIndex;
const item = event.target.options[option];
window.location.href = item.dataset.url;
}
document.addEventListener("readthedocs-addons-data-ready", function (event) {
const config = event.detail.data();
const versionSwitch = document.querySelector(
"div.switch-menus > div.version-switch",
);
if (themeVersionSelector) {
let versions = config.versions.active;
if (config.versions.current.hidden || config.versions.current.type === "external") {
versions.unshift(config.versions.current);
}
const versionSelect = `
<select>
${versions
.map(
(version) => `
<option
value="${version.slug}"
${config.versions.current.slug === version.slug ? 'selected="selected"' : ""}
data-url="${version.urls.documentation}">
${version.slug}
</option>`,
)
.join("\n")}
</select>
`;
versionSwitch.innerHTML = versionSelect;
versionSwitch.firstElementChild.addEventListener("change", onSelectorSwitch);
}
const languageSwitch = document.querySelector(
"div.switch-menus > div.language-switch",
);
if (themeLanguageSelector) {
if (config.projects.translations.length) {
// Add the current language to the options on the selector
let languages = config.projects.translations.concat(
config.projects.current,
);
languages = languages.sort((a, b) =>
a.language.name.localeCompare(b.language.name),
);
const languageSelect = `
<select>
${languages
.map(
(language) => `
<option
value="${language.language.code}"
${config.projects.current.slug === language.slug ? 'selected="selected"' : ""}
data-url="${language.urls.documentation}">
${language.language.name}
</option>`,
)
.join("\n")}
</select>
`;
languageSwitch.innerHTML = languageSelect;
languageSwitch.firstElementChild.addEventListener("change", onSelectorSwitch);
}
else {
languageSwitch.remove();
}
}
});
}
document.addEventListener("readthedocs-addons-data-ready", function (event) {
// Trigger the Read the Docs Addons Search modal when clicking on "Search docs" input from the topnav.
document
.querySelector("[role='search'] input")
.addEventListener("focusin", () => {
const event = new CustomEvent("readthedocs-search-show");
document.dispatchEvent(event);
});
});

View File

@@ -0,0 +1,192 @@
/*
* This script contains the language-specific data used by searchtools.js,
* namely the list of stopwords, stemmer, scorer and splitter.
*/
var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"];
/* Non-minified version is copied as a separate JS file, if available */
/**
* Porter Stemmer
*/
var Stemmer = function() {
var step2list = {
ational: 'ate',
tional: 'tion',
enci: 'ence',
anci: 'ance',
izer: 'ize',
bli: 'ble',
alli: 'al',
entli: 'ent',
eli: 'e',
ousli: 'ous',
ization: 'ize',
ation: 'ate',
ator: 'ate',
alism: 'al',
iveness: 'ive',
fulness: 'ful',
ousness: 'ous',
aliti: 'al',
iviti: 'ive',
biliti: 'ble',
logi: 'log'
};
var step3list = {
icate: 'ic',
ative: '',
alize: 'al',
iciti: 'ic',
ical: 'ic',
ful: '',
ness: ''
};
var c = "[^aeiou]"; // consonant
var v = "[aeiouy]"; // vowel
var C = c + "[^aeiouy]*"; // consonant sequence
var V = v + "[aeiou]*"; // vowel sequence
var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0
var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1
var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1
var s_v = "^(" + C + ")?" + v; // vowel in stem
this.stemWord = function (w) {
var stem;
var suffix;
var firstch;
var origword = w;
if (w.length < 3)
return w;
var re;
var re2;
var re3;
var re4;
firstch = w.substr(0,1);
if (firstch == "y")
w = firstch.toUpperCase() + w.substr(1);
// Step 1a
re = /^(.+?)(ss|i)es$/;
re2 = /^(.+?)([^s])s$/;
if (re.test(w))
w = w.replace(re,"$1$2");
else if (re2.test(w))
w = w.replace(re2,"$1$2");
// Step 1b
re = /^(.+?)eed$/;
re2 = /^(.+?)(ed|ing)$/;
if (re.test(w)) {
var fp = re.exec(w);
re = new RegExp(mgr0);
if (re.test(fp[1])) {
re = /.$/;
w = w.replace(re,"");
}
}
else if (re2.test(w)) {
var fp = re2.exec(w);
stem = fp[1];
re2 = new RegExp(s_v);
if (re2.test(stem)) {
w = stem;
re2 = /(at|bl|iz)$/;
re3 = new RegExp("([^aeiouylsz])\\1$");
re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
if (re2.test(w))
w = w + "e";
else if (re3.test(w)) {
re = /.$/;
w = w.replace(re,"");
}
else if (re4.test(w))
w = w + "e";
}
}
// Step 1c
re = /^(.+?)y$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
re = new RegExp(s_v);
if (re.test(stem))
w = stem + "i";
}
// Step 2
re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
suffix = fp[2];
re = new RegExp(mgr0);
if (re.test(stem))
w = stem + step2list[suffix];
}
// Step 3
re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
suffix = fp[2];
re = new RegExp(mgr0);
if (re.test(stem))
w = stem + step3list[suffix];
}
// Step 4
re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
re2 = /^(.+?)(s|t)(ion)$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
re = new RegExp(mgr1);
if (re.test(stem))
w = stem;
}
else if (re2.test(w)) {
var fp = re2.exec(w);
stem = fp[1] + fp[2];
re2 = new RegExp(mgr1);
if (re2.test(stem))
w = stem;
}
// Step 5
re = /^(.+?)e$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
re = new RegExp(mgr1);
re2 = new RegExp(meq1);
re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
w = stem;
}
re = /ll$/;
re2 = new RegExp(mgr1);
if (re.test(w) && re2.test(w)) {
re = /.$/;
w = w.replace(re,"");
}
// and turn initial Y back to y
if (firstch == "y")
w = firstch.toLowerCase() + w.substr(1);
return w;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 B

View File

@@ -0,0 +1,75 @@
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight { background: #f8f8f8; }
.highlight .c { color: #3D7B7B; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #F00 } /* Error */
.highlight .k { color: #008000; font-weight: bold } /* Keyword */
.highlight .o { color: #666 } /* Operator */
.highlight .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */
.highlight .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #9C6500 } /* Comment.Preproc */
.highlight .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */
.highlight .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */
.highlight .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #E40000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #008400 } /* Generic.Inserted */
.highlight .go { color: #717171 } /* Generic.Output */
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #04D } /* Generic.Traceback */
.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008000 } /* Keyword.Pseudo */
.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #B00040 } /* Keyword.Type */
.highlight .m { color: #666 } /* Literal.Number */
.highlight .s { color: #BA2121 } /* Literal.String */
.highlight .na { color: #687822 } /* Name.Attribute */
.highlight .nb { color: #008000 } /* Name.Builtin */
.highlight .nc { color: #00F; font-weight: bold } /* Name.Class */
.highlight .no { color: #800 } /* Name.Constant */
.highlight .nd { color: #A2F } /* Name.Decorator */
.highlight .ni { color: #717171; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #00F } /* Name.Function */
.highlight .nl { color: #767600 } /* Name.Label */
.highlight .nn { color: #00F; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #19177C } /* Name.Variable */
.highlight .ow { color: #A2F; font-weight: bold } /* Operator.Word */
.highlight .w { color: #BBB } /* Text.Whitespace */
.highlight .mb { color: #666 } /* Literal.Number.Bin */
.highlight .mf { color: #666 } /* Literal.Number.Float */
.highlight .mh { color: #666 } /* Literal.Number.Hex */
.highlight .mi { color: #666 } /* Literal.Number.Integer */
.highlight .mo { color: #666 } /* Literal.Number.Oct */
.highlight .sa { color: #BA2121 } /* Literal.String.Affix */
.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
.highlight .sc { color: #BA2121 } /* Literal.String.Char */
.highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */
.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #BA2121 } /* Literal.String.Double */
.highlight .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
.highlight .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */
.highlight .sx { color: #008000 } /* Literal.String.Other */
.highlight .sr { color: #A45A77 } /* Literal.String.Regex */
.highlight .s1 { color: #BA2121 } /* Literal.String.Single */
.highlight .ss { color: #19177C } /* Literal.String.Symbol */
.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #00F } /* Name.Function.Magic */
.highlight .vc { color: #19177C } /* Name.Variable.Class */
.highlight .vg { color: #19177C } /* Name.Variable.Global */
.highlight .vi { color: #19177C } /* Name.Variable.Instance */
.highlight .vm { color: #19177C } /* Name.Variable.Magic */
.highlight .il { color: #666 } /* Literal.Number.Integer.Long */

View File

@@ -0,0 +1,635 @@
/*
* Sphinx JavaScript utilities for the full-text search.
*/
"use strict";
/**
* Simple result scoring code.
*/
if (typeof Scorer === "undefined") {
var Scorer = {
// Implement the following function to further tweak the score for each result
// The function takes a result array [docname, title, anchor, descr, score, filename]
// and returns the new score.
/*
score: result => {
const [docname, title, anchor, descr, score, filename, kind] = result
return score
},
*/
// query matches the full name of an object
objNameMatch: 11,
// or matches in the last dotted part of the object name
objPartialMatch: 6,
// Additive scores depending on the priority of the object
objPrio: {
0: 15, // used to be importantResults
1: 5, // used to be objectResults
2: -5, // used to be unimportantResults
},
// Used when the priority is not in the mapping.
objPrioDefault: 0,
// query found in title
title: 15,
partialTitle: 7,
// query found in terms
term: 5,
partialTerm: 2,
};
}
// Global search result kind enum, used by themes to style search results.
class SearchResultKind {
static get index() { return "index"; }
static get object() { return "object"; }
static get text() { return "text"; }
static get title() { return "title"; }
}
const _removeChildren = (element) => {
while (element && element.lastChild) element.removeChild(element.lastChild);
};
/**
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
*/
const _escapeRegExp = (string) =>
string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
const _displayItem = (item, searchTerms, highlightTerms) => {
const docBuilder = DOCUMENTATION_OPTIONS.BUILDER;
const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX;
const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX;
const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY;
const contentRoot = document.documentElement.dataset.content_root;
const [docName, title, anchor, descr, score, _filename, kind] = item;
let listItem = document.createElement("li");
// Add a class representing the item's type:
// can be used by a theme's CSS selector for styling
// See SearchResultKind for the class names.
listItem.classList.add(`kind-${kind}`);
let requestUrl;
let linkUrl;
if (docBuilder === "dirhtml") {
// dirhtml builder
let dirname = docName + "/";
if (dirname.match(/\/index\/$/))
dirname = dirname.substring(0, dirname.length - 6);
else if (dirname === "index/") dirname = "";
requestUrl = contentRoot + dirname;
linkUrl = requestUrl;
} else {
// normal html builders
requestUrl = contentRoot + docName + docFileSuffix;
linkUrl = docName + docLinkSuffix;
}
let linkEl = listItem.appendChild(document.createElement("a"));
linkEl.href = linkUrl + anchor;
linkEl.dataset.score = score;
linkEl.innerHTML = title;
if (descr) {
listItem.appendChild(document.createElement("span")).innerHTML =
" (" + descr + ")";
// highlight search terms in the description
if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js
highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted"));
}
else if (showSearchSummary)
fetch(requestUrl)
.then((responseData) => responseData.text())
.then((data) => {
if (data)
listItem.appendChild(
Search.makeSearchSummary(data, searchTerms, anchor)
);
// highlight search terms in the summary
if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js
highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted"));
});
Search.output.appendChild(listItem);
};
const _finishSearch = (resultCount) => {
Search.stopPulse();
Search.title.innerText = _("Search Results");
if (!resultCount)
Search.status.innerText = Documentation.gettext(
"Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories."
);
else
Search.status.innerText = Documentation.ngettext(
"Search finished, found one page matching the search query.",
"Search finished, found ${resultCount} pages matching the search query.",
resultCount,
).replace('${resultCount}', resultCount);
};
const _displayNextItem = (
results,
resultCount,
searchTerms,
highlightTerms,
) => {
// results left, load the summary and display it
// this is intended to be dynamic (don't sub resultsCount)
if (results.length) {
_displayItem(results.pop(), searchTerms, highlightTerms);
setTimeout(
() => _displayNextItem(results, resultCount, searchTerms, highlightTerms),
5
);
}
// search finished, update title and status message
else _finishSearch(resultCount);
};
// Helper function used by query() to order search results.
// Each input is an array of [docname, title, anchor, descr, score, filename, kind].
// Order the results by score (in opposite order of appearance, since the
// `_displayNextItem` function uses pop() to retrieve items) and then alphabetically.
const _orderResultsByScoreThenName = (a, b) => {
const leftScore = a[4];
const rightScore = b[4];
if (leftScore === rightScore) {
// same score: sort alphabetically
const leftTitle = a[1].toLowerCase();
const rightTitle = b[1].toLowerCase();
if (leftTitle === rightTitle) return 0;
return leftTitle > rightTitle ? -1 : 1; // inverted is intentional
}
return leftScore > rightScore ? 1 : -1;
};
/**
* Default splitQuery function. Can be overridden in ``sphinx.search`` with a
* custom function per language.
*
* The regular expression works by splitting the string on consecutive characters
* that are not Unicode letters, numbers, underscores, or emoji characters.
* This is the same as ``\W+`` in Python, preserving the surrogate pair area.
*/
if (typeof splitQuery === "undefined") {
var splitQuery = (query) => query
.split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu)
.filter(term => term) // remove remaining empty strings
}
/**
* Search Module
*/
const Search = {
_index: null,
_queued_query: null,
_pulse_status: -1,
htmlToText: (htmlString, anchor) => {
const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html');
for (const removalQuery of [".headerlink", "script", "style"]) {
htmlElement.querySelectorAll(removalQuery).forEach((el) => { el.remove() });
}
if (anchor) {
const anchorContent = htmlElement.querySelector(`[role="main"] ${anchor}`);
if (anchorContent) return anchorContent.textContent;
console.warn(
`Anchored content block not found. Sphinx search tries to obtain it via DOM query '[role=main] ${anchor}'. Check your theme or template.`
);
}
// if anchor not specified or not found, fall back to main content
const docContent = htmlElement.querySelector('[role="main"]');
if (docContent) return docContent.textContent;
console.warn(
"Content block not found. Sphinx search tries to obtain it via DOM query '[role=main]'. Check your theme or template."
);
return "";
},
init: () => {
const query = new URLSearchParams(window.location.search).get("q");
document
.querySelectorAll('input[name="q"]')
.forEach((el) => (el.value = query));
if (query) Search.performSearch(query);
},
loadIndex: (url) =>
(document.body.appendChild(document.createElement("script")).src = url),
setIndex: (index) => {
Search._index = index;
if (Search._queued_query !== null) {
const query = Search._queued_query;
Search._queued_query = null;
Search.query(query);
}
},
hasIndex: () => Search._index !== null,
deferQuery: (query) => (Search._queued_query = query),
stopPulse: () => (Search._pulse_status = -1),
startPulse: () => {
if (Search._pulse_status >= 0) return;
const pulse = () => {
Search._pulse_status = (Search._pulse_status + 1) % 4;
Search.dots.innerText = ".".repeat(Search._pulse_status);
if (Search._pulse_status >= 0) window.setTimeout(pulse, 500);
};
pulse();
},
/**
* perform a search for something (or wait until index is loaded)
*/
performSearch: (query) => {
// create the required interface elements
const searchText = document.createElement("h2");
searchText.textContent = _("Searching");
const searchSummary = document.createElement("p");
searchSummary.classList.add("search-summary");
searchSummary.innerText = "";
const searchList = document.createElement("ul");
searchList.setAttribute("role", "list");
searchList.classList.add("search");
const out = document.getElementById("search-results");
Search.title = out.appendChild(searchText);
Search.dots = Search.title.appendChild(document.createElement("span"));
Search.status = out.appendChild(searchSummary);
Search.output = out.appendChild(searchList);
const searchProgress = document.getElementById("search-progress");
// Some themes don't use the search progress node
if (searchProgress) {
searchProgress.innerText = _("Preparing search...");
}
Search.startPulse();
// index already loaded, the browser was quick!
if (Search.hasIndex()) Search.query(query);
else Search.deferQuery(query);
},
_parseQuery: (query) => {
// stem the search terms and add them to the correct list
const stemmer = new Stemmer();
const searchTerms = new Set();
const excludedTerms = new Set();
const highlightTerms = new Set();
const objectTerms = new Set(splitQuery(query.toLowerCase().trim()));
splitQuery(query.trim()).forEach((queryTerm) => {
const queryTermLower = queryTerm.toLowerCase();
// maybe skip this "word"
// stopwords array is from language_data.js
if (
stopwords.indexOf(queryTermLower) !== -1 ||
queryTerm.match(/^\d+$/)
)
return;
// stem the word
let word = stemmer.stemWord(queryTermLower);
// select the correct list
if (word[0] === "-") excludedTerms.add(word.substr(1));
else {
searchTerms.add(word);
highlightTerms.add(queryTermLower);
}
});
if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js
localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" "))
}
// console.debug("SEARCH: searching for:");
// console.info("required: ", [...searchTerms]);
// console.info("excluded: ", [...excludedTerms]);
return [query, searchTerms, excludedTerms, highlightTerms, objectTerms];
},
/**
* execute search (requires search index to be loaded)
*/
_performSearch: (query, searchTerms, excludedTerms, highlightTerms, objectTerms) => {
const filenames = Search._index.filenames;
const docNames = Search._index.docnames;
const titles = Search._index.titles;
const allTitles = Search._index.alltitles;
const indexEntries = Search._index.indexentries;
// Collect multiple result groups to be sorted separately and then ordered.
// Each is an array of [docname, title, anchor, descr, score, filename, kind].
const normalResults = [];
const nonMainIndexResults = [];
_removeChildren(document.getElementById("search-progress"));
const queryLower = query.toLowerCase().trim();
for (const [title, foundTitles] of Object.entries(allTitles)) {
if (title.toLowerCase().trim().includes(queryLower) && (queryLower.length >= title.length/2)) {
for (const [file, id] of foundTitles) {
const score = Math.round(Scorer.title * queryLower.length / title.length);
const boost = titles[file] === title ? 1 : 0; // add a boost for document titles
normalResults.push([
docNames[file],
titles[file] !== title ? `${titles[file]} > ${title}` : title,
id !== null ? "#" + id : "",
null,
score + boost,
filenames[file],
SearchResultKind.title,
]);
}
}
}
// search for explicit entries in index directives
for (const [entry, foundEntries] of Object.entries(indexEntries)) {
if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) {
for (const [file, id, isMain] of foundEntries) {
const score = Math.round(100 * queryLower.length / entry.length);
const result = [
docNames[file],
titles[file],
id ? "#" + id : "",
null,
score,
filenames[file],
SearchResultKind.index,
];
if (isMain) {
normalResults.push(result);
} else {
nonMainIndexResults.push(result);
}
}
}
}
// lookup as object
objectTerms.forEach((term) =>
normalResults.push(...Search.performObjectSearch(term, objectTerms))
);
// lookup as search terms in fulltext
normalResults.push(...Search.performTermsSearch(searchTerms, excludedTerms));
// let the scorer override scores with a custom scoring function
if (Scorer.score) {
normalResults.forEach((item) => (item[4] = Scorer.score(item)));
nonMainIndexResults.forEach((item) => (item[4] = Scorer.score(item)));
}
// Sort each group of results by score and then alphabetically by name.
normalResults.sort(_orderResultsByScoreThenName);
nonMainIndexResults.sort(_orderResultsByScoreThenName);
// Combine the result groups in (reverse) order.
// Non-main index entries are typically arbitrary cross-references,
// so display them after other results.
let results = [...nonMainIndexResults, ...normalResults];
// remove duplicate search results
// note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept
let seen = new Set();
results = results.reverse().reduce((acc, result) => {
let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(',');
if (!seen.has(resultStr)) {
acc.push(result);
seen.add(resultStr);
}
return acc;
}, []);
return results.reverse();
},
query: (query) => {
const [searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms] = Search._parseQuery(query);
const results = Search._performSearch(searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms);
// for debugging
//Search.lastresults = results.slice(); // a copy
// console.info("search results:", Search.lastresults);
// print the results
_displayNextItem(results, results.length, searchTerms, highlightTerms);
},
/**
* search for object names
*/
performObjectSearch: (object, objectTerms) => {
const filenames = Search._index.filenames;
const docNames = Search._index.docnames;
const objects = Search._index.objects;
const objNames = Search._index.objnames;
const titles = Search._index.titles;
const results = [];
const objectSearchCallback = (prefix, match) => {
const name = match[4]
const fullname = (prefix ? prefix + "." : "") + name;
const fullnameLower = fullname.toLowerCase();
if (fullnameLower.indexOf(object) < 0) return;
let score = 0;
const parts = fullnameLower.split(".");
// check for different match types: exact matches of full name or
// "last name" (i.e. last dotted part)
if (fullnameLower === object || parts.slice(-1)[0] === object)
score += Scorer.objNameMatch;
else if (parts.slice(-1)[0].indexOf(object) > -1)
score += Scorer.objPartialMatch; // matches in last name
const objName = objNames[match[1]][2];
const title = titles[match[0]];
// If more than one term searched for, we require other words to be
// found in the name/title/description
const otherTerms = new Set(objectTerms);
otherTerms.delete(object);
if (otherTerms.size > 0) {
const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase();
if (
[...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0)
)
return;
}
let anchor = match[3];
if (anchor === "") anchor = fullname;
else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname;
const descr = objName + _(", in ") + title;
// add custom score for some objects according to scorer
if (Scorer.objPrio.hasOwnProperty(match[2]))
score += Scorer.objPrio[match[2]];
else score += Scorer.objPrioDefault;
results.push([
docNames[match[0]],
fullname,
"#" + anchor,
descr,
score,
filenames[match[0]],
SearchResultKind.object,
]);
};
Object.keys(objects).forEach((prefix) =>
objects[prefix].forEach((array) =>
objectSearchCallback(prefix, array)
)
);
return results;
},
/**
* search for full-text terms in the index
*/
performTermsSearch: (searchTerms, excludedTerms) => {
// prepare search
const terms = Search._index.terms;
const titleTerms = Search._index.titleterms;
const filenames = Search._index.filenames;
const docNames = Search._index.docnames;
const titles = Search._index.titles;
const scoreMap = new Map();
const fileMap = new Map();
// perform the search on the required terms
searchTerms.forEach((word) => {
const files = [];
// find documents, if any, containing the query word in their text/title term indices
// use Object.hasOwnProperty to avoid mismatching against prototype properties
const arr = [
{ files: terms.hasOwnProperty(word) ? terms[word] : undefined, score: Scorer.term },
{ files: titleTerms.hasOwnProperty(word) ? titleTerms[word] : undefined, score: Scorer.title },
];
// add support for partial matches
if (word.length > 2) {
const escapedWord = _escapeRegExp(word);
if (!terms.hasOwnProperty(word)) {
Object.keys(terms).forEach((term) => {
if (term.match(escapedWord))
arr.push({ files: terms[term], score: Scorer.partialTerm });
});
}
if (!titleTerms.hasOwnProperty(word)) {
Object.keys(titleTerms).forEach((term) => {
if (term.match(escapedWord))
arr.push({ files: titleTerms[term], score: Scorer.partialTitle });
});
}
}
// no match but word was a required one
if (arr.every((record) => record.files === undefined)) return;
// found search word in contents
arr.forEach((record) => {
if (record.files === undefined) return;
let recordFiles = record.files;
if (recordFiles.length === undefined) recordFiles = [recordFiles];
files.push(...recordFiles);
// set score for the word in each file
recordFiles.forEach((file) => {
if (!scoreMap.has(file)) scoreMap.set(file, new Map());
const fileScores = scoreMap.get(file);
fileScores.set(word, record.score);
});
});
// create the mapping
files.forEach((file) => {
if (!fileMap.has(file)) fileMap.set(file, [word]);
else if (fileMap.get(file).indexOf(word) === -1) fileMap.get(file).push(word);
});
});
// now check if the files don't contain excluded terms
const results = [];
for (const [file, wordList] of fileMap) {
// check if all requirements are matched
// as search terms with length < 3 are discarded
const filteredTermCount = [...searchTerms].filter(
(term) => term.length > 2
).length;
if (
wordList.length !== searchTerms.size &&
wordList.length !== filteredTermCount
)
continue;
// ensure that none of the excluded terms is in the search result
if (
[...excludedTerms].some(
(term) =>
terms[term] === file ||
titleTerms[term] === file ||
(terms[term] || []).includes(file) ||
(titleTerms[term] || []).includes(file)
)
)
break;
// select one (max) score for the file.
const score = Math.max(...wordList.map((w) => scoreMap.get(file).get(w)));
// add result to the result list
results.push([
docNames[file],
titles[file],
"",
null,
score,
filenames[file],
SearchResultKind.text,
]);
}
return results;
},
/**
* helper function to return a node containing the
* search summary for a given text. keywords is a list
* of stemmed words.
*/
makeSearchSummary: (htmlText, keywords, anchor) => {
const text = Search.htmlToText(htmlText, anchor);
if (text === "") return null;
const textLower = text.toLowerCase();
const actualStartPosition = [...keywords]
.map((k) => textLower.indexOf(k.toLowerCase()))
.filter((i) => i > -1)
.slice(-1)[0];
const startWithContext = Math.max(actualStartPosition - 120, 0);
const top = startWithContext === 0 ? "" : "...";
const tail = startWithContext + 240 < text.length ? "..." : "";
let summary = document.createElement("p");
summary.classList.add("context");
summary.textContent = top + text.substr(startWithContext, 240).trim() + tail;
return summary;
},
};
_ready(Search.init);

View File

@@ -0,0 +1,154 @@
/* Highlighting utilities for Sphinx HTML documentation. */
"use strict";
const SPHINX_HIGHLIGHT_ENABLED = true
/**
* highlight a given string on a node by wrapping it in
* span elements with the given class name.
*/
const _highlight = (node, addItems, text, className) => {
if (node.nodeType === Node.TEXT_NODE) {
const val = node.nodeValue;
const parent = node.parentNode;
const pos = val.toLowerCase().indexOf(text);
if (
pos >= 0 &&
!parent.classList.contains(className) &&
!parent.classList.contains("nohighlight")
) {
let span;
const closestNode = parent.closest("body, svg, foreignObject");
const isInSVG = closestNode && closestNode.matches("svg");
if (isInSVG) {
span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
} else {
span = document.createElement("span");
span.classList.add(className);
}
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
const rest = document.createTextNode(val.substr(pos + text.length));
parent.insertBefore(
span,
parent.insertBefore(
rest,
node.nextSibling
)
);
node.nodeValue = val.substr(0, pos);
/* There may be more occurrences of search term in this node. So call this
* function recursively on the remaining fragment.
*/
_highlight(rest, addItems, text, className);
if (isInSVG) {
const rect = document.createElementNS(
"http://www.w3.org/2000/svg",
"rect"
);
const bbox = parent.getBBox();
rect.x.baseVal.value = bbox.x;
rect.y.baseVal.value = bbox.y;
rect.width.baseVal.value = bbox.width;
rect.height.baseVal.value = bbox.height;
rect.setAttribute("class", className);
addItems.push({ parent: parent, target: rect });
}
}
} else if (node.matches && !node.matches("button, select, textarea")) {
node.childNodes.forEach((el) => _highlight(el, addItems, text, className));
}
};
const _highlightText = (thisNode, text, className) => {
let addItems = [];
_highlight(thisNode, addItems, text, className);
addItems.forEach((obj) =>
obj.parent.insertAdjacentElement("beforebegin", obj.target)
);
};
/**
* Small JavaScript module for the documentation.
*/
const SphinxHighlight = {
/**
* highlight the search words provided in localstorage in the text
*/
highlightSearchWords: () => {
if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight
// get and clear terms from localstorage
const url = new URL(window.location);
const highlight =
localStorage.getItem("sphinx_highlight_terms")
|| url.searchParams.get("highlight")
|| "";
localStorage.removeItem("sphinx_highlight_terms")
url.searchParams.delete("highlight");
window.history.replaceState({}, "", url);
// get individual terms from highlight string
const terms = highlight.toLowerCase().split(/\s+/).filter(x => x);
if (terms.length === 0) return; // nothing to do
// There should never be more than one element matching "div.body"
const divBody = document.querySelectorAll("div.body");
const body = divBody.length ? divBody[0] : document.querySelector("body");
window.setTimeout(() => {
terms.forEach((term) => _highlightText(body, term, "highlighted"));
}, 10);
const searchBox = document.getElementById("searchbox");
if (searchBox === null) return;
searchBox.appendChild(
document
.createRange()
.createContextualFragment(
'<p class="highlight-link">' +
'<a href="javascript:SphinxHighlight.hideSearchWords()">' +
_("Hide Search Matches") +
"</a></p>"
)
);
},
/**
* helper function to hide the search marks again
*/
hideSearchWords: () => {
document
.querySelectorAll("#searchbox .highlight-link")
.forEach((el) => el.remove());
document
.querySelectorAll("span.highlighted")
.forEach((el) => el.classList.remove("highlighted"));
localStorage.removeItem("sphinx_highlight_terms")
},
initEscapeListener: () => {
// only install a listener if it is really needed
if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return;
document.addEventListener("keydown", (event) => {
// bail for input elements
if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return;
// bail with special keys
if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return;
if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) {
SphinxHighlight.hideSearchWords();
event.preventDefault();
}
});
},
};
_ready(() => {
/* Do not call highlightSearchWords() when we are on the search page.
* It will highlight words from the *previous* search query.
*/
if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords();
SphinxHighlight.initEscapeListener();
});

384
docs/main_index/index.html Normal file
View File

@@ -0,0 +1,384 @@
<!DOCTYPE html>
<html class="writer-html5" lang="en" data-content_root="./">
<head>
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Welcome to slsDetectorPackage's documentation! &mdash; slsDetectorPackage documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=b86133f3" />
<link rel="stylesheet" type="text/css" href="_static/css/theme.css?v=e59714d7" />
<link rel="stylesheet" type="text/css" href="_static/css/extra.css?v=2be88464" />
<script src="_static/jquery.js?v=5d32c60e"></script>
<script src="_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
<script src="_static/documentation_options.js?v=5929fcd5"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/js/theme.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="10.0.0" href="https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.0/index.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="#" class="icon icon-home">
slsDetectorPackage
</a>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="search.html" method="get">
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Versions:</span></p>
<ul>
<li class="toctree-l1"><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.0/index.html">10.0.0</a></li>
<li class="toctree-l1"><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/9.2.0/index.html">9.2.0</a></li>
<li class="toctree-l1"><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/9.1.1/index.html">9.1.1</a></li>
<li class="toctree-l1"><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/9.1.0/index.html">9.1.0</a></li>
<li class="toctree-l1"><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/9.0.0/index.html">9.0.0</a></li>
<li class="toctree-l1"><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/developer/index.html">Developer</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="#">slsDetectorPackage</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="#" class="icon icon-home" aria-label="Home"></a></li>
<li class="breadcrumb-item active">Welcome to slsDetectorPackage's documentation!</li>
<li class="wy-breadcrumbs-aside">
<a href="_sources/index.html.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<section id="welcome-to-slsdetectorpackage-s-documentation">
<h1>Welcome to slsDetectorPackage's documentation!<a class="headerlink" href="#welcome-to-slsdetectorpackage-s-documentation" title="Link to this heading"></a></h1>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>This is the documentation for the latest versions of the slsDetectorPackage. For further detector specific documentation, visit <a class="reference external" href="https://www.psi.ch/en/detectors/documentation">this page</a>.</p>
<p><b>Mailing list: </b>To receive updates about the latest releases, please susbscribe <a class="reference external" href="https://psilists.ethz.ch/sympa/subscribe/slsdetectorpackage">here</a>.</p>
</div>
<div class="toctree-wrapper compound">
<p class="caption" role="heading"><span class="caption-text">Versions:</span></p>
<dl>
<dd>
<table class="docutils align-default">
<thead>
<tr class="row-odd">
<th class="head"><p>GitHub Link</p></th>
<th class="head"><p>Release Type</p></th>
<th class="head"><p>Release Date</p></th>
<th class="head"><p>Release Notes</p></th>
<th class="head"><p>Documentation</p></th>
</tr>
</thead>
<tbody>
<tr class="row-odd">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/releases/tag/10.0.0">10.0.0</a></p></td>
<td><p>Major</p></td>
<td><p>10.09.2025</p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/releases/RELEASE_v10.0.0.txt">10.0.0 Release Notes</a></p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.0/index.html">10.0.0 Docs</a></p></td>
</tr>
<tr class="row-even">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/releases/tag/9.2.0">9.2.0</a></p></td>
<td><p>Minor</p></td>
<td><p>02.06.2025</p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/releases/RELEASE_v9.2.0.txt">9.2.0 Release Notes</a></p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/9.2.0/index.html">9.2.0 Docs</a></p></td>
</tr>
<tr class="row-odd">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/releases/tag/9.1.1">9.1.1</a></p></td>
<td><p>Bug Fix</p></td>
<td><p>22.05.2025</p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/releases/RELEASE_v9.1.1.txt">9.1.1 Release Notes</a></p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/9.1.1/index.html">9.1.1 Docs</a></p></td>
</tr>
<tr class="row-even">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/releases/tag/9.1.0">9.1.0</a></p></td>
<td><p>Minor</p></td>
<td><p>28.03.2025</p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/releases/RELEASE_v9.1.0.txt">9.1.0 Release Notes</a></p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/9.1.0/index.html">9.1.0 Docs</a></p></td>
</tr>
<tr class="row-odd">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/releases/tag/9.0.0">9.0.0</a></p></td>
<td><p>Major</p></td>
<td><p>26.11.2024</p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/releases/RELEASE_v9.0.0.txt">9.0.0 Release Notes</a></p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/9.0.0/index.html">9.0.0 Docs</a></p></td>
</tr>
<tr class="row-even">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/releases/tag/8.0.2">8.0.2</a></p></td>
<td><p>Bug Fix</p></td>
<td><p>18.09.2024</p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/releases/RELEASE_v8.0.2.txt">8.0.2 Release Notes</a></p></td>
<td><p>&nbsp;</p></td>
</tr>
<tr class="row-odd">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/releases/tag/8.0.1">8.0.1</a></p></td>
<td><p>Bug Fix</p></td>
<td><p>16.01.2024</p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/releases/RELEASE_v8.0.1.txt">8.0.1 Release Notes</a></p></td>
<td><p>&nbsp;</p></td>
</tr>
<tr class="row-even">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/releases/tag/8.0.0">8.0.0</a></p></td>
<td><p>Major</p></td>
<td><p>13.11.2023</p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/releases/RELEASE_v8.0.0.txt">8.0.0 Release Notes</a></p></td>
<td><p>&nbsp;</p></td>
</tr>
<tr class="row-odd">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/releases/tag/7.0.3">7.0.3</a></p></td>
<td><p>Bug Fix</p></td>
<td><p>14.11.2023</p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/releases/RELEASE_v7.0.3.txt">7.0.3 Release Notes</a></p></td>
<td><p>&nbsp;</p></td>
</tr>
<tr class="row-even">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/releases/tag/7.0.2">7.0.2</a></p></td>
<td><p>Bug Fix</p></td>
<td><p>12.07.2023</p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/releases/RELEASE_v7.0.2.txt">7.0.2 Release Notes</a></p></td>
<td><p>&nbsp;</p></td>
</tr>
<tr class="row-odd">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/releases/tag/7.0.1">7.0.1</a></p></td>
<td><p>Bug Fix</p></td>
<td><p>24.03.2023</p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/releases/RELEASE_v7.0.1.txt">7.0.1 Release Notes</a></p></td>
<td><p>&nbsp;</p></td>
</tr>
<tr class="row-even">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/releases/tag/7.0.0">7.0.0</a></p></td>
<td><p>Major</p></td>
<td><p>24.02.2023</p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/releases/RELEASE_v7.0.0.txt">7.0.0 Release Notes</a></p></td>
<td><p>&nbsp;</p></td>
</tr>
<tr class="row-odd">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/releases/tag/6.1.2">6.1.2</a></p></td>
<td><p>Bug Fix</p></td>
<td><p>25.11.2022</p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/releases/RELEASE_v6.1.2.txt">6.1.2 Release Notes</a></p></td>
<td><p>&nbsp;</p></td>
</tr>
<tr class="row-even">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/releases/tag/6.1.1">6.1.1</a></p></td>
<td><p>Bug Fix</p></td>
<td><p>04.01.2022</p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/releases/RELEASE_v6.1.1.txt">6.1.1 Release Notes</a></p></td>
<td><p>&nbsp;</p></td>
</tr>
<tr class="row-odd">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/releases/tag/6.1.0">6.1.0</a></p></td>
<td><p>Minor</p></td>
<td><p>25.11.2021</p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/releases/RELEASE_v6.1.0.txt">6.1.0 Release Notes</a></p></td>
<td><p>&nbsp;</p></td>
</tr>
<tr class="row-even">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/releases/tag/6.0.0">6.0.0</a></p></td>
<td><p>Major</p></td>
<td><p>20.10.2021</p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/releases/RELEASE_v6.0.0.txt">6.0.0 Release Notes</a></p></td>
<td><p>&nbsp;</p></td>
</tr>
<tr class="row-odd">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/releases/tag/5.1.0">5.1.0</a></p></td>
<td><p>Minor</p></td>
<td><p>22.03.2021</p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/releases/RELEASE_v5.1.0.txt">5.1.0 Release Notes</a></p></td>
<td><p>&nbsp;</p></td>
</tr>
<tr class="row-even">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/releases/tag/5.0.1">5.0.1</a></p></td>
<td><p>Bug Fix</p></td>
<td><p>25.11.2020</p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/releases/RELEASE_v5.0.1.txt">5.0.1 Release Notes</a></p></td>
<td><p>&nbsp;</p></td>
</tr>
<tr class="row-odd">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/releases/tag/5.0.0">5.0.0</a></p></td>
<td><p>Major</p></td>
<td><p>18.11.2020</p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/releases/RELEASE_v5.0.0.txt">5.0.0 Release Notes</a></p></td>
<td><p>&nbsp;</p></td>
</tr>
<tr class="row-odd">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/tree/developer">Developer</a></p></td>
<td><p>&nbsp;</p></td>
<td><p>&nbsp;</p></td>
<td><p>&nbsp;</p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/developer/index.html">Developer Docs</a></p></td>
</tr>
</tbody>
</table>
</dd>
</dl>
</div>
</section>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.0/index.html" class="btn btn-neutral float-right" title="10.0.0" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2020, PSD Detector Group.</p>
</div>
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
<a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);ion>
});
</script>
ery(function () {
</body>hinxRtdTheme.Navigation.enable(true);
</html></body>
</html>

View File

@@ -0,0 +1,160 @@
<!DOCTYPE html>
<html class="writer-html5" lang="en" data-content_root="./">
<head>
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Welcome to slsDetectorPackage's documentation! &mdash; slsDetectorPackage documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=b86133f3" />
<link rel="stylesheet" type="text/css" href="_static/css/theme.css?v=e59714d7" />
<link rel="stylesheet" type="text/css" href="_static/css/extra.css?v=2be88464" />
<script src="_static/jquery.js?v=5d32c60e"></script>
<script src="_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
<script src="_static/documentation_options.js?v=5929fcd5"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/js/theme.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="{{ versions[0]["version"] }}" href="https://slsdetectorgroup.github.io/slsDetectorPackage/{{ versions[0]["version"] }}/index.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="#" class="icon icon-home">
slsDetectorPackage
</a>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="search.html" method="get">
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Versions:</span></p>
<ul>
{% for v in versions if v["has_docs"] %}
<li class="toctree-l1"><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/{{ v["version"] }}/index.html">{{ v["version"] }}</a></li>
{% endfor %}
<li class="toctree-l1"><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/developer/index.html">Developer</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="#">slsDetectorPackage</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="#" class="icon icon-home" aria-label="Home"></a></li>
<li class="breadcrumb-item active">Welcome to slsDetectorPackage's documentation!</li>
<li class="wy-breadcrumbs-aside">
<a href="_sources/index.html.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<section id="welcome-to-slsdetectorpackage-s-documentation">
<h1>Welcome to slsDetectorPackage's documentation!<a class="headerlink" href="#welcome-to-slsdetectorpackage-s-documentation" title="Link to this heading"></a></h1>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>This is the documentation for the latest versions of the slsDetectorPackage. For further detector specific documentation, visit <a class="reference external" href="https://www.psi.ch/en/detectors/documentation">this page</a>.</p>
<p><b>Mailing list: </b>To receive updates about the latest releases, please susbscribe <a class="reference external" href="https://psilists.ethz.ch/sympa/subscribe/slsdetectorpackage">here</a>.</p>
</div>
<div class="toctree-wrapper compound">
<p class="caption" role="heading"><span class="caption-text">Versions:</span></p>
<dl>
<dd>
<table class="docutils align-default">
<thead>
<tr class="row-odd">
<th class="head"><p>GitHub Link</p></th>
<th class="head"><p>Release Type</p></th>
<th class="head"><p>Release Date</p></th>
<th class="head"><p>Release Notes</p></th>
<th class="head"><p>Documentation</p></th>
</tr>
</thead>
<tbody>
{% for v in versions %}
{# Check if version >= 10.0.0 for .md vs .txt #}
{% set version_parts = v["version"].split('.') | map('int') | list %}
{% set is_new_format = (version_parts[0] > 10) or (version_parts[0] == 10 and version_parts[1] > 0 and version_parts[2] > 0) %}
{% set release_ext = '.md' if is_new_format else '.txt' %}
<tr class="row-{{ 'even' if loop.index is even else 'odd' }}">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/releases/tag/{{ v["version"] }}">{{ v["version"] }}</a></p></td>
<td><p>{{ v["type"] }}</p></td>
<td><p>{{ v["date"] }}</p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/releases/RELEASE_v{{ v["version"] }}{{ release_ext }}">{{ v["version"] }} Release Notes</a></p></td>
<td><p>{% if v["has_docs"] %}<a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/{{ v["version"] }}/index.html">{{ v["version"] }} Docs</a>{% else %}&nbsp;{% endif %}</p></td>
</tr>
{% endfor %}
<tr class="row-{{ 'even' if versions|length is even else 'odd' }}">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/tree/developer">Developer</a></p></td>
<td><p>&nbsp;</p></td>
<td><p>&nbsp;</p></td>
<td><p>&nbsp;</p></td>
<td><p><a class="reference external" href="https://slsdetectorgroup.github.io/slsDetectorPackage/developer/index.html">Developer Docs</a></p></td>
</tr>
</tbody>
</table>
</dd>
</dl>
</div>
</section>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="https://slsdetectorgroup.github.io/slsDetectorPackage/{{ versions[0]["version"] }}/index.html" class="btn btn-neutral float-right" title="{{ versions[0]["version"] }}" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2020, PSD Detector Group.</p>
</div>
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
<a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);ion>
});
</script>
ery(function () {
</body>hinxRtdTheme.Navigation.enable(true);
</html></body>
</html>

View File

@@ -0,0 +1,119 @@
"""
Render the index HTML from a Jinja2 template with version data.
Can also add new versions to the YAML data file.
Usage:
# Just render from existing data
python render_main_index.py --template main_index.html.j2 --output main_index.html --data versions.yaml
# Add a new version and render
python render_main_index.py --data versions.yaml --add-version 10.1.0 --type Minor --date "15.10.2025" --template main_index.html.j2 --output main_index.html
"""
import argparse
from pathlib import Path
from jinja2 import Template
import yaml
import os
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
def load_versions(data_path: Path):
"""Load version data from YAML file."""
with open(data_path, 'r') as f:
data = yaml.safe_load(f)
return data['versions']
def save_versions(data_path: Path, versions):
"""Save version data to YAML file."""
data = {
'versions': versions
}
with open(data_path, 'w') as f:
yaml.dump(data, f, default_flow_style=False, sort_keys=False)
print(f"✓ Saved version data to {data_path}")
def extract_release_type(version: str) -> str:
"""Extract release type from version string."""
parts = version.split('.')
if len(parts) != 3:
return "Unknown"
major, minor, patch = map(int, parts)
if minor == 0 and patch == 0:
return "Major"
elif patch == 0:
return "Minor"
else:
return "Bug Fix"
def add_version(data_path: Path, version: str, release_type: str, date: str, has_docs: bool = True):
"""Add a new version to the YAML data file."""
versions = load_versions(data_path)
# Add to table (check if not already present)
new_entry = {
'version': version,
'type': release_type,
'date': date,
'has_docs': has_docs
}
versions.insert(0, new_entry)
print(f"✓ Added version {new_entry} to version data")
save_versions(data_path, versions)
def render_template(template_path: Path, output_path: Path, data_path: Path):
"""Render the Jinja2 template with version data."""
versions = load_versions(data_path)
with open(template_path, 'r') as f:
template = Template(f.read())
html = template.render(
versions=versions
)
with open(output_path, 'w') as f:
f.write(html)
print(f"✓ Rendered {output_path}")
def main():
parser = argparse.ArgumentParser(description='Manage versions and render main index HTML')
parser.add_argument('--data', type=Path, default=Path(SCRIPT_DIR + "/versions.yaml"),
help='Path to versions YAML data file')
# Options for adding a new version
parser.add_argument('--version', type=str,
help='new version (e.g., 10.1.0)')
parser.add_argument('--date', type=str,
help='Release date (e.g., 15.10.2025)')
# Options for rendering
parser.add_argument('--template', type=Path, default=Path(SCRIPT_DIR + "/index.html.j2"),
help='Path to Jinja2 template file')
parser.add_argument('--output', type=Path, default=Path(SCRIPT_DIR + "/index.html"),
help='Path to output HTML file')
args = parser.parse_args()
# Add new version if requested
if args.version:
if not args.date:
parser.error("--version requires --date")
release_type = extract_release_type(args.version)
add_version(args.data, args.version, release_type, args.date, has_docs=True)
# Render template if requested
if args.template and args.output:
render_template(args.template, args.output, args.data)
elif args.template or args.output:
parser.error("--template and --output must be used together")
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,77 @@
versions:
- version: 10.0.0
type: Major
date: 10.09.2025
has_docs: true
- version: 9.2.0
type: Minor
date: 02.06.2025
has_docs: true
- version: 9.1.1
type: Bug Fix
date: 22.05.2025
has_docs: true
- version: 9.1.0
type: Minor
date: 28.03.2025
has_docs: true
- version: 9.0.0
type: Major
date: 26.11.2024
has_docs: true
- version: 8.0.2
type: Bug Fix
date: 18.09.2024
has_docs: false
- version: 8.0.1
type: Bug Fix
date: 16.01.2024
has_docs: false
- version: 8.0.0
type: Major
date: 13.11.2023
has_docs: false
- version: 7.0.3
type: Bug Fix
date: 14.11.2023
has_docs: false
- version: 7.0.2
type: Bug Fix
date: 12.07.2023
has_docs: false
- version: 7.0.1
type: Bug Fix
date: 24.03.2023
has_docs: false
- version: 7.0.0
type: Major
date: 24.02.2023
has_docs: false
- version: 6.1.2
type: Bug Fix
date: 25.11.2022
has_docs: false
- version: 6.1.1
type: Bug Fix
date: 04.01.2022
has_docs: false
- version: 6.1.0
type: Minor
date: 25.11.2021
has_docs: false
- version: 6.0.0
type: Major
date: 20.10.2021
has_docs: false
- version: 5.1.0
type: Minor
date: 22.03.2021
has_docs: false
- version: 5.0.1
type: Bug Fix
date: 25.11.2020
has_docs: false
- version: 5.0.0
type: Major
date: 18.11.2020
has_docs: false

9
docs/src/Versioning.rst Normal file
View File

@@ -0,0 +1,9 @@
Package Versioning
===================
We use Semantic Versioning for our releases. Each version number is in the format MAJOR.MINOR.PATCH, where:
- **MAJOR** version increments indicate incompatible API changes,
- **MINOR** version increments indicate added functionality in a backward-compatible manner,
- **PATCH** version increments indicate backward-compatible bug fixes.

View File

@@ -66,6 +66,7 @@ slsDetectorPackage
container_utils
type_traits
ToString
Versioning
Testing
.. toctree::

View File

@@ -6,17 +6,18 @@ Script to update API VERSION file based on the version in VERSION file.
import argparse
import sys
from pathlib import Path
import os
import re
import time
from datetime import datetime
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
ROOT_DIR = Path(__file__).resolve().parent.parent
API_FILE = SCRIPT_DIR + "/slsSupportLib/include/sls/versionAPI.h"
API_FILE = ROOT_DIR / "slsSupportLib/include/sls/versionAPI.h"
VERSION_FILE = SCRIPT_DIR + "/VERSION"
VERSION_FILE = ROOT_DIR / "VERSION"
parser = argparse.ArgumentParser(description = 'updates API version')
parser.add_argument('api_module_name', choices=["APILIB", "APIRECEIVER", "APICTB", "APIGOTTHARD2", "APIMOENCH", "APIEIGER", "APIXILINXCTB", "APIJUNGFRAU", "APIMYTHEN3"], help = 'module name to change api version options are: ["APILIB", "APIRECEIVER", "APICTB", "APIGOTTHARD2", "APIMOENCH", "APIEIGER", "APIXILINXCTB", "APIJUNGFRAU", "APIMYTHEN3"]')
@@ -73,7 +74,7 @@ if __name__ == "__main__":
args = parser.parse_args()
api_dir = SCRIPT_DIR + "/" + args.api_dir
api_dir = ROOT_DIR / args.api_dir
update_api_version(args.api_module_name, api_dir)

View File

@@ -1,15 +1,15 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2025 Contributors to the SLS Detector Package
"""
Script to update API VERSION for slsReceiverSoftware or slsDetectorSoftware
script to update API VERSION for slsReceiverSoftware or slsDetectorSoftware
"""
import argparse
import os
from pathlib import Path
from updateAPIVersion import update_api_version
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
ROOT_DIR = Path(__file__).resolve().parent.parent
parser = argparse.ArgumentParser(description = 'updates API version')
parser.add_argument('module_name', nargs="?", choices=["slsDetectorSoftware", "slsReceiverSoftware", "all"], default="all", help = 'module name to change api version options are: ["slsDetectorSoftware", "slsReceiverSoftware, "all"]')
@@ -19,13 +19,13 @@ if __name__ == "__main__":
if args.module_name == "all":
client_names = ["APILIB", "APIRECEIVER"]
client_directories = [SCRIPT_DIR+"/slsDetectorSoftware", SCRIPT_DIR+"/slsReceiverSoftware"]
client_directories = [ROOT_DIR / "slsDetectorSoftware", ROOT_DIR / "slsReceiverSoftware"]
elif args.module_name == "slsDetectorSoftware":
client_names = ["APILIB"]
client_directories = [SCRIPT_DIR+"/slsDetectorSoftware"]
client_directories = [ROOT_DIR / "slsDetectorSoftware"]
else:
client_names = ["APIRECEIVER"]
client_directories = [SCRIPT_DIR+"/slsReceiverSoftware"]
client_directories = [ROOT_DIR / "slsReceiverSoftware"]
for client_name, client_directory in zip(client_names, client_directories):
update_api_version(client_name, client_directory)

90
etc/update_version.py Normal file
View File

@@ -0,0 +1,90 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package
"""
Script to update VERSION file with semantic versioning if provided as an argument, or with 0.0.0 if no argument is provided.
"""
import sys
from pathlib import Path
from datetime import datetime
from tempfile import template
import yaml
import argparse
from packaging.version import Version, InvalidVersion
ROOT_DIR = Path(__file__).resolve().parent.parent
SCRIPT_DIR = Path(__file__).resolve().parent.parent
def get_version(version : str) -> str:
try:
v = Version(version) # normalizcheck if version follows PEP 440 specification
#replace -
return version.replace("-", ".")
except InvalidVersion as e:
print(f"Invalid version {version}. Version format must follow semantic versioning format of python PEP 440 version identification specification.")
sys.exit(1)
def write_version_to_file(version):
version_file_path = Path(SCRIPT_DIR / "VERSION")
with open(version_file_path, "w") as version_file:
version_file.write(version)
print(f"Version {version} written to VERSION file.")
def extract_release_type(version: str) -> str:
"""Extract release type from version string."""
parts = version.split('.')
if len(parts) != 3:
raise ValueError(f"Version {version} does not follow semantic versioning format of major.minor.patch")
major, minor, patch = map(int, parts)
if minor == 0 and patch == 0:
return "Major"
elif patch == 0:
return "Minor"
else:
return "Bug Fix"
def get_previous_version(data_path: Path, version : str) -> str:
"""Get the previous version from the versions YAML file."""
with open(data_path, 'r') as f:
data = yaml.safe_load(f)
prev_version = data['versions'][0]["version"]
if prev_version == version: #already updated to new version
prev_version = data['versions'][1]["version"]
return prev_version
def main():
parser = argparse.ArgumentParser(description='Update version release notes')
parser.add_argument('--version', required=True, type=str, help='version to write to VERSION file')
parser.add_argument('--update_version_only', action="store_true", help='Only update version in VERSION file, do not generate release notes')
args = parser.parse_args()
version = get_version(args.version)
write_version_to_file(version)
if not args.update_version_only:
release_type = extract_release_type(version)
prev_version = get_previous_version(ROOT_DIR / "docs/main_index/versions.yaml", version)
# Read template
template = Path(ROOT_DIR / "RELEASE.md").read_text()
# Substitute version and date
output = template.replace("{{VERSION}}", version)
output = output.replace("{{DATE}}", datetime.now().strftime("%Y-%m-%d"))
output = output.replace("{{RELEASE_TYPE}}", release_type)
output = output.replace("{{PREVIOUS_VERSION}}", prev_version)
# Write output
Path(ROOT_DIR / "RELEASE.md").write_text(output)
print(f"Generated RELEASE.md for version {version}")
# Main script
if __name__ == "__main__":
main()

View File

@@ -1,42 +0,0 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package
"""
Script to update VERSION file with semantic versioning if provided as an argument, or with 0.0.0 if no argument is provided.
"""
import sys
import os
from packaging.version import Version, InvalidVersion
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
def get_version():
# Check at least one argument is passed
if len(sys.argv) < 2:
return "0.0.0"
version = sys.argv[1]
try:
v = Version(version) # normalizcheck if version follows PEP 440 specification
#replace -
return version.replace("-", ".")
except InvalidVersion as e:
print(f"Invalid version {version}. Version format must follow semantic versioning format of python PEP 440 version identification specification.")
sys.exit(1)
def write_version_to_file(version):
version_file_path = os.path.join(SCRIPT_DIR, "VERSION")
with open(version_file_path, "w") as version_file:
version_file.write(version)
print(f"Version {version} written to VERSION file.")
# Main script
if __name__ == "__main__":
version = get_version()
write_version_to_file(version)