Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BaseGELFHandler._sanitize_to_unicode and NamedTuple #141

Open
gjdanis opened this issue Nov 30, 2022 · 0 comments
Open

BaseGELFHandler._sanitize_to_unicode and NamedTuple #141

gjdanis opened this issue Nov 30, 2022 · 0 comments

Comments

@gjdanis
Copy link

gjdanis commented Nov 30, 2022

It looks like there might be an issue with the implementation of _sanitize_to_unicode for handling NamedTuple:

Python 3.8.10 (default, Feb 10 2022, 14:12:17)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from graypy.handler import BaseGELFHandler
>>> from typing import NamedTuple
>>> class Test(NamedTuple):
...     a: int
...     b: str
...
>>> t = Test(a=1, b="test")
>>> print(BaseGELFHandler._sanitize_to_unicode(t))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "python3.8/site-packages/graypy/handler.py", line 352, in _sanitize_to_unicode
    return obj.__class__([cls._sanitize_to_unicode(i) for i in obj])
TypeError: __new__() missing 1 required positional argument: 'b'

Checking if something is a NamedTuple isn't super straightforward but can be done like this.

The _asdict() function can then be used to reuse _sanitize_to_unicode with the object as a dictionary.

Here's an example of how this might be handled:

from typing import NamedTuple

data = bytes

def isinstance_namedtuple(obj) -> bool:
    return (
        isinstance(obj, tuple) and
        hasattr(obj, '_asdict') and
        hasattr(obj, '_fields')
    )


def _sanitize_to_unicode(obj):
    if isinstance(obj, dict):
        return dict(
            (_sanitize_to_unicode(k), _sanitize_to_unicode(v))
            for k, v in obj.items()
        )

    ## NEW CODE BEGIN
    if isinstance_namedtuple(obj):
        return _sanitize_to_unicode(obj._asdict())
    ## NEW CODE END

    if isinstance(obj, (list, tuple)):
        return obj.__class__([_sanitize_to_unicode(i) for i in obj])
    if isinstance(obj, data):
        obj = obj.decode("utf-8", errors="replace")
    return obj


class Test(NamedTuple):
    a: int
    b: str

t = Test(a=1, b="test")
print(_sanitize_to_unicode(t))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant