mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2026-10-17 19:15:12 +02:00
10.0.1.rc (#1607)
* Fix conda build and update GitHub Actions versions (10.0.1) (#1596) * repalce conda build with conda-build, bump actions versions (cherry picked from commitfbd5edaa82) * updated github actions versions to run on node 24 (cherry picked from commitc1db2c8958) * updated workflows --------- Co-authored-by: lrlunin <lunin.leonid@gmail.com> Co-authored-by: Alice <alice.mazzoleni@psi.ch> * Fix/fifo race (#1591) (#1592) * fix race condition in Fifo::FreeAddress (cherry picked from commitdd5b2360d6) * bumped version to 10.0.1 (#1598) * port of RPM building and gitea workflows (#1599) * removed uid test (#1604) * Dev/automate documentation build (#1357) (#1605) * 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> * 1001/updated release notes (#1606) * updated release notes * updated Release notes * typo --------- Co-authored-by: Erik Fröjdh <erik.frojdh@gmail.com> Co-authored-by: lrlunin <lunin.leonid@gmail.com> Co-authored-by: Dhanya Thattil <dhanya.thattil@psi.ch>
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
name: Build RPMs on RHEL8 docker image
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
deploy:
|
||||
description: "Upload the RPMs to the Gitea package registry"
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: "ubuntu-latest"
|
||||
container:
|
||||
image: gitea.psi.ch/detectors/rhel8-detectors-dev
|
||||
steps:
|
||||
- name: Clone repository
|
||||
run: |
|
||||
git lfs install --skip-smudge
|
||||
echo Cloning ${{ github.ref_name }}
|
||||
git clone https://${{secrets.GITHUB_TOKEN}}@gitea.psi.ch/${{ github.repository }}.git --branch=${{ github.ref_name }} .
|
||||
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
dnf -y install rpm-build qt5-qtbase-devel qt5-qtsvg-devel \
|
||||
libpng-devel zlib-devel expat-devel libtiff-devel
|
||||
|
||||
- name: Build with versioned binaries
|
||||
run: |
|
||||
cmake -S . -B build \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DSLS_USE_GUI=ON \
|
||||
-DSLS_USE_MOENCH=ON \
|
||||
-DSLS_INSTALL_VERSIONED_BINARIES=ON
|
||||
cmake --build build -j 2
|
||||
|
||||
- name: Build RPMs
|
||||
run: |
|
||||
cpack --config build/CPackConfig.cmake -G RPM \
|
||||
-D 'CPACK_COMPONENTS_ALL=cli;receiver;zmq;gui' -B build/rpms
|
||||
|
||||
- name: Inspect RPMs
|
||||
run: |
|
||||
for rpm in build/rpms/*.rpm; do
|
||||
echo "::group::$rpm"
|
||||
rpm -qpi "$rpm"
|
||||
rpm -qpl "$rpm"
|
||||
rpm -qpR "$rpm"
|
||||
echo "::endgroup::"
|
||||
done
|
||||
|
||||
- name: Install RPMs and check versioned binaries
|
||||
run: |
|
||||
VERSION=$(cat VERSION)
|
||||
dnf -y install build/rpms/*.rpm
|
||||
for component in cli receiver zmq gui; do
|
||||
rpm -q slsdetectorpackage-${VERSION}-${component}
|
||||
done
|
||||
for exe in sls_detector_get sls_detector_put slsReceiver \
|
||||
slsMultiReceiver slsFrameSynchronizer moench03ZmqProcess slsDetectorGui; do
|
||||
test -x /usr/bin/${exe}-${VERSION}
|
||||
test ! -e /usr/bin/${exe}
|
||||
done
|
||||
sls_detector_get-${VERSION} --version
|
||||
slsReceiver-${VERSION} --version
|
||||
|
||||
- name: Upload RPMs to Gitea
|
||||
if: ${{ inputs.deploy }}
|
||||
env:
|
||||
SERVICE: ${{ secrets.SERVICE }}
|
||||
run: |
|
||||
url=https://gitea.psi.ch/api/packages/${{ github.repository_owner }}/rpm/el8
|
||||
upload() {
|
||||
curl --silent --show-error --output /tmp/upload-response \
|
||||
--write-out "%{http_code}" \
|
||||
--user "detectors-gitea:${SERVICE}" \
|
||||
--upload-file "$1" "$url/upload"
|
||||
}
|
||||
for rpm in build/rpms/*.rpm; do
|
||||
echo "Uploading $rpm"
|
||||
code=$(upload "$rpm")
|
||||
if [ "$code" = 409 ]; then
|
||||
echo "Already in the registry, replacing"
|
||||
curl --silent --show-error --fail -X DELETE \
|
||||
--user "detectors-gitea:${SERVICE}" \
|
||||
"$url/package/$(rpm -qp --queryformat '%{NAME}/%{VERSION}-%{RELEASE}/%{ARCH}' "$rpm")"
|
||||
code=$(upload "$rpm")
|
||||
fi
|
||||
if [ "$code" != 201 ]; then
|
||||
echo "Upload failed with HTTP $code"
|
||||
cat /tmp/upload-response
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
@@ -0,0 +1,93 @@
|
||||
name: Build RPMs on RHEL9 docker image
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
deploy:
|
||||
description: "Upload the RPMs to the Gitea package registry"
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: "ubuntu-latest"
|
||||
container:
|
||||
image: gitea.psi.ch/detectors/rhel9-detectors-dev
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
dnf -y install rpm-build qt5-qtbase-devel qt5-qtsvg-devel \
|
||||
libpng-devel zlib-devel expat-devel libtiff-devel
|
||||
|
||||
- name: Build with versioned binaries
|
||||
run: |
|
||||
cmake -S . -B build \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DSLS_USE_GUI=ON \
|
||||
-DSLS_USE_MOENCH=ON \
|
||||
-DSLS_INSTALL_VERSIONED_BINARIES=ON
|
||||
cmake --build build -j 2
|
||||
|
||||
- name: Build RPMs
|
||||
run: |
|
||||
cpack --config build/CPackConfig.cmake -G RPM \
|
||||
-D 'CPACK_COMPONENTS_ALL=cli;receiver;zmq;gui' -B build/rpms
|
||||
|
||||
- name: Inspect RPMs
|
||||
run: |
|
||||
for rpm in build/rpms/*.rpm; do
|
||||
echo "::group::$rpm"
|
||||
rpm -qpi "$rpm"
|
||||
rpm -qpl "$rpm"
|
||||
rpm -qpR "$rpm"
|
||||
echo "::endgroup::"
|
||||
done
|
||||
|
||||
- name: Install RPMs and check versioned binaries
|
||||
run: |
|
||||
VERSION=$(cat VERSION)
|
||||
dnf -y install build/rpms/*.rpm
|
||||
for component in cli receiver zmq gui; do
|
||||
rpm -q slsdetectorpackage-${VERSION}-${component}
|
||||
done
|
||||
for exe in sls_detector_get sls_detector_put slsReceiver \
|
||||
slsMultiReceiver slsFrameSynchronizer moench03ZmqProcess slsDetectorGui; do
|
||||
test -x /usr/bin/${exe}-${VERSION}
|
||||
test ! -e /usr/bin/${exe}
|
||||
done
|
||||
sls_detector_get-${VERSION} --version
|
||||
slsReceiver-${VERSION} --version
|
||||
|
||||
- name: Upload RPMs to Gitea
|
||||
if: ${{ inputs.deploy }}
|
||||
env:
|
||||
SERVICE: ${{ secrets.SERVICE }}
|
||||
run: |
|
||||
url=https://gitea.psi.ch/api/packages/${{ github.repository_owner }}/rpm/el9
|
||||
upload() {
|
||||
curl --silent --show-error --output /tmp/upload-response \
|
||||
--write-out "%{http_code}" \
|
||||
--user "detectors-gitea:${SERVICE}" \
|
||||
--upload-file "$1" "$url/upload"
|
||||
}
|
||||
for rpm in build/rpms/*.rpm; do
|
||||
echo "Uploading $rpm"
|
||||
code=$(upload "$rpm")
|
||||
if [ "$code" = 409 ]; then
|
||||
echo "Already in the registry, replacing"
|
||||
curl --silent --show-error --fail -X DELETE \
|
||||
--user "detectors-gitea:${SERVICE}" \
|
||||
"$url/package/$(rpm -qp --queryformat '%{NAME}/%{VERSION}-%{RELEASE}/%{ARCH}' "$rpm")"
|
||||
code=$(upload "$rpm")
|
||||
fi
|
||||
if [ "$code" != 201 ]; then
|
||||
echo "Upload failed with HTTP $code"
|
||||
cat /tmp/upload-response
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
@@ -0,0 +1,126 @@
|
||||
name: Build and upload Documentation
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
branches:
|
||||
- developer
|
||||
- main
|
||||
push:
|
||||
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@v6
|
||||
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@v1.6.1
|
||||
with:
|
||||
packages: libhdf5-dev doxygen libfmt-dev
|
||||
version: 1.0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.12
|
||||
cache: 'pip'
|
||||
|
||||
- name: Install Python Packages
|
||||
run: pip install sphinx sphinx_rtd_theme breathe pyyaml jinja2 numpy
|
||||
|
||||
|
||||
- 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@v6
|
||||
with:
|
||||
ref: gh-pages
|
||||
path: gh-pages
|
||||
|
||||
|
||||
- name: Copy documentation and Release notes to versioned folder
|
||||
if: github.event_name == 'release' || (github.event_name == 'push')
|
||||
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 == 'push')
|
||||
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 }}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -20,12 +20,12 @@ jobs:
|
||||
os: [ubuntu-latest,]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Build wheels
|
||||
run: pipx run cibuildwheel==2.23.0
|
||||
run: pipx run cibuildwheel==3.2.1
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
|
||||
path: ./wheelhouse/*.whl
|
||||
@@ -34,12 +34,12 @@ jobs:
|
||||
name: Build source distribution
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Build sdist
|
||||
run: pipx run build --sdist
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: cibw-sdist
|
||||
path: dist/*.tar.gz
|
||||
@@ -54,7 +54,7 @@ jobs:
|
||||
# or, alternatively, upload to PyPI on every tag starting with 'v' (remove on: release above to use this)
|
||||
# if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
- uses: actions/download-artifact@v7
|
||||
with:
|
||||
# unpacks all CIBW artifacts into dist/
|
||||
pattern: cibw-*
|
||||
|
||||
@@ -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.)
|
||||
@@ -14,14 +14,14 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Configure and build using cmake
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: 3.12
|
||||
cache: 'pip'
|
||||
- run: pip install pytest numpy
|
||||
|
||||
- uses: awalsh128/cache-apt-pkgs-action@latest
|
||||
- uses: awalsh128/cache-apt-pkgs-action@v1.6.1
|
||||
with:
|
||||
packages: libhdf5-dev qtbase5-dev qt5-qmake libqt5svg5-dev libpng-dev libtiff-dev
|
||||
version: 1.0
|
||||
@@ -45,3 +45,8 @@ jobs:
|
||||
python -m pytest ${{github.workspace}}/python/tests
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
name: Build and deploy slsdetlib
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [ubuntu-latest, ] # macos-12, windows-2019]
|
||||
python-version: ["3.12",]
|
||||
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
# The setup-miniconda action needs this to activate miniconda
|
||||
defaults:
|
||||
run:
|
||||
shell: "bash -l {0}"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Get conda
|
||||
uses: conda-incubator/setup-miniconda@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
channels: conda-forge
|
||||
|
||||
- name: Prepare
|
||||
run: conda install conda-build conda-verify pytest anaconda-client
|
||||
|
||||
- name: Enable upload
|
||||
run: conda config --set anaconda_upload yes
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
CONDA_TOKEN: ${{ secrets.CONDA_TOKEN }}
|
||||
run: conda-build conda-recipes/main-library --user slsdetectorgroup --token ${CONDA_TOKEN} --output-folder build_output
|
||||
|
||||
- name: Upload all Conda to github as artifacts
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: conda-packages
|
||||
path: build_output/** # Uploads all packages
|
||||
@@ -18,10 +18,10 @@ jobs:
|
||||
shell: "bash -l {0}"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Get conda
|
||||
uses: conda-incubator/setup-miniconda@v3.0.4
|
||||
uses: conda-incubator/setup-miniconda@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
channels: conda-forge
|
||||
@@ -33,10 +33,10 @@ jobs:
|
||||
run: conda config --set anaconda_upload no
|
||||
|
||||
- name: Build
|
||||
run: conda build conda-recipes/main-library --output-folder build_output
|
||||
run: conda-build conda-recipes/main-library --output-folder build_output
|
||||
|
||||
- name: Upload all Conda packages
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: conda-packages
|
||||
path: build_output/** # Uploads all packages
|
||||
@@ -18,10 +18,10 @@ jobs:
|
||||
shell: "bash -l {0}"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Get conda
|
||||
uses: conda-incubator/setup-miniconda@v3.0.4
|
||||
uses: conda-incubator/setup-miniconda@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
channels: conda-forge
|
||||
@@ -33,10 +33,10 @@ jobs:
|
||||
run: conda config --set anaconda_upload no
|
||||
|
||||
- name: Build
|
||||
run: conda build conda-recipes/python-client --output-folder build_output
|
||||
run: conda-build conda-recipes/python-client --output-folder build_output
|
||||
|
||||
- name: Upload all Conda packages
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: conda-packages
|
||||
path: build_output/** # Uploads all packages
|
||||
+42
-1
@@ -22,6 +22,7 @@ endif()
|
||||
include(cmake/project_version.cmake)
|
||||
include(cmake/SlsAddFlag.cmake)
|
||||
include(cmake/helpers.cmake)
|
||||
include(cmake/SlsInstallExecutable.cmake)
|
||||
|
||||
|
||||
|
||||
@@ -141,6 +142,7 @@ option(SLS_TUNE_LOCAL "tune to local machine" OFF)
|
||||
option(SLS_DEVEL_HEADERS "install headers for devel" OFF)
|
||||
option(SLS_USE_MOENCH "compile zmq and post processing for Moench" OFF)
|
||||
option(SLS_USE_JUNGFRAU "compile post processing for Jungfrau" OFF)
|
||||
option(SLS_INSTALL_VERSIONED_BINARIES "Add version number to installed executables and RPM package names" OFF)
|
||||
|
||||
#Convenience option to switch off defaults when building Moench binaries only
|
||||
option(SLS_BUILD_ONLY_MOENCH "compile only Moench" OFF)
|
||||
@@ -390,4 +392,43 @@ if(SLS_MASTER_PROJECT)
|
||||
set(CMAKE_INSTALL_DIR "share/cmake/${PROJECT_NAME}")
|
||||
set(PROJECT_LIBRARIES slsSupportShared slsDetectorShared slsReceiverShared)
|
||||
include(cmake/package_config.cmake)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
#Packaging
|
||||
# Generic CPack metadata
|
||||
set(CPACK_PACKAGE_NAME "slsDetectorPackage")
|
||||
set(CPACK_PACKAGE_VENDOR "Paul Scherrer Institut")
|
||||
set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "DAQ software for PSI developed detectors")
|
||||
|
||||
# RPM-specific settings
|
||||
string(TOLOWER "${CPACK_PACKAGE_NAME}" CPACK_RPM_PACKAGE_NAME)
|
||||
if(SLS_INSTALL_VERSIONED_BINARIES)
|
||||
string(APPEND CPACK_RPM_PACKAGE_NAME "-${PROJECT_VERSION}")
|
||||
endif()
|
||||
set(CPACK_GENERATOR "RPM")
|
||||
set(CPACK_RPM_FILE_NAME
|
||||
"${PROJECT_NAME_LOWER}-%{VERSION}-%{RELEASE}.%{ARCH}.rpm")
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "LGPL-3.0")
|
||||
set(CPACK_RPM_PACKAGE_GROUP "Applications/System")
|
||||
set(CPACK_RPM_PACKAGE_RELEASE 1)
|
||||
# Adds %{?dist} to the RPM Release field
|
||||
set(CPACK_RPM_PACKAGE_RELEASE_DIST ON)
|
||||
set(CPACK_RPM_COMPONENT_INSTALL ON)
|
||||
|
||||
|
||||
set(CPACK_RPM_GUI_PACKAGE_REQUIRES
|
||||
"qt5-qtbase, qt5-qtbase-gui"
|
||||
)
|
||||
|
||||
#control which RPMs are generated
|
||||
set(CPACK_COMPONENTS_ALL cli receiver zmq gui)
|
||||
# Keep the project version only once in filenames; RPM expands its metadata.
|
||||
foreach(component IN LISTS CPACK_COMPONENTS_ALL)
|
||||
string(TOUPPER "${component}" component_upper)
|
||||
set(CPACK_RPM_${component_upper}_FILE_NAME
|
||||
"${PROJECT_NAME_LOWER}-${component}-%{VERSION}-%{RELEASE}.%{ARCH}.rpm")
|
||||
endforeach()
|
||||
include(CPack)
|
||||
|
||||
@@ -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
|
||||
|
||||
```
|
||||
|
||||
+225
@@ -0,0 +1,225 @@
|
||||
SLS Detector Package Bug Fix Release 10.0.1 released on 2026-10-07
|
||||
===============================================================
|
||||
|
||||
This document describes the differences between v10.0.1 and v10.0.0
|
||||
|
||||
|
||||
|
||||
CONTENTS
|
||||
--------
|
||||
1 New, Changed or Resolved Features
|
||||
1.1 Compilation
|
||||
1.2 Receiver
|
||||
1.3 Package Distribution
|
||||
2 On-board Detector Server Compatibility
|
||||
3 Firmware Requirements
|
||||
4 Kernel Requirements
|
||||
5 Download, Documentation & Support
|
||||
|
||||
|
||||
|
||||
1 New, Changed or Resolved Features
|
||||
=====================================
|
||||
|
||||
1.1 Compilation Changes
|
||||
========================
|
||||
|
||||
* Added CPack RPM packaging for CLI, receiver, Moench tools, GUI and zmq streaming.
|
||||
* Compiler option SLS_INSTALL_VERSIONED_BINARIES=ON adds the project version to RPM
|
||||
package names and all installed executable names, including the GUI,
|
||||
Jungfrau tools and virtual detector servers, for side-by-side use.
|
||||
|
||||
1.2 Receiver
|
||||
=============
|
||||
|
||||
* fixed race condition in slsReceiver potentially leading to corrupted data e.g. frame duplications, torn frames, header-only frames with missing data - leading to misalignments in file
|
||||
* Data corruption could have happened only if using discard policy `DISCARD_PARTIAL_FRAMES` or `DISCARD_EMPTY_FRAMES`
|
||||
taken at high frame rates and if packet loss occured
|
||||
* bug does not apply for receiver discard policy `NO_DISCARD`
|
||||
|
||||
|
||||
1.3 Package Distribution
|
||||
=========================
|
||||
|
||||
RPM packages for CLI, Receiver, Moench tools and GUI and zmq streaming are provided for the folowing platforms
|
||||
|
||||
* RHEL9/Enterprise Linux 9 - x86_64
|
||||
* RHEL8/Enterprise Linux 8 - x86_64
|
||||
|
||||
The RPM can be downloaded from https://gitea.psi.ch/detectors/-/packages
|
||||
|
||||
2 On-board Detector Server Compatibility
|
||||
==========================================
|
||||
|
||||
No need to update Detector Servers. Software changes are compatible with Detector Server version 10.0.0.
|
||||
|
||||
|
||||
3 Firmware Requirements
|
||||
========================
|
||||
|
||||
No need to update on-board Detector-Server firmware.
|
||||
|
||||
Eiger 02.10.2023 (v32) (updated in 7.0.3)
|
||||
|
||||
Jungfrau 09.02.2025 (v1.6, HW v1.0) (updated in 9.1.0)
|
||||
08.02.2025 (v2.6, HW v2.0) (updated in 9.1.0)
|
||||
|
||||
Mythen3 13.11.2024 (v2.0) (updated in 9.0.0)
|
||||
|
||||
Gotthard2 03.10.2024 (v1.0) (updated in 9.0.0)
|
||||
|
||||
Moench 26.10.2023 (v2.0) (updated in 8.0.2)
|
||||
|
||||
|
||||
Detector Upgrade
|
||||
----------------
|
||||
|
||||
The following can be upgraded remotely:
|
||||
|
||||
Eiger via bit files
|
||||
Jungfrau via command <.pof>
|
||||
Mythen3 via command <.rbf>
|
||||
Gotthard2 via command <.rbf>
|
||||
Moench via command <.pof>
|
||||
|
||||
Except Eiger,
|
||||
upgrade
|
||||
Using command 'programfpga' or
|
||||
|
||||
udpate both on-board detector server and firmware simultaneously
|
||||
Using command 'update'
|
||||
|
||||
|
||||
Instructions available at
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/firmware.html
|
||||
|
||||
|
||||
|
||||
|
||||
4 Kernel Requirements
|
||||
======================
|
||||
|
||||
|
||||
Blackfin
|
||||
--------
|
||||
Latest version: Fri Oct 29 00:00:00 2021
|
||||
|
||||
Older ones will work, but might have issues with programming firmware via
|
||||
the package.
|
||||
|
||||
|
||||
Nios
|
||||
-----
|
||||
Compatible version: Mon May 10 18:00:21 CEST 2021
|
||||
|
||||
|
||||
Kernel Upgrade
|
||||
---------------
|
||||
Eiger via bit files
|
||||
Others via command
|
||||
|
||||
Commands: udpatekernel, kernelversion
|
||||
Instructions available at
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/commandline.html
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/detector.html
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/pydetector.html
|
||||
|
||||
|
||||
|
||||
|
||||
5 Download, Documentation & Support
|
||||
====================================
|
||||
|
||||
Download
|
||||
--------
|
||||
|
||||
The Source Code:
|
||||
https://github.com/slsdetectorgroup/slsDetectorPackage
|
||||
|
||||
RPM Packages:
|
||||
https://gitea.psi.ch/detectors/-/packages
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
Installation:
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/installation.html
|
||||
|
||||
Quick Start Guide:
|
||||
https://slsdetectorgroup.github.io//10.0.1/quick_start_guide.html
|
||||
|
||||
Firmware Upgrade:
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/firmware.html
|
||||
|
||||
Detector Server upgrade:
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/serverupgrade.html
|
||||
|
||||
Detector Simulators:
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/virtualserver.html
|
||||
|
||||
Consuming slsDetectorPackage:
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/consuming.html
|
||||
|
||||
Software Architecture
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/softwarearchitecture.html
|
||||
|
||||
Set up commands in config file
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/configcommands.html
|
||||
|
||||
Image Size and Output Characteristics
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/dataformat.html
|
||||
|
||||
API Examples:
|
||||
https://github.com/slsdetectorgroup/api-examples
|
||||
|
||||
Command Line Documentation:
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/commandline.html
|
||||
|
||||
C++ API Documentation:
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/detector.html
|
||||
|
||||
C++ API Example:
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/examples.html#
|
||||
|
||||
Python API Documentation:
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/pygettingstarted.html
|
||||
|
||||
Python API Example:
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/pyexamples.html
|
||||
|
||||
Receivers (including custom receiver):
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/receivers.html
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/slsreceiver.html
|
||||
|
||||
Detector UDP Header:
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/udpheader.html
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/udpdetspec.html
|
||||
|
||||
Output Data:
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/dataformat.html
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/fileformat.html
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/slsreceiverheaderformat.html
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/masterfileattributes.html
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/binaryfileformat.html
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/hdf5fileformat.html
|
||||
|
||||
slsReceiver Zmq Format:
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/slsreceiver.html#zmq-json-header-format
|
||||
|
||||
TroubleShooting:
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/troubleshooting.html
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/10.0.1/troubleshooting.html#receiver-pc-tuning-options
|
||||
|
||||
Further Documentation:
|
||||
https://www.psi.ch/en/detectors/documentation
|
||||
|
||||
Info on Releases:
|
||||
https://slsdetectorgroup.github.io/slsDetectorPackage/index.html
|
||||
|
||||
|
||||
Support
|
||||
-------
|
||||
|
||||
dhanya.thattil@psi.ch
|
||||
erik.frojdh@psi.ch
|
||||
alice.mazzoleni@psi.ch
|
||||
+10
@@ -1,3 +1,13 @@
|
||||
Unreleased changes
|
||||
==================
|
||||
|
||||
* Added CPack RPM packaging for CLI, receiver, Moench tools and GUI.
|
||||
SLS_INSTALL_VERSIONED_BINARIES=ON adds the project version to RPM
|
||||
package names and all installed executable names, including the GUI,
|
||||
Jungfrau tools and virtual detector servers, for side-by-side use.
|
||||
RPM filenames include the project version only once.
|
||||
|
||||
|
||||
SLS Detector Package Major Release 10.0.0 released on 10.09.2025
|
||||
================================================================
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
# Copyright (C) 2026 Contributors to the SLS Detector Package
|
||||
|
||||
function(sls_install_executable target)
|
||||
cmake_parse_arguments(ARG "" "DESTINATION;COMPONENT;EXPORT" "" ${ARGN})
|
||||
if(NOT ARG_DESTINATION)
|
||||
set(ARG_DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
endif()
|
||||
|
||||
set(install_args DESTINATION "${ARG_DESTINATION}")
|
||||
if(ARG_COMPONENT)
|
||||
list(APPEND install_args COMPONENT "${ARG_COMPONENT}")
|
||||
endif()
|
||||
|
||||
if(SLS_INSTALL_VERSIONED_BINARIES)
|
||||
install(PROGRAMS "$<TARGET_FILE:${target}>"
|
||||
${install_args}
|
||||
RENAME "$<TARGET_FILE_BASE_NAME:${target}>-${PROJECT_VERSION}${CMAKE_EXECUTABLE_SUFFIX}"
|
||||
)
|
||||
else()
|
||||
set(export_args)
|
||||
if(ARG_EXPORT)
|
||||
list(APPEND export_args EXPORT "${ARG_EXPORT}")
|
||||
endif()
|
||||
install(TARGETS ${target}
|
||||
${export_args}
|
||||
RUNTIME ${install_args}
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -70,6 +70,7 @@ set(SPHINX_SOURCE_FILES
|
||||
src/dataformat.rst
|
||||
src/softwarearchitecture.rst
|
||||
src/configcommands.rst
|
||||
src/Versioning.rst
|
||||
)
|
||||
|
||||
foreach(filename ${SPHINX_SOURCE_FILES})
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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}
|
||||
@@ -0,0 +1,4 @@
|
||||
/* override table no-wrap */
|
||||
.wy-table-responsive table td, .wy-table-responsive table th {
|
||||
white-space: normal;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
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.
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.
File diff suppressed because one or more lines are too long
@@ -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);
|
||||
@@ -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.
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.
Vendored
+2
File diff suppressed because one or more lines are too long
@@ -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
@@ -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);
|
||||
});
|
||||
});
|
||||
@@ -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 |
@@ -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 */
|
||||
@@ -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);
|
||||
@@ -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();
|
||||
});
|
||||
@@ -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! — 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> </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> </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> </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> </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> </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> </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> </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> </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> </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> </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> </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> </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> </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> </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> </p></td>
|
||||
<td><p> </p></td>
|
||||
<td><p> </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>© 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>
|
||||
@@ -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! — 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 %} {% 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> </p></td>
|
||||
<td><p> </p></td>
|
||||
<td><p> </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>© 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>
|
||||
@@ -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()
|
||||
@@ -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
|
||||
@@ -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.
|
||||
|
||||
@@ -66,6 +66,8 @@ Welcome to slsDetectorPackage's documentation!
|
||||
container_utils
|
||||
type_traits
|
||||
ToString
|
||||
Versioning
|
||||
Testing
|
||||
|
||||
.. toctree::
|
||||
:caption: Firmware
|
||||
|
||||
@@ -240,6 +240,52 @@ Example cmake options Comment
|
||||
For v7.x.x of slsDetectorPackage and older, refer :ref:`zeromq notes for cmk script option to hint library location. <zeromq for different slsDetectorPackage versions>`
|
||||
|
||||
|
||||
3.2.3. Build RPM packages
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
CPack builds separate RPMs for the command line tools (``cli``), receiver
|
||||
executables (``receiver``), Moench processing tools (``zmq``), and GUI (``gui``).
|
||||
Install ``rpm-build`` and the dependencies for the selected features, and build
|
||||
on the target distribution or a matching container.
|
||||
|
||||
For example, to package the command line tools, receiver and GUI:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr -DSLS_USE_GUI=ON \
|
||||
-DSLS_INSTALL_VERSIONED_BINARIES=ON
|
||||
cmake --build build -j4
|
||||
cpack --config build/CPackConfig.cmake -G RPM \
|
||||
-D 'CPACK_COMPONENTS_ALL=cli;receiver;gui' -B build
|
||||
|
||||
Select only components enabled in the build. Add ``-DSLS_USE_MOENCH=ON`` and
|
||||
the ``zmq`` component to package the Moench tools.
|
||||
|
||||
``SLS_INSTALL_VERSIONED_BINARIES=ON`` includes the project version in the RPM
|
||||
package names, for example ``slsdetectorpackage-10.0.0-cli`` and
|
||||
``slsdetectorpackage-10.0.0-gui``. Installed executables also receive a version
|
||||
suffix, such as ``sls_detector_get-10.0.0`` and ``slsDetectorGui-10.0.0``. This
|
||||
allows RPMs for different project versions to be installed side by side.
|
||||
RPM revisions of the same project version retain the same package names and
|
||||
can be upgraded normally.
|
||||
|
||||
RPM filenames include the version once, for example
|
||||
``slsdetectorpackage-cli-10.0.0-1.fc44.x86_64.rpm``. The package's internal name
|
||||
remains ``slsdetectorpackage-10.0.0-cli`` and its RPM version remains ``10.0.0``.
|
||||
|
||||
The option also applies to Jungfrau processing tools and virtual detector
|
||||
servers installed with ``cmake --install``. These are outside the current RPM
|
||||
component selection. Executables in the build directory keep their original
|
||||
names. With the option set to ``OFF`` (the default), installed executables and
|
||||
RPM package names omit the project version.
|
||||
|
||||
The RPM components contain executables; Python bindings, libraries and headers
|
||||
are not included. A full ``cmake --install`` still installs libraries and
|
||||
headers at their usual paths, so use separate prefixes for full installations
|
||||
of different versions.
|
||||
|
||||
|
||||
3.3. Build on old distributions using conda
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
+2
-1
@@ -17,7 +17,7 @@ dependencies = [
|
||||
|
||||
[tool.cibuildwheel]
|
||||
before-all = "uname -a"
|
||||
build = "cp{311,312,313}-manylinux_x86_64"
|
||||
build = "cp{311,312,313,314}-manylinux_x86_64"
|
||||
|
||||
[tool.scikit-build.build]
|
||||
verbose = true
|
||||
@@ -31,6 +31,7 @@ components = [ "python",]
|
||||
[tool.scikit-build.cmake.define]
|
||||
SLS_USE_RECEIVER = "OFF"
|
||||
SLS_USE_RECEIVER_BINARIES = "OFF"
|
||||
SLS_USE_SERVER = "OFF"
|
||||
SLS_USE_TEXTCLIENT = "OFF"
|
||||
SLS_BUILD_SHARED_LIBRARIES = "OFF"
|
||||
SLS_USE_PYTHON = "ON"
|
||||
|
||||
@@ -95,7 +95,5 @@ foreach(exe ${JUNGFRAU_EXECUTABLES})
|
||||
set_property(TARGET ${exe} PROPERTY INTERPROCEDURAL_OPTIMIZATION True)
|
||||
endif()
|
||||
|
||||
|
||||
sls_install_executable(${exe} DESTINATION bin)
|
||||
endforeach(exe ${JUNGFRAU_EXECUTABLES})
|
||||
|
||||
install(TARGETS ${JUNGFRAU_EXECUTABLES} DESTINATION bin)
|
||||
@@ -85,7 +85,6 @@ foreach(exe ${MOENCH_EXECUTABLES})
|
||||
set_property(TARGET ${exe} PROPERTY INTERPROCEDURAL_OPTIMIZATION True)
|
||||
endif()
|
||||
|
||||
sls_install_executable(${exe} DESTINATION bin COMPONENT zmq)
|
||||
|
||||
endforeach(exe ${MOENCH_EXECUTABLES})
|
||||
|
||||
install(TARGETS ${MOENCH_EXECUTABLES} DESTINATION bin)
|
||||
|
||||
@@ -119,11 +119,4 @@ if((CMAKE_BUILD_TYPE STREQUAL "Release") AND SLS_LTO_AVAILABLE)
|
||||
set_property(TARGET slsDetectorGui PROPERTY INTERPROCEDURAL_OPTIMIZATION True)
|
||||
endif()
|
||||
|
||||
install(TARGETS slsDetectorGui
|
||||
# EXPORT "${TARGETS_EXPORT_NAME}" #do not export gui
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
# PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
|
||||
sls_install_executable(slsDetectorGui COMPONENT gui)
|
||||
|
||||
@@ -44,6 +44,4 @@ set_target_properties(ctbDetectorServer_virtual PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
|
||||
)
|
||||
|
||||
install(TARGETS ctbDetectorServer_virtual
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
sls_install_executable(ctbDetectorServer_virtual)
|
||||
|
||||
@@ -37,9 +37,7 @@ set_target_properties(eigerDetectorServer_virtual PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
|
||||
)
|
||||
|
||||
install(TARGETS eigerDetectorServer_virtual
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
sls_install_executable(eigerDetectorServer_virtual)
|
||||
|
||||
|
||||
configure_file(config_eiger.txt ${CMAKE_BINARY_DIR}/bin/config_eiger.txt COPYONLY)
|
||||
|
||||
@@ -38,9 +38,7 @@ set_target_properties(gotthard2DetectorServer_virtual PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
|
||||
)
|
||||
|
||||
install(TARGETS gotthard2DetectorServer_virtual
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
sls_install_executable(gotthard2DetectorServer_virtual)
|
||||
|
||||
configure_file(config_gotthard2.txt ${CMAKE_BINARY_DIR}/bin/config_gotthard2.txt COPYONLY)
|
||||
configure_file(detid_gotthard2.txt ${CMAKE_BINARY_DIR}/bin/detid_gotthard2.txt COPYONLY)
|
||||
|
||||
@@ -40,9 +40,8 @@ set_target_properties(jungfrauDetectorServer_virtual PROPERTIES
|
||||
#target_compile_options(jungfrauDetectorServer_virtual PRIVATE -m32)
|
||||
#target_link_options(jungfrauDetectorServer_virtual PRIVATE -m32)
|
||||
|
||||
install(TARGETS jungfrauDetectorServer_virtual
|
||||
sls_install_executable(jungfrauDetectorServer_virtual
|
||||
EXPORT "${TARGETS_EXPORT_NAME}"
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
|
||||
configure_file(config_jungfrau.txt ${CMAKE_BINARY_DIR}/bin/config_jungfrau.txt COPYONLY)
|
||||
|
||||
@@ -36,9 +36,8 @@ set_target_properties(moenchDetectorServer_virtual PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
|
||||
)
|
||||
|
||||
install(TARGETS moenchDetectorServer_virtual
|
||||
sls_install_executable(moenchDetectorServer_virtual
|
||||
EXPORT "${TARGETS_EXPORT_NAME}"
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
|
||||
configure_file(detid_moench.txt ${CMAKE_BINARY_DIR}/bin/detid_moench.txt COPYONLY)
|
||||
|
||||
@@ -40,9 +40,7 @@ set_target_properties(mythen3DetectorServer_virtual PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
|
||||
)
|
||||
|
||||
install(TARGETS mythen3DetectorServer_virtual
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
sls_install_executable(mythen3DetectorServer_virtual)
|
||||
|
||||
configure_file(DefaultPattern_mythen3.txt ${CMAKE_BINARY_DIR}/bin/DefaultPattern_mythen3.txt COPYONLY)
|
||||
configure_file(detid_mythen3.txt ${CMAKE_BINARY_DIR}/bin/detid_mythen3.txt COPYONLY)
|
||||
|
||||
@@ -37,9 +37,7 @@ set_target_properties(xilinx_ctbDetectorServer_virtual PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
|
||||
)
|
||||
|
||||
install(TARGETS xilinx_ctbDetectorServer_virtual
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
sls_install_executable(xilinx_ctbDetectorServer_virtual)
|
||||
|
||||
configure_file(chip_config_xilinx.txt ${CMAKE_BINARY_DIR}/bin/chip_config_xilinx.txt COPYONLY)
|
||||
configure_file(reset_chip_xilinx.txt ${CMAKE_BINARY_DIR}/bin/reset_chip_xilinx.txt COPYONLY)
|
||||
|
||||
@@ -110,8 +110,10 @@ if(SLS_USE_TEXTCLIENT)
|
||||
if((CMAKE_BUILD_TYPE STREQUAL "Release") AND SLS_LTO_AVAILABLE)
|
||||
set_property(TARGET ${val1} PROPERTY INTERPROCEDURAL_OPTIMIZATION True)
|
||||
endif()
|
||||
|
||||
sls_install_executable(${val1} DESTINATION bin COMPONENT cli)
|
||||
endforeach()
|
||||
install(TARGETS ${det_bin_names} DESTINATION bin)
|
||||
|
||||
|
||||
|
||||
endif(SLS_USE_TEXTCLIENT)
|
||||
|
||||
@@ -165,13 +165,21 @@ if (SLS_USE_RECEIVER_BINARIES)
|
||||
"$<BUILD_INTERFACE:libzmq-static>"
|
||||
)
|
||||
|
||||
install(TARGETS slsReceiver slsMultiReceiver slsFrameSynchronizer
|
||||
EXPORT "${TARGETS_EXPORT_NAME}"
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sls
|
||||
# Receiver binaries
|
||||
set(SLS_RECEIVER_BINARIES
|
||||
slsReceiver
|
||||
slsMultiReceiver
|
||||
slsFrameSynchronizer
|
||||
)
|
||||
foreach(target IN LISTS SLS_RECEIVER_BINARIES)
|
||||
sls_install_executable(${target}
|
||||
EXPORT "${TARGETS_EXPORT_NAME}"
|
||||
COMPONENT receiver
|
||||
)
|
||||
endforeach()
|
||||
|
||||
|
||||
|
||||
|
||||
endif(SLS_USE_RECEIVER_BINARIES)
|
||||
|
||||
|
||||
@@ -81,7 +81,10 @@ void Fifo::DestroyFifos() {
|
||||
fifoStream = nullptr;
|
||||
}
|
||||
|
||||
void Fifo::FreeAddress(char *&address) { fifoFree->push(address); }
|
||||
void Fifo::FreeAddress(char *&address) {
|
||||
std::lock_guard<std::mutex> lock(fifoFreeMutex);
|
||||
fifoFree->push(address);
|
||||
}
|
||||
|
||||
void Fifo::GetNewAddress(char *&address) {
|
||||
int temp = fifoFree->getDataValue();
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "sls/sls_detector_defs.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
|
||||
namespace sls {
|
||||
|
||||
@@ -52,6 +53,9 @@ class Fifo : private virtual slsDetectorDefs {
|
||||
int fifoDepth;
|
||||
std::atomic<int> status_fifoBound;
|
||||
std::atomic<int> status_fifoFree;
|
||||
/** fifoFree has several producers, CircularFifo allows only one.
|
||||
* Aligned to avoid false sharing with the members above */
|
||||
alignas(128) std::mutex fifoFreeMutex;
|
||||
};
|
||||
|
||||
} // namespace sls
|
||||
|
||||
@@ -138,40 +138,23 @@ TEST_CASE("Parse version and help", "[detector]") {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Parse port and uid", "[detector]") {
|
||||
uid_t uid = getuid();
|
||||
std::string uidStr = std::to_string(uid);
|
||||
uid_t invalidUid = uid + 1000;
|
||||
std::string invalidUidStr = std::to_string(invalidUid);
|
||||
|
||||
TEST_CASE("Parse port", "[detector]") {
|
||||
for (auto app : {AppType::SingleReceiver, AppType::MultiReceiver,
|
||||
AppType::FrameSynchronizer}) {
|
||||
CommandLineOptions s(app);
|
||||
REQUIRE_THROWS(
|
||||
s.parse({"", "-p", "1234", "-u", invalidUidStr})); // invalid uid
|
||||
REQUIRE_THROWS(s.parse({"", "-p", "500"})); // invalid port
|
||||
|
||||
auto opts = s.parse({"", "-p", "1234", "-u", uidStr});
|
||||
std::visit(
|
||||
[&](const auto &o) {
|
||||
REQUIRE(o.port == 1234);
|
||||
REQUIRE(o.userid == uid);
|
||||
},
|
||||
opts);
|
||||
REQUIRE_THROWS(s.parse({"", "-p", "500"})); // invalid port
|
||||
|
||||
auto opts = s.parse({"", "-p", "1234"});
|
||||
std::visit([&](const auto &o) { REQUIRE(o.port == 1234); }, opts);
|
||||
|
||||
opts = s.parse({"", "-p", "5678"});
|
||||
std::visit(
|
||||
[](const auto &o) {
|
||||
REQUIRE(o.port == 5678);
|
||||
REQUIRE(o.userid == static_cast<uid_t>(-1)); // default
|
||||
},
|
||||
opts);
|
||||
std::visit([](const auto &o) { REQUIRE(o.port == 5678); }, opts);
|
||||
|
||||
opts = s.parse({});
|
||||
std::visit(
|
||||
[](const auto &o) {
|
||||
REQUIRE(o.port == 1954); // default
|
||||
REQUIRE(o.userid == static_cast<uid_t>(-1)); // default
|
||||
REQUIRE(o.port == 1954); // default
|
||||
},
|
||||
opts);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user