hydraflow 0.12.0__py3-none-any.whl → 0.12.1__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.
hydraflow/core/main.py CHANGED
@@ -16,6 +16,7 @@ used to wrap experiment entry points. This decorator handles:
16
16
 
17
17
  Example:
18
18
  ```python
19
+ import hydraflow
19
20
  from dataclasses import dataclass
20
21
  from mlflow.entities import Run
21
22
 
@@ -24,7 +25,7 @@ Example:
24
25
  learning_rate: float
25
26
  batch_size: int
26
27
 
27
- @main(Config)
28
+ @hydraflow.main(Config)
28
29
  def train(run: Run, config: Config):
29
30
  # Your training code here
30
31
  pass
@@ -83,7 +83,7 @@ def count_decimal_places(x: str) -> int:
83
83
 
84
84
 
85
85
  def is_number(x: str) -> bool:
86
- """Check if a string is a number.
86
+ """Check if a string represents a valid number.
87
87
 
88
88
  Args:
89
89
  x (str): The string to check.
@@ -140,18 +140,54 @@ def _get_range(arg: str) -> tuple[float, float, float]:
140
140
 
141
141
 
142
142
  def _arange(start: float, step: float, stop: float) -> list[float]:
143
+ """Generate a range of floating point numbers.
144
+
145
+ This function generates a range of floating point numbers
146
+ with protection against rounding errors.
147
+
148
+ Args:
149
+ start (float): The starting value.
150
+ step (float): The step size.
151
+ stop (float): The end value (inclusive).
152
+
153
+ Returns:
154
+ list[float]: A list of floating point numbers from start to stop
155
+ (inclusive) with the given step.
156
+
157
+ """
158
+ if step == 0:
159
+ raise ValueError("Step cannot be zero")
160
+
161
+ epsilon = 1e-10
162
+
163
+ decimal_places = max(
164
+ count_decimal_places(str(start)),
165
+ count_decimal_places(str(step)),
166
+ count_decimal_places(str(stop)),
167
+ )
168
+
143
169
  result = []
144
170
  current = start
145
171
 
146
- while current <= stop if step > 0 else current >= stop:
147
- result.append(current)
148
- current += step
172
+ if step > 0:
173
+ while current <= stop + epsilon:
174
+ rounded = round(current, decimal_places)
175
+ result.append(rounded)
176
+ current += step
177
+ else:
178
+ while current >= stop - epsilon:
179
+ rounded = round(current, decimal_places)
180
+ result.append(rounded)
181
+ current += step
149
182
 
150
183
  return result
151
184
 
152
185
 
153
186
  def split_suffix(arg: str) -> tuple[str, str]:
154
- """Split a string into prefix and suffix.
187
+ """Split a string into the prefix and suffix.
188
+
189
+ The suffix is the part of the string that starts with a colon (:).
190
+ The prefix is the part of the string that precedes the suffix.
155
191
 
156
192
  Args:
157
193
  arg (str): The string to split.
@@ -194,6 +230,16 @@ def add_exponent(value: str, exponent: str) -> str:
194
230
  Returns:
195
231
  str: The value with the exponent added.
196
232
 
233
+ Examples:
234
+ >>> add_exponent("1", "e3")
235
+ '1e3'
236
+ >>> add_exponent("1", "")
237
+ '1'
238
+ >>> add_exponent("0", "e-3")
239
+ '0'
240
+ >>> add_exponent("0.0", "e-3")
241
+ '0.0'
242
+
197
243
  """
198
244
  if value in ["0", "0.", "0.0"] or not exponent:
199
245
  return value
@@ -201,43 +247,6 @@ def add_exponent(value: str, exponent: str) -> str:
201
247
  return f"{value}{exponent}"
202
248
 
203
249
 
204
- def collect_values(arg: str) -> list[str]:
205
- """Collect a list of values from a range argument.
206
-
207
- Collect all individual values within a numeric range
208
- represented by a string (e.g., `1:4`) and return them
209
- as a list of strings.
210
- Support both integer and floating-point ranges.
211
-
212
- Args:
213
- arg (str): The argument to collect.
214
-
215
- Returns:
216
- list[str]: A list of the collected values.
217
-
218
- """
219
- if "(" in arg:
220
- return collect_parentheses(arg)
221
-
222
- if ":" not in arg:
223
- return [arg]
224
-
225
- arg, exponent = split_suffix(arg)
226
-
227
- if ":" not in arg:
228
- return [f"{arg}{exponent}"]
229
-
230
- rng = _get_range(arg)
231
-
232
- if all(isinstance(x, int) for x in rng):
233
- values = [str(x) for x in _arange(*rng)]
234
- else:
235
- n = max(*(count_decimal_places(x) for x in arg.split(":")))
236
- values = [str(round(x, n)) for x in _arange(*rng)]
237
-
238
- return [add_exponent(x, exponent) for x in values]
239
-
240
-
241
250
  def split_parentheses(arg: str) -> Iterator[str]:
242
251
  """Split a string with parentheses into a list of strings.
243
252
 
@@ -290,8 +299,59 @@ def collect_parentheses(arg: str) -> list[str]:
290
299
  return ["".join(x[::-1]) for x in product(*it[::-1])]
291
300
 
292
301
 
302
+ def collect_values(arg: str) -> list[str]:
303
+ """Collect a list of values from a range argument.
304
+
305
+ Collect all individual values within a numeric range
306
+ represented by a string (e.g., `1:4`) and return them
307
+ as a list of strings.
308
+ Support both integer and floating-point ranges.
309
+
310
+ Args:
311
+ arg (str): The argument to collect.
312
+
313
+ Returns:
314
+ list[str]: A list of the collected values.
315
+
316
+ Examples:
317
+ >>> collect_values("1:4")
318
+ ['1', '2', '3', '4']
319
+ >>> collect_values("1.2:0.1:1.4:k")
320
+ ['1.2e3', '1.3e3', '1.4e3']
321
+ >>> collect_values("0.1")
322
+ ['0.1']
323
+ >>> collect_values("4:M")
324
+ ['4e6']
325
+ >>> collect_values("(1:3,5:7)M")
326
+ ['1e6', '2e6', '3e6', '5e6', '6e6', '7e6']
327
+ >>> collect_values("(1,5)e-(1:3)")
328
+ ['1e-1', '5e-1', '1e-2', '5e-2', '1e-3', '5e-3']
329
+
330
+ """
331
+ if "(" in arg:
332
+ return collect_parentheses(arg)
333
+
334
+ if ":" not in arg:
335
+ return [arg]
336
+
337
+ arg, exponent = split_suffix(arg)
338
+
339
+ if ":" not in arg:
340
+ return [f"{arg}{exponent}"]
341
+
342
+ rng = _get_range(arg)
343
+
344
+ if all(isinstance(x, int) for x in rng):
345
+ values = [str(x) for x in _arange(*rng)]
346
+ else:
347
+ n = max(*(count_decimal_places(x) for x in arg.split(":")))
348
+ values = [str(round(x, n)) for x in _arange(*rng)]
349
+
350
+ return [add_exponent(x, exponent) for x in values]
351
+
352
+
293
353
  def split(arg: str) -> list[str]:
294
- r"""Split a string by top-level commas.
354
+ """Split a string by top-level commas.
295
355
 
296
356
  Splits a string by commas while respecting nested structures.
297
357
  Commas inside brackets and quotes are ignored, only splitting
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hydraflow
3
- Version: 0.12.0
3
+ Version: 0.12.1
4
4
  Summary: Hydraflow integrates Hydra and MLflow to manage and track machine learning experiments.
5
5
  Project-URL: Documentation, https://daizutabi.github.io/hydraflow/
6
6
  Project-URL: Source, https://github.com/daizutabi/hydraflow
@@ -5,7 +5,7 @@ hydraflow/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  hydraflow/core/config.py,sha256=SJzjgsO_kzB78_whJ3lmy7GlZvTvwZONH1BJBn8zCuI,3817
6
6
  hydraflow/core/context.py,sha256=QPyPg1xrTlmhviKNn-0nDY9bXcVky1zInqRqPN-VNhc,4741
7
7
  hydraflow/core/io.py,sha256=C207DsGAU4CLvlHySyyIl0_aKZ83ysJ-W_wNM2n4RPI,6754
8
- hydraflow/core/main.py,sha256=500fh5cnlKj9CHFgD8-f16wZcOuPF-5zSvFeVMqI8MQ,5100
8
+ hydraflow/core/main.py,sha256=66-X2-IJVEcJ4XrEC2BIKNzdd_M1RfVIAHME8k70Jo0,5131
9
9
  hydraflow/core/mlflow.py,sha256=M3MhiChnMzKnKRmjBl4h_SRGkAZKL7GAmFr3DdzwRuQ,5666
10
10
  hydraflow/core/param.py,sha256=LHU9j9_7oA99igasoOyKofKClVr9FmGA3UABJ-KmyS0,4538
11
11
  hydraflow/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -16,9 +16,9 @@ hydraflow/executor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuF
16
16
  hydraflow/executor/conf.py,sha256=2dv6_PlsynRmia-fGZlmBEVt8GopT0f32N13qY7tYnM,402
17
17
  hydraflow/executor/io.py,sha256=yZMcBVmAbPZZ82cAXhgiJfj9p8WvHmzOCMBg_vtEVek,1509
18
18
  hydraflow/executor/job.py,sha256=IL7ek0Vwa3Bl_gANq0wCbldNCUclo8YBckeEeO6W6xg,4852
19
- hydraflow/executor/parser.py,sha256=llbv6BLPyO5UlExeRibkYI0vaxZbqS4q3uPZ1NnkIDM,11891
20
- hydraflow-0.12.0.dist-info/METADATA,sha256=-CLwckmFxrCb9GEyhoz1ZaSaChVQU5_pQ0zkCCqfUMw,4549
21
- hydraflow-0.12.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
22
- hydraflow-0.12.0.dist-info/entry_points.txt,sha256=XI0khPbpCIUo9UPqkNEpgh-kqK3Jy8T7L2VCWOdkbSM,48
23
- hydraflow-0.12.0.dist-info/licenses/LICENSE,sha256=IGdDrBPqz1O0v_UwCW-NJlbX9Hy9b3uJ11t28y2srmY,1062
24
- hydraflow-0.12.0.dist-info/RECORD,,
19
+ hydraflow/executor/parser.py,sha256=YiA-Upn7H39BZYyvmCumtXXS27an6aDdHKkaF7Nl8Vk,13617
20
+ hydraflow-0.12.1.dist-info/METADATA,sha256=DWSgcm2oCZt8udPqgoTpQJzyIepIrjfujSggYn3MZ_U,4549
21
+ hydraflow-0.12.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
22
+ hydraflow-0.12.1.dist-info/entry_points.txt,sha256=XI0khPbpCIUo9UPqkNEpgh-kqK3Jy8T7L2VCWOdkbSM,48
23
+ hydraflow-0.12.1.dist-info/licenses/LICENSE,sha256=IGdDrBPqz1O0v_UwCW-NJlbX9Hy9b3uJ11t28y2srmY,1062
24
+ hydraflow-0.12.1.dist-info/RECORD,,