summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Andreoli <dave@gurumeditation.it>2018-01-02 15:43:15 +0100
committerDave Andreoli <dave@gurumeditation.it>2018-01-02 15:44:43 +0100
commitb9ed84f4edc505737c9f9d034c24e080f5fa2242 (patch)
treeecf4a5ef8159391c2840bdd6bb1c3f77829f4e85
parentb8f4dc296ff1e95e6c2a88b7071e3ed8e2dffd86 (diff)
Pyolian: implement an utility class: Namspace
Update tests and generator to use this new feature
-rw-r--r--src/scripts/pyolian/eolian.py82
-rwxr-xr-xsrc/scripts/pyolian/generator.py23
-rwxr-xr-xsrc/scripts/pyolian/test_eolian.py66
-rw-r--r--src/scripts/pyolian/test_gen_namespace.template36
4 files changed, 179 insertions, 28 deletions
diff --git a/src/scripts/pyolian/eolian.py b/src/scripts/pyolian/eolian.py
index 75a98ff0fe..645b463278 100644
--- a/src/scripts/pyolian/eolian.py
+++ b/src/scripts/pyolian/eolian.py
@@ -301,6 +301,20 @@ class Eolian_Unit(EolianBaseObject):
301 return Iterator(Class, lib.eolian_all_classes_get(self._obj)) 301 return Iterator(Class, lib.eolian_all_classes_get(self._obj))
302 302
303 @property 303 @property
304 def all_namespaces(self):
305 # TODO find a better way to find namespaces (maybe inside eolian?)
306 nspaces = []
307 for cls in self.all_classes:
308 ns = Namespace(self, cls.namespace)
309 if not ns in nspaces:
310 nspaces.append(ns)
311 nspaces.sort()
312 return nspaces
313
314 def namespace_get_by_name(self, name):
315 return Namespace(self, name)
316
317 @property
304 def typedecl_all_enums(self): 318 def typedecl_all_enums(self):
305 return Iterator(Typedecl, lib.eolian_typedecl_all_enums_get(self._obj)) 319 return Iterator(Typedecl, lib.eolian_typedecl_all_enums_get(self._obj))
306 320
@@ -416,6 +430,72 @@ class Eolian(Eolian_Unit):
416 return bool(lib.eolian_all_eot_files_parse(self._obj)) 430 return bool(lib.eolian_all_eot_files_parse(self._obj))
417 431
418 432
433### Namespace Utility Class #################################################
434
435class Namespace(object):
436 def __init__(self, unit, namespace_name):
437 self._name = namespace_name
438 self._unit = unit
439
440 def __repr__(self):
441 return "<eolian.Namespace '{0._name}'>".format(self)
442
443 def __eq__(self, other):
444 return self.name == other.name
445
446 def __lt__(self, other):
447 return self.name < other.name
448
449 def __gt__(self, other):
450 return self.name > other.name
451
452 @property
453 def name(self):
454 return self._name
455
456 @property
457 def namespaces(self):
458 return self._name.split('.')
459
460 @property
461 def classes(self):
462 return [ c for c in self._unit.all_classes
463 if c.namespace == self._name ]
464
465 @property
466 def regulars(self):
467 return [ c for c in self._unit.all_classes
468 if c.type == Eolian_Class_Type.REGULAR and
469 c.namespace == self._name]
470
471 @property
472 def mixins(self):
473 return [ c for c in self._unit.all_classes
474 if c.type == Eolian_Class_Type.MIXIN and
475 c.namespace == self._name]
476
477 @property
478 def interfaces(self):
479 return [ c for c in self._unit.all_classes
480 if c.type == Eolian_Class_Type.INTERFACE and
481 c.namespace == self._name]
482
483 @property
484 def aliases(self):
485 return [ td for td in self._unit.typedecl_all_aliases
486 if td.namespace == self._name]
487
488 @property
489 def structs(self):
490 return [ td for td in self._unit.typedecl_all_structs
491 if td.namespace == self._name]
492
493 @property
494 def enums(self):
495 return [ td for td in self._unit.typedecl_all_enums
496 if td.namespace == self._name]
497
498
419### Eolian Classes ########################################################## 499### Eolian Classes ##########################################################
420 500
421class Class(EolianBaseObject): 501class Class(EolianBaseObject):
@@ -1240,6 +1320,7 @@ class _Eolian_Doc_Token_Struct(ctypes.Structure):
1240 ("text", c_char_p), 1320 ("text", c_char_p),
1241 ("text_end", c_char_p)] 1321 ("text_end", c_char_p)]
1242 1322
1323
1243class Documentation(EolianBaseObject): 1324class Documentation(EolianBaseObject):
1244 # def __repr__(self): 1325 # def __repr__(self):
1245 # return "<eolian.Documentation '{0.name}'>".format(self) 1326 # return "<eolian.Documentation '{0.name}'>".format(self)
@@ -1345,7 +1426,6 @@ lib.eolian_init()
1345atexit.register(lambda: lib.eolian_shutdown()) 1426atexit.register(lambda: lib.eolian_shutdown())
1346 1427
1347 1428
1348
1349### API coverage statistics ################################################# 1429### API coverage statistics #################################################
1350 1430
1351if __name__ == '__main__': 1431if __name__ == '__main__':
diff --git a/src/scripts/pyolian/generator.py b/src/scripts/pyolian/generator.py
index 2640bfaf40..140b620a6d 100755
--- a/src/scripts/pyolian/generator.py
+++ b/src/scripts/pyolian/generator.py
@@ -90,9 +90,9 @@ class Template(pyratemp.Template):
90 90
91 Args: 91 Args:
92 filename: Template file to load. (REQUIRED) 92 filename: Template file to load. (REQUIRED)
93 data: User provided context for the template. 93 context: User provided context for the template (dict).
94 """ 94 """
95 def __init__(self, filename, encoding='utf-8', data=None, escape=None, 95 def __init__(self, filename, encoding='utf-8', context=None, escape=None,
96 loader_class=pyratemp.LoaderFile, 96 loader_class=pyratemp.LoaderFile,
97 parser_class=pyratemp.Parser, 97 parser_class=pyratemp.Parser,
98 renderer_class=pyratemp.Renderer, 98 renderer_class=pyratemp.Renderer,
@@ -101,8 +101,8 @@ class Template(pyratemp.Template):
101 # Build the global context for the template 101 # Build the global context for the template
102 global_ctx = {} 102 global_ctx = {}
103 # user provided context (low pri) 103 # user provided context (low pri)
104 if data: 104 if context:
105 global_ctx.update(data) 105 global_ctx.update(context)
106 # standard names (not overwritables) 106 # standard names (not overwritables)
107 global_ctx.update({ 107 global_ctx.update({
108 # Template info 108 # Template info
@@ -164,23 +164,14 @@ class Template(pyratemp.Template):
164 ctx.update(kargs) 164 ctx.update(kargs)
165 if cls: 165 if cls:
166 ctx['cls'] = eolian_db.class_get_by_name(cls) 166 ctx['cls'] = eolian_db.class_get_by_name(cls)
167 if ns:
168 ctx['namespace'] = eolian_db.namespace_get_by_name(ns)
167 if struct: 169 if struct:
168 ctx['struct'] = eolian_db.typedecl_struct_get_by_name(struct) 170 ctx['struct'] = eolian_db.typedecl_struct_get_by_name(struct)
169 if enum: 171 if enum:
170 ctx['enum'] = eolian_db.typedecl_enum_get_by_name(enum) 172 ctx['enum'] = eolian_db.typedecl_enum_get_by_name(enum)
171 if alias: 173 if alias:
172 ctx['alias'] = eolian_db.typedecl_alias_get_by_name(alias) 174 ctx['alias'] = eolian_db.typedecl_alias_get_by_name(alias)
173 if ns:
174 ctx['namespace'] = ns
175 ctx['namespaces'] = ns.split('.')
176 ctx['classes'] = [ c for c in eolian_db.all_classes
177 if c.full_name.startswith(ns + '.') ]
178 ctx['aliases'] = [ a for a in eolian_db.typedecl_all_aliases
179 if a.full_name.startswith(ns + '.') ]
180 ctx['structs'] = [ s for s in eolian_db.typedecl_all_structs
181 if s.full_name.startswith(ns + '.') ]
182 ctx['enums'] = [ e for e in eolian_db.typedecl_all_enums
183 if e.full_name.startswith(ns + '.') ]
184 175
185 if verbose and filename: 176 if verbose and filename:
186 print('generating "{}" from template "{}"'.format( 177 print('generating "{}" from template "{}"'.format(
@@ -205,7 +196,7 @@ class Template(pyratemp.Template):
205if __name__ == '__main__': 196if __name__ == '__main__':
206 import argparse 197 import argparse
207 198
208 parser = argparse.ArgumentParser(description='Pyolian generator.') 199 parser = argparse.ArgumentParser(description='Pyolian template based generator.')
209 parser.add_argument('template', 200 parser.add_argument('template',
210 help='The template file to use. (REQUIRED)') 201 help='The template file to use. (REQUIRED)')
211 parser.add_argument('--output', '-o', metavar='FILE', default=None, 202 parser.add_argument('--output', '-o', metavar='FILE', default=None,
diff --git a/src/scripts/pyolian/test_eolian.py b/src/scripts/pyolian/test_eolian.py
index 76baf887f2..c7b9769b4e 100755
--- a/src/scripts/pyolian/test_eolian.py
+++ b/src/scripts/pyolian/test_eolian.py
@@ -50,7 +50,6 @@ class TestBaseObject(unittest.TestCase):
50 self.assertNotEqual(enum1, 0) 50 self.assertNotEqual(enum1, 0)
51 51
52 self.assertNotEqual(cls1, enum1) 52 self.assertNotEqual(cls1, enum1)
53
54 53
55 54
56class TestEolianUnit(unittest.TestCase): 55class TestEolianUnit(unittest.TestCase):
@@ -149,6 +148,71 @@ class TestEolianUnit(unittest.TestCase):
149 self.assertGreater(all_count, 400) 148 self.assertGreater(all_count, 400)
150 149
151 150
151class TestEolianNamespace(unittest.TestCase):
152 def test_all_namespace(self):
153 count = 0
154 for ns in state.all_namespaces:
155 self.assertIsInstance(ns, eolian.Namespace)
156 count += 1
157 self.assertGreater(count, 100)
158
159 def test_namespace_equality(self):
160 ns1 = eolian.Namespace(state, 'Efl.Io')
161 ns2 = eolian.Namespace(state, 'Efl.Net')
162 self.assertIsInstance(ns1, eolian.Namespace)
163 self.assertIsInstance(ns2, eolian.Namespace)
164 self.assertNotEqual(ns1, ns2)
165 self.assertEqual(ns1, eolian.Namespace(state, 'Efl.Io'))
166 self.assertEqual(ns2, eolian.Namespace(state, 'Efl.Net'))
167
168 def test_namespace_sorting(self):
169 nspaces = state.all_namespaces
170 nspaces.sort(reverse=True)
171 self.assertGreater(nspaces[0], nspaces[-1])
172 self.assertLess(nspaces[1], nspaces[0])
173
174 def test_namespace_by_name(self):
175 ns = eolian.Namespace(state, 'Efl.Net')
176 self.assertIsInstance(ns, eolian.Namespace)
177 self.assertEqual(ns.name, 'Efl.Net')
178 self.assertEqual(ns.namespaces, ['Efl', 'Net'])
179
180 ns = state.namespace_get_by_name('Efl')
181 self.assertIsInstance(ns, eolian.Namespace)
182 self.assertEqual(ns.name, 'Efl')
183
184 self.assertGreater(len(ns.classes), 30)
185 for cls in ns.classes:
186 self.assertIsInstance(cls, eolian.Class)
187 self.assertGreater(len(ns.regulars), 4)
188 for cls in ns.regulars:
189 self.assertIsInstance(cls, eolian.Class)
190 self.assertEqual(cls.type, eolian.Eolian_Class_Type.REGULAR)
191 self.assertGreater(len(ns.mixins), 0)
192 for cls in ns.mixins:
193 self.assertIsInstance(cls, eolian.Class)
194 self.assertEqual(cls.type, eolian.Eolian_Class_Type.MIXIN)
195 self.assertGreater(len(ns.interfaces), 15)
196 for cls in ns.interfaces:
197 self.assertIsInstance(cls, eolian.Class)
198 self.assertEqual(cls.type, eolian.Eolian_Class_Type.INTERFACE)
199
200 self.assertGreater(len(ns.enums), 1)
201 for td in ns.enums:
202 self.assertIsInstance(td, eolian.Typedecl)
203 self.assertEqual(td.type, eolian.Eolian_Typedecl_Type.ENUM)
204 self.assertGreater(len(ns.aliases), 0)
205 for td in ns.aliases:
206 self.assertIsInstance(td, eolian.Typedecl)
207 # TODO eolian_typedecl_all_aliases_get also return FUNCTION_POINTER
208 # is this correct? or an eolian bug ?
209 # self.assertEqual(td.type, eolian.Eolian_Typedecl_Type.ALIAS)
210 self.assertGreater(len(ns.structs), 2)
211 for td in ns.structs:
212 self.assertIsInstance(td, eolian.Typedecl)
213 self.assertEqual(td.type, eolian.Eolian_Typedecl_Type.STRUCT)
214
215
152class TestEolianClass(unittest.TestCase): 216class TestEolianClass(unittest.TestCase):
153 def test_class(self): 217 def test_class(self):
154 cls = state.class_get_by_file('efl_loop_timer.eo') 218 cls = state.class_get_by_file('efl_loop_timer.eo')
diff --git a/src/scripts/pyolian/test_gen_namespace.template b/src/scripts/pyolian/test_gen_namespace.template
index 09b7763bb0..87557c6ad8 100644
--- a/src/scripts/pyolian/test_gen_namespace.template
+++ b/src/scripts/pyolian/test_gen_namespace.template
@@ -1,19 +1,35 @@
1 1
2================================================================================ 2================================================================================
3Namespace: ${namespace}$ ${namespaces}$ 3Namespace: ${namespace.name}$ ${namespace.namespaces}$
4================================================================================ 4================================================================================
5 5
6Classes: 6Regular Classes:
7======== 7================
8<!--(for cls in classes)--> 8<!--(for cls in namespace.regulars)-->
9 * ${cls.full_name}$ (${cls.type}$) 9 * ${cls.full_name}$ (${cls.type.name.lower()}$)
10<!--(else)-->
11 no classes available
12<!--(end)-->
13
14Interfaces:
15===========
16<!--(for cls in namespace.interfaces)-->
17 * ${cls.full_name}$ (${cls.type.name.lower()}$)
18<!--(else)-->
19 no classes available
20<!--(end)-->
21
22Mixins:
23=======
24<!--(for cls in namespace.mixins)-->
25 * ${cls.full_name}$ (${cls.type.name.lower()}$)
10<!--(else)--> 26<!--(else)-->
11 no classes available 27 no classes available
12<!--(end)--> 28<!--(end)-->
13 29
14Aliases: 30Aliases:
15======== 31========
16<!--(for typedecl in aliases)--> 32<!--(for typedecl in namespace.aliases)-->
17 * ${typedecl.full_name}$ 33 * ${typedecl.full_name}$
18<!--(else)--> 34<!--(else)-->
19 no alias available 35 no alias available
@@ -21,10 +37,10 @@ Aliases:
21 37
22Structs: 38Structs:
23======== 39========
24<!--(for typedecl in structs)--> 40<!--(for typedecl in namespace.structs)-->
25 * ${typedecl.full_name}$ 41 * ${typedecl.full_name}$
26 <!--(for field in typedecl.struct_fields)--> 42 <!--(for field in typedecl.struct_fields)-->
27 ${field}$ 43 ${field.type.name}$ ${field.name}$
28 <!--(end)--> 44 <!--(end)-->
29<!--(else)--> 45<!--(else)-->
30 no structs available 46 no structs available
@@ -32,10 +48,10 @@ Structs:
32 48
33Enums: 49Enums:
34====== 50======
35<!--(for typedecl in enums)--> 51<!--(for typedecl in namespace.enums)-->
36 * ${typedecl.full_name}$ 52 * ${typedecl.full_name}$
37 <!--(for field in typedecl.enum_fields)--> 53 <!--(for field in typedecl.enum_fields)-->
38 ${field}$ 54 ${field.c_name}$ = ${field.value.serialize}$
39 <!--(end)--> 55 <!--(end)-->
40<!--(else)--> 56<!--(else)-->
41 no enums available 57 no enums available