You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by hu...@apache.org on 2023/01/26 17:47:38 UTC

[superset] branch api-contracts created (now c0381b756d)

This is an automated email from the ASF dual-hosted git repository.

hugh pushed a change to branch api-contracts
in repository https://gitbox.apache.org/repos/asf/superset.git


      at c0381b756d first iteration

This branch includes the following new commits:

     new c0381b756d first iteration

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[superset] 01/01: first iteration

Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

hugh pushed a commit to branch api-contracts
in repository https://gitbox.apache.org/repos/asf/superset.git

commit c0381b756dc1f84bd172a7288228d54b7bebe3b0
Author: hughhhh <hu...@gmail.com>
AuthorDate: Thu Jan 26 19:47:19 2023 +0200

    first iteration
---
 api_to_ts.py           | 12 +++++++
 output.ts              |  6 ++++
 superset/typemallow.py | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 104 insertions(+)

diff --git a/api_to_ts.py b/api_to_ts.py
new file mode 100644
index 0000000000..6a5516b027
--- /dev/null
+++ b/api_to_ts.py
@@ -0,0 +1,12 @@
+from superset import typemallow as tm
+from marshmallow import Schema, fields
+
+
+@tm.ts_interface()
+class Foo(Schema):
+    some_field_one = fields.Str(required=True)
+    another_field = fields.Date()
+    one_more_field = fields.Integer()
+
+
+tm.generate_ts('./output.ts')
\ No newline at end of file
diff --git a/output.ts b/output.ts
new file mode 100644
index 0000000000..bdea128497
--- /dev/null
+++ b/output.ts
@@ -0,0 +1,6 @@
+export interface Foo {
+	some_field_one?: string;
+	another_field?: any;
+	one_more_field?: number;
+}
+
diff --git a/superset/typemallow.py b/superset/typemallow.py
new file mode 100644
index 0000000000..507874885f
--- /dev/null
+++ b/superset/typemallow.py
@@ -0,0 +1,86 @@
+from marshmallow import Schema, fields
+
+mappings = {
+    fields.Bool: 'boolean',
+    fields.Boolean: 'boolean',
+    fields.Constant: 'any',
+    fields.DateTime: 'Date',
+    fields.Decimal: 'number',
+    fields.Dict: 'object',
+    fields.Email: 'string',
+    fields.Field: 'any',
+    fields.Float: 'number',
+    fields.Function: 'any',
+    fields.Int: 'number',
+    fields.Integer: 'number',
+    fields.List: 'any[]',
+    fields.Mapping: 'any',
+    fields.Method: 'any',
+    fields.Number: 'number',
+    fields.Raw: 'any',
+    fields.Str: 'string',
+    fields.String: 'string',
+    fields.TimeDelta: 'any',
+    fields.Url: 'string',
+    fields.UUID: 'string',
+}
+
+__schemas = dict()
+
+def ts_interface(context='default'):
+    '''
+    Any valid Marshmallow schemas with this class decorator will 
+    be added to a list in a dictionary. An optional parameter: 'context'
+    may be provided, which will create separate dictionary keys per context.
+    Otherwise, all values will be inserted into a list with a key of 'default'.
+    e.g.
+    @ts_interface(context='internal')
+    class Foo(Schema):
+        first_field = fields.Integer()
+    '''
+    def decorator(cls):
+        if issubclass(cls, Schema):
+            if not context in __schemas:
+                __schemas[context] = []
+            __schemas[context].append(cls)
+        return cls
+    return decorator
+
+
+def __get_ts_interface(schema):
+    '''
+    Generates and returns a Typescript Interface by iterating
+    through the declared Marshmallow fields of the Marshmallow Schema class
+    passed in as a parameter, and mapping them to the appropriate Typescript
+    data type.
+    '''
+    name = schema.__name__.replace('Schema', '')
+    ts_fields = []
+    for key, value in schema._declared_fields.items():
+        if isinstance(value, fields.Nested):
+            ts_type = value.nested.__name__.replace('Schema', '')
+            if value.many:
+                ts_type += '[]'
+        else:
+            ts_type = mappings.get(type(value), 'any')
+
+        ts_fields.append(
+            f'\t{key}: {ts_type};'
+        )
+    ts_fields = '\n'.join(ts_fields)
+    return f'export interface {name} {{\n{ts_fields}\n}}\n\n'
+
+
+def generate_ts(output_path, context='default'):
+    '''
+    When this function is called, a Typescript interface will be generated
+    for each Marshmallow schema in the schemas dictionary, depending on the
+    optional context parameter provided. If the parameter is ignored, all
+    schemas in the default value, 'default' will be iterated over and a list
+    of Typescript interfaces will be returned via a list comprehension.
+    
+    The Typescript interfaces will then be outputted to the file provided.
+    '''
+    with open(output_path, 'w') as output_file:
+        interfaces = [__get_ts_interface(schema) for schema in __schemas[context]]
+        output_file.write(''.join(interfaces))
\ No newline at end of file