hydraflow 0.12.0__py3-none-any.whl → 0.12.2__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
@@ -48,7 +48,7 @@ def to_number(x: str) -> int | float:
48
48
  return int(x)
49
49
 
50
50
 
51
- def count_decimal_places(x: str) -> int:
51
+ def count_decimal_digits(x: str) -> int:
52
52
  """Count decimal places in a string.
53
53
 
54
54
  Examine a string representing a number and returns the count
@@ -62,13 +62,13 @@ def count_decimal_places(x: str) -> int:
62
62
  int: The number of decimal places.
63
63
 
64
64
  Examples:
65
- >>> count_decimal_places("1")
65
+ >>> count_decimal_digits("1")
66
66
  0
67
- >>> count_decimal_places("-1.2")
67
+ >>> count_decimal_digits("-1.2")
68
68
  1
69
- >>> count_decimal_places("1.234")
69
+ >>> count_decimal_digits("1.234")
70
70
  3
71
- >>> count_decimal_places("-1.234e-10")
71
+ >>> count_decimal_digits("-1.234e-10")
72
72
  3
73
73
 
74
74
  """
@@ -82,8 +82,52 @@ def count_decimal_places(x: str) -> int:
82
82
  return len(decimal_part)
83
83
 
84
84
 
85
+ def count_integer_digits(num_str: str) -> int:
86
+ """Count the number of digits in the integer part of a number.
87
+
88
+ Consider only the integer part of a number, even if it is in
89
+ scientific notation.
90
+
91
+ Args:
92
+ num_str (str): The string representing a number.
93
+
94
+ Returns:
95
+ int: The number of digits in the integer part of a number.
96
+ (excluding the sign)
97
+
98
+ Examples:
99
+ >>> count_integer_digits("123")
100
+ 3
101
+ >>> count_integer_digits("-123.45")
102
+ 3
103
+ >>> count_integer_digits("+0.00123")
104
+ 1
105
+ >>> count_integer_digits("-1.200")
106
+ 1
107
+ >>> count_integer_digits("+1.20e3")
108
+ 1
109
+ >>> count_integer_digits("-0.120e-3")
110
+ 1
111
+ >>> count_integer_digits(".123")
112
+ 0
113
+
114
+ """
115
+ if num_str.startswith(("+", "-")):
116
+ num_str = num_str[1:]
117
+
118
+ if "e" in num_str.lower():
119
+ num_str = num_str.lower().split("e")[0]
120
+
121
+ if "." in num_str:
122
+ int_part = num_str.split(".")[0]
123
+ if not int_part:
124
+ return 0
125
+ return len(int_part)
126
+ return len(num_str)
127
+
128
+
85
129
  def is_number(x: str) -> bool:
86
- """Check if a string is a number.
130
+ """Check if a string represents a valid number.
87
131
 
88
132
  Args:
89
133
  x (str): The string to check.
@@ -140,18 +184,46 @@ def _get_range(arg: str) -> tuple[float, float, float]:
140
184
 
141
185
 
142
186
  def _arange(start: float, step: float, stop: float) -> list[float]:
187
+ """Generate a range of floating point numbers.
188
+
189
+ This function generates a range of floating point numbers
190
+ with protection against rounding errors.
191
+
192
+ Args:
193
+ start (float): The starting value.
194
+ step (float): The step size.
195
+ stop (float): The end value (inclusive).
196
+
197
+ Returns:
198
+ list[float]: A list of floating point numbers from start to stop
199
+ (inclusive) with the given step.
200
+
201
+ """
202
+ if step == 0:
203
+ raise ValueError("Step cannot be zero")
204
+
205
+ epsilon = min(abs(start), abs(stop)) * 1e-5
206
+
143
207
  result = []
144
208
  current = start
145
209
 
146
- while current <= stop if step > 0 else current >= stop:
147
- result.append(current)
148
- current += step
210
+ if step > 0:
211
+ while current <= stop + epsilon:
212
+ result.append(current)
213
+ current += step
214
+ else:
215
+ while current >= stop - epsilon:
216
+ result.append(current)
217
+ current += step
149
218
 
150
219
  return result
151
220
 
152
221
 
153
222
  def split_suffix(arg: str) -> tuple[str, str]:
154
- """Split a string into prefix and suffix.
223
+ """Split a string into the prefix and suffix.
224
+
225
+ The suffix is the part of the string that starts with a colon (:).
226
+ The prefix is the part of the string that precedes the suffix.
155
227
 
156
228
  Args:
157
229
  arg (str): The string to split.
@@ -194,6 +266,16 @@ def add_exponent(value: str, exponent: str) -> str:
194
266
  Returns:
195
267
  str: The value with the exponent added.
196
268
 
269
+ Examples:
270
+ >>> add_exponent("1", "e3")
271
+ '1e3'
272
+ >>> add_exponent("1", "")
273
+ '1'
274
+ >>> add_exponent("0", "e-3")
275
+ '0'
276
+ >>> add_exponent("0.0", "e-3")
277
+ '0.0'
278
+
197
279
  """
198
280
  if value in ["0", "0.", "0.0"] or not exponent:
199
281
  return value
@@ -201,43 +283,6 @@ def add_exponent(value: str, exponent: str) -> str:
201
283
  return f"{value}{exponent}"
202
284
 
203
285
 
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
286
  def split_parentheses(arg: str) -> Iterator[str]:
242
287
  """Split a string with parentheses into a list of strings.
243
288
 
@@ -290,8 +335,60 @@ def collect_parentheses(arg: str) -> list[str]:
290
335
  return ["".join(x[::-1]) for x in product(*it[::-1])]
291
336
 
292
337
 
338
+ def collect_values(arg: str) -> list[str]:
339
+ """Collect a list of values from a range argument.
340
+
341
+ Collect all individual values within a numeric range
342
+ represented by a string (e.g., `1:4`) and return them
343
+ as a list of strings.
344
+ Support both integer and floating-point ranges.
345
+
346
+ Args:
347
+ arg (str): The argument to collect.
348
+
349
+ Returns:
350
+ list[str]: A list of the collected values.
351
+
352
+ Examples:
353
+ >>> collect_values("1:4")
354
+ ['1', '2', '3', '4']
355
+ >>> collect_values("1.2:0.1:1.4:k")
356
+ ['1.2e3', '1.3e3', '1.4e3']
357
+ >>> collect_values("0.1")
358
+ ['0.1']
359
+ >>> collect_values("4:M")
360
+ ['4e6']
361
+ >>> collect_values("(1:3,5:7)M")
362
+ ['1e6', '2e6', '3e6', '5e6', '6e6', '7e6']
363
+ >>> collect_values("(1,5)e-(1:3)")
364
+ ['1e-1', '5e-1', '1e-2', '5e-2', '1e-3', '5e-3']
365
+
366
+ """
367
+ if "(" in arg:
368
+ return collect_parentheses(arg)
369
+
370
+ if ":" not in arg:
371
+ return [arg]
372
+
373
+ arg, exponent = split_suffix(arg)
374
+
375
+ if ":" not in arg:
376
+ return [f"{arg}{exponent}"]
377
+
378
+ rng = _get_range(arg)
379
+
380
+ if all(isinstance(x, int) for x in rng):
381
+ values = [str(x) for x in _arange(*rng)]
382
+ else:
383
+ n = max(*(count_integer_digits(x) for x in arg.split(":")))
384
+ m = max(*(count_decimal_digits(x) for x in arg.split(":")))
385
+ values = [f"{x:.{n + m}g}" for x in _arange(*rng)]
386
+
387
+ return [add_exponent(x, exponent) for x in values]
388
+
389
+
293
390
  def split(arg: str) -> list[str]:
294
- r"""Split a string by top-level commas.
391
+ """Split a string by top-level commas.
295
392
 
296
393
  Splits a string by commas while respecting nested structures.
297
394
  Commas inside brackets and quotes are ignored, only splitting
@@ -355,8 +452,9 @@ def split(arg: str) -> list[str]:
355
452
  def expand_values(arg: str, suffix: str = "") -> Iterator[str]:
356
453
  """Expand a string argument into a list of values.
357
454
 
358
- Take a string containing comma-separated values or ranges and return a list
359
- of all individual values. Handle numeric ranges and special characters.
455
+ Take a string containing comma-separated values or ranges
456
+ and return a list of all individual values.
457
+ Handle numeric ranges and special characters.
360
458
 
361
459
  Args:
362
460
  arg (str): The argument to expand.
@@ -379,7 +477,8 @@ def split_arg(arg: str) -> tuple[str, str, str]:
379
477
  arg (str): The argument to split.
380
478
 
381
479
  Returns:
382
- tuple[str, str, str]: A tuple containing the key, suffix, and value.
480
+ tuple[str, str, str]: A tuple containing the key,
481
+ suffix, and value.
383
482
 
384
483
  """
385
484
  if "=" not in arg:
@@ -398,8 +497,9 @@ def split_arg(arg: str) -> tuple[str, str, str]:
398
497
  def collect_arg(arg: str) -> str:
399
498
  """Collect a string of expanded key-value pairs.
400
499
 
401
- Take a key-value pair argument and concatenates all expanded values with commas,
402
- returning a single string suitable for command-line usage.
500
+ Take a key-value pair argument and concatenates all expanded
501
+ values with commas, returning a single string suitable for
502
+ command-line usage.
403
503
 
404
504
  Args:
405
505
  arg (str): The argument to collect.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hydraflow
3
- Version: 0.12.0
3
+ Version: 0.12.2
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=_Rfund3FDgrXitTt_znsTpgEtMDqZ_ICynaB_Zje14Q,14561
20
+ hydraflow-0.12.2.dist-info/METADATA,sha256=8i5Ejzdakw6X9t6ddhuNGW0DaeQT9N3-xVCWrmX1QfQ,4549
21
+ hydraflow-0.12.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
22
+ hydraflow-0.12.2.dist-info/entry_points.txt,sha256=XI0khPbpCIUo9UPqkNEpgh-kqK3Jy8T7L2VCWOdkbSM,48
23
+ hydraflow-0.12.2.dist-info/licenses/LICENSE,sha256=IGdDrBPqz1O0v_UwCW-NJlbX9Hy9b3uJ11t28y2srmY,1062
24
+ hydraflow-0.12.2.dist-info/RECORD,,