aboutsummaryrefslogtreecommitdiff
path: root/scripts/qapi/schema.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/qapi/schema.py')
-rw-r--r--scripts/qapi/schema.py42
1 files changed, 35 insertions, 7 deletions
diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index d65c35f..cbe3b5a 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -19,7 +19,6 @@
from __future__ import annotations
from abc import ABC, abstractmethod
-from collections import OrderedDict
import os
import re
from typing import (
@@ -29,6 +28,7 @@ from typing import (
List,
Optional,
Union,
+ ValuesView,
cast,
)
@@ -556,7 +556,7 @@ class QAPISchemaObjectType(QAPISchemaType):
super().check(schema)
assert self._checked and not self._check_complete
- seen = OrderedDict()
+ seen = {}
if self._base_name:
self.base = schema.resolve_type(self._base_name, self.info,
"'base'")
@@ -933,8 +933,11 @@ class QAPISchemaEnumMember(QAPISchemaMember):
class QAPISchemaFeature(QAPISchemaMember):
role = 'feature'
+ # Features which are standardized across all schemas
+ SPECIAL_NAMES = ['deprecated', 'unstable']
+
def is_special(self) -> bool:
- return self.name in ('deprecated', 'unstable')
+ return self.name in QAPISchemaFeature.SPECIAL_NAMES
class QAPISchemaObjectTypeMember(QAPISchemaMember):
@@ -1137,7 +1140,17 @@ class QAPISchema:
self.docs = parser.docs
self._entity_list: List[QAPISchemaEntity] = []
self._entity_dict: Dict[str, QAPISchemaDefinition] = {}
- self._module_dict: Dict[str, QAPISchemaModule] = OrderedDict()
+ self._module_dict: Dict[str, QAPISchemaModule] = {}
+ # NB, values in the dict will identify the first encountered
+ # usage of a named feature only
+ self._feature_dict: Dict[str, QAPISchemaFeature] = {}
+
+ # All schemas get the names defined in the QapiSpecialFeature enum.
+ # Rely on dict iteration order matching insertion order so that
+ # the special names are emitted first when generating code.
+ for f in QAPISchemaFeature.SPECIAL_NAMES:
+ self._feature_dict[f] = QAPISchemaFeature(f, None)
+
self._schema_dir = os.path.dirname(fname)
self._make_module(QAPISchemaModule.BUILTIN_MODULE_NAME)
self._make_module(fname)
@@ -1147,6 +1160,9 @@ class QAPISchema:
self._def_exprs(exprs)
self.check()
+ def features(self) -> ValuesView[QAPISchemaFeature]:
+ return self._feature_dict.values()
+
def _def_entity(self, ent: QAPISchemaEntity) -> None:
self._entity_list.append(ent)
@@ -1249,7 +1265,7 @@ class QAPISchema:
[{'name': n} for n in qtypes], None)
self._def_definition(QAPISchemaEnumType(
- 'QType', None, None, None, None, qtype_values, 'QTYPE'))
+ 'QType', None, None, None, None, qtype_values, None))
def _make_features(
self,
@@ -1258,6 +1274,12 @@ class QAPISchema:
) -> List[QAPISchemaFeature]:
if features is None:
return []
+
+ for f in features:
+ feat = QAPISchemaFeature(f['name'], info)
+ if feat.name not in self._feature_dict:
+ self._feature_dict[feat.name] = feat
+
return [QAPISchemaFeature(f['name'], info,
QAPISchemaIfCond(f.get('if')))
for f in features]
@@ -1431,7 +1453,7 @@ class QAPISchema:
ifcond = QAPISchemaIfCond(expr.get('if'))
info = expr.info
features = self._make_features(expr.get('features'), info)
- if isinstance(data, OrderedDict):
+ if isinstance(data, dict):
data = self._make_implicit_object_type(
name, info, ifcond,
'arg', self._make_members(data, info))
@@ -1450,7 +1472,7 @@ class QAPISchema:
ifcond = QAPISchemaIfCond(expr.get('if'))
info = expr.info
features = self._make_features(expr.get('features'), info)
- if isinstance(data, OrderedDict):
+ if isinstance(data, dict):
data = self._make_implicit_object_type(
name, info, ifcond,
'arg', self._make_members(data, info))
@@ -1485,6 +1507,12 @@ class QAPISchema:
for doc in self.docs:
doc.check()
+ features = list(self._feature_dict.values())
+ if len(features) > 64:
+ raise QAPISemError(
+ features[64].info,
+ "Maximum of 64 schema features is permitted")
+
def visit(self, visitor: QAPISchemaVisitor) -> None:
visitor.visit_begin(self)
for mod in self._module_dict.values():