Contributing to Albert Python SDK
Thanks for your interest in contributing to the Albert Python SDK! We aim to make it as easy as possible to get started and see your changes released quickly.
🚀 Quickstart
-
Clone the repository:
-
Run the setup script (installs all dependencies and hooks):
-
Create a new branch for your work:
-
Make your changes, then commit. Pre-commit hooks and linting will run automatically.
- Push your branch and open a Pull Request against
main.
Your contribution could ship in days or weeks -- welcome aboard! 🚀
Dynamic Versioning
The package version is defined in the src/albert/__init__.py file
and read dynamically when building distributions.
Code Style
This project uses ruff for both formatting and linting. Formatting and linting rules are enforced in the CI process.
To check (or fix) your code formatting, you can run the commands,
To check (or fix) your code linting, you can run the commands
For VSCode users, there is also base workspace settings defined in .vscode/settings.json that enable
automatic fomatting and import sorting on-save using the
Ruff for VSCode extension.
Commit Guidelines
We use the Conventional Commits format:
type: one offeat,fix,refactor,chore,docs,test,style,build,ci,perf,revertscope: optional, a module or feature name (e.g.,auth,session)!: optional, indicates a breaking changesummary: short and clear — think “when applied, the SDK will…”
Examples
feat(auth): support token refresh
fix!: remove deprecated param handling
docs: clarify local dev setup
This keeps commit history readable and enables changelog automation.
Documentation
Using Numpy-Style Docstrings
All public methods and classes in this repository should follow the Numpy-style docstring format. Docs are generated from these docstrings with mkdocstrings, so a few formatting rules matter for the site to render correctly. Getting them right up front avoids tedious repo-wide clean-up later.
Example
class CasCollection(BaseCollection):
"""Manage CAS entries in the Albert platform.
!!! example
```python
from albert import Albert
client = Albert()
cas = client.cas.get_by_id(id="CAS1")
cas.number
# '7732-18-5'
```
Parameters
----------
session : AlbertSession
The authenticated Albert session used for API calls.
Methods
-------
get_by_id(id) -> Cas
Get a single CAS by its ID.
create(cas) -> Cas
Create a new CAS.
"""
def get_by_id(self, *, id: str) -> Cas:
"""Get a single CAS by its ID.
!!! example
```python
cas = client.cas.get_by_id(id="CAS1")
cas.number
# '7732-18-5'
```
Parameters
----------
id : str
The CAS ID.
Returns
-------
Cas
The fully populated CAS. See [`Cas`][albert.resources.cas.Cas].
"""
...
Ensure all public members have properly formatted Numpy-style docstrings.
Cross-references: use autorefs, not Sphinx roles
mkdocstrings does not understand Sphinx roles — :class:, :meth:, :attr: render as literal text on the docs site. Link with autorefs syntax instead:
- The display text is the short name in backticks; the target is the fully-qualified dotted path.
- Fully qualify every target, even a sibling method in the same class, e.g.
[`get_all`][albert.collections.cas.CasCollection.get_all]. - The
autorefsplugin (bundled withmkdocstrings) is enabled inmkdocs.yml. A target only resolves if that class/method is rendered on a docs page — if you reference something in an undocumented module, add a page for it (see Adding New Classes) or don't link it.
Examples: use !!! example admonitions, placed before Parameters
Use !!! example admonitions -- they render as a styled purple box. Placement is critical:
Always place !!! example in the description block, before the first numpy section. Every numpy section (Parameters, Attributes, Methods, Returns, Notes, Raises) renders its content as a table. Any markdown placed after the last entry of a section -- including admonitions -- is absorbed into that section and rendered as a stray table row.
Method docstrings -- place before Parameters:
def get_by_id(self, *, id: str) -> Cas:
"""Get a single CAS by its ID.
!!! example
```python
from albert import Albert
client = Albert()
cas = client.cas.get_by_id(id="CAS1")
cas.number
# '7732-18-5'
```
Parameters
----------
id : str
The CAS ID.
Returns
-------
Cas
The fully populated CAS. See [`Cas`][albert.resources.cas.Cas].
"""
Class docstrings (collections and resources alike) -- place before Parameters or Attributes, whichever comes first. Do not place after Methods or Attributes -- those render as tables too.
Do not wrap examples in Examples\n-------- -- it adds a redundant "Examples:" label above the box.
Do not use a bare ```python fence inside an Examples numpy section -- it loses the box styling entirely.
- Instantiate the client zero-arg:
client = Albert(). Show it once in the class-level example and reuseclientafterward. - Async collections use
async with AsyncAlbert() as client:andawait. - Show returned values as
# commentlines.
Wording conventions
Keep wording consistent across the SDK:
- Imperative mood: Get (reads), Create, Update, Delete, Search — not
Retrieve/Fetch/Register/Gets. - Class opener:
Manage <Entity> in the Albert platform.(read-only collections useAccess <Entity> …). __init__:Initialize a/an <CollectionClass>.- Refer to identifiers as "by its ID"; use "fully populated" (not "fully hydrated").
- Describe what from the caller's perspective — never internal details (diffing, patching, HTTP, "returned by the API").
- No em dashes (
—); use commas, colons, or parentheses. - Beta features use the
(🧪 Beta)badge (with a space).
Adding New Classes
To add coverage for a new microservice, you can add a page by doing the following:
-
in the
docs/folder make a new markdown file following the pattern of the others. For example: -
In
mkdocs.ymladd a link to thenavsection (Alphabetically Sorted) following the existing pattern.
Note: a class is only a valid autorefs cross-reference target once it is rendered on a docs page, so add pages for modules you link to. A package directory must contain an
__init__.pyformkdocstringsto collect it (implicit namespace packages are not collectable).
Testing Documentation Locally
Before pushing documentation changes, verify that everything is rendering correctly.
1. Install dependencies (if not already installed)
2. Build and serve the documentation locally
3. Open http://127.0.0.1:8000/ (or specified address) in your browser and navigate through the docs to confirm that
- All references and links are resolving correctly.
- Docstrings are properly formatted.
- No missing or broken sections exist.
Deploying Documentation
The documentation is automatically built and deployed to GitHub Pages when a pull request is merged into main.
How It Works
- A PR is merged into main.
-
CircleCI runs the deploy_docs job, which:
- Builds the latest version of the documentation using mkdocs build --clean.
- Pushes the built docs to the gh-pages branch.
- GitHub Pages automatically serves the latest docs
Manually Triggering a Docs Deployment
If needed, you can manually re-deploy the docs by running:
Creating a Release
- Ensure the version in
src/albert/__init__.pyis updated to the desired release version - Go to the Releases section of the repository
- Click "Draft a new release"
- Create a new tag matching the version in
__init__.py(e.g., if__init__.pyhas__version__ = "0.3.0", use tagv0.3.0) - Click "Generate release notes" and review/edit as needed
- Publish the release
The release will automatically trigger the CircleCI workflow to:
- Build and publish the package to PyPI
- Build and deploy the documentation
Note: Only designated Albert team members have permissions to create releases.