Skip to content

Commit

Permalink
[Python] Fixes for custom hash values (#3796)
Browse files Browse the repository at this point in the history
  • Loading branch information
dbrattli authored Apr 1, 2024
1 parent e557a84 commit c8c1c0d
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 72 deletions.
72 changes: 36 additions & 36 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 17 additions & 8 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ authors = ["Alfonso Garcia-Caro <@alfonsogcnunez>", "Dag Brattli <dag@brattli.ne
license = "MIT License"
readme = "README.md"
homepage = "https://fable.io"

packages = [
{ include = "temp/fable-library-py/fable_library", from = "." },
]
[tool.poetry.dependencies]
python = ">= 3.10, < 4.0"
python-dateutil = "^2.8.2"
python-dateutil = "^2.9.0"

[tool.poetry.dev-dependencies]
pytest = "^7.2.0"
ruff = "^0.1.3"
pytest = "^8.1.1"
ruff = "^0.3.4"

[tool.pyright]
reportMissingTypeStubs = false
Expand All @@ -37,17 +39,24 @@ typeCheckingMode = "strict"
[tool.ruff]
# Keep in sync with .pre-commit-config.yaml
line-length = 120
ignore = []
lint.ignore = []
target-version = "py310"
select = ["E", "W", "F", "I", "T", "RUF", "TID", "UP"]
lint.select = ["E", "W", "F", "I", "T", "RUF", "TID", "UP"]
include =["*.py"]

[tool.ruff.pydocstyle]
[tool.ruff.lint.pydocstyle]
convention = "google"

[tool.ruff.isort]
[tool.ruff.lint.isort]
lines-after-imports = 2

[tool.pytest.ini_options]
minversion = "8.0"
pythonpath = "temp/tests/Python"
testpaths = [
"temp/tests/Python",
]

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
4 changes: 2 additions & 2 deletions src/Fable.Build/FableLibrary/Python.fs
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ type BuildFableLibraryPython() =

Directory.GetFiles(linkedFileFolder, "*") |> Shell.copyFiles this.OutDir

Shell.deleteDir (this.BuildDir </> "fable_library/fable-library")
Shell.deleteDir (this.BuildDir </> "fable_library/fable-library-ts")

// Install the python dependencies at the root of the project
Command.Run("poetry", "install")

// Run Ruff linter checking import sorting and fix any issues
Command.Run("poetry", $"run ruff --select I --fix {this.BuildDir}")
Command.Run("poetry", $"run ruff check --select I --fix {this.BuildDir}")
// Run Ruff formatter on all generated files
Command.Run("poetry", $"run ruff format {this.BuildDir}")
4 changes: 4 additions & 0 deletions src/Fable.Cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

* [JS/TS] Add `ConditionalWeakTable` (by @chkn)

### fixed

* [GH-3778](https://github.com/fable-compiler/Fable/issues/3778) [Python] Fixed custom hash values on Record types (by @dbrattli)

## 4.15.0 - 2024-03-18

### Fixed
Expand Down
40 changes: 14 additions & 26 deletions src/fable-library-py/fable_library/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@ class IDisposable(ABC):
__slots__ = ()

@abstractmethod
def Dispose(self) -> None:
...
def Dispose(self) -> None: ...

def __enter__(self):
"""Enter context management."""
Expand Down Expand Up @@ -155,8 +154,7 @@ class IComparer(Protocol):

@property
@abstractmethod
def Compare(self) -> Callable[[_T_in, _T_in], int]:
...
def Compare(self) -> Callable[[_T_in, _T_in], int]: ...


class IComparer_1(Generic[_T_in], Protocol):
Expand All @@ -167,8 +165,7 @@ class IComparer_1(Generic[_T_in], Protocol):

@property
@abstractmethod
def Compare(self) -> Callable[[_T_in, _T_in], int]:
...
def Compare(self) -> Callable[[_T_in, _T_in], int]: ...


class IEqualityComparer(Protocol):
Expand Down Expand Up @@ -420,8 +417,7 @@ def pad_left_and_right_with_zeros(i: int, length_left: int, length_right: int) -


class Atom(Generic[_T], Protocol):
def __call__(self, *value: _T) -> _T | None:
...
def __call__(self, *value: _T) -> _T | None: ...


def create_atom(value: _T) -> Atom[_T]:
Expand Down Expand Up @@ -506,19 +502,16 @@ def Reset(self) -> None:
return self.System_Collections_IEnumerator_Reset()

@abstractmethod
def System_Collections_Generic_IEnumerator_1_get_Current(self) -> _T:
...
def System_Collections_Generic_IEnumerator_1_get_Current(self) -> _T: ...

def System_Collections_IEnumerator_get_Current(self) -> Any:
return self.System_Collections_Generic_IEnumerator_1_get_Current()

@abstractmethod
def System_Collections_IEnumerator_MoveNext(self) -> bool:
...
def System_Collections_IEnumerator_MoveNext(self) -> bool: ...

@abstractmethod
def System_Collections_IEnumerator_Reset(self) -> None:
...
def System_Collections_IEnumerator_Reset(self) -> None: ...

def __iter__(self) -> Iterator[_T]:
return self
Expand All @@ -533,8 +526,7 @@ class IEnumerable(Iterable[Any], Protocol):
__slots__ = ()

@abstractmethod
def GetEnumerator(self) -> IEnumerator[Any]:
...
def GetEnumerator(self) -> IEnumerator[Any]: ...

def __iter__(self) -> Iterator[Any]:
return self.GetEnumerator()
Expand All @@ -544,24 +536,20 @@ class IEnumerable_1(Iterable[_T], Protocol):
__slots__ = ()

@abstractmethod
def GetEnumerator(self) -> IEnumerator[_T]:
...
def GetEnumerator(self) -> IEnumerator[_T]: ...

def __iter__(self) -> Iterator[_T]:
return self.GetEnumerator()


class ICollection(IEnumerable_1[_T], Protocol):
...
class ICollection(IEnumerable_1[_T], Protocol): ...


class IDictionary(ICollection[tuple[_Key, _Value]], Protocol):
@abstractmethod
def keys(self) -> IEnumerable_1[_Key]:
...
def keys(self) -> IEnumerable_1[_Key]: ...

def values(self) -> IEnumerable_1[_Value]:
...
def values(self) -> IEnumerable_1[_Value]: ...


class Enumerator(IEnumerator[_T]):
Expand Down Expand Up @@ -2627,10 +2615,10 @@ def safe_hash(x: Any) -> int:
return (
0
if x is None
else x.GetHashCode()
if is_hashable(x)
else hash(x)
if is_hashable_py(x)
else x.GetHashCode()
if is_hashable(x)
else number_hash(ObjectRef.id(x))
)

Expand Down
18 changes: 18 additions & 0 deletions tests/Python/TestNonRegression.fs
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,21 @@ let ``test nested type with custom equality works`` () =
equal x1 x2
equal y1 y2
equal y1 y3

[<CustomEquality>]
[<NoComparison>]
type MyRecord =

{Name : string; Age: int }

override this.Equals(that) =
this.GetHashCode() = that.GetHashCode()

/// Hash should just return age of person
override this.GetHashCode() =
this.Age

let ``test custom equality and hashcode works`` () =
let p1 = {Name = "John"; Age = 30}

equal 30 (p1.GetHashCode())

0 comments on commit c8c1c0d

Please sign in to comment.