acryl-datahub 1.2.0__py3-none-any.whl → 1.2.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of acryl-datahub might be problematic. Click here for more details.
- {acryl_datahub-1.2.0.dist-info → acryl_datahub-1.2.0.1.dist-info}/METADATA +2390 -2390
- {acryl_datahub-1.2.0.dist-info → acryl_datahub-1.2.0.1.dist-info}/RECORD +16 -16
- datahub/_version.py +1 -1
- datahub/configuration/pydantic_migration_helpers.py +7 -5
- datahub/ingestion/source/mock_data/datahub_mock_data.py +55 -20
- datahub/ingestion/source/mock_data/table_naming_helper.py +10 -4
- datahub/metadata/_internal_schema_classes.py +74 -8
- datahub/metadata/com/linkedin/pegasus2avro/module/__init__.py +2 -0
- datahub/metadata/schema.avsc +42 -5
- datahub/metadata/schemas/DataHubPageModuleProperties.avsc +42 -5
- datahub/sdk/search_filters.py +95 -27
- datahub/upgrade/upgrade.py +14 -5
- {acryl_datahub-1.2.0.dist-info → acryl_datahub-1.2.0.1.dist-info}/WHEEL +0 -0
- {acryl_datahub-1.2.0.dist-info → acryl_datahub-1.2.0.1.dist-info}/entry_points.txt +0 -0
- {acryl_datahub-1.2.0.dist-info → acryl_datahub-1.2.0.1.dist-info}/licenses/LICENSE +0 -0
- {acryl_datahub-1.2.0.dist-info → acryl_datahub-1.2.0.1.dist-info}/top_level.txt +0 -0
datahub/sdk/search_filters.py
CHANGED
|
@@ -2,6 +2,8 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import abc
|
|
4
4
|
from typing import (
|
|
5
|
+
TYPE_CHECKING,
|
|
6
|
+
Annotated,
|
|
5
7
|
Any,
|
|
6
8
|
ClassVar,
|
|
7
9
|
Iterator,
|
|
@@ -15,7 +17,10 @@ from typing import (
|
|
|
15
17
|
import pydantic
|
|
16
18
|
|
|
17
19
|
from datahub.configuration.common import ConfigModel
|
|
18
|
-
from datahub.configuration.pydantic_migration_helpers import
|
|
20
|
+
from datahub.configuration.pydantic_migration_helpers import (
|
|
21
|
+
PYDANTIC_SUPPORTS_CALLABLE_DISCRIMINATOR,
|
|
22
|
+
PYDANTIC_VERSION_2,
|
|
23
|
+
)
|
|
19
24
|
from datahub.ingestion.graph.client import flexible_entity_type_to_graphql
|
|
20
25
|
from datahub.ingestion.graph.filters import (
|
|
21
26
|
FilterOperator,
|
|
@@ -42,12 +47,29 @@ class _BaseFilter(ConfigModel):
|
|
|
42
47
|
populate_by_name = True
|
|
43
48
|
|
|
44
49
|
@abc.abstractmethod
|
|
45
|
-
def compile(self) -> _OrFilters:
|
|
46
|
-
pass
|
|
50
|
+
def compile(self) -> _OrFilters: ...
|
|
47
51
|
|
|
48
52
|
def dfs(self) -> Iterator[_BaseFilter]:
|
|
49
53
|
yield self
|
|
50
54
|
|
|
55
|
+
@classmethod
|
|
56
|
+
def _field_discriminator(cls) -> str:
|
|
57
|
+
if cls is _BaseFilter:
|
|
58
|
+
raise ValueError("Cannot get discriminator for _BaseFilter")
|
|
59
|
+
if PYDANTIC_VERSION_2:
|
|
60
|
+
fields: dict = cls.model_fields # type: ignore
|
|
61
|
+
else:
|
|
62
|
+
fields = cls.__fields__ # type: ignore
|
|
63
|
+
|
|
64
|
+
# Assumes that there's only one field name per filter.
|
|
65
|
+
# If that's not the case, this method should be overridden.
|
|
66
|
+
if len(fields.keys()) != 1:
|
|
67
|
+
raise ValueError(
|
|
68
|
+
f"Found multiple fields that could be the discriminator for this filter: {list(fields.keys())}"
|
|
69
|
+
)
|
|
70
|
+
name, field = next(iter(fields.items()))
|
|
71
|
+
return field.alias or name # type: ignore
|
|
72
|
+
|
|
51
73
|
|
|
52
74
|
class _EntityTypeFilter(_BaseFilter):
|
|
53
75
|
"""Filter for specific entity types.
|
|
@@ -74,15 +96,19 @@ class _EntityTypeFilter(_BaseFilter):
|
|
|
74
96
|
|
|
75
97
|
|
|
76
98
|
class _EntitySubtypeFilter(_BaseFilter):
|
|
77
|
-
entity_subtype: str = pydantic.Field(
|
|
99
|
+
entity_subtype: List[str] = pydantic.Field(
|
|
78
100
|
description="The entity subtype to filter on. Can be 'Table', 'View', 'Source', etc. depending on the native platform's concepts.",
|
|
79
101
|
)
|
|
80
102
|
|
|
103
|
+
@pydantic.validator("entity_subtype", pre=True)
|
|
104
|
+
def validate_entity_subtype(cls, v: str) -> List[str]:
|
|
105
|
+
return [v] if not isinstance(v, list) else v
|
|
106
|
+
|
|
81
107
|
def _build_rule(self) -> SearchFilterRule:
|
|
82
108
|
return SearchFilterRule(
|
|
83
109
|
field="typeNames",
|
|
84
110
|
condition="EQUAL",
|
|
85
|
-
values=
|
|
111
|
+
values=self.entity_subtype,
|
|
86
112
|
)
|
|
87
113
|
|
|
88
114
|
def compile(self) -> _OrFilters:
|
|
@@ -196,6 +222,10 @@ class _CustomCondition(_BaseFilter):
|
|
|
196
222
|
)
|
|
197
223
|
return [{"and": [rule]}]
|
|
198
224
|
|
|
225
|
+
@classmethod
|
|
226
|
+
def _field_discriminator(cls) -> str:
|
|
227
|
+
return "_custom"
|
|
228
|
+
|
|
199
229
|
|
|
200
230
|
class _And(_BaseFilter):
|
|
201
231
|
"""Represents an AND conjunction of filters."""
|
|
@@ -302,31 +332,69 @@ class _Not(_BaseFilter):
|
|
|
302
332
|
yield from self.not_.dfs()
|
|
303
333
|
|
|
304
334
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
335
|
+
def _filter_discriminator(v: Any) -> Optional[str]:
|
|
336
|
+
if isinstance(v, _BaseFilter):
|
|
337
|
+
return v._field_discriminator()
|
|
338
|
+
|
|
339
|
+
if not isinstance(v, dict):
|
|
340
|
+
return None
|
|
341
|
+
|
|
342
|
+
keys = list(v.keys())
|
|
343
|
+
if len(keys) == 1:
|
|
344
|
+
return keys[0]
|
|
345
|
+
elif set(keys).issuperset({"field", "condition"}):
|
|
346
|
+
return _CustomCondition._field_discriminator()
|
|
347
|
+
|
|
348
|
+
return None
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
if TYPE_CHECKING or not PYDANTIC_SUPPORTS_CALLABLE_DISCRIMINATOR:
|
|
352
|
+
# The `not TYPE_CHECKING` bit is required to make the linter happy,
|
|
353
|
+
# since we currently only run mypy with pydantic v1.
|
|
354
|
+
Filter = Union[
|
|
355
|
+
_And,
|
|
356
|
+
_Or,
|
|
357
|
+
_Not,
|
|
358
|
+
_EntityTypeFilter,
|
|
359
|
+
_EntitySubtypeFilter,
|
|
360
|
+
_StatusFilter,
|
|
361
|
+
_PlatformFilter,
|
|
362
|
+
_DomainFilter,
|
|
363
|
+
_EnvFilter,
|
|
364
|
+
_CustomCondition,
|
|
365
|
+
]
|
|
366
|
+
|
|
327
367
|
_And.update_forward_refs()
|
|
328
368
|
_Or.update_forward_refs()
|
|
329
369
|
_Not.update_forward_refs()
|
|
370
|
+
else:
|
|
371
|
+
from pydantic import Discriminator, Tag
|
|
372
|
+
|
|
373
|
+
# TODO: Once we're fully on pydantic 2, we can use a RootModel here.
|
|
374
|
+
# That way we'd be able to attach methods to the Filter type.
|
|
375
|
+
# e.g. replace load_filters(...) with Filter.load(...)
|
|
376
|
+
Filter = Annotated[
|
|
377
|
+
Union[
|
|
378
|
+
Annotated[_And, Tag(_And._field_discriminator())],
|
|
379
|
+
Annotated[_Or, Tag(_Or._field_discriminator())],
|
|
380
|
+
Annotated[_Not, Tag(_Not._field_discriminator())],
|
|
381
|
+
Annotated[_EntityTypeFilter, Tag(_EntityTypeFilter._field_discriminator())],
|
|
382
|
+
Annotated[
|
|
383
|
+
_EntitySubtypeFilter, Tag(_EntitySubtypeFilter._field_discriminator())
|
|
384
|
+
],
|
|
385
|
+
Annotated[_StatusFilter, Tag(_StatusFilter._field_discriminator())],
|
|
386
|
+
Annotated[_PlatformFilter, Tag(_PlatformFilter._field_discriminator())],
|
|
387
|
+
Annotated[_DomainFilter, Tag(_DomainFilter._field_discriminator())],
|
|
388
|
+
Annotated[_EnvFilter, Tag(_EnvFilter._field_discriminator())],
|
|
389
|
+
Annotated[_CustomCondition, Tag(_CustomCondition._field_discriminator())],
|
|
390
|
+
],
|
|
391
|
+
Discriminator(_filter_discriminator),
|
|
392
|
+
]
|
|
393
|
+
|
|
394
|
+
# Required to resolve forward references to "Filter"
|
|
395
|
+
_And.model_rebuild() # type: ignore
|
|
396
|
+
_Or.model_rebuild() # type: ignore
|
|
397
|
+
_Not.model_rebuild() # type: ignore
|
|
330
398
|
|
|
331
399
|
|
|
332
400
|
def load_filters(obj: Any) -> Filter:
|
datahub/upgrade/upgrade.py
CHANGED
|
@@ -7,7 +7,7 @@ from typing import Any, Callable, Optional, Tuple, TypeVar
|
|
|
7
7
|
|
|
8
8
|
import click
|
|
9
9
|
import humanfriendly
|
|
10
|
-
from packaging.version import Version
|
|
10
|
+
from packaging.version import InvalidVersion, Version
|
|
11
11
|
from pydantic import BaseModel
|
|
12
12
|
|
|
13
13
|
from datahub._version import __version__
|
|
@@ -28,6 +28,18 @@ class VersionStats(BaseModel, arbitrary_types_allowed=True):
|
|
|
28
28
|
release_date: Optional[datetime] = None
|
|
29
29
|
|
|
30
30
|
|
|
31
|
+
def _safe_version_stats(version_string: str) -> Optional[VersionStats]:
|
|
32
|
+
"""
|
|
33
|
+
Safely create a VersionStats object from a version string.
|
|
34
|
+
Returns None if the version string is invalid.
|
|
35
|
+
"""
|
|
36
|
+
try:
|
|
37
|
+
return VersionStats(version=Version(version_string), release_date=None)
|
|
38
|
+
except InvalidVersion:
|
|
39
|
+
log.warning(f"Invalid version format received: {version_string!r}")
|
|
40
|
+
return None
|
|
41
|
+
|
|
42
|
+
|
|
31
43
|
class ServerVersionStats(BaseModel):
|
|
32
44
|
current: VersionStats
|
|
33
45
|
latest: Optional[VersionStats] = None
|
|
@@ -233,10 +245,7 @@ async def _retrieve_version_stats(
|
|
|
233
245
|
version=current_server_version, release_date=current_server_release_date
|
|
234
246
|
),
|
|
235
247
|
current_server_default_cli_version=(
|
|
236
|
-
|
|
237
|
-
version=Version(current_server_default_cli_version),
|
|
238
|
-
release_date=None,
|
|
239
|
-
)
|
|
248
|
+
_safe_version_stats(current_server_default_cli_version)
|
|
240
249
|
if current_server_default_cli_version
|
|
241
250
|
else None
|
|
242
251
|
),
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|