Skip to content

Commit c67add3

Browse files
committed
Add unique_attributes to Referenceable for use with convenience method create when a qualified_name is used
1 parent 2624713 commit c67add3

4 files changed

Lines changed: 158 additions & 9 deletions

File tree

pyatlan/generator/templates/entity.jinja2

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@ class {{ entity_def.name }}({{super_classes[0]}} {%- if "Asset" in super_classes
220220
)
221221
pending_tasks: Optional[list[str]] = Field(None)
222222

223+
unique_attributes: Optional[dict[str, Any]] = Field(None)
224+
223225
def validate_required(self):
224226
if not self.create_time or self.created_by:
225227
self.attributes.validate_required()
@@ -571,7 +573,7 @@ class {{ entity_def.name }}({{super_classes[0]}} {%- if "Asset" in super_classes
571573
)
572574
if glossary_qualified_name:
573575
anchor = AtlasGlossary()
574-
anchor.qualified_name = glossary_qualified_name
576+
anchor.unique_attributes = {"qualifiedName": glossary_qualified_name}
575577
if glossary_guid:
576578
anchor = AtlasGlossary()
577579
anchor.guid = glossary_guid
@@ -724,13 +726,15 @@ class {{ entity_def.name }}({{super_classes[0]}} {%- if "Asset" in super_classes
724726
cls,
725727
*,
726728
name: StrictStr,
727-
anchor: AtlasGlossary,
729+
anchor: Optional[AtlasGlossary] = None,
730+
glossary_qualified_name: Optional[StrictStr] = None,
731+
glossary_guid: Optional[StrictStr] = None,
728732
categories: Optional[list[AtlasGlossaryCategory]] = None,
729733
) -> AtlasGlossaryTerm:
730-
validate_required_fields(["name", "anchor"], [name, anchor])
734+
validate_required_fields(["name"], [name])
731735
return cls(
732736
attributes=AtlasGlossaryTerm.Attributes.create(
733-
name=name, anchor=anchor, categories=categories
737+
name=name, anchor=anchor, glossary_qualified_name=glossary_qualified_name, glossary_guid = glossary_guid, categories=categories
734738
)
735739
)
736740

pyatlan/model/assets.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,8 @@ def validate_required(self):
240240
)
241241
pending_tasks: Optional[list[str]] = Field(None)
242242

243+
unique_attributes: Optional[dict[str, Any]] = Field(None)
244+
243245
def validate_required(self):
244246
if not self.create_time or self.created_by:
245247
self.attributes.validate_required()
@@ -2235,7 +2237,7 @@ def create(
22352237
)
22362238
if glossary_qualified_name:
22372239
anchor = AtlasGlossary()
2238-
anchor.qualified_name = glossary_qualified_name
2240+
anchor.unique_attributes = {"qualifiedName": glossary_qualified_name}
22392241
if glossary_guid:
22402242
anchor = AtlasGlossary()
22412243
anchor.guid = glossary_guid
@@ -2268,13 +2270,19 @@ def create(
22682270
cls,
22692271
*,
22702272
name: StrictStr,
2271-
anchor: AtlasGlossary,
2273+
anchor: Optional[AtlasGlossary] = None,
2274+
glossary_qualified_name: Optional[StrictStr] = None,
2275+
glossary_guid: Optional[StrictStr] = None,
22722276
categories: Optional[list[AtlasGlossaryCategory]] = None,
22732277
) -> AtlasGlossaryTerm:
2274-
validate_required_fields(["name", "anchor"], [name, anchor])
2278+
validate_required_fields(["name"], [name])
22752279
return cls(
22762280
attributes=AtlasGlossaryTerm.Attributes.create(
2277-
name=name, anchor=anchor, categories=categories
2281+
name=name,
2282+
anchor=anchor,
2283+
glossary_qualified_name=glossary_qualified_name,
2284+
glossary_guid=glossary_guid,
2285+
categories=categories,
22782286
)
22792287
)
22802288

tests/integration/test_entity_model.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,67 @@ def test_create_glossary_term(client: AtlanClient, increment_counter):
389389
assert 1 == len(response.assets_updated(AtlasGlossaryTerm))
390390

391391

392+
def test_create_glossary_term_with_glossary_guid(
393+
client: AtlanClient, increment_counter
394+
):
395+
suffix = increment_counter()
396+
glossary = AtlasGlossary.create(name=f"Integration Test Glossary {suffix}")
397+
response = client.upsert(glossary)
398+
assert response.mutated_entities
399+
assert response.mutated_entities.CREATE
400+
assert isinstance(response.mutated_entities.CREATE[0], AtlasGlossary)
401+
glossary = response.mutated_entities.CREATE[0]
402+
term = AtlasGlossaryTerm.create(
403+
name=f"Integration Test Glossary Term {suffix}", glossary_guid=glossary.guid
404+
)
405+
response = client.upsert(term)
406+
assert response.mutated_entities
407+
assert response.mutated_entities.UPDATE
408+
assert response.mutated_entities.UPDATE
409+
assert len(response.mutated_entities.UPDATE) == 1
410+
assert isinstance(response.mutated_entities.UPDATE[0], AtlasGlossary)
411+
assert response.mutated_entities.CREATE
412+
assert len(response.mutated_entities.CREATE) == 1
413+
guid = list(response.guid_assignments.values())[0]
414+
assert isinstance(response.mutated_entities.CREATE[0], AtlasGlossaryTerm)
415+
term = response.mutated_entities.CREATE[0]
416+
assert guid == term.guid
417+
term = client.get_asset_by_guid(guid, AtlasGlossaryTerm)
418+
assert isinstance(term, AtlasGlossaryTerm)
419+
assert term.guid == guid
420+
421+
422+
def test_create_glossary_term_with_glossary_qualified_name(
423+
client: AtlanClient, increment_counter
424+
):
425+
suffix = increment_counter()
426+
glossary = AtlasGlossary.create(name=f"Integration Test Glossary {suffix}")
427+
response = client.upsert(glossary)
428+
assert response.mutated_entities
429+
assert response.mutated_entities.CREATE
430+
assert isinstance(response.mutated_entities.CREATE[0], AtlasGlossary)
431+
glossary = response.mutated_entities.CREATE[0]
432+
term = AtlasGlossaryTerm.create(
433+
name=f"Integration Test Glossary Term {suffix}",
434+
glossary_qualified_name=glossary.qualified_name,
435+
)
436+
response = client.upsert(term)
437+
assert response.mutated_entities
438+
assert response.mutated_entities.UPDATE
439+
assert response.mutated_entities.UPDATE
440+
assert len(response.mutated_entities.UPDATE) == 1
441+
assert isinstance(response.mutated_entities.UPDATE[0], AtlasGlossary)
442+
assert response.mutated_entities.CREATE
443+
assert len(response.mutated_entities.CREATE) == 1
444+
guid = list(response.guid_assignments.values())[0]
445+
assert isinstance(response.mutated_entities.CREATE[0], AtlasGlossaryTerm)
446+
term = response.mutated_entities.CREATE[0]
447+
assert guid == term.guid
448+
term = client.get_asset_by_guid(guid, AtlasGlossaryTerm)
449+
assert isinstance(term, AtlasGlossaryTerm)
450+
assert term.guid == guid
451+
452+
392453
def test_create_hierarchy(client: AtlanClient, increment_counter):
393454
suffix = increment_counter()
394455
glossary = AtlasGlossary(

tests/unit/test_glossary_term.py

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,82 @@ def test_create_atttributes_with_required_parameters(
7070
if anchor:
7171
assert anchor == sut.anchor
7272
if glossary_qualified_name:
73-
assert sut.anchor.qualified_name == glossary_qualified_name
73+
assert sut.anchor.unique_attributes == {
74+
"qualifiedName": glossary_qualified_name
75+
}
7476
if glossary_guid:
7577
assert sut.anchor.guid == glossary_guid
78+
79+
80+
@pytest.mark.parametrize(
81+
"name, anchor, glossary_qualified_name, glossary_guid, message",
82+
[
83+
(None, None, None, "1234", "name is required"),
84+
(
85+
"Glossary",
86+
None,
87+
None,
88+
None,
89+
"One of the following parameters are required: anchor, glossary_qualified_name, glossary_guid",
90+
),
91+
(
92+
"Glossary",
93+
AtlasGlossary(),
94+
"qname",
95+
None,
96+
"Only one of the following parameters are allowed: anchor, glossary_qualified_name",
97+
),
98+
(
99+
"Glossary",
100+
AtlasGlossary(),
101+
None,
102+
"123",
103+
"Only one of the following parameters are allowed: anchor, glossary_guid",
104+
),
105+
(
106+
"Glossary",
107+
None,
108+
"qname",
109+
"123",
110+
"Only one of the following parameters are allowed: glossary_qualified_name, glossary_guid",
111+
),
112+
],
113+
)
114+
def test_create_without_required_parameters_raises_value_error(
115+
name, anchor, glossary_qualified_name, glossary_guid, message
116+
):
117+
with pytest.raises(ValueError, match=message):
118+
AtlasGlossaryTerm.create(
119+
name=name,
120+
anchor=anchor,
121+
glossary_qualified_name=glossary_qualified_name,
122+
glossary_guid=glossary_guid,
123+
)
124+
125+
126+
@pytest.mark.parametrize(
127+
"name, anchor, glossary_qualified_name, glossary_guid",
128+
[
129+
("Glossary", AtlasGlossary(), None, None),
130+
("Glossary", None, "glossary/qualifiedName", None),
131+
("Glossary", None, None, "123"),
132+
],
133+
)
134+
def test_create_with_required_parameters(
135+
name, anchor, glossary_qualified_name, glossary_guid
136+
):
137+
sut = AtlasGlossaryTerm.create(
138+
name=name,
139+
anchor=anchor,
140+
glossary_qualified_name=glossary_qualified_name,
141+
glossary_guid=glossary_guid,
142+
)
143+
144+
if anchor:
145+
assert anchor == sut.attributes.anchor
146+
if glossary_qualified_name:
147+
assert sut.attributes.anchor.unique_attributes == {
148+
"qualifiedName": glossary_qualified_name
149+
}
150+
if glossary_guid:
151+
assert sut.attributes.anchor.guid == glossary_guid

0 commit comments

Comments
 (0)