Esempio n. 1
0
    def _create_iterencode(self):
        """
        Mostly an awful redefinition of json.encoder.JSONEncoder.iterencode just to "unsupport" tuples.
        Tuples then get processed by default() method.

        Used to avoid tuples get converted to lists and also adds support of namedtuples.
        """
        if self.check_circular:
            markers = {}
        else:
            markers = None
        if self.ensure_ascii:
            _encoder = encode_basestring_ascii
        else:
            _encoder = encode_basestring

        def floatstr(_o, allow_nan=self.allow_nan, _repr=float.__repr__, _inf=INFINITY, _neginf=-INFINITY):
            if _o != _o:
                text = 'NaN'
            elif _o == _inf:
                text = 'Infinity'
            elif _o == _neginf:
                text = '-Infinity'
            else:
                return _repr(_o)

            if not allow_nan:
                raise ValueError("Out of range float values are not JSON compliant: " + repr(_o))

            return text

        return _make_iterencode(
            markers, self.default, _encoder, self.indent, floatstr,
            self.key_separator, self.item_separator, self.sort_keys,
            self.skipkeys, False, tuple=type("FakeClass", (), {}))
    def iterencode(self, o, _one_shot=False):
        """Encode the given object and yield each string
        representation as available.

        For example::

            for chunk in JSONEncoder().iterencode(bigobject):
                mysocket.write(chunk)

        """
        # Hack to enforce
        c_make_encoder = None
        if self.check_circular:
            markers = {}
        else:
            markers = None
        if self.ensure_ascii:
            _encoder = encode_basestring_ascii
        else:
            _encoder = encode_basestring

        def floatstr(o,
                     allow_nan=True,
                     _repr=lambda o: format(o, '.4f'),
                     _inf=INFINITY,
                     _neginf=-INFINITY):
            # Check for specials.  Note that this type of test is processor
            # and/or platform-specific, so do tests which don't depend on the
            # internals.

            if o != o:
                text = '0'
            elif o == _inf:
                text = '1000000'  # infinity is 1000000
            elif o == _neginf:
                text = '-1000000'
            else:
                return _repr(o)

            if not allow_nan:
                raise ValueError(
                    "Out of range float values are not JSON compliant: " +
                    repr(o))

            return text

        if _one_shot and c_make_encoder is not None and self.indent is None:
            _iterencode = c_make_encoder(
                markers, self.default, _encoder, self.indent,
                self.key_separator, self.item_separator, self.sort_keys,
                self.skipkeys,
                self.allow_nan)  # TODO: fix call to non-callable object
        else:
            _iterencode = _make_iterencode(markers, self.default, _encoder,
                                           self.indent, floatstr,
                                           self.key_separator,
                                           self.item_separator, self.sort_keys,
                                           self.skipkeys, _one_shot)
        return _iterencode(o, 0)
Esempio n. 3
0
    def iterencode(self, o, _one_shot=False):
        """This is almost a copy of the base class implementation of this method

        The changes are inspired by http://stackoverflow.com/a/17684652
        The execution might be slower than that of the base class, as the `c_make_encoder` is never called. However,
        the changes allow the implementation of a custom `isinstance` method.
        """
        if self.check_circular:
            markers = {}
        else:
            markers = None
        if self.ensure_ascii:
            _encoder = encode_basestring_ascii
        else:
            _encoder = encode_basestring
        if getattr(self, 'enocing', 'utf-8') != 'utf-8':

            def _encoder(o, _orig_encoder=_encoder, _encoding=self.encoding):
                if isinstance(o, str):
                    o = o.decode(_encoding)
                return _orig_encoder(o)

        def floatstr(o,
                     allow_nan=self.allow_nan,
                     _repr=FLOAT_REPR,
                     _inf=INFINITY,
                     _neginf=-INFINITY):
            # Check for specials.  Note that this type of test is processor
            # and/or platform-specific, so do tests which don't depend on the
            # internals.

            if o != o:
                text = 'NaN'
            elif o == _inf:
                text = 'Infinity'
            elif o == _neginf:
                text = '-Infinity'
            else:
                return _repr(o)

            if not allow_nan:
                raise ValueError(
                    "Out of range float values are not JSON compliant: " +
                    repr(o))

            return text

        _iterencode = _make_iterencode(markers,
                                       self.default,
                                       _encoder,
                                       self.indent,
                                       floatstr,
                                       self.key_separator,
                                       self.item_separator,
                                       self.sort_keys,
                                       self.skipkeys,
                                       _one_shot,
                                       isinstance=self.isinstance)
        return _iterencode(o, 0)
Esempio n. 4
0
    def iterencode(self, o, _one_shot=False):
        """Encode the given object and yield each string
        representation as available.
        For example::
            for chunk in JSONEncoder().iterencode(bigobject):
                mysocket.write(chunk)
        """
        c_make_encoder_original = encoder.c_make_encoder
        encoder.c_make_encoder = None

        if self.check_circular:
            markers = {}
        else:
            markers = None
        if self.ensure_ascii:
            _encoder = encoder.encode_basestring_ascii
        else:
            _encoder = encoder.encode_basestring

        def floatstr(o,
                     allow_nan=self.allow_nan,
                     _repr=lambda x: format(x, self._formatter),
                     _inf=float("inf"),
                     _neginf=-float("inf")):
            # Check for specials.  Note that this type of test is processor
            # and/or platform-specific, so do tests which don't depend on the
            # internals.
            if o != o:
                text = 'NaN'
            elif o == _inf:
                text = 'Infinity'
            elif o == _neginf:
                text = '-Infinity'
            else:
                return _repr(o)

            if not allow_nan:
                raise ValueError(
                    "Out of range float values are not JSON compliant: " +
                    repr(o))

            return text

        if (_one_shot and encoder.c_make_encoder is not None
                and self.indent is None):
            _iterencode = encoder.c_make_encoder(markers, self.default,
                                                 _encoder, self.indent,
                                                 self.key_separator,
                                                 self.item_separator,
                                                 self.sort_keys, self.skipkeys,
                                                 self.allow_nan)
        else:
            _iterencode = encoder._make_iterencode(
                markers, self.default, _encoder, self.indent, floatstr,
                self.key_separator, self.item_separator, self.sort_keys,
                self.skipkeys, _one_shot)
        encoder.c_make_encoder = c_make_encoder_original
        return _iterencode(o, 0)
Esempio n. 5
0
    def iterencode(self, o, _one_shot=False):  # pragma: no cover
        """Encode the given object and yield each string
        representation as available.

        For example::

            for chunk in JSONEncoder().iterencode(bigobject):
                mysocket.write(chunk)

        This method is identical to json.JSONEncoder.iterencode, except that one shot is ignored.
        """
        if self.check_circular:
            markers = {}
        else:
            markers = None
        if self.ensure_ascii:
            _encoder = encode_basestring_ascii
        else:
            _encoder = encode_basestring

        def floatstr(oo,
                     allow_nan=self.allow_nan,
                     _repr=float.__repr__,
                     _inf=INFINITY,
                     _neginf=-INFINITY):
            # Check for specials.  Note that this type of test is processor
            # and/or platform-specific, so do tests which don't depend on the
            # internals.

            if oo != oo:
                text = 'NaN'
            elif oo == _inf:
                text = 'Infinity'
            elif oo == _neginf:
                text = '-Infinity'
            else:
                return _repr(oo)

            if not allow_nan:
                raise ValueError(
                    "Out of range float values are not JSON compliant: " +
                    repr(o))

            return text

        # Force using _make_iterencode with custom isinstance fn
        _iterencode = _make_iterencode(markers,
                                       self.default,
                                       _encoder,
                                       self.indent,
                                       floatstr,
                                       self.key_separator,
                                       self.item_separator,
                                       self.sort_keys,
                                       self.skipkeys,
                                       False,
                                       isinstance=self.__class__._isinstance)
        return _iterencode(o, 0)
Esempio n. 6
0
    def iterencode(self, o, _one_shot=False):
        if self.check_circular:
            markers = {}
        else:
            markers = None
        if self.ensure_ascii:
            _encoder = encode_basestring_ascii
        else:
            _encoder = encode_basestring
        if self.encoding != 'utf-8':

            def _encoder(o, _orig_encoder=_encoder, _encoding=self.encoding):
                if isinstance(o, str):
                    o = o.decode(_encoding)
                return _orig_encoder(o)

        def floatstr(o,
                     allow_nan=self.allow_nan,
                     _repr=None,
                     _inf=INFINITY,
                     _neginf=-INFINITY):
            # Check for specials.  Note that this type of test is processor
            # and/or platform-specific, so do tests which don't depend on the
            # internals.

            if o != o:
                text = 'NaN'
            elif o == _inf:
                text = 'Infinity'
            elif o == _neginf:
                text = '-Infinity'
            else:
                return format(o, '.2f')

            if not allow_nan:
                raise ValueError(
                    "Out of range float values are not JSON compliant: " +
                    repr(o))

            return text

        # if (_one_shot and c_make_encoder is not None
        #         and self.indent is None and not self.sort_keys):
        #     _iterencode = c_make_encoder(
        #         markers, self.default, _encoder, self.indent,
        #         self.key_separator, self.item_separator, self.sort_keys,
        #         self.skipkeys, self.allow_nan)
        # else:
        _iterencode = _make_iterencode(markers, self.default, _encoder,
                                       self.indent, floatstr,
                                       self.key_separator, self.item_separator,
                                       self.sort_keys, self.skipkeys,
                                       _one_shot)
        return _iterencode(o, 0)
Esempio n. 7
0
    def iterencode(self, obj, _one_shot=False):
        """Encode the given object and yield each string
        representation as available.

        For example::

            for chunk in JSONEncoder().iterencode(bigobject):
                mysocket.write(chunk)

        """
        if self.check_circular:
            markers = {}
        else:
            markers = None
        if self.ensure_ascii:
            _encoder = encode_basestring_ascii
        else:
            _encoder = encode_basestring

        def floatstr(
            obj,
            allow_nan=self.allow_nan,
            _repr=float.__repr__,
            _inf=INFINITY,
            _neginf=-INFINITY,
        ):
            # Check for specials.  Note that this type of test is processor
            # and/or platform-specific, so do tests which don't depend on the
            # internals.

            if obj != obj:  # obj is NaN
                text = "null"
            elif obj == _inf:
                text = _repr(INFINITY_VALUE)
            elif obj == _neginf:
                text = _repr(-INFINITY_VALUE)
            else:
                return _repr(obj)

            return text

        _iterencode = _make_iterencode(
            markers,
            self.default,
            _encoder,
            self.indent,
            floatstr,
            self.key_separator,
            self.item_separator,
            self.sort_keys,
            self.skipkeys,
            _one_shot,
        )
        return _iterencode(obj, 0)
Esempio n. 8
0
    def iterencode(self, o, _one_shot=False):
        if self.check_circular:
            markers = {}
        else:
            markers = None

        _iterencode = _make_iterencode(markers, self.default, max_stringify,
                                       self.indent, str, self.key_separator,
                                       self.item_separator, self.sort_keys,
                                       self.skipkeys, _one_shot)

        return _iterencode(o, 0)
Esempio n. 9
0
 def iterencode(self, o: Any, _one_shot: bool = False) -> Any:
     """Replace a stdlib method, so we encode integer-valued floats as ints."""
     return _make_iterencode(
         {},
         self.default,
         encode_basestring_ascii,
         self.indent,
         _floatstr,
         self.key_separator,
         self.item_separator,
         self.sort_keys,
         self.skipkeys,
         _one_shot,
     )(o, 0)
Esempio n. 10
0
    def iterencode(self, o, _one_shot=False):
        if self.check_circular:
            markers = {}
        else:
            markers = None
        if self.ensure_ascii:
            _encoder = encode_basestring_ascii
        else:
            _encoder = encode_basestring

        def floatstr(o,
                     allow_nan=self.allow_nan,
                     _repr=float.__repr__,
                     _inf=INFINITY,
                     _neginf=-INFINITY):
            # Check for specials.  Note that this type of test is processor
            # and/or platform-specific, so do tests which don't depend on the
            # internals.

            if o != o:
                text = 'NaN'
            elif o == _inf:
                text = 'Infinity'
            elif o == _neginf:
                text = '-Infinity'
            else:
                if self.float_digits >= 0:
                    return format(o, '.%df' % self.float_digits)
                else:
                    return '{0}'.format(o)

            if not allow_nan:
                raise ValueError(
                    "Out of range float values are not JSON compliant: " +
                    repr(o))

            return text

        if (_one_shot and c_make_encoder is not None and self.indent is None):
            _iterencode = c_make_encoder(markers, self.default, _encoder,
                                         self.indent, self.key_separator,
                                         self.item_separator, self.sort_keys,
                                         self.skipkeys, self.allow_nan)
        else:
            _iterencode = _make_iterencode(markers, self.default, _encoder,
                                           self.indent, floatstr,
                                           self.key_separator,
                                           self.item_separator, self.sort_keys,
                                           self.skipkeys, _one_shot)
        return _iterencode(o, 0)
Esempio n. 11
0
 def iterencode(self, o, _one_shot=False):
     # Rip-off from repo of CPython 3.7.1
     # https://github.com/python/cpython/blob/v3.7.1/Lib/json/encoder.py#L204-L257
     markers = None
     _encoder = json_encoder.encode_basestring_ascii
     _iterencode = json_encoder._make_iterencode(
         markers,
         self.default,
         _encoder,
         self.indent,
         numberstr,
         self.key_separator,
         self.item_separator,
         self.sort_keys,
         self.skipkeys,
         _one_shot,
         _intstr=numberstr,
     )
     return _iterencode(o, 0)
Esempio n. 12
0
 def iterencode(self, o, _one_shot=False):
     # Rip-off from repo of CPython 3.7.1
     # https://github.com/python/cpython/blob/v3.7.1/Lib/json/encoder.py#L204-L257
     markers = None
     _encoder = json_encoder.encode_basestring_ascii
     _iterencode = json_encoder._make_iterencode(
         markers,
         self.default,
         _encoder,
         self.indent,
         numberstr,
         self.key_separator,
         self.item_separator,
         self.sort_keys,
         self.skipkeys,
         _one_shot,
         _intstr=numberstr,
     )
     return _iterencode(o, 0)
Esempio n. 13
0
File: io.py Progetto: gwk/pithy
  def iterencode(self, o, _one_shot=False):
    '''
    Derived from Python/Lib/json/encoder.py.
    Custom iterencode always avoids using c_make_encoder,
    and passes hacked isinstance to _make_iterencode.'
    '''
    if self.check_circular:
      markers = {}
    else:
      markers = None
    if self.ensure_ascii:
      _encoder = _json_enc.encode_basestring_ascii
    else:
      _encoder = _json_enc.encode_basestring

    def floatstr(o, allow_nan=self.allow_nan,
      _repr=float.__repr__, _inf=_json_enc.INFINITY, _neginf=-_json_enc.INFINITY):
      if o != o:
        text = 'NaN'
      elif o == _inf:
        text = 'Infinity'
      elif o == _neginf:
        text = '-Infinity'
      else:
        return _repr(o)
      if not allow_nan:
        raise ValueError(
          "Out of range float values are not JSON compliant: " +
          repr(o))
      return text

    def isinstance_hacked(obj, type):
      'Prevent namedtuple types from being recognized as tuples, so that default is invoked.'
      return isinstance(obj, type) and not hasattr(obj, '_asdict')

    _iterencode = _json_enc._make_iterencode(
      markers, self.default, _encoder, self.indent, floatstr,
      self.key_separator, self.item_separator, self.sort_keys,
      self.skipkeys, _one_shot, isinstance=isinstance_hacked)
    return _iterencode(o, 0)
Esempio n. 14
0
    def iterencode(self, o: Any, _one_shot: bool = False) -> Any:
        """Replace a stdlib method, so we encode integer-valued floats as ints."""
        def floatstr(o: float) -> str:
            # This is the bit we're overriding - integer-valued floats are
            # encoded as integers, to support JSONschemas's uniqueness.
            assert math.isfinite(o)
            if o == int(o):
                return repr(int(o))
            return repr(o)

        return _make_iterencode(
            {},
            self.default,
            encode_basestring_ascii,
            self.indent,
            floatstr,
            self.key_separator,
            self.item_separator,
            self.sort_keys,
            self.skipkeys,
            _one_shot,
        )(o, 0)
Esempio n. 15
0
    def iterencode(self, o, _one_shot=False):
        """Encode the given object and yield each string
        representation as available.
        For example::
            for chunk in JSONEncoder().iterencode(bigobject):
                mysocket.write(chunk)
        """
        if self.check_circular:
            markers = {}
        else:
            markers = None
        if self.ensure_ascii:
            _encoder = encode_basestring_ascii
        else:
            _encoder = encode_basestring

        def floatstr(
            o, _repr=float.__repr__, _inf=INFINITY, _neginf=-INFINITY,
        ):
            if o != o or o == _inf or o == _neginf:
                return "null"
            else:
                return _repr(o)

        _iterencode = _make_iterencode(
            markers,
            self.default,
            _encoder,
            self.indent,
            floatstr,
            self.key_separator,
            self.item_separator,
            self.sort_keys,
            self.skipkeys,
            _one_shot,
        )
        return _iterencode(o, 0)
    def iterencode(self, o, _one_shot=False):
        def floatstr(o, **kwargs):  # pylint: disable=unused-argument
            if o != o:
                return '"NaN"'
            elif o == INFINITY:
                return '"Infinity"'
            elif o == -INFINITY:
                return '"-Infinity"'

            return "{:.5g}".format(o)

        _iterencode = _make_iterencode(
            {},
            self.default,
            encode_basestring_ascii,
            None,  # indent,
            floatstr,
            ":",  # key_separator,
            ",",  # item_separator,
            False,  #  sort_keys,
            False,  #  skipkeys,
            _one_shot,
        )
        return _iterencode(o, 0)
Esempio n. 17
0
    def iterencode(self, o, _one_shot=False):
        """Custom implementation of iterencode that is almost identical to the
        built-in JSONEncoder.iterencode implementation but changes the way
        structs are serialized.

        By default JSONEncoder would serialize a namedtuple-like instance into
        a list, but it should be serialized into a dictionary. In order to do
        this, the isinstance function passed to _make_iterencode is changed to
        always return False for namedtuple-like instances, so that they can be
        handled using a self.default method.

        This implementation is not using c_make_encoder because it does not
        provide a way to customize struct serialization.
        """
        if self.check_circular:
            markers = {}
        else:
            markers = None
        if self.ensure_ascii:
            _encoder = encode_basestring_ascii
        else:
            _encoder = encode_basestring

        def floatstr(
            o,
            allow_nan=self.allow_nan,
            _repr=float.__repr__,
            _inf=INFINITY,
            _neginf=-INFINITY,
        ):
            # Check for specials.  Note that this type of test is processor
            # and/or platform-specific, so do tests which don't depend on the
            # internals.

            if o != o:
                text = "NaN"
            elif o == _inf:
                text = "Infinity"
            elif o == _neginf:
                text = "-Infinity"
            else:
                return _repr(o)

            if not allow_nan:
                raise ValueError(
                    "Out of range float values are not JSON compliant: " + repr(o)
                )

            return text

        _iterencode = _make_iterencode(
            markers,
            self.default,
            _encoder,
            self.indent,
            floatstr,
            self.key_separator,
            self.item_separator,
            self.sort_keys,
            self.skipkeys,
            _one_shot,
            isinstance=self.isinstance,
        )
        return _iterencode(o, 0)
Esempio n. 18
0
    def iterencode(self, o, _one_shot=False):
        """Encode the given object and yield each string
        representation as available.

        For example::

            for chunk in JSONEncoder().iterencode(bigobject):
                mysocket.write(chunk)

        """
        if self.check_circular:
            markers = {}
        else:
            markers = None

        _encoder = self.make_safe_string

        def floatstr(
            o,
            allow_nan=self.allow_nan,
            _repr=float.__repr__,
            _inf=INFINITY,
            _neginf=-INFINITY,
        ):
            # Check for specials.  Note that this type of test is processor
            # and/or platform-specific, so do tests which don't depend on the
            # internals.

            if o != o:
                text = "NaN"
            elif o == _inf:
                text = "Infinity"
            elif o == _neginf:
                text = "-Infinity"
            else:
                return _repr(o)

            if not allow_nan:
                raise ValueError(
                    "Out of range float values are not JSON compliant: " +
                    repr(o))

            return text

        if _one_shot and c_make_encoder is not None and self.indent is None:
            _iterencode = c_make_encoder(
                markers,
                self.default,
                _encoder,
                self.indent,
                self.key_separator,
                self.item_separator,
                self.sort_keys,
                self.skipkeys,
                self.allow_nan,
            )
        else:
            _iterencode = _make_iterencode(
                markers,
                self.default,
                _encoder,
                self.indent,
                floatstr,
                self.key_separator,
                self.item_separator,
                self.sort_keys,
                self.skipkeys,
                _one_shot,
            )
        return _iterencode(o, 0)
Esempio n. 19
0
    def iterencode(self, o, _one_shot=False):
        """Custom implementation of iterencode that is almost identical to the
        built-in JSONEncoder.iterencode implementation but changes the way
        structs are serialized.

        By default JSONEncoder would serialize a namedtuple-like instance into
        a list, but it should be serialized into a dictionary. In order to do
        this, the isinstance function passed to _make_iterencode is changed to
        always return False for namedtuple-like instances, so that they can be
        handled using a self.default method.

        This implementation is not using c_make_encoder because it does not
        provide a way to customize struct serialization.
        """
        if self.check_circular:
            markers = {}
        else:
            markers = None
        if self.ensure_ascii:
            _encoder = encode_basestring_ascii
        else:
            _encoder = encode_basestring

        def floatstr(
            o,
            allow_nan=self.allow_nan,
            _repr=float.__repr__,
            _inf=INFINITY,
            _neginf=-INFINITY,
        ):
            # Check for specials.  Note that this type of test is processor
            # and/or platform-specific, so do tests which don't depend on the
            # internals.

            if o != o:
                text = "NaN"
            elif o == _inf:
                text = "Infinity"
            elif o == _neginf:
                text = "-Infinity"
            else:
                return _repr(o)

            if not allow_nan:
                raise ValueError(
                    "Out of range float values are not JSON compliant: " +
                    repr(o))

            return text

        _iterencode = _make_iterencode(
            markers,
            self.default,
            _encoder,
            self.indent,
            floatstr,
            self.key_separator,
            self.item_separator,
            self.sort_keys,
            self.skipkeys,
            _one_shot,
            isinstance=self.isinstance,
        )
        return _iterencode(o, 0)