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.
- {lbkit-0.5.18/lbkit.egg-info → lbkit-0.5.20}/PKG-INFO +1 -1
- lbkit-0.5.20/lbkit/__init__.py +2 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/cli.py +3 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/idf_interface.py +146 -19
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/template/client.c.mako +18 -1
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/template/public.c.mako +1 -1
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/template/server.c.mako +120 -1
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/component/build.py +2 -2
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/component/test.py +7 -1
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/errors.py +2 -0
- lbkit-0.5.20/lbkit/helper.py +96 -0
- {lbkit-0.5.18 → lbkit-0.5.20/lbkit.egg-info}/PKG-INFO +1 -1
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit.egg-info/SOURCES.txt +4 -1
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit.egg-info/top_level.txt +1 -0
- lbkit-0.5.20/test/__init__.py +0 -0
- lbkit-0.5.20/test/test_codegen.py +283 -0
- lbkit-0.5.20/test/test_helper.py +247 -0
- lbkit-0.5.18/lbkit/__init__.py +0 -2
- lbkit-0.5.18/lbkit/helper.py +0 -27
- {lbkit-0.5.18 → lbkit-0.5.20}/AUTHORS +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/LICENSE +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/MANIFEST.in +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/README.md +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/ci_robot/__init__.py +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/ci_robot/gitee.py +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/__init__.py +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/codegen.py +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/ctype_defination.py +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/renderer.py +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/template/client.h.mako +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/template/interface.c.mako +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/template/interface.introspect.xml.mako +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/template/public.h.mako +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/codegen/template/server.h.mako +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/component/__init__.py +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/component/arg_parser.py +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/component/template/conanbase.mako +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/component/template/deploy.mako +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/integration/__init__.py +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/integration/build_image.py +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/integration/build_manifest.py +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/integration/build_prepare.py +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/integration/build_rootfs.py +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/integration/config.py +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/integration/task.py +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/integration/template/conanfile.py.mako +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/lbkit.py +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/log.py +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/misc.py +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit/tools.py +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit.egg-info/dependency_links.txt +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit.egg-info/entry_points.txt +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/lbkit.egg-info/requires.txt +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/setup.cfg +0 -0
- {lbkit-0.5.18 → lbkit-0.5.20}/setup.py +0 -0
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
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}
|
|
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.
|
|
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
|
-
|
|
985
|
-
|
|
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
|
-
|
|
992
|
-
|
|
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
|
|
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
|
-
|
|
89
|
-
|
|
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测试提供相对路径
|
|
@@ -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()
|
|
@@ -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
|