[CORD-1539] Static choices from xproto to GUI
Change-Id: I7ad877884c7803bb64c086c860b73c48951f5231
diff --git a/lib/xos-genx/tests/translator_test.py b/lib/xos-genx/tests/translator_test.py
index 40e1b50..e82af6d 100644
--- a/lib/xos-genx/tests/translator_test.py
+++ b/lib/xos-genx/tests/translator_test.py
@@ -153,6 +153,81 @@
self.assertEqual(len(yaml_ir['items']), 1)
self.assertIn('name', output)
self.assertNotIn('secret', output)
+
+ def test_static_options(self):
+ xproto = \
+"""
+option app_label = "test";
+
+message Foo {
+ required string name = 1 [ null = "False", blank="False"];
+ required string isolation = 14 [default = "vm", choices = "(('vm', 'Virtual Machine'), ('container', 'Container'), ('container_vm', 'Container In VM'))", max_length = 30, blank = False, null = False, db_index = False];
+}
+"""
+
+ args = FakeArgs()
+ args.inputs = xproto
+ args.target = 'modeldefs.xtarget'
+ output = XOSGenerator.generate(args)
+ self.assertIn("options:", output)
+ self.assertIn(" {'id': 'container_vm', 'label': 'Container In VM'}", output)
+
+ def test_not_static_options(self):
+ xproto = \
+"""
+option app_label = "test";
+
+message Foo {
+ required string name = 1 [ null = "False", blank="False"];
+}
+"""
+
+ args = FakeArgs()
+ args.inputs = xproto
+ args.target = 'modeldefs.xtarget'
+ output = XOSGenerator.generate(args)
+ self.assertNotIn("options:", output)
+
+ def test_default_value_in_modeldef(self):
+ xproto = \
+"""
+option app_label = "test";
+
+message Foo {
+ required string name = 1 [ null = "False", blank="False", default = "bar"];
+ required string falsetrue = 1 [ null = "False", blank="False", default = False];
+ required string truefalse = 1 [ null = "False", blank="False", default = True];
+ required string some = 1 [ null = "False", blank="False", default = None];
+ required string zero = 1 [ null = "False", blank="False", default = 0];
+}
+"""
+
+ args = FakeArgs()
+ args.inputs = xproto
+ args.target = 'modeldefs.xtarget'
+ output = XOSGenerator.generate(args)
+ self.assertIn('default: "bar"', output)
+ self.assertIn('default: "false"', output)
+ self.assertIn('default: "true"', output)
+ self.assertIn('default: "null"', output)
+ self.assertIn('default: "0"', output)
+
+ def test_not_default_value_in_modeldef(self):
+ xproto = \
+"""
+option app_label = "test";
+
+message Foo {
+ required string name = 1 [ null = "False", blank="False"];
+}
+"""
+
+ args = FakeArgs()
+ args.inputs = xproto
+ args.target = 'modeldefs.xtarget'
+ output = XOSGenerator.generate(args)
+ self.assertNotIn('default:', output)
+
if __name__ == '__main__':
unittest.main()
diff --git a/lib/xos-genx/xosgenx/jinja2_extensions/__init__.py b/lib/xos-genx/xosgenx/jinja2_extensions/__init__.py
index ea30100..ad03907 100644
--- a/lib/xos-genx/xosgenx/jinja2_extensions/__init__.py
+++ b/lib/xos-genx/xosgenx/jinja2_extensions/__init__.py
@@ -1,3 +1,4 @@
from .django import *
from .base import *
from .fol2 import *
+from .gui import *
diff --git a/lib/xos-genx/xosgenx/jinja2_extensions/base.py b/lib/xos-genx/xosgenx/jinja2_extensions/base.py
index c15bf32..3cb9886 100644
--- a/lib/xos-genx/xosgenx/jinja2_extensions/base.py
+++ b/lib/xos-genx/xosgenx/jinja2_extensions/base.py
@@ -16,6 +16,8 @@
def unquote(s):
if (s.startswith('"') and s.endswith('"')):
return s[1:-1]
+ else:
+ return s
def xproto_singularize(field):
try:
@@ -151,44 +153,6 @@
links.extend(model_links)
return links
-
-def xproto_validators(f):
- # To be cleaned up when we formalize validation in xproto
- validators = []
-
- # bound-based validators
- bound_validators = [('max_length','maxlength'), ('min', 'min'), ('max', 'max')]
-
- for v0, v1 in bound_validators:
- try:
- validators.append({'name':v1, 'int_value':int(f['options'][v0])})
- except KeyError:
- pass
-
- # validators based on content_type
- content_type_validators = ['ip', 'url', 'email']
-
- for v in content_type_validators:
- #if f['name']=='ip': pdb.set_trace()
- try:
- val = unquote(f['options']['content_type'])==v
- if not val:
- raise KeyError
-
- validators.append({'name':v, 'bool_value': True})
- except KeyError:
- pass
-
- # required validator
- try:
- required = f['options']['blank']=='False' and f['options']['null']=='False'
- if required:
- validators.append({'name':'required', 'bool_value':required})
- except KeyError:
- pass
-
- return validators
-
def xproto_string_type(xptags):
try:
max_length = eval(xptags['max_length'])
@@ -200,25 +164,6 @@
else:
return 'text'
-def xproto_type_to_ui_type(f):
- try:
- content_type = f['options']['content_type']
- content_type = eval(content_type)
- except:
- content_type = None
- pass
-
- if content_type == 'date':
- return 'date'
- elif f['type'] == 'bool':
- return 'boolean'
- elif f['type'] == 'string':
- return xproto_string_type(f['options'])
- elif f['type'] in ['int','uint32','int32'] or 'link' in f:
- return 'number'
- elif f['type'] in ['double','float']:
- return 'string'
-
def xproto_tuplify(nested_list_or_set):
if not isinstance(nested_list_or_set, list) and not isinstance(nested_list_or_set, set):
return nested_list_or_set
diff --git a/lib/xos-genx/xosgenx/jinja2_extensions/gui.py b/lib/xos-genx/xosgenx/jinja2_extensions/gui.py
new file mode 100644
index 0000000..bd23fdb
--- /dev/null
+++ b/lib/xos-genx/xosgenx/jinja2_extensions/gui.py
@@ -0,0 +1,90 @@
+from base import xproto_string_type, unquote
+
+def xproto_type_to_ui_type(f):
+ try:
+ content_type = f['options']['content_type']
+ content_type = eval(content_type)
+ except:
+ content_type = None
+ pass
+
+ if 'choices' in f['options']:
+ return 'select';
+ elif content_type == 'date':
+ return 'date'
+ elif f['type'] == 'bool':
+ return 'boolean'
+ elif f['type'] == 'string':
+ return xproto_string_type(f['options'])
+ elif f['type'] in ['int','uint32','int32'] or 'link' in f:
+ return 'number'
+ elif f['type'] in ['double','float']:
+ return 'string'
+
+def xproto_options_choices_to_dict(choices):
+ list = []
+
+ for c in eval(choices):
+ list.append({'id': c[0], 'label': c[1]})
+ if len(list) > 0:
+ return list
+ else:
+ return None
+
+def xproto_validators(f):
+ # To be cleaned up when we formalize validation in xproto
+ validators = []
+
+ # bound-based validators
+ bound_validators = [('max_length','maxlength'), ('min', 'min'), ('max', 'max')]
+
+ for v0, v1 in bound_validators:
+ try:
+ validators.append({'name':v1, 'int_value':int(f['options'][v0])})
+ except KeyError:
+ pass
+
+ # validators based on content_type
+ content_type_validators = ['ip', 'url', 'email']
+
+ for v in content_type_validators:
+ #if f['name']=='ip': pdb.set_trace()
+ try:
+ val = unquote(f['options']['content_type'])==v
+ if not val:
+ raise KeyError
+
+ validators.append({'name':v, 'bool_value': True})
+ except KeyError:
+ pass
+
+ # required validator
+ try:
+ required = f['options']['blank']=='False' and f['options']['null']=='False'
+ if required:
+ validators.append({'name':'required', 'bool_value':required})
+ except KeyError:
+ pass
+
+ return validators
+
+def is_number(s):
+ try:
+ float(s)
+ return True
+ except ValueError:
+ return False
+
+def xproto_default_to_gui(default):
+ val = "null"
+ if is_number(default):
+ val = str(default)
+ elif eval(default) == True:
+ val = 'true'
+ elif eval(default) == False:
+ val = 'false'
+ elif eval(default) == None:
+ val = 'null'
+ else:
+ val = str(default)
+ return val
\ No newline at end of file
diff --git a/lib/xos-genx/xosgenx/targets/modeldefs.xtarget b/lib/xos-genx/xosgenx/targets/modeldefs.xtarget
index 8c4771f..366f2ee 100644
--- a/lib/xos-genx/xosgenx/targets/modeldefs.xtarget
+++ b/lib/xos-genx/xosgenx/targets/modeldefs.xtarget
@@ -13,6 +13,15 @@
name: {{ f.name }}_id
relation: {model: {{ f.options.model }}, type: {{ f.options.link_type }}}
{% endif %}
+ {%- if f.options.default %}
+ default: "{{ xproto_unquote(xproto_default_to_gui(f.options.default)) }}"
+ {%- endif %}
+ {%- if f.options.choices %}
+ options:
+ {% for o in xproto_options_choices_to_dict(xproto_unquote(f.options.choices)) %}
+ - {{ o }}
+ {% endfor %}
+ {%- endif %}
type: {{ xproto_type_to_ui_type(f) }}
{% set validators = xproto_validators(f) -%}
{% if validators -%}
@@ -25,7 +34,7 @@
{% endif %}
{% endif -%}
{% endfor %}
- name: {{ m.name }}
+ name: {{ m.name }}
{%- set goodlinks = xproto_links_to_modeldef_relations( xproto_base_links(m, proto.message_table) + m.links ) %}
{% if goodlinks %}
relations:
diff --git a/xos/coreapi/protos/modeldefs.proto b/xos/coreapi/protos/modeldefs.proto
index 3cd5fa8..d0d95fc 100644
--- a/xos/coreapi/protos/modeldefs.proto
+++ b/xos/coreapi/protos/modeldefs.proto
@@ -17,6 +17,11 @@
};
};
+message FieldOption {
+ string id = 1;
+ string label = 2;
+}
+
message FieldRelation {
string model = 1;
string type = 2;
@@ -28,6 +33,8 @@
string type = 3;
FieldRelation relation = 4;
repeated FieldValidator validators = 5;
+ repeated FieldOption options = 6;
+ string default = 7;
};
message ModelDef {