Skip to content

Commit 7981dfc

Browse files
committed
RF: add (partial?) python 2 compatibility
Make code somewhat more ugly by adding Python 2 compatibility. I wasn't able to get the citeproc-test set up properly to test this well.
1 parent f49804c commit 7981dfc

14 files changed

+80
-51
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
__pycache__
2+
*.pyc

citeproc/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from __future__ import absolute_import
12

23
import os
34

citeproc/formatter/html.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1+
try:
2+
from html import escape
3+
except ImportError:
4+
from cgi import escape
15

2-
from html import escape
3-
6+
from ..py2compat import text_type
47

58
def preformat(text):
6-
return escape(str(text))
9+
return escape(text_type(text))
710

811

9-
class TagWrapper(str):
12+
class TagWrapper(text_type):
1013
tag = None
1114
attributes = None
1215

@@ -57,7 +60,7 @@ class SmallCaps(TagWrapper):
5760
attributes = {'style': 'font-variant:small-caps;'}
5861

5962

60-
class Bibliography(str):
63+
class Bibliography(text_type):
6164
bib_prefix = '<div class="csl-bib-body">'
6265
bib_suffix = '</div>'
6366
item_prefix = ' <div class="csl-entry">'
@@ -66,7 +69,7 @@ class Bibliography(str):
6669
def __new__(cls, items):
6770
output = [cls.bib_prefix]
6871
for text in items:
69-
text = cls.item_prefix + str(text) + cls.item_suffix
72+
text = cls.item_prefix + text_type(text) + cls.item_suffix
7073
output.append(text)
7174
output.append(cls.bib_suffix)
7275
return super().__new__(cls, '\n'.join(output))

citeproc/formatter/plain.py

+12-11
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1+
from ..py2compat import text_type
12

23
def preformat(text):
34
return text
45

56

6-
Italic = str
7-
Oblique = str
8-
Bold = str
9-
Light = str
10-
Underline = str
11-
Superscript = str
12-
Subscript = str
13-
SmallCaps = str
7+
Italic = text_type
8+
Oblique = text_type
9+
Bold = text_type
10+
Light = text_type
11+
Underline = text_type
12+
Superscript = text_type
13+
Subscript = text_type
14+
SmallCaps = text_type
1415

15-
class Bibliography(str):
16+
class Bibliography(text_type):
1617
def __new__(cls, items):
17-
items = map(str, items)
18-
return super().__new__(cls, '\n'.join(items))
18+
items = map(text_type, items)
19+
return super(Bibliography, cls).__new__(cls, '\n'.join(items))

citeproc/frontend.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class CitationStylesLocale(CitationStylesXML):
3535
def __init__(self, locale):
3636
locale_path = os.path.join(LOCALES_PATH, 'locales-{}.xml'.format(locale))
3737
try:
38-
super().__init__(locale_path)
38+
super(CitationStylesLocale, self).__init__(locale_path)
3939
except IOError:
4040
raise ValueError("'{}' is not a known locale".format(locale))
4141

@@ -48,7 +48,7 @@ def __init__(self, style, locale=None):
4848
except TypeError:
4949
pass
5050
try:
51-
super().__init__(style)
51+
super(CitationStylesStyle, self).__init__(style)
5252
except IOError:
5353
raise ValueError("'{}' is not a known style".format(style))
5454
if locale is None:

citeproc/model.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def loc(self):
6868
print('\n'.join(tree))
6969

7070
def get_option(self, name):
71-
return self.get(name, __class__._default_options[name])
71+
return self.get(name, self._default_options[name])
7272

7373
def get_macro(self, name):
7474
expression = "cs:macro[@name='{}'][1]".format(name)
@@ -195,7 +195,7 @@ def get_option(self, name):
195195
options = self.find('cs:style-options', self.nsmap)
196196
if options is None:
197197
raise IndexError
198-
return options.get(name, __class__._default_options[name])
198+
return options.get(name, self._default_options[name])
199199

200200
def get_formatter(self):
201201
return self.style.formatter

citeproc/py2compat.py

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import sys
2+
3+
PY2 = sys.version_info[0] < 3
4+
5+
if PY2:
6+
string_types = basestring,
7+
text_type = unicode
8+
else:
9+
string_types = str,
10+
text_type = str

citeproc/source/__init__.py

+10-10
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def __getattr__(self, name):
3636

3737
def __getitem__(self, key):
3838
try:
39-
return super().__getitem__(key)
39+
return super(CustomDict, self).__getitem__(key)
4040
except KeyError:
4141
raise VariableError
4242

@@ -48,7 +48,7 @@ def __init__(self, key, type, **args):
4848
#required_or = [set(csl.VARIABLES)]
4949
optional = ({'uri', 'container_uri', 'contributor', 'date'} |
5050
set(VARIABLES))
51-
super().__init__(args, optional=optional)
51+
super(Reference, self).__init__(args, optional=optional)
5252

5353
def __repr__(self):
5454
return '{}({})'.format(self.__class__.__name__, self.key)
@@ -67,7 +67,7 @@ def __init__(self, **args):
6767
required = {'family'}
6868
optional = {'given', 'dropping-particle', 'non-dropping-particle',
6969
'suffix'}
70-
super().__init__(args, required, optional)
70+
super(Name, self).__init__(args, required, optional)
7171

7272
def parts(self):
7373
return (self.get('given'), self.get('family'),
@@ -78,7 +78,7 @@ def parts(self):
7878
class DateBase(CustomDict):
7979
def __init__(self, args, required=set(), optional=set()):
8080
optional = {'circa'} | optional
81-
super().__init__(args, required, optional)
81+
super(DateBase, self).__init__(args, required, optional)
8282
# defaults
8383
if 'circa' not in self:
8484
self['circa'] = False
@@ -92,7 +92,7 @@ def __init__(self, **args):
9292
raise TypeError('When specifying the day, you should also specify '
9393
'the month')
9494
args = {key: int(value) for key, value in args.items()}
95-
super().__init__(args, required, optional)
95+
super(Date, self).__init__(args, required, optional)
9696

9797
def sort_key(self):
9898
year = self.year
@@ -108,7 +108,7 @@ def is_nil(self):
108108
class LiteralDate(DateBase):
109109
def __init__(self, text, **args):
110110
self.text = text
111-
super().__init__(args)
111+
super(LiteralDate, self).__init__(args)
112112

113113
def sort_key(self):
114114
return self.text
@@ -118,7 +118,7 @@ class DateRange(DateBase):
118118
def __init__(self, **args):
119119
required = {'begin'}
120120
optional = {'end'}
121-
super().__init__(args, required, optional)
121+
super(DateRange, self).__init__(args, required, optional)
122122

123123
def sort_key(self):
124124
begin = self.begin.sort_key()
@@ -139,15 +139,15 @@ def __init__(self, **args):
139139
args[key] = int(value)
140140
except ValueError:
141141
pass
142-
super().__init__(args, required, optional)
142+
super(Pages, self).__init__(args, required, optional)
143143

144144

145145
class Citation(CustomDict):
146146
def __init__(self, cites, **kwargs):
147147
for cite in cites:
148148
cite.citation = self
149149
self.cites = cites
150-
super().__init__(kwargs)
150+
super(Citation, self).__init__(kwargs)
151151

152152
def __repr__(self):
153153
cites = ', '.join([cite.key for cite in self.cites])
@@ -158,7 +158,7 @@ class CitationItem(CustomDict):
158158
def __init__(self, key, bibliography=None, **args):
159159
self.key = key.lower()
160160
optional = {'locator', 'prefix', 'suffix'}
161-
super().__init__(args, optional=optional)
161+
super(CitationItem, self).__init__(args, optional=optional)
162162

163163
def __repr__(self):
164164
return '{}({})'.format(self.__class__.__name__, self.key)

citeproc/source/bibtex/bibparse.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
from __future__ import print_function, unicode_literals
2+
3+
from ...py2compat import string_types
14

25
import unicodedata
36

@@ -6,7 +9,7 @@
69

710
class BibTeXEntry(dict):
811
def __init__(self, document_type, attributes):
9-
super().__init__(attributes)
12+
super(BibTeXEntry, self).__init__(attributes)
1013
self.document_type = document_type
1114

1215

@@ -26,7 +29,7 @@ class BibTeXParser(dict):
2629

2730
def __init__(self, file_or_filename):
2831
try:
29-
self.file = open(file_or_filename, 'r')
32+
self.file = open(file_or_filename, 'rt')
3033
except TypeError:
3134
self.file = file_or_filename
3235
self.variables = {}
@@ -47,7 +50,7 @@ def _parse(self, file):
4750
self._parse_preamble(self._preamble)
4851
for key, entry in self.items():
4952
for attribute, value in entry.items():
50-
if isinstance(value, str):
53+
if isinstance(value, string_types):
5154
entry[attribute] = self._expand_macros(value)
5255

5356
def _parse_entry(self, file):
@@ -164,7 +167,7 @@ def _parse_variable(self, file, char):
164167
def _parse_integer(self, file, char):
165168
integer = ''
166169
restore_point = file.tell()
167-
while char.isnumeric():
170+
while char.isdigit():
168171
integer += char
169172
restore_point = file.tell()
170173
char = file.read(1)

citeproc/source/bibtex/bibtex.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-

1+
from __future__ import print_function, unicode_literals
2+
23
import re
34

45
from warnings import warn
@@ -195,10 +196,10 @@ def _parse_author(self, authors):
195196
csl_authors = []
196197
for author in authors.split(' and '):
197198
if ',' in author:
198-
family, given = map(str.strip, author.split(',', 1))
199+
family, given = [a.strip() for a in author.split(',', 1)]
199200
name = Name(family=family, given=given)
200201
elif ' ' in author:
201-
given, family = map(str.strip, author.rsplit(' ', 1))
202+
given, family = [a.strip() for a in author.rsplit(' ', 1)]
202203
name = Name(family=family, given=given)
203204
else:
204205
# TODO: handle 'others'

citeproc/string.py

+13-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
from __future__ import print_function, unicode_literals
12

3+
from .py2compat import text_type
24

3-
class String(str):
5+
class String(text_type):
46
def __radd__(self, other):
57
return MixedString([other]).__add__(self)
68

@@ -11,16 +13,16 @@ def __iadd__(self, other):
1113
return self.__add__(other)
1214

1315
def replace(self, *args, **kwargs):
14-
return self.__class__(super().replace(*args, **kwargs))
16+
return self.__class__(super(String, self).replace(*args, **kwargs))
1517

1618
def rstrip(self, *args, **kwargs):
17-
return self.__class__(super().rstrip(*args, **kwargs))
19+
return self.__class__(super(String, self).rstrip(*args, **kwargs))
1820

1921
def lower(self):
20-
return self.__class__(super().lower())
22+
return self.__class__(super(String, self).lower())
2123

2224
def upper(self):
23-
return self.__class__(super().upper())
25+
return self.__class__(super(String, self).upper())
2426

2527
def soft_lower(self):
2628
return self.lower()
@@ -39,9 +41,10 @@ def words(self):
3941
class MixedString(list):
4042
def __add__(self, other):
4143
try:
42-
return self.__class__(super().__add__(other))
44+
return self.__class__(super(MixedString, self).__add__(other))
4345
except TypeError:
44-
return self.__class__(super().__add__(__class__([other])))
46+
return self.__class__(super(MixedString, self).__add__(
47+
self.__class__([other])))
4548

4649
def __radd__(self, other):
4750
return self.__class__([other]).__add__(self)
@@ -50,7 +53,7 @@ def __iadd__(self, other):
5053
return self.__add__(other)
5154

5255
def __str__(self):
53-
return ''.join(map(str, self))
56+
return ''.join(map(text_type, self))
5457

5558
def __getitem__(self, index):
5659
return str(self)[index]
@@ -80,7 +83,7 @@ def isupper(self):
8083
return all(string.isupper() for string in self)
8184

8285
def split(self, *args, **kwargs):
83-
return str(self).split(*args, **kwargs)
86+
return text_type(self).split(*args, **kwargs)
8487

8588
def rstrip(self, *args, **kwargs):
8689
rev_iter = reversed(self)
@@ -96,7 +99,7 @@ def words(self):
9699

97100
class NoCase(String):
98101
def __repr__(self):
99-
return '{}({})'.format(self.__class__.__name__, str(self))
102+
return '{}({})'.format(self.__class__.__name__, text_type(self))
100103

101104
def soft_lower(self):
102105
return self

examples/bibtex.py

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from __future__ import print_function, unicode_literals
12

23
# The references are parsed from a BibTeX database, so we import the
34
# corresponding parser.
File renamed without changes.

tests/citeproc-test.py

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
1+
from __future__ import (print_function, unicode_literals, absolute_import,
2+
division)
23

34
import glob
45
import io
@@ -215,8 +216,12 @@ def main():
215216
failed.append(test_name)
216217

217218
def print_result(name, passed, total):
218-
print('{:<13} {:>3} / {:>3} ({:>4.0%})'
219-
.format(name, passed, total, passed / total), file=destination)
219+
if total == 0:
220+
print('<no tests found>: check README.md file for instructions')
221+
else:
222+
print('{:<13} {:>3} / {:>3} ({:>4.0%})'.format(
223+
name, passed, total, passed / total),
224+
file=destination)
220225

221226
print('Failed tests:')
222227
for test_name in failed:

0 commit comments

Comments
 (0)