Skip to content

Commit

Permalink
impl generated python Map
Browse files Browse the repository at this point in the history
Summary:
Pure python implementation of map, insofar as generated code is concerned. Most of the functions are implemented in cython base class.

The interesting part here are the `check_{key,val}_or_raise`, which are used in `__init__` to replicate the type checking done by the cpp conversions in cython. `__contains__` uses `_check_key_or_none` because it shouldn't raise, similar to current `_check_key_type`. This is also used by `__getitem__` since it doesn't want `TypeError` stacktrace, just a fresh `KeyError`.

Reviewed By: yoney

Differential Revision: D66275060

fbshipit-source-id: cf56801cb0012b9d24e79157fa81530df473dc59
  • Loading branch information
ahilger authored and facebook-github-bot committed Nov 25, 2024
1 parent 9f83204 commit d2265fd
Show file tree
Hide file tree
Showing 70 changed files with 4,354 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ want to include.
import thrift.py3.types
import importlib
from collections.abc import Sequence, Set
from collections.abc import Mapping, Sequence, Set
"""
This is a helper module to define py3 container types.
Expand Down Expand Up @@ -203,7 +203,99 @@ class {{type:flat_name}}(thrift.py3.types.Set):
Set.register({{type:flat_name}})
{{/type:set?}}{{^type:map?}}
__all__.append('{{type:flat_name}}')
{{/type:set?}}{{#type:map?}}
class {{type:flat_name}}(thrift.py3.types.MapNew):
{{! make the type appear to originate from .types module }}
__module__ = _fbthrift__module_name__
{{! __slots__ prevents accidental treatment as py-deprecated }}
__slots__ = ()
_FBTHRIFT_USE_SORTED_REPR = {{!
}}{{#type:defaultTemplate?}}True{{/type:defaultTemplate?}}{{!
}}{{^type:defaultTemplate?}}False{{/type:defaultTemplate?}}
def __init__(self, items=None, private_ctor_token=None) -> None:
if private_ctor_token is thrift.py3.types._fbthrift_map_private_ctor:
{{!
For internal use only, when items dict has been created internally
and each item has been converted from cpp so we can trust the type.
Do not use with user-exposed `dict` to avoid accidental mutability.
}}
_py_obj = items
elif isinstance(items, {{type:flat_name}}):
_py_obj = dict(items)
elif items is None:
_py_obj = dict()
else:
check_key = {{type:flat_name}}._check_key_type_or_raise
check_val = {{type:flat_name}}._check_val_type_or_raise
_py_obj = {check_key(k) : check_val(v) for k, v in items.items()}
super().__init__(_py_obj, {{type:flat_name}})
@staticmethod
def _check_key_type_or_raise(key):
{{#type:key_type}}
{{#type:container?}}
if key is None:
raise TypeError("None is not of the type {{> types/pep484_type}}")
if not isinstance(key, {{> types/python_type}}):
key = {{> types/python_type}}(key)
{{/type:container?}}
{{^type:container?}}
if not (
isinstance(key, {{> types/python_is_instance_type}}){{#type:enum?}} or
isinstance(key, thrift.py3.types.BadEnum){{/type:enum?}}
):
raise TypeError(f"{key!r} is not of type {{> types/pep484_type}}")
{{/type:container?}}
{{/type:key_type}}
return key
{{! __contains__ doesn't raise TypeError; __getitem__ uses KeyError }}
@staticmethod
def _check_key_type_or_none(key):
if key is None:
return None
{{#type:key_type}}
if isinstance(key, {{> types/python_type}}):
return key
{{#type:container?}}
try:
return {{> types/python_type}}(key)
except:
return None
{{/type:container?}}
{{/type:key_type}}

@staticmethod
def _check_val_type_or_raise(item):
{{#type:value_type}}
{{#type:container?}}
if item is None:
raise TypeError("None is not of the type {{> types/pep484_type}}")
if not isinstance(item, {{> types/python_type}}):
item = {{> types/python_type}}(item)
{{/type:container?}}
{{^type:container?}}
if not (
isinstance(item, {{> types/python_is_instance_type}}){{#type:enum?}} or
isinstance(item, thrift.py3.types.BadEnum){{/type:enum?}}
):
raise TypeError(f"{item!r} is not of type {{> types/pep484_type}}")
{{/type:container?}}
{{/type:value_type}}
return item

@staticmethod
def __get_reflection__():
return get_types_reflection().get_reflection__{{type:flat_name}}()


Mapping.register({{type:flat_name}})
{{/type:map?}}
__all__.append('{{type:flat_name}}')


{{/program:containerTypes}}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import thrift.py3.types
import importlib
from collections.abc import Sequence, Set
from collections.abc import Mapping, Sequence, Set

"""
This is a helper module to define py3 container types.
Expand Down Expand Up @@ -69,3 +69,5 @@ def __get_reflection__():
Sequence.register(std_deque_std_string__List__string)

__all__.append('std_deque_std_string__List__string')


Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import thrift.py3.types
import importlib
from collections.abc import Sequence, Set
from collections.abc import Mapping, Sequence, Set

"""
This is a helper module to define py3 container types.
Expand All @@ -27,3 +27,56 @@ def get_types_reflection():

__all__ = []

class Map__MyEnum_string(thrift.py3.types.MapNew):
__module__ = _fbthrift__module_name__
__slots__ = ()

_FBTHRIFT_USE_SORTED_REPR = True

def __init__(self, items=None, private_ctor_token=None) -> None:
if private_ctor_token is thrift.py3.types._fbthrift_map_private_ctor:
_py_obj = items
elif isinstance(items, Map__MyEnum_string):
_py_obj = dict(items)
elif items is None:
_py_obj = dict()
else:
check_key = Map__MyEnum_string._check_key_type_or_raise
check_val = Map__MyEnum_string._check_val_type_or_raise
_py_obj = {check_key(k) : check_val(v) for k, v in items.items()}

super().__init__(_py_obj, Map__MyEnum_string)

@staticmethod
def _check_key_type_or_raise(key):
if not (
isinstance(key, _test_fixtures_enumstrict_module_types.MyEnum) or
isinstance(key, thrift.py3.types.BadEnum)
):
raise TypeError(f"{key!r} is not of type _test_fixtures_enumstrict_module_types.MyEnum")
return key

@staticmethod
def _check_key_type_or_none(key):
if key is None:
return None
if isinstance(key, _test_fixtures_enumstrict_module_types.MyEnum):
return key

@staticmethod
def _check_val_type_or_raise(item):
if not (
isinstance(item, str)
):
raise TypeError(f"{item!r} is not of type str")
return item

@staticmethod
def __get_reflection__():
return get_types_reflection().get_reflection__Map__MyEnum_string()


Mapping.register(Map__MyEnum_string)
__all__.append('Map__MyEnum_string')


Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import thrift.py3.types
import importlib
from collections.abc import Sequence, Set
from collections.abc import Mapping, Sequence, Set

"""
This is a helper module to define py3 container types.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import thrift.py3.types
import importlib
from collections.abc import Sequence, Set
from collections.abc import Mapping, Sequence, Set

"""
This is a helper module to define py3 container types.
Expand Down Expand Up @@ -65,7 +65,10 @@ def __get_reflection__():


Set.register(Set__float)

__all__.append('Set__float')


class List__i32(thrift.py3.types.List):
__module__ = _fbthrift__module_name__
__slots__ = ()
Expand Down Expand Up @@ -106,6 +109,8 @@ def __get_reflection__():
Sequence.register(List__i32)

__all__.append('List__i32')


class Set__string(thrift.py3.types.Set):
__module__ = _fbthrift__module_name__
__slots__ = ()
Expand Down Expand Up @@ -146,4 +151,111 @@ def __get_reflection__():


Set.register(Set__string)

__all__.append('Set__string')


class Map__string_i64(thrift.py3.types.MapNew):
__module__ = _fbthrift__module_name__
__slots__ = ()

_FBTHRIFT_USE_SORTED_REPR = True

def __init__(self, items=None, private_ctor_token=None) -> None:
if private_ctor_token is thrift.py3.types._fbthrift_map_private_ctor:
_py_obj = items
elif isinstance(items, Map__string_i64):
_py_obj = dict(items)
elif items is None:
_py_obj = dict()
else:
check_key = Map__string_i64._check_key_type_or_raise
check_val = Map__string_i64._check_val_type_or_raise
_py_obj = {check_key(k) : check_val(v) for k, v in items.items()}

super().__init__(_py_obj, Map__string_i64)

@staticmethod
def _check_key_type_or_raise(key):
if not (
isinstance(key, str)
):
raise TypeError(f"{key!r} is not of type str")
return key

@staticmethod
def _check_key_type_or_none(key):
if key is None:
return None
if isinstance(key, str):
return key

@staticmethod
def _check_val_type_or_raise(item):
if not (
isinstance(item, int)
):
raise TypeError(f"{item!r} is not of type int")
return item

@staticmethod
def __get_reflection__():
return get_types_reflection().get_reflection__Map__string_i64()


Mapping.register(Map__string_i64)
__all__.append('Map__string_i64')


class Map__string_List__i32(thrift.py3.types.MapNew):
__module__ = _fbthrift__module_name__
__slots__ = ()

_FBTHRIFT_USE_SORTED_REPR = True

def __init__(self, items=None, private_ctor_token=None) -> None:
if private_ctor_token is thrift.py3.types._fbthrift_map_private_ctor:
_py_obj = items
elif isinstance(items, Map__string_List__i32):
_py_obj = dict(items)
elif items is None:
_py_obj = dict()
else:
check_key = Map__string_List__i32._check_key_type_or_raise
check_val = Map__string_List__i32._check_val_type_or_raise
_py_obj = {check_key(k) : check_val(v) for k, v in items.items()}

super().__init__(_py_obj, Map__string_List__i32)

@staticmethod
def _check_key_type_or_raise(key):
if not (
isinstance(key, str)
):
raise TypeError(f"{key!r} is not of type str")
return key

@staticmethod
def _check_key_type_or_none(key):
if key is None:
return None
if isinstance(key, str):
return key

@staticmethod
def _check_val_type_or_raise(item):
if item is None:
raise TypeError("None is not of the type _typing.Sequence[int]")
if not isinstance(item, _test_fixtures_basic_module_types.List__i32):
item = _test_fixtures_basic_module_types.List__i32(item)
return item

@staticmethod
def __get_reflection__():
return get_types_reflection().get_reflection__Map__string_List__i32()


Mapping.register(Map__string_List__i32)
__all__.append('Map__string_List__i32')


Loading

0 comments on commit d2265fd

Please sign in to comment.