When debugging tests execution of swh-graph, I stumbled across that error:
graph_client = <RemoteGraphClient url=http://127.0.0.1:54177/graph/> def test_stats(graph_client): > stats = graph_client.stats() swh/graph/tests/test_api_client.py:2: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ swh/graph/client.py:36: in stats return self.get('stats') ../swh-core/swh/core/api/__init__.py:220: in get return self._decode_response(response) ../swh-core/swh/core/api/__init__.py:246: in _decode_response return decode_response(response) ../swh-core/swh/core/api/serializers.py:31: in decode_response r = response.json(cls=SWHJSONDecoder) /usr/lib/python3/dist-packages/requests/models.py:889: in json self.content.decode(encoding), **kwargs _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ s = '{"counts":{"nodes":21,"edges":23},"ratios":{"compression":1.578,"bits_per_node":9.524,"bits_per_edge":8.696,"avg_loca...":3.696},"indegree":{"min":0,"max":3,"avg":1.0952380952380953},"outdegree":{"min":0,"max":3,"avg":1.0952380952380953}}', encoding = None cls = <class 'swh.core.api.serializers.SWHJSONDecoder'>, object_hook = None, parse_float = None, parse_int = None, parse_constant = None, object_pairs_hook = None, use_decimal = False, kw = {} def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, use_decimal=False, **kw): """Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a JSON document) to a Python object. *encoding* determines the encoding used to interpret any :class:`str` objects decoded by this instance (``'utf-8'`` by default). It has no effect when decoding :class:`unicode` objects. Note that currently only encodings that are a superset of ASCII work, strings of other encodings should be passed in as :class:`unicode`. *object_hook*, if specified, will be called with the result of every JSON object decoded and its return value will be used in place of the given :class:`dict`. This can be used to provide custom deserializations (e.g. to support JSON-RPC class hinting). *object_pairs_hook* is an optional function that will be called with the result of any object literal decode with an ordered list of pairs. The return value of *object_pairs_hook* will be used instead of the :class:`dict`. This feature can be used to implement custom decoders that rely on the order that the key and value pairs are decoded (for example, :func:`collections.OrderedDict` will remember the order of insertion). If *object_hook* is also defined, the *object_pairs_hook* takes priority. *parse_float*, if specified, will be called with the string of every JSON float to be decoded. By default, this is equivalent to ``float(num_str)``. This can be used to use another datatype or parser for JSON floats (e.g. :class:`decimal.Decimal`). *parse_int*, if specified, will be called with the string of every JSON int to be decoded. By default, this is equivalent to ``int(num_str)``. This can be used to use another datatype or parser for JSON integers (e.g. :class:`float`). *parse_constant*, if specified, will be called with one of the following strings: ``'-Infinity'``, ``'Infinity'``, ``'NaN'``. This can be used to raise an exception if invalid JSON numbers are encountered. If *use_decimal* is true (default: ``False``) then it implies parse_float=decimal.Decimal for parity with ``dump``. To use a custom ``JSONDecoder`` subclass, specify it with the ``cls`` kwarg. NOTE: You should use *object_hook* or *object_pairs_hook* instead of subclassing whenever possible. """ if (cls is None and encoding is None and object_hook is None and parse_int is None and parse_float is None and parse_constant is None and object_pairs_hook is None and not use_decimal and not kw): return _default_decoder.decode(s) if cls is None: cls = JSONDecoder if object_hook is not None: kw['object_hook'] = object_hook if object_pairs_hook is not None: kw['object_pairs_hook'] = object_pairs_hook if parse_float is not None: kw['parse_float'] = parse_float if parse_int is not None: kw['parse_int'] = parse_int if parse_constant is not None: kw['parse_constant'] = parse_constant if use_decimal: if parse_float is not None: raise TypeError("use_decimal=True implies parse_float=Decimal") kw['parse_float'] = Decimal > return cls(encoding=encoding, **kw).decode(s) E TypeError: __init__() got an unexpected keyword argument 'encoding' /usr/lib/python3/dist-packages/simplejson/__init__.py:535: TypeError
Indeed, when the simplejson module is present in the Phython environment (this is a pgadmin4 dependency for instance),
requests will use it to decode json but a call to response.json(cls=...) will raise an exception as the arguments
accepted by JSONDecoder are inconsistent between the standard library json and simplejson.
See https://github.com/psf/requests/issues/4842 for more details.
So ensure to use standard json module for decoding response texts and thus avoid possible errors when the
simplejson module is present in the Python environment.