22# Note: We shouldn't ever need to use this directly. We should go via the apispec converter
33from apispec .ext .marshmallow .field_converter import DEFAULT_FIELD_MAPPING
44
5- from . import fields
5+ from labthings .server import fields
6+ from labthings .core .utilities import rapply
7+
8+ from labthings .server .schema import Schema
69
710# Extra standard library Python types
811from datetime import date , datetime , time , timedelta
912from decimal import Decimal
1013from typing import Dict , List , Tuple , Union
1114from uuid import UUID
1215
16+ import inspect
17+ import copy
18+
1319"""
1420TODO: Use this to convert arbitrary dictionary into its own schema, for W3C TD
1521
@@ -59,8 +65,54 @@ def to_string(o):
5965 "fractions.Fraction" : to_float ,
6066}
6167
68+
69+ def make_primative (value ):
70+ global DEFAULT_BUILTIN_CONVERSIONS , DEFAULT_TYPE_MAPPING
71+
72+ value_typestrings = [x .__module__ + "." + x .__name__ for x in inspect .getmro (type (value ))]
73+
74+ for typestring in value_typestrings :
75+ if typestring in DEFAULT_BUILTIN_CONVERSIONS :
76+ value = DEFAULT_BUILTIN_CONVERSIONS .get (typestring )(value )
77+ break
78+
79+ # If the final type is not primative
80+ if not type (value ) in DEFAULT_TYPE_MAPPING :
81+ # Fall back to a string representation
82+ value = str (value )
83+
84+ return value
85+
86+
87+ def value_to_field (value ):
88+ global DEFAULT_TYPE_MAPPING
89+ if type (value ) in DEFAULT_TYPE_MAPPING :
90+ return DEFAULT_TYPE_MAPPING .get (type (value ))(example = value )
91+ else :
92+ raise TypeError (f"Unsupported data type { type (value )} " )
93+
94+
95+ def data_dict_to_schema (data_dict ):
96+ working_dict = copy .deepcopy (data_dict )
97+ working_dict = rapply (working_dict , make_primative )
98+
99+ working_dict = rapply (working_dict , value_to_field )
100+ return Schema .from_dict (working_dict )
101+
62102# TODO: Deserialiser with inverse defaults
63103# TODO: Option to switch to .npy serialisation/deserialisation (or look for a better common array format)
64104
65- # Use with [x.__module__+"."+x.__name__ for x in inspect.getmro(type(POSSIBLE_MATCHER))]
66- # Resulting array will contain strings with the same format as keys in DEFAULT_BUILTIN_CONVERSIONS
105+ """
106+ # TODO: MOVE TO UNIT TESTS
107+ from fractions import Fraction
108+
109+ d = {
110+ "val1": Fraction(5,2),
111+ "map1": {
112+ "subval1": "Hello",
113+ "subval2": False
114+ },
115+ "val2": 5
116+ }
117+
118+ """
0 commit comments