Skip to content

Commit dc3b877

Browse files
author
James William Pye
committed
Fix the driver to work on Python 3.
This entailed: - Refactoring the typio system - Refactoring connection negotiation to be an actual Transaction - Fixing issues with environ, clientparams and driver.pythoncommand
1 parent 6ab7032 commit dc3b877

17 files changed

Lines changed: 1382 additions & 1131 deletions

postgresql/api.py

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -108,18 +108,6 @@ def load(self, iterable):
108108
optimize the operation.
109109
"""
110110

111-
@abstractmethod
112-
def __invert__(self):
113-
"""
114-
Shorthand for a call to the `first` method without any arguments.
115-
Useful for resolving static queries. Example usage:
116-
117-
>>> ~pg_con.query("INSERT INTO ttable VALUES ('value')")
118-
1
119-
>>> ~pg_con.query("SELECT 'somestring'")
120-
'somestring'
121-
"""
122-
123111
@abstractmethod
124112
def close(self):
125113
"""
@@ -133,12 +121,6 @@ def prepare(self):
133121
used if the query were closed at some point.
134122
"""
135123

136-
@abstractmethod
137-
def reprepare(self):
138-
"""
139-
Shorthand for ``close`` then ``prepare``.
140-
"""
141-
142124
class Cursor(
143125
collections.Iterator,
144126
collections.Iterable,
@@ -376,10 +358,9 @@ class Settings(
376358
metaclass = ABCMeta
377359
):
378360
"""
379-
A mapping interface to the session's settings. This dictionary-like object
380-
provides a direct interface to ``SHOW`` or ``SET`` commands. Identifiers and
381-
values need not be quoted specially as the implementation must do that work
382-
for the user.
361+
A mapping interface to the session's settings. This provides a direct interface
362+
to ``SHOW`` or ``SET`` commands. Identifiers and values need not be quoted
363+
specially as the implementation must do that work for the user.
383364
"""
384365

385366
def getpath(self) -> "Sequence of schema names that make up the search_path":
@@ -538,7 +519,7 @@ def query(self,
538519
sql : "The query text.",
539520
*default_args : "The default positional parameters to pass to the statement.",
540521
title : "The query's name, used in tracebacks when available" = None,
541-
prepare : "Whether or not to prepare the query." = True,
522+
prepare : "Whether or not to prepare the query." = True
542523
):
543524
"""
544525
Create a new `.query` instance that provides an interface to the prepared statement.
@@ -578,7 +559,7 @@ def cquery(self,
578559
sql : "The query text.",
579560
*default_args : "The default positional parameters to pass to the statement.",
580561
title : "The query's name, used in tracebacks when available" = None,
581-
prepare : "Whether or not to prepare the query." = True,
562+
prepare : "Whether or not to prepare the query." = True
582563
):
583564
"""
584565
Exactly like `query`, but cache the created `PreparedStatement` using the
@@ -593,7 +574,7 @@ def statement(self,
593574
statement_id : "The identifier of the statement.",
594575
*default_args : "The default positional parameters to pass to the statement.",
595576
title : "The query's name, used in tracebacks when available" = None,
596-
prepare : "Whether or not to prepare the query." = True,
577+
prepare : "Whether or not to prepare the query." = True
597578
):
598579
"""
599580
Create a `PreparedStatement` object that was already prepared on the server.
@@ -748,8 +729,8 @@ def closed(self):
748729
doc = """
749730
A property that provides an interface to "SELECT current_user", ``SET
750731
ROLE``, and ``RESET ROLE``. When the attribute is resolved, the current user will
751-
be given as a character string(unicode). When the attribute is set, it will
752-
issue a ``SET ROLE`` command to the server, changing the session's user. When
732+
be given as a character string. When the attribute is set, it will issue a
733+
``SET ROLE`` command to the server, changing the session's user. When
753734
the attribute is deleted, a ``RESET ROLE`` command will be issued to the
754735
server.
755736
"""
@@ -827,7 +808,7 @@ def restart(self):
827808
@abstractproperty
828809
def settings(self):
829810
"""
830-
A `Settings` interface to the postgresql.conf file associated with the
811+
A `Settings` interface to the ``postgresql.conf`` file associated with the
831812
cluster.
832813
"""
833814

postgresql/clientparams.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ def getuser():
2828
pg_appdata_passfile = 'pgpass.conf'
2929

3030
def defaults(getuser = getuser, environ = {}, params = None):
31+
"""
32+
Create a client parameters dictionary with all the default values.
33+
"""
3134
user = getuser()
3235
if sys.platform == 'win32':
3336
appdata = environ.get('APPDATA')
@@ -108,22 +111,32 @@ def resolve_password(d):
108111
# exists, or has been resolved.
109112
d.pop('pgpassfile', None)
110113

111-
def create(param_layers, environ = os.environ, params = None):
114+
def create(
115+
param_layers : "a sequence of mappings to apply to `params`",
116+
environ : "environment variables to apply" = os.environ,
117+
params : "The target mapping to fill the merged parameters into" = None,
118+
prompt_password : "whether to issue a password prompt" = False
119+
):
112120
"""
113-
Create the normal parameter configuration
121+
Create the normal parameter configuration.
122+
123+
If `params` is `None`, a new dictionary will be returned. Otherwise,
124+
`params` is modified and returned.
114125
"""
115126
d = defaults(environ = environ, params = params)
116127
for x in param_layers:
117128
merge_params(d, x)
118129

119-
if co.prompt_password is True:
130+
if prompt_password is True:
120131
if sys.stdin.isatty():
121132
d['password'] = getpass("Password for user %s: " %(
122133
d['user'],
123134
))
124135
else:
125136
# getpass will throw an exception if it's not a tty,
137+
# so just take the next line; could be another command.
126138
pw = sys.stdin.readline()
139+
# try to clean it up..
127140
if pw.endswith(os.linesep):
128141
pw = pw[:len(pw)-len(os.linesep)]
129142
d['password'] = pw

postgresql/cluster.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@
2323
from . import configfile
2424
from . import pg_config
2525
from . import exceptions as pg_exc
26-
# Used for connection ready check.
27-
from .driver import pgapi as pgapi
26+
from . import driver as pg_driver
2827

2928
DEFAULT_CONFIG_FILENAME = 'postgresql.conf'
3029
DEFAULT_HBA_FILENAME = 'pg_hba.conf'
@@ -268,7 +267,7 @@ def ready_for_connections(self):
268267
host = '::1'
269268

270269
try:
271-
pg.connect(
270+
pg_driver.connect(
272271
user = 'ping',
273272
host = host,
274273
port = int(d.get('port') or 5432),

postgresql/driver/dbapi20.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22
# copyright 2007, pg/python project.
33
# http://python.projects.postgresql.org
44
##
5-
'DB-API 2.0 conforming interface on driver.pg_api'
6-
5+
"""
6+
DB-API 2.0 conforming interface on postgresql.driver.pgapi.
7+
"""
78
threadsafety = 1
89
paramstyle = 'pyformat'
910
apilevel = '2.0'
1011

11-
import postgresql.driver.pgapi as pgapi
12+
import postgresql.driver.pgapi as pg_driver
1213
import postgresql.types as pg_type
1314
import postgresql.strings as pg_str
1415
import datetime, time
@@ -162,6 +163,8 @@ def close(self):
162163
self.__portals = None
163164
for p in ps: p.close()
164165

166+
# Describe the "real" cursor as a "portal".
167+
# This should keep ambiguous terminology out of the picture.
165168
def _portal():
166169
def fget(self):
167170
if self.__portals is None:
@@ -217,5 +220,5 @@ def connect(**kw):
217220
kwi = tuple(kwi)
218221
con = _connectors.get(kwi)
219222
if not con:
220-
con = _connectors[kwi] = pgapi.connector(**kw)
223+
con = _connectors[kwi] = pg_driver.connector(**kw)
221224
return Connection(con())

0 commit comments

Comments
 (0)