Skip to content

Commit 9014c1b

Browse files
committed
Various fixes for Python 3 compatibility.
1 parent d73923d commit 9014c1b

File tree

4 files changed

+105
-37
lines changed

4 files changed

+105
-37
lines changed

rdflib/parser.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616
from urllib import pathname2url, url2pathname
1717
from urllib2 import urlopen, Request, HTTPError
1818
from urlparse import urljoin
19-
from StringIO import StringIO
19+
try:
20+
from io import BytesIO
21+
except:
22+
from StringIO import StringIO as BytesIO
2023
from xml.sax import xmlreader
2124
from xml.sax.saxutils import prepare_input_source
2225
import types
@@ -56,7 +59,7 @@ class StringInputSource(InputSource):
5659

5760
def __init__(self, value, system_id=None):
5861
super(StringInputSource, self).__init__(system_id)
59-
stream = StringIO(value)
62+
stream = BytesIO(value)
6063
self.setByteStream(stream)
6164
# TODO:
6265
# encoding = value.encoding

rdflib/plugins/parsers/notation3.py

Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import StringIO
3939
import codecs
4040

41-
from string import find, rfind
4241
from decimal import Decimal
4342

4443
from rdflib.term import URIRef, BNode, Literal, Variable, _XSD_PFX, _unique_id
@@ -81,7 +80,7 @@ def splitFrag(uriref):
8180
8281
"""
8382

84-
i = rfind(uriref, "#")
83+
i = uriref.rfind("#")
8584
if i>= 0: return uriref[:i], uriref[i+1:]
8685
else: return uriref, None
8786

@@ -100,7 +99,7 @@ def splitFragP(uriref, punct=0):
10099
101100
"""
102101

103-
i = rfind(uriref, "#")
102+
i = uriref.rfind("#")
104103
if i>= 0: return uriref[:i], uriref[i:]
105104
else: return uriref, ''
106105

@@ -139,16 +138,16 @@ def join(here, there):
139138
u'http://example.org/#Andr\\xe9'
140139
"""
141140

142-
assert(find(here, "#") < 0), "Base may not contain hash: '%s'"% here # caller must splitFrag (why?)
141+
assert(here.find("#") < 0), "Base may not contain hash: '%s'"% here # caller must splitFrag (why?)
143142

144-
slashl = find(there, '/')
145-
colonl = find(there, ':')
143+
slashl = there.find('/')
144+
colonl = there.find(':')
146145

147146
# join(base, 'foo:/') -- absolute
148147
if colonl >= 0 and (slashl < 0 or colonl < slashl):
149148
return there
150149

151-
bcolonl = find(here, ':')
150+
bcolonl = here.find(':')
152151
assert(bcolonl >= 0), "Base uri '%s' is not absolute" % here # else it's not absolute
153152

154153
path, frag = splitFragP(there)
@@ -159,7 +158,7 @@ def join(here, there):
159158
raise ValueError ("Base <%s> has no slash after colon - with relative '%s'." %(here, there))
160159

161160
if here[bcolonl+1:bcolonl+3] == '//':
162-
bpath = find(here, '/', bcolonl+3)
161+
bpath = here.find('/', bcolonl+3)
163162
else:
164163
bpath = bcolonl+1
165164

@@ -176,7 +175,7 @@ def join(here, there):
176175
if there[:1] == '/':
177176
return here[:bpath] + there
178177

179-
slashr = rfind(here, '/')
178+
slashr = here.rfind('/')
180179

181180
while 1:
182181
if path[:2] == './':
@@ -185,7 +184,7 @@ def join(here, there):
185184
path = ''
186185
elif path[:3] == '../' or path == '..':
187186
path = path[3:]
188-
i = rfind(here, '/', bpath, slashr)
187+
i = here.rfind('/', bpath, slashr)
189188
if i >= 0:
190189
here = here[:i+1]
191190
slashr = i
@@ -261,10 +260,10 @@ def refTo(base, uri):
261260
while i>0 and uri[i-1] != '/' : i=i-1 # scan for slash
262261

263262
if i < 3: return uri # No way.
264-
if string.find(base, "//", i-2)>0 \
265-
or string.find(uri, "//", i-2)>0: return uri # An unshared "//"
266-
if string.find(base, ":", i)>0: return uri # An unshared ":"
267-
n = string.count(base, "/", i)
263+
if base.find("//", i-2)>0 \
264+
or uri.find("//", i-2)>0: return uri # An unshared "//"
265+
if base.find(":", i)>0: return uri # An unshared ":"
266+
n = base.count("/", i)
268267
if n == 0 and i<len(uri) and uri[i] == '#':
269268
return "./" + uri[i:]
270269
elif n == 0 and i == len(uri):
@@ -568,10 +567,10 @@ def _do_text(self, node):
568567
Process a text or CDATA node. Render various special characters
569568
as their C14N entity representations.'''
570569
if not _in_subset(self.subset, node): return
571-
s = string.replace(node.data, "&", "&amp;")
572-
s = string.replace(s, "<", "&lt;")
573-
s = string.replace(s, ">", "&gt;")
574-
s = string.replace(s, "\015", "&#xD;")
570+
s = node.data.replace("&", "&amp;")
571+
s = s.replace("<", "&lt;")
572+
s = s.replace(">", "&gt;")
573+
s = s.replace("\015", "&#xD;")
575574
if s: self.write(s)
576575
handlers[Node.TEXT_NODE] = _do_text
577576
handlers[Node.CDATA_SECTION_NODE] = _do_text
@@ -622,12 +621,12 @@ def _do_attr(self, n, value):
622621
W(' ')
623622
W(n)
624623
W('="')
625-
s = string.replace(value, "&", "&amp;")
626-
s = string.replace(s, "<", "&lt;")
627-
s = string.replace(s, '"', '&quot;')
628-
s = string.replace(s, '\011', '&#x9')
629-
s = string.replace(s, '\012', '&#xA')
630-
s = string.replace(s, '\015', '&#xD')
624+
s = value.replace(value, "&", "&amp;")
625+
s = s.replace("<", "&lt;")
626+
s = s.replace('"', '&quot;')
627+
s = s.replace('\011', '&#x9')
628+
s = s.replace('\012', '&#xA')
629+
s = s.replace('\015', '&#xD')
631630
W(s)
632631
W('"')
633632

@@ -1501,7 +1500,7 @@ def uri_ref2(self, str, i, res):
15011500
res.append(self._variables[symb])
15021501
else:
15031502
res.append(symb) # @@@ "#" CONVENTION
1504-
if not string.find(ns, "#"):progress(
1503+
if not ns.find("#"):progress(
15051504
"Warning: no # on namespace %s," % ns)
15061505
return j
15071506

@@ -1825,7 +1824,7 @@ def strconst(self, str, i, delim):
18251824
if not ch:
18261825
raise BadSyntax(self._thisDoc, startline, str, i,
18271826
"unterminated string literal (2)")
1828-
k = string.find('abfrtvn\\"', ch)
1827+
k = 'abfrtvn\\"'.find(ch)
18291828
if k >= 0:
18301829
uch = '\a\b\f\r\t\v\n\\"'[k]
18311830
ustr = ustr + uch
@@ -1855,7 +1854,7 @@ def uEscape(self, str, i, startline):
18551854
if ch == "":
18561855
raise BadSyntax(self._thisDoc, startline, str, i,
18571856
"unterminated string literal(3)")
1858-
k = string.find("0123456789abcdef", ch)
1857+
k = "0123456789abcdef".find(ch)
18591858
if k < 0:
18601859
raise BadSyntax(self._thisDoc, startline, str, i,
18611860
"bad string literal hex escape")
@@ -1876,7 +1875,7 @@ def UEscape(self, str, i, startline):
18761875
if ch == "":
18771876
raise BadSyntax(self._thisDoc, startline, str, i,
18781877
"unterminated string literal(3)")
1879-
k = string.find("0123456789abcdef", ch)
1878+
k = "0123456789abcdef".find(ch)
18801879
if k < 0:
18811880
raise BadSyntax(self._thisDoc, startline, str, i,
18821881
"bad string literal hex escape")
@@ -2139,8 +2138,8 @@ def stringToN3(str, singleLine=0, flags=""):
21392138
if (len(str) > 20 and
21402139
str[-1] <> '"' and
21412140
not singleLine and
2142-
(string.find(str, "\n") >=0
2143-
or string.find(str, '"') >=0)):
2141+
(str.find("\n") >=0
2142+
or str.find('"') >=0)):
21442143
delim= '"""'
21452144
forbidden = forbidden1 # (allow tabs too now)
21462145
else:
@@ -2160,7 +2159,7 @@ def stringToN3(str, singleLine=0, flags=""):
21602159
if ch == '"' and delim == '"""' and str[j:j+3] != '"""': #"
21612160
res = res + ch
21622161
else:
2163-
k = string.find('\a\b\f\r\t\v\n\\"', ch)
2162+
k = '\a\b\f\r\t\v\n\\"'.find(ch)
21642163
if k >= 0: res = res + "\\" + 'abfrtvn\\"'[k]
21652164
else:
21662165
if 'e' in flags:
@@ -2220,16 +2219,16 @@ def hexify(ustr):
22202219

22212220
def dummy():
22222221
res = ""
2223-
if len(str) > 20 and (string.find(str, "\n") >=0
2224-
or string.find(str, '"') >=0):
2222+
if len(str) > 20 and (str.find("\n") >=0
2223+
or str.find('"') >=0):
22252224
delim= '"""'
22262225
forbidden = "\\\"\a\b\f\r\v" # (allow tabs too now)
22272226
else:
22282227
delim = '"'
22292228
forbidden = "\\\"\a\b\f\r\v\t\n"
22302229
for i in range(len(str)):
22312230
ch = str[i]
2232-
j = string.find(forbidden, ch)
2231+
j = forbidden.find(ch)
22332232
if ch == '"' and delim == '"""' \
22342233
and i+1 < len(str) and str[i+1] != '"':
22352234
j=-1 # Single quotes don't need escaping in long format

rdflib/py3compat.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
"""
2+
Utility functions and objects to ease Python 3 compatibility.
3+
"""
4+
import sys
5+
6+
try:
7+
from functools import wraps
8+
except ImportError:
9+
# No-op wraps decorator
10+
def wraps(f):
11+
def dec(newf): return newf
12+
return dec
13+
14+
PY3 = (sys.version_info[0] >= 3)
15+
16+
def _modify_str_or_docstring(str_change_func):
17+
@wraps(str_change_func)
18+
def wrapper(func_or_str):
19+
if isinstance(func_or_str, str):
20+
func = None
21+
doc = func_or_str
22+
else:
23+
func = func_or_str
24+
doc = func.__doc__
25+
26+
doc = str_change_func(doc)
27+
28+
if func:
29+
func.__doc__ = doc
30+
return func
31+
return doc
32+
return wrapper
33+
34+
if PY3:
35+
# Python 3:
36+
# ---------
37+
38+
# Abstract u'abc' syntax:
39+
@_modify_str_or_docstring
40+
def u_format(s):
41+
""""%(u)s'abc'" --> "'abc'" (Python 3)
42+
43+
Accepts a string or a function, so it can be used as a decorator."""
44+
return s % {'u':''}
45+
46+
else:
47+
# Python 2
48+
# --------
49+
50+
# Abstract u'abc' syntax:
51+
@_modify_str_or_docstring
52+
def u_format(s):
53+
""""%(u)s'abc'" --> "u'abc'" (Python 2)
54+
55+
Accepts a string or a function, so it can be used as a decorator."""
56+
return s % {'u':'u'}

rdflib/util.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@
3838
from time import time
3939
from time import timezone
4040

41+
try:
42+
cmp
43+
except NameError:
44+
def sign(n):
45+
if n < 0: return -1
46+
if n > 0: return 1
47+
return 0
48+
else:
49+
def sign(n): return cmp(n, 0)
50+
4151
from rdflib.exceptions import ContextTypeError
4252
from rdflib.exceptions import ObjectTypeError
4353
from rdflib.exceptions import PredicateTypeError
@@ -260,7 +270,7 @@ def parse_date_time(val):
260270
else:
261271
signed_hrs = int(tz_str[:3])
262272
mins = int(tz_str[4:6])
263-
secs = (cmp(signed_hrs, 0) * mins + signed_hrs * 60) * 60
273+
secs = (sign(signed_hrs) * mins + signed_hrs * 60) * 60
264274
tz_offset = -secs
265275

266276
year, month, day = ymd.split("-")

0 commit comments

Comments
 (0)