Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Python 3 support #51

Merged
merged 55 commits into from
May 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
9ef86b8
Start Python 3 porting
tomgross Aug 9, 2017
01ad691
Test Python 3 on travis
tomgross Aug 9, 2017
eb485af
Adjust path of buildout script
tomgross Aug 9, 2017
853e29e
More Py3 fixes
tomgross Aug 9, 2017
bad5608
text type fixes
tomgross Aug 9, 2017
8d52b2e
Test Python 3 via tox.
Aug 23, 2017
2906058
Ensure to use the newest non-pinned versions.
Aug 23, 2017
39a705e
Colorize output.
Aug 23, 2017
1faaf31
Fix imports.
Aug 23, 2017
91c9d83
Merge branch 'master' into py3
gotcha Oct 21, 2017
9dc0158
Let's not 3.5 until we got 3.6 working...
witsch Oct 21, 2017
1091141
avoid version conflict for py36 on Travis
gotcha Oct 21, 2017
9b9e1a3
Merge branch 'py3' of github.com:zopefoundation/Products.GenericSetup…
gotcha Oct 21, 2017
a5962e7
cache eggs on Travis
gotcha Oct 21, 2017
b52ae8e
revert change that broke python27 on Travis
gotcha Oct 21, 2017
132acb2
Allow to pass arguments to the testrunner.
witsch Oct 21, 2017
2bfac16
try to have buildout running under python36 on Travis
gotcha Oct 21, 2017
eb2c157
Pass explicit encoding (of "utf-8") when generating XML.
witsch Oct 21, 2017
a32024c
The value of the property will be (utf-8) encoded in Python 2.
witsch Oct 21, 2017
49b419c
With eb2c1578 all test XML snippets will need to be encoded (to bytes).
witsch Oct 21, 2017
1d95587
Let's use the latest beta KGS of Zope.
witsch Oct 21, 2017
651e7a2
Put (all) source checkouts into the top-level directory.
witsch Oct 21, 2017
b213541
Adjust to 'lines' property now storing bytes.
witsch Oct 21, 2017
a1dd854
Refactor tests to work with both Python 2 & 3.
witsch Oct 22, 2017
f65a104
(Mostly) fix handling of tarballs.
witsch Oct 22, 2017
bf4e7f3
Provide bytes when writing to files.
witsch Oct 22, 2017
9d04a80
get tests passing
davisagli Jan 1, 2018
ae3b4e7
Merge remote-tracking branch 'origin/master' into davisagli-py3
davisagli Jan 24, 2018
3293530
fix merge
davisagli Jan 24, 2018
bdbd8ae
fixes from @tseaver feedback
davisagli Jan 25, 2018
700ee09
Replace calls to filter(None, seq)by list comprehensions
davilima6 Feb 4, 2018
9aac94c
Fetch AccessControl from feature branch
davilima6 Feb 4, 2018
eb4dff1
do not use bytes for actions properties and report-filename in py3
pbauer Mar 24, 2018
98f06b9
Temporarily allow Python 3 failures to assure Python 2 stays green. (…
Apr 5, 2018
0f131a7
Revert "do not use bytes for actions properties and report-filename i…
pbauer Apr 5, 2018
6782252
fix report-generation
pbauer Apr 5, 2018
81bba2a
Fix RuntimeError: dictionary changed size during iteration
ale-rt Apr 9, 2018
d280dc4
Merge pull request #59 from zopefoundation/davisagli-py3-extension-1
ale-rt Apr 12, 2018
33abae2
- DateIndexes have a new property precision
dataflake May 13, 2018
ef6c7f9
- move Zope dependency to version 4.0b4 and get rid of all source che…
dataflake May 13, 2018
d6a12be
- Zope has dropped Python 3.4 compatibility, so it makes no sense here.
dataflake May 13, 2018
93bc544
- update change log and setup.py compatibility identifier [ci-skip]
dataflake May 13, 2018
6051b50
- downgrade Zope2 version - only Zope has a 4.0b4
dataflake May 13, 2018
ec7a77b
Merge branch 'master' into davisagli-py3
dataflake May 13, 2018
ab7f8b5
- change XML representation to fix last failing tests
dataflake May 13, 2018
bab3eea
- no longer allow failures in Python 3 tests
dataflake May 13, 2018
6b873bb
- add a test for importing older-style XML
dataflake May 13, 2018
3124f89
- drop ``Zope2`` egg dependency and use straight ``Zope`` instead
dataflake May 14, 2018
009fab8
Zope2 is no more, long live Zope!
May 15, 2018
5018a9a
Prepare merge to default.
May 15, 2018
a7e074a
- add a test for importing ISO-8859-1-encoded properties
dataflake May 16, 2018
7800f5c
- use the passed-in encoding for creating export XML instead of hard-…
dataflake May 16, 2018
c18b499
- respect XML-provided encoding instead of hard-coding UTF-8
dataflake May 16, 2018
5f8ca74
- ZPublisher type_converters may use encoding that doesn't match our XML
dataflake May 16, 2018
5f7a084
- last contortions to make CMFCore tests run
dataflake May 16, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
.eggs
.installed.cfg
.mr.developer.cfg
.Python
.tox
bin
build
Expand All @@ -21,6 +22,10 @@ local.cfg
parts
src
var
/include
/lib*
pip-selfcheck.json
/src
docs/_build/

# VirtualEnv on Windows:
Expand Down
5 changes: 5 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
sudo: false
language: python
cache:
directories:
- $TRAVIS_BUILD_DIR/eggs
python:
- "2.7"
- "3.5"
- "3.6"
install:
- pip install -U coverage coveralls
- pip install -U six==$(curl $(awk '$1 == "extends" {print $3}' buildout.cfg) 2>/dev/null | awk '$1 == "six" {print $3}')
Expand Down
14 changes: 12 additions & 2 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
Changelog
=========

1.10.1 (unreleased)
-------------------
2.0 (unreleased)
----------------

Breaking changes:

- Require Zope 4.0b4 as minimum supported Zope version and drop
explicit ``Zope2`` egg dependency.

- Drop Python 3.4 support

New features:

- Fixed tests with ``Products.ZCatalog 4.1``. [maurits]

Expand All @@ -12,6 +21,7 @@ Changelog
- Prevent AttributeError 'NoneType' object has no attribute 'decode'.
[maurits]

- Finished compatibility with Python 3.5 and 3.6

1.10.0 (2017-12-07)
-------------------
Expand Down
14 changes: 12 additions & 2 deletions Products/GenericSetup/OFSP/tests/test_exportimport.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@

import unittest

from Products.GenericSetup.interfaces import IBody
from Products.GenericSetup.testing import BodyAdapterTestCase
from Products.GenericSetup.testing import ExportImportZCMLLayer
from Products.GenericSetup.testing import DummySetupEnviron
from zope.component import getMultiAdapter

_FOLDER_BODY = """\
<?xml version="1.0"?>
_FOLDER_BODY = b"""\
<?xml version="1.0" encoding="utf-8"?>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the default. I guess "explicit is better than implicit" blesses the change.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the other hand, we should probably leave it out of at least one of the tests to make sure that we stay backward-compatible with existing files that don't have it. I'll take it out of this one.

<object name="foo_folder" meta_type="Folder">
<property name="title">Foo</property>
</object>
Expand Down Expand Up @@ -48,6 +51,13 @@ def setUp(self):
self._obj = Folder('foo_folder')
self._BODY = _FOLDER_BODY

def test_body_set_without_encoding(self):
context = DummySetupEnviron()
adapted = getMultiAdapter((self._obj, context), IBody)
adapted.body = self._BODY.replace(b'encoding="utf-8"', b'')
self._verifyImport(self._obj)
self.assertEqual(adapted.body, self._BODY)


def test_suite():
return unittest.TestSuite((
Expand Down
4 changes: 3 additions & 1 deletion Products/GenericSetup/PageTemplates/exportimport.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

from .interfaces import IZopePageTemplate

import six


class ZopePageTemplateBodyAdapter(BodyAdapterBase):

Expand All @@ -32,7 +34,7 @@ def _exportBody(self):
"""Export the object as a file body.
"""
text = self.context.read()
if isinstance(text, unicode):
if isinstance(text, six.text_type):
return text.encode('utf-8')
return text

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from Products.GenericSetup.testing import BodyAdapterTestCase
from Products.GenericSetup.testing import ExportImportZCMLLayer

_PAGETEMPLATE_BODY = """\
_PAGETEMPLATE_BODY = b"""\
<html>
<div>Foo</div>
</html>
Expand Down
8 changes: 4 additions & 4 deletions Products/GenericSetup/PluginIndexes/exportimport.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def _importNode(self, node):
for child in node.childNodes:
if child.nodeName == 'indexed_attr':
indexed_attrs.append(
child.getAttribute('value').encode('utf-8'))
child.getAttribute('value'))
if _before != indexed_attrs:
self.context.indexed_attrs = indexed_attrs
self.context.clear()
Expand Down Expand Up @@ -114,8 +114,8 @@ def _importNode(self, node):
"""Import the object from the DOM node.
"""
_before = (self.context._since_field, self.context._until_field)
self.context._edit(node.getAttribute('since_field').encode('utf-8'),
node.getAttribute('until_field').encode('utf-8'))
self.context._edit(node.getAttribute('since_field'),
node.getAttribute('until_field'))
_after = (self.context._since_field, self.context._until_field)
if _before != _after:
self.context.clear()
Expand Down Expand Up @@ -157,7 +157,7 @@ def _importNode(self, node):
"""
_before = self.context.expr
self.context.setExpression(
node.getAttribute('expression').encode('utf-8'))
node.getAttribute('expression'))
_after = self.context.expr
if _before != _after:
self.context.clear()
Expand Down
47 changes: 38 additions & 9 deletions Products/GenericSetup/PluginIndexes/tests/test_exportimport.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,44 +18,44 @@
from Products.GenericSetup.testing import NodeAdapterTestCase
from Products.GenericSetup.testing import ExportImportZCMLLayer

_DATE_XML = """\
_DATE_XML = b"""\
<index name="foo_date" meta_type="DateIndex">
<property name="index_naive_time_as_local">True</property>
<property name="precision">1</property>
<property name="precision">0</property>
</index>
"""

_DATERANGE_XML = """\
_DATERANGE_XML = b"""\
<index name="foo_daterange" meta_type="DateRangeIndex" since_field="bar"
until_field="baz"/>
"""

_FIELD_XML = """\
_FIELD_XML = b"""\
<index name="foo_field" meta_type="FieldIndex">
<indexed_attr value="bar"/>
</index>
"""

_KEYWORD_XML = """\
_KEYWORD_XML = b"""\
<index name="foo_keyword" meta_type="KeywordIndex">
<indexed_attr value="bar"/>
</index>
"""

_ODDBALL_XML = """\
_ODDBALL_XML = b"""\
<index name="foo_keyword" meta_type="OddballIndex">
</index>
"""

_PATH_XML = """\
_PATH_XML = b"""\
<index name="foo_path" meta_type="PathIndex"/>
"""

_SET_XML = """\
_SET_XML = b"""\
<filtered_set name="bar" meta_type="PythonFilteredSet" expression="True"/>
"""

_TOPIC_XML = """\
_TOPIC_XML = b"""\
<index name="foo_topic" meta_type="TopicIndex">
<filtered_set name="bar" meta_type="PythonFilteredSet" expression="True"/>
<filtered_set name="baz" meta_type="PythonFilteredSet" expression="False"/>
Expand All @@ -75,8 +75,12 @@ def _getTargetClass(self):
def setUp(self):
from Products.PluginIndexes.DateIndex.DateIndex import DateIndex
self._obj = DateIndex('foo_date')
self._obj._setPropValue('precision', 0)
self._XML = _DATE_XML

def _verifyImport(self, obj):
self.assertEqual(obj.id, 'foo_date')


class DateRangeIndexNodeAdapterTests(NodeAdapterTestCase, unittest.TestCase):

Expand All @@ -96,6 +100,11 @@ def setUp(self):
self._obj = DateRangeIndex('foo_daterange')
self._XML = _DATERANGE_XML

def _verifyImport(self, obj):
self.assertEqual(obj.id, 'foo_daterange')
self.assertEqual(obj._since_field, 'bar')
self.assertEqual(obj._until_field, 'baz')


class FieldIndexNodeAdapterTests(NodeAdapterTestCase, unittest.TestCase):

Expand All @@ -114,6 +123,10 @@ def setUp(self):
self._obj = FieldIndex('foo_field')
self._XML = _FIELD_XML

def _verifyImport(self, obj):
self.assertEqual(obj.id, 'foo_field')
self.assertEqual(obj.indexed_attrs, ['bar'])


class KeywordIndexNodeAdapterTests(NodeAdapterTestCase, unittest.TestCase):

Expand All @@ -133,6 +146,10 @@ def setUp(self):
self._obj = KeywordIndex('foo_keyword')
self._XML = _KEYWORD_XML

def _verifyImport(self, obj):
self.assertEqual(obj.id, 'foo_keyword')
self.assertEqual(obj.indexed_attrs, ['bar'])


class PathIndexNodeAdapterTests(NodeAdapterTestCase, unittest.TestCase):

Expand All @@ -148,6 +165,9 @@ def setUp(self):
self._obj = PathIndex('foo_path')
self._XML = _PATH_XML

def _verifyImport(self, obj):
self.assertEqual(obj.id, 'foo_path')


class FilteredSetNodeAdapterTests(NodeAdapterTestCase, unittest.TestCase):

Expand All @@ -167,6 +187,10 @@ def setUp(self):
self._obj = PythonFilteredSet('bar', '')
self._XML = _SET_XML

def _verifyImport(self, obj):
self.assertEqual(obj.id, 'bar')
self.assertEqual(obj.getExpression(), 'True')


class TopicIndexNodeAdapterTests(NodeAdapterTestCase, unittest.TestCase):

Expand All @@ -186,6 +210,10 @@ def setUp(self):
self._obj = TopicIndex('foo_topic')
self._XML = _TOPIC_XML

def _verifyImport(self, obj):
self.assertEqual(obj.id, 'foo_topic')
self.assertEqual(len(obj.filteredSets), 2)


class UnchangedTests(unittest.TestCase):

Expand Down Expand Up @@ -248,6 +276,7 @@ def _no_clear(*a):
raise AssertionError("Don't clear me!")
index = DateIndex('foo_date')
index._setPropValue('index_naive_time_as_local', True)
index._setPropValue('precision', 0)
index.clear = _no_clear
adapted = DateIndexNodeAdapter(index, environ)
adapted.node = parseString(_DATE_XML).documentElement # no raise
Expand Down
6 changes: 5 additions & 1 deletion Products/GenericSetup/PythonScripts/exportimport.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"""PythonScript export / import support.
"""

import six

from zope.component import adapts

from Products.GenericSetup.interfaces import ISetupEnviron
Expand All @@ -31,11 +33,13 @@ class PythonScriptBodyAdapter(BodyAdapterBase):
def _exportBody(self):
"""Export the object as a file body.
"""
return self.context.read()
return self.context.read().encode('utf-8')

def _importBody(self, body):
"""Import the object from the file body.
"""
if six.PY3:
body = body.decode('utf-8')
body = body.replace('\r\n', '\n').replace('\r', '\n')
self.context.write(body)

Expand Down
10 changes: 9 additions & 1 deletion Products/GenericSetup/PythonScripts/tests/test_exportimport.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@
"""PythonScript export / import support unit tests.
"""

import six
import unittest

from Products.GenericSetup.testing import BodyAdapterTestCase
from Products.GenericSetup.testing import ExportImportZCMLLayer

_PYTHONSCRIPT_BODY = """\
_PYTHONSCRIPT_BODY = b"""\
## Script (Python) "foo_script"
##bind container=container
##bind context=context
Expand Down Expand Up @@ -47,6 +48,13 @@ def setUp(self):
self._obj = PythonScript('foo_script')
self._BODY = _PYTHONSCRIPT_BODY

def _verifyImport(self, obj):
# Imported script body should be a native string
expected = _PYTHONSCRIPT_BODY
if six.PY3:
expected = _PYTHONSCRIPT_BODY.decode('utf-8')
self.assertEqual(obj.read(), expected)


def test_suite():
return unittest.TestSuite((
Expand Down
6 changes: 3 additions & 3 deletions Products/GenericSetup/ZCTextIndex/exportimport.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ def _importNode(self, node):
for child in node.childNodes:
if child.nodeName == 'element':
element = element_factory.instantiate(
child.getAttribute('group').encode('utf-8'),
child.getAttribute('name').encode('utf-8'))
child.getAttribute('group'),
child.getAttribute('name'))
pipeline.append(element)
pipeline = tuple(pipeline)
if self.context._pipeline != pipeline:
Expand Down Expand Up @@ -108,7 +108,7 @@ def _importNode(self, node):
for child in node.childNodes:
if child.nodeName == 'indexed_attr':
indexed_attrs.append(
child.getAttribute('value').encode('utf-8'))
child.getAttribute('value'))
if self.context._indexed_attrs != indexed_attrs:
self.context._indexed_attrs = indexed_attrs
self.context.clear()
Expand Down
8 changes: 4 additions & 4 deletions Products/GenericSetup/ZCTextIndex/tests/test_exportimport.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@
from Products.GenericSetup.testing import NodeAdapterTestCase
from Products.GenericSetup.testing import ExportImportZCMLLayer

_PLEXICON_XML = """\
_PLEXICON_XML = b"""\
<object name="foo_plexicon" meta_type="ZCTextIndex Lexicon">
<element name="Whitespace splitter" group="Word Splitter"/>
<element name="Case Normalizer" group="Case Normalizer"/>
<element name="Remove listed stop words only" group="Stop Words"/>
</object>
"""

_ZCTEXT_XML = """\
_ZCTEXT_XML = b"""\
<index name="foo_zctext" meta_type="ZCTextIndex">
<indexed_attr value="foo_zctext"/>
<indexed_attr value="baz_zctext"/>
Expand Down Expand Up @@ -109,7 +109,7 @@ def test_ZCLexicon(self):
from Products.GenericSetup.ZCTextIndex.exportimport \
import ZCLexiconNodeAdapter

_XML = """\
_XML = b"""\
<object name="foo_plexicon" meta_type="ZCTextIndex Lexicon">
<element name="foo" group="gs"/>
<element name="bar" group="gs"/>
Expand Down Expand Up @@ -140,7 +140,7 @@ def test_ZCTextIndex(self):
from Products.GenericSetup.testing import DummySetupEnviron
from Products.GenericSetup.ZCTextIndex.exportimport \
import ZCTextIndexNodeAdapter
_XML = """\
_XML = b"""\
<index name="foo_zctext" meta_type="ZCTextIndex">
<indexed_attr value="bar"/>
<extra name="index_type" value="Okapi BM25 Rank"/>
Expand Down
Loading