dycw-utilities 0.135.0__py3-none-any.whl → 0.178.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.

Potentially problematic release.


This version of dycw-utilities might be problematic. Click here for more details.

Files changed (97) hide show
  1. dycw_utilities-0.178.1.dist-info/METADATA +34 -0
  2. dycw_utilities-0.178.1.dist-info/RECORD +105 -0
  3. dycw_utilities-0.178.1.dist-info/WHEEL +4 -0
  4. dycw_utilities-0.178.1.dist-info/entry_points.txt +4 -0
  5. utilities/__init__.py +1 -1
  6. utilities/altair.py +13 -10
  7. utilities/asyncio.py +312 -787
  8. utilities/atomicwrites.py +18 -6
  9. utilities/atools.py +64 -4
  10. utilities/cachetools.py +9 -6
  11. utilities/click.py +195 -77
  12. utilities/concurrent.py +1 -1
  13. utilities/contextlib.py +216 -17
  14. utilities/contextvars.py +20 -1
  15. utilities/cryptography.py +3 -3
  16. utilities/dataclasses.py +15 -28
  17. utilities/docker.py +387 -0
  18. utilities/enum.py +2 -2
  19. utilities/errors.py +17 -3
  20. utilities/fastapi.py +28 -59
  21. utilities/fpdf2.py +2 -2
  22. utilities/functions.py +24 -269
  23. utilities/git.py +9 -30
  24. utilities/grp.py +28 -0
  25. utilities/gzip.py +31 -0
  26. utilities/http.py +3 -2
  27. utilities/hypothesis.py +513 -159
  28. utilities/importlib.py +17 -1
  29. utilities/inflect.py +12 -4
  30. utilities/iterables.py +33 -58
  31. utilities/jinja2.py +148 -0
  32. utilities/json.py +70 -0
  33. utilities/libcst.py +38 -17
  34. utilities/lightweight_charts.py +4 -7
  35. utilities/logging.py +136 -93
  36. utilities/math.py +8 -4
  37. utilities/more_itertools.py +43 -45
  38. utilities/operator.py +27 -27
  39. utilities/orjson.py +189 -36
  40. utilities/os.py +61 -4
  41. utilities/packaging.py +115 -0
  42. utilities/parse.py +8 -5
  43. utilities/pathlib.py +269 -40
  44. utilities/permissions.py +298 -0
  45. utilities/platform.py +7 -6
  46. utilities/polars.py +1205 -413
  47. utilities/polars_ols.py +1 -1
  48. utilities/postgres.py +408 -0
  49. utilities/pottery.py +43 -19
  50. utilities/pqdm.py +3 -3
  51. utilities/psutil.py +5 -57
  52. utilities/pwd.py +28 -0
  53. utilities/pydantic.py +4 -52
  54. utilities/pydantic_settings.py +240 -0
  55. utilities/pydantic_settings_sops.py +76 -0
  56. utilities/pyinstrument.py +7 -7
  57. utilities/pytest.py +104 -143
  58. utilities/pytest_plugins/__init__.py +1 -0
  59. utilities/pytest_plugins/pytest_randomly.py +23 -0
  60. utilities/pytest_plugins/pytest_regressions.py +56 -0
  61. utilities/pytest_regressions.py +26 -46
  62. utilities/random.py +11 -6
  63. utilities/re.py +1 -1
  64. utilities/redis.py +220 -343
  65. utilities/sentinel.py +10 -0
  66. utilities/shelve.py +4 -1
  67. utilities/shutil.py +25 -0
  68. utilities/slack_sdk.py +35 -104
  69. utilities/sqlalchemy.py +496 -471
  70. utilities/sqlalchemy_polars.py +29 -54
  71. utilities/string.py +2 -3
  72. utilities/subprocess.py +1977 -0
  73. utilities/tempfile.py +112 -4
  74. utilities/testbook.py +50 -0
  75. utilities/text.py +174 -42
  76. utilities/throttle.py +158 -0
  77. utilities/timer.py +2 -2
  78. utilities/traceback.py +70 -35
  79. utilities/types.py +102 -30
  80. utilities/typing.py +479 -19
  81. utilities/uuid.py +42 -5
  82. utilities/version.py +27 -26
  83. utilities/whenever.py +1559 -361
  84. utilities/zoneinfo.py +80 -22
  85. dycw_utilities-0.135.0.dist-info/METADATA +0 -39
  86. dycw_utilities-0.135.0.dist-info/RECORD +0 -96
  87. dycw_utilities-0.135.0.dist-info/WHEEL +0 -4
  88. dycw_utilities-0.135.0.dist-info/licenses/LICENSE +0 -21
  89. utilities/aiolimiter.py +0 -25
  90. utilities/arq.py +0 -216
  91. utilities/eventkit.py +0 -388
  92. utilities/luigi.py +0 -183
  93. utilities/period.py +0 -152
  94. utilities/pudb.py +0 -62
  95. utilities/python_dotenv.py +0 -101
  96. utilities/streamlit.py +0 -105
  97. utilities/typed_settings.py +0 -123
utilities/hypothesis.py CHANGED
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import builtins
4
+ import datetime as dt
4
5
  from contextlib import contextmanager
5
6
  from dataclasses import dataclass
6
7
  from enum import Enum, auto
@@ -31,6 +32,7 @@ from hypothesis.strategies import (
31
32
  sampled_from,
32
33
  sets,
33
34
  text,
35
+ timezones,
34
36
  uuids,
35
37
  )
36
38
  from hypothesis.utils.conventions import not_set
@@ -38,46 +40,53 @@ from whenever import (
38
40
  Date,
39
41
  DateDelta,
40
42
  DateTimeDelta,
43
+ MonthDay,
41
44
  PlainDateTime,
42
45
  RepeatedTime,
43
46
  SkippedTime,
44
47
  Time,
45
48
  TimeDelta,
46
49
  TimeZoneNotFoundError,
50
+ YearMonth,
47
51
  ZonedDateTime,
48
52
  )
49
53
 
50
- from utilities.functions import ensure_int, ensure_str
54
+ from utilities.functions import ensure_int, ensure_str, max_nullable, min_nullable
51
55
  from utilities.math import (
52
56
  MAX_FLOAT32,
53
57
  MAX_FLOAT64,
58
+ MAX_INT8,
59
+ MAX_INT16,
54
60
  MAX_INT32,
55
61
  MAX_INT64,
62
+ MAX_UINT8,
63
+ MAX_UINT16,
56
64
  MAX_UINT32,
57
65
  MAX_UINT64,
58
66
  MIN_FLOAT32,
59
67
  MIN_FLOAT64,
68
+ MIN_INT8,
69
+ MIN_INT16,
60
70
  MIN_INT32,
61
71
  MIN_INT64,
72
+ MIN_UINT8,
73
+ MIN_UINT16,
62
74
  MIN_UINT32,
63
75
  MIN_UINT64,
64
76
  is_zero,
65
77
  )
66
78
  from utilities.os import get_env_var
67
- from utilities.pathlib import temp_cwd
68
- from utilities.platform import IS_WINDOWS
69
- from utilities.sentinel import Sentinel, sentinel
79
+ from utilities.pathlib import module_path, temp_cwd
80
+ from utilities.permissions import Permissions
81
+ from utilities.platform import IS_LINUX
82
+ from utilities.sentinel import Sentinel, is_sentinel, sentinel
70
83
  from utilities.tempfile import TEMP_DIR, TemporaryDirectory
71
- from utilities.types import DateTimeRoundUnit
72
- from utilities.typing import get_literal_elements
73
84
  from utilities.version import Version
74
85
  from utilities.whenever import (
75
86
  DATE_DELTA_MAX,
76
87
  DATE_DELTA_MIN,
77
88
  DATE_DELTA_PARSABLE_MAX,
78
89
  DATE_DELTA_PARSABLE_MIN,
79
- DATE_MAX,
80
- DATE_MIN,
81
90
  DATE_TIME_DELTA_MAX,
82
91
  DATE_TIME_DELTA_MIN,
83
92
  DATE_TIME_DELTA_PARSABLE_MAX,
@@ -85,31 +94,29 @@ from utilities.whenever import (
85
94
  DATE_TWO_DIGIT_YEAR_MAX,
86
95
  DATE_TWO_DIGIT_YEAR_MIN,
87
96
  DAY,
88
- MONTH_MAX,
89
- MONTH_MIN,
90
- PLAIN_DATE_TIME_MAX,
91
- PLAIN_DATE_TIME_MIN,
92
97
  TIME_DELTA_MAX,
93
98
  TIME_DELTA_MIN,
94
- TIME_MAX,
95
- TIME_MIN,
96
- Freq,
97
- Month,
99
+ DatePeriod,
100
+ TimePeriod,
101
+ ZonedDateTimePeriod,
102
+ get_now,
98
103
  to_date_time_delta,
99
104
  to_days,
100
- to_nanos,
105
+ to_nanoseconds,
101
106
  )
102
- from utilities.zoneinfo import UTC, ensure_time_zone
107
+ from utilities.zoneinfo import UTC, to_zone_info
103
108
 
104
109
  if TYPE_CHECKING:
105
- import datetime as dt
106
110
  from collections.abc import Collection, Hashable, Iterable, Iterator
111
+ from zoneinfo import ZoneInfo
107
112
 
108
113
  from hypothesis.database import ExampleDatabase
114
+ from libcst import Import, ImportFrom
109
115
  from numpy.random import RandomState
116
+ from sqlalchemy import URL
110
117
 
111
118
  from utilities.numpy import NDArrayB, NDArrayF, NDArrayI, NDArrayO
112
- from utilities.types import Number, TimeZoneLike
119
+ from utilities.types import Number, TimeZone, TimeZoneLike
113
120
 
114
121
 
115
122
  type MaybeSearchStrategy[_T] = _T | SearchStrategy[_T]
@@ -184,14 +191,14 @@ def date_deltas(
184
191
  min_value_ = DATE_DELTA_MIN
185
192
  case DateDelta():
186
193
  ...
187
- case _ as never:
194
+ case never:
188
195
  assert_never(never)
189
196
  match max_value_:
190
197
  case None:
191
198
  max_value_ = DATE_DELTA_MAX
192
199
  case DateDelta():
193
200
  ...
194
- case _ as never:
201
+ case never:
195
202
  assert_never(never)
196
203
  min_days = to_days(min_value_)
197
204
  max_days = to_days(max_value_)
@@ -205,6 +212,26 @@ def date_deltas(
205
212
  ##
206
213
 
207
214
 
215
+ @composite
216
+ def date_periods(
217
+ draw: DrawFn,
218
+ /,
219
+ *,
220
+ min_value: MaybeSearchStrategy[Date | None] = None,
221
+ max_value: MaybeSearchStrategy[Date | None] = None,
222
+ two_digit: MaybeSearchStrategy[bool] = False,
223
+ ) -> DatePeriod:
224
+ """Strategy for generating date periods."""
225
+ min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
226
+ two_digit_ = draw2(draw, two_digit)
227
+ strategy = dates(min_value=min_value_, max_value=max_value_, two_digit=two_digit_)
228
+ start, end = draw(pairs(strategy, sorted=True))
229
+ return DatePeriod(start, end)
230
+
231
+
232
+ ##
233
+
234
+
208
235
  @composite
209
236
  def date_time_deltas(
210
237
  draw: DrawFn,
@@ -213,6 +240,7 @@ def date_time_deltas(
213
240
  min_value: MaybeSearchStrategy[DateTimeDelta | None] = None,
214
241
  max_value: MaybeSearchStrategy[DateTimeDelta | None] = None,
215
242
  parsable: MaybeSearchStrategy[bool] = False,
243
+ nativable: MaybeSearchStrategy[bool] = False,
216
244
  ) -> DateTimeDelta:
217
245
  """Strategy for generating date deltas."""
218
246
  min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
@@ -221,20 +249,26 @@ def date_time_deltas(
221
249
  min_value_ = DATE_TIME_DELTA_MIN
222
250
  case DateTimeDelta():
223
251
  ...
224
- case _ as never:
252
+ case never:
225
253
  assert_never(never)
226
254
  match max_value_:
227
255
  case None:
228
256
  max_value_ = DATE_TIME_DELTA_MAX
229
257
  case DateTimeDelta():
230
258
  ...
231
- case _ as never:
259
+ case never:
232
260
  assert_never(never)
233
- min_nanos, max_nanos = map(to_nanos, [min_value_, max_value_])
261
+ min_nanos, max_nanos = map(to_nanoseconds, [min_value_, max_value_])
234
262
  if draw2(draw, parsable):
235
- min_nanos = max(min_nanos, to_nanos(DATE_TIME_DELTA_PARSABLE_MIN))
236
- max_nanos = min(max_nanos, to_nanos(DATE_TIME_DELTA_PARSABLE_MAX))
237
- nanos = draw(integers(min_value=min_nanos, max_value=max_nanos))
263
+ min_nanos = max(min_nanos, to_nanoseconds(DATE_TIME_DELTA_PARSABLE_MIN))
264
+ max_nanos = min(max_nanos, to_nanoseconds(DATE_TIME_DELTA_PARSABLE_MAX))
265
+ if draw2(draw, nativable):
266
+ min_micros, _ = divmod(min_nanos, 1000)
267
+ max_micros, _ = divmod(max_nanos, 1000)
268
+ micros = draw(integers(min_value=min_micros + 1, max_value=max_micros))
269
+ nanos = 1000 * micros
270
+ else:
271
+ nanos = draw(integers(min_value=min_nanos, max_value=max_nanos))
238
272
  return to_date_time_delta(nanos)
239
273
 
240
274
 
@@ -254,17 +288,17 @@ def dates(
254
288
  min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
255
289
  match min_value_:
256
290
  case None:
257
- min_value_ = DATE_MIN
291
+ min_value_ = Date.MIN
258
292
  case Date():
259
293
  ...
260
- case _ as never:
294
+ case never:
261
295
  assert_never(never)
262
296
  match max_value_:
263
297
  case None:
264
- max_value_ = DATE_MAX
298
+ max_value_ = Date.MAX
265
299
  case Date():
266
300
  ...
267
- case _ as never:
301
+ case never:
268
302
  assert_never(never)
269
303
  if draw2(draw, two_digit):
270
304
  min_value_ = max(min_value_, DATE_TWO_DIGIT_YEAR_MIN)
@@ -333,21 +367,21 @@ def draw2[T](
333
367
  return value
334
368
  case None, SearchStrategy(), False:
335
369
  value2 = draw(default)
336
- if isinstance(value2, Sentinel):
370
+ if is_sentinel(value2):
337
371
  raise _Draw2DefaultGeneratedSentinelError
338
372
  return value2
339
373
  case Sentinel(), None, _:
340
374
  raise _Draw2InputResolvedToSentinelError
341
375
  case Sentinel(), SearchStrategy(), True:
342
376
  value2 = draw(default)
343
- if isinstance(value2, Sentinel):
377
+ if is_sentinel(value2):
344
378
  raise _Draw2DefaultGeneratedSentinelError
345
379
  return value2
346
380
  case Sentinel(), SearchStrategy(), False:
347
381
  raise _Draw2InputResolvedToSentinelError
348
382
  case _, _, _:
349
383
  return value
350
- case _ as never:
384
+ case never:
351
385
  assert_never(never)
352
386
 
353
387
 
@@ -377,16 +411,27 @@ def float32s(
377
411
  draw: DrawFn,
378
412
  /,
379
413
  *,
380
- min_value: MaybeSearchStrategy[float] = MIN_FLOAT32,
381
- max_value: MaybeSearchStrategy[float] = MAX_FLOAT32,
414
+ min_value: MaybeSearchStrategy[float | None] = None,
415
+ max_value: MaybeSearchStrategy[float | None] = None,
416
+ exclude_min: MaybeSearchStrategy[bool] = False,
417
+ exclude_max: MaybeSearchStrategy[bool] = False,
382
418
  ) -> float:
383
419
  """Strategy for generating float32s."""
384
420
  min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
385
- min_value_ = max(min_value_, MIN_FLOAT32)
386
- max_value_ = min(max_value_, MAX_FLOAT32)
421
+ min_value_ = max_nullable([min_value_, MIN_FLOAT32])
422
+ max_value_ = min_nullable([max_value_, MAX_FLOAT32])
387
423
  if is_zero(min_value_) and is_zero(max_value_):
388
424
  min_value_ = max_value_ = 0.0
389
- return draw(floats(min_value_, max_value_, width=32))
425
+ exclude_min_, exclude_max_ = [draw2(draw, e) for e in [exclude_min, exclude_max]]
426
+ return draw(
427
+ floats(
428
+ min_value_,
429
+ max_value_,
430
+ width=32,
431
+ exclude_min=exclude_min_,
432
+ exclude_max=exclude_max_,
433
+ )
434
+ )
390
435
 
391
436
 
392
437
  @composite
@@ -394,16 +439,27 @@ def float64s(
394
439
  draw: DrawFn,
395
440
  /,
396
441
  *,
397
- min_value: MaybeSearchStrategy[float] = MIN_FLOAT64,
398
- max_value: MaybeSearchStrategy[float] = MAX_FLOAT64,
442
+ min_value: MaybeSearchStrategy[float | None] = None,
443
+ max_value: MaybeSearchStrategy[float | None] = None,
444
+ exclude_min: MaybeSearchStrategy[bool] = False,
445
+ exclude_max: MaybeSearchStrategy[bool] = False,
399
446
  ) -> float:
400
447
  """Strategy for generating float64s."""
401
448
  min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
402
- min_value_ = max(min_value_, MIN_FLOAT64)
403
- max_value_ = min(max_value_, MAX_FLOAT64)
449
+ min_value_ = max_nullable([min_value_, MIN_FLOAT64])
450
+ max_value_ = min_nullable([max_value_, MAX_FLOAT64])
404
451
  if is_zero(min_value_) and is_zero(max_value_):
405
452
  min_value_ = max_value_ = 0.0
406
- return draw(floats(min_value_, max_value_, width=64))
453
+ exclude_min_, exclude_max_ = [draw2(draw, e) for e in [exclude_min, exclude_max]]
454
+ return draw(
455
+ floats(
456
+ min_value_,
457
+ max_value_,
458
+ width=64,
459
+ exclude_min=exclude_min_,
460
+ exclude_max=exclude_max_,
461
+ )
462
+ )
407
463
 
408
464
 
409
465
  ##
@@ -495,38 +551,6 @@ def floats_extra(
495
551
  ##
496
552
 
497
553
 
498
- @composite
499
- def freqs(
500
- draw: DrawFn, /, *, unit: MaybeSearchStrategy[DateTimeRoundUnit | None] = None
501
- ) -> Freq:
502
- unit_ = draw2(draw, unit, _freq_units())
503
- match unit_:
504
- case "day":
505
- return Freq(unit=unit_)
506
- case "hour":
507
- return Freq(unit=unit_, increment=draw(_freq_increments(24)))
508
- case "minute" | "second":
509
- return Freq(unit=unit_, increment=draw(_freq_increments(60)))
510
- case "millisecond" | "microsecond" | "nanosecond":
511
- return Freq(unit=unit_, increment=draw(_freq_increments(1000)))
512
- case _ as never:
513
- assert_never(never)
514
-
515
-
516
- @composite
517
- def _freq_units(draw: DrawFn, /) -> DateTimeRoundUnit:
518
- return draw(sampled_from(get_literal_elements(DateTimeRoundUnit)))
519
-
520
-
521
- @composite
522
- def _freq_increments(draw: DrawFn, n: int, /) -> int:
523
- divisors = [i for i in range(1, n) if n % i == 0]
524
- return draw(sampled_from(divisors))
525
-
526
-
527
- ##
528
-
529
-
530
554
  @composite
531
555
  def git_repos(draw: DrawFn, /) -> Path:
532
556
  path = draw(temp_paths())
@@ -555,6 +579,59 @@ def hashables() -> SearchStrategy[Hashable]:
555
579
  ##
556
580
 
557
581
 
582
+ @composite
583
+ def import_froms(
584
+ draw: DrawFn,
585
+ /,
586
+ *,
587
+ min_depth: MaybeSearchStrategy[int | None] = None,
588
+ max_depth: MaybeSearchStrategy[int | None] = None,
589
+ ) -> ImportFrom:
590
+ """Strategy for generating import-froms."""
591
+ from utilities.libcst import generate_import_from
592
+
593
+ min_depth_, max_depth_ = [draw2(draw, d) for d in [min_depth, max_depth]]
594
+ path = draw(
595
+ paths(
596
+ min_depth=1 if min_depth_ is None else max(min_depth_, 1),
597
+ max_depth=max_depth_,
598
+ )
599
+ )
600
+ module = module_path(path)
601
+ name = draw(text_ascii(min_size=1))
602
+ asname = draw(text_ascii(min_size=1) | none())
603
+ return generate_import_from(module, name, asname=asname)
604
+
605
+
606
+ ##
607
+
608
+
609
+ @composite
610
+ def imports(
611
+ draw: DrawFn,
612
+ /,
613
+ *,
614
+ min_depth: MaybeSearchStrategy[int | None] = None,
615
+ max_depth: MaybeSearchStrategy[int | None] = None,
616
+ ) -> Import:
617
+ """Strategy for generating imports."""
618
+ from utilities.libcst import generate_import
619
+
620
+ min_depth_, max_depth_ = [draw2(draw, d) for d in [min_depth, max_depth]]
621
+ path = draw(
622
+ paths(
623
+ min_depth=1 if min_depth_ is None else max(min_depth_, 1),
624
+ max_depth=max_depth_,
625
+ )
626
+ )
627
+ module = module_path(path)
628
+ asname = draw(text_ascii(min_size=1) | none())
629
+ return generate_import(module, asname=asname)
630
+
631
+
632
+ ##
633
+
634
+
558
635
  @composite
559
636
  def int_arrays(
560
637
  draw: DrawFn,
@@ -584,18 +661,48 @@ def int_arrays(
584
661
  ##
585
662
 
586
663
 
664
+ @composite
665
+ def int8s(
666
+ draw: DrawFn,
667
+ /,
668
+ *,
669
+ min_value: MaybeSearchStrategy[int | None] = None,
670
+ max_value: MaybeSearchStrategy[int | None] = None,
671
+ ) -> int:
672
+ """Strategy for generating int8s."""
673
+ min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
674
+ min_value_ = max_nullable([min_value_, MIN_INT8])
675
+ max_value_ = min_nullable([max_value_, MAX_INT8])
676
+ return draw(integers(min_value=min_value_, max_value=max_value_))
677
+
678
+
679
+ @composite
680
+ def int16s(
681
+ draw: DrawFn,
682
+ /,
683
+ *,
684
+ min_value: MaybeSearchStrategy[int | None] = None,
685
+ max_value: MaybeSearchStrategy[int | None] = None,
686
+ ) -> int:
687
+ """Strategy for generating int16s."""
688
+ min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
689
+ min_value_ = max_nullable([min_value_, MIN_INT16])
690
+ max_value_ = min_nullable([max_value_, MAX_INT16])
691
+ return draw(integers(min_value=min_value_, max_value=max_value_))
692
+
693
+
587
694
  @composite
588
695
  def int32s(
589
696
  draw: DrawFn,
590
697
  /,
591
698
  *,
592
- min_value: MaybeSearchStrategy[int] = MIN_INT32,
593
- max_value: MaybeSearchStrategy[int] = MAX_INT32,
699
+ min_value: MaybeSearchStrategy[int | None] = None,
700
+ max_value: MaybeSearchStrategy[int | None] = None,
594
701
  ) -> int:
595
702
  """Strategy for generating int32s."""
596
703
  min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
597
- min_value_ = max(min_value_, MIN_INT32)
598
- max_value_ = min(max_value_, MAX_INT32)
704
+ min_value_ = max_nullable([min_value_, MIN_INT32])
705
+ max_value_ = min_nullable([max_value_, MAX_INT32])
599
706
  return draw(integers(min_value_, max_value_))
600
707
 
601
708
 
@@ -604,13 +711,13 @@ def int64s(
604
711
  draw: DrawFn,
605
712
  /,
606
713
  *,
607
- min_value: MaybeSearchStrategy[int] = MIN_INT64,
608
- max_value: MaybeSearchStrategy[int] = MAX_INT64,
714
+ min_value: MaybeSearchStrategy[int | None] = None,
715
+ max_value: MaybeSearchStrategy[int | None] = None,
609
716
  ) -> int:
610
717
  """Strategy for generating int64s."""
611
718
  min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
612
- min_value_ = max(min_value_, MIN_INT64)
613
- max_value_ = min(max_value_, MAX_INT64)
719
+ min_value_ = max_nullable([min_value_, MIN_INT64])
720
+ max_value_ = min_nullable([max_value_, MAX_INT64])
614
721
  return draw(integers(min_value_, max_value_))
615
722
 
616
723
 
@@ -641,47 +748,32 @@ def lists_fixed_length[T](
641
748
 
642
749
 
643
750
  @composite
644
- def months(
751
+ def month_days(
645
752
  draw: DrawFn,
646
753
  /,
647
754
  *,
648
- min_value: MaybeSearchStrategy[Month | None] = None,
649
- max_value: MaybeSearchStrategy[Month | None] = None,
650
- two_digit: MaybeSearchStrategy[bool] = False,
651
- ) -> Month:
652
- """Strategy for generating months."""
755
+ min_value: MaybeSearchStrategy[MonthDay | None] = None,
756
+ max_value: MaybeSearchStrategy[MonthDay | None] = None,
757
+ ) -> MonthDay:
758
+ """Strategy for generating month-days."""
653
759
  min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
654
760
  match min_value_:
655
761
  case None:
656
- min_value_ = MONTH_MIN
657
- case Month():
762
+ min_value_ = MonthDay.MIN
763
+ case MonthDay():
658
764
  ...
659
- case _ as never:
765
+ case never:
660
766
  assert_never(never)
661
767
  match max_value_:
662
768
  case None:
663
- max_value_ = MONTH_MAX
664
- case Month():
769
+ max_value_ = MonthDay.MAX
770
+ case MonthDay():
665
771
  ...
666
- case _ as never:
772
+ case never:
667
773
  assert_never(never)
668
- min_date, max_date = [m.to_date() for m in [min_value_, max_value_]]
669
- date = draw(dates(min_value=min_date, max_value=max_date, two_digit=two_digit))
670
- return Month.from_date(date)
671
-
672
-
673
- ##
674
-
675
-
676
- @composite
677
- def namespace_mixins(draw: DrawFn, /) -> type:
678
- """Strategy for generating task namespace mixins."""
679
- path = draw(temp_paths())
680
-
681
- class NamespaceMixin:
682
- task_namespace = path.name
683
-
684
- return NamespaceMixin
774
+ min_date, max_date = [m.in_year(2000) for m in [min_value_, max_value_]]
775
+ date = draw(dates(min_value=min_date, max_value=max_date))
776
+ return date.month_day()
685
777
 
686
778
 
687
779
  ##
@@ -746,18 +838,67 @@ def _pairs_map[T](elements: list[T], /) -> tuple[T, T]:
746
838
  ##
747
839
 
748
840
 
749
- def paths() -> SearchStrategy[Path]:
841
+ @composite
842
+ def paths(
843
+ draw: DrawFn,
844
+ /,
845
+ *,
846
+ min_depth: MaybeSearchStrategy[int | None] = None,
847
+ max_depth: MaybeSearchStrategy[int | None] = None,
848
+ ) -> Path:
750
849
  """Strategy for generating `Path`s."""
751
- reserved = {"AUX", "NUL"}
752
- strategy = text_ascii(min_size=1, max_size=10).filter(lambda x: x not in reserved)
753
- return lists(strategy, max_size=10).map(lambda parts: Path(*parts))
850
+ min_depth_, max_depth_ = [draw2(draw, d) for d in [min_depth, max_depth]]
851
+ min_depth_ = max_nullable([min_depth_, 0])
852
+ max_depth_ = min_nullable([max_depth_, 10])
853
+ parts = draw(lists(_path_parts(), min_size=min_depth_, max_size=max_depth_))
854
+ return Path(*parts)
855
+
856
+
857
+ @composite
858
+ def _path_parts(draw: DrawFn, /) -> str:
859
+ part = draw(text_ascii(min_size=1, max_size=10))
860
+ reserved = {"AUX", "NUL", "nuL", "pRn"}
861
+ _ = assume(part not in reserved)
862
+ return part
863
+
864
+
865
+ ##
866
+
867
+
868
+ @composite
869
+ def permissions(
870
+ draw: DrawFn,
871
+ /,
872
+ *,
873
+ user_read: MaybeSearchStrategy[bool | None] = None,
874
+ user_write: MaybeSearchStrategy[bool | None] = None,
875
+ user_execute: MaybeSearchStrategy[bool | None] = None,
876
+ group_read: MaybeSearchStrategy[bool | None] = None,
877
+ group_write: MaybeSearchStrategy[bool | None] = None,
878
+ group_execute: MaybeSearchStrategy[bool | None] = None,
879
+ others_read: MaybeSearchStrategy[bool | None] = None,
880
+ others_write: MaybeSearchStrategy[bool | None] = None,
881
+ others_execute: MaybeSearchStrategy[bool | None] = None,
882
+ ) -> Permissions:
883
+ """Strategy for generating `Permissions`."""
884
+ return Permissions(
885
+ user_read=draw2(draw, user_read, booleans()),
886
+ user_write=draw2(draw, user_write, booleans()),
887
+ user_execute=draw2(draw, user_execute, booleans()),
888
+ group_read=draw2(draw, group_read, booleans()),
889
+ group_write=draw2(draw, group_write, booleans()),
890
+ group_execute=draw2(draw, group_execute, booleans()),
891
+ others_read=draw2(draw, others_read, booleans()),
892
+ others_write=draw2(draw, others_write, booleans()),
893
+ others_execute=draw2(draw, others_execute, booleans()),
894
+ )
754
895
 
755
896
 
756
897
  ##
757
898
 
758
899
 
759
900
  @composite
760
- def plain_datetimes(
901
+ def plain_date_times(
761
902
  draw: DrawFn,
762
903
  /,
763
904
  *,
@@ -768,17 +909,17 @@ def plain_datetimes(
768
909
  min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
769
910
  match min_value_:
770
911
  case None:
771
- min_value_ = PLAIN_DATE_TIME_MIN
912
+ min_value_ = PlainDateTime.MIN
772
913
  case PlainDateTime():
773
914
  ...
774
- case _ as never:
915
+ case never:
775
916
  assert_never(never)
776
917
  match max_value_:
777
918
  case None:
778
- max_value_ = PLAIN_DATE_TIME_MAX
919
+ max_value_ = PlainDateTime.MAX
779
920
  case PlainDateTime():
780
921
  ...
781
- case _ as never:
922
+ case never:
782
923
  assert_never(never)
783
924
  py_datetime = draw(
784
925
  datetimes(
@@ -791,6 +932,46 @@ def plain_datetimes(
791
932
  ##
792
933
 
793
934
 
935
+ @composite
936
+ def py_datetimes(
937
+ draw: DrawFn, /, *, zoned: MaybeSearchStrategy[bool | None] = None
938
+ ) -> dt.datetime:
939
+ """Strategy for generating standard library datetimes."""
940
+ zoned_ = draw2(draw, zoned, booleans())
941
+ timezones = just(UTC) if zoned_ else none()
942
+ return draw(
943
+ hypothesis.strategies.datetimes(
944
+ min_value=dt.datetime(2000, 1, 1), # noqa: DTZ001
945
+ max_value=dt.datetime(2000, 12, 31), # noqa: DTZ001
946
+ timezones=timezones,
947
+ )
948
+ )
949
+
950
+
951
+ ##
952
+
953
+
954
+ def quadruples[T](
955
+ strategy: SearchStrategy[T],
956
+ /,
957
+ *,
958
+ unique: MaybeSearchStrategy[bool] = False,
959
+ sorted: MaybeSearchStrategy[bool] = False, # noqa: A002
960
+ ) -> SearchStrategy[tuple[T, T, T, T]]:
961
+ """Strategy for generating quadruples of elements."""
962
+ return lists_fixed_length(strategy, 4, unique=unique, sorted=sorted).map(
963
+ _quadruples_map
964
+ )
965
+
966
+
967
+ def _quadruples_map[T](elements: list[T], /) -> tuple[T, T, T, T]:
968
+ first, second, third, fourth = elements
969
+ return first, second, third, fourth
970
+
971
+
972
+ ##
973
+
974
+
794
975
  @composite
795
976
  def random_states(
796
977
  draw: DrawFn, /, *, seed: MaybeSearchStrategy[int | None] = None
@@ -798,7 +979,7 @@ def random_states(
798
979
  """Strategy for generating `numpy` random states."""
799
980
  from numpy.random import RandomState
800
981
 
801
- seed_ = draw2(draw, seed, integers(0, MAX_UINT32))
982
+ seed_ = draw2(draw, seed, uint32s())
802
983
  return RandomState(seed=seed_)
803
984
 
804
985
 
@@ -845,7 +1026,7 @@ def setup_hypothesis_profiles(
845
1026
  return 100
846
1027
  case Profile.ci:
847
1028
  return 1000
848
- case _ as never:
1029
+ case never:
849
1030
  assert_never(never)
850
1031
 
851
1032
  @property
@@ -855,11 +1036,11 @@ def setup_hypothesis_profiles(
855
1036
  return Verbosity.quiet
856
1037
  case Profile.ci:
857
1038
  return Verbosity.verbose
858
- case _ as never:
1039
+ case never:
859
1040
  assert_never(never)
860
1041
 
861
1042
  phases = {Phase.explicit, Phase.reuse, Phase.generate, Phase.target}
862
- if "HYPOTHESIS_NO_SHRINK" not in environ:
1043
+ if "HYPOTHESIS_NO_SHRINK" not in environ: # pragma: no cover
863
1044
  phases.add(Phase.shrink)
864
1045
  for profile in Profile:
865
1046
  try:
@@ -980,9 +1161,7 @@ def temp_dirs(draw: DrawFn, /) -> TemporaryDirectory:
980
1161
  """Search strategy for temporary directories."""
981
1162
  _TEMP_DIR_HYPOTHESIS.mkdir(exist_ok=True)
982
1163
  uuid = draw(uuids())
983
- return TemporaryDirectory(
984
- prefix=f"{uuid}__", dir=_TEMP_DIR_HYPOTHESIS, ignore_cleanup_errors=IS_WINDOWS
985
- )
1164
+ return TemporaryDirectory(prefix=f"{uuid}__", dir=_TEMP_DIR_HYPOTHESIS)
986
1165
 
987
1166
 
988
1167
  ##
@@ -1112,14 +1291,14 @@ def time_deltas(
1112
1291
  min_value_ = TIME_DELTA_MIN
1113
1292
  case TimeDelta():
1114
1293
  ...
1115
- case _ as never:
1294
+ case never:
1116
1295
  assert_never(never)
1117
1296
  match max_value_:
1118
1297
  case None:
1119
1298
  max_value_ = TIME_DELTA_MAX
1120
1299
  case TimeDelta():
1121
1300
  ...
1122
- case _ as never:
1301
+ case never:
1123
1302
  assert_never(never)
1124
1303
  py_time = draw(
1125
1304
  hypothesis.strategies.timedeltas(
@@ -1132,6 +1311,24 @@ def time_deltas(
1132
1311
  ##
1133
1312
 
1134
1313
 
1314
+ @composite
1315
+ def time_periods(
1316
+ draw: DrawFn,
1317
+ /,
1318
+ *,
1319
+ min_value: MaybeSearchStrategy[Time | None] = None,
1320
+ max_value: MaybeSearchStrategy[Time | None] = None,
1321
+ ) -> TimePeriod:
1322
+ """Strategy for generating time periods."""
1323
+ min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
1324
+ strategy = times(min_value=min_value_, max_value=max_value_)
1325
+ start, end = draw(pairs(strategy, sorted=True))
1326
+ return TimePeriod(start, end)
1327
+
1328
+
1329
+ ##
1330
+
1331
+
1135
1332
  @composite
1136
1333
  def times(
1137
1334
  draw: DrawFn,
@@ -1144,17 +1341,17 @@ def times(
1144
1341
  min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
1145
1342
  match min_value_:
1146
1343
  case None:
1147
- min_value_ = TIME_MIN
1344
+ min_value_ = Time.MIN
1148
1345
  case Time():
1149
1346
  ...
1150
- case _ as never:
1347
+ case never:
1151
1348
  assert_never(never)
1152
1349
  match max_value_:
1153
1350
  case None:
1154
- max_value_ = TIME_MAX
1351
+ max_value_ = Time.MAX
1155
1352
  case Time():
1156
1353
  ...
1157
- case _ as never:
1354
+ case never:
1158
1355
  assert_never(never)
1159
1356
  py_time = draw(
1160
1357
  hypothesis.strategies.times(
@@ -1188,18 +1385,48 @@ def _triples_map[T](elements: list[T], /) -> tuple[T, T, T]:
1188
1385
  ##
1189
1386
 
1190
1387
 
1388
+ @composite
1389
+ def uint8s(
1390
+ draw: DrawFn,
1391
+ /,
1392
+ *,
1393
+ min_value: MaybeSearchStrategy[int | None] = None,
1394
+ max_value: MaybeSearchStrategy[int | None] = None,
1395
+ ) -> int:
1396
+ """Strategy for generating uint8s."""
1397
+ min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
1398
+ min_value_ = max_nullable([min_value_, MIN_UINT8])
1399
+ max_value_ = min_nullable([max_value_, MAX_UINT8])
1400
+ return draw(integers(min_value=min_value_, max_value=max_value_))
1401
+
1402
+
1403
+ @composite
1404
+ def uint16s(
1405
+ draw: DrawFn,
1406
+ /,
1407
+ *,
1408
+ min_value: MaybeSearchStrategy[int | None] = None,
1409
+ max_value: MaybeSearchStrategy[int | None] = None,
1410
+ ) -> int:
1411
+ """Strategy for generating uint16s."""
1412
+ min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
1413
+ min_value_ = max_nullable([min_value_, MIN_UINT16])
1414
+ max_value_ = min_nullable([max_value_, MAX_UINT16])
1415
+ return draw(integers(min_value=min_value_, max_value=max_value_))
1416
+
1417
+
1191
1418
  @composite
1192
1419
  def uint32s(
1193
1420
  draw: DrawFn,
1194
1421
  /,
1195
1422
  *,
1196
- min_value: MaybeSearchStrategy[int] = MIN_UINT32,
1197
- max_value: MaybeSearchStrategy[int] = MAX_UINT32,
1423
+ min_value: MaybeSearchStrategy[int | None] = None,
1424
+ max_value: MaybeSearchStrategy[int | None] = None,
1198
1425
  ) -> int:
1199
1426
  """Strategy for generating uint32s."""
1200
1427
  min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
1201
- min_value_ = max(min_value_, MIN_UINT32)
1202
- max_value_ = min(max_value_, MAX_UINT32)
1428
+ min_value_ = max_nullable([min_value_, MIN_UINT32])
1429
+ max_value_ = min_nullable([max_value_, MAX_UINT32])
1203
1430
  return draw(integers(min_value=min_value_, max_value=max_value_))
1204
1431
 
1205
1432
 
@@ -1208,19 +1435,54 @@ def uint64s(
1208
1435
  draw: DrawFn,
1209
1436
  /,
1210
1437
  *,
1211
- min_value: MaybeSearchStrategy[int] = MIN_UINT64,
1212
- max_value: MaybeSearchStrategy[int] = MAX_UINT64,
1438
+ min_value: MaybeSearchStrategy[int | None] = None,
1439
+ max_value: MaybeSearchStrategy[int | None] = None,
1213
1440
  ) -> int:
1214
1441
  """Strategy for generating uint64s."""
1215
1442
  min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
1216
- min_value_ = max(min_value_, MIN_UINT64)
1217
- max_value_ = min(max_value_, MAX_UINT64)
1443
+ min_value_ = max_nullable([min_value_, MIN_UINT64])
1444
+ max_value_ = min_nullable([max_value_, MAX_UINT64])
1218
1445
  return draw(integers(min_value=min_value_, max_value=max_value_))
1219
1446
 
1220
1447
 
1221
1448
  ##
1222
1449
 
1223
1450
 
1451
+ @composite
1452
+ def urls(
1453
+ draw: DrawFn,
1454
+ /,
1455
+ *,
1456
+ all_: MaybeSearchStrategy[bool] = False,
1457
+ username: MaybeSearchStrategy[bool] = False,
1458
+ password: MaybeSearchStrategy[bool] = False,
1459
+ host: MaybeSearchStrategy[bool] = False,
1460
+ port: MaybeSearchStrategy[bool] = False,
1461
+ database: MaybeSearchStrategy[bool] = False,
1462
+ ) -> URL:
1463
+ from sqlalchemy import URL
1464
+
1465
+ have_all, have_username, have_password, have_host, have_port, have_database = [
1466
+ draw2(draw, b) for b in [all_, username, password, host, port, database]
1467
+ ]
1468
+ username_use = draw(text_ascii(min_size=1)) if have_all or have_username else None
1469
+ password_use = draw(text_ascii(min_size=1)) if have_all or have_password else None
1470
+ host_use = draw(text_ascii(min_size=1)) if have_all or have_host else None
1471
+ port_use = draw(integers(min_value=1)) if have_all or have_port else None
1472
+ database_use = draw(text_ascii(min_size=1)) if have_all or have_database else None
1473
+ return URL.create(
1474
+ drivername="sqlite",
1475
+ username=username_use,
1476
+ password=password_use,
1477
+ host=host_use,
1478
+ port=port_use,
1479
+ database=database_use,
1480
+ )
1481
+
1482
+
1483
+ ##
1484
+
1485
+
1224
1486
  @composite
1225
1487
  def versions(draw: DrawFn, /, *, suffix: MaybeSearchStrategy[bool] = False) -> Version:
1226
1488
  """Strategy for generating versions."""
@@ -1234,7 +1496,81 @@ def versions(draw: DrawFn, /, *, suffix: MaybeSearchStrategy[bool] = False) -> V
1234
1496
 
1235
1497
 
1236
1498
  @composite
1237
- def zoned_datetimes(
1499
+ def year_months(
1500
+ draw: DrawFn,
1501
+ /,
1502
+ *,
1503
+ min_value: MaybeSearchStrategy[YearMonth | None] = None,
1504
+ max_value: MaybeSearchStrategy[YearMonth | None] = None,
1505
+ two_digit: MaybeSearchStrategy[bool] = False,
1506
+ ) -> YearMonth:
1507
+ """Strategy for generating months."""
1508
+ min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
1509
+ match min_value_:
1510
+ case None:
1511
+ min_value_ = YearMonth.MIN
1512
+ case YearMonth():
1513
+ ...
1514
+ case never:
1515
+ assert_never(never)
1516
+ match max_value_:
1517
+ case None:
1518
+ max_value_ = YearMonth.MAX
1519
+ case YearMonth():
1520
+ ...
1521
+ case never:
1522
+ assert_never(never)
1523
+ min_date, max_date = [m.on_day(1) for m in [min_value_, max_value_]]
1524
+ date = draw(dates(min_value=min_date, max_value=max_date, two_digit=two_digit))
1525
+ return date.year_month()
1526
+
1527
+
1528
+ ##
1529
+
1530
+
1531
+ @composite
1532
+ def zone_infos(draw: DrawFn, /) -> ZoneInfo:
1533
+ """Strategy for generating time-zones."""
1534
+ time_zone = draw(timezones())
1535
+ if IS_LINUX: # skipif-not-linux
1536
+ _ = assume(time_zone.key not in _LINUX_DISALLOW_TIME_ZONES)
1537
+ with assume_does_not_raise(TimeZoneNotFoundError):
1538
+ _ = get_now(time_zone)
1539
+ return time_zone
1540
+
1541
+
1542
+ _LINUX_DISALLOW_TIME_ZONES: set[TimeZone | Literal["localtime"]] = {
1543
+ "Etc/UTC",
1544
+ "localtime",
1545
+ }
1546
+
1547
+ ##
1548
+
1549
+
1550
+ @composite
1551
+ def zoned_date_time_periods(
1552
+ draw: DrawFn,
1553
+ /,
1554
+ *,
1555
+ min_value: MaybeSearchStrategy[PlainDateTime | ZonedDateTime | None] = None,
1556
+ max_value: MaybeSearchStrategy[PlainDateTime | ZonedDateTime | None] = None,
1557
+ time_zone: MaybeSearchStrategy[TimeZoneLike] = UTC,
1558
+ ) -> ZonedDateTimePeriod:
1559
+ """Strategy for generating zoned date-time periods."""
1560
+ min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
1561
+ time_zone_: TimeZoneLike = draw2(draw, time_zone)
1562
+ strategy = zoned_date_times(
1563
+ min_value=min_value_, max_value=max_value_, time_zone=time_zone_
1564
+ )
1565
+ start, end = draw(pairs(strategy, sorted=True))
1566
+ return ZonedDateTimePeriod(start, end)
1567
+
1568
+
1569
+ ##
1570
+
1571
+
1572
+ @composite
1573
+ def zoned_date_times(
1238
1574
  draw: DrawFn,
1239
1575
  /,
1240
1576
  *,
@@ -1242,16 +1578,16 @@ def zoned_datetimes(
1242
1578
  max_value: MaybeSearchStrategy[PlainDateTime | ZonedDateTime | None] = None,
1243
1579
  time_zone: MaybeSearchStrategy[TimeZoneLike] = UTC,
1244
1580
  ) -> ZonedDateTime:
1245
- """Strategy for generating zoned datetimes."""
1581
+ """Strategy for generating zoned date-times."""
1246
1582
  min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
1247
- time_zone_ = ensure_time_zone(draw2(draw, time_zone))
1583
+ time_zone_ = to_zone_info(draw2(draw, time_zone))
1248
1584
  match min_value_:
1249
1585
  case None | PlainDateTime():
1250
1586
  ...
1251
1587
  case ZonedDateTime():
1252
1588
  with assume_does_not_raise(ValueError):
1253
1589
  min_value_ = min_value_.to_tz(time_zone_.key).to_plain()
1254
- case _ as never:
1590
+ case never:
1255
1591
  assert_never(never)
1256
1592
  match max_value_:
1257
1593
  case None | PlainDateTime():
@@ -1259,22 +1595,26 @@ def zoned_datetimes(
1259
1595
  case ZonedDateTime():
1260
1596
  with assume_does_not_raise(ValueError):
1261
1597
  max_value_ = max_value_.to_tz(time_zone_.key).to_plain()
1262
- case _ as never:
1598
+ case never:
1263
1599
  assert_never(never)
1264
- plain = draw(plain_datetimes(min_value=min_value_, max_value=max_value_))
1600
+ plain = draw(plain_date_times(min_value=min_value_, max_value=max_value_))
1265
1601
  with (
1266
1602
  assume_does_not_raise(RepeatedTime),
1267
1603
  assume_does_not_raise(SkippedTime),
1268
- assume_does_not_raise(TimeZoneNotFoundError),
1269
- assume_does_not_raise(ValueError, match="Resulting datetime is out of range"),
1604
+ assume_does_not_raise(ValueError, match=r"Resulting time is out of range"),
1270
1605
  ):
1271
1606
  zoned = plain.assume_tz(time_zone_.key, disambiguate="raise")
1272
- with assume_does_not_raise(OverflowError, match="date value out of range"):
1273
- if not ((DATE_MIN + DAY) <= zoned.date() <= (DATE_MAX - DAY)):
1607
+ with assume_does_not_raise(OverflowError, match=r"date value out of range"):
1608
+ if not ((Date.MIN + DAY) <= zoned.date() <= (Date.MAX - DAY)):
1274
1609
  _ = zoned.py_datetime()
1275
1610
  return zoned
1276
1611
 
1277
1612
 
1613
+ zoned_date_times_2000 = zoned_date_times(
1614
+ min_value=ZonedDateTime(2000, 1, 1, tz=UTC.key),
1615
+ max_value=ZonedDateTime(2000, 12, 31, tz=UTC.key),
1616
+ )
1617
+
1278
1618
  __all__ = [
1279
1619
  "Draw2Error",
1280
1620
  "MaybeSearchStrategy",
@@ -1282,6 +1622,7 @@ __all__ = [
1282
1622
  "assume_does_not_raise",
1283
1623
  "bool_arrays",
1284
1624
  "date_deltas",
1625
+ "date_periods",
1285
1626
  "date_time_deltas",
1286
1627
  "dates",
1287
1628
  "draw2",
@@ -1289,19 +1630,24 @@ __all__ = [
1289
1630
  "float64s",
1290
1631
  "float_arrays",
1291
1632
  "floats_extra",
1292
- "freqs",
1293
1633
  "git_repos",
1294
1634
  "hashables",
1635
+ "import_froms",
1636
+ "imports",
1637
+ "int8s",
1638
+ "int16s",
1295
1639
  "int32s",
1296
1640
  "int64s",
1297
1641
  "int_arrays",
1298
1642
  "lists_fixed_length",
1299
- "months",
1300
- "namespace_mixins",
1643
+ "month_days",
1301
1644
  "numbers",
1302
1645
  "pairs",
1303
1646
  "paths",
1304
- "plain_datetimes",
1647
+ "permissions",
1648
+ "plain_date_times",
1649
+ "py_datetimes",
1650
+ "quadruples",
1305
1651
  "random_states",
1306
1652
  "sentinels",
1307
1653
  "sets_fixed_length",
@@ -1317,10 +1663,18 @@ __all__ = [
1317
1663
  "text_digits",
1318
1664
  "text_printable",
1319
1665
  "time_deltas",
1666
+ "time_periods",
1320
1667
  "times",
1321
1668
  "triples",
1669
+ "uint8s",
1670
+ "uint16s",
1322
1671
  "uint32s",
1323
1672
  "uint64s",
1673
+ "urls",
1324
1674
  "versions",
1325
- "zoned_datetimes",
1675
+ "year_months",
1676
+ "zone_infos",
1677
+ "zoned_date_time_periods",
1678
+ "zoned_date_times",
1679
+ "zoned_date_times_2000",
1326
1680
  ]