Skip to content

Commit 72841f1

Browse files
committed
Require 3.3 minimum and update collections references to collections.abc per deprecation warnings.
* Clean abc usage by preferring register over multiple inheritance. * Eliminate more types-as-docs * Relocate api.Connection.query to api.Database.query. postgresql.api has been somewhat neglected and should be given a thorough evaluation.
1 parent 066c0d4 commit 72841f1

8 files changed

Lines changed: 68 additions & 104 deletions

File tree

postgresql/api.py

Lines changed: 50 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
This module is used to define "PG-API". It creates a set of ABCs
1212
that makes up the basic interfaces used to work with a PostgreSQL server.
1313
"""
14-
import collections
14+
import collections.abc
1515
import abc
1616

1717
from .python.element import Element
@@ -125,7 +125,8 @@ class Result(Element):
125125
@abc.abstractmethod
126126
def close(self) -> None:
127127
"""
128-
Close the Result handle.
128+
Close the Result discarding any supporting resources and causing
129+
future read operations to emit empty record sets.
129130
"""
130131

131132
@property
@@ -202,18 +203,12 @@ def statement(self) -> ("Statement", None):
202203
`postgresql.api.Database.cursor_from_id`.
203204
"""
204205

205-
class Chunks(
206-
Result,
207-
collections.Iterator,
208-
collections.Iterable,
209-
):
206+
@collections.abc.Iterator.register
207+
class Chunks(Result):
210208
pass
211209

212-
class Cursor(
213-
Result,
214-
collections.Iterator,
215-
collections.Iterable,
216-
):
210+
@collections.abc.Iterator.register
211+
class Cursor(Result):
217212
"""
218213
A `Cursor` object is an interface to a sequence of tuples(rows). A result
219214
set. Cursors publish a file-like interface for reading tuples from a cursor
@@ -259,10 +254,7 @@ def direction(self) -> bool:
259254
"""
260255

261256
@abc.abstractmethod
262-
def read(self,
263-
quantity : "Number of rows to read" = None,
264-
direction : "Direction to fetch in, defaults to `self.direction`" = None,
265-
) -> ["Row"]:
257+
def read(self, quantity = None, direction = None) -> ["Row"]:
266258
"""
267259
Read, fetch, the specified number of rows and return them in a list.
268260
If quantity is `None`, all records will be fetched.
@@ -312,7 +304,7 @@ class Execution(metaclass = abc.ABCMeta):
312304
"""
313305

314306
@abc.abstractmethod
315-
def __call__(self, *parameters : "Positional Parameters") -> ["Row"]:
307+
def __call__(self, *parameters) -> ["Row"]:
316308
"""
317309
Execute the prepared statement with the given arguments as parameters.
318310
@@ -324,7 +316,7 @@ def __call__(self, *parameters : "Positional Parameters") -> ["Row"]:
324316
"""
325317

326318
@abc.abstractmethod
327-
def column(self, *parameters) -> collections.Iterable:
319+
def column(self, *parameters) -> collections.abc.Iterable:
328320
"""
329321
Return an iterator producing the values of first column of the
330322
rows produced by the cursor created from the statement bound with the
@@ -345,7 +337,7 @@ def column(self, *parameters) -> collections.Iterable:
345337
"""
346338

347339
@abc.abstractmethod
348-
def chunks(self, *parameters) -> collections.Iterable:
340+
def chunks(self, *parameters) -> collections.abc.Iterable:
349341
"""
350342
Return an iterator producing sequences of rows produced by the cursor
351343
created from the statement bound with the given parameters.
@@ -359,12 +351,12 @@ def chunks(self, *parameters) -> collections.Iterable:
359351
Each iteration returns sequences of rows *normally* of length(seq) ==
360352
chunksize. If chunksize is unspecified, a default, positive integer will
361353
be filled in. The rows contained in the sequences are only required to
362-
support the basic `collections.Sequence` interfaces; simple and quick
354+
support the basic `collections.abc.Sequence` interfaces; simple and quick
363355
sequence types should be used.
364356
"""
365357

366358
@abc.abstractmethod
367-
def rows(self, *parameters) -> collections.Iterable:
359+
def rows(self, *parameters) -> collections.abc.Iterable:
368360
"""
369361
Return an iterator producing rows produced by the cursor
370362
created from the statement bound with the given parameters.
@@ -382,7 +374,7 @@ def rows(self, *parameters) -> collections.Iterable:
382374
"""
383375

384376
@abc.abstractmethod
385-
def column(self, *parameters) -> collections.Iterable:
377+
def column(self, *parameters) -> collections.abc.Iterable:
386378
"""
387379
Return an iterator producing the values of the first column in
388380
the cursor created from the statement bound with the given parameters.
@@ -407,7 +399,7 @@ def declare(self, *parameters) -> Cursor:
407399
"""
408400

409401
@abc.abstractmethod
410-
def first(self, *parameters) -> "'First' object that is returned by the query":
402+
def first(self, *parameters):
411403
"""
412404
Execute the prepared statement with the given arguments as parameters.
413405
If the statement returns rows with multiple columns, return the first
@@ -426,9 +418,7 @@ def first(self, *parameters) -> "'First' object that is returned by the query":
426418
"""
427419

428420
@abc.abstractmethod
429-
def load_rows(self,
430-
iterable : "A iterable of tuples to execute the statement with"
431-
):
421+
def load_rows(self, iterable):
432422
"""
433423
Given an iterable, `iterable`, feed the produced parameters to the
434424
query. This is a bulk-loading interface for parameterized queries.
@@ -445,9 +435,7 @@ def load_rows(self,
445435
"""
446436

447437
@abc.abstractmethod
448-
def load_chunks(self,
449-
iterable : "A iterable of chunks of tuples to execute the statement with"
450-
):
438+
def load_chunks(self, iterable):
451439
"""
452440
Given an iterable, `iterable`, feed the produced parameters of the chunks
453441
produced by the iterable to the query. This is a bulk-loading interface
@@ -465,11 +453,10 @@ def load_chunks(self,
465453
that the operation can be optimized.
466454
"""
467455

468-
class Statement(
469-
Element,
470-
collections.Callable,
471-
collections.Iterable,
472-
):
456+
@collections.abc.Iterator.register
457+
@collections.abc.Callable.register
458+
@Execution.register
459+
class Statement(Element):
473460
"""
474461
Instances of `Statement` are returned by the `prepare` method of
475462
`Database` instances.
@@ -595,21 +582,18 @@ def close(self) -> None:
595582
"""
596583
Close the prepared statement releasing resources associated with it.
597584
"""
598-
Execution.register(Statement)
599585
PreparedStatement = Statement
600586

601-
class StoredProcedure(
602-
Element,
603-
collections.Callable,
604-
):
587+
@collections.abc.Callable.register
588+
class StoredProcedure(Element):
605589
"""
606590
A function stored on the database.
607591
"""
608592
_e_label = 'FUNCTION'
609593
_e_factors = ('database',)
610594

611595
@abc.abstractmethod
612-
def __call__(self, *args, **kw) -> (object, Cursor, collections.Iterable):
596+
def __call__(self, *args, **kw) -> (object, Cursor, collections.abc.Iterable):
613597
"""
614598
Execute the procedure with the given arguments. If keyword arguments are
615599
passed they must be mapped to the argument whose name matches the key.
@@ -759,10 +743,8 @@ def __exit__(self, typ, obj, tb):
759743
block's exit.
760744
"""
761745

762-
class Settings(
763-
Element,
764-
collections.MutableMapping
765-
):
746+
@collections.abc.MutableMapping.register
747+
class Settings(Element):
766748
"""
767749
A mapping interface to the session's settings. This provides a direct
768750
interface to ``SHOW`` or ``SET`` commands. Identifiers and values need
@@ -881,10 +863,7 @@ def client_port(self) -> (int, None):
881863

882864
@property
883865
@abc.abstractmethod
884-
def xact(self,
885-
isolation : "ISOLATION LEVEL to use with the transaction" = None,
886-
mode : "Mode of the transaction, READ ONLY or READ WRITE" = None,
887-
) -> Transaction:
866+
def xact(self, isolation = None, mode = None) -> Transaction:
888867
"""
889868
Create a `Transaction` object using the given keyword arguments as its
890869
configuration.
@@ -926,9 +905,14 @@ def prepare(self, sql : str) -> Statement:
926905
"""
927906

928907
@abc.abstractmethod
929-
def statement_from_id(self,
930-
statement_id : "The statement's identification string.",
931-
) -> Statement:
908+
def query(self, sql : str, *args) -> Execution:
909+
"""
910+
Prepare and execute the statement, `sql`, with the given arguments.
911+
Equivalent to ``db.prepare(sql)(*args)``.
912+
"""
913+
914+
@abc.abstractmethod
915+
def statement_from_id(self, statement_id) -> Statement:
932916
"""
933917
Create a `Statement` object that was already prepared on the
934918
server. The distinction between this and a regular query is that it
@@ -938,9 +922,7 @@ def statement_from_id(self,
938922
"""
939923

940924
@abc.abstractmethod
941-
def cursor_from_id(self,
942-
cursor_id : "The cursor's identification string."
943-
) -> Cursor:
925+
def cursor_from_id(self, cursor_id) -> Cursor:
944926
"""
945927
Create a `Cursor` object from the given `cursor_id` that was already
946928
declared on the server.
@@ -953,10 +935,7 @@ def cursor_from_id(self,
953935
"""
954936

955937
@abc.abstractmethod
956-
def proc(self,
957-
procedure_id : \
958-
"The procedure identifier; a valid ``regprocedure`` or Oid."
959-
) -> StoredProcedure:
938+
def proc(self, procedure_id) -> StoredProcedure:
960939
"""
961940
Create a `StoredProcedure` instance using the given identifier.
962941
@@ -1030,7 +1009,7 @@ def listening_channels(self) -> ["channel name", ...]:
10301009
"""
10311010

10321011
@abc.abstractmethod
1033-
def iternotifies(self, timeout = None) -> collections.Iterator:
1012+
def iternotifies(self, timeout = None) -> collections.abc.Iterator:
10341013
"""
10351014
Return an iterator to the notifications received by the connection. The
10361015
iterator *must* produce triples in the form ``(channel, payload, pid)``.
@@ -1096,7 +1075,7 @@ def fatal_exception_message(self, err : Exception) -> (str, None):
10961075
"""
10971076

10981077
@abc.abstractmethod
1099-
def socket_secure(self, socket : "socket object") -> "secured socket":
1078+
def socket_secure(self, socket):
11001079
"""
11011080
Return a reference to the secured socket using the given parameters.
11021081
@@ -1106,7 +1085,7 @@ def socket_secure(self, socket : "socket object") -> "secured socket":
11061085
"""
11071086

11081087
@abc.abstractmethod
1109-
def socket_factory_sequence(self) -> [collections.Callable]:
1088+
def socket_factory_sequence(self) -> [collections.abc.Callable]:
11101089
"""
11111090
Return a sequence of `SocketCreator`s that `Connection` objects will use to
11121091
create the socket object.
@@ -1145,7 +1124,7 @@ def __call__(self, *args, **kw):
11451124
return self.driver.connection(self, *args, **kw)
11461125

11471126
def __init__(self,
1148-
user : "required keyword specifying the user name(str)" = None,
1127+
user : str = None,
11491128
password : str = None,
11501129
database : str = None,
11511130
settings : (dict, [(str,str)]) = None,
@@ -1179,15 +1158,6 @@ def connector(self) -> Connector:
11791158
communication and initialization.
11801159
"""
11811160

1182-
@property
1183-
@abc.abstractmethod
1184-
def query(self) -> Execution:
1185-
"""
1186-
The :py:class:`Execution` instance providing a one-shot query interface::
1187-
1188-
connection.query.<method>(sql, *parameters) == connection.prepare(sql).<method>(*parameters)
1189-
"""
1190-
11911161
@property
11921162
@abc.abstractmethod
11931163
def closed(self) -> bool:
@@ -1317,18 +1287,13 @@ def data_directory(self) -> str:
13171287

13181288
@abc.abstractmethod
13191289
def init(self,
1320-
initdb : "path to the initdb to use" = None,
1321-
user : "name of the cluster's superuser" = None,
1322-
password : "superuser's password" = None,
1323-
encoding : "the encoding to use for the cluster" = None,
1324-
locale : "the locale to use for the cluster" = None,
1325-
collate : "the collation to use for the cluster" = None,
1326-
ctype : "the ctype to use for the cluster" = None,
1327-
monetary : "the monetary to use for the cluster" = None,
1328-
numeric : "the numeric to use for the cluster" = None,
1329-
time : "the time to use for the cluster" = None,
1330-
text_search_config : "default text search configuration" = None,
1331-
xlogdir : "location for the transaction log directory" = None,
1290+
initdb = None,
1291+
user = None, password = None,
1292+
encoding = None, locale = None,
1293+
collate = None, ctype = None,
1294+
monetary = None, numeric = None, time = None,
1295+
text_search_config = None,
1296+
xlogdir = None,
13321297
):
13331298
"""
13341299
Create the cluster at the `data_directory` associated with the Cluster
@@ -1366,9 +1331,7 @@ def restart(self):
13661331
"""
13671332

13681333
@abc.abstractmethod
1369-
def wait_until_started(self,
1370-
timeout : "maximum time to wait" = 10
1371-
):
1334+
def wait_until_started(self, timeout = 10):
13721335
"""
13731336
After the start() method is ran, the database may not be ready for use.
13741337
This method provides a mechanism to block until the cluster is ready for
@@ -1379,9 +1342,7 @@ def wait_until_started(self,
13791342
"""
13801343

13811344
@abc.abstractmethod
1382-
def wait_until_stopped(self,
1383-
timeout : "maximum time to wait" = 10
1384-
):
1345+
def wait_until_stopped(self, timeout = 10):
13851346
"""
13861347
After the stop() method is ran, the database may still be running.
13871348
This method provides a mechanism to block until the cluster is completely

postgresql/documentation/changes-v1.3.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ Changes in v1.3
55
-----
66

77
* Commit DB-API 2.0 ClientCannotConnect exception correction.
8+
* Eliminate types-as-documentation annotations.
9+
* Eliminate multiple inheritance in `postgresql.api` in favor of ABC registration.

postgresql/documentation/clientparameters.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ accept:
6868

6969
``environ``
7070
Environment variables to extract client parameter variables from.
71-
Defaults to `os.environ` and expects a `collections.Mapping` interface.
71+
Defaults to `os.environ` and expects a `collections.abc.Mapping` interface.
7272

7373
``environ_prefix``
7474
Environment variable prefix to use. Defaults to "PG". This allows the

postgresql/documentation/cluster.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ Methods and properties available on `postgresql.cluster.Cluster` instances:
348348
`Cluster.wait_until_started`.
349349

350350
``Cluster.settings``
351-
A `collections.Mapping` interface to the ``postgresql.conf`` file of the
351+
A `collections.abc.Mapping` interface to the ``postgresql.conf`` file of the
352352
cluster.
353353

354354
A notable extension to the mapping interface is the ``getset`` method. This

postgresql/documentation/copyman.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ The following Producers are available:
260260
``postgresql.copyman.StatementProducer(postgresql.api.Statement)``
261261
Given a Statement producing COPY data, construct a Producer.
262262

263-
``postgresql.copyman.IteratorProducer(collections.Iterator)``
263+
``postgresql.copyman.IteratorProducer(collections.abc.Iterator)``
264264
Given an Iterator producing *chunks* of COPY lines, construct a Producer to
265265
manage the data coming from the iterator.
266266

0 commit comments

Comments
 (0)