def test_longest_match(): class FancyComplexExtension(object): @property def types(self): return [] @property def tag_mapping(self): return [] @property def url_mapping(self): return [('http://stsci.edu/schemas/asdf/core/', 'FOOBAR/{url_suffix}')] l = extension.AsdfExtensionList( [extension.BuiltinExtension(), FancyComplexExtension()]) assert l.url_mapping( 'http://stsci.edu/schemas/asdf/core/asdf-1.0.0') == 'FOOBAR/asdf-1.0.0' assert l.url_mapping( 'http://stsci.edu/schemas/asdf/transform/transform-1.0.0') != 'FOOBAR/transform-1.0.0'
def __init__(self, init=None, schema=None, extensions=None, pass_invalid_values=False): """ Parameters ---------- init : shape tuple, file path, file object, astropy.io.fits.HDUList, numpy array, None - None: A default data model with no shape - shape tuple: Initialize with empty data of the given shape - file path: Initialize from the given file (FITS or ASDF) - readable file object: Initialize from the given file object - ``astropy.io.fits.HDUList``: Initialize from the given `~astropy.io.fits.HDUList`. - A numpy array: Used to initialize the data array - dict: The object model tree for the data model schema : tree of objects representing a JSON schema, or string naming a schema, optional The schema to use to understand the elements on the model. If not provided, the schema associated with this class will be used. extensions: classes extending the standard set of extensions, optional. If an extension is defined, the prefix used should be 'url'. pass_invalid_values: If true, values that do not validate the schema can be read and written and only a warning will be generated """ # Set the extensions if extensions is None: extensions = jwst_extensions[:] else: extensions.extend(jwst_extensions) self._extensions = extensions # Override value of pass_invalid value if environment value set if "PASS_INVALID_VALUES" in os.environ: pass_invalid_values = os.environ["PASS_INVALID_VALUES"] try: pass_invalid_values = bool(int(pass_invalid_values)) except ValueError: pass_invalid_values = False self._pass_invalid_values = pass_invalid_values # Construct the path to the schema files filename = os.path.abspath(inspect.getfile(self.__class__)) base_url = os.path.join(os.path.dirname(filename), 'schemas', '') # Load the schema files if schema is None: schema_path = os.path.join(base_url, self.schema_url) extension_list = asdf_extension.AsdfExtensionList(self._extensions) schema = asdf_schema.load_schema( schema_path, resolver=extension_list.url_mapping, resolve_references=True) self._schema = mschema.flatten_combiners(schema) # Determine what kind of input we have (init) and execute the # proper code to intiailize the model self._files_to_close = [] self._iscopy = False is_array = False is_shape = False shape = None if init is None: asdf = AsdfFile(extensions=extensions) elif isinstance(init, dict): asdf = AsdfFile(init, extensions=extensions) elif isinstance(init, np.ndarray): asdf = AsdfFile(extensions=extensions) shape = init.shape is_array = True elif isinstance(init, self.__class__): self.clone(self, init) return elif isinstance(init, DataModel): raise TypeError( "Passed in {0!r} is not of the expected subclass {1!r}".format( init.__class__.__name__, self.__class__.__name__)) elif isinstance(init, AsdfFile): asdf = init elif isinstance(init, tuple): for item in init: if not isinstance(item, int): raise ValueError("shape must be a tuple of ints") shape = init asdf = AsdfFile() is_shape = True elif isinstance(init, fits.HDUList): asdf = fits_support.from_fits(init, self._schema, extensions, pass_invalid_values) elif isinstance(init, (six.string_types, bytes)): if isinstance(init, bytes): init = init.decode(sys.getfilesystemencoding()) file_type = filetype.check(init) if file_type == "fits": hdulist = fits.open(init) asdf = fits_support.from_fits(hdulist, self._schema, extensions, pass_invalid_values) self._files_to_close.append(hdulist) elif file_type == "asdf": asdf = AsdfFile.open(init, extensions=extensions) else: # TODO handle json files as well raise IOError( "File does not appear to be a FITS or ASDF file.") else: raise ValueError("Can't initialize datamodel using {0}".format( str(type(init)))) # Initialize object fields as determined fro the code above self._shape = shape self._instance = asdf.tree self._asdf = asdf self._ctx = self # if the input is from a file, set the filename attribute if isinstance(init, six.string_types): self.meta.filename = os.path.basename(init) elif isinstance(init, fits.HDUList): info = init.fileinfo(0) if info is not None: filename = info.get('filename') if filename is not None: self.meta.filename = os.path.basename(filename) # if the input model doesn't have a date set, use the current date/time if self.meta.date is None: self.meta.date = Time(datetime.datetime.now()) if hasattr(self.meta.date, 'value'): self.meta.date.format = 'isot' self.meta.date = str(self.meta.date.value) # store the data model type, if not already set if hasattr(self.meta, 'model_type'): if self.meta.model_type is None: self.meta.model_type = self.__class__.__name__ else: self.meta.model_type = None if is_array: primary_array_name = self.get_primary_array_name() if primary_array_name is None: raise TypeError( "Array passed to DataModel.__init__, but model has " "no primary array in its schema") setattr(self, primary_array_name, init) # TODO this code looks useless if is_shape: getattr(self, self.get_primary_array_name())