Example #1
0
 def encode_as_pil(obj):
     """Attempt to convert PIL.Image.Image to base64 data uri"""
     image = get_module("PIL.Image")
     if image is not None and isinstance(obj, image.Image):
         return ImageUriValidator.pil_image_to_uri(obj)
     else:
         raise NotEncodable
Example #2
0
def test_validator_coercion_PIL(validator: ImageUriValidator):
    # Single pixel black png (http://png-pixel.com/)

    img_path = '_plotly_utils/tests/resources/1x1-black.png'
    with open(img_path, 'rb') as f:
        hex_bytes = base64.b64encode(f.read()).decode('ascii')
        expected_uri = 'data:image/png;base64,' + hex_bytes

    img = Image.open(img_path)
    coerce_val = validator.validate_coerce(img)
    assert coerce_val == expected_uri
def validator():
    return ImageUriValidator('prop', 'parent')
Example #4
0
def clean_to_json_compatible(obj, **kwargs):
    # Try handling value as a scalar value that we have a conversion for.
    # Return immediately if we know we've hit a primitive value

    # Bail out fast for simple scalar types
    if isinstance(obj, (int, float, string_types)):
        return obj

    if isinstance(obj, dict):
        return {str(k): clean_to_json_compatible(v, **kwargs) for k, v in obj.items()}
    elif isinstance(obj, (list, tuple)):
        if obj:
            # Must process list recursively even though it may be slow
            return [clean_to_json_compatible(v, **kwargs) for v in obj]

    # unpack kwargs
    numpy_allowed = kwargs.get("numpy_allowed", False)
    datetime_allowed = kwargs.get("datetime_allowed", False)

    modules = kwargs.get("modules", {})
    sage_all = modules["sage_all"]
    np = modules["np"]
    pd = modules["pd"]
    image = modules["image"]

    # Sage
    if sage_all is not None:
        if obj in sage_all.RR:
            return float(obj)
        elif obj in sage_all.ZZ:
            return int(obj)

    # numpy
    if np is not None:
        if obj is np.ma.core.masked:
            return float("nan")
        elif isinstance(obj, np.ndarray):
            if numpy_allowed and obj.dtype.kind in ("b", "i", "u", "f"):
                return np.ascontiguousarray(obj)
            elif obj.dtype.kind == "M":
                # datetime64 array
                return np.datetime_as_string(obj).tolist()
            elif obj.dtype.kind == "U":
                return obj.tolist()
            elif obj.dtype.kind == "O":
                # Treat object array as a lists, continue processing
                obj = obj.tolist()
        elif isinstance(obj, np.datetime64):
            return str(obj)

    # pandas
    if pd is not None:
        if obj is pd.NaT:
            return None
        elif isinstance(obj, (pd.Series, pd.DatetimeIndex)):
            if numpy_allowed and obj.dtype.kind in ("b", "i", "u", "f"):
                return np.ascontiguousarray(obj.values)
            elif obj.dtype.kind == "M":
                if isinstance(obj, pd.Series):
                    dt_values = obj.dt.to_pydatetime().tolist()
                else:  # DatetimeIndex
                    dt_values = obj.to_pydatetime().tolist()

                if not datetime_allowed:
                    # Note: We don't need to handle dropping timezones here because
                    # numpy's datetime64 doesn't support them and pandas's tz_localize
                    # above drops them.
                    for i in range(len(dt_values)):
                        dt_values[i] = dt_values[i].isoformat()

                return dt_values

    # datetime and date
    try:
        # Need to drop timezone for scalar datetimes. Don't need to convert
        # to string since engine can do that
        obj = obj.to_pydatetime()
    except (TypeError, AttributeError):
        pass

    if not datetime_allowed:
        try:
            return obj.isoformat()
        except (TypeError, AttributeError):
            pass
    elif isinstance(obj, datetime.datetime):
        return obj

    # Try .tolist() convertible, do not recurse inside
    try:
        return obj.tolist()
    except AttributeError:
        pass

    # Do best we can with decimal
    if isinstance(obj, decimal.Decimal):
        return float(obj)

    # PIL
    if image is not None and isinstance(obj, image.Image):
        return ImageUriValidator.pil_image_to_uri(obj)

    # Plotly
    try:
        obj = obj.to_plotly_json()
    except AttributeError:
        pass

    # Recurse into lists and dictionaries
    if isinstance(obj, dict):
        return {k: clean_to_json_compatible(v, **kwargs) for k, v in obj.items()}
    elif isinstance(obj, (list, tuple)):
        if obj:
            # Must process list recursively even though it may be slow
            return [clean_to_json_compatible(v, **kwargs) for v in obj]

    return obj
Example #5
0
def test_validator_acceptance(val, validator: ImageUriValidator):
    assert validator.validate_coerce(val) == val
Example #6
0
def validator():
    return ImageUriValidator("prop", "parent")