Beispiel #1
0
 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")
Beispiel #2
0
    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)
Beispiel #3
0
    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
Beispiel #4
0
    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)
Beispiel #5
0
    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
Beispiel #6
0
 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)