Skip to content

Commit 65d12f2

Browse files
committed
Handling of fields with init set to False
When a field in the dataclass is set to False it means that field won't be added to the list of arguments in the class initializer. This commit handle cases where a field has init set to False. The DataclassReader will skip these fields and won't add them to the argument list when initializing the class. Default values and default factories will be handled by the dataclass implementation.
1 parent 1ac84ed commit 65d12f2

File tree

3 files changed

+52
-6
lines changed

3 files changed

+52
-6
lines changed

dataclass_csv/dataclass_reader.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ def __init__(
3131
self.optional_fields = self._get_optional_fields()
3232
self.field_mapping = {}
3333

34+
3435
self.reader = csv.DictReader(
3536
f, fieldnames, restkey, restval, dialect, *args, **kwds
3637
)
@@ -134,6 +135,9 @@ def _process_row(self, row):
134135
values = []
135136

136137
for field in dataclasses.fields(self.cls):
138+
if not field.init:
139+
continue
140+
137141
try:
138142
value = self._get_value(row, field)
139143
except ValueError as ex:

tests/mocks.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,17 @@ class DataclassWithBooleanValue:
6565
@dataclasses.dataclass
6666
class DataclassWithBooleanValueNoneDefault:
6767
boolValue: bool = None
68+
69+
70+
@dataclasses.dataclass
71+
class UserWithInitFalse:
72+
firstname: str
73+
lastname: str
74+
age: int = dataclasses.field(init=False)
75+
76+
77+
@dataclasses.dataclass
78+
class UserWithInitFalseAndDefaultValue:
79+
firstname: str
80+
lastname: str
81+
age: int = dataclasses.field(init=False, default=0)

tests/test_dataclass_reader.py

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@
33

44
from dataclass_csv import DataclassReader, CsvValueError
55

6-
from .mocks import User, DataclassWithBooleanValue, DataclassWithBooleanValueNoneDefault
6+
from .mocks import (
7+
User,
8+
DataclassWithBooleanValue,
9+
DataclassWithBooleanValueNoneDefault,
10+
UserWithInitFalse,
11+
UserWithInitFalseAndDefaultValue,
12+
)
713

814

915
def test_reader_with_non_dataclass(create_csv):
@@ -114,19 +120,41 @@ def test_parse_bool_value_false(create_csv):
114120
def test_parse_bool_value_invalid(create_csv):
115121
csv_file = create_csv({'boolValue': 'notValidBoolean'})
116122
with csv_file.open() as f:
117-
try:
123+
with pytest.raises(CsvValueError):
118124
reader = DataclassReader(f, DataclassWithBooleanValue)
119125
list(reader)
120-
assert False # Should not be able to successfully parse
121-
except CsvValueError:
122-
pass
123126

124127

125128
def test_parse_bool_value_none_default(create_csv):
126-
"""Verify that blank/null values are parsed as None for optional fields"""
127129
csv_file = create_csv({'boolValue': ''})
128130
with csv_file.open() as f:
129131
reader = DataclassReader(f, DataclassWithBooleanValueNoneDefault)
130132
items = list(reader)
131133
dataclass_instance = items[0]
132134
assert dataclass_instance.boolValue is None
135+
136+
137+
def test_skip_dataclass_field_when_init_is_false(create_csv):
138+
csv_file = create_csv({'firstname': 'User1', 'lastname': 'TestUser'})
139+
with csv_file.open() as f:
140+
reader = DataclassReader(f, UserWithInitFalse)
141+
items = list(reader)
142+
143+
144+
def test_try_to_access_not_initialized_prop_raise_attr_error(create_csv):
145+
csv_file = create_csv({'firstname': 'User1', 'lastname': 'TestUser'})
146+
with csv_file.open() as f:
147+
reader = DataclassReader(f, UserWithInitFalse)
148+
items = list(reader)
149+
with pytest.raises(AttributeError):
150+
user = items[0]
151+
user_age = user.age
152+
153+
154+
def test_try_to_access_not_initialized_prop_with_default_value(create_csv):
155+
csv_file = create_csv({'firstname': 'User1', 'lastname': 'TestUser'})
156+
with csv_file.open() as f:
157+
reader = DataclassReader(f, UserWithInitFalseAndDefaultValue)
158+
items = list(reader)
159+
user = items[0]
160+
assert user.age == 0

0 commit comments

Comments
 (0)