cloud-sql-python-connector 1.13.0__tar.gz → 1.15.0__tar.gz
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.
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/PKG-INFO +147 -13
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/README.md +144 -11
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/cloud_sql_python_connector.egg-info/PKG-INFO +147 -13
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/cloud_sql_python_connector.egg-info/SOURCES.txt +2 -0
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/cloud_sql_python_connector.egg-info/requires.txt +2 -1
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/google/cloud/sql/connector/__init__.py +4 -0
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/google/cloud/sql/connector/asyncpg.py +1 -0
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/google/cloud/sql/connector/client.py +40 -20
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/google/cloud/sql/connector/connection_info.py +4 -2
- cloud_sql_python_connector-1.15.0/google/cloud/sql/connector/connection_name.py +61 -0
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/google/cloud/sql/connector/connector.py +20 -15
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/google/cloud/sql/connector/exceptions.py +7 -0
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/google/cloud/sql/connector/instance.py +15 -52
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/google/cloud/sql/connector/lazy.py +11 -19
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/google/cloud/sql/connector/pg8000.py +1 -0
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/google/cloud/sql/connector/pymysql.py +1 -0
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/google/cloud/sql/connector/pytds.py +1 -0
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/google/cloud/sql/connector/refresh_utils.py +3 -3
- cloud_sql_python_connector-1.15.0/google/cloud/sql/connector/resolver.py +70 -0
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/google/cloud/sql/connector/utils.py +2 -4
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/google/cloud/sql/connector/version.py +1 -1
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/setup.py +2 -1
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/LICENSE +0 -0
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/cloud_sql_python_connector.egg-info/dependency_links.txt +0 -0
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/cloud_sql_python_connector.egg-info/not-zip-safe +0 -0
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/cloud_sql_python_connector.egg-info/top_level.txt +0 -0
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/google/cloud/sql/connector/enums.py +0 -0
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/google/cloud/sql/connector/py.typed +0 -0
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/google/cloud/sql/connector/rate_limiter.py +0 -0
- {cloud_sql_python_connector-1.13.0 → cloud_sql_python_connector-1.15.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cloud-sql-python-connector
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.15.0
|
|
4
4
|
Summary: The Cloud SQL Python Connector is a library that can be used alongside a database driver to allow users with sufficient permissions to connect to a Cloud SQL database without having to manually allowlist IPs or manage SSL certificates.
|
|
5
5
|
Home-page: https://github.com/GoogleCloudPlatform/cloud-sql-python-connector
|
|
6
6
|
Author: Google LLC
|
|
@@ -22,6 +22,7 @@ License-File: LICENSE
|
|
|
22
22
|
Requires-Dist: aiofiles
|
|
23
23
|
Requires-Dist: aiohttp
|
|
24
24
|
Requires-Dist: cryptography>=42.0.0
|
|
25
|
+
Requires-Dist: dnspython>=2.0.0
|
|
25
26
|
Requires-Dist: Requests
|
|
26
27
|
Requires-Dist: google-auth>=2.28.0
|
|
27
28
|
Provides-Extra: pymysql
|
|
@@ -31,7 +32,7 @@ Requires-Dist: pg8000>=1.31.1; extra == "pg8000"
|
|
|
31
32
|
Provides-Extra: pytds
|
|
32
33
|
Requires-Dist: python-tds>=1.15.0; extra == "pytds"
|
|
33
34
|
Provides-Extra: asyncpg
|
|
34
|
-
Requires-Dist: asyncpg>=0.
|
|
35
|
+
Requires-Dist: asyncpg>=0.30.0; extra == "asyncpg"
|
|
35
36
|
|
|
36
37
|
<p align="center">
|
|
37
38
|
<a href="https://cloud.google.com/blog/topics/developers-practitioners/how-connect-cloud-sql-using-python-easy-way">
|
|
@@ -400,6 +401,69 @@ conn = connector.connect(
|
|
|
400
401
|
)
|
|
401
402
|
```
|
|
402
403
|
|
|
404
|
+
### Using DNS domain names to identify instances
|
|
405
|
+
|
|
406
|
+
The connector can be configured to use DNS to look up an instance. This would
|
|
407
|
+
allow you to configure your application to connect to a database instance, and
|
|
408
|
+
centrally configure which instance in your DNS zone.
|
|
409
|
+
|
|
410
|
+
#### Configure your DNS Records
|
|
411
|
+
|
|
412
|
+
Add a DNS TXT record for the Cloud SQL instance to a **private** DNS server
|
|
413
|
+
or a private Google Cloud DNS Zone used by your application.
|
|
414
|
+
|
|
415
|
+
> [!NOTE]
|
|
416
|
+
>
|
|
417
|
+
> You are strongly discouraged from adding DNS records for your
|
|
418
|
+
> Cloud SQL instances to a public DNS server. This would allow anyone on the
|
|
419
|
+
> internet to discover the Cloud SQL instance name.
|
|
420
|
+
|
|
421
|
+
For example: suppose you wanted to use the domain name
|
|
422
|
+
`prod-db.mycompany.example.com` to connect to your database instance
|
|
423
|
+
`my-project:region:my-instance`. You would create the following DNS record:
|
|
424
|
+
|
|
425
|
+
* Record type: `TXT`
|
|
426
|
+
* Name: `prod-db.mycompany.example.com` – This is the domain name used by the application
|
|
427
|
+
* Value: `my-project:my-region:my-instance` – This is the Cloud SQL instance connection name
|
|
428
|
+
|
|
429
|
+
#### Configure the connector
|
|
430
|
+
|
|
431
|
+
Configure the connector to resolve DNS names by initializing it with
|
|
432
|
+
`resolver=DnsResolver` and replacing the instance connection name with the DNS
|
|
433
|
+
name in `connector.connect`:
|
|
434
|
+
|
|
435
|
+
```python
|
|
436
|
+
from google.cloud.sql.connector import Connector, DnsResolver
|
|
437
|
+
import pymysql
|
|
438
|
+
import sqlalchemy
|
|
439
|
+
|
|
440
|
+
# helper function to return SQLAlchemy connection pool
|
|
441
|
+
def init_connection_pool(connector: Connector) -> sqlalchemy.engine.Engine:
|
|
442
|
+
# function used to generate database connection
|
|
443
|
+
def getconn() -> pymysql.connections.Connection:
|
|
444
|
+
conn = connector.connect(
|
|
445
|
+
"prod-db.mycompany.example.com", # using DNS name
|
|
446
|
+
"pymysql",
|
|
447
|
+
user="my-user",
|
|
448
|
+
password="my-password",
|
|
449
|
+
db="my-db-name"
|
|
450
|
+
)
|
|
451
|
+
return conn
|
|
452
|
+
|
|
453
|
+
# create connection pool
|
|
454
|
+
pool = sqlalchemy.create_engine(
|
|
455
|
+
"mysql+pymysql://",
|
|
456
|
+
creator=getconn,
|
|
457
|
+
)
|
|
458
|
+
return pool
|
|
459
|
+
|
|
460
|
+
# initialize Cloud SQL Python Connector with `resolver=DnsResolver`
|
|
461
|
+
with Connector(resolver=DnsResolver) as connector:
|
|
462
|
+
# initialize connection pool
|
|
463
|
+
pool = init_connection_pool(connector)
|
|
464
|
+
# ... use SQLAlchemy engine normally
|
|
465
|
+
```
|
|
466
|
+
|
|
403
467
|
### Using the Python Connector with Python Web Frameworks
|
|
404
468
|
|
|
405
469
|
The Python Connector can be used alongside popular Python web frameworks such
|
|
@@ -537,6 +601,42 @@ The `create_async_connector` allows all the same input arguments as the
|
|
|
537
601
|
Once a `Connector` object is returned by `create_async_connector` you can call
|
|
538
602
|
its `connect_async` method, just as you would the `connect` method:
|
|
539
603
|
|
|
604
|
+
#### Asyncpg Connection Pool
|
|
605
|
+
|
|
606
|
+
```python
|
|
607
|
+
import asyncpg
|
|
608
|
+
from google.cloud.sql.connector import Connector, create_async_connector
|
|
609
|
+
|
|
610
|
+
async def main():
|
|
611
|
+
# initialize Connector object for connections to Cloud SQL
|
|
612
|
+
connector = create_async_connector()
|
|
613
|
+
|
|
614
|
+
# creation function to generate asyncpg connections as the 'connect' arg
|
|
615
|
+
async def getconn(instance_connection_name, **kwargs) -> asyncpg.Connection:
|
|
616
|
+
return await connector.connect_async(
|
|
617
|
+
instance_connection_name,
|
|
618
|
+
"asyncpg",
|
|
619
|
+
user="my-user",
|
|
620
|
+
password="my-password",
|
|
621
|
+
db="my-db",
|
|
622
|
+
**kwargs, # ... additional asyncpg args
|
|
623
|
+
)
|
|
624
|
+
|
|
625
|
+
# initialize connection pool
|
|
626
|
+
pool = await asyncpg.create_pool(
|
|
627
|
+
"my-project:my-region:my-instance", connect=getconn
|
|
628
|
+
)
|
|
629
|
+
|
|
630
|
+
# acquire connection and query Cloud SQL database
|
|
631
|
+
async with pool.acquire() as conn:
|
|
632
|
+
res = await conn.fetch("SELECT NOW()")
|
|
633
|
+
|
|
634
|
+
# close Connector
|
|
635
|
+
await connector.close_async()
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
#### SQLAlchemy Async Engine
|
|
639
|
+
|
|
540
640
|
```python
|
|
541
641
|
import asyncpg
|
|
542
642
|
|
|
@@ -546,7 +646,7 @@ from sqlalchemy.ext.asyncio import AsyncEngine, create_async_engine
|
|
|
546
646
|
from google.cloud.sql.connector import Connector, create_async_connector
|
|
547
647
|
|
|
548
648
|
async def init_connection_pool(connector: Connector) -> AsyncEngine:
|
|
549
|
-
#
|
|
649
|
+
# creation function to generate asyncpg connections as 'async_creator' arg
|
|
550
650
|
async def getconn() -> asyncpg.Connection:
|
|
551
651
|
conn: asyncpg.Connection = await connector.connect_async(
|
|
552
652
|
"project:region:instance", # Cloud SQL instance connection name
|
|
@@ -599,6 +699,40 @@ calls to `connector.close_async()` to cleanup resources.
|
|
|
599
699
|
> This alternative requires that the running event loop be
|
|
600
700
|
> passed in as the `loop` argument to `Connector()`.
|
|
601
701
|
|
|
702
|
+
#### Asyncpg Connection Pool
|
|
703
|
+
|
|
704
|
+
```python
|
|
705
|
+
import asyncpg
|
|
706
|
+
from google.cloud.sql.connector import Connector, create_async_connector
|
|
707
|
+
|
|
708
|
+
async def main():
|
|
709
|
+
# initialize Connector object for connections to Cloud SQL
|
|
710
|
+
loop = asyncio.get_running_loop()
|
|
711
|
+
async with Connector(loop=loop) as connector:
|
|
712
|
+
|
|
713
|
+
# creation function to generate asyncpg connections as the 'connect' arg
|
|
714
|
+
async def getconn(instance_connection_name, **kwargs) -> asyncpg.Connection:
|
|
715
|
+
return await connector.connect_async(
|
|
716
|
+
instance_connection_name,
|
|
717
|
+
"asyncpg",
|
|
718
|
+
user="my-user",
|
|
719
|
+
password="my-password",
|
|
720
|
+
db="my-db",
|
|
721
|
+
**kwargs, # ... additional asyncpg args
|
|
722
|
+
)
|
|
723
|
+
|
|
724
|
+
# create connection pool
|
|
725
|
+
pool = await asyncpg.create_pool(
|
|
726
|
+
"my-project:my-region:my-instance", connect=getconn
|
|
727
|
+
)
|
|
728
|
+
|
|
729
|
+
# acquire connection and query Cloud SQL database
|
|
730
|
+
async with pool.acquire() as conn:
|
|
731
|
+
res = await conn.fetch("SELECT NOW()")
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
#### SQLAlchemy Async Engine
|
|
735
|
+
|
|
602
736
|
```python
|
|
603
737
|
import asyncio
|
|
604
738
|
import asyncpg
|
|
@@ -609,17 +743,17 @@ from sqlalchemy.ext.asyncio import AsyncEngine, create_async_engine
|
|
|
609
743
|
from google.cloud.sql.connector import Connector
|
|
610
744
|
|
|
611
745
|
async def init_connection_pool(connector: Connector) -> AsyncEngine:
|
|
612
|
-
#
|
|
746
|
+
# creation function to generate asyncpg connections as 'async_creator' arg
|
|
613
747
|
async def getconn() -> asyncpg.Connection:
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
748
|
+
conn: asyncpg.Connection = await connector.connect_async(
|
|
749
|
+
"project:region:instance", # Cloud SQL instance connection name
|
|
750
|
+
"asyncpg",
|
|
751
|
+
user="my-user",
|
|
752
|
+
password="my-password",
|
|
753
|
+
db="my-db-name"
|
|
754
|
+
# ... additional database driver args
|
|
755
|
+
)
|
|
756
|
+
return conn
|
|
623
757
|
|
|
624
758
|
# The Cloud SQL Python Connector can be used along with SQLAlchemy using the
|
|
625
759
|
# 'async_creator' argument to 'create_async_engine'
|
|
@@ -365,6 +365,69 @@ conn = connector.connect(
|
|
|
365
365
|
)
|
|
366
366
|
```
|
|
367
367
|
|
|
368
|
+
### Using DNS domain names to identify instances
|
|
369
|
+
|
|
370
|
+
The connector can be configured to use DNS to look up an instance. This would
|
|
371
|
+
allow you to configure your application to connect to a database instance, and
|
|
372
|
+
centrally configure which instance in your DNS zone.
|
|
373
|
+
|
|
374
|
+
#### Configure your DNS Records
|
|
375
|
+
|
|
376
|
+
Add a DNS TXT record for the Cloud SQL instance to a **private** DNS server
|
|
377
|
+
or a private Google Cloud DNS Zone used by your application.
|
|
378
|
+
|
|
379
|
+
> [!NOTE]
|
|
380
|
+
>
|
|
381
|
+
> You are strongly discouraged from adding DNS records for your
|
|
382
|
+
> Cloud SQL instances to a public DNS server. This would allow anyone on the
|
|
383
|
+
> internet to discover the Cloud SQL instance name.
|
|
384
|
+
|
|
385
|
+
For example: suppose you wanted to use the domain name
|
|
386
|
+
`prod-db.mycompany.example.com` to connect to your database instance
|
|
387
|
+
`my-project:region:my-instance`. You would create the following DNS record:
|
|
388
|
+
|
|
389
|
+
* Record type: `TXT`
|
|
390
|
+
* Name: `prod-db.mycompany.example.com` – This is the domain name used by the application
|
|
391
|
+
* Value: `my-project:my-region:my-instance` – This is the Cloud SQL instance connection name
|
|
392
|
+
|
|
393
|
+
#### Configure the connector
|
|
394
|
+
|
|
395
|
+
Configure the connector to resolve DNS names by initializing it with
|
|
396
|
+
`resolver=DnsResolver` and replacing the instance connection name with the DNS
|
|
397
|
+
name in `connector.connect`:
|
|
398
|
+
|
|
399
|
+
```python
|
|
400
|
+
from google.cloud.sql.connector import Connector, DnsResolver
|
|
401
|
+
import pymysql
|
|
402
|
+
import sqlalchemy
|
|
403
|
+
|
|
404
|
+
# helper function to return SQLAlchemy connection pool
|
|
405
|
+
def init_connection_pool(connector: Connector) -> sqlalchemy.engine.Engine:
|
|
406
|
+
# function used to generate database connection
|
|
407
|
+
def getconn() -> pymysql.connections.Connection:
|
|
408
|
+
conn = connector.connect(
|
|
409
|
+
"prod-db.mycompany.example.com", # using DNS name
|
|
410
|
+
"pymysql",
|
|
411
|
+
user="my-user",
|
|
412
|
+
password="my-password",
|
|
413
|
+
db="my-db-name"
|
|
414
|
+
)
|
|
415
|
+
return conn
|
|
416
|
+
|
|
417
|
+
# create connection pool
|
|
418
|
+
pool = sqlalchemy.create_engine(
|
|
419
|
+
"mysql+pymysql://",
|
|
420
|
+
creator=getconn,
|
|
421
|
+
)
|
|
422
|
+
return pool
|
|
423
|
+
|
|
424
|
+
# initialize Cloud SQL Python Connector with `resolver=DnsResolver`
|
|
425
|
+
with Connector(resolver=DnsResolver) as connector:
|
|
426
|
+
# initialize connection pool
|
|
427
|
+
pool = init_connection_pool(connector)
|
|
428
|
+
# ... use SQLAlchemy engine normally
|
|
429
|
+
```
|
|
430
|
+
|
|
368
431
|
### Using the Python Connector with Python Web Frameworks
|
|
369
432
|
|
|
370
433
|
The Python Connector can be used alongside popular Python web frameworks such
|
|
@@ -502,6 +565,42 @@ The `create_async_connector` allows all the same input arguments as the
|
|
|
502
565
|
Once a `Connector` object is returned by `create_async_connector` you can call
|
|
503
566
|
its `connect_async` method, just as you would the `connect` method:
|
|
504
567
|
|
|
568
|
+
#### Asyncpg Connection Pool
|
|
569
|
+
|
|
570
|
+
```python
|
|
571
|
+
import asyncpg
|
|
572
|
+
from google.cloud.sql.connector import Connector, create_async_connector
|
|
573
|
+
|
|
574
|
+
async def main():
|
|
575
|
+
# initialize Connector object for connections to Cloud SQL
|
|
576
|
+
connector = create_async_connector()
|
|
577
|
+
|
|
578
|
+
# creation function to generate asyncpg connections as the 'connect' arg
|
|
579
|
+
async def getconn(instance_connection_name, **kwargs) -> asyncpg.Connection:
|
|
580
|
+
return await connector.connect_async(
|
|
581
|
+
instance_connection_name,
|
|
582
|
+
"asyncpg",
|
|
583
|
+
user="my-user",
|
|
584
|
+
password="my-password",
|
|
585
|
+
db="my-db",
|
|
586
|
+
**kwargs, # ... additional asyncpg args
|
|
587
|
+
)
|
|
588
|
+
|
|
589
|
+
# initialize connection pool
|
|
590
|
+
pool = await asyncpg.create_pool(
|
|
591
|
+
"my-project:my-region:my-instance", connect=getconn
|
|
592
|
+
)
|
|
593
|
+
|
|
594
|
+
# acquire connection and query Cloud SQL database
|
|
595
|
+
async with pool.acquire() as conn:
|
|
596
|
+
res = await conn.fetch("SELECT NOW()")
|
|
597
|
+
|
|
598
|
+
# close Connector
|
|
599
|
+
await connector.close_async()
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
#### SQLAlchemy Async Engine
|
|
603
|
+
|
|
505
604
|
```python
|
|
506
605
|
import asyncpg
|
|
507
606
|
|
|
@@ -511,7 +610,7 @@ from sqlalchemy.ext.asyncio import AsyncEngine, create_async_engine
|
|
|
511
610
|
from google.cloud.sql.connector import Connector, create_async_connector
|
|
512
611
|
|
|
513
612
|
async def init_connection_pool(connector: Connector) -> AsyncEngine:
|
|
514
|
-
#
|
|
613
|
+
# creation function to generate asyncpg connections as 'async_creator' arg
|
|
515
614
|
async def getconn() -> asyncpg.Connection:
|
|
516
615
|
conn: asyncpg.Connection = await connector.connect_async(
|
|
517
616
|
"project:region:instance", # Cloud SQL instance connection name
|
|
@@ -564,6 +663,40 @@ calls to `connector.close_async()` to cleanup resources.
|
|
|
564
663
|
> This alternative requires that the running event loop be
|
|
565
664
|
> passed in as the `loop` argument to `Connector()`.
|
|
566
665
|
|
|
666
|
+
#### Asyncpg Connection Pool
|
|
667
|
+
|
|
668
|
+
```python
|
|
669
|
+
import asyncpg
|
|
670
|
+
from google.cloud.sql.connector import Connector, create_async_connector
|
|
671
|
+
|
|
672
|
+
async def main():
|
|
673
|
+
# initialize Connector object for connections to Cloud SQL
|
|
674
|
+
loop = asyncio.get_running_loop()
|
|
675
|
+
async with Connector(loop=loop) as connector:
|
|
676
|
+
|
|
677
|
+
# creation function to generate asyncpg connections as the 'connect' arg
|
|
678
|
+
async def getconn(instance_connection_name, **kwargs) -> asyncpg.Connection:
|
|
679
|
+
return await connector.connect_async(
|
|
680
|
+
instance_connection_name,
|
|
681
|
+
"asyncpg",
|
|
682
|
+
user="my-user",
|
|
683
|
+
password="my-password",
|
|
684
|
+
db="my-db",
|
|
685
|
+
**kwargs, # ... additional asyncpg args
|
|
686
|
+
)
|
|
687
|
+
|
|
688
|
+
# create connection pool
|
|
689
|
+
pool = await asyncpg.create_pool(
|
|
690
|
+
"my-project:my-region:my-instance", connect=getconn
|
|
691
|
+
)
|
|
692
|
+
|
|
693
|
+
# acquire connection and query Cloud SQL database
|
|
694
|
+
async with pool.acquire() as conn:
|
|
695
|
+
res = await conn.fetch("SELECT NOW()")
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
#### SQLAlchemy Async Engine
|
|
699
|
+
|
|
567
700
|
```python
|
|
568
701
|
import asyncio
|
|
569
702
|
import asyncpg
|
|
@@ -574,17 +707,17 @@ from sqlalchemy.ext.asyncio import AsyncEngine, create_async_engine
|
|
|
574
707
|
from google.cloud.sql.connector import Connector
|
|
575
708
|
|
|
576
709
|
async def init_connection_pool(connector: Connector) -> AsyncEngine:
|
|
577
|
-
#
|
|
710
|
+
# creation function to generate asyncpg connections as 'async_creator' arg
|
|
578
711
|
async def getconn() -> asyncpg.Connection:
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
712
|
+
conn: asyncpg.Connection = await connector.connect_async(
|
|
713
|
+
"project:region:instance", # Cloud SQL instance connection name
|
|
714
|
+
"asyncpg",
|
|
715
|
+
user="my-user",
|
|
716
|
+
password="my-password",
|
|
717
|
+
db="my-db-name"
|
|
718
|
+
# ... additional database driver args
|
|
719
|
+
)
|
|
720
|
+
return conn
|
|
588
721
|
|
|
589
722
|
# The Cloud SQL Python Connector can be used along with SQLAlchemy using the
|
|
590
723
|
# 'async_creator' argument to 'create_async_engine'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cloud-sql-python-connector
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.15.0
|
|
4
4
|
Summary: The Cloud SQL Python Connector is a library that can be used alongside a database driver to allow users with sufficient permissions to connect to a Cloud SQL database without having to manually allowlist IPs or manage SSL certificates.
|
|
5
5
|
Home-page: https://github.com/GoogleCloudPlatform/cloud-sql-python-connector
|
|
6
6
|
Author: Google LLC
|
|
@@ -22,6 +22,7 @@ License-File: LICENSE
|
|
|
22
22
|
Requires-Dist: aiofiles
|
|
23
23
|
Requires-Dist: aiohttp
|
|
24
24
|
Requires-Dist: cryptography>=42.0.0
|
|
25
|
+
Requires-Dist: dnspython>=2.0.0
|
|
25
26
|
Requires-Dist: Requests
|
|
26
27
|
Requires-Dist: google-auth>=2.28.0
|
|
27
28
|
Provides-Extra: pymysql
|
|
@@ -31,7 +32,7 @@ Requires-Dist: pg8000>=1.31.1; extra == "pg8000"
|
|
|
31
32
|
Provides-Extra: pytds
|
|
32
33
|
Requires-Dist: python-tds>=1.15.0; extra == "pytds"
|
|
33
34
|
Provides-Extra: asyncpg
|
|
34
|
-
Requires-Dist: asyncpg>=0.
|
|
35
|
+
Requires-Dist: asyncpg>=0.30.0; extra == "asyncpg"
|
|
35
36
|
|
|
36
37
|
<p align="center">
|
|
37
38
|
<a href="https://cloud.google.com/blog/topics/developers-practitioners/how-connect-cloud-sql-using-python-easy-way">
|
|
@@ -400,6 +401,69 @@ conn = connector.connect(
|
|
|
400
401
|
)
|
|
401
402
|
```
|
|
402
403
|
|
|
404
|
+
### Using DNS domain names to identify instances
|
|
405
|
+
|
|
406
|
+
The connector can be configured to use DNS to look up an instance. This would
|
|
407
|
+
allow you to configure your application to connect to a database instance, and
|
|
408
|
+
centrally configure which instance in your DNS zone.
|
|
409
|
+
|
|
410
|
+
#### Configure your DNS Records
|
|
411
|
+
|
|
412
|
+
Add a DNS TXT record for the Cloud SQL instance to a **private** DNS server
|
|
413
|
+
or a private Google Cloud DNS Zone used by your application.
|
|
414
|
+
|
|
415
|
+
> [!NOTE]
|
|
416
|
+
>
|
|
417
|
+
> You are strongly discouraged from adding DNS records for your
|
|
418
|
+
> Cloud SQL instances to a public DNS server. This would allow anyone on the
|
|
419
|
+
> internet to discover the Cloud SQL instance name.
|
|
420
|
+
|
|
421
|
+
For example: suppose you wanted to use the domain name
|
|
422
|
+
`prod-db.mycompany.example.com` to connect to your database instance
|
|
423
|
+
`my-project:region:my-instance`. You would create the following DNS record:
|
|
424
|
+
|
|
425
|
+
* Record type: `TXT`
|
|
426
|
+
* Name: `prod-db.mycompany.example.com` – This is the domain name used by the application
|
|
427
|
+
* Value: `my-project:my-region:my-instance` – This is the Cloud SQL instance connection name
|
|
428
|
+
|
|
429
|
+
#### Configure the connector
|
|
430
|
+
|
|
431
|
+
Configure the connector to resolve DNS names by initializing it with
|
|
432
|
+
`resolver=DnsResolver` and replacing the instance connection name with the DNS
|
|
433
|
+
name in `connector.connect`:
|
|
434
|
+
|
|
435
|
+
```python
|
|
436
|
+
from google.cloud.sql.connector import Connector, DnsResolver
|
|
437
|
+
import pymysql
|
|
438
|
+
import sqlalchemy
|
|
439
|
+
|
|
440
|
+
# helper function to return SQLAlchemy connection pool
|
|
441
|
+
def init_connection_pool(connector: Connector) -> sqlalchemy.engine.Engine:
|
|
442
|
+
# function used to generate database connection
|
|
443
|
+
def getconn() -> pymysql.connections.Connection:
|
|
444
|
+
conn = connector.connect(
|
|
445
|
+
"prod-db.mycompany.example.com", # using DNS name
|
|
446
|
+
"pymysql",
|
|
447
|
+
user="my-user",
|
|
448
|
+
password="my-password",
|
|
449
|
+
db="my-db-name"
|
|
450
|
+
)
|
|
451
|
+
return conn
|
|
452
|
+
|
|
453
|
+
# create connection pool
|
|
454
|
+
pool = sqlalchemy.create_engine(
|
|
455
|
+
"mysql+pymysql://",
|
|
456
|
+
creator=getconn,
|
|
457
|
+
)
|
|
458
|
+
return pool
|
|
459
|
+
|
|
460
|
+
# initialize Cloud SQL Python Connector with `resolver=DnsResolver`
|
|
461
|
+
with Connector(resolver=DnsResolver) as connector:
|
|
462
|
+
# initialize connection pool
|
|
463
|
+
pool = init_connection_pool(connector)
|
|
464
|
+
# ... use SQLAlchemy engine normally
|
|
465
|
+
```
|
|
466
|
+
|
|
403
467
|
### Using the Python Connector with Python Web Frameworks
|
|
404
468
|
|
|
405
469
|
The Python Connector can be used alongside popular Python web frameworks such
|
|
@@ -537,6 +601,42 @@ The `create_async_connector` allows all the same input arguments as the
|
|
|
537
601
|
Once a `Connector` object is returned by `create_async_connector` you can call
|
|
538
602
|
its `connect_async` method, just as you would the `connect` method:
|
|
539
603
|
|
|
604
|
+
#### Asyncpg Connection Pool
|
|
605
|
+
|
|
606
|
+
```python
|
|
607
|
+
import asyncpg
|
|
608
|
+
from google.cloud.sql.connector import Connector, create_async_connector
|
|
609
|
+
|
|
610
|
+
async def main():
|
|
611
|
+
# initialize Connector object for connections to Cloud SQL
|
|
612
|
+
connector = create_async_connector()
|
|
613
|
+
|
|
614
|
+
# creation function to generate asyncpg connections as the 'connect' arg
|
|
615
|
+
async def getconn(instance_connection_name, **kwargs) -> asyncpg.Connection:
|
|
616
|
+
return await connector.connect_async(
|
|
617
|
+
instance_connection_name,
|
|
618
|
+
"asyncpg",
|
|
619
|
+
user="my-user",
|
|
620
|
+
password="my-password",
|
|
621
|
+
db="my-db",
|
|
622
|
+
**kwargs, # ... additional asyncpg args
|
|
623
|
+
)
|
|
624
|
+
|
|
625
|
+
# initialize connection pool
|
|
626
|
+
pool = await asyncpg.create_pool(
|
|
627
|
+
"my-project:my-region:my-instance", connect=getconn
|
|
628
|
+
)
|
|
629
|
+
|
|
630
|
+
# acquire connection and query Cloud SQL database
|
|
631
|
+
async with pool.acquire() as conn:
|
|
632
|
+
res = await conn.fetch("SELECT NOW()")
|
|
633
|
+
|
|
634
|
+
# close Connector
|
|
635
|
+
await connector.close_async()
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
#### SQLAlchemy Async Engine
|
|
639
|
+
|
|
540
640
|
```python
|
|
541
641
|
import asyncpg
|
|
542
642
|
|
|
@@ -546,7 +646,7 @@ from sqlalchemy.ext.asyncio import AsyncEngine, create_async_engine
|
|
|
546
646
|
from google.cloud.sql.connector import Connector, create_async_connector
|
|
547
647
|
|
|
548
648
|
async def init_connection_pool(connector: Connector) -> AsyncEngine:
|
|
549
|
-
#
|
|
649
|
+
# creation function to generate asyncpg connections as 'async_creator' arg
|
|
550
650
|
async def getconn() -> asyncpg.Connection:
|
|
551
651
|
conn: asyncpg.Connection = await connector.connect_async(
|
|
552
652
|
"project:region:instance", # Cloud SQL instance connection name
|
|
@@ -599,6 +699,40 @@ calls to `connector.close_async()` to cleanup resources.
|
|
|
599
699
|
> This alternative requires that the running event loop be
|
|
600
700
|
> passed in as the `loop` argument to `Connector()`.
|
|
601
701
|
|
|
702
|
+
#### Asyncpg Connection Pool
|
|
703
|
+
|
|
704
|
+
```python
|
|
705
|
+
import asyncpg
|
|
706
|
+
from google.cloud.sql.connector import Connector, create_async_connector
|
|
707
|
+
|
|
708
|
+
async def main():
|
|
709
|
+
# initialize Connector object for connections to Cloud SQL
|
|
710
|
+
loop = asyncio.get_running_loop()
|
|
711
|
+
async with Connector(loop=loop) as connector:
|
|
712
|
+
|
|
713
|
+
# creation function to generate asyncpg connections as the 'connect' arg
|
|
714
|
+
async def getconn(instance_connection_name, **kwargs) -> asyncpg.Connection:
|
|
715
|
+
return await connector.connect_async(
|
|
716
|
+
instance_connection_name,
|
|
717
|
+
"asyncpg",
|
|
718
|
+
user="my-user",
|
|
719
|
+
password="my-password",
|
|
720
|
+
db="my-db",
|
|
721
|
+
**kwargs, # ... additional asyncpg args
|
|
722
|
+
)
|
|
723
|
+
|
|
724
|
+
# create connection pool
|
|
725
|
+
pool = await asyncpg.create_pool(
|
|
726
|
+
"my-project:my-region:my-instance", connect=getconn
|
|
727
|
+
)
|
|
728
|
+
|
|
729
|
+
# acquire connection and query Cloud SQL database
|
|
730
|
+
async with pool.acquire() as conn:
|
|
731
|
+
res = await conn.fetch("SELECT NOW()")
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
#### SQLAlchemy Async Engine
|
|
735
|
+
|
|
602
736
|
```python
|
|
603
737
|
import asyncio
|
|
604
738
|
import asyncpg
|
|
@@ -609,17 +743,17 @@ from sqlalchemy.ext.asyncio import AsyncEngine, create_async_engine
|
|
|
609
743
|
from google.cloud.sql.connector import Connector
|
|
610
744
|
|
|
611
745
|
async def init_connection_pool(connector: Connector) -> AsyncEngine:
|
|
612
|
-
#
|
|
746
|
+
# creation function to generate asyncpg connections as 'async_creator' arg
|
|
613
747
|
async def getconn() -> asyncpg.Connection:
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
748
|
+
conn: asyncpg.Connection = await connector.connect_async(
|
|
749
|
+
"project:region:instance", # Cloud SQL instance connection name
|
|
750
|
+
"asyncpg",
|
|
751
|
+
user="my-user",
|
|
752
|
+
password="my-password",
|
|
753
|
+
db="my-db-name"
|
|
754
|
+
# ... additional database driver args
|
|
755
|
+
)
|
|
756
|
+
return conn
|
|
623
757
|
|
|
624
758
|
# The Cloud SQL Python Connector can be used along with SQLAlchemy using the
|
|
625
759
|
# 'async_creator' argument to 'create_async_engine'
|
|
@@ -12,6 +12,7 @@ google/cloud/sql/connector/__init__.py
|
|
|
12
12
|
google/cloud/sql/connector/asyncpg.py
|
|
13
13
|
google/cloud/sql/connector/client.py
|
|
14
14
|
google/cloud/sql/connector/connection_info.py
|
|
15
|
+
google/cloud/sql/connector/connection_name.py
|
|
15
16
|
google/cloud/sql/connector/connector.py
|
|
16
17
|
google/cloud/sql/connector/enums.py
|
|
17
18
|
google/cloud/sql/connector/exceptions.py
|
|
@@ -23,5 +24,6 @@ google/cloud/sql/connector/pymysql.py
|
|
|
23
24
|
google/cloud/sql/connector/pytds.py
|
|
24
25
|
google/cloud/sql/connector/rate_limiter.py
|
|
25
26
|
google/cloud/sql/connector/refresh_utils.py
|
|
27
|
+
google/cloud/sql/connector/resolver.py
|
|
26
28
|
google/cloud/sql/connector/utils.py
|
|
27
29
|
google/cloud/sql/connector/version.py
|
|
@@ -18,12 +18,16 @@ from google.cloud.sql.connector.connector import Connector
|
|
|
18
18
|
from google.cloud.sql.connector.connector import create_async_connector
|
|
19
19
|
from google.cloud.sql.connector.enums import IPTypes
|
|
20
20
|
from google.cloud.sql.connector.enums import RefreshStrategy
|
|
21
|
+
from google.cloud.sql.connector.resolver import DefaultResolver
|
|
22
|
+
from google.cloud.sql.connector.resolver import DnsResolver
|
|
21
23
|
from google.cloud.sql.connector.version import __version__
|
|
22
24
|
|
|
23
25
|
__all__ = [
|
|
24
26
|
"__version__",
|
|
25
27
|
"create_async_connector",
|
|
26
28
|
"Connector",
|
|
29
|
+
"DefaultResolver",
|
|
30
|
+
"DnsResolver",
|
|
27
31
|
"IPTypes",
|
|
28
32
|
"RefreshStrategy",
|
|
29
33
|
]
|