ebi-eva-common-pyutils 0.7.4__tar.gz → 0.8.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/CHANGELOG.md +14 -0
  2. {ebi_eva_common_pyutils-0.7.4/ebi_eva_common_pyutils.egg-info → ebi_eva_common_pyutils-0.8.1}/PKG-INFO +1 -1
  3. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/assembly_utils.py +6 -1
  4. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1/ebi_eva_common_pyutils.egg-info}/PKG-INFO +1 -1
  5. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils.egg-info/SOURCES.txt +1 -3
  6. ebi_eva_common_pyutils-0.8.1/ebi_eva_internal_pyutils/__init__.py +1 -0
  7. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_internal_pyutils/mongodb/__init__.py +0 -2
  8. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_internal_pyutils/mongodb/mongo_database.py +1 -0
  9. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_internal_pyutils/spring_properties.py +5 -5
  10. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/setup.py +1 -1
  11. ebi_eva_common_pyutils-0.7.4/ebi_eva_internal_pyutils/__init__.py +0 -0
  12. ebi_eva_common_pyutils-0.7.4/ebi_eva_internal_pyutils/nextflow/__init__.py +0 -1
  13. ebi_eva_common_pyutils-0.7.4/ebi_eva_internal_pyutils/nextflow/nextflow_pipeline.py +0 -195
  14. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/LICENSE +0 -0
  15. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/MANIFEST.in +0 -0
  16. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/README.md +0 -0
  17. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/__init__.py +0 -0
  18. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/assembly/__init__.py +0 -0
  19. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/assembly/assembly.py +0 -0
  20. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/biosamples_communicators.py +0 -0
  21. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/command_utils.py +0 -0
  22. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/common_utils.py +0 -0
  23. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/config.py +0 -0
  24. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/contig_alias/__init__.py +0 -0
  25. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/contig_alias/contig_alias.py +0 -0
  26. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/ena_utils.py +0 -0
  27. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/file_utils.py +0 -0
  28. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/logger.py +0 -0
  29. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/ncbi_utils.py +0 -0
  30. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/network_utils.py +0 -0
  31. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/reference/__init__.py +0 -0
  32. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/reference/assembly.py +0 -0
  33. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/reference/sequence.py +0 -0
  34. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/spreadsheet/__init__.py +0 -0
  35. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/spreadsheet/metadata_xlsx_utils.py +0 -0
  36. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/taxonomy/__init__.py +0 -0
  37. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/taxonomy/taxonomy.py +0 -0
  38. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/variation/__init__.py +0 -0
  39. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils/variation/contig_utils.py +0 -0
  40. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils.egg-info/dependency_links.txt +0 -0
  41. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils.egg-info/requires.txt +0 -0
  42. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_common_pyutils.egg-info/top_level.txt +0 -0
  43. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_internal_pyutils/archive_directory.py +0 -0
  44. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_internal_pyutils/config_utils.py +0 -0
  45. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_internal_pyutils/metadata_utils.py +0 -0
  46. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_internal_pyutils/mongo_utils.py +0 -0
  47. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/ebi_eva_internal_pyutils/pg_utils.py +0 -0
  48. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/requirements.txt +0 -0
  49. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/setup.cfg +0 -0
  50. {ebi_eva_common_pyutils-0.7.4 → ebi_eva_common_pyutils-0.8.1}/tests/test_common.py +0 -0
@@ -2,6 +2,20 @@
2
2
  Changelog for ebi_eva_common_pyutils
3
3
  ===========================
4
4
 
5
+ ## 0.8.1 (2026-02-04)
6
+ ---------------------
7
+
8
+ - Remove hard-coded accessioning job name from Spring properties generator
9
+ - Set default readPreference to "primary" for accessioning properties
10
+
11
+
12
+ ## 0.8.0 (2025-12-19)
13
+ ---------------------
14
+
15
+ - Remove internal Nextflow classes
16
+ - Handle ENA errors when detecting patch assembly
17
+
18
+
5
19
  ## 0.7.4 (2025-08-07)
6
20
  ---------------------
7
21
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ebi_eva_common_pyutils
3
- Version: 0.7.4
3
+ Version: 0.8.1
4
4
  Summary: EBI EVA - Common Python Utilities
5
5
  Home-page: https://github.com/EBIVariation/eva-common-pyutils
6
6
  License: Apache
@@ -14,6 +14,7 @@
14
14
 
15
15
  import http
16
16
  import requests
17
+ from requests import HTTPError
17
18
 
18
19
  from ebi_eva_common_pyutils.assembly import NCBIAssembly
19
20
  from ebi_eva_common_pyutils.ena_utils import download_xml_from_ena
@@ -33,7 +34,11 @@ def is_patch_assembly(assembly_accession: str) -> bool:
33
34
  Check if a given assembly is a patch assembly
34
35
  Please see: https://www.ncbi.nlm.nih.gov/grc/help/patches/
35
36
  """
36
- xml_root = download_xml_from_ena(f'https://www.ebi.ac.uk/ena/browser/api/xml/{assembly_accession}')
37
+ try:
38
+ xml_root = download_xml_from_ena(f'https://www.ebi.ac.uk/ena/browser/api/xml/{assembly_accession}')
39
+ except HTTPError as e:
40
+ logger.warning(f'Failed to download assembly {assembly_accession} from ENA: {str(e)}')
41
+ return False
37
42
  xml_assembly = xml_root.xpath("//ASSEMBLY_ATTRIBUTE[TAG='count-patches']/VALUE")
38
43
  if len(xml_assembly) == 0:
39
44
  return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ebi_eva_common_pyutils
3
- Version: 0.7.4
3
+ Version: 0.8.1
4
4
  Summary: EBI EVA - Common Python Utilities
5
5
  Home-page: https://github.com/EBIVariation/eva-common-pyutils
6
6
  License: Apache
@@ -5,7 +5,7 @@ README.md
5
5
  requirements.txt
6
6
  setup.cfg
7
7
  setup.py
8
- /tmp/ebi_eva_common_pyutils-v0.7.4-_d3almln/gitclone/ebi_eva_internal_pyutils/archive_directory.py
8
+ /tmp/ebi_eva_common_pyutils-v0.8.1-r1lg01ob/gitclone/ebi_eva_internal_pyutils/archive_directory.py
9
9
  ebi_eva_common_pyutils/__init__.py
10
10
  ebi_eva_common_pyutils/assembly_utils.py
11
11
  ebi_eva_common_pyutils/biosamples_communicators.py
@@ -44,6 +44,4 @@ ebi_eva_internal_pyutils/pg_utils.py
44
44
  ebi_eva_internal_pyutils/spring_properties.py
45
45
  ebi_eva_internal_pyutils/mongodb/__init__.py
46
46
  ebi_eva_internal_pyutils/mongodb/mongo_database.py
47
- ebi_eva_internal_pyutils/nextflow/__init__.py
48
- ebi_eva_internal_pyutils/nextflow/nextflow_pipeline.py
49
47
  tests/test_common.py
@@ -1,3 +1 @@
1
1
  from ebi_eva_internal_pyutils.mongodb.mongo_database import MongoDatabase
2
-
3
-
@@ -101,6 +101,7 @@ class MongoDatabase(AppLogger):
101
101
  self.mongo_handle[self.db_name][collection_name].create_index(index_keys, name=name, **index_info)
102
102
 
103
103
  def enable_sharding(self):
104
+ # From mongodb 6.0 all database have sharding enable by default
104
105
  self.mongo_handle.admin.command({"enableSharding": self.db_name})
105
106
 
106
107
  def shard_collections(self, collections_shard_key_map, collections_to_shard):
@@ -132,16 +132,16 @@ class SpringPropertiesGenerator:
132
132
  merge = {**self._common_accessioning_properties(assembly_accession, read_preference, chunk_size), **props}
133
133
  return merge
134
134
 
135
- def get_accessioning_properties(self, *, target_assembly=None, fasta=None, assembly_report=None,
136
- project_accession=None, aggregation='BASIC', taxonomy_accession=None,
137
- vcf_file='', output_vcf='', chunk_size=100):
135
+ def get_accessioning_properties(self, *, read_preference='primary', job_name=None, target_assembly=None, fasta=None,
136
+ assembly_report=None, project_accession=None, aggregation='BASIC',
137
+ taxonomy_accession=None, vcf_file='', output_vcf='', chunk_size=100):
138
138
  """Properties for accessioning pipeline."""
139
139
  return self._format(
140
140
  self._common_accessioning_clustering_properties(assembly_accession=target_assembly,
141
- read_preference='secondaryPreferred',
141
+ read_preference=read_preference,
142
142
  chunk_size=chunk_size),
143
143
  {
144
- 'spring.batch.job.names': 'CREATE_SUBSNP_ACCESSION_JOB',
144
+ 'spring.batch.job.names': job_name,
145
145
  'parameters.assemblyReportUrl': self._format_str('file:{0}', assembly_report),
146
146
  'parameters.contigNaming': 'NO_REPLACEMENT',
147
147
  'parameters.fasta': fasta,
@@ -11,7 +11,7 @@ setup(
11
11
  name='ebi_eva_common_pyutils',
12
12
  scripts=[os.path.join(os.path.dirname(__file__), 'ebi_eva_internal_pyutils', 'archive_directory.py')],
13
13
  packages=find_packages(),
14
- version='0.7.4',
14
+ version='0.8.1',
15
15
  license='Apache',
16
16
  description='EBI EVA - Common Python Utilities',
17
17
  url='https://github.com/EBIVariation/eva-common-pyutils',
@@ -1 +0,0 @@
1
- from ebi_eva_internal_pyutils.nextflow.nextflow_pipeline import LinearNextFlowPipeline, NextFlowPipeline, NextFlowProcess
@@ -1,195 +0,0 @@
1
- # Copyright 2021 EMBL - European Bioinformatics Institute
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- # Rationale for a Nextflow pipeline abstraction
16
- # ---------------------------------------------
17
- # Dynamic pipeline generation
18
- # Abstraction to represent process dependencies
19
- # Unit testability of individual steps without scattering logic between Python and Nextflow
20
- # Ability to combine pipelines
21
-
22
- import networkx as nx
23
- import os
24
- from typing import List, Dict, Union
25
-
26
- from ebi_eva_common_pyutils.logger import AppLogger
27
- from ebi_eva_common_pyutils.command_utils import run_command_with_output
28
-
29
-
30
- class NextFlowProcess:
31
-
32
- def __init__(self, process_name: str, command_to_run: str, process_directives: Dict[str, str] = None) -> None:
33
- """
34
- Create a Nextflow process
35
- :rtype: None
36
- :param process_name: Name of the process - should be a valid identifier - ex: p1_merge
37
- :type process_name: str
38
- :param command_to_run: Command to be run - ex: bash -c "echo p1"
39
- :type command_to_run: str
40
- :param process_directives: Additional process directives - ex: {"memory": "4GB", "executor": "lsf"}
41
- :type process_directives: dict
42
- """
43
- if not process_name.isidentifier():
44
- raise ValueError(f"{process_name} is not a valid Nextflow process name")
45
- self.process_name = process_name
46
- self.success_flag = f"{self.process_name}_success"
47
- self.command_to_run = command_to_run
48
- self.process_directives = process_directives if process_directives else dict()
49
-
50
-
51
- class NextFlowPipeline(AppLogger):
52
- def __init__(self, process_dependency_map: Dict[NextFlowProcess, List[NextFlowProcess]] = None) -> None:
53
- """
54
- Create a Nextflow pipeline with a process dependency map
55
-
56
- :param process_dependency_map: Map of Nextflow processes and their corresponding dependencies
57
- - ex: {p3 : [p2], p2: [p1]} where p1, p2 and p3 are Nextflow processes that should be executed sequentially
58
- """
59
- # Modeling the dependency map as a DiGraph (Directed graph) is advantageous
60
- # in ordering/combining flows and detecting cycles
61
- self.process_dependency_map = nx.ordered.DiGraph()
62
- if process_dependency_map:
63
- self.add_dependencies(process_dependency_map)
64
-
65
- def add_dependencies(self, process_dependency_map: Dict[NextFlowProcess, List[NextFlowProcess]]):
66
- for process, dependencies in process_dependency_map.items():
67
- if dependencies:
68
- for dependency in dependencies:
69
- self.add_process_dependency(process, dependency)
70
- else:
71
- self.add_process_dependency(process, None)
72
-
73
- def add_process_dependency(self, process: NextFlowProcess, dependency: Union[NextFlowProcess, None]):
74
- if dependency:
75
- self.process_dependency_map.add_edge(process, dependency)
76
- if not nx.dag.is_directed_acyclic_graph(self.process_dependency_map):
77
- raise ValueError(f"Cycles found in pipeline when adding process {process.process_name} "
78
- f"and its dependency {dependency.process_name}")
79
- else:
80
- # If no dependency is specified, the process will just be a single node in the DAG
81
- self.process_dependency_map.add_node(process)
82
-
83
- def _write_to_pipeline_file(self, workflow_file_path: str):
84
- with open(workflow_file_path, "a") as pipeline_file_handle:
85
- pipeline_file_handle.write(self.__str__() + "\n")
86
-
87
- def run_pipeline(self, workflow_file_path: str, nextflow_binary_path: str = 'nextflow',
88
- nextflow_config_path: str = None, working_dir: str = ".", resume: bool = False,
89
- other_args: dict = None):
90
- # Remove pipeline file if it already exists
91
- if os.path.exists(workflow_file_path):
92
- os.remove(workflow_file_path)
93
- self._write_to_pipeline_file(workflow_file_path)
94
- workflow_command = f"cd {working_dir} && {nextflow_binary_path} run {workflow_file_path}"
95
- workflow_command += f" -c {nextflow_config_path}" if nextflow_config_path else ""
96
- workflow_command += f" -with-report {workflow_file_path}.report.html"
97
- workflow_command += f" -with-dag {workflow_file_path}.dag.png"
98
- workflow_command += " -resume" if resume else ""
99
- workflow_command += " ".join([f" -{arg} {val}" for arg, val in other_args.items()]) if other_args else ""
100
- run_command_with_output(f"Running pipeline {workflow_file_path}...", workflow_command)
101
-
102
- @staticmethod
103
- def join_pipelines(main_pipeline: 'NextFlowPipeline', dependent_pipeline: 'NextFlowPipeline',
104
- with_dependencies: bool = True) -> 'NextFlowPipeline':
105
- """
106
- Join two pipelines with or without dependencies
107
-
108
- With Dependencies it returns a new pipeline where:
109
- 1) root processes are those of the main pipeline.
110
- 2) final processes are those of the dependent pipeline and
111
- 3) every root process of the dependent pipeline depends on the final processes of the main pipeline.
112
- Without Dependencies it returns a new pipeline where:
113
- 1) the two pipeline are left independent
114
- 2) Only shared dependencies
115
- 3) every root process of the dependent pipeline depends on the final processes of the main pipeline.
116
-
117
- """
118
- joined_pipeline = NextFlowPipeline()
119
- # Aggregate dependency maps of both pipelines
120
- joined_pipeline.process_dependency_map = nx.compose(main_pipeline.process_dependency_map,
121
- dependent_pipeline.process_dependency_map)
122
- if with_dependencies:
123
- for final_process_in_main_pipeline in main_pipeline._get_final_processes():
124
- for root_process_in_dependent_pipeline in dependent_pipeline._get_root_processes():
125
- joined_pipeline.add_process_dependency(root_process_in_dependent_pipeline,
126
- final_process_in_main_pipeline)
127
- return joined_pipeline
128
-
129
- def _get_root_processes(self) -> List[NextFlowProcess]:
130
- # Root processes are those which have no dependencies
131
- # See https://stackoverflow.com/a/62948641
132
- roots = []
133
- for component in nx.weakly_connected_components(self.process_dependency_map):
134
- subgraph = self.process_dependency_map.subgraph(component)
135
- roots.extend([n for n, d in subgraph.out_degree() if d == 0])
136
- return roots
137
-
138
- def _get_final_processes(self) -> List[NextFlowProcess]:
139
- # Final processes are those which have no other processes depending on them
140
- # See https://stackoverflow.com/a/62948641
141
- roots = []
142
- for component in nx.weakly_connected_components(self.process_dependency_map):
143
- subgraph = self.process_dependency_map.subgraph(component)
144
- roots.extend([n for n, d in subgraph.in_degree() if d == 0])
145
- return roots
146
-
147
- @staticmethod
148
- def _get_process_repr(process: NextFlowProcess, dependencies: List[NextFlowProcess]) -> str:
149
- process_directives_str = "\n".join([f"{key}='{value}'" for key, value in process.process_directives.items()])
150
- input_dependencies = "val flag from true"
151
- if dependencies:
152
- input_dependencies = "\n".join([f"val {dependency.success_flag} from {dependency.success_flag}"
153
- for dependency in dependencies])
154
- return "\n".join(map(str.strip, f"""
155
- process {process.process_name} {{
156
- {process_directives_str}
157
- input:
158
- {input_dependencies}
159
- output:
160
- val true into {process.success_flag}
161
- script:
162
- \"\"\"
163
- {process.command_to_run}
164
- \"\"\"
165
- }}""".split("\n")))
166
-
167
- def __str__(self):
168
- # Order the list of nodes based on the dependency
169
- # See https://networkx.org/documentation/stable/reference/algorithms/generated/networkx.algorithms.traversal.depth_first_search.dfs_postorder_nodes.html?highlight=dfs_postorder_nodes#networkx.algorithms.traversal.depth_first_search.dfs_postorder_nodes
170
- ordered_list_of_processes_to_run = list(nx.dfs_postorder_nodes(self.process_dependency_map))
171
- # Get a Nextflow pipeline representation of each process and its dependencies
172
- return "\n\n".join([NextFlowPipeline._get_process_repr(process, list(self.process_dependency_map[process]))
173
- for process in ordered_list_of_processes_to_run])
174
-
175
-
176
- class LinearNextFlowPipeline(NextFlowPipeline):
177
- """
178
- Simple linear pipeline that supports resumption
179
- """
180
- previous_process: NextFlowProcess = None
181
-
182
- def __init__(self, process_list: List[NextFlowProcess] = None):
183
- dependency_map = {}
184
- if process_list:
185
- for index, process in enumerate(process_list):
186
- dependency_map[process] = [] if index == 0 else [process_list[index - 1]]
187
- super().__init__(dependency_map)
188
-
189
- def add_process(self, process_name, command_to_run):
190
- current_process = NextFlowProcess(process_name=process_name, command_to_run=command_to_run)
191
- self._add_new_process(current_process)
192
-
193
- def _add_new_process(self, current_process):
194
- super().add_process_dependency(current_process, self.previous_process)
195
- self.previous_process = current_process