rtc-tools 2.5.2rc3__py3-none-any.whl → 2.6.0__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.

Potentially problematic release.


This version of rtc-tools might be problematic. Click here for more details.

Files changed (47) hide show
  1. {rtc_tools-2.5.2rc3.dist-info → rtc_tools-2.6.0.dist-info}/METADATA +7 -7
  2. rtc_tools-2.6.0.dist-info/RECORD +50 -0
  3. {rtc_tools-2.5.2rc3.dist-info → rtc_tools-2.6.0.dist-info}/WHEEL +1 -1
  4. rtctools/__init__.py +2 -1
  5. rtctools/_internal/alias_tools.py +12 -10
  6. rtctools/_internal/caching.py +5 -3
  7. rtctools/_internal/casadi_helpers.py +11 -32
  8. rtctools/_internal/debug_check_helpers.py +1 -1
  9. rtctools/_version.py +3 -3
  10. rtctools/data/__init__.py +2 -2
  11. rtctools/data/csv.py +54 -33
  12. rtctools/data/interpolation/bspline.py +3 -3
  13. rtctools/data/interpolation/bspline1d.py +42 -29
  14. rtctools/data/interpolation/bspline2d.py +10 -4
  15. rtctools/data/netcdf.py +137 -93
  16. rtctools/data/pi.py +304 -210
  17. rtctools/data/rtc.py +64 -53
  18. rtctools/data/storage.py +91 -51
  19. rtctools/optimization/collocated_integrated_optimization_problem.py +1244 -696
  20. rtctools/optimization/control_tree_mixin.py +68 -66
  21. rtctools/optimization/csv_lookup_table_mixin.py +107 -74
  22. rtctools/optimization/csv_mixin.py +83 -52
  23. rtctools/optimization/goal_programming_mixin.py +239 -148
  24. rtctools/optimization/goal_programming_mixin_base.py +204 -111
  25. rtctools/optimization/homotopy_mixin.py +36 -27
  26. rtctools/optimization/initial_state_estimation_mixin.py +8 -8
  27. rtctools/optimization/io_mixin.py +48 -43
  28. rtctools/optimization/linearization_mixin.py +3 -1
  29. rtctools/optimization/linearized_order_goal_programming_mixin.py +57 -28
  30. rtctools/optimization/min_abs_goal_programming_mixin.py +72 -29
  31. rtctools/optimization/modelica_mixin.py +135 -81
  32. rtctools/optimization/netcdf_mixin.py +32 -18
  33. rtctools/optimization/optimization_problem.py +181 -127
  34. rtctools/optimization/pi_mixin.py +68 -36
  35. rtctools/optimization/planning_mixin.py +19 -0
  36. rtctools/optimization/single_pass_goal_programming_mixin.py +159 -112
  37. rtctools/optimization/timeseries.py +4 -6
  38. rtctools/rtctoolsapp.py +18 -18
  39. rtctools/simulation/csv_mixin.py +37 -30
  40. rtctools/simulation/io_mixin.py +9 -5
  41. rtctools/simulation/pi_mixin.py +62 -32
  42. rtctools/simulation/simulation_problem.py +471 -180
  43. rtctools/util.py +84 -56
  44. rtc_tools-2.5.2rc3.dist-info/RECORD +0 -49
  45. {rtc_tools-2.5.2rc3.dist-info → rtc_tools-2.6.0.dist-info}/COPYING.LESSER +0 -0
  46. {rtc_tools-2.5.2rc3.dist-info → rtc_tools-2.6.0.dist-info}/entry_points.txt +0 -0
  47. {rtc_tools-2.5.2rc3.dist-info → rtc_tools-2.6.0.dist-info}/top_level.txt +0 -0
rtctools/util.py CHANGED
@@ -26,9 +26,9 @@ def _resolve_folder(kwargs, base_folder, subfolder_kw, default):
26
26
  return os.path.join(base_folder, subfolder)
27
27
 
28
28
 
29
- def run_optimization_problem(optimization_problem_class,
30
- base_folder='..', log_level=logging.INFO, profile=False,
31
- **kwargs):
29
+ def run_optimization_problem(
30
+ optimization_problem_class, base_folder="..", log_level=logging.INFO, profile=False, **kwargs
31
+ ):
32
32
  """
33
33
  Sets up and solves an optimization problem.
34
34
 
@@ -36,9 +36,12 @@ def run_optimization_problem(optimization_problem_class,
36
36
 
37
37
  1. That the ``base_folder`` contains subfolders ``input``, ``output``, and ``model``,
38
38
  containing input data, output data, and the model, respectively.
39
- 2. When using :class:`.CSVLookupTableMixin`, that the base folder contains a subfolder ``lookup_tables``.
40
- 3. When using :class:`.ModelicaMixin`, that the base folder contains a subfolder ``model``.
41
- 4. When using :class:`.ModelicaMixin`, that the toplevel Modelica model name equals the class name.
39
+ 2. When using :class:`.CSVLookupTableMixin`, that the base folder contains
40
+ a subfolder ``lookup_tables``.
41
+ 3. When using :class:`.ModelicaMixin`, that the base folder contains
42
+ a subfolder ``model``.
43
+ 4. When using :class:`.ModelicaMixin`, that the toplevel Modelica model name
44
+ equals the class name.
42
45
 
43
46
  :param optimization_problem_class: Optimization problem class to solve.
44
47
  :param base_folder: Base folder.
@@ -51,36 +54,42 @@ def run_optimization_problem(optimization_problem_class,
51
54
  # Do some checks on the problem class
52
55
  if issubclass(optimization_problem_class, SimulationCSVMixin):
53
56
  raise ValueError(
54
- "Optimization problem class cannot be derived from simulation.csv_mixin.CSVMixin.")
57
+ "Optimization problem class cannot be derived from simulation.csv_mixin.CSVMixin."
58
+ )
55
59
  if issubclass(optimization_problem_class, SimulationIOMixin):
56
60
  raise ValueError(
57
- "Optimization problem class cannot be derived from simulation.csv_mixin.IOMixin.")
61
+ "Optimization problem class cannot be derived from simulation.csv_mixin.IOMixin."
62
+ )
58
63
  if issubclass(optimization_problem_class, SimulationPIMixin):
59
64
  raise ValueError(
60
- "Optimization problem class cannot be derived from simulation.csv_mixin.PIMixin.")
65
+ "Optimization problem class cannot be derived from simulation.csv_mixin.PIMixin."
66
+ )
61
67
 
62
68
  # Set input/output folders
63
69
  if not os.path.isabs(base_folder):
64
70
  # Resolve base folder relative to script folder
65
71
  base_folder = os.path.join(sys.path[0], base_folder)
66
72
 
67
- model_folder = _resolve_folder(kwargs, base_folder, 'model_folder', 'model')
68
- input_folder = _resolve_folder(kwargs, base_folder, 'input_folder', 'input')
69
- output_folder = _resolve_folder(kwargs, base_folder, 'output_folder', 'output')
73
+ model_folder = _resolve_folder(kwargs, base_folder, "model_folder", "model")
74
+ input_folder = _resolve_folder(kwargs, base_folder, "input_folder", "input")
75
+ output_folder = _resolve_folder(kwargs, base_folder, "output_folder", "output")
70
76
 
71
77
  # Set up logging
72
78
  logger = logging.getLogger("rtctools")
73
79
 
74
80
  # Add stream handler if it does not already exist.
75
- if not logger.hasHandlers() and not any((isinstance(h, logging.StreamHandler) for h in logger.handlers)):
81
+ if not logger.hasHandlers() and not any(
82
+ (isinstance(h, logging.StreamHandler) for h in logger.handlers)
83
+ ):
76
84
  handler = logging.StreamHandler()
77
- formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
85
+ formatter = logging.Formatter("%(asctime)s %(levelname)s %(message)s")
78
86
  handler.setFormatter(formatter)
79
87
  logger.addHandler(handler)
80
88
 
81
89
  # Add pi.DiagHandler, if using PIMixin. Only add it if it does not already exist.
82
- if (issubclass(optimization_problem_class, OptimizationPIMixin) and
83
- not any((isinstance(h, pi.DiagHandler) for h in logger.handlers))):
90
+ if issubclass(optimization_problem_class, OptimizationPIMixin) and not any(
91
+ (isinstance(h, pi.DiagHandler) for h in logger.handlers)
92
+ ):
84
93
  handler = pi.DiagHandler(output_folder)
85
94
  logger.addHandler(handler)
86
95
 
@@ -88,29 +97,42 @@ def run_optimization_problem(optimization_problem_class,
88
97
  logger.setLevel(log_level)
89
98
 
90
99
  # Log version info
91
- logger.info(
92
- "Using RTC-Tools {}.".format(__version__))
93
- logger.debug(
94
- "Using CasADi {}.".format(casadi.__version__))
100
+ logger.info("Using RTC-Tools {}.".format(__version__))
101
+ logger.debug("Using CasADi {}.".format(casadi.__version__))
95
102
 
96
103
  # Check for some common mistakes in inheritance order
97
- suggested_order = OrderedSet([
98
- 'HomotopyMixin',
99
- 'MinAbsGoalProgrammingMixin', 'LinearizedOrderGoalProgrammingMixin',
100
- 'SinglePassGoalProgrammingMixin', 'GoalProgrammingMixin',
101
- 'PIMixin', 'CSVMixin', 'ModelicaMixin',
102
- 'ControlTreeMixin', 'CollocatedIntegratedOptimizationProblem', 'OptimizationProblem'])
104
+ suggested_order = OrderedSet(
105
+ [
106
+ "HomotopyMixin",
107
+ "MinAbsGoalProgrammingMixin",
108
+ "LinearizedOrderGoalProgrammingMixin",
109
+ "SinglePassGoalProgrammingMixin",
110
+ "GoalProgrammingMixin",
111
+ "PIMixin",
112
+ "CSVMixin",
113
+ "ModelicaMixin",
114
+ "PlanningMixin",
115
+ "ControlTreeMixin",
116
+ "CollocatedIntegratedOptimizationProblem",
117
+ "OptimizationProblem",
118
+ ]
119
+ )
103
120
  base_names = OrderedSet([b.__name__ for b in optimization_problem_class.__bases__])
104
121
  if suggested_order & base_names != base_names & suggested_order:
105
- msg = 'Please inherit from base classes in the following order: {}'.format(list(base_names & suggested_order))
122
+ msg = "Please inherit from base classes in the following order: {}".format(
123
+ list(base_names & suggested_order)
124
+ )
106
125
  logger.error(msg)
107
126
  raise Exception(msg)
108
127
 
109
128
  # Run
110
129
  try:
111
130
  prob = optimization_problem_class(
112
- model_folder=model_folder, input_folder=input_folder, output_folder=output_folder,
113
- **kwargs)
131
+ model_folder=model_folder,
132
+ input_folder=input_folder,
133
+ output_folder=output_folder,
134
+ **kwargs,
135
+ )
114
136
  if profile:
115
137
  filename = os.path.join(base_folder, "profile.prof")
116
138
 
@@ -128,13 +150,15 @@ def run_optimization_problem(optimization_problem_class,
128
150
  value = exc_info[1]
129
151
  try:
130
152
  failed_class = re.search(
131
- "Can't instantiate (.*) with abstract methods", str(value)).group(1)
132
- abstract_method = re.search(
133
- ' with abstract methods (.*)', str(value)).group(1)
153
+ "Can't instantiate (.*) with abstract methods", str(value)
154
+ ).group(1)
155
+ abstract_method = re.search(" with abstract methods (.*)", str(value)).group(1)
134
156
  logger.error(
135
- 'The {} is missing a mixin. Please add a mixin that instantiates '
136
- 'abstract method {}, so that the optimizer can run.'.format(
137
- failed_class, abstract_method))
157
+ "The {} is missing a mixin. Please add a mixin that instantiates "
158
+ "abstract method {}, so that the optimizer can run.".format(
159
+ failed_class, abstract_method
160
+ )
161
+ )
138
162
  except Exception:
139
163
  pass
140
164
  for handler in logger.handlers:
@@ -142,15 +166,15 @@ def run_optimization_problem(optimization_problem_class,
142
166
  raise
143
167
 
144
168
 
145
- def run_simulation_problem(simulation_problem_class,
146
- base_folder='..', log_level=logging.INFO,
147
- **kwargs):
169
+ def run_simulation_problem(
170
+ simulation_problem_class, base_folder="..", log_level=logging.INFO, **kwargs
171
+ ):
148
172
  """
149
173
  Sets up and runs a simulation problem.
150
174
 
151
175
  :param simulation_problem_class: Simulation problem class to solve.
152
- :param base_folder: Folder within which subfolders "input", "output", and "model" exist,
153
- containing input and output data, and the model, respectively.
176
+ :param base_folder: Folder within which subfolders "input", "output", and "model"
177
+ exist, containing input and output data, and the model, respectively.
154
178
  :param log_level: The log level to use.
155
179
 
156
180
  :returns: :class:`SimulationProblem` instance.
@@ -159,13 +183,16 @@ def run_simulation_problem(simulation_problem_class,
159
183
  # Do some checks on the problem class
160
184
  if issubclass(simulation_problem_class, OptimizationCSVMixin):
161
185
  raise ValueError(
162
- "Simulation problem class cannot be derived from optimization.csv_mixin.CSVMixin.")
186
+ "Simulation problem class cannot be derived from optimization.csv_mixin.CSVMixin."
187
+ )
163
188
  if issubclass(simulation_problem_class, OptimizationIOMixin):
164
189
  raise ValueError(
165
- "Simulation problem class cannot be derived from optimization.csv_mixin.IOMixin.")
190
+ "Simulation problem class cannot be derived from optimization.csv_mixin.IOMixin."
191
+ )
166
192
  if issubclass(simulation_problem_class, OptimizationPIMixin):
167
193
  raise ValueError(
168
- "Simulation problem class cannot be derived from optimization.csv_mixin.PIMixin.")
194
+ "Simulation problem class cannot be derived from optimization.csv_mixin.PIMixin."
195
+ )
169
196
 
170
197
  # Set input/output folders
171
198
  if base_folder is None:
@@ -179,34 +206,35 @@ def run_simulation_problem(simulation_problem_class,
179
206
  # Resolve base folder relative to script folder
180
207
  base_folder = os.path.join(sys.path[0], base_folder)
181
208
 
182
- model_folder = _resolve_folder(kwargs, base_folder, 'model_folder', 'model')
183
- input_folder = _resolve_folder(kwargs, base_folder, 'input_folder', 'input')
184
- output_folder = _resolve_folder(kwargs, base_folder, 'output_folder', 'output')
209
+ model_folder = _resolve_folder(kwargs, base_folder, "model_folder", "model")
210
+ input_folder = _resolve_folder(kwargs, base_folder, "input_folder", "input")
211
+ output_folder = _resolve_folder(kwargs, base_folder, "output_folder", "output")
185
212
 
186
213
  # Set up logging
187
214
  logger = logging.getLogger("rtctools")
188
- if not logger.hasHandlers() and not any((isinstance(h, logging.StreamHandler) for h in logger.handlers)):
215
+ if not logger.hasHandlers() and not any(
216
+ (isinstance(h, logging.StreamHandler) for h in logger.handlers)
217
+ ):
189
218
  handler = logging.StreamHandler()
190
- formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
219
+ formatter = logging.Formatter("%(asctime)s %(levelname)s %(message)s")
191
220
  handler.setFormatter(formatter)
192
221
  logger.addHandler(handler)
193
222
 
194
223
  # Add pi.DiagHandler, if using PIMixin. Only add it if it does not already exist.
195
- if (issubclass(simulation_problem_class, SimulationPIMixin) and
196
- not any((isinstance(h, pi.DiagHandler) for h in logger.handlers))):
224
+ if issubclass(simulation_problem_class, SimulationPIMixin) and not any(
225
+ (isinstance(h, pi.DiagHandler) for h in logger.handlers)
226
+ ):
197
227
  handler = pi.DiagHandler(output_folder)
198
228
  logger.addHandler(handler)
199
229
 
200
230
  logger.setLevel(log_level)
201
231
 
202
- logger.info(
203
- 'Using RTC-Tools {}'.format(__version__))
204
- logger.debug(
205
- 'Using CasADi {}.'.format(casadi.__version__))
232
+ logger.info("Using RTC-Tools {}".format(__version__))
233
+ logger.debug("Using CasADi {}.".format(casadi.__version__))
206
234
 
207
235
  # Run
208
236
  prob = simulation_problem_class(
209
- model_folder=model_folder, input_folder=input_folder, output_folder=output_folder,
210
- **kwargs)
237
+ model_folder=model_folder, input_folder=input_folder, output_folder=output_folder, **kwargs
238
+ )
211
239
  prob.simulate()
212
240
  return prob
@@ -1,49 +0,0 @@
1
- rtctools/__init__.py,sha256=GzuYmrfvai2LnOnLGZUweYWn4SJQH9txwzwVO-ykvN4,106
2
- rtctools/_version.py,sha256=MbT8a-OnwVZRth24l2b35B12YzffQOVyu3w3qOPMFp0,500
3
- rtctools/rtctoolsapp.py,sha256=tK8hLfozegtH9kY5bmAox8lCE427uhxBWEp5pBqhiSA,4193
4
- rtctools/util.py,sha256=v2NLIB7NAqb_FvwNY2md7lgSXkfz_3M7xOuZcImM0Kw,8905
5
- rtctools/_internal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- rtctools/_internal/alias_tools.py,sha256=4lVd2S1gK3AlR5Wns79EVmTq4I2SSXIzUgeqL2VMIoo,5336
7
- rtctools/_internal/caching.py,sha256=CIJQ0oi-S2TQ7EM1oYzYN3CMfZe1F8R5-kIis1tNcIc,903
8
- rtctools/_internal/casadi_helpers.py,sha256=-hEgtp88koJSyok-_081i2QAzKKLGGVHcv5-4D2vRB8,2243
9
- rtctools/_internal/debug_check_helpers.py,sha256=YDPNB2yVY2Lkztoz8GabG0TX3-2CS0DNCIwMWQRT68Y,1084
10
- rtctools/data/__init__.py,sha256=k4WorSsD-Y8l2meIYHPaSOdGEgonribLkyoMASAhe90,157
11
- rtctools/data/csv.py,sha256=1pEYJ2Y0pxNFONH0iwacAbkKb3959lyqA_-jQ0O4CPo,4947
12
- rtctools/data/netcdf.py,sha256=QpAzAowSdmbJRkuPLCFbhoyGpecxZENhJi9Tjc7YDOY,18692
13
- rtctools/data/pi.py,sha256=RR66S-lQRPStDyMjF7ccam-LVvWpA92zGfKeEM2cpoo,43530
14
- rtctools/data/rtc.py,sha256=2cPDTuU0T4GiueG8ESHUPObtkDY9jahEBQ48Bc-CCeg,8853
15
- rtctools/data/storage.py,sha256=A2U1OuBzzTYADCN_BhLf9mmIQN4BZ_GNG_DdN_JoGoo,13011
16
- rtctools/data/interpolation/__init__.py,sha256=GBubCIT5mFoSTV-lOk7cpwvZekNMEe5bvqSQJ9HE34M,73
17
- rtctools/data/interpolation/bspline.py,sha256=xg1PqXlbpBZ5dPE5ngvdnJ7utSZyx8BgMqdDDLL8Hgw,958
18
- rtctools/data/interpolation/bspline1d.py,sha256=tNAQmTerjC0XWP5YQZZUp67jzVbOVmmyV6xzr81KL1g,5985
19
- rtctools/data/interpolation/bspline2d.py,sha256=RJO9XbjrNFNgkYjS88l-c4miu9xW1yroACpQ9v0u7bg,1607
20
- rtctools/optimization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
- rtctools/optimization/collocated_integrated_optimization_problem.py,sha256=TnxYTUJ9nGVxGs7Hrkk8y10PQEAU9kgA4qG66imIYdE,117456
22
- rtctools/optimization/control_tree_mixin.py,sha256=dZBEvhLToqiuwei5Nvv6ywXtaa08zgueKI5p4m-JyzQ,9026
23
- rtctools/optimization/csv_lookup_table_mixin.py,sha256=mEZdl1ca69K9ptJdKxCGIle4MrAwBTB4AJiVYQctyZg,16651
24
- rtctools/optimization/csv_mixin.py,sha256=FvMcuLlKu-YJo2NNudwMUUYKNb6HN4cevndWjlo5nis,11624
25
- rtctools/optimization/goal_programming_mixin.py,sha256=uzi2Kpr_i1ORfjB5Sta-mrMZXa3Xz0RCmG3AWsBn-L0,31608
26
- rtctools/optimization/goal_programming_mixin_base.py,sha256=NSyDuZD46fLadpM3tE-CXELStMBlH9IdlIaTkl_osOU,41999
27
- rtctools/optimization/homotopy_mixin.py,sha256=cgRPL-Ag9kd4iJQMbgKrRok-BUaRQwVJSCiAw_-1eck,6782
28
- rtctools/optimization/initial_state_estimation_mixin.py,sha256=CasRmqWVtyEpc4DwWcvpEcHBX7y0jsFERg5MSVb2FUo,3126
29
- rtctools/optimization/io_mixin.py,sha256=ZvltLXl1UON_GzlPVfkuvZvM2DUsz71B4HPVDoOSMgg,11817
30
- rtctools/optimization/linearization_mixin.py,sha256=ZG7553zowwSgl9Roe2yc24cp0DlqKkb2cmImGnaVGt0,1019
31
- rtctools/optimization/linearized_order_goal_programming_mixin.py,sha256=Aws3b0rnL-t8Bp_KOI9TbqqcuLb5ofSKKQMYjtUtLS0,8736
32
- rtctools/optimization/min_abs_goal_programming_mixin.py,sha256=kom9pV7Th5N31Adoc9RZRlQTcfqIzwui0PDe5AQnYuU,13293
33
- rtctools/optimization/modelica_mixin.py,sha256=usc9GZLLX8rjDIbIR9pI7m9wU7cwC8eXRszrvr8UN3I,16198
34
- rtctools/optimization/netcdf_mixin.py,sha256=fqhQSiSARQ4l6lwqp6ZDQ-SuIAeMPkQ69NcFnvk97C4,7259
35
- rtctools/optimization/optimization_problem.py,sha256=iUXcSz-jo4U9fhC3hWBLtkRosyrKg2LaTbYp46onL8w,43624
36
- rtctools/optimization/pi_mixin.py,sha256=QeHodXb5EO2Ueou8RUjeUfJMuv-cd55vCMi1dHuN4Q4,10783
37
- rtctools/optimization/single_pass_goal_programming_mixin.py,sha256=LxLquZYAnhR5wV39S3cgL3jKKQi4C3n6i0K55DETSdc,25126
38
- rtctools/optimization/timeseries.py,sha256=W2xYBZRZxKgOQ0aW_le5NDbXOBbokCeK-mjSUUa_EVs,1753
39
- rtctools/simulation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
- rtctools/simulation/csv_mixin.py,sha256=SIggsf7lfml3iWyhFSzCSCdxLt86ElluJQYxPYUkSiQ,6606
41
- rtctools/simulation/io_mixin.py,sha256=DizXxYg3MhOqyYXdHVlF9rLTfOo_aXc59Jh_hzGcgkc,6163
42
- rtctools/simulation/pi_mixin.py,sha256=ejHStj5LVILAnaqkoRGmXjxJ-XiUlV8L8-_VkmPEeGE,8922
43
- rtctools/simulation/simulation_problem.py,sha256=BiiijrKqD-G5QnFecs0vGHICD9QTxmfRZPEdwSrZtMM,35419
44
- rtc_tools-2.5.2rc3.dist-info/COPYING.LESSER,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
45
- rtc_tools-2.5.2rc3.dist-info/METADATA,sha256=EwEm47q4dRyM0yP77oEedzVBaMhPmbFazq8HKMsJWvk,1455
46
- rtc_tools-2.5.2rc3.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
47
- rtc_tools-2.5.2rc3.dist-info/entry_points.txt,sha256=-x622IB_l1duw2M6t6syfQ4yzOiQTp0IZxKGcYRgWgk,151
48
- rtc_tools-2.5.2rc3.dist-info/top_level.txt,sha256=pnBrb58PFPd1kp1dqa-JHU7R55h3alDNJIJnF3Jf9Dw,9
49
- rtc_tools-2.5.2rc3.dist-info/RECORD,,