Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pyrightconfig.ci.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
"**/.venv/**",
"**/node_modules/**",
"temp/tests/Python/test_applicative.py",
"temp/tests/Python/test_hash_set.py",
"temp/tests/Python/test_nested_and_recursive_pattern.py",
"temp/tests/Python/fable_modules/thoth_json_python/encode.py"
]
}
1 change: 1 addition & 0 deletions src/Fable.Cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

* [Python] Fix HashSet operations (Count, Contains, Remove, UnionWith, IntersectWith, ExceptWith) to work with both native Python sets and custom MutableSet (by @dbrattli)
* [Python] Fix `Array.length`, `.Length`, `Array.isEmpty`, and `ResizeArray.Count` to use `len()` instead of `.length` property for plain Python list interop (by @dbrattli)
* [Python] Fix `Task<T>` pass-through returns not being awaited in if/else and try/with branches (by @dbrattli)
* [Python] Fix `:? T as x` type test pattern in closures causing `UnboundLocalError` due to `cast()` shadowing outer variable (by @dbrattli)
Expand Down
1 change: 1 addition & 0 deletions src/Fable.Compiler/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

* [Python] Fix HashSet operations (Count, Contains, Remove, UnionWith, IntersectWith, ExceptWith) to work with both native Python sets and custom MutableSet (by @dbrattli)
* [Python] Fix `Array.length`, `.Length`, `Array.isEmpty`, and `ResizeArray.Count` to use `len()` instead of `.length` property for plain Python list interop (by @dbrattli)
* [Python] Fix `Task<T>` pass-through returns not being awaited in if/else and try/with branches (by @dbrattli)
* [Python] Fix `:? T as x` type test pattern in closures causing `UnboundLocalError` due to `cast()` shadowing outer variable (by @dbrattli)
Expand Down
6 changes: 2 additions & 4 deletions src/Fable.Transforms/Python/Fable2Python.Transforms.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3679,8 +3679,7 @@ let declareType
let body, stmts = transformReflectionInfo com ctx None ent generics
let expr, stmts' = makeFunctionExpression com ctx None (args, body, [], ta)

let name =
com.GetIdentifier(ctx, Naming.toPascalCase entName + Naming.reflectionSuffix)
let name = com.GetIdentifier(ctx, entName + Naming.reflectionSuffix)

expr |> declareModuleMember com ctx ent.IsPublic name None, stmts @ stmts'

Expand Down Expand Up @@ -4065,8 +4064,7 @@ let transformUnion (com: IPythonCompiler) ctx (ent: Fable.Entity) (entName: stri
let body, stmts = transformReflectionInfo com ctx None ent generics
let expr, stmts' = makeFunctionExpression com ctx None (args, body, [], ta)

let name =
com.GetIdentifier(ctx, Naming.toPascalCase entName + Naming.reflectionSuffix)
let name = com.GetIdentifier(ctx, entName + Naming.reflectionSuffix)

expr |> declareModuleMember com ctx ent.IsPublic name None, stmts @ stmts'

Expand Down
24 changes: 16 additions & 8 deletions src/Fable.Transforms/Python/Replacements.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2630,17 +2630,25 @@ let hashSets (com: ICompiler) (ctx: Context) r t (i: CallInfo) (thisArg: Expr op
|> makeHashSetWithComparer com r t (makeArray Any [])
|> Some
| _ -> None
| "get_Count", Some c, _ ->
Helper.LibCall(com, "mutable_set", "HashSet__get_Count", t, [ c ], ?loc = r)
|> Some
| "get_Count", Some c, _ -> Helper.GlobalCall("len", t, [ c ], ?loc = r) |> Some
| "get_IsReadOnly", _, _ -> BoolConstant false |> makeValue r |> Some
| ReplaceName [ "Clear", "clear"; "Contains", "has"; "Remove", "delete" ] methName, Some c, args ->
Helper.InstanceCall(c, methName, t, args, i.SignatureArgTypes, ?loc = r) |> Some
| "Clear", Some c, _ -> Helper.InstanceCall(c, "clear", t, args, i.SignatureArgTypes, ?loc = r) |> Some
| "Contains", Some c, [ arg ] ->
Helper.LibCall(com, "map_util", "containsInSet", t, [ arg; c ], ?loc = r)
|> Some
| "Remove", Some c, [ arg ] ->
Helper.LibCall(com, "map_util", "removeFromSet", t, [ arg; c ], ?loc = r)
|> Some
| "GetEnumerator", Some c, _ -> getEnumerator com r t c |> Some
| "Add", Some c, [ arg ] -> Helper.LibCall(com, "map_util", "addToSet", t, [ arg; c ], ?loc = r) |> Some
| ("IsProperSubsetOf" | "IsProperSupersetOf" | "UnionWith" | "IntersectWith" | "ExceptWith" | "IsSubsetOf" | "IsSupersetOf" as meth),
Some c,
args ->
| "UnionWith", Some c, [ arg ] -> Helper.LibCall(com, "map_util", "unionWithSet", t, [ c; arg ], ?loc = r) |> Some
| "IntersectWith", Some c, [ arg ] ->
Helper.LibCall(com, "map_util", "intersectWithSet", t, [ c; arg ], ?loc = r)
|> Some
| "ExceptWith", Some c, [ arg ] ->
Helper.LibCall(com, "map_util", "exceptWithSet", t, [ c; arg ], ?loc = r)
|> Some
| ("IsProperSubsetOf" | "IsProperSupersetOf" | "IsSubsetOf" | "IsSupersetOf" as meth), Some c, args ->
let meth = Naming.lowerFirst meth
let args = injectArg com ctx r "Set" meth i.GenericArgs args

Expand Down
34 changes: 34 additions & 0 deletions src/fable-library-py/fable_library/map_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,40 @@ def add_to_set(v: object, st: MutableSet[object]) -> bool:
return True


def remove_from_set(v: object, st: MutableSet[object]) -> bool:
"""Remove from set-like object - returns True if removed, False if not present."""
if v in st:
st.discard(v)
return True

return False


def contains_in_set(v: object, st: MutableSet[object]) -> bool:
"""Check if set-like object contains a value."""
return v in st


def union_with_set(s1: MutableSet[object], s2: Iterable[object]) -> None:
"""Add all elements from s2 to s1. Works with both native set and custom HashSet."""
for x in s2:
s1.add(x)


def intersect_with_set(s1: MutableSet[object], s2: Iterable[object]) -> None:
"""Remove elements from s1 that are not in s2. Works with both native set and custom HashSet."""
s2_items = set(s2)
to_remove = [x for x in s1 if x not in s2_items]
for x in to_remove:
s1.discard(x)


def except_with_set(s1: MutableSet[object], s2: Iterable[object]) -> None:
"""Remove all elements in s2 from s1. Works with both native set and custom HashSet."""
for x in s2:
s1.discard(x)


def add_to_dict(di: dict[_K, _V], k: _K, v: _V) -> None:
if k in di:
raise Exception("An item with the same key has already been added. Key: " + str(k))
Expand Down
2 changes: 2 additions & 0 deletions tests/Python/Fable.Tests.Python.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@
<Compile Include="TestUri.fs" />
<Compile Include="TestPyInterop.fs" />
<Compile Include="TestPatternMatch.fs" />
<Compile Include="TestHashSet.fs" />
<Compile Include="TestNestedAndRecursivePattern.fs" />

<Compile Include="TestNonRegression.fs" />
<Compile Include="Main.fs" />
Expand Down
Loading
Loading