Skip to content

Commit

Permalink
BREAKING: kw onlyh args and overloads for `calculate_implied_probabil…
Browse files Browse the repository at this point in the history
…ities`

Makes all arguments other than `odds` kw only, this drastically reduces the number of required overloads to type the signature properly.

```py
# still works
calculate_implied_probabilities([2.0, 2.0])
calculate_implied_probabilities(odds=[2.0, 2.0])
calculate_implied_probabilities([2.0, 2.0], full_output=True)
## also any other combination of passing arguments as keyword args remains the same

# patterns of passing any arg other than `odds` as positional breaks
calculate_implied_probabilibies([2.0, 2.0], 1000)
calculate_impolied_probabilities([2.0, 2.0], 1000, 1e-12, True)
```

This encourages clarity at the callsite and also helps from a library perspective as it is easier to add new kw only args to an api without breaking downstream.

Adds overloads and tests for combination of input types and value of `full_output` flag.
  • Loading branch information
peterschutt authored and mberk committed Feb 22, 2024
1 parent 2d588fe commit 06a4ce9
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 1 deletion.
42 changes: 41 additions & 1 deletion python/shin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from collections.abc import Mapping, Sequence
from math import sqrt
from typing import Any
from typing import Any, Literal, overload

from .shin import optimise as _optimise_rust

Expand Down Expand Up @@ -31,8 +31,48 @@ def _optimise(
return z, delta, iterations


# sequence input, full output False
@overload
def calculate_implied_probabilities(
odds: Sequence[float],
*,
max_iterations: int = ...,
convergence_threshold: float = ...,
full_output: Literal[False] = False,
force_python_optimiser: bool = ...,
) -> list[float]:
...


# mapping, full output False
@overload
def calculate_implied_probabilities(
odds: Mapping[Any, float],
*,
max_iterations: int = ...,
convergence_threshold: float = ...,
full_output: Literal[False] = False,
force_python_optimiser: bool = ...,
) -> dict[Any, float]:
...


# full output True
@overload
def calculate_implied_probabilities(
odds: Sequence[float] | Mapping[Any, float],
*,
max_iterations: int = ...,
convergence_threshold: float = ...,
full_output: Literal[True],
force_python_optimiser: bool = ...,
) -> dict[str, Any]:
...


def calculate_implied_probabilities(
odds: Sequence[float] | Mapping[Any, float],
*,
max_iterations: int = 1000,
convergence_threshold: float = 1e-12,
full_output: bool = False,
Expand Down
32 changes: 32 additions & 0 deletions typesafety/test_shin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,35 @@
reveal_type(shin.optimise)
out: |
main:3: note: Revealed type is "def (inverse_odds: builtins.list[builtins.float], sum_inverse_odds: builtins.float, n: builtins.int, max_iterations: builtins.int =, convergence_threshold: builtins.float =) -> tuple[builtins.float, builtins.float, builtins.float]"
- case: test_sequence_input_overload
main: |
import shin
reveal_type(shin.calculate_implied_probabilities([3.0, 3.0, 3.0]))
out: |
main:3: note: Revealed type is "builtins.list[builtins.float]"
- case: test_mapping_input_overload
main: |
import shin
reveal_type(shin.calculate_implied_probabilities({1: 3.0, 2: 3.0, 3: 3.0}))
out: |
main:3: note: Revealed type is "builtins.dict[Any, builtins.float]"
- case: test_sequence_input_full_output_overload
main: |
import shin
reveal_type(shin.calculate_implied_probabilities([3.0, 3.0, 3.0], full_output=True))
out: |
main:3: note: Revealed type is "builtins.dict[builtins.str, Any]"
- case: test_mapping_input_full_output_overload
main: |
import shin
reveal_type(shin.calculate_implied_probabilities({1: 3.0, 2: 3.0, 3: 3.0}, full_output=True))
out: |
main:3: note: Revealed type is "builtins.dict[builtins.str, Any]"

0 comments on commit 06a4ce9

Please sign in to comment.