lbkit 0.5.18__tar.gz → 0.5.20__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. {lbkit-0.5.18/lbkit.egg-info → lbkit-0.5.20}/PKG-INFO +1 -1
  2. lbkit-0.5.20/lbkit/__init__.py +2 -0
  3. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/cli.py +3 -0
  4. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/idf_interface.py +146 -19
  5. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/template/client.c.mako +18 -1
  6. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/template/public.c.mako +1 -1
  7. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/template/server.c.mako +120 -1
  8. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/component/build.py +2 -2
  9. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/component/test.py +7 -1
  10. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/errors.py +2 -0
  11. lbkit-0.5.20/lbkit/helper.py +96 -0
  12. {lbkit-0.5.18 → lbkit-0.5.20/lbkit.egg-info}/PKG-INFO +1 -1
  13. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit.egg-info/SOURCES.txt +4 -1
  14. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit.egg-info/top_level.txt +1 -0
  15. lbkit-0.5.20/test/__init__.py +0 -0
  16. lbkit-0.5.20/test/test_codegen.py +283 -0
  17. lbkit-0.5.20/test/test_helper.py +247 -0
  18. lbkit-0.5.18/lbkit/__init__.py +0 -2
  19. lbkit-0.5.18/lbkit/helper.py +0 -27
  20. {lbkit-0.5.18 → lbkit-0.5.20}/AUTHORS +0 -0
  21. {lbkit-0.5.18 → lbkit-0.5.20}/LICENSE +0 -0
  22. {lbkit-0.5.18 → lbkit-0.5.20}/MANIFEST.in +0 -0
  23. {lbkit-0.5.18 → lbkit-0.5.20}/README.md +0 -0
  24. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/ci_robot/__init__.py +0 -0
  25. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/ci_robot/gitee.py +0 -0
  26. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/__init__.py +0 -0
  27. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/codegen.py +0 -0
  28. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/ctype_defination.py +0 -0
  29. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/renderer.py +0 -0
  30. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/template/client.h.mako +0 -0
  31. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/template/interface.c.mako +0 -0
  32. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/template/interface.introspect.xml.mako +0 -0
  33. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/template/public.h.mako +0 -0
  34. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/template/server.h.mako +0 -0
  35. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/component/__init__.py +0 -0
  36. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/component/arg_parser.py +0 -0
  37. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/component/template/conanbase.mako +0 -0
  38. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/component/template/deploy.mako +0 -0
  39. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/integration/__init__.py +0 -0
  40. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/integration/build_image.py +0 -0
  41. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/integration/build_manifest.py +0 -0
  42. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/integration/build_prepare.py +0 -0
  43. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/integration/build_rootfs.py +0 -0
  44. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/integration/config.py +0 -0
  45. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/integration/task.py +0 -0
  46. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/integration/template/conanfile.py.mako +0 -0
  47. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/lbkit.py +0 -0
  48. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/log.py +0 -0
  49. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/misc.py +0 -0
  50. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/tools.py +0 -0
  51. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit.egg-info/dependency_links.txt +0 -0
  52. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit.egg-info/entry_points.txt +0 -0
  53. {lbkit-0.5.18 → lbkit-0.5.20}/lbkit.egg-info/requires.txt +0 -0
  54. {lbkit-0.5.18 → lbkit-0.5.20}/setup.cfg +0 -0
  55. {lbkit-0.5.18 → lbkit-0.5.20}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lbkit
3
- Version: 0.5.18
3
+ Version: 0.5.20
4
4
  Summary: Tools provided by litebmc.com
5
5
  Home-page: https://www.litebmc.com
6
6
  Author: xuhj@litebmc.com
@@ -0,0 +1,2 @@
1
+
2
+ __version__ = '0.5.20'
@@ -232,6 +232,9 @@ class Command(object):
232
232
  ret_code = -1
233
233
  msg = str(exc)
234
234
  log.error(misc.Color.RED + msg + misc.Color.RESET_ALL)
235
+ except errors.TestException:
236
+ log.error(exc)
237
+ ret_code = -1
235
238
 
236
239
  return ret_code
237
240
 
@@ -8,6 +8,7 @@ from lbkit.codegen.renderer import Renderer
8
8
  from lbkit.codegen.ctype_defination import CTYPE_OBJS, RefObjArrayValidator, RefObjValidator
9
9
  from lbkit.misc import load_yml_with_json_schema_validate
10
10
  from lbkit.errors import OdfValidateException
11
+ from lbkit.helper import SigInvalidException, validate_glib_signature
11
12
 
12
13
  log = Logger("gen_interface")
13
14
 
@@ -133,6 +134,7 @@ class IdfCtypeRender():
133
134
  ctype: str = None
134
135
  name: str = ""
135
136
  idf_data = None
137
+ default = None
136
138
  flags: list[str] = []
137
139
 
138
140
  def __init__(self):
@@ -186,20 +188,27 @@ class IdfCtypeRender():
186
188
  log.debug(f"Get odf schema info, name: {self.name}, ctype: {self.ctype}")
187
189
  if "variant" == self.ctype:
188
190
  return None
191
+ validator_cfg = self.validator_cfg
189
192
  match = re.match(f"^array\[({CTYPE_BASE_REG})\]$", self.ctype)
190
193
  if match:
191
194
  if "refobj" in self.flags:
192
195
  valiator = RefObjArrayValidator()
193
196
  return valiator.odf_schema(allow_ref)
194
- ctype_obj = CTYPE_OBJS.get(self.ctype)
195
- return ctype_obj.validator.odf_schema(allow_ref)
197
+ ctype_obj = copy.deepcopy(CTYPE_OBJS.get(self.ctype))
198
+ validator = ctype_obj.validator
199
+ if validator_cfg:
200
+ validator.set_validator(validator_cfg, self.name)
201
+ return validator.odf_schema(allow_ref)
196
202
  match = re.match(f"^({CTYPE_BASE_REG})$", self.ctype)
197
203
  if match:
198
204
  if "refobj" in self.flags:
199
205
  valiator = RefObjValidator()
200
206
  return valiator.odf_schema(allow_ref)
201
207
  ctype_obj = CTYPE_OBJS.get(self.ctype)
202
- return ctype_obj.validator.odf_schema(allow_ref)
208
+ validator = ctype_obj.validator
209
+ if validator_cfg:
210
+ validator.set_validator(validator_cfg, self.name)
211
+ return validator.odf_schema(allow_ref)
203
212
  # 非基础类型
204
213
  is_array = False
205
214
  ctype = self.ctype
@@ -519,13 +528,11 @@ class IdfCtypeRender():
519
528
  value = self.idf_data.get("pattern")
520
529
  if value:
521
530
  cfg["pattern"] = value
522
- elif (self.ctype == "byte" or self.ctype == "array[byte]" or
523
- self.ctype == "int16" or self.ctype == "array[int16]" or
524
- self.ctype == "uint16" or self.ctype == "array[uint16]" or
525
- self.ctype == "int32" or self.ctype == "array[int32]" or
526
- self.ctype == "uint32" or self.ctype == "array[uint32]" or
527
- self.ctype == "int64" or self.ctype == "array[int64]" or
528
- self.ctype == "uint64" or self.ctype == "array[uint64]"):
531
+ elif self.ctype in ["byte", "array[byte]", "int16", "array[int16]",
532
+ "uint16", "array[uint16]", "int32", "array[int32]",
533
+ "uint32", "array[uint32]","int64", "array[int64]",
534
+ "uint64", "array[uint64]", "size", "array[size]",
535
+ "ssize", "array[ssize]"]:
529
536
  value = self.idf_data.get("max")
530
537
  if value:
531
538
  cfg["max"] = value
@@ -596,6 +603,128 @@ class IdfProperty(IdfCtypeRender):
596
603
  else:
597
604
  self.desc_flags = " | ".join(c_flags)
598
605
 
606
+ self._load_default()
607
+
608
+ def _load_default(self):
609
+ # 只有基础类型有default值
610
+ match = re.match(f"^array\[({CTYPE_BASE_REG})\]$", self.ctype)
611
+ if not match:
612
+ match = re.match(f"^({CTYPE_BASE_REG})$", self.ctype)
613
+ if not match:
614
+ return
615
+ self.default = self.idf_data.get("default")
616
+ if self.default is None:
617
+ return
618
+
619
+ if self.ctype in ["boolean", "array[boolean]"]:
620
+ return
621
+ pattern = self.idf_data.get("pattern")
622
+ if self.ctype == "string":
623
+ if pattern:
624
+ match = re.match(pattern, self.default)
625
+ if not match:
626
+ raise OdfValidateException(f"Fail to validation default value of property {self.name} with pattern \"{pattern}\", get default: {self.default}")
627
+ return
628
+ if self.ctype == "array[string]":
629
+ if pattern:
630
+ for val in self.default:
631
+ match = re.match(pattern, val)
632
+ if not match:
633
+ raise OdfValidateException(f"Fail to validation default value of property {self.name} with pattern \"{pattern}\", get default: {val}")
634
+ return
635
+ if self.ctype == "object_path":
636
+ if pattern:
637
+ match = re.match(pattern, self.default)
638
+ if not match:
639
+ raise OdfValidateException(f"Fail to validation default value of property {self.name} with pattern \"{pattern}\", get default: {self.default}")
640
+ match = re.match(f"^(/[A-Z0-9a-z_]+)+$", self.default)
641
+ if not match:
642
+ raise OdfValidateException(f"Fail to validation default value of property {self.name} with pattern \"^(/[A-Z0-9a-z_]+)+$\", get default: {self.default}")
643
+ return
644
+ if self.ctype == "array[object_path]":
645
+ for val in self.default:
646
+ if pattern:
647
+ match = re.match(pattern, val)
648
+ if not match:
649
+ raise OdfValidateException(f"Fail to validation default value of property {self.name} with pattern \"{pattern}\", get default: {val}")
650
+ match = re.match(f"^(/[A-Z0-9a-z_]+)+$", val)
651
+ if not match:
652
+ raise OdfValidateException(f"Fail to validation default value of property {self.name} with pattern \"^(/[A-Z0-9a-z_]+)+$\", get default: {val}")
653
+ return
654
+
655
+ if self.ctype == "signature":
656
+ try:
657
+ validate_glib_signature(self.default)
658
+ if pattern:
659
+ match = re.match(pattern, self.default)
660
+ if not match:
661
+ raise OdfValidateException(f"Fail to validation default value of property {self.name} with pattern \"{pattern}\", get default: {self.default}")
662
+ except SigInvalidException:
663
+ raise OdfValidateException(f"Fail to validation default value of property {self.name}, get default: {self.default}")
664
+ return
665
+ if self.ctype == "array[oobject_path]":
666
+ try:
667
+ for val in self.default:
668
+ validate_glib_signature(val)
669
+ if pattern:
670
+ match = re.match(pattern, self.default)
671
+ if not match:
672
+ raise OdfValidateException(f"Fail to validation default value of property {self.name} with pattern \"{pattern}\", get default: {self.default}")
673
+ except SigInvalidException:
674
+ raise OdfValidateException(f"Fail to validation default value of property {self.name}, get default: {self.default}")
675
+ return
676
+
677
+ cfg = self.validator_cfg
678
+ if self.ctype in ["byte", "int16", "uint16", "int32", "uint32", "size", "ssize",
679
+ "int64", "uint64"]:
680
+ mmax = cfg.get("max")
681
+ if mmax is not None and mmax < self.default:
682
+ raise OdfValidateException(f"Fail to validation default value of property {self.name}, get default: {self.default}, max: {mmax}")
683
+ mmin = cfg.get("min")
684
+ if mmin is not None and mmin > self.default:
685
+ raise OdfValidateException(f"Fail to validation default value of property {self.name}, get default: {self.default}, min: {mmin}")
686
+ return
687
+ if self.ctype in ["array[byte]", "array[int16]", "array[uint16]", "array[int32]", "array[uint32]", "array[size]",
688
+ "array[ssize]", "array[int64]", "array[uint64]"]:
689
+ for val in self.default:
690
+ mmax = cfg.get("max")
691
+ if mmax is not None and mmax < val:
692
+ raise OdfValidateException(f"Fail to validation default value of property {self.name}, get default: {val}, max: {mmax}")
693
+ mmin = cfg.get("min")
694
+ if mmin is not None and mmin > val:
695
+ raise OdfValidateException(f"Fail to validation default value of property {self.name}, get default: {val}, min: {mmin}")
696
+ return
697
+
698
+ if self.ctype == "double":
699
+ emax = cfg.get("exclusive_max")
700
+ mmax = cfg.get("max")
701
+ if emax is not None and emax <= self.default:
702
+ raise OdfValidateException(f"Fail to validation default value of property {self.name}, get default: {self.default}, eclusive_max: {emax}")
703
+ if mmax is not None and mmax < self.default:
704
+ raise OdfValidateException(f"Fail to validation default value of property {self.name}, get default: {self.default}, max: {mmax}")
705
+ emin = cfg.get("exclusive_min")
706
+ mmin = cfg.get("min")
707
+ if emin is not None and emin >= self.default:
708
+ raise OdfValidateException(f"Fail to validation default value of property {self.name}, get default: {self.default}, exclusive_min: {emin}")
709
+ if mmin is not None and mmin > self.default:
710
+ raise OdfValidateException(f"Fail to validation default value of property {self.name}, get default: {self.default}, min: {emin}")
711
+ return
712
+ if self.ctype == "array[double]":
713
+ for val in self.default:
714
+ emax = cfg.get("exclusive_max")
715
+ mmax = cfg.get("max")
716
+ if emax is not None and emax <= val:
717
+ raise OdfValidateException(f"Fail to validation default value of property {self.name}, get default: {val}, eclusive_max: {emax}")
718
+ if mmax is not None and mmax < val:
719
+ raise OdfValidateException(f"Fail to validation default value of property {self.name}, get default: {val}, max: {mmax}")
720
+ emin = cfg.get("exclusive_min")
721
+ mmin = cfg.get("min")
722
+ if emin is not None and emin >= val:
723
+ raise OdfValidateException(f"Fail to validation default value of property {self.name}, get default: {val}, exclusive_min: {emin}")
724
+ if mmin is not None and mmin > val:
725
+ raise OdfValidateException(f"Fail to validation default value of property {self.name}, get default: {val}, min: {emin}")
726
+ return
727
+ raise OdfValidateException(f"Only basic type(byaqiuxtdsog) support default value, Property {self.name} type is {self.ctype}")
599
728
 
600
729
  @property
601
730
  def signature(self):
@@ -819,8 +948,8 @@ class IdfDictionary():
819
948
 
820
949
  class IdfInterface(IdfInterfaceBase):
821
950
  def __init__(self, lookup, idf_file):
822
- if not idf_file.endswith(".yaml"):
823
- raise IDFException(f"IDF file {idf_file} not endswith .yaml")
951
+ if not idf_file.endswith(".yaml") and not idf_file.endswith(".yml"):
952
+ raise IDFException(f"IDF file {idf_file} neither endswith .yaml nor endswith .yml")
824
953
  super().__init__()
825
954
  self.lookup = lookup
826
955
  self.file = idf_file
@@ -920,7 +1049,7 @@ class IdfInterface(IdfInterfaceBase):
920
1049
  # 使用schema校验数据,确保IDF文件符合格式要求,减少程序处理过程中的异常处理
921
1050
  # 验证失败时抛异常,此处不用处理,由外层处理
922
1051
  idf = load_yml_with_json_schema_validate(self.file, "/usr/share/litebmc/schema/idf.v1.json")
923
- log.info(f"validate {self.file} successfully")
1052
+ log.debug(f"validate {self.file} successfully")
924
1053
  self.version = idf.get("version")
925
1054
  self.description = idf.get("description", "")
926
1055
  # 别名
@@ -974,19 +1103,17 @@ class IdfInterface(IdfInterfaceBase):
974
1103
  self.structures[self.alias] = intf_stru
975
1104
 
976
1105
  def render_dbus_xml(self, template, out_file):
977
- fd = open(out_file, "w")
978
1106
 
979
1107
  out = self.render(self.lookup, template, intf=self)
980
1108
  hash = hashlib.sha256()
981
1109
  hash.update(out.encode('utf-8'))
982
1110
  self.introspect_xml_sha256 = hash.hexdigest()
983
1111
  log.info("The sha256sum of interface {} is {}".format(out_file, self.introspect_xml_sha256))
984
- fd.write(out)
985
- fd.close()
1112
+ with open(out_file, "w") as fd:
1113
+ fd.write(out)
986
1114
 
987
1115
  def render_c_source(self, template, out_file):
988
- fd = open(out_file, "w")
989
1116
 
990
1117
  out = self.render(self.lookup, template, intf=self)
991
- fd.write(out)
992
- fd.close()
1118
+ with open(out_file, "w") as fd:
1119
+ fd.write(out)
@@ -104,22 +104,39 @@ int ${class_name}_Call_${method.name}(const ${class_name} *object,
104
104
 
105
105
  % endfor
106
106
  static GclObject *_${class_name}_create(const gchar *obj_name, gpointer opaque);
107
+ static void _${class_name}_destroy(GclObject *obj);
107
108
 
108
109
  static GclInterface _${class_name}_interface = {
109
110
  .create = _${class_name}_create,
111
+ .destroy = _${class_name}_destroy,
110
112
  .is_remote = 1,
111
113
  .name = "${intf.name}",
112
114
  .properties = (GclProperty *)&${properties},
113
115
  .interface = NULL, /* load from usr/share/dbus-1/interfaces/${intf.name}.xml by gcl_init */
114
116
  };
115
117
 
118
+ /**
119
+ * @brief 销毁对象
120
+ *
121
+ * @param gcl_obj 待销毁的对象句柄
122
+ */
123
+ static void _${class_name}_destroy(GclObject *gcl_obj)
124
+ {
125
+ g_assert(gcl_obj);
126
+ ${class_name} *obj = (${class_name} *)gcl_obj;
127
+ g_rec_mutex_clear(obj->_base.lock);
128
+ g_free(obj->_base.lock);
129
+ ${intf.alias}_clean(obj);
130
+ memset(obj, 0, sizeof(${class_name}));
131
+ }
132
+
116
133
  /**
117
134
  * @brief 分配对象
118
135
  *
119
136
  * @param obj_name 对象名,需要由调用者分配内存
120
137
  * @param opaque 上层应用需要写入对象的用户数据,由上层应用使用
121
138
  */
122
- GclObject *_${class_name}_create(const gchar *obj_name, gpointer opaque)
139
+ static GclObject *_${class_name}_create(const gchar *obj_name, gpointer opaque)
123
140
  {
124
141
  ${class_name} *obj = g_new0(${class_name}, 1);
125
142
  memcpy(obj->_base.magic, GCL_MAGIC, strlen(GCL_MAGIC) + 1);
@@ -282,7 +282,7 @@ ${name} *${name}_decode_v(GVariant *in, gsize *n)
282
282
  }
283
283
  ${name} *output = g_new0(${name}, *n);
284
284
  while (g_variant_iter_loop(&iter, "s", &str_val)) {
285
- for (int i = 0; i <= ${len(enum.values.parameters)}; i++) {
285
+ for (int i = 0; i < ${len(enum.values.parameters)}; i++) {
286
286
  if (g_strcmp0(str_val, _${name}StrMap[i]) == 0) {
287
287
  output[id++] = (${name})i;
288
288
  }
@@ -234,11 +234,13 @@ gboolean ${class_name}_${signal.name}_Signal(const ${class_name} *object, const
234
234
 
235
235
  % endfor
236
236
  static GclObject *_${class_name}_create(const gchar *obj_name, gpointer opaque);
237
+ static void _${class_name}_destroy(GclObject *obj);
237
238
  static void _load_from_odf(yaml_document_t *doc, yaml_node_t *node, GclObject *gcl_obj,
238
239
  property_reference_loaded ref_loaded, gpointer user_data);
239
240
 
240
241
  static GclInterface _${class_name}_interface = {
241
242
  .create = _${intf.alias}_create,
243
+ .destroy = _${class_name}_destroy,
242
244
  .validate_odf = ${intf.name.replace(".", "_")}_validate_odf,
243
245
  .load_from_odf = _load_from_odf,
244
246
  .is_remote = 0,
@@ -251,6 +253,7 @@ static GclInterface _${class_name}_interface = {
251
253
  static void _load_odf_as_prop_${prop.name}(yaml_document_t *doc, GHashTable *prop_table,
252
254
  ${class_name} *obj, property_reference_loaded ref_loaded, gpointer user_data)
253
255
  {
256
+ __attribute__((unused)) gint i = 0;
254
257
  const gchar *flags = NULL;
255
258
  yaml_node_t *val = g_hash_table_lookup(prop_table, "_${prop.name}_flags");
256
259
  if (val && val->type == YAML_SCALAR_NODE) {
@@ -259,6 +262,55 @@ static void _load_odf_as_prop_${prop.name}(yaml_document_t *doc, GHashTable *pro
259
262
  val = g_hash_table_lookup(prop_table, "${prop.name}");
260
263
  ## validate接口在加载odf前完成属性是否必选校验,此处如果是必选属性一定存在
261
264
  if (!val) {
265
+ ## 设置默认值
266
+ % if prop.default:
267
+ % if prop.ctype == "boolean":
268
+ % if prop.default:
269
+ obj->${prop.name} = TRUE;
270
+ % endif
271
+ % elif prop.ctype in ["byte", "int16", "uint16", "int32", "uint32", "int64", "uint64", "size", "ssize", "double"]:
272
+ % if prop.ctype == "uint64":
273
+ obj->${prop.name} = ${prop.default}UL;
274
+ % elif prop.ctype == "int64":
275
+ obj->${prop.name} = ${prop.default}LL;
276
+ % else:
277
+ obj->${prop.name} = ${prop.default};
278
+ % endif
279
+ % elif prop.ctype in ["object_path", "string", "signature"]:
280
+ obj->${prop.name} = g_strdup("${prop.default}");
281
+ % elif prop.ctype == "array[boolean]":
282
+ i = 0;
283
+ obj->n_${prop.name} = ${len(prop.default)};
284
+ obj->${prop.name} = g_new0(gboolean, obj->n_${prop.name});
285
+ % for val in prop.default:
286
+ % if val:
287
+ obj->${prop.name}[i++] = TRUE;
288
+ % else:
289
+ obj->${prop.name}[i++] = FALSE;
290
+ % endif
291
+ % endfor
292
+ % elif prop.ctype in ["array[byte]", "array[int16]", "array[uint16]", "array[int32]", "array[uint32]", "array[int64]", "array[uint64]", "array[size]", "array[ssize]", "array[double]"]:
293
+ <% ctype = prop.ctype[6:-1]%>
294
+ i = 0;
295
+ obj->n_${prop.name} = ${len(prop.default)};
296
+ obj->${prop.name} = g_new0(g${ctype}, obj->n_${prop.name});
297
+ % for val in prop.default:
298
+ % if prop.ctype == "array[uint64]":
299
+ obj->${prop.name}[i++] = ${val}UL;
300
+ % elif prop.ctype == "array[int64]":
301
+ obj->${prop.name}[i++] = ${val}LL;
302
+ % else:
303
+ obj->${prop.name}[i++] = ${val};
304
+ % endif
305
+ % endfor
306
+ % elif prop.ctype in ["array[object_path]", "array[string]", "array[signature]"]:
307
+ i = 0;
308
+ obj->${prop.name} = g_new0(gchar *, ${len(prop.default) + 1});
309
+ % for val in prop.default:
310
+ obj->${prop.name}[i++] = g_strdup("${val}");
311
+ % endfor
312
+ % endif
313
+ % endif
262
314
  if (flags) {
263
315
  ## 属性不存在时传入的value为空,需要开发者在回调函数中完成异常(有flags无属性值)处理
264
316
  ref_loaded(obj, &${properties}.${prop.name}, doc, NULL, user_data, flags);
@@ -311,14 +363,31 @@ static void _load_from_odf(yaml_document_t *doc, yaml_node_t *node, GclObject *g
311
363
  % endif
312
364
  }
313
365
 
366
+ /**
367
+ * @brief 销毁对象
368
+ *
369
+ * @param gcl_obj 待销毁的对象句柄
370
+ */
371
+ static void _${class_name}_destroy(GclObject *gcl_obj)
372
+ {
373
+ g_assert(gcl_obj);
374
+ ${class_name} *obj = (${class_name} *)gcl_obj;
375
+ g_rec_mutex_clear(obj->_base.lock);
376
+ g_free(obj->_base.lock);
377
+ ${class_name}_clean(obj);
378
+ memset(obj, 0, sizeof(${class_name}));
379
+ g_free(obj);
380
+ }
381
+
314
382
  /**
315
383
  * @brief 分配对象
316
384
  *
317
385
  * @param obj_name 对象名,需要由调用者分配内存
318
386
  * @param opaque 上层应用需要写入对象的用户数据,由上层应用使用
319
387
  */
320
- GclObject *_${class_name}_create(const gchar *obj_name, gpointer opaque)
388
+ static GclObject *_${class_name}_create(const gchar *obj_name, gpointer opaque)
321
389
  {
390
+ __attribute__((unused)) gint i = 0;
322
391
  ${class_name} *obj = g_new0(${class_name}, 1);
323
392
  memcpy(obj->_base.magic, GCL_MAGIC, strlen(GCL_MAGIC) + 1);
324
393
  obj->_base.lock = g_new0(GRecMutex, 1);
@@ -326,6 +395,56 @@ GclObject *_${class_name}_create(const gchar *obj_name, gpointer opaque)
326
395
  obj->_base.name = obj_name;
327
396
  obj->_base.intf = &_${class_name}_interface;
328
397
  obj->_base.opaque = opaque;
398
+ % for prop in intf.properties:
399
+ % if prop.default:
400
+ % if prop.ctype == "boolean":
401
+ % if prop.default:
402
+ obj->${prop.name} = TRUE;
403
+ % endif
404
+ % elif prop.ctype in ["byte", "int16", "uint16", "int32", "uint32", "int64", "uint64", "size", "ssize", "double"]:
405
+ % if prop.ctype == "uint64":
406
+ obj->${prop.name} = ${prop.default}UL;
407
+ % elif prop.ctype == "int64":
408
+ obj->${prop.name} = ${prop.default}LL;
409
+ % else:
410
+ obj->${prop.name} = ${prop.default};
411
+ % endif
412
+ % elif prop.ctype in ["object_path", "string", "signature"]:
413
+ obj->${prop.name} = g_strdup("${prop.default}");
414
+ % elif prop.ctype == "array[boolean]":
415
+ i = 0;
416
+ obj->n_${prop.name} = ${len(prop.default)};
417
+ obj->${prop.name} = g_new0(gboolean, obj->n_${prop.name});
418
+ % for val in prop.default:
419
+ % if val:
420
+ obj->${prop.name}[i++] = TRUE;
421
+ % else:
422
+ obj->${prop.name}[i++] = FALSE;
423
+ % endif
424
+ % endfor
425
+ % elif prop.ctype in ["array[byte]", "array[int16]", "array[uint16]", "array[int32]", "array[uint32]", "array[int64]", "array[uint64]", "array[size]", "array[ssize]", "array[double]"]:
426
+ <% ctype = prop.ctype[6:-1]%>
427
+ i = 0;
428
+ obj->n_${prop.name} = ${len(prop.default)};
429
+ obj->${prop.name} = g_new0(g${ctype}, obj->n_${prop.name});
430
+ % for val in prop.default:
431
+ % if prop.ctype == "array[uint64]":
432
+ obj->${prop.name}[i++] = ${val}UL;
433
+ % elif prop.ctype == "array[int64]":
434
+ obj->${prop.name}[i++] = ${val}LL;
435
+ % else:
436
+ obj->${prop.name}[i++] = ${val};
437
+ % endif
438
+ % endfor
439
+ % elif prop.ctype in ["array[object_path]", "array[string]", "array[signature]"]:
440
+ i = 0;
441
+ obj->${prop.name} = g_new0(gchar *, ${len(prop.default) + 1});
442
+ % for val in prop.default:
443
+ obj->${prop.name}[i++] = g_strdup("${val}");
444
+ % endfor
445
+ % endif
446
+ % endif
447
+ % endfor
329
448
  return (GclObject *)obj;
330
449
  }
331
450
 
@@ -85,8 +85,8 @@ class BuildComponent():
85
85
  示例: project(gcom LANGUAGES C VERSION 0.1.0)
86
86
  """
87
87
  try:
88
- fp = open("CMakeLists.txt", "r")
89
- content = fp.read()
88
+ with open("CMakeLists.txt", "r") as fp:
89
+ content = fp.read()
90
90
  version = re.search("project\((.*)VERSION ([0-9][1-9]*.[0-9][1-9]*.[0-9][1-9]*)\)", content).group(2)
91
91
  return version.strip()
92
92
  except Exception as e:
@@ -3,6 +3,7 @@ import shutil
3
3
  import re
4
4
  import os
5
5
  import imp
6
+ import unittest
6
7
  from lbkit.component.build import BuildComponent
7
8
  from lbkit.component.arg_parser import ArgParser
8
9
  from lbkit import errors
@@ -109,7 +110,12 @@ class TestComponent():
109
110
  return 0
110
111
 
111
112
  log.success("call test method...")
112
- test.test()
113
+ ret = test.test()
114
+ if ret is not None:
115
+ if isinstance(ret, unittest.TestResult) and (len(ret.errors) > 0 or len(ret.failures) > 0):
116
+ raise errors.TestException(f"Test failed, ret: {ret}")
117
+ elif isinstance(ret, int) and ret != 0:
118
+ raise errors.TestException(f"Test failed, ret: {ret}")
113
119
 
114
120
  test_src_folder = getattr(test, "test_src_folder", [])
115
121
  # 设置ROOTFS_DIR环境变量,为DT测试提供相对路径
@@ -72,6 +72,8 @@ class HttpRequestException(Exception):
72
72
  def __str__(self):
73
73
  return super(HttpRequestException, self).__str__()
74
74
 
75
+ class TestException(Exception):
76
+ pass
75
77
 
76
78
  class OdfValidateException(Exception):
77
79
  def __init__(self, *args, **kwargs):
@@ -0,0 +1,96 @@
1
+ import os
2
+ import yaml
3
+ import unittest
4
+ from xml.dom import minidom, Node
5
+
6
+ class Helper():
7
+ @staticmethod
8
+ def get_node_value(dom: Node, name, default=None):
9
+ node: minidom.Attr = dom.attributes.get(name)
10
+ if node is None:
11
+ if default is None:
12
+ raise Exception("Parse node failed, abort")
13
+ return default
14
+ return node.childNodes[0].nodeValue.strip()
15
+
16
+ def read_yaml(file: str, key, default=None):
17
+ if not os.path.isfile(file):
18
+ return default
19
+ fd = open(file, "r");
20
+ try:
21
+ data = yaml.load(fd, Loader=yaml.FullLoader)
22
+ for split in key.split("/", -1):
23
+ data = data.get(split)
24
+ if data is None:
25
+ return default
26
+ return data
27
+ except:
28
+ return default
29
+
30
+
31
+ generate_sig_chars = [
32
+ "y", "b", "n", "q", "i", "u", "x", "t", "h",
33
+ "d", "v", "s", "o", "g"]
34
+
35
+
36
+ class SigInvalidException(Exception):
37
+ pass
38
+
39
+ def _validate_glib_signature(sig_str, sigs):
40
+ if len(sigs) == 0:
41
+ raise SigInvalidException(f"String {sig_str} is not a valid signature str")
42
+ if sigs[0] in generate_sig_chars:
43
+ if len(sigs) > 1:
44
+ return _validate_glib_signature(sig_str, sigs[1:])
45
+ return
46
+ if sigs[0] == "a":
47
+ return _validate_glib_signature(sig_str, sigs[1:])
48
+ if sigs[0] in ["(", "{"]:
49
+ next_chr = ")"
50
+ if sigs[0] == "{":
51
+ next_chr = "}"
52
+
53
+ cnt = 0
54
+ next_pos = -1
55
+ for i, c in enumerate(sigs):
56
+ if c == sigs[0]:
57
+ cnt += 1
58
+ elif c == next_chr:
59
+ cnt -= 1
60
+ if cnt == 0:
61
+ next_pos = i
62
+ break
63
+ # 未找到下一个右括号
64
+ if next_pos == -1:
65
+ raise SigInvalidException(f"String {sig_str} is not a valid signature str")
66
+ # 元组()之间可以为空
67
+ if sigs[0] == '(' and next_pos == 1:
68
+ return
69
+ if sigs[0] == "{":
70
+ # 字典至少需要两个字符
71
+ if next_pos < 3:
72
+ raise SigInvalidException(f"String {sig_str} is not a valid signature str")
73
+ # 字典第一个签名必须是简单类型
74
+ if sigs[1] not in generate_sig_chars:
75
+ raise SigInvalidException(f"String {sig_str} is not a valid signature str")
76
+ _validate_glib_signature(sig_str, sigs[1:next_pos])
77
+ sigs = sigs[next_pos + 1:]
78
+ if not sigs:
79
+ return
80
+ _validate_glib_signature(sig_str, sigs)
81
+ return
82
+
83
+ # '}' 和 ')'及其它字符起始的认为是非法字符
84
+ raise SigInvalidException(f"String {sig_str} is not a valid signature str")
85
+
86
+
87
+ def validate_glib_signature(sig_str):
88
+ _validate_glib_signature(sig_str, list(sig_str))
89
+
90
+
91
+ class TestSignatureValidateClass(unittest.TestCase):
92
+ def test_validate_glib_signature(self):
93
+ validate_glib_signature("as")
94
+
95
+ if __name__ == "__main__":
96
+ unittest.main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lbkit
3
- Version: 0.5.18
3
+ Version: 0.5.20
4
4
  Summary: Tools provided by litebmc.com
5
5
  Home-page: https://www.litebmc.com
6
6
  Author: xuhj@litebmc.com
@@ -45,4 +45,7 @@ lbkit/integration/build_prepare.py
45
45
  lbkit/integration/build_rootfs.py
46
46
  lbkit/integration/config.py
47
47
  lbkit/integration/task.py
48
- lbkit/integration/template/conanfile.py.mako
48
+ lbkit/integration/template/conanfile.py.mako
49
+ test/__init__.py
50
+ test/test_codegen.py
51
+ test/test_helper.py
File without changes