fmu-manipulation-toolbox 1.9.1.3__py3-none-any.whl → 1.9.2b2__py3-none-any.whl

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 (32) hide show
  1. fmu_manipulation_toolbox/__main__.py +2 -2
  2. fmu_manipulation_toolbox/__version__.py +1 -1
  3. fmu_manipulation_toolbox/assembly.py +12 -8
  4. fmu_manipulation_toolbox/checker.py +4 -2
  5. fmu_manipulation_toolbox/cli/fmucontainer.py +27 -19
  6. fmu_manipulation_toolbox/cli/fmusplit.py +5 -2
  7. fmu_manipulation_toolbox/cli/fmutool.py +8 -3
  8. fmu_manipulation_toolbox/cli/utils.py +11 -1
  9. fmu_manipulation_toolbox/container.py +292 -82
  10. fmu_manipulation_toolbox/ls.py +35 -0
  11. fmu_manipulation_toolbox/operations.py +3 -2
  12. fmu_manipulation_toolbox/resources/darwin64/container.dylib +0 -0
  13. fmu_manipulation_toolbox/resources/linux32/client_sm.so +0 -0
  14. fmu_manipulation_toolbox/resources/linux64/client_sm.so +0 -0
  15. fmu_manipulation_toolbox/resources/linux64/container.so +0 -0
  16. fmu_manipulation_toolbox/resources/win32/client_sm.dll +0 -0
  17. fmu_manipulation_toolbox/resources/win32/server_sm.exe +0 -0
  18. fmu_manipulation_toolbox/resources/win64/client_sm.dll +0 -0
  19. fmu_manipulation_toolbox/resources/win64/container.dll +0 -0
  20. fmu_manipulation_toolbox/resources/win64/server_sm.exe +0 -0
  21. fmu_manipulation_toolbox/split.py +59 -3
  22. fmu_manipulation_toolbox/terminals.py +137 -0
  23. fmu_manipulation_toolbox/version.py +1 -1
  24. fmu_manipulation_toolbox-1.9.2b2.dist-info/METADATA +42 -0
  25. {fmu_manipulation_toolbox-1.9.1.3.dist-info → fmu_manipulation_toolbox-1.9.2b2.dist-info}/RECORD +29 -29
  26. {fmu_manipulation_toolbox-1.9.1.3.dist-info → fmu_manipulation_toolbox-1.9.2b2.dist-info}/entry_points.txt +1 -1
  27. {fmu_manipulation_toolbox-1.9.1.3.dist-info → fmu_manipulation_toolbox-1.9.2b2.dist-info}/licenses/LICENSE.txt +1 -1
  28. fmu_manipulation_toolbox/gui.py +0 -749
  29. fmu_manipulation_toolbox/gui_style.py +0 -252
  30. fmu_manipulation_toolbox-1.9.1.3.dist-info/METADATA +0 -30
  31. {fmu_manipulation_toolbox-1.9.1.3.dist-info → fmu_manipulation_toolbox-1.9.2b2.dist-info}/WHEEL +0 -0
  32. {fmu_manipulation_toolbox-1.9.1.3.dist-info → fmu_manipulation_toolbox-1.9.2b2.dist-info}/top_level.txt +0 -0
@@ -3,7 +3,7 @@ import sys
3
3
 
4
4
  def gui():
5
5
  try:
6
- from .gui import main
6
+ from .gui.gui import main
7
7
  main()
8
8
  except ModuleNotFoundError as e:
9
9
  print(f"FATAL ERROR: {e}. No GUI Available.")
@@ -11,7 +11,7 @@ def gui():
11
11
 
12
12
  def cli():
13
13
  from .cli.fmutool import fmutool
14
- fmutool(sys.argv[1:])
14
+ fmutool()
15
15
 
16
16
 
17
17
  def main():
@@ -1 +1 @@
1
- 'V1.9.1.3'
1
+ 'V1.9.2b2'
@@ -7,7 +7,7 @@ import uuid
7
7
  import xml.parsers.expat
8
8
  import zipfile
9
9
 
10
- from .container import FMUContainer, AutoWired
10
+ from .container import FMUContainer
11
11
 
12
12
  logger = logging.getLogger("fmu_manipulation_toolbox")
13
13
 
@@ -103,7 +103,8 @@ class AssemblyNode:
103
103
  def add_start_value(self, fmu_filename: str, port_name: str, value: str):
104
104
  self.start_values[Port(fmu_filename, port_name)] = value
105
105
 
106
- def make_fmu(self, fmu_directory: Path, debug=False, description_pathname=None, fmi_version=2):
106
+ def make_fmu(self, fmu_directory: Path, debug=False, description_pathname=None, fmi_version=2, datalog=False,
107
+ filename=None):
107
108
  for node in self.children.values():
108
109
  node.make_fmu(fmu_directory, debug=debug, fmi_version=fmi_version)
109
110
 
@@ -142,8 +143,11 @@ class AssemblyNode:
142
143
  for link_rule in wired.rule_link:
143
144
  self.add_link(link_rule[0], link_rule[1], link_rule[2], link_rule[3])
144
145
 
145
- container.make_fmu(self.name, self.step_size, mt=self.mt, profiling=self.profiling, sequential=self.sequential,
146
- debug=debug, ts_multiplier=self.ts_multiplier)
146
+ if filename is None:
147
+ filename = self.name
148
+
149
+ container.make_fmu(filename, self.step_size, mt=self.mt, profiling=self.profiling, sequential=self.sequential,
150
+ debug=debug, ts_multiplier=self.ts_multiplier, datalog=datalog)
147
151
 
148
152
  for node in self.children.values():
149
153
  logger.info(f"Deleting transient FMU Container '{node.name}'")
@@ -241,7 +245,7 @@ class Assembly:
241
245
  self.transient_dirnames: Set[Path] = set()
242
246
 
243
247
  if not fmu_directory.is_dir():
244
- raise AssemblyError(f"FMU directory is not valid: '{fmu_directory}'")
248
+ raise AssemblyError(f"FMU directory is not valid: '{fmu_directory.resolve()}'")
245
249
 
246
250
  self.input_pathname = fmu_directory / self.filename
247
251
  self.description_pathname = self.input_pathname # For inclusion in FMU
@@ -284,7 +288,7 @@ class Assembly:
284
288
  elif filename.endswith(".json"):
285
289
  return self.write_json(filename)
286
290
  else:
287
- logger.critical(f"Unable to write to '{filename}': format unsupported.")
291
+ raise AssemblyError(f"Unable to write to '{filename}': format unsupported.")
288
292
 
289
293
  def read_csv(self):
290
294
  name = str(self.filename.with_suffix(".fmu"))
@@ -525,9 +529,9 @@ class Assembly:
525
529
  self.root = sdd.parse(self.description_pathname)
526
530
  self.root.name = str(self.filename.with_suffix(".fmu"))
527
531
 
528
- def make_fmu(self, dump_json=False, fmi_version=2):
532
+ def make_fmu(self, dump_json=False, fmi_version=2, datalog=False, filename=None):
529
533
  self.root.make_fmu(self.fmu_directory, debug=self.debug, description_pathname=self.description_pathname,
530
- fmi_version=fmi_version)
534
+ fmi_version=fmi_version, datalog=datalog, filename=filename)
531
535
  if dump_json:
532
536
  dump_file = Path(self.input_pathname.stem + "-dump").with_suffix(".json")
533
537
  logger.info(f"Dump Json '{dump_file}'")
@@ -27,11 +27,11 @@ class OperationGenericCheck(OperationAbstract):
27
27
  return
28
28
 
29
29
  fmi_name = f"fmi{attrs['fmiVersion'][0]}"
30
-
31
30
  xsd_filename = os.path.join(os.path.dirname(__file__), "resources", "fmi-" + attrs['fmiVersion'],
32
31
  f"{fmi_name}ModelDescription.xsd")
32
+ xsd = xmlschema.XMLSchema(xsd_filename)
33
33
  try:
34
- xmlschema.validate(self.fmu.descriptor_filename, schema=xsd_filename)
34
+ xsd.validate(self.fmu.descriptor_filename)
35
35
  except XMLSchemaValidationError as error:
36
36
  logger.error(error.reason, error.msg)
37
37
  else:
@@ -43,8 +43,10 @@ class OperationGenericCheck(OperationAbstract):
43
43
  else:
44
44
  logger.error(f"This FMU does not validate with FMI standard.")
45
45
 
46
+
46
47
  _checkers_list: List[type[OperationAbstract]] = [OperationGenericCheck]
47
48
 
49
+
48
50
  def get_checkers() -> List[type[OperationAbstract]]:
49
51
  if sys.version_info < (3, 10):
50
52
  from importlib_metadata import entry_points
@@ -4,7 +4,7 @@ import sys
4
4
 
5
5
  from pathlib import Path
6
6
 
7
- from .utils import setup_logger, make_wide
7
+ from .utils import setup_logger, close_logger, make_wide
8
8
  from ..assembly import Assembly, AssemblyError
9
9
  from ..container import FMUContainerError
10
10
  from ..version import __version__ as version
@@ -22,36 +22,42 @@ def fmucontainer():
22
22
 
23
23
  parser.add_argument('-h', '-help', action="help")
24
24
 
25
- parser.add_argument("-fmu-directory", action="store", dest="fmu_directory", required=False, default=".",
26
- help="Directory containing initial FMU’s and used to generate containers. "
27
- "If not defined, current directory is used.")
28
-
29
- parser.add_argument("-fmi", action="store", dest="fmi_version", required=False, default="2",
30
- help="Define version of FMI to be used for container interface."
31
- "Only '2' or '3' is supported.")
32
-
33
25
  parser.add_argument("-container", action="append", dest="container_descriptions_list", default=[],
34
26
  metavar="filename.{csv|json|ssp},[:step_size]", required=True,
35
27
  help="Description of the container to create.")
36
28
 
29
+ parser.add_argument("-datalog", action="store_true", dest="datalog", default=False,
30
+ help="Log into log file input, output and local variables of the container")
31
+
37
32
  parser.add_argument("-debug", action="store_true", dest="debug",
38
33
  help="Add lot of useful log during the process.")
39
34
 
35
+ parser.add_argument("-dump-json", action="store_true", dest="dump", default=False,
36
+ help="Dump a JSON file for each container.")
37
+
38
+ parser.add_argument("-fmi", action="store", dest="fmi_version", required=False, default="2",
39
+ help="Define version of FMI to be used for container interface."
40
+ "Only '2' or '3' is supported.")
41
+
42
+ parser.add_argument("-fmu-directory", action="store", dest="fmu_directory", required=False, default=".",
43
+ help="Directory containing initial FMU’s and used to generate containers. "
44
+ "If not defined, current directory is used.")
45
+
40
46
  parser.add_argument("-no-auto-input", action="store_false", dest="auto_input", default=True,
41
47
  help="Create ONLY explicit input.")
42
48
 
49
+ parser.add_argument("-no-auto-link", action="store_false", dest="auto_link", default=True,
50
+ help="Create ONLY explicit links.")
51
+
52
+ parser.add_argument("-auto-local", action="store_true", dest="auto_local", default=False,
53
+ help="Expose local variables of the embedded fmu's.")
54
+
43
55
  parser.add_argument("-no-auto-output", action="store_false", dest="auto_output", default=True,
44
56
  help="Create ONLY explicit output.")
45
57
 
46
58
  parser.add_argument("-auto-parameter", action="store_true", dest="auto_parameter", default=False,
47
59
  help="Expose parameters of the embedded fmu's.")
48
60
 
49
- parser.add_argument("-auto-local", action="store_true", dest="auto_local", default=False,
50
- help="Expose local variables of the embedded fmu's.")
51
-
52
- parser.add_argument("-no-auto-link", action="store_false", dest="auto_link", default=True,
53
- help="Create ONLY explicit links.")
54
-
55
61
  parser.add_argument("-mt", action="store_true", dest="mt", default=False,
56
62
  help="Enable Multi-Threaded mode for the generated container.")
57
63
 
@@ -61,9 +67,6 @@ def fmucontainer():
61
67
  parser.add_argument("-sequential", action="store_true", dest="sequential", default=False,
62
68
  help="Use sequential mode to schedule embedded fmu's.")
63
69
 
64
- parser.add_argument("-dump-json", action="store_true", dest="dump", default=False,
65
- help="Dump a JSON file for each container.")
66
-
67
70
  parser.add_argument("-vr", action="store_true", dest="ts_multiplier", default=False,
68
71
  help="Add TS_MULTIPLIER input port to control step_size")
69
72
 
@@ -92,16 +95,21 @@ def fmucontainer():
92
95
  auto_parameter=config.auto_parameter, ts_multiplier=config.ts_multiplier)
93
96
  except FileNotFoundError as e:
94
97
  logger.fatal(f"Cannot read file: {e}")
98
+ close_logger(logger)
95
99
  sys.exit(-1)
96
100
  except (FMUContainerError, AssemblyError) as e:
97
101
  logger.fatal(f"{filename}: {e}")
102
+ close_logger(logger)
98
103
  sys.exit(-2)
99
104
 
100
105
  try:
101
- assembly.make_fmu(dump_json=config.dump, fmi_version=int(config.fmi_version))
106
+ assembly.make_fmu(dump_json=config.dump, fmi_version=int(config.fmi_version), datalog=config.datalog)
102
107
  except FMUContainerError as e:
103
108
  logger.fatal(f"{filename}: {e}")
109
+ close_logger(logger)
104
110
  sys.exit(-3)
105
111
 
112
+ close_logger(logger)
113
+
106
114
  if __name__ == "__main__":
107
115
  fmucontainer()
@@ -2,8 +2,7 @@ import argparse
2
2
  import logging
3
3
  import sys
4
4
 
5
-
6
- from .utils import setup_logger, make_wide
5
+ from .utils import setup_logger, close_logger, make_wide
7
6
  from ..split import FMUSplitter, FMUSplitterError
8
7
  from ..version import __version__ as version
9
8
 
@@ -37,11 +36,15 @@ def fmusplit():
37
36
  splitter.split_fmu()
38
37
  except FMUSplitterError as e:
39
38
  logger.fatal(f"{fmu_filename}: {e}")
39
+ close_logger(logger)
40
40
  sys.exit(-1)
41
41
  except FileNotFoundError as e:
42
42
  logger.fatal(f"Cannot read file: {e}")
43
+ close_logger(logger)
43
44
  sys.exit(-2)
44
45
 
46
+ close_logger(logger)
47
+
45
48
 
46
49
  if __name__ == "__main__":
47
50
  fmusplit()
@@ -1,9 +1,7 @@
1
1
  import argparse
2
2
  import sys
3
3
 
4
- from typing import *
5
-
6
- from .utils import setup_logger, make_wide
4
+ from .utils import setup_logger, close_logger, make_wide
7
5
  from ..operations import (OperationSummary, OperationError, OperationRemoveRegexp,
8
6
  OperationRemoveSources, OperationTrimUntil, OperationKeepOnlyRegexp, OperationMergeTopLevel,
9
7
  OperationStripTopLevel, OperationRenameFromCSV, OperationSaveNamesToCSV, FMU, FMUError)
@@ -78,6 +76,7 @@ def fmutool():
78
76
 
79
77
  if cli_options.fmu_input == cli_options.fmu_output:
80
78
  logger.fatal(f"'-input' and '-output' should point to different files.")
79
+ close_logger(logger)
81
80
  sys.exit(-3)
82
81
 
83
82
  logger.info(f"READING Input='{cli_options.fmu_input}'")
@@ -85,6 +84,7 @@ def fmutool():
85
84
  fmu = FMU(cli_options.fmu_input)
86
85
  except FMUError as reason:
87
86
  logger.fatal(f"{reason}")
87
+ close_logger(logger)
88
88
  sys.exit(-4)
89
89
 
90
90
  if cli_options.apply_on:
@@ -107,6 +107,7 @@ def fmutool():
107
107
  fmu.apply_operation(operation, cli_options.apply_on)
108
108
  except OperationError as reason:
109
109
  logger.fatal(f"{reason}")
110
+ close_logger(logger)
110
111
  sys.exit(-6)
111
112
 
112
113
  if cli_options.extract_description:
@@ -119,9 +120,13 @@ def fmutool():
119
120
  fmu.repack(cli_options.fmu_output)
120
121
  except FMUError as reason:
121
122
  logger.fatal(f"FATAL ERROR: {reason}")
123
+ close_logger(logger)
122
124
  sys.exit(-5)
123
125
  else:
124
126
  logger.info(f"INFO Modified FMU is not saved. If necessary use '-output' option.")
125
127
 
128
+ close_logger(logger)
129
+
130
+
126
131
  if __name__ == "__main__":
127
132
  fmutool()
@@ -2,7 +2,8 @@ import logging
2
2
  import sys
3
3
  from colorama import Fore, Style, init
4
4
 
5
- def setup_logger():
5
+
6
+ def setup_logger() -> logging.Logger:
6
7
  class CustomFormatter(logging.Formatter):
7
8
  def format(self, record):
8
9
  log_format = "%(levelname)-8s | %(message)s"
@@ -24,6 +25,15 @@ def setup_logger():
24
25
 
25
26
  return logger
26
27
 
28
+
29
+ def close_logger(logger: logging.Logger):
30
+ for handler in logger.handlers:
31
+ logger.removeHandler(handler)
32
+ handler.close()
33
+ logger.setLevel(logging.NOTSET)
34
+ logger.propagate = True
35
+
36
+
27
37
  def make_wide(formatter, w=120, h=36):
28
38
  """Return a wider HelpFormatter, if possible."""
29
39
  try: