summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJon Dufresne <jon.dufresne@gmail.com>2017-12-10 18:35:41 -0800
committerJon Dufresne <jon.dufresne@gmail.com>2017-12-11 20:26:58 -0800
commit8ad2098b74ee90f341e69937a1503e29decf4594 (patch)
treeca6bb581c11fcb1a4cbe56b24aa9b83662293f3a /lib
parentf35465231f76039fae8677d48beacbdd2479095a (diff)
downloadpsycopg2-8ad2098b74ee90f341e69937a1503e29decf4594.tar.gz
Drop 2to3 build step; make all code compatible with all Pythons
Make all library code compatible with both Python 2 and Python 3. Helps move to modern Python idioms. Can now write for Python 3 (with workarounds for Python 2) instead of the other way around. In the future, when it is eventually time to drop Python 2, the library will be in a better position to remove workarounds Added a very small comparability module compat.py where required. It includes definitions for: - text_type -- A type. str on Python 3. unicode on Python 2. - string_types -- A tuple. Contains only str on Python 3. Contains str & unicode on Python 2.
Diffstat (limited to 'lib')
-rw-r--r--lib/_ipaddress.py5
-rw-r--r--lib/_range.py11
-rw-r--r--lib/compat.py10
-rw-r--r--lib/errorcodes.py2
-rw-r--r--lib/extensions.py6
-rw-r--r--lib/extras.py14
-rw-r--r--lib/pool.py4
-rw-r--r--lib/sql.py9
8 files changed, 39 insertions, 22 deletions
diff --git a/lib/_ipaddress.py b/lib/_ipaddress.py
index ee05a26..beb2fb3 100644
--- a/lib/_ipaddress.py
+++ b/lib/_ipaddress.py
@@ -25,6 +25,7 @@
from psycopg2.extensions import (
new_type, new_array_type, register_type, register_adapter, QuotedString)
+from psycopg2.compat import text_type
# The module is imported on register_ipaddress
ipaddress = None
@@ -76,13 +77,13 @@ def cast_interface(s, cur=None):
if s is None:
return None
# Py2 version force the use of unicode. meh.
- return ipaddress.ip_interface(unicode(s))
+ return ipaddress.ip_interface(text_type(s))
def cast_network(s, cur=None):
if s is None:
return None
- return ipaddress.ip_network(unicode(s))
+ return ipaddress.ip_network(text_type(s))
def adapt_ipaddress(obj):
diff --git a/lib/_range.py b/lib/_range.py
index c1facc0..fd15a76 100644
--- a/lib/_range.py
+++ b/lib/_range.py
@@ -29,6 +29,7 @@ import re
from psycopg2._psycopg import ProgrammingError, InterfaceError
from psycopg2.extensions import ISQLQuote, adapt, register_adapter
from psycopg2.extensions import new_type, new_array_type, register_type
+from psycopg2.compat import string_types
class Range(object):
@@ -126,9 +127,13 @@ class Range(object):
return True
- def __nonzero__(self):
+ def __bool__(self):
return self._bounds is not None
+ def __nonzero__(self):
+ # Python 2 compatibility
+ return type(self).__bool__(self)
+
def __eq__(self, other):
if not isinstance(other, Range):
return False
@@ -296,7 +301,7 @@ class RangeCaster(object):
# an implementation detail and is not documented. It is currently used
# for the numeric ranges.
self.adapter = None
- if isinstance(pgrange, basestring):
+ if isinstance(pgrange, string_types):
self.adapter = type(pgrange, (RangeAdapter,), {})
self.adapter.name = pgrange
else:
@@ -313,7 +318,7 @@ class RangeCaster(object):
self.range = None
try:
- if isinstance(pyrange, basestring):
+ if isinstance(pyrange, string_types):
self.range = type(pyrange, (Range,), {})
if issubclass(pyrange, Range) and pyrange is not Range:
self.range = pyrange
diff --git a/lib/compat.py b/lib/compat.py
new file mode 100644
index 0000000..cfd5a88
--- /dev/null
+++ b/lib/compat.py
@@ -0,0 +1,10 @@
+import sys
+
+if sys.version_info[0] == 2:
+ # Python 2
+ string_types = basestring,
+ text_type = unicode
+else:
+ # Python 3
+ string_types = str,
+ text_type = str
diff --git a/lib/errorcodes.py b/lib/errorcodes.py
index 24fcf25..b8742f5 100644
--- a/lib/errorcodes.py
+++ b/lib/errorcodes.py
@@ -40,7 +40,7 @@ def lookup(code, _cache={}):
# Generate the lookup map at first usage.
tmp = {}
- for k, v in globals().iteritems():
+ for k, v in globals().items():
if isinstance(v, str) and len(v) in (2, 5):
tmp[v] = k
diff --git a/lib/extensions.py b/lib/extensions.py
index d15f76c..8644e41 100644
--- a/lib/extensions.py
+++ b/lib/extensions.py
@@ -163,7 +163,7 @@ def make_dsn(dsn=None, **kwargs):
kwargs['dbname'] = kwargs.pop('database')
# Drop the None arguments
- kwargs = {k: v for (k, v) in kwargs.iteritems() if v is not None}
+ kwargs = {k: v for (k, v) in kwargs.items() if v is not None}
if dsn is not None:
tmp = parse_dsn(dsn)
@@ -171,7 +171,7 @@ def make_dsn(dsn=None, **kwargs):
kwargs = tmp
dsn = " ".join(["%s=%s" % (k, _param_escape(str(v)))
- for (k, v) in kwargs.iteritems()])
+ for (k, v) in kwargs.items()])
# verify that the returned dsn is valid
parse_dsn(dsn)
@@ -216,7 +216,7 @@ del Range
# When the encoding is set its name is cleaned up from - and _ and turned
# uppercase, so an encoding not respecting these rules wouldn't be found in the
# encodings keys and would raise an exception with the unicode typecaster
-for k, v in encodings.items():
+for k, v in list(encodings.items()):
k = k.replace('_', '').replace('-', '').upper()
encodings[k] = v
diff --git a/lib/extras.py b/lib/extras.py
index 64467a8..1b0b2b6 100644
--- a/lib/extras.py
+++ b/lib/extras.py
@@ -318,14 +318,14 @@ class NamedTupleCursor(_cursor):
nt = self.Record
if nt is None:
nt = self.Record = self._make_nt()
- return map(nt._make, ts)
+ return list(map(nt._make, ts))
def fetchall(self):
ts = super(NamedTupleCursor, self).fetchall()
nt = self.Record
if nt is None:
nt = self.Record = self._make_nt()
- return map(nt._make, ts)
+ return list(map(nt._make, ts))
def __iter__(self):
try:
@@ -566,7 +566,7 @@ class ReplicationCursor(_replicationCursor):
"cannot specify output plugin options for physical replication")
command += " ("
- for k, v in options.iteritems():
+ for k, v in options.items():
if not command.endswith('('):
command += ", "
command += "%s %s" % (quote_ident(k, self), _A(str(v)))
@@ -762,7 +762,7 @@ class HstoreAdapter(object):
adapt = _ext.adapt
rv = []
- for k, v in self.wrapped.iteritems():
+ for k, v in self.wrapped.items():
k = adapt(k)
k.prepare(self.conn)
k = k.getquoted()
@@ -784,9 +784,9 @@ class HstoreAdapter(object):
if not self.wrapped:
return b"''::hstore"
- k = _ext.adapt(self.wrapped.keys())
+ k = _ext.adapt(list(self.wrapped.keys()))
k.prepare(self.conn)
- v = _ext.adapt(self.wrapped.values())
+ v = _ext.adapt(list(self.wrapped.values()))
v.prepare(self.conn)
return b"hstore(" + k.getquoted() + b", " + v.getquoted() + b")"
@@ -1112,7 +1112,7 @@ def _paginate(seq, page_size):
it = iter(seq)
while 1:
try:
- for i in xrange(page_size):
+ for i in range(page_size):
page.append(next(it))
yield page
page = []
diff --git a/lib/pool.py b/lib/pool.py
index a91c9cc..6c26f7d 100644
--- a/lib/pool.py
+++ b/lib/pool.py
@@ -209,8 +209,8 @@ class PersistentConnectionPool(AbstractConnectionPool):
# we we'll need the thread module, to determine thread ids, so we
# import it here and copy it in an instance variable
- import thread as _thread # work around for 2to3 bug - see ticket #348
- self.__thread = _thread
+ import thread
+ self.__thread = thread
def getconn(self):
"""Generate thread id and return a connection."""
diff --git a/lib/sql.py b/lib/sql.py
index 849b25f..7ba9295 100644
--- a/lib/sql.py
+++ b/lib/sql.py
@@ -27,6 +27,7 @@ import sys
import string
from psycopg2 import extensions as ext
+from psycopg2.compat import string_types
_formatter = string.Formatter()
@@ -147,7 +148,7 @@ class Composed(Composable):
"foo", "bar"
"""
- if isinstance(joiner, basestring):
+ if isinstance(joiner, string_types):
joiner = SQL(joiner)
elif not isinstance(joiner, SQL):
raise TypeError(
@@ -179,7 +180,7 @@ class SQL(Composable):
select "foo", "bar" from "table"
"""
def __init__(self, string):
- if not isinstance(string, basestring):
+ if not isinstance(string, string_types):
raise TypeError("SQL values must be strings")
super(SQL, self).__init__(string)
@@ -308,7 +309,7 @@ class Identifier(Composable):
"""
def __init__(self, string):
- if not isinstance(string, basestring):
+ if not isinstance(string, string_types):
raise TypeError("SQL identifiers must be strings")
super(Identifier, self).__init__(string)
@@ -395,7 +396,7 @@ class Placeholder(Composable):
"""
def __init__(self, name=None):
- if isinstance(name, basestring):
+ if isinstance(name, string_types):
if ')' in name:
raise ValueError("invalid name: %r" % name)