Skip to content

Commit

Permalink
add lint, changelog reminder, black and isort
Browse files Browse the repository at this point in the history
  • Loading branch information
dnil committed Dec 5, 2024
1 parent a8baa5e commit 50705f5
Show file tree
Hide file tree
Showing 49 changed files with 539 additions and 447 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/keep_a_changelog.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: "Changelog Reminder"
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled]

jobs:
# Enforces the update of a changelog file on every pull request
changelog:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dangoslen/changelog-enforcer@v3
with:
changeLogPath: 'CHANGELOG.md'
skipLabels: 'Skip-Changelog'
47 changes: 47 additions & 0 deletions .github/workflows/linting_only.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Lint files - no fixing

# This will check linting in local PRs
on: ["push", "pull_request"]

jobs:
build:

name: Lint-only
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.11]

steps:

# Check out Scout code
- name: Check out git repository
uses: actions/checkout@v4

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

- name: Install Python Dependencies
run: |
pip install black flake8 isort
- name: Run linters
uses: wearerequired/lint-action@v2
# Let linters fix problems if they can
with:
github_token: ${{ secrets.github_token }}
auto_fix: false
# Enable linters
black: true
black_args: "--check -l 100"
# stop the build if there are Python syntax errors or undefined names
flake8: true
flake8_args: "chanjo/ --count --select=E9,F63,F7,F82 --show-source --statistics"

- name: Run isort
uses: jamescurtin/isort-action@master
with:
configuration: "--check-only --diff -m 3 --tc --fgw 0 --up -n -l 100"
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [4.7.1] - 2024-06-05
### Fixed
- Added `cryptography` module among the dependencies
- Refactored to allow later python versions than 3.8 (pkg_resources to importlib, os.path and path.py to pathlib, distutils to shutil) [#262](https://github.com/Clinical-Genomics/chanjo/pull/262)
- Updated actions to use python 3.11, add changelog reminder, add linting, format for linters

## [4.7] - 2024-05-22
### Added
Expand Down
17 changes: 9 additions & 8 deletions chanjo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
:licence: MIT, see LICENCE for more details
"""
import logging

try:
from importlib.metadata import version
except ImportError: # Backport support for importlib metadata on Python 3.7
Expand All @@ -23,18 +24,18 @@
/___/
"""

__title__ = 'chanjo'
__summary__ = 'coverage analysis tool for clinical sequencing'
__uri__ = 'http://www.chanjo.co/'
__title__ = "chanjo"
__summary__ = "coverage analysis tool for clinical sequencing"
__uri__ = "http://www.chanjo.co/"

__version__ = version(__title__)
__codename__ = 'Optimistic Otter'
__codename__ = "Optimistic Otter"

__author__ = 'Robin Andeer'
__email__ = '[email protected]'
__author__ = "Robin Andeer"
__email__ = "[email protected]"

__license__ = 'MIT'
__copyright__ = 'Copyright 2016 Robin Andeer'
__license__ = "MIT"
__copyright__ = "Copyright 2016 Robin Andeer"

# the user should dictate what happens when a logging event occurs
logging.getLogger(__name__).addHandler(logging.NullHandler())
26 changes: 15 additions & 11 deletions chanjo/calculate.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@


class CalculateMixin:

"""Methods for calculating various metrics."""

def mean(self, sample_ids=None):
Expand Down Expand Up @@ -39,16 +38,21 @@ def gene_metrics(self, *genes):
def sample_coverage(self, sample_ids: list, genes: list) -> dict:
"""Calculate coverage for samples."""
with self.begin() as session:
query = session.query(
TranscriptStat.sample_id.label('sample_id'),
func.avg(TranscriptStat.mean_coverage).label('mean_coverage'),
func.avg(TranscriptStat.completeness_10).label('mean_completeness'),
).join(
Transcript,
).filter(
Transcript.gene_id.in_(genes),
TranscriptStat.sample_id.in_(sample_ids),
).group_by(TranscriptStat.sample_id)
query = (
session.query(
TranscriptStat.sample_id.label("sample_id"),
func.avg(TranscriptStat.mean_coverage).label("mean_coverage"),
func.avg(TranscriptStat.completeness_10).label("mean_completeness"),
)
.join(
Transcript,
)
.filter(
Transcript.gene_id.in_(genes),
TranscriptStat.sample_id.in_(sample_ids),
)
.group_by(TranscriptStat.sample_id)
)

data = {
result.sample_id: {
Expand Down
6 changes: 3 additions & 3 deletions chanjo/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from .base import root
from .calculate import calculate
from .sex import sex
from .load import link, load
from .sambamba import sambamba
from .db import db_cmd
from .init import init
from .load import link, load
from .sambamba import sambamba
from .sex import sex
23 changes: 13 additions & 10 deletions chanjo/cli/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"""
import logging
import os

try:
from importlib.metadata import entry_points
except ImportError: # Backport support for importlib metadata on Python 3.7
Expand All @@ -15,19 +16,20 @@
import coloredlogs
import yaml

from chanjo import __version__, __title__
from chanjo import __title__, __version__

LOG = logging.getLogger(__name__)

COMMAND_GROUP_KEY = 'chanjo.subcommands.4'
COMMAND_GROUP_KEY = "chanjo.subcommands.4"


class EntryPointsCLI(click.MultiCommand):
"""Add sub-commands dynamically to a CLI via entry points."""

def _iter_commands(self):
"""Iterate over all sub-commands as defined by the entry point."""
# Get all entry points for the specified group
if hasattr(entry_points(), 'select'):
if hasattr(entry_points(), "select"):
# Python >3.10, importlib
eps = entry_points(group=COMMAND_GROUP_KEY)
else:
Expand All @@ -49,16 +51,17 @@ def get_command(self, ctx, name):


@click.group(cls=EntryPointsCLI)
@click.option('-c', '--config', default='./chanjo.yaml',
type=click.Path(), help='path to config file')
@click.option('-d', '--database', help='path/URI of the SQL database')
@click.option('-l', '--log-level', default='INFO')
@click.option('--log-file', type=click.File('a'))
@click.option(
"-c", "--config", default="./chanjo.yaml", type=click.Path(), help="path to config file"
)
@click.option("-d", "--database", help="path/URI of the SQL database")
@click.option("-l", "--log-level", default="INFO")
@click.option("--log-file", type=click.File("a"))
@click.version_option(__version__, prog_name=__title__)
@click.pass_context
def root(context, config, database, log_level, log_file):
"""Clinical sequencing coverage analysis tool."""
logout = log_file or click.get_text_stream('stderr')
logout = log_file or click.get_text_stream("stderr")
coloredlogs.install(level=log_level, stream=logout)
LOG.debug("version %s", __version__)

Expand All @@ -68,7 +71,7 @@ def root(context, config, database, log_level, log_file):
context.obj = yaml.safe_load(conf_handle)
else:
context.obj = {}
context.obj['database'] = (database or context.obj.get('database'))
context.obj["database"] = database or context.obj.get("database")

# Update the context with new defaults from the config file
context.default_map = context.obj
29 changes: 15 additions & 14 deletions chanjo/cli/calculate.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
"""Functions for calculating operations on database"""

import json
import logging

import click

from chanjo.store.api import ChanjoDB
from chanjo.store.constants import STAT_COLUMNS, OMIM_GENE_IDS
from chanjo.store.constants import OMIM_GENE_IDS, STAT_COLUMNS

LOG = logging.getLogger(__name__)

Expand All @@ -23,30 +24,30 @@ def dump_json(data, pretty=False):
@click.pass_context
def calculate(context):
"""Calculate statistics across samples."""
context.obj['db'] = ChanjoDB(uri=context.obj['database'])
context.obj["db"] = ChanjoDB(uri=context.obj["database"])


@calculate.command()
@click.option('-p', '--pretty', is_flag=True)
@click.option('-s', '--sample', multiple=True, help='sample to limit query to')
@click.option("-p", "--pretty", is_flag=True)
@click.option("-s", "--sample", multiple=True, help="sample to limit query to")
@click.pass_context
def mean(context, sample, pretty):
"""Calculate mean statistics."""
query = context.obj['db'].mean(sample_ids=sample)
columns = ['sample_id'] + STAT_COLUMNS
query = context.obj["db"].mean(sample_ids=sample)
columns = ["sample_id"] + STAT_COLUMNS
for result in query:
row = {column: value for column, value in zip(columns, result)}
click.echo(dump_json(row, pretty=pretty))


@calculate.command()
@click.option('-p', '--pretty', is_flag=True, help="Print in pretty format")
@click.option('-s', '--sample', multiple=True, type=str, help="Sample to get coverage for")
@click.option('-o', '--omim', is_flag=True, help="Use genes in the OMIM panel")
@click.option('-f', '--gene-file',
type=click.Path(exists=True),
help="File with row separated gene IDs")
@click.argument('genes', nargs=-1)
@click.option("-p", "--pretty", is_flag=True, help="Print in pretty format")
@click.option("-s", "--sample", multiple=True, type=str, help="Sample to get coverage for")
@click.option("-o", "--omim", is_flag=True, help="Use genes in the OMIM panel")
@click.option(
"-f", "--gene-file", type=click.Path(exists=True), help="File with row separated gene IDs"
)
@click.argument("genes", nargs=-1)
@click.pass_context
def coverage(context, pretty, sample, omim, gene_file, genes):
"""Calculate coverage for sample on specified genes"""
Expand All @@ -55,5 +56,5 @@ def coverage(context, pretty, sample, omim, gene_file, genes):
if gene_file:
with open(gene_file) as file_handle:
genes = file_handle.read().strip().split("\n")
query = context.obj['db'].sample_coverage(sample_ids=sample, genes=list(genes))
query = context.obj["db"].sample_coverage(sample_ids=sample, genes=list(genes))
click.echo(dump_json(query, pretty=pretty))
8 changes: 2 additions & 6 deletions chanjo/cli/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,7 @@ def samples(context, group_id, sample_id, pretty):
indent = None
if pretty:
indent = 4
click.echo(
json.dumps([dict(result) for result in query], default=str, indent=indent)
)
click.echo(json.dumps([dict(result) for result in query], default=str, indent=indent))


@db_cmd.command()
Expand All @@ -75,9 +73,7 @@ def transcripts(context, sample_id, pretty):
indent = None
if pretty:
indent = 4
click.echo(
json.dumps([dict(result) for result in query], default=str, indent=indent)
)
click.echo(json.dumps([dict(result) for result in query], default=str, indent=indent))


@db_cmd.command()
Expand Down
30 changes: 15 additions & 15 deletions chanjo/cli/init.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
# -*- coding: utf-8 -*-
import codecs
from shutil import which
import logging
from pathlib import Path
from shutil import which

import click
from pathlib import Path
import yaml

from chanjo.init.bootstrap import BED_NAME, DB_NAME, pull
from chanjo.init.demo import DEMO_BED_NAME, setup_demo
from chanjo.store.api import ChanjoDB
from chanjo.init.bootstrap import pull, BED_NAME, DB_NAME
from chanjo.init.demo import setup_demo, DEMO_BED_NAME

LOG = logging.getLogger(__name__)


@click.command()
@click.option('-f', '--force', is_flag=True, help='overwrite existing files')
@click.option('-d', '--demo', is_flag=True, help='copy demo files')
@click.option('-a', '--auto', is_flag=True)
@click.argument('root_dir', default='.', required=False)
@click.option("-f", "--force", is_flag=True, help="overwrite existing files")
@click.option("-d", "--demo", is_flag=True, help="copy demo files")
@click.option("-a", "--auto", is_flag=True)
@click.argument("root_dir", default=".", required=False)
@click.pass_context
def init(context, force, demo, auto, root_dir):
"""Bootstrap a new chanjo setup."""
is_bootstrapped = False
root_path = Path(root_dir)

LOG.info("setting up chanjo under: %s", root_path)
db_uri = context.obj.get('database')
db_uri = context.obj.get("database")
db_uri = db_uri or "sqlite:///{}".format(root_path.joinpath(DB_NAME).resolve())

# test setup of sambamba
sambamba_bin = which('sambamba')
sambamba_bin = which("sambamba")
if sambamba_bin is None: # pragma: no cover
LOG.warning("'sambamba' command not found")
else:
Expand All @@ -44,7 +44,7 @@ def init(context, force, demo, auto, root_dir):
chanjo_db = ChanjoDB(db_uri)
chanjo_db.set_up()
is_bootstrapped = True
elif auto or click.confirm('Bootstrap HGNC transcript BED?'):
elif auto or click.confirm("Bootstrap HGNC transcript BED?"):
pull(root_dir, force=force)

LOG.info("configure new chanjo database: %s", db_uri)
Expand All @@ -54,13 +54,13 @@ def init(context, force, demo, auto, root_dir):

# setup config file
root_path.mkdir(parents=True, exist_ok=True)
conf_path = root_path.joinpath('chanjo.yaml')
with open(conf_path, 'w') as conf_handle:
data = {'database': db_uri}
conf_path = root_path.joinpath("chanjo.yaml")
with open(conf_path, "w") as conf_handle:
data = {"database": db_uri}
LOG.info("writing config file: %s", conf_path)
yaml.dump(data, conf_handle, default_flow_style=False)

if is_bootstrapped:
click.echo('Chanjo bootstrap successful! Now run: ')
click.echo("Chanjo bootstrap successful! Now run: ")
bed_path = root_path.joinpath(DEMO_BED_NAME if demo else BED_NAME)
click.echo("chanjo --config {} link {}".format(conf_path, bed_path))
Loading

0 comments on commit 50705f5

Please sign in to comment.