Skip to content

Commit 2d7519d

Browse files
committed
Merge branch 'feat/py3_without_2to3'
* feat/py3_without_2to3: No longer need to call 2to3 during build. Use __name__ instead of func_name for compatibility with Python 3. Unicode→str kwargs hack only needed for Python <2.7. Wrap print statement/function in scripts for compatibility. Remove library rebuild hack in tox config. Removed now unused build path hack in tests. No need for unicode→str kwargs hack in Python 3. Use Python 2 & 3 compatible syntax for metaclass usage. Attempt to import using Python 3 stdlib names first. Conflicts: github2/core.py github2/request.py
2 parents e221921 + c6afe29 commit 2d7519d

22 files changed

Lines changed: 84 additions & 70 deletions

github2/bin/manage_collaborators.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,27 @@
1212
# BSD licensed
1313

1414
import logging
15+
import sys
16+
1517
from optparse import OptionParser
18+
1619
import github2.client
1720

1821

22+
#: Running under Python 3
23+
PY3K = sys.version_info[0] == 3 and True or False
24+
25+
26+
def print_(text):
27+
"""Python 2 & 3 compatible print function
28+
29+
We support <2.6, so can't use __future__.print_function"""
30+
if PY3K:
31+
print(text)
32+
else:
33+
sys.stdout.write(text + '\n')
34+
35+
1936
def parse_commandline():
2037
"""Parse the comandline and return parsed options."""
2138

@@ -72,19 +89,19 @@ def main():
7289
if len(args) == 1:
7390
for repos in github.repos.list(options.account):
7491
fullreposname = github.project_for_user_repo(options.account, repos.name)
75-
print "%s: %s" % (repos.name, ' '.join(github.repos.list_collaborators(fullreposname)))
92+
print_("%s: %s" % (repos.name, ' '.join(github.repos.list_collaborators(fullreposname))))
7693
elif len(args) == 2:
7794
command, collaborator = args
7895
for repos in github.repos.list(options.account):
7996
fullreposname = github.project_for_user_repo(options.account, repos.name)
8097
if collaborator in github.repos.list_collaborators(fullreposname):
8198
if command == 'remove':
8299
github.repos.remove_collaborator(repos.name, collaborator)
83-
print "removed %r from %r" % (collaborator, repos.name)
100+
print_("removed %r from %r" % (collaborator, repos.name))
84101
else:
85102
if command == 'add':
86103
github.repos.add_collaborator(repos.name, collaborator)
87-
print "added %r to %r" % (collaborator, repos.name)
104+
print_("added %r to %r" % (collaborator, repos.name))
88105

89106
logging.shutdown()
90107

github2/bin/search_repos.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,20 @@
1212
import github2.client
1313

1414

15+
#: Running under Python 3
16+
PY3K = sys.version_info[0] == 3 and True or False
17+
18+
19+
def print_(text):
20+
"""Python 2 & 3 compatible print function
21+
22+
We support <2.6, so can't use __future__.print_function"""
23+
if PY3K:
24+
print(text)
25+
else:
26+
sys.stdout.write(text + '\n')
27+
28+
1529
def parse_commandline():
1630
"""Parse the comandline and return parsed options."""
1731

@@ -47,14 +61,14 @@ def main():
4761

4862
repos = github.repos.search(term)
4963
if not repos:
50-
print 'No repos found!'
64+
print_('No repos found!')
5165
return_value = 255
5266
else:
5367
for repo in repos:
54-
print repo.project
68+
print(repo.project)
5569
if repo.description:
56-
print '\n'.join(wrap(repo.description, initial_indent=' ',
57-
subsequent_indent=' '))
70+
print_('\n'.join(wrap(repo.description, initial_indent=' ',
71+
subsequent_indent=' ')))
5872

5973
logging.shutdown()
6074
return return_value

github2/core.py

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
#: Running under Python 3
1010
PY3K = sys.version_info[0] == 3 and True or False
1111

12+
#: Running under Python 2.7, or newer
13+
PY27 = sys.version_info[:2] == 3 and True or False
14+
1215
GITHUB_DATE_FORMAT = "%Y/%m/%d %H:%M:%S %z"
1316
# We need to manually mangle the timezone for commit date formatting because it
1417
# uses -xx:xx format
@@ -158,22 +161,26 @@ def get_value(self, *args, **kwargs):
158161
datatype = kwargs.pop("datatype", None)
159162
value = self.make_request(*args, **kwargs)
160163
if datatype:
161-
# unicode keys are not accepted as kwargs by python, see:
162-
#http://mail-archives.apache.org/mod_mbox/qpid-dev/200609.mbox/%3C1159389941.4505.10.camel@localhost.localdomain%3E
163-
# So we make a local dict with the same keys but as strings:
164-
return datatype(**dict((str(k), v)
165-
for (k, v) in value.iteritems()))
164+
if not PY27:
165+
# unicode keys are not accepted as kwargs by python, until 2.7:
166+
# http://bugs.python.org/issue2646
167+
# So we make a local dict with the same keys but as strings:
168+
return datatype(**dict((str(k), v) for (k, v) in value.items()))
169+
else:
170+
return datatype(**value)
166171
return value
167172

168173
def get_values(self, *args, **kwargs):
169174
datatype = kwargs.pop("datatype", None)
170175
values = self.make_request(*args, **kwargs)
171176
if datatype:
172-
# Same as above, unicode keys will blow up in **args, so we need to
173-
# create a new 'values' dict with string keys
174-
return [datatype(**dict((str(k), v)
175-
for (k, v) in value.iteritems()))
176-
for value in values]
177+
if not PY27:
178+
# Same as above, unicode keys will blow up in **args, so we need to
179+
# create a new 'values' dict with string keys
180+
return [datatype(**dict((str(k), v) for (k, v) in value.items()))
181+
for value in values]
182+
else:
183+
return [datatype(**value) for value in values]
177184
else:
178185
return values
179186

@@ -243,7 +250,7 @@ def __new__(cls, name, bases, attrs):
243250
for attr_name in attributes]))
244251

245252
def _contribute_method(name, func):
246-
func.func_name = name
253+
func.__name__ = name
247254
attrs[name] = func
248255

249256
def constructor(self, **kwargs):
@@ -265,9 +272,9 @@ def iterate(self):
265272
return result_cls
266273

267274

268-
class BaseData(object):
269-
__metaclass__ = BaseDataType
270-
275+
# Ugly base class definition for Python 2 and 3 compatibility, where metaclass
276+
# syntax is incompatible
277+
class BaseData(BaseDataType('BaseData', (object, ), {})):
271278
def __getitem__(self, key):
272279
"""Access objects's attribute using subscript notation
273280

github2/issues.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import urllib
1+
try:
2+
from urllib.parse import quote_plus # For Python 3
3+
except ImportError:
4+
from urllib import quote_plus
25

36
from github2.core import (GithubCommand, BaseData, Attribute, DateAttribute,
47
repr_string, requires_auth)
@@ -47,9 +50,8 @@ def search(self, project, term, state="open"):
4750
:param str term: term to search issues for
4851
:param str state: can be either ``open`` or ``closed``.
4952
"""
50-
return self.get_values("search", project, state,
51-
urllib.quote_plus(term), filter="issues",
52-
datatype=Issue)
53+
return self.get_values("search", project, state, quote_plus(term),
54+
filter="issues", datatype=Issue)
5355

5456
def list(self, project, state="open"):
5557
"""Get all issues for project with given state.

github2/request.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,29 @@
44
import time
55
import httplib2
66
try:
7+
# For Python 3
8+
from http.client import responses
9+
except ImportError: # For Python 2.5-2.7
710
from httplib import responses
811
except ImportError: # For Python 2.4
912
from BaseHTTPServer import BaseHTTPRequestHandler
1013
responses = dict([(k, v[0])
1114
for k, v in BaseHTTPRequestHandler.responses.items()])
1215
try:
13-
import json as simplejson # For Python 2.6
16+
import json as simplejson # For Python 2.6+
1417
except ImportError:
1518
import simplejson
1619
from os import path
17-
from urlparse import (urlsplit, urlunsplit)
1820
try:
19-
from urlparse import parse_qs
21+
# For Python 3
22+
from urllib.parse import (parse_qs, quote, urlencode, urlsplit, urlunsplit)
2023
except ImportError:
21-
from cgi import parse_qs
22-
from urllib import urlencode, quote
24+
from urlparse import (urlsplit, urlunsplit)
25+
try:
26+
from urlparse import parse_qs
27+
except ImportError:
28+
from cgi import parse_qs
29+
from urllib import urlencode, quote
2330

2431

2532
#: Hostname for API access

github2/users.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
try:
2+
from urllib.parse import quote_plus # For Python 3
3+
except ImportError:
4+
from urllib import quote_plus
5+
16
from github2.core import (BaseData, GithubCommand, DateAttribute, Attribute,
27
enhanced_by_auth, requires_auth)
3-
import urllib
48

59

610
class User(BaseData):
@@ -48,8 +52,8 @@ def search(self, query):
4852
4953
:param str query: term to search for
5054
"""
51-
return self.get_values("search", urllib.quote_plus(query),
52-
filter="users", datatype=User)
55+
return self.get_values("search", quote_plus(query), filter="users",
56+
datatype=User)
5357

5458
def search_by_email(self, query):
5559
"""Search for users by email address

setup.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,8 @@
1313
if sys.version_info[:2] < (2, 6):
1414
install_requires.append('simplejson >= 2.0.9')
1515

16-
extra = {}
1716
if sys.version_info >= (3,):
1817
install_requires.append('python-dateutil >= 2.0')
19-
extra['use_2to3'] = True
2018
else:
2119
install_requires.append('python-dateutil < 2.0')
2220

@@ -64,5 +62,4 @@
6462
"Topic :: Software Development",
6563
"Topic :: Software Development :: Libraries",
6664
],
67-
**extra
6865
)

tests/_setup.py

Lines changed: 0 additions & 6 deletions
This file was deleted.

tests/test_charset_header.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import _setup
2-
31
from nose.tools import assert_equals
42

53
from github2.request import charset_from_headers

tests/test_commits.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import _setup
2-
31
from nose.tools import assert_equals
42

53
import utils

0 commit comments

Comments
 (0)