def check(self, image_data, diff_threshold=0.1, expect_equal=True, basename=None): """ Checks that the given image contents are comparable with the ones stored in the data directory. :param bytes image_data: image data :param str|None basename: basename to store the information in the data directory. If none, use the name of the test function. :param bool expect_equal: if the image should considered equal below of the given threshold. If False, the image should be considered different at least above the threshold. :param float diff_threshold: Tolerage as a percentage (1 to 100) on how the images are allowed to differ. """ __tracebackhide__ = True from PIL import Image def dump_fn(target): image = Image.open(io.BytesIO(image_data)) image.save(six.text_type(target), "PNG") perform_regression_check( datadir=self.datadir, original_datadir=self.original_datadir, request=self.request, check_fn=partial( self._check_images_manhattan_distance, diff_threshold=diff_threshold, expect_equal=expect_equal, ), dump_fn=dump_fn, extension=".png", basename=basename, force_regen=self.force_regen, )
def check( # type: ignore self, contents: Union[str, StringList], encoding: Optional[str] = "UTF-8", extension: str = ".txt", newline: Optional[str] = None, basename: Optional[str] = None, fullpath: Optional[str] = None, binary: bool = False, obtained_filename: Optional[str] = None, check_fn: Optional[Callable[[Any, Any], Any]] = None, ): r""" Checks the contents against a previously recorded version, or generates a new file. :param contents: :param extension: The extension of the reference file. :param \*\*kwargs: Additional keyword arguments passed to :meth:`pytest_regressions.file_regression.FileRegressionFixture.check`. .. seealso:: :func:`~.check_file_regression` """ __tracebackhide__ = True if isinstance(contents, StringList): contents = str(contents) if not isinstance(contents, str): raise TypeError( f"Expected text contents but received type {type(contents).__name__!r}" ) if check_fn is None: check_fn = partial(check_text_files, encoding="UTF-8") def dump_fn(filename): PathPlus(filename, newline=newline).write_clean(cast(str, contents)) perform_regression_check( datadir=self.datadir, original_datadir=self.original_datadir, request=self.request, check_fn=check_fn, dump_fn=dump_fn, extension=extension, basename=basename, fullpath=fullpath, force_regen=self.force_regen, obtained_filename=obtained_filename, )
def check(self, data_dict, basename=None, fullpath=None, ignores=None): """ Checks the given dict against a previously recorded version, or generate a new file. :param dict data_dict: any yaml serializable dict. :param str basename: basename of the file to test/record. If not given the name of the test is used. Use either `basename` or `fullpath`. :param str fullpath: complete path to use as a reference file. This option will ignore ``datadir`` fixture when reading *expected* files but will still use it to write *obtained* files. Useful if a reference file is located in the session data dir for example. ``basename`` and ``fullpath`` are exclusive. """ __tracebackhide__ = True if ignores: data_dict = delete_keys_from_dict(data_dict, ignores) def dump(filename): """Dump dict contents to the given filename""" import yaml with filename.open("wb") as f: yaml.dump_all( [data_dict], f, Dumper=RegressionYamlDumper, default_flow_style=False, allow_unicode=True, indent=2, encoding="utf-8", ) perform_regression_check( datadir=self.datadir, original_datadir=self.original_datadir, request=self.request, check_fn=partial(check_text_files, encoding="UTF-8"), dump_fn=dump, extension=".yml", basename=basename, fullpath=fullpath, force_regen=self.force_regen, )
def check( self, data_frame, basename=None, fullpath=None, tolerances=None, default_tolerance=None, ): """ Checks the given pandas dataframe against a previously recorded version, or generate a new file. Example:: data_frame = pandas.DataFrame.from_dict({ 'U_gas': U[0][positions], 'U_liquid': U[1][positions], 'gas_vol_frac [-]': vol_frac[0][positions], 'liquid_vol_frac [-]': vol_frac[1][positions], 'P': Pa_to_bar(P)[positions], }) dataframe_regression.check(data_frame) :param pandas.DataFrame data_frame: pandas DataFrame containing data for regression check. :param str basename: basename of the file to test/record. If not given the name of the test is used. :param str fullpath: complete path to use as a reference file. This option will ignore embed_data completely, being useful if a reference file is located in the session data dir for example. :param dict tolerances: dict mapping keys from the data_dict to tolerance settings for the given data. Example:: tolerances={'U': Tolerance(atol=1e-2)} :param dict default_tolerance: dict mapping the default tolerance for the current check call. Example:: default_tolerance=dict(atol=1e-7, rtol=1e-18). If not provided, will use defaults from numpy's ``isclose`` function. ``basename`` and ``fullpath`` are exclusive. """ try: import pandas as pd except ModuleNotFoundError: raise ModuleNotFoundError(import_error_message("Pandas")) import functools __tracebackhide__ = True assert type(data_frame) is pd.DataFrame, ( "Only pandas DataFrames are supported on on dataframe_regression fixture.\n" "Object with type '%s' was given." % (str(type(data_frame)),) ) for column in data_frame.columns: array = data_frame[column] # Skip assertion if an array of strings if (array.dtype == "O") and (type(array[0]) is str): continue # Rejected: timedelta, datetime, objects, zero-terminated bytes, unicode strings and raw data assert array.dtype not in ["m", "M", "O", "S", "a", "U", "V"], ( "Only numeric data is supported on dataframe_regression fixture.\n" "Array with type '%s' was given.\n" % (str(array.dtype),) ) if tolerances is None: tolerances = {} self._tolerances_dict = tolerances if default_tolerance is None: default_tolerance = {} self._default_tolerance = default_tolerance dump_fn = functools.partial(self._dump_fn, data_frame) with pd.option_context(*self._pandas_display_options): perform_regression_check( datadir=self.datadir, original_datadir=self.original_datadir, request=self.request, check_fn=self._check_fn, dump_fn=dump_fn, extension=".csv", basename=basename, fullpath=fullpath, force_regen=self._force_regen, )
def check( self, data_dict, basename=None, fullpath=None, tolerances=None, default_tolerance=None, data_index=None, fill_different_shape_with_nan=True, ): """ Checks the given dict against a previously recorded version, or generate a new file. The dict must map from user-defined keys to 1d numpy arrays. Example:: num_regression.check({ 'U_gas': U[0][positions], 'U_liquid': U[1][positions], 'gas_vol_frac [-]': vol_frac[0][positions], 'liquid_vol_frac [-]': vol_frac[1][positions], 'P': Pa_to_bar(P)[positions], }) :param dict data_dict: dict mapping keys to numpy arrays. :param str basename: basename of the file to test/record. If not given the name of the test is used. :param str fullpath: complete path to use as a reference file. This option will ignore embed_data completely, being useful if a reference file is located in the session data dir for example. :param dict tolerances: dict mapping keys from the data_dict to tolerance settings for the given data. Example:: tolerances={'U': Tolerance(atol=1e-2)} :param dict default_tolerance: dict mapping the default tolerance for the current check call. Example:: default_tolerance=dict(atol=1e-7, rtol=1e-18). If not provided, will use defaults from numpy's ``isclose`` function. :param list data_index: If set, will override the indexes shown in the outputs. Default is panda's default, which is ``range(0, len(data))``. :param bool fill_different_shape_with_nan: If set, all the data provided in the data_dict that has size lower than the bigger size will be filled with ``np.NaN``, in order to save the data in a CSV file. ``basename`` and ``fullpath`` are exclusive. """ try: import numpy as np except ModuleNotFoundError: raise ModuleNotFoundError(import_error_message("Numpy")) try: import pandas as pd except ModuleNotFoundError: raise ModuleNotFoundError(import_error_message("Pandas")) import functools __tracebackhide__ = True if tolerances is None: tolerances = {} self._tolerances_dict = tolerances if default_tolerance is None: default_tolerance = {} self._default_tolerance = default_tolerance data_shapes = [] for obj in data_dict.values(): assert type(obj) in [ np.ndarray ], "Only numpy arrays are valid for numeric_data_regression fixture.\n" shape = obj.shape assert len(shape) == 1, ( "Only 1D arrays are supported on num_data_regression fixture.\n" "Array with shape %s was given.\n" % (shape, )) data_shapes.append(shape[0]) data_shapes = np.array(data_shapes) if not np.all(data_shapes == data_shapes[0]): if not fill_different_shape_with_nan: assert ( False ), "Data dict with different array lengths will not be accepted. Try setting fill_different_shape_with_nan=True." elif len(data_dict) > 1 and not all( np.issubdtype(a.dtype, np.floating) for a in data_dict.values()): raise TypeError( "Checking multiple arrays with different shapes are not supported for non-float arrays" ) else: max_size = max(data_shapes) for k, obj in data_dict.items(): new_data = np.empty(shape=(max_size, ), dtype=obj.dtype) new_data[:len(obj)] = obj new_data[len(obj):] = np.nan data_dict[k] = new_data data_frame = pd.DataFrame(data_dict, index=data_index) dump_fn = functools.partial(self._dump_fn, data_frame) with pd.option_context(*self._pandas_display_options): perform_regression_check( datadir=self.datadir, original_datadir=self.original_datadir, request=self.request, check_fn=self._check_fn, dump_fn=dump_fn, extension=".csv", basename=basename, fullpath=fullpath, force_regen=self._force_regen, )
def check( self, data_dict, basename=None, fullpath=None, tolerances=None, default_tolerance=None, ): """ Checks a dictionary of NumPy ndarrays, containing only numeric data, against a previously recorded version, or generate a new file. Example:: def test_some_data(ndarrays_regression): points, values = some_function() ndarrays_regression.check( { 'points': points, # array with shape (100, 3) 'values': values, # array with shape (100,) }, default_tolerance=dict(atol=1e-8, rtol=1e-8) ) :param Dict[str, numpy.ndarray] data_dict: dictionary of NumPy ndarrays containing data for regression check. The arrays can have any shape. :param str basename: basename of the file to test/record. If not given the name of the test is used. :param str fullpath: complete path to use as a reference file. This option will ignore embed_data completely, being useful if a reference file is located in the session data dir for example. :param dict tolerances: dict mapping keys from the data_dict to tolerance settings for the given data. Example:: tolerances={'U': Tolerance(atol=1e-2)} :param dict default_tolerance: dict mapping the default tolerance for the current check call. Example:: default_tolerance=dict(atol=1e-7, rtol=1e-18). If not provided, will use defaults from numpy's ``isclose`` function. ``basename`` and ``fullpath`` are exclusive. """ try: import numpy as np except ModuleNotFoundError: raise ModuleNotFoundError(import_error_message("NumPy")) import functools __tracebackhide__ = True if not isinstance(data_dict, dict): raise TypeError( "Only dictionaries with NumPy arrays or array-like objects are " "supported on ndarray_regression fixture.\n" "Object with type '{}' was given.".format(str(type(data_dict))) ) for key, array in data_dict.items(): assert isinstance(key, str), ( "The dictionary keys must be strings. " "Found key with type '{}'".format(str(type(key))) ) data_dict[key] = np.asarray(array) for key, array in data_dict.items(): # Accepted: # - b: boolean # - i: signed integer # - u: unsigned integer # - f: floating-point number # - c: complex floating-point number # - U: unicode string # Rejected: # - m: timedelta # - M: datetime # - O: objects # - S: zero-terminated bytes # - V: void (raw data, structured arrays) if array.dtype.kind not in ["b", "i", "u", "f", "c", "U"]: raise TypeError( "Only numeric or unicode data is supported on ndarrays_regression " f"fixture.\nArray '{key}' with type '{array.dtype}' was given." ) if tolerances is None: tolerances = {} self._tolerances_dict = tolerances if default_tolerance is None: default_tolerance = {} self._default_tolerance = default_tolerance dump_fn = functools.partial(self._dump_fn, data_dict) perform_regression_check( datadir=self.datadir, original_datadir=self.original_datadir, request=self.request, check_fn=self._check_fn, dump_fn=dump_fn, extension=".npz", basename=basename, fullpath=fullpath, force_regen=self._force_regen, with_test_class_names=self._with_test_class_names, )