[PATCH phosphor-objmgr 1/2] Generalize introspection parser

OpenBMC Patches patches at stwcx.xyz
Thu Oct 29 13:06:11 AEDT 2015


From: Brad Bishop <bradleyb at us.ibm.com>

Doing this in prep for sharing with with rest-dbus.
---
 phosphor-mapper | 130 +++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 92 insertions(+), 38 deletions(-)

diff --git a/phosphor-mapper b/phosphor-mapper
index 28d2600..890e546 100644
--- a/phosphor-mapper
+++ b/phosphor-mapper
@@ -201,7 +201,7 @@ class ObjectMapper(dbus.service.Object):
 
 	def process_new_owner(self, name):
 		# unique name
-		return self.discover([ Owner(name, self.bus) ])
+		return self.discover([ IntrospectionParser(name, self.bus.dbus) ])
 
 	def process_old_owner(self, name):
 		# unique name
@@ -217,6 +217,17 @@ class ObjectMapper(dbus.service.Object):
 		if old:
 			self.process_old_owner(old)
 
+	def add_match_interfaces(self, owner, path, interfaces):
+		for x in interfaces:
+			if self.intf_match not in x:
+				continue
+
+			self.cache.add_item((path, owner, x))
+
+	def add_match_items(self, owner, bus_items):
+		for x,y in bus_items.iteritems():
+			self.add_match_interfaces(owner, x, y['interfaces'])
+
 	def discover(self, owners = None):
 		discovery = not self.discovery_done
 		if not owners:
@@ -229,7 +240,7 @@ class ObjectMapper(dbus.service.Object):
 			if self.cache.has_bus(o.name):
 				continue
 
-			self.cache.add_items(o.discover(self.intf_match))
+			self.add_match_items(o.name, o.introspect())
 
 		if discovery:
 			print "ObjectMapper discovery complete..."
@@ -249,64 +260,107 @@ class ObjectMapper(dbus.service.Object):
 			values.update(self.GetTree(x, depth, match_type))
 		return values
 
-class IntrospectionParser:
+class IntrospectionNodeParser:
 	def __init__(self, data):
 		self.data = data
 		self.cache = {}
 
-	def get_interfaces(self, match):
-		if 'interfaces' not in self.cache.keys():
-			self.cache['interfaces'] = [ x.attrib['name' ] \
-					for x in self.data.findall('interface') \
-					if match in x.attrib['name'] ]
-		return self.cache['interfaces']
+	def parse_args(self):
+		return [ x.attrib for x in self.data.findall('arg') ]
+
+	def parse_children(self):
+		return [ x.attrib['name'] for x in self.data.findall('node') ]
+
+	def parse_method_or_signal(self):
+		name = self.data.attrib['name']
+		return name, self.parse_args()
+
+	def parse_interface(self):
+		iface = {}
+		iface['method'] = {}
+		iface['signal'] = {}
+		name = self.data.attrib['name']
+
+		for node in self.data:
+			p = IntrospectionNodeParser(node)
+			if node.tag not in ['method', 'signal']:
+				continue
+			n, element = p.parse_method_or_signal()
+			iface[node.tag][n] = element
+
+		return name, iface
+
+	def parse_node(self):
+		if self.cache:
+			return self.cache
 
-	def get_kids(self):
-		if 'kids' not in self.cache.keys():
-			self.cache['kids'] = [ x.attrib['name' ] \
-					for x in self.data.findall('node') ]
-		return self.cache['kids']
+		self.cache['interfaces'] = {}
+		self.cache['children'] = []
+
+		for node in self.data:
+			p = IntrospectionNodeParser(node)
+			if node.tag == 'interface':
+				name, ifaces = p.parse_interface()
+				self.cache['interfaces'][name] = ifaces
+			elif node.tag == 'node':
+				self.cache['children'] = self.parse_children()
+
+		return self.cache
+
+	def get_interfaces(self):
+		return self.parse_node()['interfaces']
+
+	def get_children(self):
+		return self.parse_node()['children']
 
 	def recursive_binding(self):
-		return any('/' in s for s in self.get_kids())
+		return any('/' in s for s in self.get_children())
 
-class Owner:
+class IntrospectionParser:
 	def __init__(self, name, bus):
 		self.name = name
 		self.bus = bus
 
-	def introspect(self, path):
+	def _introspect(self, path):
 		try:
-			obj = self.bus.dbus.get_object(self.name, path)
-			iface = dbus.Interface(obj, 'org.freedesktop.DBus.Introspectable')
+			obj = self.bus.get_object(self.name, path)
+			iface = dbus.Interface(obj, dbus.BUS_DAEMON_IFACE + '.Introspectable')
 			data = iface.Introspect()
 		except dbus.DBusException:
 			return None
 
-		return IntrospectionParser(ElementTree.fromstring(data))
+		return IntrospectionNodeParser(ElementTree.fromstring(data))
 
-	def discover(self, match, path = '/'):
-		parser = self.introspect(path)
-		if not parser:
-			return []
+	def _discover_flat(self, path, parser):
+		items = {}
+		interfaces = parser.get_interfaces().keys()
+		if interfaces:
+			items[path] = {}
+			items[path]['interfaces'] = interfaces
 
-		items = []
-		for x in parser.get_interfaces(match):
-			items.append((path, self.name, x))
+		return items
+
+	def introspect(self, path = '/', parser = None):
+		items = {}
+		if not parser:
+			parser = self._introspect(path)
+		if not parser:
+			return {}
+		items.update(self._discover_flat(path, parser))
 
 		if path != '/':
 			path += '/'
 
-		recursive = parser.recursive_binding()
-		for k in parser.get_kids():
-			if recursive:
-				parser = self.introspect(path + k)
-				if not parser:
-					return []
-				for x in parser.get_interfaces(match):
-					items.append((path + k, self.name, x))
-			else:
-				items.extend(self.discover(match, path + k))
+		if parser.recursive_binding():
+			callback = self._discover_flat
+		else:
+			callback = self.introspect
+
+		for k in parser.get_children():
+			parser = self._introspect(path + k)
+			if not parser:
+				continue
+			items.update(callback(path + k, parser))
 
 		return items
 
@@ -325,7 +379,7 @@ class BusWrapper:
 				for x in self.get_service_names(match) ] ) )
 
 	def get_owners(self, match):
-		return [ Owner(x, self) \
+		return [ IntrospectionParser(x, self.dbus) \
 				for x in self.get_owner_names(match) ]
 
 if __name__ == '__main__':
-- 
2.6.0




More information about the openbmc mailing list