pythonfmu3 0.1.16__py3-none-any.whl → 0.1.18__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.
pythonfmu3/__init__.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from ._version import __version__
2
2
  from .builder import FmuBuilder
3
- from .enums import Fmi3Causality, Fmi3Initial, Fmi3Variability
4
- from .fmi3slave import Fmi3Slave
3
+ from .enums import Fmi3Causality, Fmi3Initial, Fmi3Status, Fmi3Variability
4
+ from .fmi3slave import Fmi3Slave, Fmi3StepResult
5
5
  from .variables import Boolean, Enumeration, Int32, Int64, UInt64, Float64, String, Dimension
6
6
  from .default_experiment import DefaultExperiment
7
7
  from .variable_types import Float64Type, EnumerationType
pythonfmu3/_version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.16"
1
+ __version__ = "0.1.18"
pythonfmu3/builder.py CHANGED
@@ -66,6 +66,7 @@ class FmuBuilder:
66
66
  dest: FilePath = ".",
67
67
  project_files: Iterable[FilePath] = set(),
68
68
  documentation_folder: Optional[FilePath] = None,
69
+ terminals : Optional[FilePath] = None,
69
70
  **options,
70
71
  ) -> Path:
71
72
  script_file = Path(script_file)
@@ -85,6 +86,17 @@ class FmuBuilder:
85
86
  raise ValueError(
86
87
  f"The documentation folder does not exists {documentation_folder!s}"
87
88
  )
89
+
90
+ if terminals is not None:
91
+ terminals = Path(terminals)
92
+ if not terminals.exists():
93
+ raise ValueError(
94
+ f"The specified terminalsAndIcons file does not exists {terminals!s}"
95
+ )
96
+ if not terminals.name == "terminalsAndIcons.xml":
97
+ raise ValueError(
98
+ f"Incorrect terminal name {terminals!s}. Terminal file must be named terminalsAndIcons.xml"
99
+ )
88
100
 
89
101
  module_name = script_file.stem
90
102
 
@@ -178,6 +190,12 @@ class FmuBuilder:
178
190
  relative_f = f.relative_to(documentation_folder)
179
191
  zip_fmu.write(f, arcname=(documentation / relative_f))
180
192
 
193
+ if terminals is not None:
194
+ terminalsFolder = Path("terminalsAndIcons")
195
+ relative_f = terminals.relative_to(terminals.parent)
196
+ zip_fmu.write(f, arcname=(terminalsFolder / relative_f))
197
+
198
+
181
199
  # Add the model description
182
200
  xml_str = parseString(tostring(xml, "UTF-8"))
183
201
  zip_fmu.writestr(
@@ -215,6 +233,13 @@ def create_command_parser(parser: argparse.ArgumentParser):
215
233
  default=None
216
234
  )
217
235
 
236
+ parser.add_argument(
237
+ "--terminals",
238
+ dest="terminals",
239
+ help="Terminals file (terminalsAndIcons.xml) to include in the FMU.",
240
+ default=None
241
+ )
242
+
218
243
  for option in FMI3_MODEL_OPTIONS:
219
244
  action = "store_false" if option.value else "store_true"
220
245
  parser.add_argument(
pythonfmu3/fmi3slave.py CHANGED
@@ -5,7 +5,7 @@ import datetime
5
5
  from abc import ABC, abstractmethod
6
6
  from collections import OrderedDict, namedtuple
7
7
  from pathlib import Path
8
- from typing import Any, ClassVar, Dict, List, Optional
8
+ from typing import Any, ClassVar, Dict, List, NamedTuple, Optional
9
9
  from uuid import uuid1
10
10
  from xml.etree.ElementTree import Element, SubElement
11
11
 
@@ -27,6 +27,11 @@ FMI3_MODEL_OPTIONS: List[ModelOptions] = [
27
27
  ModelOptions("canSerializeFMUState", False, "serialize-state")
28
28
  ]
29
29
 
30
+ class Fmi3StepResult(NamedTuple):
31
+ status: Fmi3Status = Fmi3Status.ok
32
+ eventHandlingNeeded: bool = False
33
+ terminateSimulation: bool = False
34
+ earlyReturn: bool = False
30
35
 
31
36
  class Fmi3Slave(ABC):
32
37
  """Abstract facade class to execute Python through FMI standard."""
@@ -235,7 +240,7 @@ class Fmi3Slave(ABC):
235
240
  pass
236
241
 
237
242
  @abstractmethod
238
- def do_step(self, current_time: float, step_size: float) -> bool:
243
+ def do_step(self, current_time: float, step_size: float) -> Fmi3StepResult:
239
244
  pass
240
245
 
241
246
  def terminate(self):
File without changes
@@ -124,10 +124,13 @@ public:
124
124
  FMIString value[]) const;
125
125
 
126
126
  // Called from fmi3DoStep()/fmiDoStep(). Must be implemented in model code.
127
- virtual bool DoStep(
127
+ virtual FMIStatus DoStep(
128
128
  FMIFloat64 currentCommunicationPoint,
129
129
  FMIFloat64 communicationStepSize,
130
130
  FMIBoolean newStep,
131
+ FMIBoolean* eventHandlingNeeded,
132
+ FMIBoolean* terminateSimulation,
133
+ FMIBoolean* earlyReturn,
131
134
  FMIFloat64& endOfStep) = 0;
132
135
 
133
136
  virtual void GetFMUstate(fmi3FMUState& state) = 0;
@@ -50,7 +50,7 @@ struct Component
50
50
  Component(cppfmu::FMIComponentEnvironment instanceEnvironment,
51
51
  cppfmu::FMICallbackLogger logCallback,
52
52
  cppfmu::FMIBoolean loggingOn) : loggerSettings{std::make_shared<cppfmu::Logger::Settings>()},
53
- logger{instanceEnvironment, logCallback, loggerSettings}, lastSuccessfulTime{std::numeric_limits<cppfmu::FMIFloat64>::quiet_NaN()}
53
+ logger{instanceEnvironment, logCallback, loggerSettings}
54
54
  {
55
55
  loggerSettings->debugLoggingEnabled = (loggingOn == cppfmu::FMITrue);
56
56
  }
@@ -62,7 +62,6 @@ struct Component
62
62
 
63
63
  // Co-simulation
64
64
  std::unique_ptr<cppfmu::SlaveInstance> slave;
65
- cppfmu::FMIFloat64 lastSuccessfulTime;
66
65
  };
67
66
  } // namespace
68
67
 
@@ -659,27 +658,30 @@ fmi3Status fmi3DoStep(
659
658
  fmi3Instance c,
660
659
  fmi3Float64 currentCommunicationPoint,
661
660
  fmi3Float64 communicationStepSize,
662
- fmi3Boolean /*noSetFMUStatePriorToCurrentPoint*/,
663
- fmi3Boolean*,
664
- fmi3Boolean*,
665
- fmi3Boolean*,
666
- fmi3Float64*)
661
+ fmi3Boolean noSetFmuStatePriorToCurrentPoint,
662
+ fmi3Boolean* eventHandlingNeeded ,
663
+ fmi3Boolean* terminateSimulation,
664
+ fmi3Boolean* earlyReturn,
665
+ fmi3Float64* lastSuccessfulTime)
667
666
  {
668
667
  const auto component = reinterpret_cast<Component*>(c);
669
668
  try {
670
669
  double endTime = currentCommunicationPoint;
671
- const auto ok = component->slave->DoStep(
670
+ const auto status = component->slave->DoStep(
672
671
  currentCommunicationPoint,
673
672
  communicationStepSize,
674
- fmi3True,
673
+ noSetFmuStatePriorToCurrentPoint,
674
+ eventHandlingNeeded,
675
+ terminateSimulation,
676
+ earlyReturn,
675
677
  endTime);
676
- if (ok) {
677
- component->lastSuccessfulTime =
678
+ if (status == fmi3Status::fmi3OK) {
679
+ *lastSuccessfulTime =
678
680
  currentCommunicationPoint + communicationStepSize;
679
681
  return fmi3OK;
680
682
  } else {
681
- component->lastSuccessfulTime = endTime;
682
- return fmi3Discard;
683
+ *lastSuccessfulTime = endTime;
684
+ return status;
683
685
  }
684
686
  } catch (const cppfmu::FatalError& e) {
685
687
  component->logger.Log(fmi3Fatal, "", e.what());
@@ -200,20 +200,46 @@ void PySlaveInstance::ExitInitializationMode()
200
200
  });
201
201
  }
202
202
 
203
- bool PySlaveInstance::DoStep(cppfmu::FMIFloat64 currentTime, cppfmu::FMIFloat64 stepSize, cppfmu::FMIBoolean, cppfmu::FMIFloat64& endOfStep)
204
- {
205
- bool status;
206
- py_safe_run([this, &status, currentTime, stepSize](PyGILState_STATE gilState) {
203
+ cppfmu::FMIStatus PySlaveInstance::DoStep(cppfmu::FMIFloat64 currentTime,
204
+ cppfmu::FMIFloat64 stepSize,
205
+ cppfmu::FMIBoolean noSetFmuStatePriorToCurrentPoint,
206
+ cppfmu::FMIBoolean* eventHandlingNeeded,
207
+ cppfmu::FMIBoolean* terminateSimulation,
208
+ cppfmu::FMIBoolean* earlyReturn,
209
+ cppfmu::FMIFloat64& endOfStep)
210
+ {
211
+ cppfmu::FMIStatus fmuStatus = cppfmu::FMIOK;
212
+ py_safe_run([this, &fmuStatus, currentTime, stepSize, terminateSimulation](PyGILState_STATE gilState) {
207
213
  auto f = PyObject_CallMethod(pInstance_, "do_step", "(dd)", currentTime, stepSize);
208
214
  if (f == nullptr) {
209
215
  handle_py_exception("[doStep] PyObject_CallMethod", gilState);
210
216
  }
211
- status = static_cast<bool>(PyObject_IsTrue(f));
217
+
218
+ if (PyObject_HasAttrString(f, "status")) {
219
+ PyObject* pyStatus = PyObject_GetAttrString(f, "status");
220
+ if (pyStatus) {
221
+ fmuStatus = static_cast<cppfmu::FMIStatus>(PyLong_AsLong(pyStatus));
222
+ Py_DECREF(pyStatus);
223
+ }
224
+ } else {
225
+ bool status = static_cast<bool>(PyObject_IsTrue(f));
226
+ if (!status) {
227
+ fmuStatus = cppfmu::FMIDiscard;
228
+ }
229
+ }
230
+
231
+ if (PyObject_HasAttrString(f, "terminateSimulation")) {
232
+ PyObject* pyTerminateSimulation = PyObject_GetAttrString(f, "terminateSimulation");
233
+ if (pyTerminateSimulation) {
234
+ *terminateSimulation = static_cast<bool>(PyObject_IsTrue(pyTerminateSimulation));
235
+ Py_DECREF(pyTerminateSimulation);
236
+ }
237
+ }
212
238
  Py_DECREF(f);
213
239
  clearLogBuffer();
214
240
  });
215
241
 
216
- return status;
242
+ return fmuStatus;
217
243
  }
218
244
 
219
245
  void PySlaveInstance::Reset()
@@ -25,7 +25,13 @@ public:
25
25
  void ExitInitializationMode() override;
26
26
  void Terminate() override;
27
27
  void Reset() override;
28
- bool DoStep(cppfmu::FMIFloat64 currentCommunicationPoint, cppfmu::FMIFloat64 communicationStepSize, cppfmu::FMIBoolean newStep, cppfmu::FMIFloat64& endOfStep) override;
28
+ cppfmu::FMIStatus DoStep(cppfmu::FMIFloat64 currentCommunicationPoint,
29
+ cppfmu::FMIFloat64 communicationStepSize,
30
+ cppfmu::FMIBoolean newStep,
31
+ cppfmu::FMIBoolean* eventHandlingNeeded,
32
+ cppfmu::FMIBoolean* terminateSimulation,
33
+ cppfmu::FMIBoolean* earlyReturn,
34
+ cppfmu::FMIFloat64& endOfStep) override;
29
35
 
30
36
  void SetFloat64(const cppfmu::FMIValueReference* vr, std::size_t nvr, const cppfmu::FMIFloat64* value, std::size_t nValues) override;
31
37
  void SetInt32(const cppfmu::FMIValueReference* vr, std::size_t nvr, const cppfmu::FMIInt32* value) override;
@@ -176,3 +176,20 @@ def test_documentation(tmp_path):
176
176
 
177
177
  assert "documentation/index.html" in names
178
178
  assert "documentation/licenses/license.txt" in names
179
+
180
+
181
+ def test_terminals(tmp_path):
182
+ script_file = Path(__file__).parent / "slaves/pythonslave.py"
183
+ def build():
184
+ with tempfile.TemporaryDirectory() as terminals_dir:
185
+ terminals_dir = Path(terminals_dir)
186
+ terminals = terminals_dir / "terminalsAndIcons.xml"
187
+ terminals.write_text("Dummy Terminal 1")
188
+
189
+ return FmuBuilder.build_FMU(script_file, dest=tmp_path, terminals=terminals)
190
+
191
+ fmu = build()
192
+ with zipfile.ZipFile(fmu) as files:
193
+ names = files.namelist()
194
+
195
+ assert "terminalsAndIcons/terminalsAndIcons.xml" in names
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pythonfmu3
3
- Version: 0.1.16
3
+ Version: 0.1.18
4
4
  Summary: A lightweight framework that enables the packaging of Python3.x code as co-simulation FMUs.
5
5
  Home-page: https://github.com/stephensmith25/PythonFMU3
6
6
  Author: Stephen Smith
@@ -62,7 +62,7 @@ pip install pythonfmu3
62
62
  3. Run `pythonfmu3 build` to create the fmu.
63
63
 
64
64
  ```
65
- usage: pythonfmu3 build [-h] -f SCRIPT_FILE [-d DEST] [--doc DOCUMENTATION_FOLDER] [--no-external-tool]
65
+ usage: pythonfmu3 build [-h] -f SCRIPT_FILE [-d DEST] [--doc DOCUMENTATION_FOLDER] [--terminals TERMINALS_FILE] [--no-external-tool]
66
66
  [--no-variable-step] [--interpolate-inputs] [--only-one-per-process] [--handle-state]
67
67
  [--serialize-state] [--use-memory-management]
68
68
  [Project files [Project files ...]]
@@ -79,6 +79,8 @@ optional arguments:
79
79
  -d DEST, --dest DEST Where to save the FMU.
80
80
  --doc DOCUMENTATION_FOLDER
81
81
  Documentation folder to include in the FMU.
82
+ --terminals TERMINALS_FILE
83
+ Terminals file (terminalsAndIcons.xml) to include in the FMU.
82
84
  --no-external-tool If given, needsExecutionTool=false
83
85
  --no-variable-step If given, canHandleVariableCommunicationStepSize=false
84
86
  --interpolate-inputs If given, canInterpolateInputs=true
@@ -1,11 +1,11 @@
1
- pythonfmu3/__init__.py,sha256=PT1R0LpSInyVdXGJbkWMTQym6_SEU7CqUkG7OH5j1f0,396
1
+ pythonfmu3/__init__.py,sha256=oN-2oXyCFwq0gvL2IEf5QvwIXBXZgsSBwAJw7LZ9vzc,424
2
2
  pythonfmu3/__main__.py,sha256=gC1T8x2d02hhqshyNQGSS70SyCk-3I3t8zPqoRo2Xd8,1543
3
- pythonfmu3/_version.py,sha256=yF88-8vL8keLe6gCTumymw0UoMkWkSrJnzLru4zBCLQ,23
4
- pythonfmu3/builder.py,sha256=YLTeLLpiFOkoDYwnJ55GEhb3ham0xxROMjMN6bvaw5Y,8784
3
+ pythonfmu3/_version.py,sha256=6BiuMUkhwQp6bzUZSF8np8F1NwCltEtK0sPBF__tepU,23
4
+ pythonfmu3/builder.py,sha256=d_nTRWKohZrZsMbTmxiYJzszzVBp-CRisV_y_OVyW6U,9779
5
5
  pythonfmu3/default_experiment.py,sha256=FJ0l0FpU7pT4Pox2RiA2y-Cb_e7DE2XlbWKySRYQaVk,293
6
6
  pythonfmu3/deploy.py,sha256=eqFWVxZUkJCLvmq1-GuMNjn2j0VCGoaXPhRWrCk2Vxg,3741
7
7
  pythonfmu3/enums.py,sha256=ZmC6vGeBTGt7HarPQ4uYV10ezPsvIxAHH1ypjNq7G3E,729
8
- pythonfmu3/fmi3slave.py,sha256=7rDp_5TCQnkFLV11UF55mKEvUDXbpZPfn8sOjYCNCSw,16569
8
+ pythonfmu3/fmi3slave.py,sha256=M5zZbsdM8fv8NPfMp9ljyrLcqzE5RSvM3iFz5qyxnN0,16770
9
9
  pythonfmu3/logmsg.py,sha256=0wn11GLwq0LLWqyC2ktLRjQFWlpj07wWliZ8rUHx1gg,359
10
10
  pythonfmu3/osutil.py,sha256=1qN6qudN4zCupZwc15pzp52WObkqi6jGy9a-MehNt9Q,656
11
11
  pythonfmu3/unit.py,sha256=SjOaywb5lVQbAO_iLjc_7Ly3nYrmAvIW2_hAGt12UFU,1475
@@ -18,20 +18,20 @@ pythonfmu3/pythonfmu-export/build_win.sh,sha256=UzmAcWqFmwBu6mvYne2Dx3UK8iPwTtP4
18
18
  pythonfmu3/pythonfmu-export/src/CMakeLists.txt,sha256=RyjGhUUDhG_HEieCdt5WMfTR1snofOqigEKc83_zvfE,1104
19
19
  pythonfmu3/pythonfmu-export/src/cppfmu/cppfmu_common.hpp,sha256=cgrlZa5L-bbjZeVi0pmy4JKE5UJ2GszzuyOqTdRcBRQ,4353
20
20
  pythonfmu3/pythonfmu-export/src/cppfmu/cppfmu_cs.cpp,sha256=EsUIevwmCzX9hsui3i8x1crSnSOG8dEK15Zm1ZIavYQ,3843
21
- pythonfmu3/pythonfmu-export/src/cppfmu/cppfmu_cs.hpp,sha256=v4Fb8gOWk2tsUgnuQ2NBeqwc3EFQhWRxvDYHtL1C0zk,6144
22
- pythonfmu3/pythonfmu-export/src/cppfmu/fmi_functions.cpp,sha256=olF5Umz35uqXVMT_v9UMvwmvOJzbRbjuq1uOfnlvtUA,25539
21
+ pythonfmu3/pythonfmu-export/src/cppfmu/cppfmu_cs.hpp,sha256=UmqAVAVE1KHNHMC8mIh8gIHRJ_aQk0Ma139TU6Kvv4o,6264
22
+ pythonfmu3/pythonfmu-export/src/cppfmu/fmi_functions.cpp,sha256=FL8TveY4TNAbtrgzElC4WliY8C1vOfvtd5Sh2CcVFgc,25610
23
23
  pythonfmu3/pythonfmu-export/src/fmi/fmi3FunctionTypes.h,sha256=Tk1WY0nAYBGiOAQ8zVbmqRAfdQttITWsLba7udhBwG4,30050
24
24
  pythonfmu3/pythonfmu-export/src/fmi/fmi3Functions.h,sha256=NsHuclp20wcuUInYf-91UXZbljTeu2cPXENqNEORdgU,16262
25
25
  pythonfmu3/pythonfmu-export/src/fmi/fmi3PlatformTypes.h,sha256=ZCQLJgSbRGrMsBiQ4auaYCY4J3Hck6g3t1iZp5NEguw,4251
26
26
  pythonfmu3/pythonfmu-export/src/pythonfmu/IPyState.hpp,sha256=GLiOjhKLDVEICersnqVwezwEshbxfdh_cyMxBJGFbu8,456
27
- pythonfmu3/pythonfmu-export/src/pythonfmu/PySlaveInstance.cpp,sha256=pzHSx3Cfq7Lt7dcvMR5na7tyOrTs0RsNglnrAcRc0cs,24333
28
- pythonfmu3/pythonfmu-export/src/pythonfmu/PySlaveInstance.hpp,sha256=Q8eulMAkv7YkfzCi2KSwxvYngv0I_nRbmfTJR9vT92M,4063
27
+ pythonfmu3/pythonfmu-export/src/pythonfmu/PySlaveInstance.cpp,sha256=MpEUUcxPwoJlM_mW-9qxj4ezgKQd-CkDc2ud0mM7HbQ,25362
28
+ pythonfmu3/pythonfmu-export/src/pythonfmu/PySlaveInstance.hpp,sha256=T-epGp68SjhDv-JupxUe2ZgnV8unU4htc-PUBokjWm4,4239
29
29
  pythonfmu3/pythonfmu-export/src/pythonfmu/PyState.hpp,sha256=CjFEIrZu8b1jxQAIgfI_o36hyItW_SdQ5VSkImf7JNs,2977
30
- pythonfmu3/resources/binaries/x86_64-linux/libpythonfmu-export.so,sha256=w89mM0c5nt_5RT1uYWtFFrM-qd40y7vdW-cmLbuo9Cc,365120
31
- pythonfmu3/resources/binaries/x86_64-windows/pythonfmu-export.dll,sha256=jjd6J1oOhFfExxYkoUClk4uakAmUc00HbZParm7iFXY,430592
30
+ pythonfmu3/resources/binaries/x86_64-linux/libpythonfmu-export.so,sha256=LLTlb6TDjJ24xuy7zhO5Sbj39nVzQSODkkXMXGl8Y7s,365224
31
+ pythonfmu3/resources/binaries/x86_64-windows/pythonfmu-export.dll,sha256=wi2jjGlTgRz5Gi8YNZsi4xoEzrxKO4UE7xVT0nBZViY,430592
32
32
  pythonfmu3/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
33
  pythonfmu3/tests/conftest.py,sha256=B6XxTnBdeF_tEJ3w2DlfPKUfvlk-oULgIhQtXkgOJIc,171
34
- pythonfmu3/tests/test_builder.py,sha256=StR9oNmF6dtuxxKtPFlncLQN-O7n97nvHm6EFH4Qn14,6252
34
+ pythonfmu3/tests/test_builder.py,sha256=GrD4ziin3RLOe_36rBQCMnKrSkhc3IqnxE1a6kCFPok,6842
35
35
  pythonfmu3/tests/test_deploy.py,sha256=JCDo-O93-izxrP9Q4K0njBcfZ-gAXYx9aZ4plgctz7k,1783
36
36
  pythonfmu3/tests/test_fmi3slave.py,sha256=1uwTdfiFZNmU0yzIdC30kAuu95xsZSTMA9CGk_Kdmm4,4304
37
37
  pythonfmu3/tests/test_integration.py,sha256=zA3iJ4rI2cKEE8mDsAmcVuwNWlJzhonV8Wxz92hzEac,10387
@@ -46,9 +46,9 @@ pythonfmu3/tests/slaves/localmodule.py,sha256=-q5Lmh2I88MG7nLTscms0n5xhHLkUDed1I
46
46
  pythonfmu3/tests/slaves/pythonslave.py,sha256=uzrTQmfk0QBalxNTviGMZNph_YgVmcbxPqKgX5rSvXg,2172
47
47
  pythonfmu3/tests/slaves/pythonslave_read_file.py,sha256=t2sDaZSr2veD91gdqCO9W9CN-AN3TyXABXXfV9Rt0Xs,791
48
48
  pythonfmu3/tests/slaves/slavewithdep.py,sha256=hHDFB0dw8wkHiGzxeAVbz9O5LR6ghsFeONgRFdiK_t0,812
49
- pythonfmu3-0.1.16.dist-info/LICENSE,sha256=24Cw_MPouLK-G_t8Hgjm59IS9BnPoL6SKkyuZ0xesXY,1155
50
- pythonfmu3-0.1.16.dist-info/METADATA,sha256=fNhz4isDTQ1wlef8U-x5AYctr3bPGKRSqtSC8IunMhU,7442
51
- pythonfmu3-0.1.16.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
52
- pythonfmu3-0.1.16.dist-info/entry_points.txt,sha256=GgkWYs0DKGHLcijMEYZGkhkHOK2RVUpjGwvl1fwyDwQ,60
53
- pythonfmu3-0.1.16.dist-info/top_level.txt,sha256=6ne7bh_cME1hepxCx1BG8N5QVhVAufrp7LLok6vq7nE,11
54
- pythonfmu3-0.1.16.dist-info/RECORD,,
49
+ pythonfmu3-0.1.18.dist-info/LICENSE,sha256=24Cw_MPouLK-G_t8Hgjm59IS9BnPoL6SKkyuZ0xesXY,1155
50
+ pythonfmu3-0.1.18.dist-info/METADATA,sha256=FKgLxqU6YXlmXZaZSKkQVd7zxxMP-Dz86QJND8BehKA,7586
51
+ pythonfmu3-0.1.18.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
52
+ pythonfmu3-0.1.18.dist-info/entry_points.txt,sha256=GgkWYs0DKGHLcijMEYZGkhkHOK2RVUpjGwvl1fwyDwQ,60
53
+ pythonfmu3-0.1.18.dist-info/top_level.txt,sha256=6ne7bh_cME1hepxCx1BG8N5QVhVAufrp7LLok6vq7nE,11
54
+ pythonfmu3-0.1.18.dist-info/RECORD,,