Skip to content

Commit d67c3b7

Browse files
committed
[generator] Fixed generator as per latest async refactoring changes
1 parent 8dda545 commit d67c3b7

File tree

9 files changed

+239
-2
lines changed

9 files changed

+239
-2
lines changed

pyatlan/generator/class_generator.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,15 @@
3030
("array<int>", "Set[int]"),
3131
("array<float>", "Set[float]"),
3232
("array<long>", "Set[int]"),
33+
("array<double>", "Set[float]"),
3334
("icon_type", "IconType"),
3435
("string", "str"),
3536
("date", "datetime"),
3637
("array", "List"),
3738
("boolean", "bool"),
3839
("float", "float"),
3940
("long", "int"),
41+
("double", "float"),
4042
("__internal", "Internal"),
4143
("certificate_status", "CertificateStatus"),
4244
("map", "Dict"),
@@ -64,6 +66,7 @@
6466
"long": "int",
6567
"date": "int",
6668
"float": "float",
69+
"double": "float",
6770
"string,string": "str, str",
6871
"string,long": "str, int",
6972
}
@@ -229,6 +232,11 @@ class AssetInfo:
229232
"Purpose",
230233
"alpha_DQRule",
231234
}
235+
_ASSETS_REQUIRE_ASYNC_CLIENT = {
236+
"Badge",
237+
"Connection",
238+
"Referenceable",
239+
}
232240
_CORE_ASSETS = {
233241
"Referenceable",
234242
"Asset",
@@ -1002,6 +1010,9 @@ def filter_attributes_of_custom_entity_type():
10021010
)
10031011
args = parser.parse_args()
10041012

1013+
# Ensure docs directory exists
1014+
DOCS_DIR.mkdir(parents=True, exist_ok=True)
1015+
10051016
type_defs = get_type_defs(args.typedefs_file)
10061017
filter_attributes_of_custom_entity_type()
10071018
AssetInfo.sub_type_names_to_ignore = type_defs.custom_entity_def_names

pyatlan/generator/templates/imports.jinja2

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,9 @@ from pyatlan.model.structs import (
115115
alpha_DQRuleTemplateConfig,
116116
ResponseValue,
117117
FormField,
118-
DatabricksAIModelVersionMetric
118+
DatabricksAIModelVersionMetric,
119+
AssetHistogram,
120+
AppWorkflowRunStep,
119121
)
120122
from pyatlan.utils import (
121123
init_guid,

pyatlan/generator/templates/methods/asset/badge.jinja2

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,28 @@
2121
),
2222
)
2323

24+
@classmethod
25+
@init_guid
26+
async def creator_async(
27+
cls,
28+
*,
29+
client: AsyncAtlanClient,
30+
name: StrictStr,
31+
cm_name: str,
32+
cm_attribute: str,
33+
badge_conditions: List[BadgeCondition],
34+
) -> Badge:
35+
return cls(
36+
status=EntityStatus.ACTIVE,
37+
attributes=await Badge.Attributes.create_async(
38+
client=client,
39+
name=name,
40+
cm_name=cm_name,
41+
cm_attribute=cm_attribute,
42+
badge_conditions=badge_conditions,
43+
),
44+
)
45+
2446
@classmethod
2547
@init_guid
2648
def create(

pyatlan/generator/templates/methods/asset/connection.jinja2

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,61 @@
3636
attr.port = port
3737
return cls(attributes=attr)
3838

39+
@classmethod
40+
@init_guid
41+
async def creator_async(
42+
cls,
43+
*,
44+
client: AsyncAtlanClient,
45+
name: str,
46+
connector_type: AtlanConnectorType,
47+
admin_users: Optional[List[str]] = None,
48+
admin_groups: Optional[List[str]] = None,
49+
admin_roles: Optional[List[str]] = None,
50+
host: Optional[str] = None,
51+
port: Optional[int] = None,
52+
) -> Connection:
53+
"""
54+
Async version of creator() method for creating a new connection.
55+
56+
:param client: async client to use for validation
57+
:param name: name for the connection
58+
:param connector_type: type of connector this connection is for
59+
:param admin_users: list of admin usernames for the connection
60+
:param admin_groups: list of admin group names for the connection
61+
:param admin_roles: list of admin role GUIDs for the connection
62+
:param host: hostname for the connection
63+
:param port: port number for the connection
64+
:returns: the new connection object
65+
:raises ValueError: if required parameters are missing or invalid
66+
"""
67+
validate_required_fields(
68+
["client", "name", "connector_type"], [client, name, connector_type]
69+
)
70+
if not admin_users and not admin_groups and not admin_roles:
71+
raise ValueError(
72+
"One of admin_user, admin_groups or admin_roles is required"
73+
)
74+
attr = cls.Attributes(
75+
name=name,
76+
qualified_name=connector_type.to_qualified_name(),
77+
connector_name=connector_type.value,
78+
category=connector_type.category.value,
79+
)
80+
81+
# Use async cache validation methods
82+
await client.user_cache.validate_names(names=admin_users or [])
83+
await client.role_cache.validate_idstrs(idstrs=admin_roles or [])
84+
await client.group_cache.validate_aliases(aliases=admin_groups or [])
85+
86+
attr.admin_users = set() if admin_users is None else set(admin_users)
87+
attr.admin_groups = set() if admin_groups is None else set(admin_groups)
88+
attr.admin_roles = set() if admin_roles is None else set(admin_roles)
89+
90+
attr.host = host
91+
attr.port = port
92+
return cls(attributes=attr)
93+
3994
@classmethod
4095
@init_guid
4196
def create(

pyatlan/generator/templates/methods/attribute/badge.jinja2

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,29 @@
2424
badge_metadata_attribute=f"{cm_id}.{cm_attr_id}",
2525
badge_conditions=badge_conditions,
2626
)
27+
28+
@classmethod
29+
@init_guid
30+
async def create_async(
31+
cls,
32+
*,
33+
client: AsyncAtlanClient,
34+
name: StrictStr,
35+
cm_name: str,
36+
cm_attribute: str,
37+
badge_conditions: List[BadgeCondition],
38+
) -> Badge.Attributes:
39+
validate_required_fields(
40+
["client", "name", "cm_name", "cm_attribute", "badge_conditions"],
41+
[client, name, cm_name, cm_attribute, badge_conditions],
42+
)
43+
cm_id = await client.custom_metadata_cache.get_id_for_name(cm_name)
44+
cm_attr_id = await client.custom_metadata_cache.get_attr_id_for_name(
45+
set_name=cm_name, attr_name=cm_attribute
46+
)
47+
return Badge.Attributes(
48+
name=name,
49+
qualified_name=f"badges/global/{cm_id}.{cm_attr_id}",
50+
badge_metadata_attribute=f"{cm_id}.{cm_attr_id}",
51+
badge_conditions=badge_conditions,
52+
)

pyatlan/generator/templates/module.jinja2

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ if TYPE_CHECKING:
4343
{% if asset_info.name == 'alpha_DQRule' %}
4444
from pyatlan.model.assets import Column
4545
{% endif %}
46+
{% if asset_info.name in asset_info._ASSETS_REQUIRE_ASYNC_CLIENT %}
47+
from pyatlan.client.aio.client import AsyncAtlanClient
48+
from pyatlan.model.aio import AsyncCustomMetadataProxy
49+
{% endif %}
4650
{% endif %}
4751

4852
{% if asset_info.name == 'Asset' %}

pyatlan/generator/templates/referenceable_attributes.jinja2

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
type_name: str = Field(default="Referenceable", description='Name of the type definition that defines this instance.'
9797
)
9898
_metadata_proxy: CustomMetadataProxy = PrivateAttr(default=None)
99+
_async_metadata_proxy: AsyncCustomMetadataProxy = PrivateAttr(default=None)
99100
attributes: {{entity_def.name}}.Attributes = Field(
100101
default_factory = lambda : {{entity_def.name}}.Attributes(),
101102
description='Map of attributes in the instance and their values. The specific keys of this map will vary '

pyatlan/generator/templates/referenceable_methods.jinja2

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,16 @@
2121
return values
2222

2323
def json(self, *args, **kwargs) -> str:
24+
from pyatlan.model.aio.custom_metadata import AsyncCustomMetadataProxy
2425
if not self._metadata_proxy and kwargs.get("client"):
2526
self._metadata_proxy = CustomMetadataProxy(
2627
client=kwargs.get("client"), # type: ignore[arg-type]
2728
business_attributes=self.business_attributes,
2829
)
30+
self._async_metadata_proxy = AsyncCustomMetadataProxy(
31+
client=kwargs.get("client"), # type: ignore[arg-type]
32+
business_attributes=self.business_attributes,
33+
)
2934
self.business_attributes = self._metadata_proxy.business_attributes
3035
return super().json(**kwargs)
3136

@@ -56,6 +61,72 @@
5661
)
5762
self.business_attributes = self._metadata_proxy.business_attributes
5863

64+
async def flush_custom_metadata_async(self, client):
65+
"""
66+
Async version of flush_custom_metadata for use with AsyncAtlanClient.
67+
This properly handles async metadata proxy and sets business_attributes.
68+
"""
69+
from pyatlan.model.aio.custom_metadata import AsyncCustomMetadataProxy
70+
71+
if not self._async_metadata_proxy:
72+
self._async_metadata_proxy = AsyncCustomMetadataProxy(
73+
business_attributes=self.business_attributes, client=client
74+
)
75+
# Get the business attributes asynchronously and set them
76+
business_attrs = await self._async_metadata_proxy.business_attributes()
77+
self.business_attributes = business_attrs
78+
79+
async def get_custom_metadata_async(self, client: AsyncAtlanClient, name: str):
80+
"""
81+
Async version of get_custom_metadata.
82+
83+
:param client: async Atlan client to use for the request
84+
:param name: human-readable name of the custom metadata set to retrieve
85+
:returns: the requested custom metadata set, or an empty one if none exists
86+
"""
87+
from pyatlan.model.aio.custom_metadata import AsyncCustomMetadataProxy
88+
89+
if not self._async_metadata_proxy:
90+
self._async_metadata_proxy = AsyncCustomMetadataProxy(
91+
business_attributes=self.business_attributes, client=client
92+
)
93+
return await self._async_metadata_proxy.get_custom_metadata(name=name)
94+
95+
async def set_custom_metadata_async(
96+
self, client: AsyncAtlanClient, custom_metadata
97+
):
98+
"""
99+
Async version of set_custom_metadata.
100+
101+
:param client: async Atlan client to use for the request
102+
:param custom_metadata: the custom metadata to set on this asset
103+
"""
104+
from pyatlan.model.aio.custom_metadata import AsyncCustomMetadataProxy
105+
106+
if not self._async_metadata_proxy:
107+
self._async_metadata_proxy = AsyncCustomMetadataProxy(
108+
business_attributes=self.business_attributes, client=client
109+
)
110+
return await self._async_metadata_proxy.set_custom_metadata(
111+
custom_metadata=custom_metadata
112+
)
113+
114+
async def flush_custom_metadata_async(self, client: AsyncAtlanClient):
115+
"""
116+
Async version of flush_custom_metadata.
117+
118+
:param client: async Atlan client to use for the request
119+
"""
120+
from pyatlan.model.aio.custom_metadata import AsyncCustomMetadataProxy
121+
122+
if not self._async_metadata_proxy:
123+
self._async_metadata_proxy = AsyncCustomMetadataProxy(
124+
business_attributes=self.business_attributes, client=client
125+
)
126+
self.business_attributes = (
127+
await self._async_metadata_proxy.business_attributes()
128+
)
129+
59130
@classmethod
60131
def __get_validators__(cls):
61132
yield cls._convert_to_real_type_

pyatlan/generator/templates/structs.jinja2

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# SPDX-License-Identifier: Apache-2.0
2-
# Copyright 2024 Atlan Pte. Ltd.
2+
# Copyright 2025 Atlan Pte. Ltd.
33

44
from __future__ import annotations
55

@@ -16,13 +16,15 @@ from pyatlan.model.enums import (
1616
FormFieldDimension,
1717
FormFieldType,
1818
alpha_DQRuleThresholdUnit,
19+
AppWorkflowRunStatus,
1920
)
2021
from pyatlan.model.utils import to_camel_case
2122
from pyatlan.utils import select_optional_set_fields, validate_required_fields
2223

2324
if TYPE_CHECKING:
2425
from pyatlan.cache.source_tag_cache import SourceTagName
2526
from pyatlan.client.atlan import AtlanClient
27+
from pyatlan.client.aio import AsyncAtlanClient
2628

2729

2830
class AtlanObject(BaseModel):
@@ -123,6 +125,49 @@ class {{struct.name}}(AtlanObject):
123125
),
124126
)
125127

128+
@classmethod
129+
async def by_name_async(
130+
cls,
131+
client: AsyncAtlanClient,
132+
name: SourceTagName,
133+
source_tag_values: List[SourceTagAttachmentValue],
134+
source_tag_sync_timestamp: Optional[datetime] = None,
135+
is_source_tag_synced: Optional[bool] = None,
136+
source_tag_sync_error: Optional[str] = None,
137+
):
138+
"""
139+
Async version of by_name that creates a source-synced tag attachment with
140+
a particular value when the attachment is synced to the source.
141+
142+
:param client: async connectivity to an Atlan tenant
143+
:param name: unique name of the source tag in Atlan
144+
:param source_tag_values: value of the tag attachment from the source
145+
:param is_source_tag_synced: whether the tag attachment has been synced at the source (True) or not (False)
146+
:param source_tag_sync_timestamp: time (epoch) when the tag attachment was synced at the source, in milliseconds
147+
:param source_tag_sync_error: error message if the tag attachment sync at the source failed
148+
:returns: a SourceTagAttachment with the provided information
149+
:raises AtlanError: on any error communicating via the underlying APIs
150+
:raises NotFoundError: if the source-synced tag cannot be resolved
151+
"""
152+
tag = await client.source_tag_cache.get_by_name(name)
153+
tag_connector_name = AtlanConnectorType._get_connector_type_from_qualified_name(
154+
tag.qualified_name or ""
155+
)
156+
return cls.of(
157+
source_tag_name=tag.name,
158+
source_tag_qualified_name=tag.qualified_name,
159+
source_tag_guid=tag.guid,
160+
source_tag_connector_name=tag_connector_name,
161+
source_tag_values=source_tag_values,
162+
**select_optional_set_fields(
163+
dict(
164+
is_source_tag_synced=is_source_tag_synced,
165+
source_tag_sync_timestamp=source_tag_sync_timestamp,
166+
source_tag_sync_error=source_tag_sync_error,
167+
)
168+
),
169+
)
170+
126171
@classmethod
127172
def by_qualified_name(
128173
cls,

0 commit comments

Comments
 (0)