From 967a0d7cb90c63c7be00b49fd535cf1029f63b5b Mon Sep 17 00:00:00 2001 From: Hocnonsense <48747984+Hocnonsense@users.noreply.github.com> Date: Mon, 8 Jan 2024 17:39:02 +0800 Subject: [PATCH] fix: correctly report lineno (#2584) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Description fix: #2583, #1256 and #2574 ### QC maybe #2583 * [ ] The PR contains a test case for the changes or the changes are already covered by an existing test case. * [ ] The documentation (`docs/`) is updated to reflect the changes or this is not necessary (e.g. if the change does neither modify the language nor the behavior or functionalities of Snakemake). --------- Co-authored-by: Johannes Köster --- snakemake/exceptions.py | 14 ++++++++++---- snakemake/workflow.py | 15 ++++++++++++--- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/snakemake/exceptions.py b/snakemake/exceptions.py index c8e088575..d5cda406f 100644 --- a/snakemake/exceptions.py +++ b/snakemake/exceptions.py @@ -160,6 +160,12 @@ def print_exception(ex, linemaps=None): traceback.print_exception(type(ex), ex, ex.__traceback__) +def update_lineno(ex: SyntaxError, linemaps): + if ex.filename and ex.lineno: + ex.lineno = linemaps[ex.filename][ex.lineno] + return ex + + class SourceFileError(WorkflowError): def __init__(self, msg): super().__init__(f"Error in source file definition: {msg}") @@ -188,18 +194,18 @@ def __init__( snakefile -- the file the exception originates """ super(RuleException, self).__init__(message) - self._include = set() + _include = set() if include: for ex in include: - self._include.add(ex) - self._include.update(ex._include) + _include.add(ex) + _include.update(ex._include) if rule is not None: if lineno is None: lineno = rule.lineno if snakefile is None: snakefile = rule.snakefile - self._include = list(self._include) + self._include = list(_include) self.rule = rule self.lineno = lineno self.filename = snakefile diff --git a/snakemake/workflow.py b/snakemake/workflow.py index e763b3ce8..1b10ec2a2 100644 --- a/snakemake/workflow.py +++ b/snakemake/workflow.py @@ -57,6 +57,7 @@ UnknownRuleException, NoRulesException, WorkflowError, + update_lineno, ) from snakemake.dag import DAG, ChangeType from snakemake.scheduler import JobScheduler @@ -164,7 +165,7 @@ def __post_init__(self): self._linemaps = dict() self.rule_count = 0 self.included = [] - self.included_stack = [] + self.included_stack: list[SourceFile] = [] self._persistence: Optional[Persistence] = None self._dag: Optional[DAG] = None self._onsuccess = lambda log: None @@ -1353,14 +1354,22 @@ def include( if print_compilation: print(code) - if isinstance(snakefile, LocalSourceFile): + snakefile_path_or_uri = snakefile.get_basedir().get_path_or_uri() + if ( + isinstance(snakefile, LocalSourceFile) + and snakefile_path_or_uri not in sys.path + ): # insert the current directory into sys.path # this allows to import modules from the workflow directory sys.path.insert(0, snakefile.get_basedir().get_path_or_uri()) self.linemaps[snakefile.get_path_or_uri()] = linemap - exec(compile(code, snakefile.get_path_or_uri(), "exec"), self.globals) + try: + exec(compile(code, snakefile.get_path_or_uri(), "exec"), self.globals) + except SyntaxError as e: + e = update_lineno(e, self.linemaps) + raise if not overwrite_default_target: self.default_target = default_target