Skip to content

Commit

Permalink
Merge pull request Pylons#1471 from Pylons/feature.py3-coverage
Browse files Browse the repository at this point in the history
update tox/travis to check code coverage on py3
  • Loading branch information
mmerickel committed Mar 5, 2015
2 parents 17997b3 + d476e69 commit 6c1a1c6
Show file tree
Hide file tree
Showing 23 changed files with 112 additions and 100 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@
*~
.*.swp
.coverage
.coverage.*
.tox/
nosetests.xml
coverage.xml
nosetests-*.xml
coverage-*.xml
tutorial.db
build/
dist/
Expand Down
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ env:
- TOXENV=py34
- TOXENV=pypy
- TOXENV=pypy3
- TOXENV=cover
- TOXENV=py2-docs
- TOXENV=py3-docs
- TOXENV=py2-cover,py3-cover,coverage

install:
- travis_retry pip install tox
Expand Down
3 changes: 3 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ Features
- Added support / testing for 'pypy3' under Tox and Travis.
See https://github.com/Pylons/pyramid/pull/1469

- Automate code coverage metrics across py2 and py3 instead of just py2.
See https://github.com/Pylons/pyramid/pull/1471

- Cache busting for static resources has been added and is available via a new
argument to ``pyramid.config.Configurator.add_static_view``: ``cachebust``.
Core APIs are shipped for both cache busting via query strings and
Expand Down
55 changes: 25 additions & 30 deletions pyramid/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
# True if we are running on Python 3.
PY3 = sys.version_info[0] == 3

if PY3: # pragma: no cover
if PY3:
string_types = str,
integer_types = int,
class_types = type,
Expand All @@ -38,23 +38,21 @@
binary_type = str
long = long


def text_(s, encoding='latin-1', errors='strict'):
""" If ``s`` is an instance of ``binary_type``, return
``s.decode(encoding, errors)``, otherwise return ``s``"""
if isinstance(s, binary_type):
return s.decode(encoding, errors)
return s # pragma: no cover

return s

def bytes_(s, encoding='latin-1', errors='strict'):
""" If ``s`` is an instance of ``text_type``, return
``s.encode(encoding, errors)``, otherwise return ``s``"""
if isinstance(s, text_type): # pragma: no cover
if isinstance(s, text_type):
return s.encode(encoding, errors)
return s

if PY3: # pragma: no cover
if PY3:
def ascii_native_(s):
if isinstance(s, text_type):
s = s.encode('ascii')
Expand All @@ -74,7 +72,7 @@ def ascii_native_(s):
"""


if PY3: # pragma: no cover
if PY3:
def native_(s, encoding='latin-1', errors='strict'):
""" If ``s`` is an instance of ``text_type``, return
``s``, otherwise return ``str(s, encoding, errors)``"""
Expand All @@ -97,7 +95,7 @@ def native_(s, encoding='latin-1', errors='strict'):
``s.encode(encoding, errors)``, otherwise return ``str(s)``
"""

if PY3: # pragma: no cover
if PY3:
from urllib import parse
urlparse = parse
from urllib.parse import quote as url_quote
Expand Down Expand Up @@ -174,13 +172,13 @@ def iterkeys_(d):
return d.iterkeys()


if PY3: # pragma: no cover
if PY3:
def map_(*arg):
return list(map(*arg))
else:
map_ = map

if PY3: # pragma: no cover
if PY3:
def is_nonstr_iter(v):
if isinstance(v, str):
return False
Expand All @@ -189,51 +187,48 @@ def is_nonstr_iter(v):
def is_nonstr_iter(v):
return hasattr(v, '__iter__')

if PY3: # pragma: no cover
if PY3:
im_func = '__func__'
im_self = '__self__'
else:
im_func = 'im_func'
im_self = 'im_self'

try: # pragma: no cover
try:
import configparser
except ImportError: # pragma: no cover
except ImportError:
import ConfigParser as configparser

try:
from Cookie import SimpleCookie
except ImportError: # pragma: no cover
from http.cookies import SimpleCookie
except ImportError:
from Cookie import SimpleCookie

if PY3: # pragma: no cover
if PY3:
from html import escape
else:
from cgi import escape

try: # pragma: no cover
input_ = raw_input
except NameError: # pragma: no cover
if PY3:
input_ = input
else:
input_ = raw_input


# support annotations and keyword-only arguments in PY3
if PY3: # pragma: no cover
if PY3:
from inspect import getfullargspec as getargspec
else:
from inspect import getargspec

try:
from StringIO import StringIO as NativeIO
except ImportError: # pragma: no cover
if PY3:
from io import StringIO as NativeIO
else:
from io import BytesIO as NativeIO

# "json" is not an API; it's here to support older pyramid_debugtoolbar
# versions which attempt to import it
import json


if PY3: # pragma: no cover
if PY3:
# see PEP 3333 for why we encode WSGI PATH_INFO to latin-1 before
# decoding it to utf-8
def decode_path_info(path):
Expand All @@ -242,8 +237,8 @@ def decode_path_info(path):
def decode_path_info(path):
return path.decode('utf-8')

if PY3: # pragma: no cover
# see PEP 3333 for why we decode the path to latin-1
if PY3:
# see PEP 3333 for why we decode the path to latin-1
from urllib.parse import unquote_to_bytes

def unquote_bytes_to_wsgi(bytestring):
Expand Down Expand Up @@ -277,7 +272,7 @@ def is_unbound_method(fn):
is_bound = is_bound_method(fn)

if not is_bound and inspect.isroutine(fn):
spec = inspect.getargspec(fn)
spec = getargspec(fn)
has_self = len(spec.args) > 0 and spec.args[0] == 'self'

if PY3 and inspect.isfunction(fn) and has_self: # pragma: no cover
Expand Down
8 changes: 4 additions & 4 deletions pyramid/i18n.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,9 +331,9 @@ def dugettext(self, domain, message):
"""Like ``ugettext()``, but look the message up in the specified
domain.
"""
if PY3: # pragma: no cover
if PY3:
return self._domains.get(domain, self).gettext(message)
else: # pragma: no cover
else:
return self._domains.get(domain, self).ugettext(message)

def dngettext(self, domain, singular, plural, num):
Expand All @@ -352,10 +352,10 @@ def dungettext(self, domain, singular, plural, num):
"""Like ``ungettext()`` but look the message up in the specified
domain.
"""
if PY3: # pragma: no cover
if PY3:
return self._domains.get(domain, self).ngettext(
singular, plural, num)
else: # pragma: no cover
else:
return self._domains.get(domain, self).ungettext(
singular, plural, num)

Expand Down
4 changes: 2 additions & 2 deletions pyramid/scaffolds/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
import time

try:
import http.client as httplib
except ImportError:
import httplib
except ImportError: # pragma: no cover
import http.client as httplib #py3

class TemplateTest(object):
def make_venv(self, directory): # pragma: no cover
Expand Down
8 changes: 0 additions & 8 deletions pyramid/tests/test_config/pkgs/asset/models.py

This file was deleted.

22 changes: 0 additions & 22 deletions pyramid/tests/test_config/pkgs/asset/views.py

This file was deleted.

2 changes: 1 addition & 1 deletion pyramid/tests/test_config/test_adapters.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ class Adapter(object):
def test_add_response_adapter_dottednames(self):
from pyramid.interfaces import IResponse
config = self._makeOne(autocommit=True)
if PY3: # pragma: no cover
if PY3:
str_name = 'builtins.str'
else:
str_name = '__builtin__.str'
Expand Down
2 changes: 1 addition & 1 deletion pyramid/tests/test_path.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ def config_exc(self, func, *arg, **kw):

def test_zope_dottedname_style_resolve_builtin(self):
typ = self._makeOne()
if PY3: # pragma: no cover
if PY3:
result = typ._zope_dottedname_style('builtins.str', None)
else:
result = typ._zope_dottedname_style('__builtin__.str', None)
Expand Down
2 changes: 1 addition & 1 deletion pyramid/tests/test_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ def test_json_body_alternate_charset(self):
b'/\xe6\xb5\x81\xe8\xa1\x8c\xe8\xb6\x8b\xe5\x8a\xbf',
'utf-8'
)
if PY3: # pragma: no cover
if PY3:
body = bytes(json.dumps({'a':inp}), 'utf-16')
else:
body = json.dumps({'a':inp}).decode('utf-8').encode('utf-16')
Expand Down
1 change: 0 additions & 1 deletion pyramid/tests/test_scripts/pystartup.py

This file was deleted.

3 changes: 3 additions & 0 deletions pyramid/tests/test_scripts/pystartup.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# this file has a .txt extension to avoid coverage reports
# since it is not imported but rather the contents are read and exec'd
foo = 1
2 changes: 1 addition & 1 deletion pyramid/tests/test_scripts/test_pserve.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import unittest

from pyramid.compat import PY3
if PY3: # pragma: no cover
if PY3:
import builtins as __builtin__
else:
import __builtin__
Expand Down
2 changes: 1 addition & 1 deletion pyramid/tests/test_scripts/test_pshell.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ def test_command_loads_pythonstartup(self):
os.path.abspath(
os.path.join(
os.path.dirname(__file__),
'pystartup.py')))
'pystartup.txt')))
shell = dummy.DummyShell()
command.run(shell)
self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp')
Expand Down
2 changes: 1 addition & 1 deletion pyramid/tests/test_traversal.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ def test_call_with_vh_root_highorder(self):
foo = DummyContext(bar, path)
root = DummyContext(foo, 'root')
policy = self._makeOne(root)
if PY3: # pragma: no cover
if PY3:
vhm_root = b'/Qu\xc3\xa9bec'.decode('latin-1')
else:
vhm_root = b'/Qu\xc3\xa9bec'
Expand Down
2 changes: 1 addition & 1 deletion pyramid/tests/test_urldispatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def test_connect_static_overridden(self):
def test___call__pathinfo_cant_be_decoded(self):
from pyramid.exceptions import URLDecodeError
mapper = self._makeOne()
if PY3: # pragma: no cover
if PY3:
path_info = b'\xff\xfe\xe6\x00'.decode('latin-1')
else:
path_info = b'\xff\xfe\xe6\x00'
Expand Down
4 changes: 2 additions & 2 deletions pyramid/tests/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -431,9 +431,9 @@ def test_tuple(self):
self.assertEqual(self._callFUT(('a', 'b')), "('a', 'b')")

def test_set(self):
if PY3: # pragma: no cover
if PY3:
self.assertEqual(self._callFUT(set(['a'])), "{'a'}")
else: # pragma: no cover
else:
self.assertEqual(self._callFUT(set(['a'])), "set(['a'])")

def test_list(self):
Expand Down
2 changes: 1 addition & 1 deletion pyramid/traversal.py
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ def split_path_info(path):
"""


if PY3: # pragma: no cover
if PY3:
# special-case on Python 2 for speed? unchecked
def quote_path_segment(segment, safe=''):
""" %s """ % quote_path_segment_doc
Expand Down
2 changes: 1 addition & 1 deletion pyramid/urldispatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ def matcher(path):
def generator(dict):
newdict = {}
for k, v in dict.items():
if PY3: # pragma: no cover
if PY3:
if v.__class__ is binary_type:
# url_quote below needs a native string, not bytes on Py3
v = v.decode('utf-8')
Expand Down
2 changes: 1 addition & 1 deletion pyramid/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ def object_description(object):
if isinstance(object, (bool, float, type(None))):
return text_(str(object))
if isinstance(object, set):
if PY3: # pragma: no cover
if PY3:
return shortrepr(object, '}')
else:
return shortrepr(object, ')')
Expand Down
3 changes: 0 additions & 3 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ zip_ok = false
match=^test
where=pyramid
nocapture=1
cover-package=pyramid
cover-erase=1
cover-min-percentage=100

[aliases]
dev = develop easy_install pyramid[testing]
Expand Down
Loading

0 comments on commit 6c1a1c6

Please sign in to comment.