Skip to content
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

Issue 492 refactor pipestat #496

Merged
merged 27 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ba8c3db
first pass at creating pipestat config and associating psms with pifaces
donaldcampbelljr May 22, 2024
1ce86fb
fix bug with pipestat key present but value being None
donaldcampbelljr May 23, 2024
8040e29
use_pipestat = is_pipestat_configured
donaldcampbelljr May 23, 2024
396ea40
ensure a pipestatmanager is created if a config file does already exist
donaldcampbelljr May 23, 2024
970f18b
modify comprehensive tests to have correct paths
donaldcampbelljr May 23, 2024
99c2e24
refactor Checker code
donaldcampbelljr May 23, 2024
f54f85d
refactor Reporter code
donaldcampbelljr May 23, 2024
946b408
refactor Linker and Tabulator
donaldcampbelljr May 23, 2024
9989c9f
refactor Destroyer
donaldcampbelljr May 23, 2024
08e4fa0
attempt refactor for obtaining project level pifaces and associated psms
donaldcampbelljr May 23, 2024
25d5d6a
bump pipestat req to 0.9.2a1
donaldcampbelljr May 24, 2024
e1b3aef
set multi_pipelines to True so that sample and project pipelines can …
donaldcampbelljr May 24, 2024
f63e1ca
Add warning for mismatched pipeline names
donaldcampbelljr May 24, 2024
e95b62a
refactor _set_pipestat_namespace
donaldcampbelljr Jun 3, 2024
2e1d136
remove unused code, finish Destroyer refactor
donaldcampbelljr Jun 3, 2024
55eb51f
refactor func names
donaldcampbelljr Jun 3, 2024
60d807c
remove unnecessary variable duplication
donaldcampbelljr Jun 3, 2024
f476e68
remove commented code
donaldcampbelljr Jun 3, 2024
64c81f1
add "--project" argument back to Looper
donaldcampbelljr Jun 3, 2024
ba7f03e
refactor obtaining results_file_path during pipestat configuration cr…
donaldcampbelljr Jun 3, 2024
19d3130
remove commented code
donaldcampbelljr Jun 3, 2024
5c9ea75
remove print statements, change info to debug
donaldcampbelljr Jun 3, 2024
c1825c1
ensure we are checking for project level pipestat configuration if us…
donaldcampbelljr Jun 3, 2024
5411139
reduce looper verbosity by switching to logger.debug in some places
donaldcampbelljr Jun 3, 2024
d4f576c
bumbp pipestat req to v0.9.2
donaldcampbelljr Jun 3, 2024
4ec9bed
Merge branch 'dev' into dev_492_refactor_pipestat
donaldcampbelljr Jun 3, 2024
affd8d4
add enum for pipeline type #360
donaldcampbelljr Jun 3, 2024
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
23 changes: 13 additions & 10 deletions looper/cli_pydantic.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

from divvy import select_divvy_config

from .const import PipelineLevel
from . import __version__

from .command_models.arguments import ArgumentEnum
Expand Down Expand Up @@ -241,6 +242,14 @@ def run_looper(args: TopLevelParser, parser: ArgumentParser, test_args=None):
selector_flag=subcommand_args.sel_flag,
exclusion_flag=subcommand_args.exc_flag,
) as prj:

# Check at the beginning if user wants to use pipestat and pipestat is configurable
is_pipestat_configured = (
prj._check_if_pipestat_configured(pipeline_type=PipelineLevel.PROJECT.value)
if getattr(args, "project", None)
else prj._check_if_pipestat_configured()
)

if subcommand_name in ["run", "rerun"]:
rerun = subcommand_name == "rerun"
run = Runner(prj)
Expand Down Expand Up @@ -271,32 +280,26 @@ def run_looper(args: TopLevelParser, parser: ArgumentParser, test_args=None):
if subcommand_name == "destroy":
return Destroyer(prj)(subcommand_args)

use_pipestat = (
prj.pipestat_configured_project
if getattr(subcommand_args, "project", None)
else prj.pipestat_configured
)

if subcommand_name == "table":
if use_pipestat:
if is_pipestat_configured:
return Tabulator(prj)(subcommand_args)
else:
raise PipestatConfigurationException("table")

if subcommand_name == "report":
if use_pipestat:
if is_pipestat_configured:
return Reporter(prj)(subcommand_args)
else:
raise PipestatConfigurationException("report")

if subcommand_name == "link":
if use_pipestat:
if is_pipestat_configured:
Linker(prj)(subcommand_args)
else:
raise PipestatConfigurationException("link")

if subcommand_name == "check":
if use_pipestat:
if is_pipestat_configured:
return Checker(prj)(subcommand_args)
else:
raise PipestatConfigurationException("check")
Expand Down
9 changes: 7 additions & 2 deletions looper/command_models/arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,13 +192,13 @@ class ArgumentEnum(enum.Enum):
name="sample_pipeline_interfaces",
alias="-S",
default=(List, []),
description="Paths to looper sample config files",
description="Paths to looper sample pipeline interfaces",
)
PROJECT_PIPELINE_INTERFACES = Argument(
name="project_pipeline_interfaces",
alias="-P",
default=(List, []),
description="Paths to looper project config files",
description="Paths to looper project pipeline interfaces",
)
AMEND = Argument(
name="amend", default=(List, []), description="List of amendments to activate"
Expand Down Expand Up @@ -276,3 +276,8 @@ class ArgumentEnum(enum.Enum):
default=(bool, False),
description="Makes html report portable.",
)
PROJECT_LEVEL = Argument(
name="project",
default=(bool, False),
description="Is this command executed for project-level?",
)
1 change: 1 addition & 0 deletions looper/command_models/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ def create_model(self) -> Type[pydantic.BaseModel]:
ArgumentEnum.PIPESTAT.value,
ArgumentEnum.SETTINGS.value,
ArgumentEnum.AMEND.value,
ArgumentEnum.PROJECT_LEVEL.value,
]

RunParser = Command(
Expand Down
27 changes: 16 additions & 11 deletions looper/conductor.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from .exceptions import JobSubmissionException, SampleFailedException
from .processed_project import populate_sample_paths
from .utils import fetch_sample_flags, jinja_render_template_strictly
from .const import PipelineLevel


_LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -90,6 +91,13 @@ def write_pipestat_config(looper_pipestat_config_path, pipestat_config_dict):
:param dict pipestat_config_dict: the dict containing key value pairs to be written to the pipestat configutation
return bool
"""

if not os.path.exists(os.path.dirname(looper_pipestat_config_path)):
try:
os.makedirs(os.path.dirname(looper_pipestat_config_path))
except FileExistsError:
pass

with open(looper_pipestat_config_path, "w") as f:
yaml.dump(pipestat_config_dict, f)
_LOGGER.debug(
Expand Down Expand Up @@ -266,8 +274,12 @@ def is_project_submittable(self, force=False):

:param bool frorce: whether to force the project submission (ignore status/flags)
"""
psms = {}
if self.prj.pipestat_configured_project:
psm = self.prj.get_pipestat_managers(project_level=True)[self.pl_name]
for piface in self.prj.project_pipeline_interfaces:
if piface.psm.pipeline_type == PipelineLevel.PROJECT.value:
psms[piface.psm.pipeline_name] = piface.psm
psm = psms[self.pl_name]
status = psm.get_status()
if not force and status is not None:
_LOGGER.info(f"> Skipping project. Determined status: {status}")
Expand All @@ -293,12 +305,11 @@ def add_sample(self, sample, rerun=False):
)
)
if self.prj.pipestat_configured:
psms = self.prj.get_pipestat_managers(sample_name=sample.sample_name)
sample_statuses = psms[self.pl_name].get_status(
sample_statuses = self.pl_iface.psm.get_status(
record_identifier=sample.sample_name
)
if sample_statuses == "failed" and rerun is True:
psms[self.pl_name].set_status(
self.pl_iface.psm.set_status(
record_identifier=sample.sample_name, status_identifier="waiting"
)
sample_statuses = "waiting"
Expand Down Expand Up @@ -537,12 +548,7 @@ def _set_pipestat_namespace(
:return yacman.YAMLConfigManager: pipestat namespace
"""
try:
psms = (
self.prj.get_pipestat_managers(sample_name)
if sample_name
else self.prj.get_pipestat_managers(project_level=True)
)
psm = psms[self.pl_iface.pipeline_name]
psm = self.pl_iface.psm
except (PipestatError, AttributeError) as e:
# pipestat section faulty or not found in project.looper or sample
# or project is missing required pipestat attributes
Expand Down Expand Up @@ -630,7 +636,6 @@ def write_script(self, pool, size):
argstring = jinja_render_template_strictly(
template=templ, namespaces=namespaces
)
print(argstring)
except UndefinedError as jinja_exception:
_LOGGER.warning(NOT_SUB_MSG.format(str(jinja_exception)))
except KeyError as e:
Expand Down
8 changes: 8 additions & 0 deletions looper/const.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
""" Shared project constants """

import os
from enum import Enum

__author__ = "Databio lab"
__email__ = "nathan@code.databio.org"
Expand Down Expand Up @@ -268,3 +269,10 @@ def _get_apperance_dict(type, templ=APPEARANCE_BY_FLAG):
"init-piface": "Initialize generic pipeline interface.",
"link": "Create directory of symlinks for reported results.",
}

# Add project/sample enum


class PipelineLevel(Enum):
SAMPLE = "sample"
PROJECT = "project"
Loading
Loading