Commit 783fe764 authored by Pierre Augier's avatar Pierre Augier
Browse files

typing Set

parent 9575cd4039a0
Short term (Milestones for 0.4.0)
---------------------------------
- Set
Full support of https://pythran.readthedocs.io/en/latest/MANUAL.html#concerning-pythran-specifications
- Tuple
- mem_layout for arrays (C, F, C_or_F, strided)
- fixed dimension for arrays
- alternative make_header_from_fdef_annotations for Cython
setup.py & more than one backend at runtime
......
......@@ -64,6 +64,7 @@ show_missing = True
exclude_lines =
raise ValueError
raise NotImplementedError
raise RunTimeError
raise ImportError
except ImportError:
except ModuleNotFoundError:
......
......@@ -62,6 +62,9 @@ class TypeFormatterCython(TypeFormatter):
def make_dict_code(self, type_keys, type_values, **kwargs):
return "dict"
def make_set_code(self, type_keys, **kwargs):
return "set"
def make_list_code(self, type_elem, **kwargs):
return "list"
......
......@@ -24,6 +24,10 @@ class TypeFormatter:
value = format_type_as_backend_type(type_values, self, **kwargs)
return f"{key}: {value} dict"
def make_set_code(self, type_keys, **kwargs):
key = format_type_as_backend_type(type_keys, self, **kwargs)
return f"{key} set"
def make_list_code(self, type_elem, **kwargs):
return format_type_as_backend_type(type_elem, self, **kwargs) + " list"
......
......@@ -9,6 +9,8 @@ from transonic.typing import (
ListMeta,
Dict,
DictMeta,
Set,
SetMeta,
analyze_array_type,
typeof,
)
......@@ -36,7 +38,6 @@ def test_NDim():
def test_str2type_simple():
str2type("int") == np.int
str2type("float") == np.float
......@@ -62,16 +63,27 @@ def test_str2type_or():
def test_list():
L = List[List[int]]
repr(L)
assert isinstance(L, ListMeta)
assert L.format_as_backend_type(base_type_formatter) == "int list list"
def test_dict():
D = Dict[str, int]
repr(D)
assert isinstance(D, DictMeta)
assert D.format_as_backend_type(base_type_formatter) == "str: int dict"
def test_set():
str2type("int set")
S = Set["str"]
S.get_template_parameters()
repr(S)
assert isinstance(S, SetMeta)
assert S.format_as_backend_type(base_type_formatter) == "str set"
def test_float0():
dtype, ndim = analyze_array_type("float[]")
assert dtype == "np.float"
......@@ -103,6 +115,12 @@ def test_typeof_dict():
assert D.format_as_backend_type(base_type_formatter) == "str: int dict"
def test_typeof_set():
S = typeof({"a", "b"})
assert isinstance(S, SetMeta)
assert S.format_as_backend_type(base_type_formatter) == "str set"
def test_typeof_array():
A = typeof(np.ones((2, 2)))
compare_array_types(A, Array[np.float64, "2d"])
......
......@@ -193,7 +193,6 @@ class NDim(TemplateVar):
class UnionVar(TemplateVar):
_type_values = type
_letter = "U"
......@@ -339,8 +338,6 @@ class ArrayMeta(type):
class Array(metaclass=ArrayMeta):
"""Represent a Numpy array in type hinname_calling_module"""
pass
class UnionMeta(type):
"""Metaclass for the Union class"""
......@@ -391,8 +388,6 @@ class Union(metaclass=UnionMeta):
"""
pass
class ListMeta(type):
"""Metaclass for the List class"""
......@@ -425,8 +420,6 @@ class List(metaclass=ListMeta):
"""
pass
class DictMeta(type):
"""Metaclass for the Dict class"""
......@@ -475,7 +468,38 @@ class Dict(metaclass=DictMeta):
"""
pass
class SetMeta(type):
"""Metaclass for the Set class"""
def __getitem__(self, type_keys):
if isinstance(type_keys, str):
type_keys = str2type(type_keys)
return type("SetBis", (Set,), {"type_keys": type_keys})
def get_template_parameters(self):
if hasattr(self.type_keys, "get_template_parameters"):
return self.type_keys.get_template_parameters()
else:
return tuple()
def __repr__(self):
if isinstance(self.type_keys, type):
key = self.type_keys.__name__
else:
key = repr(self.type_keys)
return f"Set[{key}]"
def format_as_backend_type(self, backend_type_formatter, **kwargs):
return backend_type_formatter.make_set_code(self.type_keys, **kwargs)
class Set(metaclass=SetMeta):
"""Similar to typing.Set
>>> S = Set[str]
"""
def format_type_as_backend_type(type_, backend_type_formatter, **kwargs):
......@@ -489,8 +513,7 @@ def format_type_as_backend_type(type_, backend_type_formatter, **kwargs):
elif hasattr(type_, "__name__"):
backend_type = type_.__name__
else:
print(type_)
raise RuntimeError
raise RuntimeError(f"type_: {type_}")
assert backend_type is not None
......@@ -530,12 +553,17 @@ def str2type(str_type):
if words[-1] == "dict":
if len(words) != 3:
print(words)
raise NotImplementedError
raise NotImplementedError(f"words: {words}")
key = words[0][:-1]
value = words[1]
return Dict[key, value]
if words[-1] == "set":
if len(words) != 2:
raise NotImplementedError(f"words: {words}")
key = words[0]
return Set[key]
dtype, ndim = analyze_array_type(str_type)
dtype = eval(dtype, {"np": np})
......@@ -574,29 +602,32 @@ def typeof(obj):
return List[typeof(obj[0])]
if isinstance(obj, dict):
key = next(iter(obj.keys()))
if isinstance(obj, (dict, set)):
key = next(iter(obj))
type_key = type(key)
if not all(isinstance(key, type_key) for key in obj.keys()):
raise ValueError("The dict {obj} is not homogeneous in type")
value = next(iter(obj.values()))
type_value = type(value)
if not all(isinstance(value, type_value) for value in obj.values()):
if not all(isinstance(key, type_key) for key in obj):
raise ValueError("The dict {obj} is not homogeneous in type")
return Dict[typeof(key), typeof(value)]
if isinstance(obj, dict):
value = next(iter(obj.values()))
type_value = type(value)
if not all(isinstance(value, type_value) for value in obj.values()):
raise ValueError("The dict {obj} is not homogeneous in type")
return Dict[typeof(key), typeof(value)]
else:
return Set[typeof(key)]
# TODO: isinstance(obj, set)
# TODO: Tuple
if isinstance(obj, tuple):
raise NotImplementedError
if isinstance(obj, np.ndarray):
if np.isscalar(obj):
return obj.dtype.type
# TODO: deeper analysis
return Array[obj.dtype, f"{obj.ndim}d"]
if np.isscalar(obj):
return obj.dtype.type
raise NotImplementedError(
f"Not able to determine the full type of {obj} (of type {type(obj)})"
)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment