aboutsummaryrefslogtreecommitdiff
path: root/netclass/netclass.py
blob: 988bc773c16dcbf17a7fa4a8be081c6717b35e9c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# The netclasses derive this so they can be identified.
class netclass_root:
	pass

classes = {}

def netclass(name, assembly, members):
	member_names = [n for _, n in members]
	class proxy(netclass_root):
		def __init__(self, *args, **kwargs):
			if args == ():
				super().__setattr__("_contents", kwargs)
			else:
				super().__setattr__("_contents", dict(zip(member_names, args)))
			self._validate()
		
		def _validate(self):
			if set(member_names) != set(self._contents.keys()):
				raise TypeError("The instance does not have the correct members")
				for typ, name in members:
					val = self._contents[name]
					if not isinstance(val, typ):
						raise TypeError(f"{name} is {val}, must be {typ}")
		
		@staticmethod
		def from_dict(d):
			cleaned = {}
			for typ, name in members:
				val = d[name]
				if isinstance(val, dict) and issubclass(typ, netclass_root):
					val = typ.from_dict(val)
				cleaned[name] = val
			return proxy(**cleaned)
		
		def __getattr__(self, member):
			try:
				return self._contents[member]
			except KeyError:
				raise AttributeError(f"No such member {member}")
		
		def __setattr__(self, member, value):
			if member in self._members:
				self._contents[member] = value
			else:
				raise AttributeError(f"No such member {member}")
	
	proxy._name = name
	proxy._assembly = assembly
	proxy._members = members
	proxy.__name__ = name.split(".")[-1]
	classes[name] = proxy
	return proxy