Skip to content

Commit 89f6d69

Browse files
dbrattliclaude
andcommitted
refactor(stdlib): rework datetime bindings, fix justfile, apply fantomas
Datetime: - Switch from paired static-factory types to Queue.fs-style primary-ctor classes. The original factory pattern combined [<Emit("$0($1...)")>] with [<NamedParams>], which silently dropped all kwargs (generated timedelta() instead of timedelta(days=3.0)). - timedelta: empty primary ctor plus static ofDays/ofHours/ofMinutes/ ofSeconds/ofWeeks/ofMilliseconds/ofMicroseconds factories with float() emit wrappers so Fable's Float64 doesn't reach Python's datetime. Added add/sub/neg arithmetic. - timezone: moved above datetime so datetime.astimezone/now(tz)/ fromtimestamp(tz) can take timezone instead of obj. - date/time/datetime: collapsed replaceDate/replaceTime into a single [<NamedParams>] replace that supports partial replacement (any subset of fields). Added time.replace. - datetime: arithmetic via sub(datetime)->timedelta, sub(timedelta)-> datetime, add(timedelta)->datetime. utcnow marked [<Obsolete>] pointing at now(tz = timezone.utc). - Module-level doc note about the `time` identifier collision with Fable.Python.Time. - Tests expanded from 30 to 37 covering partial replace, arithmetic, datetime.now(tz), and the ofX factories. justfile: - Drop -r from `dotnet fantomas` invocations in `format` and `format-check`; fantomas has no -r flag and it caused both recipes to fail. Other files: fantomas reformatting applied by `just format` to pre-existing files touched by the formatter. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 92627b9 commit 89f6d69

17 files changed

Lines changed: 426 additions & 375 deletions

‎justfile‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,13 @@ shipit *args:
8383

8484
# Format code with Fantomas
8585
format:
86-
dotnet fantomas {{src_path}} -r
87-
dotnet fantomas {{test_path}} -r
86+
dotnet fantomas {{src_path}}
87+
dotnet fantomas {{test_path}}
8888

8989
# Check code formatting without making changes
9090
format-check:
91-
dotnet fantomas {{src_path}} -r --check
92-
dotnet fantomas {{test_path}} -r --check
91+
dotnet fantomas {{src_path}} --check
92+
dotnet fantomas {{test_path}} --check
9393

9494
# Install .NET tools (Fable, Fantomas) and Python dependencies
9595
setup:

‎src/fable/Testing.fs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ let throwsError (expected: string) (f: unit -> 'a) : unit =
4747
let throwsErrorContaining (expected: string) (f: unit -> 'a) : unit =
4848
match run f with
4949
| Error _ when String.IsNullOrEmpty expected -> ()
50-
| Error (actual: string) when actual.Contains expected -> ()
50+
| Error(actual: string) when actual.Contains expected -> ()
5151
| Error actual -> equal (sprintf "Error containing '%s'" expected) actual
5252
| Ok _ -> equal (sprintf "Error containing '%s'" expected) "No error was thrown"
5353

‎src/stdlib/Builtins.fs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,8 @@ let __name__: string = nativeOnly
353353
let print obj = builtins.print obj
354354

355355
/// Return the value of the named attribute of object with a default.
356-
let getattr obj name defaultValue = builtins.getattr (obj, name, defaultValue)
356+
let getattr obj name defaultValue =
357+
builtins.getattr (obj, name, defaultValue)
357358

358359
/// Sets the named attribute on the given object to the specified value.
359360
let setattr obj name value = builtins.setattr (obj, name, value)

‎src/stdlib/Datetime.fs‎

Lines changed: 198 additions & 167 deletions
Large diffs are not rendered by default.

‎src/stdlib/Math.fs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,12 @@ type IExports =
8484
/// Return True if the values a and b are close to each other
8585
/// See https://docs.python.org/3/library/math.html#math.isclose
8686
abstract isclose: a: float * b: float -> bool
87+
8788
/// Return True if the values a and b are close to each other with custom tolerances
8889
/// See https://docs.python.org/3/library/math.html#math.isclose
8990
[<NamedParams(fromIndex = 2)>]
9091
abstract isclose: a: float * b: float * ?rel_tol: float * ?abs_tol: float -> bool
92+
9193
/// Return the least common multiple of the integers
9294
/// See https://docs.python.org/3/library/math.html#math.lcm
9395
abstract lcm: [<ParamArray>] ints: int[] -> int

‎src/stdlib/Queue.fs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,12 @@ type Queue<'T>() =
3434
/// operation goes into an uninterruptible wait on an underlying lock. This means that no exceptions can occur, and
3535
/// in particular a SIGINT will not trigger a KeyboardInterrupt.
3636
member x.get(?block: bool, ?timeout: float) : 'T = nativeOnly
37+
3738
/// Equivalent to get(False).
3839
/// See https://docs.python.org/3/library/queue.html#queue.Queue.get_nowait
3940
[<Emit("$0.get_nowait()")>]
4041
member x.get_nowait() : 'T = nativeOnly
42+
4143
/// Blocks until all items in the queue have been gotten and processed.
4244
///
4345
/// The count of unfinished tasks goes up whenever an item is added to the queue. The count goes down whenever a
@@ -74,6 +76,7 @@ type SimpleQueue<'T>() =
7476
member x.put(item: 'T, ?block: bool, ?timeout: float) : unit = nativeOnly
7577
/// Remove and return an item from the queue.
7678
member x.get(?block: bool, ?timeout: float) : 'T = nativeOnly
79+
7780
/// Equivalent to get(False).
7881
[<Emit("$0.get_nowait()")>]
7982
member x.get_nowait() : 'T = nativeOnly

0 commit comments

Comments
 (0)