Skip to content

Commit a6eedf7

Browse files
friendtocephalopodsjinhyukchang
authored andcommitted
Use attrs + marshmallow-annotations (#64)
Use attrs to generate python classes and marshmallow-annotations to generate schemas.
1 parent 9914c8b commit a6eedf7

File tree

6 files changed

+194
-211
lines changed

6 files changed

+194
-211
lines changed
Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
11
from typing import Optional
22

3+
import attr
4+
from marshmallow_annotations.ext.attrs import AttrsSchema
35

6+
7+
@attr.s(auto_attribs=True, kw_only=True)
48
class PopularTable:
9+
database: str = attr.ib()
10+
cluster: str = attr.ib()
11+
schema: str = attr.ib()
12+
name: str = attr.ib()
13+
description: Optional[str] = None
514

6-
def __init__(self, *,
7-
database: str,
8-
cluster: str,
9-
schema: str,
10-
name: str,
11-
description: Optional[str] = None) -> None:
12-
self.database = database
13-
self.cluster = cluster
14-
self.schema = schema
15-
self.name = name
16-
self.description = description
1715

18-
def __repr__(self) -> str:
19-
return """Table(database={!r}, cluster={!r}, schema={!r}, name={!r}, description={!r})"""\
20-
.format(self.database, self.cluster,
21-
self.schema, self.name, self.description)
16+
class PopularTableSchema(AttrsSchema):
17+
class Meta:
18+
target = PopularTable
19+
register_as_scheme = True
Lines changed: 144 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -1,175 +1,176 @@
1-
from typing import Iterable, Optional
1+
from typing import List, Optional
22

3+
import attr
4+
from marshmallow_annotations.ext.attrs import AttrsSchema
35

6+
7+
@attr.s(auto_attribs=True, kw_only=True)
48
class User:
5-
def __init__(self, *,
6-
email: str,
7-
first_name: str =None,
8-
last_name: str =None) -> None:
9-
self.email = email
10-
self.first_name = first_name
11-
self.last_name = last_name
9+
email: str = attr.ib()
10+
first_name: Optional[str] = None
11+
last_name: Optional[str] = None
12+
1213

13-
def __repr__(self) -> str:
14-
return 'User(email={!r}, first_name={!r}, last_name={!r})'.format(self.email, self.first_name, self.last_name)
14+
class UserSchema(AttrsSchema):
15+
class Meta:
16+
target = User
17+
register_as_scheme = True
1518

1619

20+
@attr.s(auto_attribs=True, kw_only=True)
1721
class Reader:
18-
def __init__(self, *,
19-
user: User,
20-
read_count: int) -> None:
21-
self.user = user
22-
self.read_count = read_count
22+
user: User = attr.ib()
23+
read_count: int = attr.ib()
2324

24-
def __repr__(self) -> str:
25-
return 'Reader(user={!r}, read_count={!r})'.format(self.user, self.read_count)
2625

26+
class ReaderSchema(AttrsSchema):
27+
class Meta:
28+
target = Reader
29+
register_as_scheme = True
2730

31+
32+
@attr.s(auto_attribs=True, kw_only=True)
2833
class Tag:
29-
def __init__(self, *,
30-
tag_type: str,
31-
tag_name: str) -> None:
32-
self.tag_name = tag_name
33-
self.tag_type = tag_type
34+
tag_type: str = attr.ib()
35+
tag_name: str = attr.ib()
36+
3437

35-
def __repr__(self) -> str:
36-
return 'Tag(tag_name={!r}, tag_type={!r})'.format(self.tag_name,
37-
self.tag_type)
38+
class TagSchema(AttrsSchema):
39+
class Meta:
40+
target = Tag
41+
register_as_scheme = True
3842

3943

44+
@attr.s(auto_attribs=True, kw_only=True)
4045
class Watermark:
41-
def __init__(self, *,
42-
watermark_type: str =None,
43-
partition_key: str =None,
44-
partition_value: str =None,
45-
create_time: str =None) -> None:
46-
self.watermark_type = watermark_type
47-
self.partition_key = partition_key
48-
self.partition_value = partition_value
49-
self.create_time = create_time
50-
51-
def __repr__(self) -> str:
52-
return 'Watermark(watermark_type={!r}, ' \
53-
'partition_key={!r}, ' \
54-
'partition_value={!r}, ' \
55-
'create_time={!r}))'.format(self.watermark_type,
56-
self.partition_key,
57-
self.partition_value,
58-
self.create_time)
46+
watermark_type: Optional[str] = None
47+
partition_key: Optional[str] = None
48+
partition_value: Optional[str] = None
49+
create_time: Optional[str] = None
5950

6051

52+
class WatermarkSchema(AttrsSchema):
53+
class Meta:
54+
target = Watermark
55+
register_as_scheme = True
56+
57+
58+
@attr.s(auto_attribs=True, kw_only=True)
6159
class Statistics:
62-
def __init__(self, *,
63-
stat_type: str,
64-
stat_val: str =None,
65-
start_epoch: int =None,
66-
end_epoch: int =None) -> None:
67-
self.stat_type = stat_type
68-
self.stat_val = stat_val
69-
self.start_epoch = start_epoch
70-
self.end_epoch = end_epoch
71-
72-
def __repr__(self) -> str:
73-
return 'Statistics(stat_type={!r}, ' \
74-
'stat_val={!r},' \
75-
'start_epoch={!r},' \
76-
'end_epoch={!r})'.format(self.stat_type,
77-
self.stat_val,
78-
self.start_epoch,
79-
self.end_epoch)
60+
stat_type: str = attr.ib()
61+
stat_val: Optional[str] = None
62+
start_epoch: Optional[int] = None
63+
end_epoch: Optional[int] = None
64+
8065

66+
class StatisticsSchema(AttrsSchema):
67+
class Meta:
68+
target = Statistics
69+
register_as_scheme = True
8170

71+
72+
@attr.s(auto_attribs=True, kw_only=True)
8273
class Column:
83-
def __init__(self, *,
84-
name: str,
85-
description: Optional[str],
86-
col_type: str,
87-
sort_order: int,
88-
stats: Iterable[Statistics] =()) -> None:
89-
self.name = name
90-
self.description = description
91-
self.col_type = col_type
92-
self.sort_order = sort_order
93-
self.stats = stats
94-
95-
def __repr__(self) -> str:
96-
return 'Column(name={!r}, description={!r}, col_type={!r}, sort_order={!r}, stats={!r})'\
97-
.format(self.name,
98-
self.description,
99-
self.col_type,
100-
self.sort_order,
101-
self.stats)
74+
name: str = attr.ib()
75+
description: Optional[str] = None
76+
col_type: str = attr.ib()
77+
sort_order: int = attr.ib()
78+
stats: List[Statistics] = []
79+
80+
81+
class ColumnSchema(AttrsSchema):
82+
class Meta:
83+
target = Column
84+
register_as_scheme = True
85+
86+
87+
@attr.s(auto_attribs=True, kw_only=True)
88+
class PiiDetail:
89+
pii_semantic_type: Optional[str] = None
90+
pii_forget_type: Optional[str] = None
91+
10292

93+
class PiiDetailSchema(AttrsSchema):
94+
class Meta:
95+
target = PiiDetail
96+
register_as_scheme = True
10397

98+
99+
@attr.s(auto_attribs=True, kw_only=True)
100+
class ForeignKey:
101+
table_uri: Optional[str] = None
102+
column_name: Optional[str] = None
103+
104+
105+
class ForeignKeySchema(AttrsSchema):
106+
class Meta:
107+
target = ForeignKey
108+
register_as_scheme = True
109+
110+
111+
@attr.s(auto_attribs=True, kw_only=True)
112+
class DataDetail:
113+
data_semantic_type: Optional[str] = None
114+
data_semantic_reference: Optional[str] = None
115+
116+
117+
class DataDetailchema(AttrsSchema):
118+
class Meta:
119+
target = DataDetail
120+
register_as_scheme = True
121+
122+
123+
@attr.s(auto_attribs=True, kw_only=True)
104124
class Application:
105-
def __init__(self, *,
106-
application_url: str,
107-
description: str,
108-
id: str,
109-
name: str) -> None:
110-
self.application_url = application_url
111-
self.description = description
112-
self.name = name
113-
self.id = id
125+
application_url: str = attr.ib()
126+
description: str = attr.ib()
127+
id: str = attr.ib()
128+
name: str = attr.ib()
129+
114130

115-
def __repr__(self) -> str:
116-
return 'Application(application_url={!r}, description={!r}, name={!r}, id={!r})'\
117-
.format(self.application_url, self.description, self.name, self.id)
131+
class ApplicationSchema(AttrsSchema):
132+
class Meta:
133+
target = Application
134+
register_as_scheme = True
118135

119136

137+
@attr.s(auto_attribs=True, kw_only=True)
120138
class Source:
121-
def __init__(self, *,
122-
source_type: str,
123-
source: str) -> None:
124-
self.source_type = source_type
125-
self.source = source
139+
source_type: str = attr.ib()
140+
source: str = attr.ib()
141+
142+
143+
class SourceSchema(AttrsSchema):
144+
class Meta:
145+
target = Source
146+
register_as_scheme = True
147+
126148

127-
def __repr__(self) -> str:
128-
return 'Source(source_type={!r}, ' \
129-
'source={!r})'.format(self.source_type,
130-
self.source)
149+
# this is a temporary hack to satisfy mypy. Once https://github.com/python/mypy/issues/6136 is resolved, use
150+
# `attr.converters.default_if_none(default=False)`
151+
def default_if_none(arg: Optional[bool]) -> bool:
152+
return arg or False
131153

132154

155+
@attr.s(auto_attribs=True, kw_only=True)
133156
class Table:
134-
def __init__(self, *,
135-
database: str,
136-
cluster: str,
137-
schema: str,
138-
name: str,
139-
tags: Iterable[Tag] =(),
140-
table_readers: Iterable[Reader] = (),
141-
description: Optional[str] = None,
142-
columns: Iterable[Column],
143-
owners: Iterable[User] = (),
144-
watermarks: Iterable[Watermark] = (),
145-
table_writer: Optional[Application] = None,
146-
last_updated_timestamp: Optional[int],
147-
source: Optional[Source] = None,
148-
is_view: Optional[bool] = None,
149-
) -> None:
150-
151-
self.database = database
152-
self.cluster = cluster
153-
self.schema = schema
154-
self.name = name
155-
self.tags = tags
156-
self.table_readers = table_readers
157-
self.description = description
158-
self.columns = columns
159-
self.owners = owners
160-
self.watermarks = watermarks
161-
self.table_writer = table_writer
162-
self.last_updated_timestamp = last_updated_timestamp
163-
self.source = source
164-
self.is_view = is_view or False
165-
166-
def __repr__(self) -> str:
167-
return """Table(database={!r}, cluster={!r}, schema={!r}, name={!r}, tags={!r}, table_readers={!r},
168-
description={!r}, columns={!r}, owners={!r}, watermarks={!r}, table_writer={!r},
169-
last_updated_timestamp={!r}, source={!r}, is_view={!r})"""\
170-
.format(self.database, self.cluster,
171-
self.schema, self.name, self.tags,
172-
self.table_readers, self.description,
173-
self.columns, self.owners, self.watermarks,
174-
self.table_writer, self.last_updated_timestamp,
175-
self.source, self.is_view)
157+
database: str = attr.ib()
158+
cluster: str = attr.ib()
159+
schema: str = attr.ib()
160+
name: str = attr.ib()
161+
tags: List[Tag] = []
162+
table_readers: List[Reader] = []
163+
description: Optional[str] = None
164+
columns: List[Column] = attr.ib()
165+
owners: List[User] = []
166+
watermarks: List[Watermark] = []
167+
table_writer: Optional[Application] = None
168+
last_updated_timestamp: Optional[int] = None
169+
source: Optional[Source] = None
170+
is_view: Optional[bool] = attr.ib(default=None, converter=default_if_none)
171+
172+
173+
class TableSchema(AttrsSchema):
174+
class Meta:
175+
target = Table
176+
register_as_scheme = True

metadata_service/entity/tag_detail.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
import attr
2+
from marshmallow_annotations.ext.attrs import AttrsSchema
3+
4+
5+
@attr.s(auto_attribs=True, kw_only=True)
16
class TagDetail:
7+
tag_name: str = attr.ib()
8+
tag_count: int = attr.ib()
29

3-
def __init__(self, *,
4-
tag_name: str,
5-
tag_count: int) -> None:
6-
self.tag_name = tag_name
7-
self.tag_count = tag_count
810

9-
def __repr__(self) -> str:
10-
return """Tag(tag_name={!r}, tag_count={!r})"""\
11-
.format(self.tag_name, self.tag_count)
11+
class TagDetailSchema(AttrsSchema):
12+
class Meta:
13+
target = TagDetail
14+
register_as_scheme = True

0 commit comments

Comments
 (0)