Skip to content

Python Client has very unexpected behavior, cannot use any value that evaludates to False #12485

@tsturzl

Description

@tsturzl

Describe the bug
Python client does very bad things with values 0, False, and empty strings. Basically any value that evaluates to False cannot be used as the value for a Field, nor can it be used as the default for the field (which has even more bizarre behavior). So anything where not val evaluates to False is not a possible value that can be used, which means zero and empty strings don't exist. The reason for this is pretty obvious, if you look at this line it should probably just be if val != None, or perhaps you want certain things like an empty list to evaluate to None? Either way this seems to cause a lot of issues, and I cannot imagine this is the intended behavior because you're now expecting the user to assume any false-y value is going to be None. Booleans actually seem to work because default() will return False instead of None, which is kind of odd since now you can never have a Boolean with the value None.

To Reproduce
Simply use the Python client and assign a zero value or empty string/dict/list.

>>> from pulsar.schema import *
>>> class MyRecord(Record):
...     a = Integer()
...     b = Boolean()
...     c = String()
... 
>>> r = MyRecord(a=0, b=None, c="")
>>> print(r)
{'_required_default': False, '_default': None, '_required': False, 'a': None, 'b': False, 'c': None}
>>> print(r.a)
None
>>> print(r.b)  # this was explicitly set to None but still comes back False instead of None
False
>>> print(r.c)
None

Also setting default to zero for an Integer results in this:

>>> a = Integer(default=0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/tsturzl/.local/lib/python3.8/site-packages/pulsar/schema/definition.py", line 184, in __init__
    default = self.validate_type('default', default)
  File "/home/tsturzl/.local/lib/python3.8/site-packages/pulsar/schema/definition.py", line 198, in validate_type
    if not val and not self._required:
AttributeError: 'Integer' object has no attribute '_required'

Expected behavior
Numeric types should be allowed to be set to 0. Booleans should allow None. Empty strings should also just be set as such instead of defaulted to None. The validation should not do simple not val evaluations on values. This is very very silly, and I cannot believe this bug has never been caught.

Screenshots
N/A

Desktop (please complete the following information):
N/A

Additional context
I'm happy to contribute a PR to fix this.

Metadata

Metadata

Assignees

Labels

type/bugThe PR fixed a bug or issue reported a bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions