Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# It will also update the test coverage using coveralls.io
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python

name: Python package
Expand All @@ -12,32 +13,44 @@ on:
jobs:
build:

runs-on: ubuntu-22.04
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
python-version: ["3.11", "3.12", "3.13", "3.14"]

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

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

- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install flake8 pytest
python -m pip install flake8 pytest pytest-cov
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi

- name: Install package
run: |
python -m pip install .

- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --statistics
- name: Test with pytest
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics

- name: Test with pytest and output coverage report
run: |
pytest
pytest --cov=mavehgvs --cov-report=xml:coverage-${{ matrix.python-version }}.xml --cov-report=term

- name: Send coverage to coveralls.io
# only calculate coverage for the Python version being used by MaveDB
if: matrix.python-version == '3.11'
uses: coverallsapp/github-action@v2
with:
file: coverage-${{ matrix.python-version }}.xml
63 changes: 45 additions & 18 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# This workflow will upload a Python Package using Twine when a release is created
# This workflow will upload a Python Package to PyPI when a release is created
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries

# This workflow uses actions that are not certified by GitHub.
Expand All @@ -16,24 +16,51 @@ permissions:
contents: read

jobs:
deploy:
release-build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.x"

- name: Build release distributions
run: |
python -m pip install --upgrade pip
python -m pip install hatch
python -m hatch build

- name: Upload distributions
uses: actions/upload-artifact@v4
with:
name: release-dists
path: dist/

pypi-publish:
runs-on: ubuntu-latest
needs:
- release-build
permissions:
# IMPORTANT: this permission is mandatory for trusted publishing
id-token: write

# Dedicated environments with protections for publishing are strongly recommended.
# For more information, see: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#deployment-protection-rules
environment:
name: pypi
# OPTIONAL: uncomment and update to include your PyPI project URL in the deployment status:
url: https://pypi.org/p/mavehgvs

steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install hatch
- name: Build package
run: hatch build
- name: Publish package
uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
with:
user: __token__
password: ${{ secrets.PYPI_MAVEHGVS }}
- name: Retrieve release distributions
uses: actions/download-artifact@v4
with:
name: release-dists
path: dist/

- name: Publish release distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist/
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
repos:
- repo: https://github.com/psf/black
rev: 23.1.0
rev: 26.5.1
hooks:
- id: black
language_version: python3.11
- repo: https://github.com/pycqa/flake8
rev: 5.0.4
rev: 7.3.0
hooks:
- id: flake8
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
[![Build Status](https://travis-ci.com/VariantEffect/mavehgvs.svg?branch=main)](https://travis-ci.com/VariantEffect/mavehgvs)
[![Coverage Status](https://coveralls.io/repos/github/VariantEffect/mavehgvs/badge.svg?branch=main)](https://coveralls.io/github/VariantEffect/mavehgvs?branch=main)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)

Expand Down
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,7 @@ exclude = [

[tool.setuptools.package-data]
"mavehgvs" = ["py.typed"]

[tool.black]
line-length = 88
target-version = ['py311']
2 changes: 1 addition & 1 deletion src/mavehgvs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from mavehgvs.variant import Variant
from mavehgvs.util import parse_variant_strings

__version__ = "0.7.0"
__version__ = "0.8.0"

__all__ = [
"__version__",
Expand Down
4 changes: 3 additions & 1 deletion src/mavehgvs/patterns/protein.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
"""

pro_equal: str = (
rf"(?P<pro_equal>(?:(?P<position>{aa_pos})?(?P<equal>=))|(?P<equal_sy>\(=\)))"
rf"(?P<pro_equal>(?:(?:(?P<position>{aa_pos})|"
+ rf"(?:(?P<start>{aa_pos})_(?P<end>{aa_pos})))?(?P<equal>=))|"
+ rf"(?P<equal_sy>\(=\)))"
)
"""str: Pattern matching protein equality or synonymous variant.
"""
Expand Down
3 changes: 1 addition & 2 deletions src/mavehgvs/patterns/util.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""Utility functions for working with mavehgvs regex pattern strings.
"""
"""Utility functions for working with mavehgvs regex pattern strings."""

import re
from typing import Sequence, Optional
Expand Down
52 changes: 40 additions & 12 deletions src/mavehgvs/variant.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,19 +396,47 @@ def _variant_dictionary_to_string( # noqa: max-complexity: 25
raise MaveHgvsParseError("variant dictionary missing required keys")

if variant_type == "equal":
expected_keys = ["variant_type", "prefix"]
if prefix == "p":
expected_keys.extend(["position", "target"])
else:
expected_keys.extend(["start_position", "end_position"])
if sorted(vdict.keys()) != sorted(expected_keys):
raise MaveHgvsParseError("variant dictionary contains invalid keys")
if prefix == "p":
variant_string = f"{vdict['target']}{vdict['position']}="
elif vdict["start_position"] == vdict["end_position"]:
variant_string = f"{vdict['start_position']}="
# special case for fully-identical variants
if sorted(vdict.keys()) == ["prefix", "variant_type"]:
variant_string = "="
elif (
sorted(vdict.keys()) == ["prefix", "synonymous", "variant_type"]
and prefix == "p"
):
variant_string = "(=)"
else:
variant_string = f"{vdict['start_position']}_{vdict['end_position']}="
expected_keys = [
"variant_type",
"prefix",
"start_position",
"end_position",
]
if prefix == "p":
expected_keys.extend(["start_target", "end_target"])
if sorted(vdict.keys()) != sorted(expected_keys):
raise MaveHgvsParseError("variant dictionary contains invalid keys")
if vdict["start_position"] == vdict["end_position"]:
if prefix == "p":
if vdict["start_target"] == vdict["end_target"]:
variant_string = (
f"{vdict['start_target']}{vdict['start_position']}="
)
else:
raise MaveHgvsParseError(
"amino acid mismatch at same position"
)
else:
variant_string = f"{vdict['start_position']}="
else:
if prefix == "p":
variant_string = (
f"{vdict['start_target']}{vdict['start_position']}_"
f"{vdict['end_target']}{vdict['end_position']}="
)
else:
variant_string = (
f"{vdict['start_position']}_{vdict['end_position']}="
)
elif variant_type == "sub":
if sorted(vdict.keys()) != sorted(
["variant_type", "prefix", "position", "target", "variant"]
Expand Down
1 change: 1 addition & 0 deletions tests/test_patterns/test_protein.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def setUpClass(cls):
"=",
"(=)",
"Cys22=",
"Gly12_Glu14=",
]

cls.invalid_strings = ["=22", "Arg18(=)", "Cys-22", "=="]
Expand Down
56 changes: 54 additions & 2 deletions tests/test_variant.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ def test_sub(self) -> None:
"c.12=",
"g.88_99=",
"c.43-6_595+12=",
"p.Glu12_Gly14=",
]

for s in variant_strings:
Expand Down Expand Up @@ -229,6 +230,7 @@ def test_creation(self):
invalid_variant_strings = [
"p.[Glu27Trp;=;Ter345Lys]",
"p.[(=);Gly18del;Glu27Trp;Ter345Lys]",
"p.[Gln7_Asn19=;Glu27Trp;Ter345Lys]",
"c.[12T>A;=;78+5_78+10del]",
"c.[1_3=;12T>A;78+5_78+10del]",
"p.[Glu27fs;Arg48Lys]",
Expand Down Expand Up @@ -296,11 +298,46 @@ def test_equal(self):
{
"variant_type": "equal",
"prefix": "p",
"position": "27",
"target": "Glu",
},
"p.=",
),
(
{
"variant_type": "equal",
"prefix": "p",
"synonymous": True,
},
"p.(=)",
),
(
{
"variant_type": "equal",
"prefix": "c",
},
"c.=",
),
(
{
"variant_type": "equal",
"prefix": "p",
"start_position": "27",
"start_target": "Glu",
"end_position": "27",
"end_target": "Glu",
},
"p.Glu27=",
),
(
{
"variant_type": "equal",
"prefix": "p",
"start_position": "12",
"start_target": "Glu",
"end_position": "14",
"end_target": "Gly",
},
"p.Glu12_Gly14=",
),
(
{
"variant_type": "equal",
Expand Down Expand Up @@ -523,6 +560,14 @@ def test_delins(self):
"end_target": "Cys",
"variant": "AlaGly",
},
{
"variant_type": "equal",
"prefix": "p",
"start_position": "27",
"start_target": "Glu",
"end_position": "27",
"end_target": "Asp",
},
]

for d, s in valid_dict_tuples:
Expand Down Expand Up @@ -561,6 +606,13 @@ def test_extra_keys(self):
"variant": "Ser",
"position": "Ala",
},
{
"variant_type": "fs",
"prefix": "p",
"position": 80,
"target": "Cys",
"start_position": 23,
},
]

for d in invalid_dicts:
Expand Down
Loading