def copy_files(self, target_dir): """ Copy base resources to the target location, according to settings. """ for origpath, module, contains in self.settings.manual_profiles: if not origpath: continue origpath = self.rel_to_settings_path(self.settings, self.clean_it(origpath)) if os.path.exists(origpath): tgt = os.path.join(target_dir, os.path.basename(origpath)) logger.info("Copying manual profiles in {} to {}".format(os.path.basename(origpath), tgt)) os.makedirs(os.path.dirname(tgt), exist_ok=True) shutil.copyfile(origpath, tgt) else: logger.error(f"Manual profile {origpath} does not exits")
def unittest_for_resource(self, resource): """ Returns a FHIRUnitTest instance or None for the given resource, depending on if the class to be tested is known. """ classname = resource.content.get('resourceType') assert classname if classname in self.settings.classmap: classname = self.settings.classmap[classname] klass = fhirclass.FHIRClass.with_name(classname) if klass is None: logger.error( 'There is no class for "{}", cannot create unit tests'.format( classname)) return None return FHIRUnitTest(self, resource.filepath, resource.content, klass)
def process_profile(self): """ Extract all elements and create classes. """ struct = self.structure.differential # or self.structure.snapshot if struct is not None: mapped = {} self.elements = [] for elem_dict in struct: element = FHIRStructureDefinitionElement( self, elem_dict, self.main_element is None) self.elements.append(element) mapped[element.path] = element # establish hierarchy (may move to extra loop in case elements are no longer in order) if element.is_main_profile_element: self.main_element = element parent = mapped.get(element.parent_name) if parent: parent.add_child(element) # resolve element dependencies for element in self.elements: element.resolve_dependencies() # run check: if n_min > 0 and parent is in summary, must also be in summary for element in self.elements: if element.n_min is not None and element.n_min > 0: if element.parent is not None and element.parent.is_summary and not element.is_summary: logger.error("n_min > 0 but not summary: `{}`".format( element.path)) element.summary_n_min_conflict = True # create classes and class properties if self.main_element is not None: snap_class, subs = self.main_element.create_class( sort_resources=self._sort_resources) if snap_class is None: raise Exception( 'The main element for "{}" did not create a class'.format( self.url)) self.found_class(snap_class) for sub in subs: self.found_class(sub) self.targetname = snap_class.name
def expand(self): """ Expand into a list of FHIRUnitTestItem_name instances. """ tests = [] for key, val in self.content.items(): if 'resourceType' == key or 'fhir_comments' == key or '_' == key[: 1]: continue prop = self.klass.property_for(key) if prop is None: path = "{}.{}".format(self.prefix, key) if self.prefix else key logger.warning( 'Unknown property "{}" in unit test on {} in {}'.format( path, self.klass.name, self.filepath)) else: propclass = fhirclass.FHIRClass.with_name(prop.class_name) if propclass is None: path = "{}.{}".format( self.prefix, prop.name) if self.prefix else prop.name logger.error( 'There is no class "{}" for property "{}" in {}'. format(prop.class_name, path, self.filepath)) else: path = self.controller.make_path(self.prefix, prop.name) if list == type(val): i = 0 for ival in val: idxpath = self.controller.settings.unittest_format_path_index.format( path, i) item = FHIRUnitTestItem(self.filepath, idxpath, ival, propclass, True, prop.enum) tests.extend(item.create_tests(self.controller)) i += 1 if i >= 10: # let's assume we don't need 100s of unit tests break else: item = FHIRUnitTestItem(self.filepath, path, val, propclass, False, prop.enum) tests.extend(item.create_tests(self.controller)) self.tests = sorted(tests, key=lambda t: t.path)
def resolve_dependencies(self): # update the definition from a reference, if there is one if self.content_reference is not None: if '#' != self.content_reference[:1]: raise Exception( "Only relative 'contentReference' element definitions are supported right now" ) elem = self.element.profile.element_with_id( self.content_reference[1:]) if elem is None: raise Exception( "There is no element definiton with id \"{}\", as referenced by {} in {}" .format(self.content_reference, self.path, self.profile.url)) self._content_referenced = elem.definition # resolve bindings if self.binding is not None and self.binding.is_required and ( self.binding.valueSet is not None or self.binding.legacy_uri is not None or self.binding.legacy_canonical is not None): uri = self.binding.valueSet or self.binding.legacy_canonical or self.binding.legacy_uri if 'http://hl7.org/fhir' != uri[:19]: logger.debug("Ignoring foreign ValueSet \"{}\"".format(uri)) return # remove version from canonical URI, if present, e.g. "http://hl7.org/fhir/ValueSet/name-use|4.0.0" if '|' in uri: uri = uri.split('|')[0] valueset = self.element.profile.spec.valueset_with_uri(uri) if valueset is None: logger.error( "There is no ValueSet for required binding \"{}\" on {} in {}" .format(uri, self.name or self.prop_name, self.element.profile.name)) else: self.element.valueset = valueset self.element.enum = valueset.enum
def do_render(self, data, template_name, target_path): """ Render the given data using a Jinja2 template, writing to the file at the target path. :param template_name: The Jinja2 template to render, located in settings.tpl_base :param target_path: Output path """ try: template = self.jinjaenv.get_template(os.path.basename(template_name)) except TemplateNotFound as e: logger.error("Template \"{}\" not found in «{}», cannot render" .format(template_name, self.settings.tpl_base)) return if not target_path: raise Exception("No target filepath provided") dirpath = os.path.dirname(target_path) if not os.path.isdir(dirpath): os.makedirs(dirpath) with io.open(target_path, 'w', encoding='utf-8') as handle: logger.info('Writing {}'.format(target_path)) rendered = template.render(data) handle.write(rendered)