diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index e4c8ddf8..fb1aba8a 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -7,6 +7,7 @@ This document records the main changes to the ``sdssdb`` code.
* :feature:`264` Add metadata for the ``sdss_id_to_catalog`` table.
* :feature:`266` Support PEP 621.
+* :feature:`268` Allows to use `psycopy3 `__ as a driver for the Peewee database connection.
* Add missing columns to the ``SDSS_ID_To_Catalog`` models (the columns were being completed via reflection).
* Change ``reflection=False`` to ``use_reflection=False`` in many ``catalogdb`` models. The previous setting was incorrect and was causing the models to be reflected.
* Add ``gortdb`` schema and models to ``lvmdb``. Moved ``lvmopsdb.overhead`` to ``gortdb``.
diff --git a/docs/sphinx/intro.rst b/docs/sphinx/intro.rst
index e5322cea..33541337 100644
--- a/docs/sphinx/intro.rst
+++ b/docs/sphinx/intro.rst
@@ -245,7 +245,7 @@ There are two database connections, ``SQLADatabaseConnection`` and ``PeeWeeDatab
A note about passwords
-----------------------
+^^^^^^^^^^^^^^^^^^^^^^
``sdssdb`` does not allow you to pass plaintext passwords when creating a connection, or to store them in the profiles. Instead, you should use `pgpass `__ to set your passwords. A typical ``~/.pgpass`` file looks something like ::
@@ -256,6 +256,22 @@ A note about passwords
where ``XXXX``, ``YYYY``, etc are the associated passwords for each set of parameters.
+Connection flags
+^^^^^^^^^^^^^^^^
+
+``sdssdb`` supports two flags that change the behaviour of the database connection.
+
+* **autoconnect**: if set to `False` the connection will not attempt to connect to the database when created. This is useful when you want to create a connection object but connect to the database later. ``autoconnect`` defaults to `True` and can be changed either by setting the environment variable ``SDSSDB_AUTOCONNECT=0`` before importing the model classes, or by doing ::
+
+ >>> import sdssdb
+ >>> sdssdb.autoconnect = False
+ ... import your model classes ...
+
+ When instantiating a `.DatabaseConnection` object manually, you can also pass the ``autoconnect=False`` keyword argument.
+
+* **use_psycopg3**: prefers to use `psycopg3 `__ instead of the default ``psycopg2``. If ``psycopg3`` is not installed, ``psycopg2`` will be used instead. This flag can be set via the environment variable ``SDSSDB_PSYCOPG3=1`` or by importing ``sdssdb`` and setting ``sdssdb.use_psycopg3 = True`` before importing the model classes.
+
+
.. _profile:
Supported Profiles
diff --git a/pyproject.toml b/pyproject.toml
index e94d5dd3..cf35eb79 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -30,6 +30,7 @@ content-type = "text/markdown"
[project.optional-dependencies]
all = [
+ "psycopg[binary]",
"progressbar2>=3.46.1",
"pydot>=1.4.1",
"astropy>=4.0.0",
@@ -37,7 +38,7 @@ all = [
"inflect>=4.1.0",
"h5py>=3.8.0",
"sdssdb[dev]",
- "sdssdb[docs]",
+ "sdssdb[docs]"
]
dev = [
"pytest>=5.2",
@@ -145,5 +146,8 @@ sdss = ["sdsstools"]
sqla = ["sqlalchemy"]
peewee = ["peewee", "playhouse"]
+[tool.ruff.format]
+preview = true
+
[tool.coverage.run]
branch = true
diff --git a/python/sdssdb/__init__.py b/python/sdssdb/__init__.py
index 8c841df5..224014a2 100644
--- a/python/sdssdb/__init__.py
+++ b/python/sdssdb/__init__.py
@@ -1,5 +1,6 @@
# encoding: utf-8
+import os
import warnings
from sqlalchemy.exc import MovedIn20Warning
@@ -32,6 +33,8 @@
config = get_config(NAME)
autoconnect = True
+use_psycopg3 = os.environ.get("SDSSDB_PSYCOPG3", "false").lower() in ["true", "1"]
+
from .connection import PeeweeDatabaseConnection # noqa
from .connection import SQLADatabaseConnection # noqa
diff --git a/python/sdssdb/connection.py b/python/sdssdb/connection.py
index fa971a4c..925088dc 100644
--- a/python/sdssdb/connection.py
+++ b/python/sdssdb/connection.py
@@ -13,6 +13,7 @@
import os
import re
import socket
+import warnings
import pgpasslib
import six
@@ -23,18 +24,30 @@
from sqlalchemy.orm import scoped_session, sessionmaker
import peewee
-from peewee import OperationalError, PostgresqlDatabase
+from peewee import OperationalError
from playhouse.postgres_ext import ArrayField
from playhouse.reflection import Introspector, UnknownField
import sdssdb
-from sdssdb import config, log
+from sdssdb import config, log, use_psycopg3
from sdssdb.utils.internals import get_database_columns
__all__ = ["DatabaseConnection", "PeeweeDatabaseConnection", "SQLADatabaseConnection"]
+if use_psycopg3 is True:
+ try:
+ import psycopg # noqa
+ from playhouse.psycopg3_ext import Psycopg3Database as PostgresqlDatabase
+ except ImportError:
+ warnings.warn("psycopg3 is not installed. Using psycopg2.")
+ from peewee import PostgresqlDatabase
+
+else:
+ from peewee import PostgresqlDatabase
+
+
def _should_autoconnect():
"""Determines whether we should autoconnect."""
@@ -62,7 +75,7 @@ def get_database_uri(
else:
auth: str = f"{user}:{password}@"
- host_port: str = f"{host or ''}" if port is None else f"{host or ''}:{port}"
+ host_port: str = f"{host or ""}" if port is None else f"{host or ""}:{port}"
if auth == "" and host_port == "":
return f"postgresql://{dbname}"
@@ -132,7 +145,10 @@ def __init__(self, dbname=None, profile=None, autoconnect=None, dbversion=None):
def __repr__(self):
return "<{} (dbname={!r}, profile={!r}, connected={})>".format(
- self.__class__.__name__, self.dbname, self.profile, self.connected
+ self.__class__.__name__,
+ self.dbname,
+ self.profile,
+ self.connected,
)
def set_profile(self, profile=None, connect=True, **params):