Initial commit from pymetrius template

This commit is contained in:
Michael Panchenko
2025-03-23 23:33:19 +01:00
commit e93169bc8d
40 changed files with 4241 additions and 0 deletions
+16
View File
@@ -0,0 +1,16 @@
{
"name": "serena Project",
"dockerFile": "../Dockerfile",
"workspaceFolder": "/workspaces/serena",
"settings": {
"terminal.integrated.shell.linux": "/bin/bash",
"python.pythonPath": "/usr/local/bin/python",
},
"extensions": [
"ms-python.python",
"ms-toolsai.jupyter",
"ms-python.vscode-pylance"
],
"forwardPorts": [],
"remoteUser": "root",
}
+9
View File
@@ -0,0 +1,9 @@
data
logs
log
test/log
docs/jupyter_execute
docs/.jupyter_cache
docs/_build
coverage.xml
docker_build_and_run.sh
+44
View File
@@ -0,0 +1,44 @@
# Common step definitions to be included by other workflows
# This way we can centralize the package manager-specific steps
# Poetry setup steps
poetry-setup:
- name: Install poetry
uses: abatilo/actions-poetry@v2
- name: Setup a local virtual environment (if no poetry.toml file)
run: |
poetry config virtualenvs.create true --local
poetry config virtualenvs.in-project true --local
- uses: actions/cache@v3
name: Define a cache for the virtual environment based on the dependencies lock file
with:
path: ./.venv
key: venv-${{ hashFiles('poetry.lock') }}
- name: Install the project dependencies
run: |
poetry install --with dev
# UV setup steps
uv-setup:
- name: Install uv
run: pip install uv
- uses: actions/cache@v3
name: Cache dependencies
with:
path: ~/.cache/uv
key: uv-${{ hashFiles('pyproject.toml') }}
- name: Install dependencies
run: |
uv venv
uv pip install -e ".[dev]"
# Pixi setup steps
pixi-setup:
- name: Install pixi
uses: prefix-dev/setup-pixi@v0.4.1
with:
pixi-version: v0.7.0
- name: Install dependencies
run: pixi install
+51
View File
@@ -0,0 +1,51 @@
name: Linting, Types and Docs Check
on: [push, pull_request]
jobs:
check:
runs-on: ubuntu-latest
permissions:
id-token: write
pages: write
actions: write
contents: read
steps:
- name: Cancel previous run
uses: styfle/cancel-workflow-action@0.11.0
with:
access_token: ${{ github.token }}
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: 3.11
# use uv package manager
- name: Install uv
run: pip install uv
- uses: actions/cache@v3
name: Cache dependencies
with:
path: ~/.cache/uv
key: uv-${{ hashFiles('pyproject.toml') }}
- name: Install dependencies
run: |
uv venv
uv pip install -e ".[dev]"
- name: Lint
run: uv run poe lint
- name: Types
run: uv run poe type-check
- name: Docs
run: uv run poe doc-build
- name: Upload artifact
uses: actions/upload-pages-artifact@v2
with:
path: "docs/_build"
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
+27
View File
@@ -0,0 +1,27 @@
name: Upload Python Package
on:
release:
types: [created]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: 3.11
- name: Install build and twine
run: pip install build twine
- name: Build and publish
env:
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
run: |
if [ -z "${PYPI_TOKEN}" ]; then echo "Set the PYPI_TOKEN variable in your repository secrets"; exit 1; fi
python -m build
python -m twine upload dist/* --username __token__ --password $PYPI_TOKEN
+40
View File
@@ -0,0 +1,40 @@
name: Tests on Ubuntu
on: [push, pull_request]
jobs:
cpu:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, 'ci skip')"
strategy:
matrix:
python-version: ["3.11"]
steps:
- name: Cancel previous run
uses: styfle/cancel-workflow-action@0.11.0
with:
access_token: ${{ github.token }}
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: "${{ matrix.python-version }}"
# Include the appropriate package manager steps based on the selection
- name: Setup and install dependencies with UV
uses: ./.github/workflows/common_steps.yml
with:
steps: uv-setup
- name: Test with pytest
run: uv run poe test
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.CODECOV }}
file: ./coverage.xml
flags: unittests
name: codecov-umbrella
fail_ci_if_error: false
+39
View File
@@ -0,0 +1,39 @@
name: Tests on Windows and MacOS
on: [push, pull_request]
jobs:
cpu-extra:
runs-on: ${{ matrix.os }}
if: "!contains(github.event.head_commit.message, 'ci skip')"
strategy:
matrix:
os: [macos-latest, windows-latest]
python-version: [3.11]
steps:
- name: Cancel previous run
uses: styfle/cancel-workflow-action@0.11.0
with:
access_token: ${{ github.token }}
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
# use uv package manager
- name: Install uv
run: pip install uv
- uses: actions/cache@v3
name: Cache dependencies
with:
path: ~/.cache/uv
key: uv-${{ hashFiles('pyproject.toml') }}
- name: Install dependencies
run: |
uv venv
uv pip install -e ".[dev]"
- name: Test with pytest
run: uv run poe test-subset
+137
View File
@@ -0,0 +1,137 @@
#
.idea
temp
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# reports
pylint.html
.pylint.d
+52
View File
@@ -0,0 +1,52 @@
default_install_hook_types: [commit-msg, pre-commit]
default_stages: [commit, manual]
fail_fast: false
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: check-added-large-files
- repo: local
hooks:
- id: ruff
name: ruff
entry: poetry run ruff
require_serial: true
language: system
types: [python]
- id: ruff-nb
name: ruff-nb
entry: poetry run nbqa ruff .
require_serial: true
language: system
pass_filenames: false
types: [python]
- id: black
name: black
entry: poetry run black
require_serial: true
language: system
types: [python]
- id: poetry-check
name: poetry check
entry: poetry check
language: system
files: pyproject.toml
pass_filenames: false
- id: poetry-lock-check
name: poetry lock check
entry: poetry check
args: [--lock]
language: system
pass_filenames: false
- id: mypy
name: mypy
entry: poetry run mypy src
# filenames should not be passed as they would collide with the config in pyproject.toml
pass_filenames: false
files: '^src(/[^/]*)*/[^/]*\.py$'
language: system
- id: mypy-nb
name: mypy-nb
entry: poetry run nbqa mypy
language: system
+10
View File
@@ -0,0 +1,10 @@
# Changelog
## 0.1.0 - Initial Release
### Features:
### Development:
- Initial setup by pymetrius
+39
View File
@@ -0,0 +1,39 @@
# Use the official Python image for the base image.
FROM python:3.11-slim
# Set environment variables to make Python print directly to the terminal and avoid .pyc files.
ENV PYTHONUNBUFFERED 1
ENV PYTHONDONTWRITEBYTECODE 1
# Install system dependencies required for package manager and build tools.
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
build-essential \
git \
&& rm -rf /var/lib/apt/lists/*
# Install pipx.
RUN python3 -m pip install --no-cache-dir pipx \
&& pipx ensurepath
# Add local bin to the path
ENV PATH="${PATH}:/root/.local/bin"
# Install the latest version of uv
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
# Set the working directory
WORKDIR /workspaces/serena
# Copy the pyproject.toml file into the image.
COPY pyproject.toml /workspaces/serena/
# Create virtual environment and install dependencies
RUN uv venv
RUN uv pip install -e ".[dev]"
ENV PATH="/workspaces/serena/.venv/bin:${PATH}"
# Entrypoint to ensure environment is activated
ENTRYPOINT ["/bin/bash", "-c", "source .venv/bin/activate && $0 $@"]
+53
View File
@@ -0,0 +1,53 @@
# serena
Welcome to the serena library!
## Getting Started
You can have a local uv or docker-interpeter based setup. The repository is also
configured to seamlessly working within a GitHub Codespace. See the instructions
for the various setup scenarios below.
Independently of how the setup was done, the virtual environment can be activated with
`source .venv/bin/activate` (after creating it with uv) and the various tasks like formatting, testing, and documentation building
can be executed using `poe`. For example, `poe format` will format the code, including the
notebooks. Just run `poe` to see the available commands.
### Python (uv) setup
You can install the dependencies with
```shell
uv venv
uv pip install -e ".[dev]"
source .venv/bin/activate
```
### Docker setup
Build the docker image with
```shell
docker build -t serena .
```
and run it with the repository mounted as a volume:
```shell
docker run -it --rm -v "$(pwd)":/workspace serena
```
You can also just run `bash docker_build_and_run.sh`, which will do both things
for you.
Note: for the WSL subsystem on Windows you might need to adjust the path for the
volume.
### Codespaces
The fastest way to get started is to use a GitHub Codespace. Just click on the
button in the repository's main page.
## Contributing
Please open new issues for bugs, feature requests and extensions. See more details about the structure and
workflow in the [contributing page](docs/04_contributing/04_contributing.rst).
+5
View File
@@ -0,0 +1,5 @@
#!/usr/bin/bash
docker build -t serena .
docker run -it --rm -v "$(pwd)":/workspace serena
+5
View File
@@ -0,0 +1,5 @@
/03_api/*
jupyter_execute
_toc.yml
.jupyter_cache
conf.py
+11
View File
@@ -0,0 +1,11 @@
Example
=======
This is a placeholder for the example.
Citation example
----------------
It contains an example of citation :cite:`TURING.1950`.
.. bibliography:: /refs.bib
:style: unsrtalpha
:filter: docname in docnames
+2
View File
@@ -0,0 +1,2 @@
Tutorials
=========
+4
View File
@@ -0,0 +1,4 @@
# Notebook Tutorials
Here is a collection of executable tutorials for serena.
You can run them directly in colab, or download them and run them locally.
+128
View File
@@ -0,0 +1,128 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# The role of notebooks\n",
"\n",
"Notebooks are great for illustrations and examples that at the same time serve as integration tests.\n",
"In this library template, notebooks will be executed with pytest (thus on every\n",
"commit in your CI/CD pipeline). The results of the executions will be saved to the docs directory and converted to\n",
"static websites through nbconvert. The static websites are then added to the documentation under the\n",
"_Guides and Tutorials_ section. These websites will be deployed to Github pages on push to develop."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Before running the notebook\n",
"\n",
"Install the library and its dependencies with, if you haven't done so already\n",
"```\n",
"poetry install\n",
"```\n",
"from the root directory. You can also execute this command directly in the notebook but will need to reload the\n",
"kernel afterwards"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"# Here an illustration of your library\n",
"from serena.sample_package.sample_module import hello_stranger\n",
"\n",
"hello_stranger()"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"## Interactive Documentation\n",
"\n",
"Note that since notebooks are rendered to html+javascript, you can embed interactive components like maps, videos and\n",
"widgets into your documentation, as long as the interaction does not require re-execution of cells.\n",
"Below an example of an interactive map created with plotly {cite}`PlotlyMaps`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"# slightly adjusted example from https://plotly.com/python/mapbox-layers/\n",
"import pandas as pd\n",
"import plotly.express as px\n",
"\n",
"us_cities = pd.read_csv(\n",
" \"https://raw.githubusercontent.com/plotly/datasets/master/us-cities-top-1k.csv\",\n",
")\n",
"\n",
"fig = px.scatter_mapbox(\n",
" us_cities,\n",
" lat=\"lat\",\n",
" lon=\"lon\",\n",
" hover_name=\"City\",\n",
" hover_data=[\"State\", \"Population\"],\n",
" color_discrete_sequence=[\"fuchsia\"],\n",
" zoom=3,\n",
" height=300,\n",
")\n",
"\n",
"fig.update_layout(mapbox_style=\"open-street-map\", margin={\"r\": 0, \"t\": 0, \"l\": 0, \"b\": 0})\n",
"fig.show()"
]
},
{
"cell_type": "markdown",
"source": [
"```{bibliography}\n",
":style: unsrtalpha\n",
":filter: docname in docnames\n",
"```"
],
"metadata": {
"collapsed": false
}
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
+91
View File
@@ -0,0 +1,91 @@
Contributing to serena
=============================================
Install Develop Version
-----------------------
serena is built and managed by `poetry <https://python-poetry.org/>`_. For example,
to install all relevant requirements in editable mode you can simply call
.. code-block:: bash
$ poetry install --with dev
PEP8 Code Style Check and Formatting
----------------------------------------
Please set up pre-commit by running
.. code-block:: bash
$ pre-commit install
in the main directory. This should make sure that your contribution is properly
formatted before every commit.
The code is inspected and formatted by `black` and `ruff`. They are executed as
pre-commit hooks. In addition, `poe the poet` tasks are configured.
Simply run `poe` to see the available tasks.
E.g, to format and check the linting manually you can run:
.. code-block:: bash
$ poe format
$ poe lint
Type Check
----------
We use `mypy <https://github.com/python/mypy/>`_ to check the type annotations. To check, in the main directory, run:
.. code-block:: bash
$ poe type-check
Test Locally
------------
This command will run automatic tests in the main directory
.. code-block:: bash
$ poe test
Documentation
-------------
Documentations are written under the ``docs/`` directory as ReStructuredText (``.rst``) files. ``index.rst`` is the main page. A Tutorial on ReStructuredText can be found `here <https://pythonhosted.org/an_example_pypi_project/sphinx.html>`_.
API References are automatically generated by `Sphinx <http://www.sphinx-doc.org/en/stable/>`_ according to the outlines under ``docs/api/`` and should be modified when any code changes.
To compile documentation into webpage, run
.. code-block:: bash
$ poe doc-build
The generated webpage is in ``docs/_build`` and can be viewed with browser (http://0.0.0.0:8000/).
Documentation Generation Test
-----------------------------
We have the following three documentation tests:
1. pydocstyle (as part of ruff): test all docstrings;
2. doc8 (as part of ruff): test ReStructuredText format;
3. sphinx spelling and test: test if there is any error/warning when generating front-end html documentation.
To check, in the main directory, run:
.. code-block:: bash
$ poe lint
$ poe doc-build
+147
View File
@@ -0,0 +1,147 @@
# Book settings
# Learn more at https://jupyterbook.org/customize/config.html
#######################################################################################
# A default configuration that will be loaded for all jupyter books
# Users are expected to override these values in their own `_config.yml` file.
# This is also the "master list" of all allowed keys and values.
#######################################################################################
# Book settings
title : serena Documentation # The title of the book. Will be placed in the left navbar.
author : serena contributors # The author of the book
copyright : "" # Copyright year to be placed in the footer
logo : "" # A path to the book logo
# Patterns to skip when building the book. Can be glob-style (e.g. "*skip.ipynb")
exclude_patterns : ['**.ipynb_checkpoints', '.DS_Store', 'Thumbs.db', '_build', 'jupyter_execute', '.jupyter_cache', '.pytest_cache', 'docs/autogen_rst.py', 'docs/create_toc.py']
# Auto-exclude files not in the toc
only_build_toc_files : false
#######################################################################################
# Execution settings
execute:
execute_notebooks : cache # Whether to execute notebooks at build time. Must be one of ("auto", "force", "cache", "off")
cache : "" # A path to the jupyter cache that will be used to store execution artifacts. Defaults to `_build/.jupyter_cache/`
exclude_patterns : [] # A list of patterns to *skip* in execution (e.g. a notebook that takes a really long time)
timeout : -1 # The maximum time (in seconds) each notebook cell is allowed to run.
run_in_temp : false # If `True`, then a temporary directory will be created and used as the command working directory (cwd),
# otherwise the notebook's parent directory will be the cwd.
allow_errors : false # If `False`, when a code cell raises an error the execution is stopped, otherwise all cells are always run.
stderr_output : show # One of 'show', 'remove', 'remove-warn', 'warn', 'error', 'severe'
#######################################################################################
# Parse and render settings
parse:
myst_enable_extensions: # default extensions to enable in the myst parser. See https://myst-parser.readthedocs.io/en/latest/using/syntax-optional.html
- amsmath
- colon_fence
# - deflist
- dollarmath
# - html_admonition
# - html_image
- linkify
# - replacements
# - smartquotes
- substitution
- tasklist
myst_url_schemes: [ mailto, http, https ] # URI schemes that will be recognised as external URLs in Markdown links
myst_dmath_double_inline: true # Allow display math ($$) within an inline context
#######################################################################################
# HTML-specific settings
html:
favicon : "" # A path to a favicon image
use_edit_page_button : false # Whether to add an "edit this page" button to pages. If `true`, repository information in repository: must be filled in
use_repository_button : false # Whether to add a link to your repository button
use_issues_button : false # Whether to add an "open an issue" button
use_multitoc_numbering : true # Continuous numbering across parts/chapters
extra_footer : ""
google_analytics_id : "" # A GA id that can be used to track book views.
home_page_in_navbar : true # Whether to include your home page in the left Navigation Bar
baseurl : "https://github.com/oraios/serena"
analytics:
comments:
hypothesis : false
utterances : false
announcement : "" # A banner announcement at the top of the site.
#######################################################################################
# LaTeX-specific settings
latex:
latex_engine : pdflatex # one of 'pdflatex', 'xelatex' (recommended for unicode), 'luatex', 'platex', 'uplatex'
use_jupyterbook_latex : true # use sphinx-jupyterbook-latex for pdf builds as default
targetname : book.tex
# Add a bibtex file so that we can create citations
bibtex_bibfiles:
- refs.bib
#######################################################################################
# Launch button settings
launch_buttons:
notebook_interface : classic # The interface interactive links will activate ["classic", "jupyterlab"]
binderhub_url : "" # The URL of the BinderHub (e.g., https://mybinder.org)
jupyterhub_url : "" # The URL of the JupyterHub (e.g., https://datahub.berkeley.edu)
thebe : false # Add a thebe button to pages (requires the repository to run on Binder)
colab_url : "https://colab.research.google.com"
repository:
url : https://github.com/oraios/serena # The URL to your book's repository
path_to_book : docs # A path to your book's folder, relative to the repository root.
branch : main # Which branch of the repository should be used when creating links
#######################################################################################
# Advanced and power-user settings
sphinx:
extra_extensions :
- sphinx.ext.autodoc
- sphinx.ext.viewcode
- sphinx_toolbox.more_autodoc.sourcelink
- sphinxcontrib.spelling
local_extensions : # A list of local extensions to load by sphinx specified by "name: path" items
recursive_update : false # A boolean indicating whether to overwrite the Sphinx config (true) or recursively update (false)
config : # key-value pairs to directly over-ride the Sphinx configuration
autodoc_typehints_format: "short"
autodoc_member_order: "bysource"
autoclass_content: "both"
autodoc_default_options:
show-inheritance: True
suppress_warnings: ["mystnb.unknown_mime_type"] # needed for plotly rendering
autodoc_show_sourcelink: True
add_module_names: False
github_username: oraios
github_repository: https://github.com/oraios/serena
python_use_unqualified_type_names: True
nb_mime_priority_overrides: [
[ 'html', 'application/vnd.jupyter.widget-view+json', 10 ],
[ 'html', 'application/javascript', 20 ],
[ 'html', 'text/html', 30 ],
[ 'html', 'text/latex', 40 ],
[ 'html', 'image/svg+xml', 50 ],
[ 'html', 'image/png', 60 ],
[ 'html', 'image/jpeg', 70 ],
[ 'html', 'text/markdown', 80 ],
[ 'html', 'text/plain', 90 ],
[ 'spelling', 'application/vnd.jupyter.widget-view+json', 10 ],
[ 'spelling', 'application/javascript', 20 ],
[ 'spelling', 'text/html', 30 ],
[ 'spelling', 'text/latex', 40 ],
[ 'spelling', 'image/svg+xml', 50 ],
[ 'spelling', 'image/png', 60 ],
[ 'spelling', 'image/jpeg', 70 ],
[ 'spelling', 'text/markdown', 80 ],
[ 'spelling', 'text/plain', 90 ],
]
mathjax_path: https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
mathjax3_config:
loader: { load: [ '[tex]/configmacros' ] }
tex:
packages: { '[+]': [ 'configmacros' ] }
macros:
vect: ["{\\mathbf{\\boldsymbol{#1}} }", 1]
E: "{\\mathbb{E}}"
P: "{\\mathbb{P}}"
R: "{\\mathbb{R}}"
abs: ["{\\left| #1 \\right|}", 1]
simpl: ["{\\Delta^{#1} }", 1]
amax: "{\\text{argmax}}"
+138
View File
@@ -0,0 +1,138 @@
body {
font-family: "Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;
}
/* Default header fonts are ugly */
h1, h2, .rst-content .toctree-wrapper p.caption, h3, h4, h5, h6, legend, p.caption {
font-family: "Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;
}
/* Use white for docs background */
.wy-side-nav-search {
background-color: #fff;
}
.wy-nav-content {
max-width: 1200px !important;
}
.wy-nav-content-wrap, .wy-menu li.current > a {
background-color: #fff;
}
.wy-side-nav-search>a img.logo {
width: 80%;
margin-top: 10px;
}
@media screen and (min-width: 1400px) {
.wy-nav-content-wrap {
background-color: #fff;
}
.wy-nav-content {
background-color: #fff;
}
}
/* Fixes for mobile */
.wy-nav-top {
background-color: #fff;
background-repeat: no-repeat;
background-position: center;
padding: 0;
margin: 0.4045em 0.809em;
color: #333;
}
.wy-nav-top > a {
display: none;
}
@media screen and (max-width: 768px) {
.wy-side-nav-search>a img.logo {
height: 60px;
}
}
/* This is needed to ensure that logo above search scales properly */
.wy-side-nav-search a {
display: block;
}
/* This ensures that multiple constructors will remain in separate lines. */
.rst-content dl:not(.docutils) dt {
display: table;
}
/* Use our red for literals (it's very similar to the original color) */
.rst-content tt.literal, .rst-content tt.literal, .rst-content code.literal {
color: #4692BC;
}
.rst-content tt.xref, a .rst-content tt, .rst-content tt.xref,
.rst-content code.xref, a .rst-content tt, a .rst-content code {
color: #404040;
}
/* Change link colors (except for the menu) */
a {
color: #4692BC;
}
a:hover {
color: #4692BC;
}
a:visited {
color: #4692BC;
}
.wy-menu a {
color: #b3b3b3;
}
.wy-menu a:hover {
color: #b3b3b3;
}
/* Default footer text is quite big */
footer {
font-size: 80%;
}
footer .rst-footer-buttons {
font-size: 125%; /* revert footer settings - 1/80% = 125% */
}
footer p {
font-size: 100%;
}
.ethical-rtd {
display: none;
}
.ethical-fixedfooter {
display: none;
}
.ethical-content {
display: none;
}
/* For hidden headers that appear in TOC tree */
/* see http://stackoverflow.com/a/32363545/3343043 */
.rst-content .hidden-section {
display: none;
}
nav .hidden-section {
display: inherit;
}
.wy-side-nav-search>div.version {
color: #000;
}
File diff suppressed because one or more lines are too long
+141
View File
@@ -0,0 +1,141 @@
import logging
import os
import shutil
from pathlib import Path
log = logging.getLogger(os.path.basename(__file__))
def module_template(module_qualname: str):
module_name = module_qualname.split(".")[-1]
title = module_name.replace("_", r"\_")
return f"""{title}
{"=" * len(title)}
.. automodule:: {module_qualname}
:members:
:undoc-members:
"""
def index_template(package_name: str, doc_references: list[str] | None = None, text_prefix=""):
doc_references = doc_references or ""
if doc_references:
doc_references = "\n" + "\n".join(f"* :doc:`{ref}`" for ref in doc_references) + "\n"
dirname = package_name.split(".")[-1]
title = dirname.replace("_", r"\_")
if title == "serena":
title = "serena API Reference"
return f"{title}\n{'=' * len(title)}" + text_prefix + doc_references
def write_to_file(content: str, path: str):
os.makedirs(os.path.dirname(path), exist_ok=True)
with open(path, "w") as f:
f.write(content)
os.chmod(path, 0o666)
_SUBTITLE = (
"\n Here is the autogenerated documentation of the serena API. \n \n "
"The Table of Contents to the left has the same structure as the "
"repository's package code. The links at each page point to the submodules and subpackages. \n\n "
"Enjoy scrolling through! \n"
)
def make_rst(src_root, rst_root, clean=False, overwrite=False, package_prefix=""):
"""Creates/updates documentation in form of rst files for modules and packages.
Does not delete any existing rst files. Thus, rst files for packages or modules that have been removed or renamed
should be deleted by hand.
This method should be executed from the project's top-level directory
:param src_root: path to library base directory, typically "src/<library_name>"
:param clean: whether to completely clean the target directory beforehand, removing any existing .rst files
:param overwrite: whether to overwrite existing rst files. This should be used with caution as it will delete
all manual changes to documentation files
:package_prefix: a prefix to prepend to each module (for the case where the src_root is not the base package),
which, if not empty, should end with a "."
:return:
"""
rst_root = os.path.abspath(rst_root)
if clean and os.path.isdir(rst_root):
shutil.rmtree(rst_root)
base_package_name = package_prefix + os.path.basename(src_root)
# TODO: reduce duplication with same logic for subpackages below
files_in_dir = os.listdir(src_root)
module_names = [f[:-3] for f in files_in_dir if f.endswith(".py") and not f.startswith("_")]
subdir_refs = [f"{f}/index" for f in files_in_dir if os.path.isdir(os.path.join(src_root, f)) and not f.startswith("_")]
package_index_rst_path = os.path.join(
rst_root,
"index.rst",
)
log.info(f"Writing {package_index_rst_path}")
write_to_file(
index_template(
base_package_name,
doc_references=module_names + subdir_refs,
text_prefix=_SUBTITLE,
),
package_index_rst_path,
)
for root, dirnames, filenames in os.walk(src_root):
if os.path.basename(root).startswith("_"):
continue
base_package_relpath = os.path.relpath(root, start=src_root)
base_package_qualname = package_prefix + os.path.relpath(
root,
start=os.path.dirname(src_root),
).replace(os.path.sep, ".")
for dirname in dirnames:
if dirname.startswith("_"):
log.debug(f"Skipping {dirname}")
continue
files_in_dir = os.listdir(os.path.join(root, dirname))
module_names = [f[:-3] for f in files_in_dir if f.endswith(".py") and not f.startswith("_")]
subdir_refs = [f"{f}/index" for f in files_in_dir if os.path.isdir(os.path.join(root, dirname, f)) and not f.startswith("_")]
if not module_names:
log.debug(f"Skipping {dirname} as it does not contain any .py files")
continue
package_qualname = f"{base_package_qualname}.{dirname}"
package_index_rst_path = os.path.join(
rst_root,
base_package_relpath,
dirname,
"index.rst",
)
log.info(f"Writing {package_index_rst_path}")
write_to_file(
index_template(package_qualname, doc_references=module_names + subdir_refs),
package_index_rst_path,
)
for filename in filenames:
base_name, ext = os.path.splitext(filename)
if ext == ".py" and not filename.startswith("_"):
module_qualname = f"{base_package_qualname}.{filename[:-3]}"
module_rst_path = os.path.join(rst_root, base_package_relpath, f"{base_name}.rst")
if os.path.exists(module_rst_path) and not overwrite:
log.debug(f"{module_rst_path} already exists, skipping it")
log.info(f"Writing module documentation to {module_rst_path}")
write_to_file(module_template(module_qualname), module_rst_path)
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
docs_root = Path(__file__).parent
make_rst(
docs_root / ".." / "src" / "serena",
docs_root / "03_api",
clean=True,
)
+10
View File
@@ -0,0 +1,10 @@
{
"cited": {
"01_tutorials/00_example": [
"TURING.1950"
],
"02_notebooks/00_example": [
"PlotlyMaps"
]
}
}
+8
View File
@@ -0,0 +1,8 @@
import os
from pathlib import Path
# This script provides a platform-independent way of making the jupyter-book call (used in pyproject.toml)
toc_file = Path(__file__).parent / "_toc.yml"
cmd = f"jupyter-book toc from-project docs -e .rst -e .md -e .ipynb >{toc_file}"
print(cmd)
os.system(cmd)
+15
View File
@@ -0,0 +1,15 @@
Welcome to serena!
=========================================
Welcome to the serena library.
See the project's repository_ for more information.
.. _repository: https://github.com/oraios/serena
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
+11
View File
@@ -0,0 +1,11 @@
"""Implements a platform-independent way of calling nbstripout (used in pyproject.toml)."""
import glob
import os
from pathlib import Path
if __name__ == "__main__":
docs_dir = Path(__file__).parent
for path in glob.glob(str(docs_dir / "02_notebooks" / "*.ipynb")):
cmd = f"nbstripout {path}"
os.system(cmd)
+21
View File
@@ -0,0 +1,21 @@
@article{TURING.1950,
author = {TURING, A. M.},
year = {1950},
title = {I.---COMPUTING MACHINERY AND INTELLIGENCE},
pages = {433--460},
volume = {LIX},
number = {236},
issn = {0026-4423},
journal = {Mind},
doi = {10.1093/mind/LIX.236.433},
file = {ICOMPUTING MACHINERY AND INTELLIGENCE:Attachments/ICOMPUTING MACHINERY AND INTELLIGENCE.pdf:application/pdf}
}
@misc{PlotlyMaps,
abstract = {Plotly's},
year = {2/16/2024},
title = {Maps},
url = {https://plotly.com/python/maps/},
urldate = {2/28/2024}
}
+21
View File
@@ -0,0 +1,21 @@
serena
serena
Oraios AI
oraios
appliedAI
autogenerated
colab
docstring
docstrings
Github
html
init
javascript
pre
pycharm
pydocstyle
submodules
subpackages
utils
webpage
View File
+254
View File
@@ -0,0 +1,254 @@
[build-system]
build-backend = "hatchling.build"
requires = [
"hatchling"
]
[project]
name = "serena"
version = "0.1.0"
description = ""
authors = [
{name = "Oraios AI", email = "michael.panchenko@oraios-ai.de"}
]
readme = "README.md"
requires-python = ">=3.11, <3.12"
classifiers = [
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3.11"
]
dependencies = [
"pandas>=2.2.1",
"plotly>=5.19.0"
]
[project.license]
text = "MIT"
[project.optional-dependencies]
dev = [
"black[jupyter]>=23.7.0",
"docutils>=0.20.1",
"jinja2",
"jupyter>=1.0.0",
"jupyter-book>=1.0.0",
"mypy>=1.4.1",
"nbqa>=1.7.1",
"nbstripout>=0.6.1",
"poethepoet>=0.20.0",
"pre-commit>=3.3.3",
"pytest>=8.0.2",
"pytest-cov",
"pytest-lazy-fixtures>=1.0.5",
"ruff>=0.0.285",
"sphinx>=7",
"sphinx-book-theme>=1.0.1",
"sphinx-comments>=0.0.3",
"sphinx-copybutton>=0.5.2",
"sphinx-jupyterbook-latex>=1.0.0",
"toml-sort>=0.24.2",
"sphinx-togglebutton>=0.3.2",
"sphinx-toolbox>=3.5.0",
"sphinxcontrib-bibtex",
"sphinxcontrib-spelling>=8.0.0",
]
[project.urls]
Homepage = "https://github.com/oraios/serena"
[tool.black]
line-length = 140
target-version = [
"py311"
]
[tool.doc8]
max-line-length = 1000
[tool.mypy]
allow_redefinition = true
check_untyped_defs = true
disallow_incomplete_defs = true
disallow_untyped_defs = true
ignore_missing_imports = true
no_implicit_optional = true
pretty = true
show_error_codes = true
show_error_context = true
show_traceback = true
strict_equality = true
strict_optional = true
warn_no_return = true
warn_redundant_casts = true
warn_unreachable = true
warn_unused_configs = true
warn_unused_ignores = true
exclude = "^build/|^docs/"
[tool.nbqa.exclude]
ruff = "\\.jupyter_cache|jupyter_execute"
mypy = "\\.jupyter_cache|jupyter_execute"
[tool.poe.env]
PYDEVD_DISABLE_FILE_VALIDATION = "1"
[tool.poe.tasks]
test = "pytest test --cov=serena --cov-report=xml --cov-report=term-missing --durations=0 -v --color=yes"
_black_check = "black --check ."
_ruff_check = "ruff check ."
_ruff_check_nb = "nbqa ruff check docs"
_black_format = "black ."
_ruff_format = "ruff check --fix ."
_ruff_format_nb = "nbqa ruff --fix docs"
lint = [
"_black_check",
"_ruff_check",
"_ruff_check_nb"
]
clean-nbs = "python docs/nbstripout.py"
format = [
"_ruff_format",
"_ruff_format_nb",
"_black_format"
]
_autogen_rst = "python docs/autogen_rst.py"
_sphinx_build = "sphinx-build -W -b html docs docs/_build"
_jb_generate_toc = "python docs/create_toc.py"
_jb_generate_config = "jupyter-book config sphinx docs/"
doc-clean = "rm -rf docs/_build"
doc-generate-files = [
"_autogen_rst",
"_jb_generate_toc",
"_jb_generate_config"
]
doc-spellcheck = "sphinx-build -W -b spelling docs docs/_build"
doc-build = [
"doc-generate-files",
"doc-spellcheck",
"_sphinx_build"
]
_mypy = "mypy src"
_mypy_nb = "nbqa mypy docs"
type-check = [
"_mypy",
"_mypy_nb"
]
[tool.ruff]
target-version = "py311"
line-length = 140
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
line-ending = "auto"
skip-magic-trailing-comma = false
docstring-code-format = true
[tool.ruff.lint]
select = [
"ASYNC",
"B",
"C4",
"C90",
"COM",
"D",
"DTZ",
"E",
"F",
"FLY",
"G",
"I",
"ISC",
"PIE",
"PLC",
"PLE",
"PLW",
"RET",
"RUF",
"RSE",
"SIM",
"TID",
"UP",
"W",
"YTT"
]
ignore = [
"RUF002",
"RUF005",
"SIM118",
"SIM108",
"E501",
"E741",
"B008",
"B011",
"B028",
"D100",
"D101",
"D102",
"D103",
"D104",
"D105",
"D107",
"D200",
"D203",
"D213",
"D401",
"D402",
"DTZ005",
"E402",
"E501",
"E701",
"E731",
"C408",
"E203",
"G004",
"RET505",
"D106",
"D205",
"D212",
"PLW2901",
"B027",
"D404",
"D407",
"D408",
"D409",
"D400",
"D415",
"COM812",
"RET503",
"RET504",
"UP038",
"F403",
"F405",
"C401",
"C901"
]
unfixable = [
"F841",
"F601",
"F602",
"B018"
]
extend-fixable = [
"F401",
"B905",
"W291"
]
[tool.ruff.lint.mccabe]
max-complexity = 20
[tool.ruff.lint.per-file-ignores]
"tests/**" = [
"D103"
]
"docs/**" = [
"D103"
]
"examples/**" = [
"D103"
]
"scripts/**" = [
"D103"
]
+5
View File
@@ -0,0 +1,5 @@
from serena.sample_module import SampleClass
if __name__ == "__main__":
print(SampleClass().sample_method("Oraios AI"))
print("Your new library project serena is waiting for you!")
+1
View File
@@ -0,0 +1 @@
__version__ = "0.1.0-dev1"
+25
View File
@@ -0,0 +1,25 @@
"""Top-level module."""
class SampleClass:
"""Sample docstring. Note that init docstrings should be underneath the class and not the init method itself
(this looks prettier in sphinx). They still will be rendered correctly in pycharm's quick documentation.
:param param: some parameter
"""
def __init__(self, param: str | None = None):
self.hello = "hello "
self.param = param
def sample_method(self, name: str) -> str:
""">>> from serena.sample_module import SampleClass
>>>
>>> greeter = SampleClass()
>>> greeter.sample_method("Oraios AI")
'hello Oraios AI'.
:param name:
:return:
"""
return self.hello + name
@@ -0,0 +1,6 @@
"""Module in a separate package."""
def hello_stranger() -> None:
"""Hello."""
print("Hello from a separate package!")
+11
View File
@@ -0,0 +1,11 @@
import pytest
@pytest.fixture()
def fixture_1():
return 1
@pytest.fixture()
def fixture_2():
return 2
@@ -0,0 +1,17 @@
# Here we demonstrate a convenient pytest plugin called lazy fixture.
# It allows to use fixtures within test parametrization, which is especially useful
# if you want to test the method on different input data. Unfortunately, this forces one to use string
# interfaces for fixture but this is a price one might be willing to pay.
import pytest
from pytest_lazy_fixtures import lf
@pytest.mark.parametrize(
"fixture, result",
[
(lf("fixture_1"), 1),
(lf("fixture_2"), 2),
],
)
def test_demonstrateLazyFixture(fixture, result):
assert fixture == result
+8
View File
@@ -0,0 +1,8 @@
from serena.sample_module import SampleClass
# the suggested naming convention for unit tests is test_method_name_testDescriptionInCamelCase
# this leads to a nicely readable output of pytest
def test_sample_class_attributes_greeterSaysHello():
greeter = SampleClass()
assert greeter.hello == "hello "
Generated
+2634
View File
File diff suppressed because it is too large Load Diff