Skip to content

Commit

Permalink
Merge pull request #5 from zopefoundation/py3
Browse files Browse the repository at this point in the history
Port to Python 3
  • Loading branch information
mgedmin committed Feb 26, 2019
2 parents eeb4e2e + 3d14313 commit d7f85c9
Show file tree
Hide file tree
Showing 13 changed files with 427 additions and 328 deletions.
7 changes: 7 additions & 0 deletions .coveragerc
@@ -0,0 +1,7 @@
[run]
source = zc.zservertracelog

[report]
exclude_lines =
pragma: nocover
if __name__ == .__main__.:
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -9,3 +9,4 @@ build/
dist/
*.egg-info/
.tox/
.coverage
17 changes: 12 additions & 5 deletions .travis.yml
@@ -1,12 +1,19 @@
language: python
sudo: false
dist: xenial
python:
- 2.6
- 2.7
- 3.4
- 3.5
- 3.6
- 3.7
- pypy2.7-6.0.0
- pypy3.5-6.0.0
install:
- python bootstrap.py
- bin/buildout
- pip install coveralls coverage zope.testrunner
- pip install -e .[test]
script:
- bin/test -pvc
- coverage run -m zope.testrunner --test-path=src -pvc
after_success:
- coveralls
notifications:
email: false
11 changes: 9 additions & 2 deletions CHANGES.rst
@@ -1,10 +1,17 @@
Changes
=======

1.4.1 (unreleased)
2.0.0 (unreleased)
------------------

- Nothing changed yet.
- Fix logic bug in seconds_difference() that could introduce error up to nearly
a whole second for any particular event.

- Limit number precision in HTML reports to 3 decimal digits.

- Drop Python 2.6 support.

- Add Python 3.4 through 3.7 support.


1.4.0 (2015-05-06)
Expand Down
2 changes: 1 addition & 1 deletion MANIFEST.in
Expand Up @@ -3,5 +3,5 @@ include *.rst
include buildout.cfg
include tox.ini
recursive-include src *.log
recursive-include src *.txt
recursive-include src *.rst
recursive-include src *.zcml
21 changes: 15 additions & 6 deletions setup.py
Expand Up @@ -22,7 +22,7 @@ def read(*rnames):

setup(
name='zc.zservertracelog',
version='1.4.1.dev0',
version='2.0.0.dev0',
url='https://github.com/zopefoundation/zc.zservertracelog',
author='Zope Corporation and Contributors',
author_email='zope3-dev@zope.org',
Expand All @@ -34,23 +34,32 @@ def read(*rnames):
),
license='ZPL 2.1',
keywords='zope3',
classifiers=[
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
],
packages=find_packages('src'),
namespace_packages=['zc'],
package_dir={'': 'src'},
install_requires=[
'setuptools',
'six',
'zope.app.appsetup',
'zope.app.server',
'zope.app.wsgi',
'zope.component',
'zope.interface',
'zope.publisher',
'zope.server',
],
extras_require=dict(
test=[
# Our test suite uses zope.testing.doctest.INTERPRET_FOOTNOTES
# That feature is gone from zope.testing 4.0.0 with the entire
# zope.testing.doctest fork of the stdlib's doctest. The proper
# way forward would be to switch to Manuel.
'zope.testing < 4.0.0',
'manuel',
],
),
include_package_data=True,
Expand Down
Expand Up @@ -57,7 +57,7 @@ Let's also define a convenience function for processing requests.

Process a simple request.

>>> req1 = """\
>>> req1 = b"""\
... GET /test-req1 HTTP/1.1
... Host: www.example.com
...
Expand Down Expand Up @@ -150,7 +150,7 @@ Log Messages Containing Line Breaks
Messages to the tracelog that contain newline characters will not split a log
entry into multiple lines.

>>> req2 = """\
>>> req2 = b"""\
... GET /test-req2/%0Aohnoes/ HTTP/1.1
... Host: www.example.com/linebreak
...
Expand All @@ -169,7 +169,7 @@ Request Query Strings

The tracelog preserves request query strings.

>>> req3 = """\
>>> req3 = b"""\
... GET /test-req3/?creature=unicorn HTTP/1.1
... Host: www.example.com/query-string
...
Expand Down
54 changes: 32 additions & 22 deletions src/zc/zservertracelog/fseek.py
@@ -1,9 +1,13 @@
import StringIO
import string
import unittest

from six.moves import cStringIO as StringIO

def fseek(f, size, search, getkey=string.strip):

def strip(s):
return s.strip()


def fseek(f, size, search, getkey=strip):
# Check first line
key = getkey(f.readline())
if key >= search:
Expand All @@ -12,15 +16,15 @@ def fseek(f, size, search, getkey=string.strip):

seen = 0
position = 0
seek = chunk = size / 2
seek = chunk = size // 2
while chunk > 0:
f.seek(seek)
line = f.readline() # maybe incomplete
line = f.readline() # maybe incomplete
position = f.tell()
line = f.readline() # complete
line = f.readline() # complete
key = getkey(line)

chunk /= 2
chunk //= 2

if key >= search:
seek -= chunk
Expand All @@ -37,7 +41,7 @@ def fseek(f, size, search, getkey=string.strip):

def _get_btree_args(*lines):
content = '\n'.join(lines)
f = StringIO.StringIO(content)
f = StringIO(content)
size = len(content)
return (f, size)

Expand All @@ -60,16 +64,20 @@ def test_1(self):
p = fseek(f, size, '0')
self.assertEqual(p, 0)

f.seek(0) ; p = fseek(f, size, '1')
f.seek(0)
p = fseek(f, size, '1')
self.assertEqual(p, 2)

f.seek(0) ; p = fseek(f, size, '2')
f.seek(0)
p = fseek(f, size, '2')
self.assertEqual(p, 4)

f.seek(0) ; p = fseek(f, size, '3')
f.seek(0)
p = fseek(f, size, '3')
self.assertEqual(p, 6)

f.seek(0) ; p = fseek(f, size, '4')
f.seek(0)
p = fseek(f, size, '4')
self.assertEqual(p, 8)

def test_2(self):
Expand All @@ -88,10 +96,12 @@ def test_2(self):
p = fseek(f, size, '0')
self.assertEqual(p, 0)

f.seek(0) ; p = fseek(f, size, '1')
f.seek(0)
p = fseek(f, size, '1')
self.assertEqual(p, 6)

f.seek(0) ; p = fseek(f, size, '2')
f.seek(0)
p = fseek(f, size, '2')
self.assertEqual(p, 12)

def test_3(self):
Expand All @@ -106,18 +116,18 @@ def test_3(self):
p = fseek(f, size, '0')
self.assertEqual(p, 0)

f.seek(0) ; p = fseek(f, size, '1', _get_colon_key)
f.seek(0)
p = fseek(f, size, '1', _get_colon_key)
self.assertEqual(p, 16)

f.seek(0) ; p = fseek(f, size, '2', _get_colon_key)
f.seek(0)
p = fseek(f, size, '2', _get_colon_key)
self.assertEqual(p, 26)

f.seek(0) ; p = fseek(f, size, '3', _get_colon_key)
f.seek(0)
p = fseek(f, size, '3', _get_colon_key)
self.assertEqual(p, 67)

f.seek(0) ; p = fseek(f, size, '4', _get_colon_key)
f.seek(0)
p = fseek(f, size, '4', _get_colon_key)
self.assertEqual(p, 76)


if __name__ == '__main__':
unittest.main()
55 changes: 36 additions & 19 deletions src/zc/zservertracelog/tests.py
Expand Up @@ -16,26 +16,40 @@
"""
__docformat__ = "reStructuredText"

from zope.testing import doctest
import datetime
import doctest
import os
import re
import unittest

import manuel.doctest
import manuel.footnote
import manuel.testing
import zope.testing.renormalizing

from zc.zservertracelog.fseek import FSeekTest
from zc.zservertracelog.fseek import FSeekTest # noqa
from zc.zservertracelog.tracereport import seconds_difference


here = os.path.dirname(os.path.abspath(__file__))

optionflags = (
doctest.NORMALIZE_WHITESPACE
| doctest.ELLIPSIS
| doctest.REPORT_ONLY_FIRST_FAILURE
)

checker = zope.testing.renormalizing.RENormalizing([
# normalize the channel id and iso8601 timestamp
(re.compile(r'-?\d+ \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{6}'),
'23418928 2008-08-26 10:55:00.000000'),
(re.compile(r'^usage: '), 'Usage: '),
(re.compile(r'options:'), 'Options:'),
(re.compile(r'zope-testrunner'), 'test'), # sys.argv[0] when run from tox
])

_null_app = lambda environ, start_response: None

def _null_app(environ, start_response):
pass


class FauxApplication(object):
Expand All @@ -48,6 +62,14 @@ def __call__(self, environ, start_response):
return app(environ, start_response)


class TestHelpers(unittest.TestCase):

def test_seconds_difference(self):
dt1 = datetime.datetime(2019, 2, 23, 14, 5, 54, 451)
dt2 = dt1 + datetime.timedelta(minutes=15, seconds=3, microseconds=42)
self.assertEqual(seconds_difference(dt2, dt1), 15 * 60 + 3 + 0.000042)


def setUp(test):
test.globs['FauxApplication'] = FauxApplication

Expand All @@ -57,21 +79,16 @@ def analysis_setUp(test):


def test_suite():
tests = [
m = manuel.doctest.Manuel(
optionflags=optionflags,
checker=checker,
)
m += manuel.footnote.Manuel()
return unittest.TestSuite([
manuel.testing.TestSuite(m, 'README.rst', setUp=setUp),
doctest.DocFileTest(
'README.txt',
optionflags=(
doctest.NORMALIZE_WHITESPACE
| doctest.ELLIPSIS
| doctest.INTERPRET_FOOTNOTES),
checker=checker,
setUp=setUp,
),
doctest.DocFileTest(
'tracereport.txt',
'tracereport.rst',
checker=checker,
setUp=analysis_setUp),
unittest.makeSuite(FSeekTest),
]

return unittest.TestSuite(tests)
unittest.defaultTestLoader.loadTestsFromName(__name__),
])

0 comments on commit d7f85c9

Please sign in to comment.