Skip to content

Commit 4abe254

Browse files
committed
#22: using pathlib to handle files and directories
1 parent e0b85a7 commit 4abe254

9 files changed

Lines changed: 170 additions & 154 deletions

File tree

wfcommons/common/file.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import logging
1212

1313
from logging import Logger
14-
from typing import Dict, Optional
14+
from typing import Dict, Optional, Union
1515

1616
from ..utils import NoValue
1717

@@ -32,22 +32,22 @@ class File:
3232
:param link: Type of file link.
3333
:type link: FileLink
3434
:param logger: The logger where to log information/warning or errors.
35-
:type logger: Logger
35+
:type logger: Optional[Logger]
3636
"""
3737

3838
def __init__(self, name: str, size: int, link: FileLink, logger: Optional[Logger] = None) -> None:
3939
"""A file used by tasks."""
40-
self.logger: Logger = logging.getLogger(__name__) if logger is None else logger
40+
self.logger: Logger = logger if logger else logging.getLogger(__name__)
4141

4242
self.name: str = name
4343
self.size: int = size
4444
self.link: FileLink = link
4545

46-
def as_dict(self) -> Dict:
46+
def as_dict(self) -> Dict[str, Union[str, int, FileLink]]:
4747
"""A JSON representation of the file.
4848
4949
:return: A JSON object representation of the file.
50-
:rtype: Dict
50+
:rtype: Dict[str, Union[str, int, FileLink]]
5151
"""
5252
return {
5353
'link': self.link.value,

wfcommons/common/machine.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,13 @@ def __init__(self,
7878
self.cpu_flops: int = cpu['count'] * cpu['speed'] * 10 ^ 6 if 'speed' in cpu else 0
7979
self.cpu_vendor: str = cpu['vendor'] if 'vendor' in cpu else None
8080

81-
self.logger.debug("created machine: {0} with {1} cores and {2} FLOPS.".format(
82-
self.name, self.cpu_cores, self.cpu_flops)
83-
)
81+
self.logger.debug(f"created machine: {self.name} with {self.cpu_cores} cores and {self.cpu_flops} FLOPS.")
8482

85-
def as_dict(self) -> Dict:
83+
def as_dict(self) -> Dict[str, Union[int, str]]:
8684
"""A JSON representation of the machine.
8785
8886
:return: A JSON object representation of the machine.
89-
:rtype: Dict
87+
:rtype: Dict[str, Union[int, str]]
9088
"""
9189
machine = {"nodeName": self.name}
9290
if self.system:

wfcommons/common/task.py

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -37,33 +37,33 @@ class Task:
3737
:param cores: Number of cores required by the task.
3838
:type cores: float
3939
:param task_id: Job unique ID (e.g., ID0000001).
40-
:type task_id: str
40+
:type task_id: Optional[str]
4141
:param category: Job category (can be used, for example, to define jobs that use the same program).
42-
:type category: str
42+
:type category: Optional[str]
4343
:param machine: Machine on which is the task has been executed.
44-
:type machine: Machine
44+
:type machine: Optional[Machine]
4545
:param program: Program name.
46-
:type program: str
46+
:type program: Optional[str]
4747
:param args: List of task arguments.
48-
:type args: List[str]
48+
:type args: Optional[List[str]]
4949
:param avg_cpu: Average CPU utilization in %.
50-
:type avg_cpu: float
50+
:type avg_cpu: Optional[float]
5151
:param bytes_read: Total bytes read in KB.
52-
:type bytes_read: int
52+
:type bytes_read: Optional[int]
5353
:param bytes_written: Total bytes written in KB.
54-
:type bytes_written: int
54+
:type bytes_written: Optional[int]
5555
:param memory: Memory (resident set) size of the process in KB.
56-
:type memory: int
56+
:type memory: Optional[int]
5757
:param energy: Total energy consumption in kWh.
58-
:type energy: int
58+
:type energy: Optional[int]
5959
:param avg_power: Average power consumption in W.
60-
:type avg_power: float
60+
:type avg_power: Optional[float]
6161
:param priority: Task priority.
62-
:type priority: int
62+
:type priority: Optional[int]
6363
:param files: List of input/output files used by the task.
64-
:type files: List[File]
64+
:type files: Optional[List[File]]
6565
:param logger: The logger where to log information/warning or errors.
66-
:type logger: Logger
66+
:type logger: Optional[Logger]
6767
"""
6868

6969
def __init__(self,
@@ -75,15 +75,15 @@ def __init__(self,
7575
category: Optional[str] = None,
7676
machine: Optional[Machine] = None,
7777
program: Optional[str] = None,
78-
args: List[str] = [],
78+
args: Optional[List[str]] = None,
7979
avg_cpu: Optional[float] = None,
8080
bytes_read: Optional[int] = None,
8181
bytes_written: Optional[int] = None,
8282
memory: Optional[int] = None,
8383
energy: Optional[int] = None,
8484
avg_power: Optional[float] = None,
8585
priority: Optional[int] = None,
86-
files: List[File] = [],
86+
files: Optional[List[File]] = None,
8787
logger: Optional[Logger] = None
8888
) -> None:
8989
"""A task in a workflow."""
@@ -95,20 +95,18 @@ def __init__(self,
9595
self.task_id: Optional[str] = task_id
9696
self.category: Optional[str] = category
9797
self.program: Optional[str] = program
98-
self.args: List[str] = args
98+
self.args: List[str] = args if args else []
9999
self.avg_cpu: Optional[float] = avg_cpu
100100
self.bytes_read: Optional[int] = bytes_read
101101
self.bytes_written: Optional[int] = bytes_written
102102
self.memory: Optional[int] = memory
103103
self.energy: Optional[int] = energy
104104
self.avg_power: Optional[float] = avg_power
105-
self.files: List[File] = files
105+
self.files: List[File] = files if files else []
106106
self.machine: Machine = machine
107-
self.priority = priority
107+
self.priority: Optional[int] = priority
108108

109-
self.logger.debug("created {0} task {1}: runtime => {2} seconds.".format(
110-
self.type, self.name, self.runtime)
111-
)
109+
self.logger.debug(f"created {self.type} task {self.name}: runtime => {self.runtime} seconds.")
112110

113111
def as_dict(self) -> Dict:
114112
"""A JSON representation of the task.

wfcommons/common/workflow.py

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import getpass
1212
import json
1313
import networkx as nx
14+
import pathlib
1415

1516
from datetime import datetime
1617
from typing import Optional
@@ -29,17 +30,17 @@ class Workflow(nx.DiGraph):
2930
:param name: Workflow name.
3031
:type name: str
3132
:param description: Workflow instance description.
32-
:type description: str
33+
:type description: Optional[str]
3334
:param wms_name: WMS name.
34-
:type wms_name: str
35+
:type wms_name: Optional[str]
3536
:param wms_version: WMS version.
36-
:type wms_version: str
37+
:type wms_version: Optional[str]
3738
:param wms_url: URL for the WMS website.
38-
:type wms_url: str
39+
:type wms_url: Optional[str]
3940
:param executed_at: Workflow start timestamp in the ISO 8601 format.
40-
:type executed_at: str
41+
:type executed_at: Optional[str]
4142
:param makespan: Workflow makespan in seconds.
42-
:type makespan: int
43+
:type makespan: Optional[int]
4344
"""
4445

4546
def __init__(self,
@@ -52,21 +53,23 @@ def __init__(self,
5253
makespan: Optional[int] = 0.0
5354
) -> None:
5455
"""Create an object of a workflow representation."""
55-
self.description = description if description else 'Instance generated with WfCommons - https://wfcommons.org'
56-
self.created_at = str(datetime.utcnow().isoformat())
57-
self.schema_version = "1.2"
58-
self.wms_name = "WfCommons" if not wms_name else wms_name
59-
self.wms_version = str(__version__) if not wms_version else wms_version
60-
self.wms_url = f"https://docs.wfcommons.org/en/v{__version__}/" if not wms_url else wms_url
61-
self.executed_at = datetime.now().astimezone().strftime("%Y%m%dT%H%M%S%z") if not executed_at else executed_at
62-
self.makespan = makespan
56+
self.description: Optional[
57+
str] = description if description else 'Instance generated with WfCommons - https://wfcommons.org'
58+
self.created_at: str = str(datetime.utcnow().isoformat())
59+
self.schema_version: str = "1.2"
60+
self.wms_name: Optional[str] = "WfCommons" if not wms_name else wms_name
61+
self.wms_version: Optional[str] = str(__version__) if not wms_version else wms_version
62+
self.wms_url: Optional[str] = f"https://docs.wfcommons.org/en/v{__version__}/" if not wms_url else wms_url
63+
self.executed_at: Optional[str] = datetime.now().astimezone().strftime(
64+
"%Y%m%dT%H%M%S%z") if not executed_at else executed_at
65+
self.makespan: Optional[int] = makespan
6366
super().__init__(name=name, makespan=self.makespan, executedat=self.executed_at)
6467

65-
def write_json(self, json_filename: Optional[str] = None) -> None:
68+
def write_json(self, json_file_path: Optional[pathlib.Path] = None) -> None:
6669
"""Write a JSON file of the workflow instance.
6770
68-
:param json_filename: JSON output file name.
69-
:type json_filename: str
71+
:param json_file_path: JSON output file name.
72+
:type json_file_path: Optional[pathlib.Path]
7073
"""
7174
workflow_machines = []
7275
machines_list = []
@@ -122,22 +125,22 @@ def write_json(self, json_filename: Optional[str] = None) -> None:
122125
workflow_json['workflow']['machines'] = workflow_machines
123126

124127
# write to file
125-
if not json_filename:
126-
json_filename = f'{self.name.lower()}.json'
127-
with open(json_filename, 'w') as outfile:
128+
if not json_file_path:
129+
json_file_path = pathlib.Path(f'{self.name.lower()}.json')
130+
with open(json_file_path, 'w') as outfile:
128131
outfile.write(json.dumps(workflow_json, indent=4))
129132

130-
def write_dot(self, dot_filename: str = None) -> None:
133+
def write_dot(self, dot_file_path: Optional[pathlib.Path] = None) -> None:
131134
"""Write a dot file of the workflow instance.
132135
133-
:param dot_filename: DOT output file name.
134-
:type dot_filename: str
136+
:param dot_file_path: DOT output file name.
137+
:type dot_file_path: Optional[pathlib.Path]
135138
"""
136-
if not dot_filename:
137-
dot_filename = f"{self.name.lower()}.dot"
138-
nx.nx_agraph.write_dot(self, dot_filename)
139+
if not dot_file_path:
140+
dot_file_path = pathlib.Path(f"{self.name.lower()}.dot")
141+
nx.nx_agraph.write_dot(self, dot_file_path)
139142

140143
def to_nx_digraph(self) -> nx.DiGraph:
141144
with tempfile.NamedTemporaryFile() as temp:
142-
self.write_json(temp.name)
143-
return create_graph(temp.name)
145+
self.write_json(pathlib.Path(temp.name))
146+
return create_graph(pathlib.Path(temp.name))

wfcommons/wfchef/utils.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,16 @@
88
# the Free Software Foundation, either version 3 of the License, or
99
# (at your option) any later version.
1010

11-
import networkx as nx
11+
import json
1212
import pathlib
13+
14+
import matplotlib.patches as mpatches
1315
import matplotlib.pyplot as plt
16+
import networkx as nx
17+
18+
from hashlib import sha256
1419
from matplotlib import cm
15-
import matplotlib.patches as mpatches
1620
from typing import Iterable, Union, Set, Optional, Tuple, Hashable
17-
import json
18-
from hashlib import sha256
1921

2022
this_dir = pathlib.Path(__file__).resolve().parent
2123

@@ -32,12 +34,12 @@ def combine_hashes(*hashes: str) -> str:
3234
return string_hash(sorted(hashes))
3335

3436

35-
def create_graph(path: Union[str, pathlib.Path]) -> nx.DiGraph:
37+
def create_graph(path: pathlib.Path) -> nx.DiGraph:
3638
"""
3739
Creates a networkX DiGraph from a JSON file in the WfFormat.
3840
3941
:param path: name (for samples available in WfCommons) or the path to graphs JSON.
40-
:type path: str or pathlib.Path.
42+
:type path: pathlib.Path
4143
4244
:return: graph.
4345
:rtype: networkX DiGraph.

0 commit comments

Comments
 (0)