Skip to content

add python distribution build workflow #217

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
92 changes: 92 additions & 0 deletions .github/workflows/pypackage_build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
name: Build and publish python package

on:
push:
tags:
- "*"

# Define permissions needed for the workflow GITHUB_TOKEN
permissions:
contents: read # Allow checkout
packages: write # Allow publishing to GitHub Packages


jobs:
build:
strategy:
matrix:
operating-system: [ macos-latest, ubuntu-latest, windows-latest ]
python-version: [ "3.10", "3.11", "3.12", "3.13" ]

name: Build Python Package (${{ matrix.operating-system }}, Python ${{ matrix.python-version }})
runs-on: ${{ matrix.operating-system }}

steps:
- name: Checkout Code
uses: actions/checkout@v4
with:
ref: ${{ github.ref }}

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install Hatch
run: pip install hatch

- name: Build distributions
run: hatch build # Uses pyproject.toml to build sdist and wheel into dist/

- name: Upload distributions artifact
uses: actions/upload-artifact@v4 # Action to save artifacts between jobs
with:
name: como-distribution-package-${{ matrix.operating-system }}-${{ matrix.python-version }} # Name for the artifact
path: dist/ # Path to the directory to upload

publish:
strategy:
matrix:
python-version: [ "3.10", "3.11", "3.12", "3.13" ]
operating-system: [ macos-latest, windows-latest, ubuntu-latest ]

name: Publish to GitHub Packages
runs-on: ubuntu-latest
needs: build # Depends on the build job succeeding

# IMPORTANT: Only run the publish job when a tag starting with 'v' is pushed
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')


permissions: # Explicit permissions needed for this job
packages: write # Required to write to GitHub Packages registry
contents: read # Needed if accessing repo content (e.g., for download artifact)

steps:
- name: Download distributions artifact
uses: actions/download-artifact@v4 # Action to retrieve artifacts from previous job.
with:
name: como-distribution-package-${{ matrix.operating-system }}-${{ matrix.python-version }}
path: dist/

- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install Twine
run: pip install twine

- name: Publish package to GitHub Packages
env:
# Use __token__ as username and the automatically generated GITHUB_TOKEN as password
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "Uploading to GitHub Packages for repository: ${{ github.repository }}"
# Construct the repository URL dynamically using the repository owner
TWINE_REPOSITORY_URL="https://pypi.pkg.github.com/${{ github.repository_owner }}"
python -m twine upload --verbose --repository-url ${TWINE_REPOSITORY_URL} dist/*



4 changes: 2 additions & 2 deletions main/como/create_context_specific_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ def _gene_rule_logical(gpr_expression: str, level: int = 0) -> str:
inner_string = inner_string.replace("[", "")
inner_string = inner_string.replace("]", "")

expression_out = f"{gpr_expression[:loc_l]}{inner_string}{gpr_expression[loc_r + 1:]}"
expression_out = f"{gpr_expression[:loc_l]}{inner_string}{gpr_expression[loc_r + 1 :]}"
expression_out = _gene_rule_logical(expression_out, level + 1)

return expression_out
Expand Down Expand Up @@ -384,7 +384,7 @@ def _map_expression_to_reaction(
continue
for gid in gene_ids:
if gid in gene_expressions.index:
rep_val = f' {gene_expressions.at[gid, "active"]} '
rep_val = f" {gene_expressions.at[gid, 'active']} "
else:
rep_val = f" {unknown_val!s} "
gene_reaction_rule = f" {gene_reaction_rule} " # pad white space to prevent gene matches inside floats
Expand Down
3 changes: 1 addition & 2 deletions main/como/rnaseq.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from functools import partial
from multiprocessing.pool import Pool
from pathlib import Path
from typing import Callable, NamedTuple

Check failure on line 13 in main/como/rnaseq.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (UP035)

main/como/rnaseq.py:13:1: UP035 Import from `collections.abc` instead: `Callable`

import numpy as np
import numpy.typing as npt
Expand Down Expand Up @@ -418,13 +418,12 @@
cores = multiprocessing.cpu_count() - 2
logger.debug(f"Processing {total:,} samples through zFPKM transform using {cores} cores")
logger.debug(
f"Will update every {update_per_step:,} steps as this is approximately "
f"{update_every_percent:.1%} of {total:,}"
f"Will update every {update_per_step:,} steps as this is approximately {update_every_percent:.1%} of {total:,}"
)

with Pool(processes=cores) as pool:
kernel = KernelDensity(kernel="gaussian", bandwidth=bandwidth)
chunksize = int(math.ceil(len(fpkm_df.columns) / (4 * cores)))

Check failure on line 426 in main/como/rnaseq.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (RUF046)

main/como/rnaseq.py:426:21: RUF046 Value being cast to `int` is already an integer
partial_func = partial(_zfpkm_calculation, kernel=kernel, peak_parameters=peak_parameters)
chunk_time = time.time()
start_time = time.time()
Expand Down Expand Up @@ -606,13 +605,13 @@
top_genes: npt.NDArray[bool] = genefilter(boolean_expression, top_func)

# Only keep `entrez_gene_ids` that pass `min_genes`
metric.entrez_gene_ids = [gene for gene, keep in zip(entrez_ids, min_genes) if keep]

Check failure on line 608 in main/como/rnaseq.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (B905)

main/como/rnaseq.py:608:58: B905 `zip()` without an explicit `strict=` parameter
metric.gene_sizes = [gene for gene, keep in zip(gene_size, min_genes) if keep]

Check failure on line 609 in main/como/rnaseq.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (B905)

main/como/rnaseq.py:609:53: B905 `zip()` without an explicit `strict=` parameter
metric.count_matrix = metric.count_matrix.iloc[min_genes, :]
metric.normalization_matrix = metrics[sample].normalization_matrix.iloc[min_genes, :]

keep_top_genes = [gene for gene, keep in zip(entrez_ids, top_genes) if keep]

Check failure on line 613 in main/como/rnaseq.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (B905)

main/como/rnaseq.py:613:50: B905 `zip()` without an explicit `strict=` parameter
metric.high_confidence_entrez_gene_ids = [gene for gene, keep in zip(entrez_ids, keep_top_genes) if keep]

Check failure on line 614 in main/como/rnaseq.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (B905)

main/como/rnaseq.py:614:74: B905 `zip()` without an explicit `strict=` parameter

metrics = calculate_z_score(metrics)

Expand Down
5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ dependencies = [
"loguru>=0.7.2",
"pandas>=1.3.5",
"plotly>=5.24.1",
"scanpy>=1.9.8",
"scanpy>=1.11.1",
"scipy>=1.7.3",
"scikit-learn>=1.5.2",
"setuptools<60.0",
"statsmodels>=0.14",
"openpyxl>=3.1.5",
"aiofiles>=24.1.0",
"aioftp>=0.23.1",
Expand Down Expand Up @@ -49,4 +50,4 @@ packages = ["main/como"]
allow-direct-references = true

[tool.pytest.ini_options]
pythonpath = [ "main/src" ]
pythonpath = [ "main/src" ]
Loading