Repository: databio/pypiper (language: python)

Issue:
Initial logging message about a stage is a bit odd
`isinstance(stage, Stage)` --> `print("Running stage: {}".format(stage)` yields something like "Running stage: Stage: ..."
Cleaner initial stage run message
Fixes #197 


Discussion / hints:

Fix patch:
diff --git a/docs/changelog.md b/docs/changelog.md
index 81a0729..472efbe 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -1,5 +1,11 @@
 # Changelog
 
+## [0.13.3a2] -- 2023-11-xx
+### Changed
+- minor refactor for pipestat 0.6.0 release
+- drop python 2.7
+- updated requirements
+
 ## [0.13.3a1] -- 2023-10-04
 ### Fixed
 - refactor for pipestat 0.6.0a1
diff --git a/pypiper/_version.py b/pypiper/_version.py
index 78a3de9..7c16d15 100644
--- a/pypiper/_version.py
+++ b/pypiper/_version.py
@@ -1,1 +1,1 @@
-__version__ = "0.13.3a1"
+__version__ = "0.13.3a2"
diff --git a/pypiper/manager.py b/pypiper/manager.py
index 65adad4..660ed85 100644
--- a/pypiper/manager.py
+++ b/pypiper/manager.py
@@ -329,8 +329,7 @@ def __init__(
         signal.signal(signal.SIGTERM, self._signal_term_handler)
 
         # pipestat setup
-        self.pipestat_sample_name = pipestat_sample_name or DEFAULT_SAMPLE_NAME
-        # getattr(self, "sample_name", DEFAULT_SAMPLE_NAME)
+        self.pipestat_record_identifier = pipestat_sample_name or DEFAULT_SAMPLE_NAME
 
         # don't force default pipestat_results_file value unless
         # pipestat config not provided
@@ -344,7 +343,7 @@ def _get_arg(args_dict, arg_name):
             return None if arg_name not in args_dict else args_dict[arg_name]
 
         self._pipestat_manager = PipestatManager(
-            record_identifier=self.pipestat_sample_name
+            record_identifier=self.pipestat_record_identifier
             or _get_arg(args_dict, "pipestat_sample_name")
             or DEFAULT_SAMPLE_NAME,
             pipeline_name=self.name,
@@ -437,7 +436,7 @@ def _completed(self):
         :return bool: Whether the managed pipeline is in a completed state.
         """
         return (
-            self.pipestat.get_status(self._pipestat_manager.sample_name)
+            self.pipestat.get_status(self._pipestat_manager.record_identifier)
             == COMPLETE_FLAG
         )
 
@@ -448,7 +447,10 @@ def _failed(self):
 
         :return bool: Whether the managed pipeline is in a failed state.
         """
-        return self.pipestat.get_status(self._pipestat_manager.sample_name) == FAIL_FLAG
+        return (
+            self.pipestat.get_status(self._pipestat_manager.record_identifier)
+            == FAIL_FLAG
+        )
 
     @property
     def halted(self):
@@ -457,7 +459,8 @@ def halted(self):
         :return bool: Whether the managed pipeline is in a paused/halted state.
         """
         return (
-            self.pipestat.get_status(self._pipestat_manager.sample_name) == PAUSE_FLAG
+            self.pipestat.get_status(self._pipestat_manager.record_identifier)
+            == PAUSE_FLAG
         )
 
     @property
@@ -720,11 +723,11 @@ def start_pipeline(self, args=None, multi=False):
         results = self._pipestat_manager.__str__().split("\n")
         for i in results:
             self.info("* " + i)
-        self.info("* Sample name: " + self.pipestat_sample_name + "\n")
+        self.info("* Sample name: " + self.pipestat_record_identifier + "\n")
         self.info("\n----------------------------------------\n")
         self.status = "running"
         self.pipestat.set_status(
-            record_identifier=self._pipestat_manager.sample_name,
+            record_identifier=self._pipestat_manager.record_identifier,
             status_identifier="running",
         )
 
@@ -771,7 +774,7 @@ def _set_status_flag(self, status):
         prev_status = self.status
         self.status = status
         self.pipestat.set_status(
-            record_identifier=self._pipestat_manager.sample_name,
+            record_identifier=self._pipestat_manager.record_identifier,
             status_identifier=status,
         )
         self.debug("\nChanged status from {} to {}.".format(prev_status, self.status))
@@ -788,8 +791,8 @@ def _flag_file_path(self, status=None):
         """
 
         flag_file_name = "{}_{}_{}".format(
-            self._pipestat_manager["_pipeline_name"],
-            self.pipestat_sample_name,
+            self._pipestat_manager.pipeline_name,
+            self.pipestat_record_identifier,
             flag_name(status or self.status),
         )
         return pipeline_filepath(self, filename=flag_file_name)
@@ -1421,7 +1424,7 @@ def _wait_for_lock(self, lock_file):
                 )
                 # self._set_status_flag(WAIT_FLAG)
                 self.pipestat.set_status(
-                    record_identifier=self._pipestat_manager.sample_name,
+                    record_identifier=self._pipestat_manager.record_identifier,
                     status_identifier="waiting",
                 )
                 first_message_flag = True
@@ -1445,7 +1448,7 @@ def _wait_for_lock(self, lock_file):
             self.timestamp("File unlocked.")
             # self._set_status_flag(RUN_FLAG)
             self.pipestat.set_status(
-                record_identifier=self._pipestat_manager.sample_name,
+                record_identifier=self._pipestat_manager.record_identifier,
                 status_identifier="running",
             )
 
@@ -1604,7 +1607,7 @@ def report_result(self, key, value, nolog=False, result_formatter=None):
 
         reported_result = self.pipestat.report(
             values={key: value},
-            record_identifier=self.pipestat_sample_name,
+            record_identifier=self.pipestat_record_identifier,
             result_formatter=rf,
         )
 
@@ -1686,7 +1689,9 @@ def report_object(
         val = {key: message_raw.replace("\t", " ")}
 
         reported_result = self.pipestat.report(
-            values=val, record_identifier=self.pipestat_sample_name, result_formatter=rf
+            values=val,
+            record_identifier=self.pipestat_record_identifier,
+            result_formatter=rf,
         )
         if not nolog:
             for r in reported_result:
@@ -1853,10 +1858,12 @@ def _refresh_stats(self):
             _, data = read_yaml_data(path=self.pipeline_stats_file, what="stats_file")
             print(data)
             pipeline_key = list(
-                data[self.pipestat["_pipeline_name"]][self.pipestat["_pipeline_type"]]
+                data[self._pipestat_manager.pipeline_name][
+                    self.pipestat["_pipeline_type"]
+                ]
             )[0]
             if self.name == pipeline_key:
-                for key, value in data[self.pipestat["_pipeline_name"]][
+                for key, value in data[self._pipestat_manager.pipeline_name][
                     self.pipestat["_pipeline_type"]
                 ][pipeline_key].items():
                     self.stats_dict[key] = value.strip()
@@ -1991,12 +1998,12 @@ def complete(self):
         """Stop a completely finished pipeline."""
         self.stop_pipeline(status=COMPLETE_FLAG)
 
-    def fail_pipeline(self, exc, dynamic_recover=False):
+    def fail_pipeline(self, exc: Exception, dynamic_recover: bool = False):
         """
         If the pipeline does not complete, this function will stop the pipeline gracefully.
         It sets the status flag to failed and skips the normal success completion procedure.
 
-        :param Exception e: Exception to raise.
+        :param Exception exc: Exception to raise.
         :param bool dynamic_recover: Whether to recover e.g. for job termination.
         """
         # Take care of any active running subprocess
@@ -2026,9 +2033,8 @@ def fail_pipeline(self, exc, dynamic_recover=False):
             total_time = datetime.timedelta(seconds=self.time_elapsed(self.starttime))
             self.info("Total time: " + str(total_time))
             self.info("Failure reason: " + str(exc))
-            # self._set_status_flag(FAIL_FLAG)
             self.pipestat.set_status(
-                record_identifier=self._pipestat_manager.sample_name,
+                record_identifier=self._pipestat_manager.record_identifier,
                 status_identifier="failed",
             )
 
@@ -2089,7 +2095,7 @@ def stop_pipeline(self, status=COMPLETE_FLAG):
         """
         # self._set_status_flag(status)
         self.pipestat.set_status(
-            record_identifier=self._pipestat_manager.sample_name,
+            record_identifier=self._pipestat_manager.record_identifier,
             status_identifier=status,
         )
         self._cleanup()
@@ -2460,8 +2466,8 @@ def _cleanup(self, dry_run=False):
                 for fn in glob.glob(self.outfolder + flag_name("*"))
                 if COMPLETE_FLAG not in os.path.basename(fn)
                 and not "{}_{}_{}".format(
-                    self._pipestat_manager["_pipeline_name"],
-                    self.pipestat_sample_name,
+                    self._pipestat_manager.pipeline_name,
+                    self.pipestat_record_identifier,
                     run_flag,
                 )
                 == os.path.basename(fn)
diff --git a/pypiper/pipeline.py b/pypiper/pipeline.py
index 88c6173..95d31f2 100644
--- a/pypiper/pipeline.py
+++ b/pypiper/pipeline.py
@@ -330,7 +330,7 @@ def run(self, start_point=None, stop_before=None, stop_after=None):
             # between results from different stages.
             skip_mode = False
 
-            print("Running stage: {}".format(stage))
+            print(f"Running stage: {getattr(stage, 'name', str(stage))}")
 
             stage.run()
             self.executed.append(stage)
diff --git a/pypiper/utils.py b/pypiper/utils.py
index 3d64071..8973466 100644
--- a/pypiper/utils.py
+++ b/pypiper/utils.py
@@ -1113,6 +1113,8 @@ def _add_args(parser, args, required):
 def result_formatter_markdown(pipeline_name, record_identifier, res_id, value) -> str:
     """
     Returns Markdown formatted value as string
+
+    # Pipeline_name and record_identifier should be kept because pipestat needs it
     """
 
     message_markdown = "\n> `{key}`\t{value}\t_RES_".format(key=res_id, value=value)
diff --git a/requirements/requirements-pypiper.txt b/requirements/requirements-pypiper.txt
index 04e6661..dd3bca5 100644
--- a/requirements/requirements-pypiper.txt
+++ b/requirements/requirements-pypiper.txt
@@ -1,7 +1,6 @@
-attmap>=0.12.5
 logmuse>=0.2.4
 psutil
 pandas
 ubiquerg>=0.4.5
 yacman
-pipestat>=0.6.0a1
+pipestat>=0.6.0a5
diff --git a/setup.py b/setup.py
index d485071..06a9d08 100644
--- a/setup.py
+++ b/setup.py
@@ -56,7 +56,10 @@ def read_reqs_file(reqs_name):
     classifiers=[
         "Development Status :: 4 - Beta",
         "License :: OSI Approved :: BSD License",
-        "Programming Language :: Python :: 2.7",
+        "Programming Language :: Python :: 3.8",
+        "Programming Language :: Python :: 3.9",
+        "Programming Language :: Python :: 3.10",
+        "Programming Language :: Python :: 3.11",
         "Topic :: Scientific/Engineering :: Bio-Informatics",
     ],
     author="Nathan Sheffield, Johanna Klughammer, Andre Rendeiro",


Test patch:
diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml
index 6bf573b..cc3d35d 100644
--- a/.github/workflows/run-pytest.yml
+++ b/.github/workflows/run-pytest.yml
@@ -11,7 +11,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     strategy:
       matrix:
-        python-version: ["3.7", "3.8", "3.9", "3.10"]
+        python-version: ["3.8", "3.10"]
         os: [ubuntu-latest]
 
     steps: