Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@feuGeneA
Last active July 25, 2019 16:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save feuGeneA/5a217c18b245364e0ef01a6784f86844 to your computer and use it in GitHub Desktop.
Save feuGeneA/5a217c18b245364e0ef01a6784f86844 to your computer and use it in GitHub Desktop.
More brainstorming on types for mesh simulation engine options
"""More brainstorming on types for mesh simulation engine options."""
# the following comment was taken from p2p_incentives/example.py:
# Any option choice is a dictionary. It must contain a key "method," to
# specify which implementation function to call. The rest entries, if any,
# are the parameters specific to this implementation that will be passed to
# the function.
# This comment could be formally specified in code as:
from mypy_extensions import TypedDict
class Option(TypedDict):
"""An option choice."""
method: str # which implementation function to call
# However, that doesn't really help us like I thought it would, because a class
# inheriting from Option cannot redefine the type of an attribute. That is, we
# would like to say:
#
# class Preference(Option):
# method = 'Passive'
#
# but then mypy says 'Cannot overwrite TypedDict field "method" while
# extending'. So maybe the multi-level TypedDict inheritance idea isn't so
# great after all.
# But I did discover Literal Types in mypy, described in detail at
# https://mypy.readthedocs.io/en/stable/literal_types.html , which we can use
# like this:
from typing_extensions import Literal # requires `pip install typing-extensions`
class Preference(TypedDict):
"""Preferences for neighbors."""
method: Literal['Passive', 'SomeOtherMethodThatsNotPassive']
# this says that method is a literal string that must have one of those values
# ('Passive', or the other one). That is,
#
# preference = Preference(method='RogueMethod')
#
# results in mypy saying "Incompatible types".
# here's how we would use this:
PREFERENCE: Preference = Preference(method='Passive')
# And here's an example of using this technique with an option whose method has
# parameters:
class Share(TypedDict):
"""How to determine the orders to share with neighbors."""
method: Literal[
'AllNewSelectedOld',
'SomeOtherMethodThatsNotAllNewSelectedOld'
]
class AllNewSelectedOld(Share):
max_to_share: int
old_share_prob: float
SHARE: Share = AllNewSelectedOld(
method='AllNewSelectedOld',
max_to_share=5000,
old_share_prob=0.5
)
# Overall I like this approach, despite the annoying redundancy in having to
# specify method='AllNewSelectedOld' in the value declaration.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment