Skip to content

Commit

Permalink
Merge pull request #8 from beardymcjohnface/dev
Browse files Browse the repository at this point in the history
DEV: Can now double-handle --profile
  • Loading branch information
beardymcjohnface authored Oct 17, 2023
2 parents 0d08a6c + 98079c7 commit 1de2c93
Show file tree
Hide file tree
Showing 12 changed files with 174 additions and 58 deletions.
69 changes: 69 additions & 0 deletions .github/workflows/codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python

name: Codecov

on:
push:
branches: [ "main" ]
paths:
- '.github/**'
- 'build/**'
- 'tests/**'
- '{{cookiecutter.project_slug}}/**'
pull_request:
branches: [ "main" ]
paths:
- '.github/**'
- 'build/**'
- 'tests/**'
- '{{cookiecutter.project_slug}}/**'

permissions:
contents: read

jobs:
tests:
name: "Codecov using python ${{ matrix.python-version }} on ${{ matrix.os }}"
runs-on: ${{ matrix.os }}

defaults:
run:
shell: bash -el {0}

strategy:
matrix:
os: [ubuntu-latest]
python-version: ["3.10"]

steps:
- uses: "actions/checkout@v3"
with:
fetch-depth: 0

# Setup env
- uses: conda-incubator/setup-miniconda@v2
with:
activate-environment: snaketool
environment-file: build/environment.yaml
python-version: ${{ matrix.python-version }}
auto-activate-base: false

- name: "Setup Snaketool on ${{ matrix.os }} for Python ${{ matrix.python-version }}"
run: |
cookiecutter --no-input ./
cd my_snaketool/
python -m pip install --upgrade pip
pip install .
- name: "Generate coverage report on ${{ matrix.os }} for Python ${{ matrix.python-version }}"
run: |
pip install pytest pytest-cov
pytest --cov=./ --cov-report=xml --cov-append
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: coverage.xml
fail_ci_if_error: true
9 changes: 1 addition & 8 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ permissions:

jobs:
tests:
name: "Python ${{ matrix.python-version }}"
name: "Python ${{ matrix.python-version }} on ${{ matrix.os }}"
runs-on: ${{ matrix.os }}

defaults:
Expand Down Expand Up @@ -60,10 +60,3 @@ jobs:
run: |
pip install pytest pytest-cov
pytest --cov=./ --cov-report=xml --cov-append
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: coverage.xml
fail_ci_if_error: true
5 changes: 3 additions & 2 deletions tests/test_snaketool.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@ def test_snaketool_cli(tmp_dir):
exec_command("my_snaketool -h")
exec_command("my_snaketool run -h")
exec_command("my_snaketool config -h")
exec_command("my_snaketool --version")


def test_snaketool_commands(tmp_dir):
"""test Snaketool"""
exec_command("my_snaketool run --input yeet")
exec_command("my_snaketool run --input yeet --no-use-conda ")
exec_command("my_snaketool config")
exec_command("my_snaketool citation")
exec_command("my_snaketool citation")
2 changes: 1 addition & 1 deletion {{cookiecutter.project_slug}}/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def get_data_files():
data_files=get_data_files(),
py_modules=["{{cookiecutter.project_slug}}"],
install_requires=[
"snaketool-utils>=0.0.2",
"snaketool-utils>=0.0.4",
"snakemake{{cookiecutter.snakemake_version}}",
"pyyaml{{cookiecutter.pyyaml_version}}",
"Click{{cookiecutter.click_version}}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ def common_options(func):
click.option(
"--threads", help="Number of threads to use", default=1, show_default=True
),
click.option(
"--profile",
default=None,
help="Snakemake profile to use",
show_default=False,
),
click.option(
"--use-conda/--no-use-conda",
default=True,
Expand All @@ -76,7 +82,6 @@ def common_options(func):
"--snake-default",
multiple=True,
default=[
"--rerun-incomplete",
"--printshellcmds",
"--nolock",
"--show-failed-logs",
Expand All @@ -90,6 +95,11 @@ def common_options(func):
callback=default_to_output,
hidden=True,
),
click.option(
"--system-config",
default=snake_base(os.path.join("config", "config.yaml")),
hidden=True,
),
click.argument("snake_args", nargs=-1),
]
for option in reversed(options):
Expand Down Expand Up @@ -137,31 +147,29 @@ def cli():
)
@click.option("--input", "_input", help="Input file/directory", type=str, required=True)
@common_options
def run(_input, output, log, **kwargs):
def run(**kwargs):
"""Run {{cookiecutter.project_name}}"""
# Config to add or update in configfile
merge_config = {
"input": _input,
"output": output,
"log": log
"{{cookiecutter.project_slug}}": {
"args": kwargs
}
}

# run!
run_snakemake(
# Full path to Snakefile
snakefile_path=snake_base(os.path.join("workflow", "Snakefile")),
system_config=snake_base(os.path.join("config", "config.yaml")),
merge_config=merge_config,
log=log,
**kwargs
)


@click.command()
@common_options
def config(configfile, **kwargs):
def config(configfile, system_config, **kwargs):
"""Copy the system default config file"""
copy_config(configfile, system_config=snake_base(os.path.join("config", "config.yaml")))
copy_config(configfile, system_config=system_config)


@click.command()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# Snakemake config
input:
output: '{{cookiecutter.project_slug}}.out/'
log: '{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}.log'
# Namespaced config file example
{{cookiecutter.project_slug}}:
args: # Command line args will be (over)written here at runtime
input:
output:
# Add customisable config here
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{{cookiecutter.project_slug}}:
# Config you don't want users to change
Original file line number Diff line number Diff line change
@@ -1,49 +1,24 @@
import glob

# Update default config with runtime config
configfile: os.path.join(workflow.basedir, "../", "config", "config.yaml")
configfile: os.path.join(workflow.basedir, "../", "config", "system_config.yaml")
config.update(config["{{cookiecutter.project_slug}}"]) # convenience if using namespaced config

configfile: os.path.join(workflow.basedir, '../', 'config', 'config.yaml')


# Concatenate Snakemake's own log file with the master log file
def copy_log_file():
files = glob.glob(os.path.join(".snakemake", "log", "*.snakemake.log"))
if not files:
return None
current_log = max(files, key=os.path.getmtime)
shell("cat " + current_log + " >> " + config['log'])

onsuccess:
copy_log_file()

onerror:
copy_log_file()


# Target file
outTouch = os.path.join(config['output'], config['input'])


# Mark target rules
target_rules = []
def targetRule(fn):
assert fn.__name__.startswith('__')
target_rules.append(fn.__name__[2:])
return fn
# Rules files
include: os.path.join(workflow.basedir, "rules", "preflight.smk")
include: os.path.join(workflow.basedir, "rules", "example.smk")


# Target rules
@targetRule
rule all:
input:
outTouch
targets


@targetRule
rule print_targets:
run:
print("\nTop level rules are: \n", file=sys.stderr)
print("* " + "\n* ".join(target_rules) + "\n\n", file=sys.stderr)


rule yeet:
output:
touch(outTouch)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name: python
channels:
- defaults
dependencies:
- python>=3.9
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
rule example:
output:
os.path.join(dirs["results"], "example.done")
conda:
os.path.join(dirs["envs"], "example.yaml")
benchmark:
os.path.join(dirs["bench"], "example.txt")
log:
os.path.join(dirs["logs"], "example.err")
script:
os.path.join(dirs["scripts"], "example.py")
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@

# Directories
dirs = {
"logs": os.path.join(config["args"]["output"], "logs"),
"bench": os.path.join(config["args"]["output"], "bench"),
"results": os.path.join(config["args"]["output"], "results"),
"envs": os.path.join(workflow.basedir, "envs"),
"scripts": os.path.join(workflow.basedir, "scripts")
}


# Targets
targets = [
os.path.join(dirs["results"], "example.done")
]


# Misc
target_rules = []


def targetRule(fn):
"""Mark rules as target rules for rule print_targets"""
assert fn.__name__.startswith("__")
target_rules.append(fn.__name__[2:])
return fn


def copy_log_file():
"""Concatenate Snakemake log to output log file"""
import glob

files = glob.glob(os.path.join(".snakemake", "log", "*.snakemake.log"))
if files:
current_log = max(files, key=os.path.getmtime)
shell("cat " + current_log + " >> " + config["args"]["log"])


onsuccess:
copy_log_file()

onerror:
copy_log_file()
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

def main(**kwargs):
open(kwargs["output"], "w").close()


if __name__ == "__main__":
main(output=snakemake.output[0],)

0 comments on commit 1de2c93

Please sign in to comment.