class Repository: def __init__(self, path): # check for conformity if not exists(path): e = MalformedRepositoryError("Repo directory does not exist") e.set_repo_path(path) raise e if not exists(join(path, "data")): e = MalformedRepositoryError("No data directory found") e.set_repo_path(path) raise e self.path = path # objects that have an id self.classes = {} self.collections = {} self.names = {} self.standards = {} self.multinames = {} self.multistandards = {} self.bodies = {} # relations self.class_names = Links() self.class_standards = Links() self.multiname_names = Links() self.multistandard_standards = Links() self.body_standards = Links() self.body_multistandards = Links() self.collection_classes = Links() self.collection_standards = Links() self.collection_multistandards = Links() self.collection_names = Links() self.collection_multinames = Links() self.standard_replaced = Links(1) # load collection data for filename in os.listdir(join(path, "data")): if splitext(filename)[1] != ".blt": continue raw_coll = list(yaml.load_all(open(join(path, "data", filename), "r", "utf8"))) if len(raw_coll) == 0: raise MalformedCollectionError("No YAML document found in file %s" % filename) if len(raw_coll) > 1: raise MalformedCollectionError("More than one YAML document found in file %s" % filename) # we only consider the first YAML document raw_coll = raw_coll[0] if not isinstance(raw_coll["classes"], list): raise MalformedCollectionError("No class in collection %s" % raw_coll["id"]) if raw_coll["id"] in self.collections: raise MalformedCollectionError("Duplicate collection id %s" % raw_coll["id"]) if raw_coll["id"] != splitext(filename)[0]: raise MalformedCollectionError("Collection ID is not identical with file name: %s" % filename) for c in raw_coll["id"]: if not c in string.ascii_letters + string.digits + "_": raise MalformedCollectionError("Collection ID contains invalid character: %s" % c) try: coll = Collection(raw_coll) self.collections[coll.id] = coll except ParsingError as e: e.set_repo_path(path) e.set_collection(filename) raise e for cl in raw_coll["classes"]: if cl["id"] in self.classes: raise MalformedRepositoryError("Duplicate class id %s" % cl["id"]) try: cls = Class(cl) self.classes[cls.id] = cls except ParsingError as e: e.set_class(cl["id"]) e.set_repo_path(path) e.set_collection(filename) raise e self.collection_classes.add_link(coll, cls) names = [] standards = [] if "names" in cl: if isinstance(cl["names"], list): names = cl["names"] else: names = [cl["names"]] if "standards" in cl: if isinstance(cl["standards"], list): standards = cl["standards"] else: standards = [cl["standards"]] if len(names + standards) == 0: raise MalformedCollectionError("Encountered class with no names: %s" % raw_coll["id"]) for cn in names: try: name = ClassName(cn) except ParsingError as e: e.set_class(cls.id) raise e if name.get_id() in self.names: raise MalformedRepositoryError("Duplicate name %s" % name.get_id()) self.names[name.get_id()] = name self.class_names.add_link(cls, name) multinameid = name.group.get_safe() if multinameid: if not multinameid in self.multinames: multiname = MultiName(name.group) self.multinames[multinameid] = multiname else: multiname = self.multinames[multinameid] self.collection_multinames.add_link(coll, multiname) self.multiname_names.add_link(multiname, name) else: self.collection_names.add_link(coll, name) for sn in standards: try: standard = ClassStandard(sn) except ParsingError as e: e.set_class(cls.id) raise e if standard.get_id() in self.standards: raise MalformedRepositoryError("Duplicate standard %s" % standard.get_id()) self.standards[standard.get_id()] = standard self.class_standards.add_link(cls, standard) bodyid = standard.body if bodyid in self.bodies: body = self.bodies[bodyid] else: body = StandardBody(bodyid) self.bodies[bodyid] = body self.body_standards.add_link(body, standard) self.collection_standards.add_link(coll, standard) multistdid = standard.group.get_safe() if multistdid: if not multistdid in self.multistandards: multistd = MultiStandard(standard.group) self.multistandards[multistdid] = multistd self.body_multistandards.add_link(body, multistd) self.collection_multistandards.add_link(coll, multistd) else: multistd = self.multistandards[multistdid] self.multistandard_standards.add_link(multistd, standard) for standard in self.standards.values(): if not standard.replaces is None: if not standard.replaces in self.standards: raise MalformedRepositoryError( "Unknown replace field %s in standard %s" % (standard.replaces, standard.get_id()) ) self.standard_replaced.add_link(standard, self.standards[standard.replaces]) def iternames(self, items=["name"], **kwargs): """ Iterator over all names of the repo. Possible items to request: name, multiname, collection, class """ check_iterator_arguments(items, "name", ["multiname", "collection", "class"], kwargs) for name in self.names.values(): its = {"name": name} its["class"] = self.class_names.get_src(name) if self.multiname_names.contains_dst(name): its["multiname"] = self.multiname_names.get_src(name) its["collection"] = self.collection_multinames.get_src(multiname) else: its["multiname"] = None its["collection"] = self.collection_names.get_src(name) if filter_iterator_items(its, kwargs): yield tuple(its[key] for key in items) def itermultinames(self, items=["multiname"], **kwargs): """ Iterator over all multinames of the repo. Possible items to rerquest: multiname, names, collection """ check_iterator_arguments(items, "multiname", ["names", "collection"], kwargs) for mname in self.multinames.values(): its = {"multiname": mname} its["names"] = self.multiname_names.get_dsts(mname) its["collection"] = self.collection_multinames.get_src(mname) if filter_iterator_items(its, kwargs): yield tuple(its[key] for key in items) def iterstandards(self, items=["standard"], **kwargs): """ Iterator over all standards of the repo. Possible items to request: standard, multistandard, body, collection, class """ check_iterator_arguments(items, "standard", ["multistandard", "body", "collection", "class"], kwargs) for std in self.standards.values(): its = {"standard": std} its["class"] = self.class_standards.get_src(std) its["body"] = self.body_standards.get_src(std) if self.multistandard_standards.contains_dst(std): its["multistandard"] = self.multistandard_standards.get_src(std) its["collection"] = self.collection_multistandards.get_src(its["multistandard"]) else: its["multistandard"] = None its["collection"] = self.collection_standards.get_src(std) if filter_iterator_items(its, kwargs): yield tuple(its[key] for key in items) def itermultistandards(self, items=["multistandard"], **kwargs): """ Iterator over all multistandards of the repo. Possible items to rerquest: multistandard, standards, collection, body """ check_iterator_arguments(items, "multistandard", ["standards", "collection", "body"], kwargs) for mstandard in self.multistandards.values(): its = {"multistandard": mstandard} its["standards"] = self.multistandard_standards.get_dsts(mstandard) its["collection"] = self.collection_multistandards.get_src(mstandard) its["body"] = self.body_multistandards.get_src(mstandard) if filter_iterator_items(its, kwargs): yield tuple(its[key] for key in items) def iterclasses(self, items=["class"], **kwargs): """ Iterator over all classes of the repo. Possible items to request: class, collection """ check_iterator_arguments(items, "class", ["collection"], kwargs) for cl in self.classes.values(): its = {"class": cl} its["collection"] = self.collection_classes.get_src(cl) if filter_iterator_items(its, kwargs): yield tuple(its[key] for key in items) def itercollections(self): """ Iterator over all collections of the repo. Not possible to request items """ for coll in self.collections.values(): yield (coll,) def iterbodies(self): """ Iterator over all standard bodies of the repo. Not possible to request items """ for body in self.bodies.values(): yield (body,)
class OpenSCADData(DataBase): def __init__(self,repo): DataBase.__init__(self,"openscad",repo) self.modules = [] self.scadfiles = [] self.connectors = [] self.module_classes = Links() self.scadfile_modules = Links() self.collection_modules = Links() self.collection_scadfiles = Links() self.module_connectors = BijectiveLinks() if not exists(join(self.backend_root)): e = MalformedRepositoryError("openscad directory does not exist") e.set_repo_path(repo.path) raise e for coll in listdir(self.backend_root): basefilename = join(self.backend_root,coll,"%s.base" % coll) if not exists(basefilename): #skip directory that is no collection continue base = list(yaml.load_all(open(basefilename,"r","utf8"))) if len(base) != 1: raise MalformedCollectionError( "No YAML document found in file %s" % basefilename) base = base[0] for basefile in base: scadfile = SCADFile(basefile,coll) self.scadfiles.append(scadfile) self.collection_scadfiles.add_link(repo.collections[coll],scadfile) if basefile["type"] == "module": for mod in basefile["modules"]: try: module = SCADModule(mod,basefile,coll) self.modules.append(module) self.collection_modules.add_link(repo.collections[coll],module) self.scadfile_modules.add_link(scadfile,module) if "connectors" in mod: connectors = Connectors(mod["connectors"]) self.module_connectors.add_link(module,connectors) for id in module.classids: if not id in repo.classes: raise MalformedBaseError( "Unknown class %s" % id) if self.module_classes.contains_dst(repo.classes[id]): raise NonUniqueBaseError(id) self.module_classes.add_link(module,repo.classes[id]) except ParsingError as e: e.set_base(basefile["filename"]) raise e else: raise MalformedBaseError("Unknown base type %s" % basefile["type"]) def iternames(self,items=["name"],**kwargs): """ Iterator over all names of the repo. Possible items to request: name, multiname, collection, class, module """ check_iterator_arguments(items,"name",["multiname","collection","class","module"],kwargs) for name,multiname,coll,cl in self.repo.iternames(["name","multiname","collection","class"]): its = {"name" : name, "multiname" : multiname, "collection" : coll, "class" : cl} if self.module_classes.contains_dst(cl): its["module"] = self.module_classes.get_src(cl) if filter_iterator_items(its,kwargs): yield tuple(its[key] for key in items) def iterstandards(self,items=["standard"],**kwargs): """ Iterator over all standards of the repo. Possible items to request: standard, multistandard, collection, class, module """ check_iterator_arguments(items,"standard",["multistandard","collection","class","module"],kwargs) for standard,multistandard,coll,cl in self.repo.iterstandards(["standard","multistandard","collection","class"]): its = {"standard" : standard, "multistandard" : multistandard, "collection" : coll, "class" : cl} if self.module_classes.contains_dst(cl): its["module"] = self.module_classes.get_src(cl) if filter_iterator_items(its,kwargs): yield tuple(its[key] for key in items) def iterclasses(self,items=["class"],**kwargs): """ Iterator over all classes of the repo. Possible items to request: class, collection, scadfile, module """ check_iterator_arguments(items,"class",["collection","scadfile","module"],kwargs) for cl, coll in self.repo.iterclasses(["class","collection"]): its = {"class" : cl, "collection" : coll} if self.module_classes.contains_dst(cl): its["module"] = self.module_classes.get_src(cl) its["scadfile"] = self.scadfile_modules.get_src(its["module"]) if filter_iterator_items(its,kwargs): yield tuple(its[key] for key in items) def itermodules(self,items=["module"],**kwargs): """ Iterator over all OpenSCAD modules of the repo. Possible items to request: module, classes, collection """ check_iterator_arguments(items,"module",["classes","collection"],kwargs) for module in self.modules: its = {"module" : module} its["collection"] = self.collection_modules.get_src(module) its["classes"] = self.module_classes.get_dsts(module) if filter_iterator_items(its,kwargs): yield tuple(its[key] for key in items) def iterscadfiles(self,items=["scadfile"],**kwargs): """ Iterator over all OpenSCAD files of the repo. Possible items to request: scadfile, collection """ check_iterator_arguments(items,"scadfile",["collection"],kwargs) for sf in self.scadfiles: its = {"scadfile" : sf} its["collection"] = self.collection_scadfiles.get_src(sf) if filter_iterator_items(its,kwargs): yield tuple(its[key] for key in items)
class OpenSCADData(DataBase): def __init__(self, repo): DataBase.__init__(self, "openscad", repo) self.modules = [] self.scadfiles = [] self.connectors = [] self.module_classes = Links() self.scadfile_modules = Links() self.collection_modules = Links() self.collection_scadfiles = Links() self.module_connectors = BijectiveLinks() if not exists(join(self.backend_root)): e = MalformedRepositoryError("openscad directory does not exist") e.set_repo_path(repo.path) raise e for coll in listdir(self.backend_root): basefilename = join(self.backend_root, coll, "%s.base" % coll) if not exists(basefilename): #skip directory that is no collection continue base = list(yaml.load_all(open(basefilename, "r", "utf8"))) if len(base) != 1: raise MalformedCollectionError( "No YAML document found in file %s" % basefilename) base = base[0] for basefile in base: scadfile = SCADFile(basefile, coll) self.scadfiles.append(scadfile) self.collection_scadfiles.add_link(repo.collections[coll], scadfile) if basefile["type"] == "module": for mod in basefile["modules"]: try: module = SCADModule(mod, basefile, coll) self.modules.append(module) self.collection_modules.add_link( repo.collections[coll], module) self.scadfile_modules.add_link(scadfile, module) if "connectors" in mod: connectors = Connectors(mod["connectors"]) self.module_connectors.add_link( module, connectors) for id in module.classids: if not id in repo.classes: raise MalformedBaseError( "Unknown class %s" % id) if self.module_classes.contains_dst( repo.classes[id]): raise NonUniqueBaseError(id) self.module_classes.add_link( module, repo.classes[id]) except ParsingError as e: e.set_base(basefile["filename"]) raise e else: raise MalformedBaseError("Unknown base type %s" % basefile["type"]) def iternames(self, items=["name"], **kwargs): """ Iterator over all names of the repo. Possible items to request: name, multiname, collection, class, module """ check_iterator_arguments( items, "name", ["multiname", "collection", "class", "module"], kwargs) for name, multiname, coll, cl in self.repo.iternames( ["name", "multiname", "collection", "class"]): its = { "name": name, "multiname": multiname, "collection": coll, "class": cl } if self.module_classes.contains_dst(cl): its["module"] = self.module_classes.get_src(cl) if filter_iterator_items(its, kwargs): yield tuple(its[key] for key in items) def iterstandards(self, items=["standard"], **kwargs): """ Iterator over all standards of the repo. Possible items to request: standard, multistandard, collection, class, module """ check_iterator_arguments( items, "standard", ["multistandard", "collection", "class", "module"], kwargs) for standard, multistandard, coll, cl in self.repo.iterstandards( ["standard", "multistandard", "collection", "class"]): its = { "standard": standard, "multistandard": multistandard, "collection": coll, "class": cl } if self.module_classes.contains_dst(cl): its["module"] = self.module_classes.get_src(cl) if filter_iterator_items(its, kwargs): yield tuple(its[key] for key in items) def iterclasses(self, items=["class"], **kwargs): """ Iterator over all classes of the repo. Possible items to request: class, collection, scadfile, module """ check_iterator_arguments(items, "class", ["collection", "scadfile", "module"], kwargs) for cl, coll in self.repo.iterclasses(["class", "collection"]): its = {"class": cl, "collection": coll} if self.module_classes.contains_dst(cl): its["module"] = self.module_classes.get_src(cl) its["scadfile"] = self.scadfile_modules.get_src(its["module"]) if filter_iterator_items(its, kwargs): yield tuple(its[key] for key in items) def itermodules(self, items=["module"], **kwargs): """ Iterator over all OpenSCAD modules of the repo. Possible items to request: module, classes, collection """ check_iterator_arguments(items, "module", ["classes", "collection"], kwargs) for module in self.modules: its = {"module": module} its["collection"] = self.collection_modules.get_src(module) its["classes"] = self.module_classes.get_dsts(module) if filter_iterator_items(its, kwargs): yield tuple(its[key] for key in items) def iterscadfiles(self, items=["scadfile"], **kwargs): """ Iterator over all OpenSCAD files of the repo. Possible items to request: scadfile, collection """ check_iterator_arguments(items, "scadfile", ["collection"], kwargs) for sf in self.scadfiles: its = {"scadfile": sf} its["collection"] = self.collection_scadfiles.get_src(sf) if filter_iterator_items(its, kwargs): yield tuple(its[key] for key in items)
class FreeCADData(DataBase): def __init__(self,repo): DataBase.__init__(self,"freecad",repo) self.bases = [] self.base_classes = Links() self.collection_bases = Links() if not exists(self.backend_root): e = MalformedRepositoryError("freecad directory does not exist") e.set_repo_path(repo.path) raise e for coll in listdir(self.backend_root): basefilename = join(self.backend_root,coll,"%s.base" % coll) if not exists(basefilename): #skip directory that is no collection continue base_info = list(yaml.load_all(open(basefilename,"r","utf8"))) if len(base_info) != 1: raise MalformedCollectionError( "Not exactly one YAML document found in file %s" % basefilename) base_info = base_info[0] for basefile in base_info: if basefile["type"] == "function": basepath = join(self.backend_root,coll,basefile["filename"]) if not exists(basepath): raise MalformedBaseError("Python module %s does not exist" % basepath) for func in basefile["functions"]: try: function = BaseFunction(func,basefile,coll,self.backend_root) self.bases.append(function) self.collection_bases.add_link(repo.collections[coll],function) for id in func["classids"]: if not id in repo.classes: raise MalformedBaseError( "Unknown class %s" % id) if self.base_classes.contains_dst(repo.classes[id]): raise NonUniqueBaseError(id) self.base_classes.add_link(function,repo.classes[id]) except ParsingError as e: e.set_base(basefile["filename"]) e.set_collection(coll) raise e else: raise MalformedBaseError("Unknown base type %s" % basefile["type"]) def iterclasses(self,items=["class"],**kwargs): """ Iterator over all classes of the repo. Possible items to request: class, collection, base """ check_iterator_arguments(items,"class",["collection","base"],kwargs) for cl,coll in self.repo.iterclasses(["class","collection"]): its = {"class" : cl, "collection" : coll} if self.base_classes.contains_dst(cl): its["base"] = self.base_classes.get_src(cl) if filter_iterator_items(its,kwargs): yield tuple(its[key] for key in items) def iterstandards(self,items=["standard"],**kwargs): """ Iterator over all standards of the repo. Possible items to request: standard, multistandard, body, collection, class, base """ check_iterator_arguments(items,"standard",["multistandard","body", "collection","class","base"],kwargs) parent = ["standard","multistandard","body", "collection","class"] for tup in self.repo.iterstandards(parent): its = dict(zip(parent,tup)) if self.base_classes.contains_dst(its["class"]): its["base"] = self.base_classes.get_src(its["class"]) if filter_iterator_items(its,kwargs): yield tuple(its[key] for key in items) def iternames(self,items=["name"],**kwargs): """ Iterator over all names of the repo. Possible items to request: name, multiname, collection, class, base """ check_iterator_arguments(items,"name",["multiname", "collection","class","base"],kwargs) parent = ["name","multiname", "collection","class"] for tup in self.repo.iternames(parent): its = dict(zip(parent,tup)) if self.base_classes.contains_dst(its["class"]): its["base"] = self.base_classes.get_src(its["class"]) if filter_iterator_items(its,kwargs): yield tuple(its[key] for key in items) def iterbases(self,items=["base"],**kwargs): """ Iterator over all freecad bases of the repo. Possible items to request: base, classes, collection """ check_iterator_arguments(items,"base",["classes", "collection"],kwargs) for base in self.bases: its = {"base" : base} its["collection"] = self.collection_bases.get_src(base) its["classes"] = self.base_classes.get_dsts(base) if filter_iterator_items(its,kwargs): yield tuple(its[key] for key in items)
class DrawingsData(DataBase): def __init__(self, repo): DataBase.__init__(self, "drawings", repo) self.dimdrawings = [] self.condrawings = [] self.conlocations = [] self.dimdrawing_classes = Links() self.condrawings_classes = BipartiteLinks() self.conlocations_condrawings = BipartiteLinks() self.collection_dimdrawings = Links() self.collection_condrawings = Links() if not exists(join(self.backend_root)): e = MalformedRepositoryError("drawings directory does not exist") e.set_repo_path(path) raise e for coll in listdir(self.backend_root): basefilename = join(self.backend_root, coll, "%s.base" % coll) if not exists(basefilename): #skip directory that is no collection continue if coll not in repo.collections: raise MalformedRepositoryError( "Drawings for unknown collection found: %s " % coll) base_info = list(yaml.load_all(open(basefilename, "r", "utf8"))) if len(base_info) != 1: raise MalformedCollectionError( "Not exactly one YAML document found in file %s" % basefilename) base_info = base_info[0] for drawing_element in base_info: if drawing_element["type"] == "drawing-dimensions": draw = DrawingDimensions(drawing_element, coll, self.backend_root) if draw.get_svg() is None and draw.get_png() is None: raise MalformedRepositoryError( "No drawing files present for %s/%s" % (coll, draw.filename)) self.dimdrawings.append(draw) if drawing_element["classids"] == []: raise MalformedBaseError( "Drawing with no associated classes found") for id in drawing_element["classids"]: self.dimdrawing_classes.add_link( draw, self.repo.classes[id]) self.collection_dimdrawings.add_link( repo.collections[coll], draw) if drawing_element["type"] == "drawing-connector": draw = DrawingConnectors(drawing_element, coll, self.backend_root) if draw.get_svg() is None and draw.get_png() is None: raise MalformedRepositoryError( "No drawing files present for %s/%s" % (coll, draw.filename)) if not draw.location in self.conlocations: self.conlocations.append(draw.location) self.conlocations_condrawings.add_link(draw.location, draw) self.condrawings.append(draw) for id in drawing_element["classids"]: self.condrawings_classes.add_link( draw, self.repo.classes[id]) self.collection_condrawings.add_link( repo.collections[coll], draw) def iterclasses(self, items=["class"], **kwargs): """ Iterator over all classes of the repo. Possible items to request: class, collection, dimdrawing, condrawings """ check_iterator_arguments(items, "class", ["collection", "dimdrawing", "condrawings"], kwargs) for cl, coll in self.repo.iterclasses(["class", "collection"]): its = {"class": cl, "collection": coll} if self.condrawings_classes.contains_dst(cl): its["condrawings"] = self.condrawings_classes.get_srcs(cl) else: its["condrawings"] = [] if self.dimdrawing_classes.contains_dst(cl): its["dimdrawing"] = self.dimdrawing_classes.get_src(cl) else: its["dimdrawing"] = None if filter_iterator_items(its, kwargs): yield tuple(its[key] for key in items) def iterdimdrawings(self, items=["dimdrawing"], **kwargs): """ Iterator over all dimension drawings of the repo. Possible items to request: dimdrawing, classes, collection """ check_iterator_arguments(items, "dimdrawing", ["classes", "collection"], kwargs) for draw in self.dimdrawings: its = {"dimdrawing": draw} its["collection"] = self.collection_dimdrawings.get_src(draw) its["classes"] = self.dimdrawing_classes.get_dsts(draw) if filter_iterator_items(its, kwargs): yield tuple(its[key] for key in items) def itercondrawings(self, items=["condrawing"], **kwargs): """ Iterator over all connector drawings of the repo. Possible items to request: condrawing, conlocations, classes, collection """ check_iterator_arguments(items, "condrawing", ["conlocations", "classes", "collection"], kwargs) for draw in self.condrawings: its = {"condrawing": draw} its["collection"] = self.collection_condrawings.get_src(draw) its["classes"] = self.condrawings_classes.get_dsts(draw) its["conlocations"] = self.conlocations_condrawings.get_srcs(draw) if filter_iterator_items(its, kwargs): yield tuple(its[key] for key in items)
class DrawingsData(DataBase): def __init__(self,repo): DataBase.__init__(self,"drawings", repo) self.dimdrawings = [] self.condrawings = [] self.conlocations = [] self.dimdrawing_classes = Links() self.condrawings_classes = BipartiteLinks() self.conlocations_condrawings = BipartiteLinks() self.collection_dimdrawings = Links() self.collection_condrawings = Links() if not exists(join(self.backend_root)): e = MalformedRepositoryError("drawings directory does not exist") e.set_repo_path(path) raise e for coll in listdir(self.backend_root): basefilename = join(self.backend_root,coll,"%s.base" % coll) if not exists(basefilename): #skip directory that is no collection continue if coll not in repo.collections: raise MalformedRepositoryError( "Drawings for unknown collection found: %s " % coll) base_info = list(yaml.load_all(open(basefilename,"r","utf8"))) if len(base_info) != 1: raise MalformedCollectionError( "Not exactly one YAML document found in file %s" % basefilename) base_info = base_info[0] for drawing_element in base_info: if drawing_element["type"] == "drawing-dimensions": draw = DrawingDimensions(drawing_element,coll,self.backend_root) if draw.get_svg() is None and draw.get_png() is None: raise MalformedRepositoryError("No drawing files present for %s/%s" % (coll,draw.filename)) self.dimdrawings.append(draw) if drawing_element["classids"] == []: raise MalformedBaseError("Drawing with no associated classes found") for id in drawing_element["classids"]: self.dimdrawing_classes.add_link(draw,self.repo.classes[id]) self.collection_dimdrawings.add_link(repo.collections[coll],draw) if drawing_element["type"] == "drawing-connector": draw = DrawingConnectors(drawing_element,coll,self.backend_root) if draw.get_svg() is None and draw.get_png() is None: raise MalformedRepositoryError("No drawing files present for %s/%s" % (coll,draw.filename)) if not draw.location in self.conlocations: self.conlocations.append(draw.location) self.conlocations_condrawings.add_link(draw.location,draw) self.condrawings.append(draw) for id in drawing_element["classids"]: self.condrawings_classes.add_link(draw,self.repo.classes[id]) self.collection_condrawings.add_link(repo.collections[coll],draw) def iterclasses(self,items=["class"],**kwargs): """ Iterator over all classes of the repo. Possible items to request: class, collection, dimdrawing, condrawings """ check_iterator_arguments(items,"class",["collection","dimdrawing","condrawings"],kwargs) for cl,coll in self.repo.iterclasses(["class","collection"]): its = {"class" : cl, "collection" : coll} if self.condrawings_classes.contains_dst(cl): its["condrawings"] = self.condrawings_classes.get_srcs(cl) else: its["condrawings"] = [] if self.dimdrawing_classes.contains_dst(cl): its["dimdrawing"] = self.dimdrawing_classes.get_src(cl) else: its["dimdrawing"] = None if filter_iterator_items(its,kwargs): yield tuple(its[key] for key in items) def iterdimdrawings(self,items=["dimdrawing"],**kwargs): """ Iterator over all dimension drawings of the repo. Possible items to request: dimdrawing, classes, collection """ check_iterator_arguments(items,"dimdrawing",["classes", "collection"],kwargs) for draw in self.dimdrawings: its = {"dimdrawing" : draw} its["collection"] = self.collection_dimdrawings.get_src(draw); its["classes"] = self.dimdrawing_classes.get_dsts(draw) if filter_iterator_items(its,kwargs): yield tuple(its[key] for key in items) def itercondrawings(self,items=["condrawing"],**kwargs): """ Iterator over all connector drawings of the repo. Possible items to request: condrawing, conlocations, classes, collection """ check_iterator_arguments(items,"condrawing",["conlocations", "classes", "collection"],kwargs) for draw in self.condrawings: its = {"condrawing" : draw} its["collection"] = self.collection_condrawings.get_src(draw) its["classes"] = self.condrawings_classes.get_dsts(draw) its["conlocations"] = self.conlocations_condrawings.get_srcs(draw) if filter_iterator_items(its,kwargs): yield tuple(its[key] for key in items)
class Repository: def __init__(self, path): #check for conformity if not exists(path): e = MalformedRepositoryError("Repo directory does not exist") e.set_repo_path(path) raise e if not exists(join(path, "data")): e = MalformedRepositoryError("No data directory found") e.set_repo_path(path) raise e self.path = path #objects that have an id self.classes = {} self.collections = {} self.names = {} self.standards = {} self.multinames = {} self.multistandards = {} self.bodies = {} #relations self.class_names = Links() self.class_standards = Links() self.multiname_names = Links() self.multistandard_standards = Links() self.body_standards = Links() self.body_multistandards = Links() self.collection_classes = Links() self.collection_standards = Links() self.collection_multistandards = Links() self.collection_names = Links() self.collection_multinames = Links() self.standard_replaced = Links(1) #load collection data for filename in os.listdir(join(path, "data")): if splitext(filename)[1] != ".blt": continue raw_coll = list( yaml.load_all(open(join(path, "data", filename), "r", "utf8"))) if len(raw_coll) == 0: raise MalformedCollectionError( "No YAML document found in file %s" % filename) if len(raw_coll) > 1: raise MalformedCollectionError( "More than one YAML document found in file %s" % filename) #we only consider the first YAML document raw_coll = raw_coll[0] if not isinstance(raw_coll["classes"], list): raise MalformedCollectionError("No class in collection %s" % raw_coll["id"]) if raw_coll["id"] in self.collections: raise MalformedCollectionError("Duplicate collection id %s" % raw_coll["id"]) if raw_coll["id"] != splitext(filename)[0]: raise MalformedCollectionError( "Collection ID is not identical with file name: %s" % filename) for c in raw_coll["id"]: if not c in string.ascii_letters + string.digits + "_": raise MalformedCollectionError( "Collection ID contains invalid character: %s" % c) try: coll = Collection(raw_coll) self.collections[coll.id] = coll except ParsingError as e: e.set_repo_path(path) e.set_collection(filename) raise e for cl in raw_coll['classes']: if cl["id"] in self.classes: raise MalformedRepositoryError("Duplicate class id %s" % cl["id"]) try: cls = Class(cl) self.classes[cls.id] = cls except ParsingError as e: e.set_class(cl["id"]) e.set_repo_path(path) e.set_collection(filename) raise e self.collection_classes.add_link(coll, cls) names = [] standards = [] if 'names' in cl: if isinstance(cl['names'], list): names = cl['names'] else: names = [cl['names']] if 'standards' in cl: if isinstance(cl['standards'], list): standards = cl['standards'] else: standards = [cl['standards']] if len(names + standards) == 0: raise MalformedCollectionError( "Encountered class with no names: %s" % raw_coll["id"]) for cn in names: try: name = ClassName(cn) except ParsingError as e: e.set_class(cls.id) raise e if name.get_id() in self.names: raise MalformedRepositoryError("Duplicate name %s" % name.get_id()) self.names[name.get_id()] = name self.class_names.add_link(cls, name) multinameid = name.group.get_safe() if multinameid: if not multinameid in self.multinames: multiname = MultiName(name.group) self.multinames[multinameid] = multiname else: multiname = self.multinames[multinameid] self.collection_multinames.add_link(coll, multiname) self.multiname_names.add_link(multiname, name) else: self.collection_names.add_link(coll, name) for sn in standards: try: standard = ClassStandard(sn) except ParsingError as e: e.set_class(cls.id) raise e if standard.get_id() in self.standards: raise MalformedRepositoryError( "Duplicate standard %s" % standard.get_id()) self.standards[standard.get_id()] = standard self.class_standards.add_link(cls, standard) bodyid = standard.body if bodyid in self.bodies: body = self.bodies[bodyid] else: body = StandardBody(bodyid) self.bodies[bodyid] = body self.body_standards.add_link(body, standard) self.collection_standards.add_link(coll, standard) multistdid = standard.group.get_safe() if multistdid: if not multistdid in self.multistandards: multistd = MultiStandard(standard.group) self.multistandards[multistdid] = multistd self.body_multistandards.add_link(body, multistd) self.collection_multistandards.add_link( coll, multistd) else: multistd = self.multistandards[multistdid] self.multistandard_standards.add_link( multistd, standard) for standard in self.standards.values(): if not standard.replaces is None: if not standard.replaces in self.standards: raise MalformedRepositoryError( "Unknown replace field %s in standard %s" % (standard.replaces, standard.get_id())) self.standard_replaced.add_link( standard, self.standards[standard.replaces]) def iternames(self, items=["name"], **kwargs): """ Iterator over all names of the repo. Possible items to request: name, multiname, collection, class """ check_iterator_arguments(items, "name", ["multiname", "collection", "class"], kwargs) for name in self.names.values(): its = {"name": name} its["class"] = self.class_names.get_src(name) if self.multiname_names.contains_dst(name): its["multiname"] = self.multiname_names.get_src(name) its["collection"] = self.collection_multinames.get_src( multiname) else: its["multiname"] = None its["collection"] = self.collection_names.get_src(name) if filter_iterator_items(its, kwargs): yield tuple(its[key] for key in items) def itermultinames(self, items=["multiname"], **kwargs): """ Iterator over all multinames of the repo. Possible items to rerquest: multiname, names, collection """ check_iterator_arguments(items, "multiname", ["names", "collection"], kwargs) for mname in self.multinames.values(): its = {"multiname": mname} its["names"] = self.multiname_names.get_dsts(mname) its["collection"] = self.collection_multinames.get_src(mname) if filter_iterator_items(its, kwargs): yield tuple(its[key] for key in items) def iterstandards(self, items=["standard"], **kwargs): """ Iterator over all standards of the repo. Possible items to request: standard, multistandard, body, collection, class """ check_iterator_arguments( items, "standard", ["multistandard", "body", "collection", "class"], kwargs) for std in self.standards.values(): its = {"standard": std} its["class"] = self.class_standards.get_src(std) its["body"] = self.body_standards.get_src(std) if self.multistandard_standards.contains_dst(std): its["multistandard"] = self.multistandard_standards.get_src( std) its["collection"] = self.collection_multistandards.get_src( its["multistandard"]) else: its["multistandard"] = None its["collection"] = self.collection_standards.get_src(std) if filter_iterator_items(its, kwargs): yield tuple(its[key] for key in items) def itermultistandards(self, items=["multistandard"], **kwargs): """ Iterator over all multistandards of the repo. Possible items to rerquest: multistandard, standards, collection, body """ check_iterator_arguments(items, "multistandard", ["standards", "collection", "body"], kwargs) for mstandard in self.multistandards.values(): its = {"multistandard": mstandard} its["standards"] = self.multistandard_standards.get_dsts(mstandard) its["collection"] = self.collection_multistandards.get_src( mstandard) its["body"] = self.body_multistandards.get_src(mstandard) if filter_iterator_items(its, kwargs): yield tuple(its[key] for key in items) def iterclasses(self, items=["class"], **kwargs): """ Iterator over all classes of the repo. Possible items to request: class, collection """ check_iterator_arguments(items, "class", ["collection"], kwargs) for cl in self.classes.values(): its = {"class": cl} its["collection"] = self.collection_classes.get_src(cl) if filter_iterator_items(its, kwargs): yield tuple(its[key] for key in items) def itercollections(self): """ Iterator over all collections of the repo. Not possible to request items """ for coll in self.collections.values(): yield (coll, ) def iterbodies(self): """ Iterator over all standard bodies of the repo. Not possible to request items """ for body in self.bodies.values(): yield (body, )