Exemplo n.º 1
0
def test__get_attribute_csv_data(request, instance_postgresql, delimiter,
                                 wrap_all_strings, wrapper_character,
                                 hybrid_value, expected_result):
    target = instance_postgresql[0][0]

    target.hybrid = hybrid_value

    attributes = [
        x for x in get_attribute_names(target,
                                       include_callable=False,
                                       include_nested=False,
                                       include_private=True,
                                       include_utilities=False)
        if x[0:2] != '__'
    ]

    result = target._get_attribute_csv_data(
        attributes,
        is_dumping=True,
        delimiter=delimiter,
        wrap_all_strings=wrap_all_strings,
        wrapper_character=wrapper_character)

    print(result)
    assert result == expected_result
Exemplo n.º 2
0
def test__get_attribute_csv_header(request, instance_postgresql, delimiter,
                                   expected_result):
    target = instance_postgresql[0][0]
    attributes = [
        x for x in get_attribute_names(target,
                                       include_callable=False,
                                       include_nested=False,
                                       include_private=True,
                                       include_utilities=False)
        if x[0:2] != '__'
    ]

    if delimiter is not None:
        result = target._get_attribute_csv_header(attributes,
                                                  delimiter=delimiter)
    else:
        result = target._get_attribute_csv_header(attributes)

    print(result)

    assert result == expected_result
Exemplo n.º 3
0
def test_get_attribute_names(model_complex_postgresql, instance_postgresql,
                             use_instance, include_callable, include_nested,
                             include_private, include_special,
                             include_utilities, expected_result):
    if use_instance:
        target = instance_postgresql[0][0]
    else:
        target = model_complex_postgresql[0]

    result = get_attribute_names(target,
                                 include_callable=include_callable,
                                 include_nested=include_nested,
                                 include_private=include_private,
                                 include_utilities=include_utilities)

    print(result)
    if sqlalchemy.__version__[2] == '9' and isinstance(expected_result, tuple):
        expected_result = expected_result[0]
    elif isinstance(expected_result, tuple):
        expected_result = expected_result[1]

    assert len(result) == expected_result
Exemplo n.º 4
0
    def dump_to_csv(self,
                    include_header=False,
                    delimiter='|',
                    wrap_all_strings=False,
                    null_text='None',
                    wrapper_character="'",
                    double_wrapper_character_when_nested=False,
                    escape_character="\\",
                    line_terminator='\r\n',
                    config_set=None):
        r"""Retrieve a :term:`CSV <Comma-Separated Value (CSV)>` representation of
        the object, *with all attributes* serialized regardless of configuration.

        .. caution::

          Nested objects (such as :term:`relationships <relationship>` or
          :term:`association proxies <association proxy>`) will **not**
          be serialized.

        .. note::

          This method ignores any ``display_name`` contributed on the
          :class:`AttributeConfiguration`.

        :param include_header: If ``True``, will include a header row with column
          labels. If ``False``, will not include a header row. Defaults to ``True``.
        :type include_header: :class:`bool <python:bool>`

        :param delimiter: The delimiter used between columns. Defaults to ``|``.
        :type delimiter: :class:`str <python:str>`

        :param wrap_all_strings: If ``True``, wraps any string data in the
          ``wrapper_character``. If ``None``, only wraps string data if it contains
          the ``delimiter``. Defaults to ``False``.
        :type wrap_all_strings: :class:`bool <python:bool>`

        :param null_text: The text value to use in place of empty values. Only
          applies if ``wrap_empty_values`` is ``True``. Defaults to ``'None'``.
        :type null_text: :class:`str <python:str>`

        :param wrapper_character: The string used to wrap string values when
          wrapping is necessary. Defaults to ``'``.
        :type wrapper_character: :class:`str <python:str>`

        :param double_wrapper_character_when_nested: If ``True``, will double the
          ``wrapper_character`` when it is found inside a column value. If ``False``,
          will precede the ``wrapper_character`` by the ``escape_character`` when
          it is found inside a column value. Defaults to ``False``.
        :type double_wrapper_character_when_nested: :class:`bool <python:bool>`

        :param escape_character: The character to use when escaping nested wrapper
          characters. Defaults to ``\``.
        :type escape_character: :class:`str <python:str>`

        :param line_terminator: The character used to mark the end of a line.
          Defaults to ``\r\n``.
        :type line_terminator: :class:`str <python:str>`

        :param config_set: If not :obj:`None <python:None>`, the named configuration set
          to use. Defaults to :obj:`None <python:None>`.
        :type config_set: :class:`str <python:str>` / :obj:`None <python:None>`

        :returns: Data from the object in CSV format ending in a newline (``\n``).
        :rtype: :class:`str <python:str>`
        """
        # pylint: disable=line-too-long

        attributes = [
            x for x in get_attribute_names(self,
                                           include_callable=False,
                                           include_nested=False,
                                           include_private=True,
                                           include_special=False,
                                           include_utilities=False)
            if x[0:2] != '__'
        ]

        if include_header:
            return self._get_attribute_csv_header(attributes,
                                                  delimiter = delimiter) + \
                   self._get_attribute_csv_data(attributes,
                                                is_dumping = True,
                                                delimiter = delimiter,
                                                wrap_all_strings = wrap_all_strings,
                                                null_text = null_text,
                                                wrapper_character = wrapper_character,
                                                double_wrapper_character_when_nested = double_wrapper_character_when_nested,
                                                escape_character = escape_character,
                                                line_terminator = line_terminator,
                                                config_set = config_set)

        return self._get_attribute_csv_data(
            attributes,
            is_dumping=True,
            delimiter=delimiter,
            wrap_all_strings=wrap_all_strings,
            null_text=null_text,
            wrapper_character=wrapper_character,
            double_wrapper_character_when_nested=
            double_wrapper_character_when_nested,
            escape_character=escape_character,
            line_terminator=line_terminator,
            config_set=config_set)
Exemplo n.º 5
0
    def _to_dict(self,
                 format,
                 max_nesting=0,
                 current_nesting=0,
                 is_dumping=False,
                 config_set=None):
        """Return a :class:`dict <python:dict>` representation of the object.

        .. warning::

          This method is an **intermediate** step that is used to produce the
          contents for certain public JSON, YAML, and :class:`dict <python:dict>`
          serialization methods. It should not be called directly.

        :param format: The format to which the :class:`dict <python:dict>` will
          ultimately be serialized. Accepts: ``'csv'``, ``'json'``, ``'yaml'``, and
          ``'dict'``.
        :type format: :class:`str <python:str>`

        :param max_nesting: The maximum number of levels that the resulting
          :class:`dict <python:dict>` object can be nested. If set to ``0``, will
          not nest other serializable objects. Defaults to ``0``.
        :type max_nesting: :class:`int <python:int>`

        :param current_nesting: The current nesting level at which the
          :class:`dict <python:dict>` representation will reside. Defaults to ``0``.
        :type current_nesting: :class:`int <python:int>`

        :param is_dumping: If ``True``, retrieves all attributes except callables,
          utilities, and specials (``__<name>``). If ``False``, only retrieves
          those that have JSON serialization enabled. Defaults to ``False``.
        :type is_dumping: :class:`bool <python:bool>`

        :param config_set: If not :obj:`None <python:None>`, the named configuration set
          to use when processing the input. Defaults to :obj:`None <python:None>`.
        :type config_set: :class:`str <python:str>` / :obj:`None <python:None>`

        :returns: A :class:`dict <python:dict>` representation of the object.
        :rtype: :class:`dict <python:dict>`

        :raises InvalidFormatError: if ``format`` is not recognized
        :raises SerializableAttributeError: if attributes is empty
        :raises UnsupportedSerializationError: if unable to serialize a value
        :raises MaximumNestingExceededError: if ``current_nesting`` is greater
          than ``max_nesting``
        :raises MaximumNestingExceededWarning: if an attribute requires nesting
          beyond ``max_nesting``
        """
        # pylint: disable=too-many-branches

        next_nesting = current_nesting + 1

        if format not in ['csv', 'json', 'yaml', 'dict']:
            raise InvalidFormatError("format '%s' not supported" % format)

        if current_nesting > max_nesting:
            raise MaximumNestingExceededError(
                'current nesting level (%s) exceeds maximum %s' %
                (current_nesting, max_nesting))

        dict_object = dict_()

        if format == 'csv':
            attribute_getter = self.get_csv_serialization_config
        elif format == 'json':
            attribute_getter = self.get_json_serialization_config
        elif format == 'yaml':
            attribute_getter = self.get_yaml_serialization_config
        elif format == 'dict':
            attribute_getter = self.get_dict_serialization_config

        if not is_dumping:
            attributes = [
                x for x in attribute_getter(
                    deserialize=None, serialize=True, config_set=config_set)
                if hasattr(self, x.name)
            ]
        else:
            attribute_names = [
                x for x in get_attribute_names(self,
                                               include_callable=False,
                                               include_nested=False,
                                               include_private=True,
                                               include_special=False,
                                               include_utilities=False)
            ]
            attributes = []
            for item in attribute_names:
                attribute_config = self.get_attribute_serialization_config(
                    item, config_set=config_set)
                if attribute_config is not None:
                    on_serialize_function = attribute_config.on_serialize.get(
                        format, None)
                else:
                    on_serialize_function = None

                attribute = AttributeConfiguration(
                    name=item,
                    supports_json=True,
                    supports_yaml=True,
                    supports_dict=True,
                    on_serialize=on_serialize_function)
                attributes.append(attribute)

        if not attributes:
            raise SerializableAttributeError(
                "'%s' has no '%s' serializable attributes" %
                (type(self.__class__), format))

        for attribute in attributes:
            item = getattr(self, attribute.name, None)
            if hasattr(item, '_to_dict'):
                try:
                    value = item._to_dict(
                        format,  # pylint: disable=protected-access
                        max_nesting=max_nesting,
                        current_nesting=next_nesting,
                        is_dumping=is_dumping,
                        config_set=config_set)
                except MaximumNestingExceededError:
                    warnings.warn(
                        "skipping key '%s' because maximum nesting has been exceeded" \
                            % attribute.name,
                        MaximumNestingExceededWarning
                    )
                    continue
            else:
                if attribute.on_serialize[format]:
                    on_serialize_function = attribute.on_serialize[format]
                    item = on_serialize_function(item)

                if checkers.is_iterable(item,
                                        forbid_literals=(str, bytes, dict)):
                    try:
                        value = iterable__to_dict(item,
                                                  format,
                                                  max_nesting=max_nesting,
                                                  current_nesting=next_nesting,
                                                  is_dumping=is_dumping,
                                                  config_set=config_set)
                    except MaximumNestingExceededError:
                        warnings.warn(
                            "skipping key '%s' because maximum nesting has been exceeded" \
                                % attribute.name,
                            MaximumNestingExceededWarning
                        )
                        continue
                    except NotAnIterableError:
                        try:
                            value = self._get_serialized_value(
                                format, attribute.name, config_set=config_set)
                        except UnsupportedSerializationError as error:
                            if is_dumping:
                                value = getattr(self, attribute.name)
                            else:
                                raise error
                else:
                    try:
                        value = self._get_serialized_value(
                            format, attribute.name, config_set=config_set)
                    except UnsupportedSerializationError as error:
                        if is_dumping:
                            value = getattr(self, attribute.name)
                        else:
                            raise error

            serialized_key = attribute.display_name or attribute.name

            dict_object[str(serialized_key)] = value

        return dict_object