apache-airflow-providers-postgres 6.3.0__py3-none-any.whl → 6.4.1rc1__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.
@@ -29,7 +29,7 @@ from airflow import __version__ as airflow_version
29
29
 
30
30
  __all__ = ["__version__"]
31
31
 
32
- __version__ = "6.3.0"
32
+ __version__ = "6.4.1"
33
33
 
34
34
  if packaging.version.parse(packaging.version.parse(airflow_version).base_version) < packaging.version.parse(
35
35
  "2.10.0"
@@ -41,24 +41,21 @@ class PostgresDialect(Dialect):
41
41
  """
42
42
  if schema is None:
43
43
  table, schema = self.extract_schema_from_table(table)
44
- pk_columns = [
45
- row[0]
46
- for row in self.get_records(
47
- """
48
- select kcu.column_name
49
- from information_schema.table_constraints tco
50
- join information_schema.key_column_usage kcu
51
- on kcu.constraint_name = tco.constraint_name
52
- and kcu.constraint_schema = tco.constraint_schema
53
- and kcu.constraint_name = tco.constraint_name
54
- where tco.constraint_type = 'PRIMARY KEY'
55
- and kcu.table_schema = %s
56
- and kcu.table_name = %s
57
- order by kcu.ordinal_position
58
- """,
59
- (self.unescape_word(schema), self.unescape_word(table)),
60
- )
61
- ]
44
+ table = self.unescape_word(table) or table
45
+ schema = self.unescape_word(schema) if schema else None
46
+ query = """
47
+ select kcu.column_name
48
+ from information_schema.table_constraints tco
49
+ join information_schema.key_column_usage kcu
50
+ on kcu.constraint_name = tco.constraint_name
51
+ and kcu.constraint_schema = tco.constraint_schema
52
+ and kcu.constraint_name = tco.constraint_name
53
+ where tco.constraint_type = 'PRIMARY KEY'
54
+ and kcu.table_schema = %s
55
+ and kcu.table_name = %s
56
+ order by kcu.ordinal_position
57
+ """
58
+ pk_columns = [row[0] for row in self.get_records(query, (schema, table))]
62
59
  return pk_columns or None
63
60
 
64
61
  @staticmethod
@@ -78,31 +75,27 @@ class PostgresDialect(Dialect):
78
75
  ) -> list[str] | None:
79
76
  if schema is None:
80
77
  table, schema = self.extract_schema_from_table(table)
81
-
82
- column_names = list(
83
- row["name"]
84
- for row in filter(
85
- predicate,
86
- map(
87
- self._to_row,
88
- self.get_records(
89
- """
90
- select column_name,
91
- data_type,
92
- is_nullable,
93
- column_default,
94
- is_generated,
95
- is_identity
96
- from information_schema.columns
97
- where table_schema = %s
98
- and table_name = %s
99
- order by ordinal_position
100
- """,
101
- (self.unescape_word(schema), self.unescape_word(table)),
102
- ),
103
- ),
104
- )
105
- )
78
+ table = self.unescape_word(table) or table
79
+ schema = self.unescape_word(schema) if schema else None
80
+ query = """
81
+ select column_name,
82
+ data_type,
83
+ is_nullable,
84
+ column_default,
85
+ is_generated,
86
+ is_identity
87
+ from information_schema.columns
88
+ where table_schema = %s
89
+ and table_name = %s
90
+ order by ordinal_position
91
+ """
92
+ column_names = []
93
+ for row in map(
94
+ self._to_row,
95
+ self.get_records(query, (schema, table)),
96
+ ):
97
+ if predicate(row):
98
+ column_names.append(row["name"])
106
99
  self.log.debug("Column names for table '%s': %s", table, column_names)
107
100
  return column_names
108
101
 
@@ -65,4 +65,18 @@ def get_provider_info():
65
65
  "handler": "airflow.providers.postgres.assets.postgres.sanitize_uri",
66
66
  }
67
67
  ],
68
+ "config": {
69
+ "postgres": {
70
+ "description": "Configuration for Postgres hooks and operators.\n",
71
+ "options": {
72
+ "azure_oauth_scope": {
73
+ "description": "The scope to use while retrieving Oauth token for Postgres Flexible Server\nfrom Azure Entra authentication.\n",
74
+ "version_added": "6.4.0",
75
+ "type": "string",
76
+ "example": None,
77
+ "default": "https://ossrdbms-aad.database.windows.net/.default",
78
+ }
79
+ },
80
+ }
81
+ },
68
82
  }
@@ -24,16 +24,17 @@ from copy import deepcopy
24
24
  from typing import TYPE_CHECKING, Any, Literal, Protocol, TypeAlias, cast, overload
25
25
 
26
26
  import psycopg2
27
- import psycopg2.extensions
28
27
  import psycopg2.extras
29
28
  from more_itertools import chunked
30
29
  from psycopg2.extras import DictCursor, NamedTupleCursor, RealDictCursor, execute_batch
31
30
  from sqlalchemy.engine import URL
32
31
 
32
+ from airflow.configuration import conf
33
33
  from airflow.exceptions import (
34
34
  AirflowException,
35
35
  AirflowOptionalProviderFeatureException,
36
36
  )
37
+ from airflow.providers.common.compat.sdk import Connection
37
38
  from airflow.providers.common.sql.hooks.sql import DbApiHook
38
39
  from airflow.providers.postgres.dialects.postgres import PostgresDialect
39
40
 
@@ -64,11 +65,6 @@ if TYPE_CHECKING:
64
65
  if USE_PSYCOPG3:
65
66
  from psycopg.errors import Diagnostic
66
67
 
67
- try:
68
- from airflow.sdk import Connection
69
- except ImportError:
70
- from airflow.models.connection import Connection # type: ignore[assignment]
71
-
72
68
  CursorType: TypeAlias = DictCursor | RealDictCursor | NamedTupleCursor
73
69
  CursorRow: TypeAlias = dict[str, Any] | tuple[Any, ...]
74
70
 
@@ -156,7 +152,9 @@ class PostgresHook(DbApiHook):
156
152
  "aws_conn_id",
157
153
  "sqlalchemy_scheme",
158
154
  "sqlalchemy_query",
155
+ "azure_conn_id",
159
156
  }
157
+ default_azure_oauth_scope = "https://ossrdbms-aad.database.windows.net/.default"
160
158
 
161
159
  def __init__(
162
160
  self, *args, options: str | None = None, enable_log_db_messages: bool = False, **kwargs
@@ -177,6 +175,8 @@ class PostgresHook(DbApiHook):
177
175
  query = conn.extra_dejson.get("sqlalchemy_query", {})
178
176
  if not isinstance(query, dict):
179
177
  raise AirflowException("The parameter 'sqlalchemy_query' must be of type dict!")
178
+ if conn.extra_dejson.get("iam", False):
179
+ conn.login, conn.password, conn.port = self.get_iam_token(conn)
180
180
  return URL.create(
181
181
  drivername="postgresql+psycopg" if USE_PSYCOPG3 else "postgresql",
182
182
  username=self.__cast_nullable(conn.login, str),
@@ -441,8 +441,14 @@ class PostgresHook(DbApiHook):
441
441
  return PostgresHook._serialize_cell_ppg2(cell, conn)
442
442
 
443
443
  def get_iam_token(self, conn: Connection) -> tuple[str, str, int]:
444
+ """Get the IAM token from different identity providers."""
445
+ if conn.extra_dejson.get("azure_conn_id"):
446
+ return self.get_azure_iam_token(conn)
447
+ return self.get_aws_iam_token(conn)
448
+
449
+ def get_aws_iam_token(self, conn: Connection) -> tuple[str, str, int]:
444
450
  """
445
- Get the IAM token.
451
+ Get the AWS IAM token.
446
452
 
447
453
  This uses AWSHook to retrieve a temporary password to connect to
448
454
  Postgres or Redshift. Port is required. If none is provided, the default
@@ -500,6 +506,34 @@ class PostgresHook(DbApiHook):
500
506
  token = rds_client.generate_db_auth_token(conn.host, port, conn.login)
501
507
  return cast("str", login), cast("str", token), port
502
508
 
509
+ def get_azure_iam_token(self, conn: Connection) -> tuple[str, str, int]:
510
+ """
511
+ Get the Azure IAM token.
512
+
513
+ This uses AzureBaseHook to retrieve an OAUTH token to connect to Postgres.
514
+ Scope for the OAuth token can be set in the config option ``azure_oauth_scope`` under the section ``[postgres]``.
515
+ """
516
+ if TYPE_CHECKING:
517
+ from airflow.providers.microsoft.azure.hooks.base_azure import AzureBaseHook
518
+
519
+ azure_conn_id = conn.extra_dejson.get("azure_conn_id", "azure_default")
520
+ try:
521
+ azure_conn = Connection.get(azure_conn_id)
522
+ except AttributeError:
523
+ azure_conn = Connection.get_connection_from_secrets(azure_conn_id) # type: ignore[attr-defined]
524
+ try:
525
+ azure_base_hook: AzureBaseHook = azure_conn.get_hook()
526
+ except TypeError as e:
527
+ if "required positional argument: 'sdk_client'" in str(e):
528
+ raise AirflowOptionalProviderFeatureException(
529
+ "Getting azure token is not supported by current version of 'AzureBaseHook'. "
530
+ "Please upgrade apache-airflow-providers-microsoft-azure>=12.8.0"
531
+ ) from e
532
+ raise
533
+ scope = conf.get("postgres", "azure_oauth_scope", fallback=self.default_azure_oauth_scope)
534
+ token = azure_base_hook.get_token(scope).token
535
+ return cast("str", conn.login or azure_conn.login), token, conn.port or 5432
536
+
503
537
  def get_table_primary_key(self, table: str, schema: str | None = "public") -> list[str] | None:
504
538
  """
505
539
  Get the table's primary key.
@@ -1,12 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apache-airflow-providers-postgres
3
- Version: 6.3.0
3
+ Version: 6.4.1rc1
4
4
  Summary: Provider package apache-airflow-providers-postgres for Apache Airflow
5
5
  Keywords: airflow-provider,postgres,airflow,integration
6
6
  Author-email: Apache Software Foundation <dev@airflow.apache.org>
7
7
  Maintainer-email: Apache Software Foundation <dev@airflow.apache.org>
8
8
  Requires-Python: >=3.10
9
9
  Description-Content-Type: text/x-rst
10
+ License-Expression: Apache-2.0
10
11
  Classifier: Development Status :: 5 - Production/Stable
11
12
  Classifier: Environment :: Console
12
13
  Classifier: Environment :: Web Environment
@@ -14,31 +15,35 @@ Classifier: Intended Audience :: Developers
14
15
  Classifier: Intended Audience :: System Administrators
15
16
  Classifier: Framework :: Apache Airflow
16
17
  Classifier: Framework :: Apache Airflow :: Provider
17
- Classifier: License :: OSI Approved :: Apache Software License
18
18
  Classifier: Programming Language :: Python :: 3.10
19
19
  Classifier: Programming Language :: Python :: 3.11
20
20
  Classifier: Programming Language :: Python :: 3.12
21
21
  Classifier: Programming Language :: Python :: 3.13
22
22
  Classifier: Topic :: System :: Monitoring
23
- Requires-Dist: apache-airflow>=2.10.0
24
- Requires-Dist: apache-airflow-providers-common-sql>=1.23.0
23
+ License-File: LICENSE
24
+ License-File: NOTICE
25
+ Requires-Dist: apache-airflow>=2.10.0rc1
26
+ Requires-Dist: apache-airflow-providers-common-compat>=1.8.0rc1
27
+ Requires-Dist: apache-airflow-providers-common-sql>=1.23.0rc1
25
28
  Requires-Dist: psycopg2-binary>=2.9.9; python_version < '3.13'
26
29
  Requires-Dist: psycopg2-binary>=2.9.10; python_version >= '3.13'
27
30
  Requires-Dist: asyncpg>=0.30.0
28
- Requires-Dist: apache-airflow-providers-amazon>=2.6.0 ; extra == "amazon"
31
+ Requires-Dist: apache-airflow-providers-amazon>=2.6.0rc1 ; extra == "amazon"
32
+ Requires-Dist: apache-airflow-providers-microsoft-azure>=12.8.0rc1 ; extra == "microsoft-azure"
29
33
  Requires-Dist: apache-airflow-providers-openlineage ; extra == "openlineage"
30
34
  Requires-Dist: pandas>=2.1.2 ; extra == "pandas" and ( python_version <"3.13")
31
35
  Requires-Dist: pandas>=2.2.3 ; extra == "pandas" and ( python_version >="3.13")
32
36
  Requires-Dist: polars>=1.26.0 ; extra == "polars"
33
37
  Requires-Dist: psycopg[binary]>=3.2.9 ; extra == "psycopg"
34
38
  Project-URL: Bug Tracker, https://github.com/apache/airflow/issues
35
- Project-URL: Changelog, https://airflow.apache.org/docs/apache-airflow-providers-postgres/6.3.0/changelog.html
36
- Project-URL: Documentation, https://airflow.apache.org/docs/apache-airflow-providers-postgres/6.3.0
39
+ Project-URL: Changelog, https://airflow.staged.apache.org/docs/apache-airflow-providers-postgres/6.4.1/changelog.html
40
+ Project-URL: Documentation, https://airflow.staged.apache.org/docs/apache-airflow-providers-postgres/6.4.1
37
41
  Project-URL: Mastodon, https://fosstodon.org/@airflow
38
42
  Project-URL: Slack Chat, https://s.apache.org/airflow-slack
39
43
  Project-URL: Source Code, https://github.com/apache/airflow
40
44
  Project-URL: YouTube, https://www.youtube.com/channel/UCSXwxpWZQ7XZ1WL3wqevChA/
41
45
  Provides-Extra: amazon
46
+ Provides-Extra: microsoft-azure
42
47
  Provides-Extra: openlineage
43
48
  Provides-Extra: pandas
44
49
  Provides-Extra: polars
@@ -69,7 +74,7 @@ Provides-Extra: psycopg
69
74
 
70
75
  Package ``apache-airflow-providers-postgres``
71
76
 
72
- Release: ``6.3.0``
77
+ Release: ``6.4.1``
73
78
 
74
79
 
75
80
  `PostgreSQL <https://www.postgresql.org/>`__
@@ -82,7 +87,7 @@ This is a provider package for ``postgres`` provider. All classes for this provi
82
87
  are in ``airflow.providers.postgres`` python package.
83
88
 
84
89
  You can find package information and changelog for the provider
85
- in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-postgres/6.3.0/>`_.
90
+ in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-postgres/6.4.1/>`_.
86
91
 
87
92
  Installation
88
93
  ------------
@@ -96,15 +101,16 @@ The package supports the following python versions: 3.10,3.11,3.12,3.13
96
101
  Requirements
97
102
  ------------
98
103
 
99
- ======================================= ======================================
100
- PIP package Version required
101
- ======================================= ======================================
102
- ``apache-airflow`` ``>=2.10.0``
103
- ``apache-airflow-providers-common-sql`` ``>=1.23.0``
104
- ``psycopg2-binary`` ``>=2.9.9; python_version < "3.13"``
105
- ``psycopg2-binary`` ``>=2.9.10; python_version >= "3.13"``
106
- ``asyncpg`` ``>=0.30.0``
107
- ======================================= ======================================
104
+ ========================================== ======================================
105
+ PIP package Version required
106
+ ========================================== ======================================
107
+ ``apache-airflow`` ``>=2.10.0``
108
+ ``apache-airflow-providers-common-compat`` ``>=1.8.0``
109
+ ``apache-airflow-providers-common-sql`` ``>=1.23.0``
110
+ ``psycopg2-binary`` ``>=2.9.9; python_version < "3.13"``
111
+ ``psycopg2-binary`` ``>=2.9.10; python_version >= "3.13"``
112
+ ``asyncpg`` ``>=0.30.0``
113
+ ========================================== ======================================
108
114
 
109
115
  Cross provider package dependencies
110
116
  -----------------------------------
@@ -119,14 +125,30 @@ You can install such cross-provider dependencies when installing from PyPI. For
119
125
  pip install apache-airflow-providers-postgres[amazon]
120
126
 
121
127
 
122
- ============================================================================================================== ===============
123
- Dependent package Extra
124
- ============================================================================================================== ===============
125
- `apache-airflow-providers-amazon <https://airflow.apache.org/docs/apache-airflow-providers-amazon>`_ ``amazon``
126
- `apache-airflow-providers-common-sql <https://airflow.apache.org/docs/apache-airflow-providers-common-sql>`_ ``common.sql``
127
- `apache-airflow-providers-openlineage <https://airflow.apache.org/docs/apache-airflow-providers-openlineage>`_ ``openlineage``
128
- ============================================================================================================== ===============
128
+ ====================================================================================================================== ===================
129
+ Dependent package Extra
130
+ ====================================================================================================================== ===================
131
+ `apache-airflow-providers-amazon <https://airflow.apache.org/docs/apache-airflow-providers-amazon>`_ ``amazon``
132
+ `apache-airflow-providers-common-compat <https://airflow.apache.org/docs/apache-airflow-providers-common-compat>`_ ``common.compat``
133
+ `apache-airflow-providers-common-sql <https://airflow.apache.org/docs/apache-airflow-providers-common-sql>`_ ``common.sql``
134
+ `apache-airflow-providers-microsoft-azure <https://airflow.apache.org/docs/apache-airflow-providers-microsoft-azure>`_ ``microsoft.azure``
135
+ `apache-airflow-providers-openlineage <https://airflow.apache.org/docs/apache-airflow-providers-openlineage>`_ ``openlineage``
136
+ ====================================================================================================================== ===================
137
+
138
+ Optional dependencies
139
+ ----------------------
140
+
141
+ =================== =====================================================================================
142
+ Extra Dependencies
143
+ =================== =====================================================================================
144
+ ``amazon`` ``apache-airflow-providers-amazon>=2.6.0``
145
+ ``microsoft.azure`` ``apache-airflow-providers-microsoft-azure>=12.8.0``
146
+ ``openlineage`` ``apache-airflow-providers-openlineage``
147
+ ``pandas`` ``pandas>=2.1.2; python_version <"3.13"``, ``pandas>=2.2.3; python_version >="3.13"``
148
+ ``polars`` ``polars>=1.26.0``
149
+ ``psycopg`` ``psycopg[binary]>=3.2.9``
150
+ =================== =====================================================================================
129
151
 
130
152
  The changelog for the provider package can be found in the
131
- `changelog <https://airflow.apache.org/docs/apache-airflow-providers-postgres/6.3.0/changelog.html>`_.
153
+ `changelog <https://airflow.apache.org/docs/apache-airflow-providers-postgres/6.4.1/changelog.html>`_.
132
154
 
@@ -0,0 +1,14 @@
1
+ airflow/providers/postgres/__init__.py,sha256=CbYIEGsVSqkb8BiKTcIUh-DPdfj6HwFI42gQ9bvRcE8,1497
2
+ airflow/providers/postgres/get_provider_info.py,sha256=tLd8Kw5q9bE0XewMKJ4zzwYQoPh_G-E3mmFxK8QzfB0,3269
3
+ airflow/providers/postgres/assets/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
4
+ airflow/providers/postgres/assets/postgres.py,sha256=XNhOJCbOA_soaaiS73JjULMqAM_7PBryhToe8FJREA0,1522
5
+ airflow/providers/postgres/dialects/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
6
+ airflow/providers/postgres/dialects/postgres.py,sha256=bsliwzooipmgluJsjGHYQHfZNWYxzzZ3WvaBLAy3u3A,5332
7
+ airflow/providers/postgres/hooks/__init__.py,sha256=mlJxuZLkd5x-iq2SBwD3mvRQpt3YR7wjz_nceyF1IaI,787
8
+ airflow/providers/postgres/hooks/postgres.py,sha256=zjAJzkhMEae5cJxVl4KHcmdev2YRuTkpWytuH7UgwPY,28800
9
+ apache_airflow_providers_postgres-6.4.1rc1.dist-info/entry_points.txt,sha256=dhtJi6PTWHd6BwKhmI4OtSPvQVI_p0yYWI0eba83HqY,104
10
+ apache_airflow_providers_postgres-6.4.1rc1.dist-info/licenses/LICENSE,sha256=gXPVwptPlW1TJ4HSuG5OMPg-a3h43OGMkZRR1rpwfJA,10850
11
+ apache_airflow_providers_postgres-6.4.1rc1.dist-info/licenses/NOTICE,sha256=E3-_E02gwwSEFzeeWPKmnIjOoos3hW28CLISV6sYrbQ,168
12
+ apache_airflow_providers_postgres-6.4.1rc1.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
13
+ apache_airflow_providers_postgres-6.4.1rc1.dist-info/METADATA,sha256=_EtjUCijBJbk-tgkMGViVqCzaIpIGEwl4RQrYHx-c24,7738
14
+ apache_airflow_providers_postgres-6.4.1rc1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Apache Airflow
2
+ Copyright 2016-2025 The Apache Software Foundation
3
+
4
+ This product includes software developed at
5
+ The Apache Software Foundation (http://www.apache.org/).
@@ -1,13 +0,0 @@
1
- airflow/providers/postgres/LICENSE,sha256=gXPVwptPlW1TJ4HSuG5OMPg-a3h43OGMkZRR1rpwfJA,10850
2
- airflow/providers/postgres/__init__.py,sha256=EBlBQkd4wsb32h6i--UVow1UxLY3oTKzALQLc1L5W7s,1497
3
- airflow/providers/postgres/get_provider_info.py,sha256=qEEYbClLY3-NH40dBk2u_nOIfvfEIHdXaWsIJ8J5Z68,2626
4
- airflow/providers/postgres/assets/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
5
- airflow/providers/postgres/assets/postgres.py,sha256=XNhOJCbOA_soaaiS73JjULMqAM_7PBryhToe8FJREA0,1522
6
- airflow/providers/postgres/dialects/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
7
- airflow/providers/postgres/dialects/postgres.py,sha256=WhRMbSQv2u373R62e3buE5J1L3j-XGHhZxrWc8Gtc5s,5551
8
- airflow/providers/postgres/hooks/__init__.py,sha256=mlJxuZLkd5x-iq2SBwD3mvRQpt3YR7wjz_nceyF1IaI,787
9
- airflow/providers/postgres/hooks/postgres.py,sha256=YwA99YPz_ZpCvBn5yyw4ykhJ9hMGNvEsMmAf5nsfVE8,26908
10
- apache_airflow_providers_postgres-6.3.0.dist-info/entry_points.txt,sha256=dhtJi6PTWHd6BwKhmI4OtSPvQVI_p0yYWI0eba83HqY,104
11
- apache_airflow_providers_postgres-6.3.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
12
- apache_airflow_providers_postgres-6.3.0.dist-info/METADATA,sha256=ndnpXUFB9vCAeT4wp6MVzJI4mxgr4KxmCO8NUA4qkIk,6283
13
- apache_airflow_providers_postgres-6.3.0.dist-info/RECORD,,