Ejemplo n.º 1
0
    def __init__(self, value):
        """Value can be of type str or dict.
        If value is str, value is expected to be of the form yyyy-mm-dd, where the yyyy, mm and dd parts can consist of
        only 0's, meaning that part is unknown.
        If value is of type dict, keys 'year', 'month' and 'day' are expected to be present (but may be null).
        Dict may also be encoded as a JSON string.

        For example:
        2021-03-22 (complete date)
        2021-03-00 (day unknown)
        2021-00-00 (month and day unknown)

        :param value:
        """
        if value is not None:
            if isinstance(value, str) and re.match(self.pattern, value):
                self.year, self.month, self.day = self.__init_from_str(value)
            else:
                if isinstance(value, str):
                    try:
                        value = json.loads(value)
                    except json.JSONDecodeError:
                        raise GOBTypeException(f"Could not decode value '{value}'")

                    assert isinstance(value, dict), "Value should be of type dict"
                self.year, self.month, self.day = self.__init_from_dict(value)

        super().__init__(json.dumps({
            'year': self.year,
            'month': self.month,
            'day': self.day,
            'formatted': self._formatted,
        }) if value is not None else value)
Ejemplo n.º 2
0
    def test_extract_field(self, mock_get_value, mock_get_gob_type_from_info,
                           mock_logger):
        row = {
            '_id': '12345',
        }
        field = 'f'
        metadata = {'source_mapping': 'any mapping'}
        typeinfo = {'type': 'any type'}
        # Implementation test of extract field
        mock_gob_type = mock.MagicMock()
        mock_get_gob_type_from_info.return_value = mock_gob_type
        result = _extract_field(row, field, metadata, typeinfo)
        self.assertEqual(result, mock_gob_type.from_value_secure.return_value)
        mock_get_value.assert_called_with(row, metadata['source_mapping'])
        mock_gob_type.from_value_secure.assert_called_with(
            mock_get_value.return_value, typeinfo)

        # Behaviour test, if GOB Type conversion fails a data error should be reported
        # And a GOB Type None value should be returned
        mock_gob_type.from_value_secure.side_effect = [
            GOBTypeException(), None
        ]
        result = _extract_field(row, field, metadata, typeinfo)
        self.assertEqual(result, None)

        # Assert error is generated
        mock_logger.error.assert_called_once()
Ejemplo n.º 3
0
 def __init__(self, value, spec=None):
     if value is not None:
         try:
             # force sort keys to have order
             value = json.dumps(json.loads(value), sort_keys=True)
             self._spec = spec
         except ValueError:
             raise GOBTypeException(f"value '{value}' cannot be interpreted as JSON")
     super().__init__(value)
Ejemplo n.º 4
0
 def __init__(self, value):
     if value == 'nan':
         value = None
     if value is not None:
         try:
             value = str(int(value))
         except ValueError:
             raise GOBTypeException(f"value '{value}' cannot be interpreted as Integer")
     super().__init__(value)
Ejemplo n.º 5
0
    def __init__(self, value):
        """Initialisation of GOBType with a string value

        :param value: the string value for internal representation
        :return: GOBType
        """
        if value is not None and not isinstance(value, str):
            raise GOBTypeException("GOBType can only be instantiated with string, "
                                   "use `GOBType.from_value(value)` instead")
        self._string = value if value is None else str(value)
Ejemplo n.º 6
0
 def __init__(self, value, **kwargs):  # noqa: C901
     if value == 'nan':
         value = None
     if value is not None:
         try:
             if 'precision' in kwargs:
                 fmt = f".{kwargs['precision']}f"
                 value = format(float(value), fmt)
             else:
                 value = str(float(value))
         except ValueError:
             raise GOBTypeException(f"value '{value}' cannot be interpreted as Decimal")
     super().__init__(value)
Ejemplo n.º 7
0
    def from_value(cls, value, **kwargs) -> GOBType:
        """
        Returns GOBType as a String containing a single character value if input has a string representation with
        len > 0, else a GOBType(None)

        :param value:
        :return: the string that holds the value in single character format or None
        """
        if value is None:
            return cls(None)
        string_value = str(value)
        if len(string_value) != 1:
            raise GOBTypeException(f"value '{string_value}' has more than one character")
        return cls(string_value[0]) if len(string_value) > 0 else cls(None)
Ejemplo n.º 8
0
    def from_value(cls, value, **kwargs):
        input_format = kwargs['format'] if 'format' in kwargs else cls.internal_format

        if value is not None:
            try:
                if not isinstance(value, datetime.datetime):
                    if isinstance(value, str) and '.%f' in input_format and len(value) == len('YYYY-MM-DDTHH:MM:SS'):
                        # Add missing microseconds if needed
                        value += '.000000'
                    value = datetime.datetime.strptime(str(value), input_format)
                # Transform to internal string format and work around issue: https://bugs.python.org/issue13305
                value = f"{value.year:04d}-" + value.strftime("%m-%dT%H:%M:%S.%f")
            except ValueError as v:
                raise GOBTypeException(v)

        return cls(str(value)) if value is not None else cls(None)
Ejemplo n.º 9
0
    def from_value(cls, value, **kwargs):
        input_format = kwargs[
            'format'] if 'format' in kwargs else cls.internal_format

        if value is not None:
            try:
                if not isinstance(value, datetime.datetime):
                    value = datetime.datetime.strptime(str(value),
                                                       input_format)
                # Transform to internal string format and work around issue: https://bugs.python.org/issue13305
                value = f"{value.year:04d}-" + value.strftime(
                    "%m-%dT%H:%M:%S.%f")
            except ValueError as v:
                raise GOBTypeException(v)

        return cls(str(value)) if value is not None else cls(None)
Ejemplo n.º 10
0
    def from_value(cls, value, **kwargs):
        """ Create a Date GOB type as a string containing a date value in ISO 8601 format:

            Date.from_value("20160504", format="%Y%m%d")

        In which `format` is the datetime formatting string of the input - usually used on import
        """
        input_format = kwargs['format'] if 'format' in kwargs else cls.internal_format

        if value is not None:
            try:
                value = datetime.datetime.strptime(str(value), input_format).date()
                # Transform to internal string format and work around issue: https://bugs.python.org/issue13305
                value = f"{value.year:04d}-" + value.strftime("%m-%d")
            except ValueError as v:
                raise GOBTypeException(v)

        return cls(str(value)) if value is not None else cls(None)
Ejemplo n.º 11
0
    def from_value(cls, value, **kwargs):
        """ Create a Decimal GOB Type from value and kwargs:

            Boolean.from_value("N", format="YN")

        Formatting might be required to enable interpretation of the value during import. And can be one of:

            - 'YN', 'Y' --> True, 'N' --> False, Other/None --> None
            - 'JN', 'J' --> True, 'N' --> False, Other/None --> None
            - '10', '1' --> True, '0' --> False, Other/None --> None
        """
        known_formats = ['YN', 'JN', '10']

        if 'format' in kwargs:
            if kwargs['format'] not in known_formats:
                raise GOBTypeException(f"Unknown boolean formatting: '{kwargs['format']}'")
            value = cls._bool_or_none(value, kwargs['format'])

        return cls(str(value)) if value is not None else cls(None)
Ejemplo n.º 12
0
    def __init_from_dict(self, value) -> Tuple[Optional[int], Optional[int], Optional[int]]:
        if not all([v in value for v in ['year', 'month', 'day']]):
            raise GOBTypeException(f"Cannot interpret value '{json.dumps(value)}' as IncompleteDate. "
                                   f"Expecting keys 'year', 'month' and 'day'.")

        return value.get('year'), value.get('month'), value.get('day')
Ejemplo n.º 13
0
 def __init__(self, value):
     if value is not None:
         if value.lower() not in ['true', 'false']:
             raise GOBTypeException("Boolean should be False, True or None")
     super().__init__(value)