Skip to content

Instantly share code, notes, and snippets.

@juriad
Created March 26, 2017 19:53
Show Gist options
  • Save juriad/937ded801a8c43283ece45aff1e9339b to your computer and use it in GitHub Desktop.
Save juriad/937ded801a8c43283ece45aff1e9339b to your computer and use it in GitHub Desktop.
Graph with Meta
from enum import Enum
class MetaItem(type):
def __new__(cls, name, bases, namespace, **kwds):
def named_adder(k):
def adder(self, val):
getattr(self, k).append(val)
val.set_parent(self)
return adder
def named_setter(k):
def setter(self, val):
setattr(self, k, val)
val.set_parent(self)
return setter
def setting_init(mod, old):
def init(self, *args, **kwargs):
old(self, *args, **kwargs)
for k, (v, _mn, _mf) in mod.items():
setattr(self, k, v)
return init
mod = {}
for k, v in namespace.items():
if isinstance(v, list):
mod[k] = (v, 'add' + k.title()[:-1], named_adder(k))
if v == None:
mod[k] = (v, 'set' + k.title(), named_setter(k))
for k, (_v, mn, mf) in mod.items():
namespace[mn] = mf
del namespace[k]
namespace['__init__'] = setting_init(mod, namespace['__init__'])
result = type.__new__(cls, name, bases, namespace, **kwds)
return result
class Item(object, metaclass=MetaItem):
def __init__(self, type, id_attr='id', add_parent=False):
self._type = type
self._id_attr = id_attr
self._add_parent = add_parent
self._gen = {}
self._id = None
self._parent = None
def _next_id(self, type):
i = self._gen.get(type, 0)
self._gen[type] = i + 1
return self.type + str(i + 1)
def set_parent(self, parent):
self._parent = parent
def get_id(self):
i = getattr(self, self._id_attr)
if i != None:
if self._add_parent:
return "%s::%s" % (self._parent.get_id(), i)
else:
return i
if self._id != None:
self._id = self._parent._next_id(self.item_type)
return '%s::%s' % (self._parent.get_id(), self._id)
class KeyForEnum(Enum):
ALL = 'all'
GRAPHML = 'graphml'
GRAPH = 'graph'
NODE = 'node'
EDGE = 'edge'
HYPEREDGE = 'hyperedge'
PORT = 'port'
ENDPOINT = 'endpoint'
class AttrTypeEnum(Enum):
BOOLEAN = 'boolean'
INT = 'int'
LONG = 'long'
FLOAT = 'float'
DOUBLE = 'double'
STRING = 'string'
class Key(Item):
def __init__(self, id, for_=KeyForEnum.ALL, desc=None, default=None, attr_name=None, attr_type=None):
super().__init__('k')
self.id = id
self.for_ = for_
self.desc = desc
self.default = default
class Data(Item):
def __init__(self, key, value, id=None):
super().__init__('d')
self.key = key
self.value = value
self.id = id
class Port(Item):
datas = []
ports = []
def __init__(self, name, desc=None):
super().__init__('p', 'name', True)
self.name = name
self.desc = desc
def get_node(self):
p = self._parent
while p != None and p._type != 'n':
p = p._parent
if p == None:
raise RuntimeError('Port is not part of any node')
return p
class Node(Item):
datas = []
ports = []
graph = None
def __init__(self, id=None, desc=None):
super().__init__('n')
self.id = id
self.desc = desc
class Edge(Item):
datas = []
graph = None
def __init__(self, source=None, target=None, id=None, desc=None, directed=None, source_port=None, target_port=None):
super().__init__('e')
self.source = source
self.target = target
self.id = id
self.desc = desc
self.directed = directed
self.source_port = source_port
self.target_port = target_port
if source == None and source_port == None:
raise RuntimeError('At least one of source and source_port must be set')
if source_port != None:
source = source_port.getNode()
if target == None and target_port == None:
raise RuntimeError('At least one of target and target_port must be set')
if target_port != None:
target = target_port.getNode()
def is_directed(self):
if self.directed != None:
return self.directed
return self._parent.edgedefault != EdgeDefaultEnum.UNDIRECTED
class EndpointTypeEnum(Enum):
IN = 'in'
OUT = 'out'
UNDIR = 'undir'
class Endpoint(Item):
def __init__(self, node=None, id=None, desc=None, port=None, type=EndpointTypeEnum.UNDIR):
super().__init__('d')
self.node = node
self.id = id
self.desc = desc
self.port = port
self.type = type
if node == None and port == None:
raise RuntimeError('At least one of node and port must be set')
if port != None:
node = port.getNode()
class Hyperedge(Item):
datas = []
endpoints = []
graph = None
def __init__(self, id=None, desc=None):
super().__init__('h')
self.id = id
self.desc = desc
class EdgeDefaultEnum(Enum):
DIRECTED = 'directed'
UNDIRECTED = 'undirected'
class Graph(Item):
datas = []
nodes = []
edges = []
hyperedges = []
def __init__(self, id=None, desc=None, edgedefault=EdgeDefaultEnum.DIRECTED):
super().__init__('g')
self.id = id
self.desc = desc
self.edgedefault = edgedefault
class GraphML (Item):
keys = []
graphs = []
datas = []
def __init__(self, desc=None):
super().__init__('_')
self.desc = desc
def get_id(self):
return ''
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment