zodb / relstorage

A backend for ZODB that stores pickles in a relational database.
Other
54 stars 46 forks source link

Specify PostgreSQL port using ZConfig and pg8000 #378

Closed brahici closed 4 years ago

brahici commented 4 years ago

I tried to use driver pg8000 with a PostgreSQL server listening on port 5436:

# coding: utf-8

import traceback
import ZODB.config

conf = """
%import relstorage
<zodb main>
    <relstorage>
        keep-history false
        <postgresql>
            driver pg8000
            dsn host=localhost dbname=rspg port=5436 user=brice
        </postgresql>
    </relstorage>
</zodb>
"""

try:
    db = ZODB.config.databaseFromString(conf)
    print(f"{db}", len(db.storage))
except Exception as error:
    traceback.print_exc()

The script fails with this error

Traceback (most recent call last):
  File "test.py", line 22, in <module>
    db = ZODB.config.databaseFromString(conf)
  File "[...]/lib/python3.8/site-packages/ZODB/config.py", line 57, in databaseFromString
    return databaseFromFile(StringIO(s))
  File "[...]/lib/python3.8/site-packages/ZODB/config.py", line 65, in databaseFromFile
    return databaseFromConfig(config.database)
  File "[...]/lib/python3.8/site-packages/ZODB/config.py", line 79, in databaseFromConfig
    db = factory.open(databases)
  File "[...]/lib/python3.8/site-packages/ZODB/config.py", line 131, in open
    storage = section.storage.open()
  File "[...]/lib/python3.8/site-packages/relstorage/config.py", line 38, in open
    return RelStorage(adapter, name=config.name, options=options)
  File "[...]/lib/python3.8/site-packages/relstorage/storage/__init__.py", line 180, in __init__
    self._adapter.schema.verify()
  File "[...]/lib/python3.8/site-packages/relstorage/adapters/schema.py", line 702, in verify
    self.connmanager.open_and_call(self._verify)
  File "[...]/lib/python3.8/site-packages/relstorage/adapters/connmanager.py", line 242, in open_and_call
    conn, cursor = self._do_open_for_call(callback)
  File "[...]/lib/python3.8/site-packages/relstorage/adapters/connmanager.py", line 316, in _do_open_for_call
    return self.open(
  File "src/perfmetrics/metric.py", line 72, in perfmetrics._metric._AbstractMetricImpl.__call__
  File "[...]/lib/python3.8/site-packages/relstorage/adapters/postgresql/connmanager.py", line 73, in open
    conn = self._db_connect_with_isolation(
  File "[...]/lib/python3.8/site-packages/relstorage/adapters/postgresql/drivers/pg8000.py", line 165, in connect_with_isolation
    conn = self.connect(dsn)
  File "[...]/lib/python3.8/site-packages/relstorage/adapters/postgresql/drivers/pg8000.py", line 151, in connect
    conn = self._connect(**kwds)
  File "[...]/lib/python3.8/site-packages/relstorage/adapters/postgresql/drivers/pg8000.py", line 124, in __init__
    super(Connection, self).__init__(
  File "[...]/lib/python3.8/site-packages/pg8000/core.py", line 1167, in __init__
    self._usock.connect((host, port))
TypeError: an integer is required (got type str)

I guess this could be solved with this naive patch:

diff --git a/src/relstorage/adapters/postgresql/drivers/pg8000.py b/src/relstorage/adapters/postgresql/drivers/pg8000.py
index 35ce608..da01bbe 100644
--- a/src/relstorage/adapters/postgresql/drivers/pg8000.py
+++ b/src/relstorage/adapters/postgresql/drivers/pg8000.py
@@ -121,6 +121,7 @@ class PG8000Driver(AbstractPostgreSQLDriver):
                     # pylint:disable=useless-super-delegation
                     # We have to do this because the super class requires
                     # all these arguments and doesn't have defaults
+                    port = int(port)
                     super(Connection, self).__init__(
                         user, host, unix_sock,
                         port, database, password, ssl, timeout, application_name,