-
-
Notifications
You must be signed in to change notification settings - Fork 76
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Branch: refs/heads/master Date: 2020-05-20T23:31:29+02:00 Author: ale-rt (ale-rt) <alessandro.pisa@gmail.com> Commit: plone/plone.z3cform@d8c2a35 Zope 5 compatibility Copy the HTTPRequest._decode from Zope4 because it is has been removed in Zope5 Fixes #13 Files changed: A news/.gitkeep A news/13.bugfix M src/plone/z3cform/tests.py M src/plone/z3cform/z2.py Repository: plone.z3cform Branch: refs/heads/master Date: 2020-05-21T23:37:26+02:00 Author: Jens W. Klein (jensens) <jk@kleinundpartner.at> Commit: plone/plone.z3cform@93eb0f1 Merge pull request #14 from plone/13-recursive-decode Zope 5 compatibility Files changed: A news/.gitkeep A news/13.bugfix M src/plone/z3cform/tests.py M src/plone/z3cform/z2.py
- Loading branch information
Showing
1 changed file
with
26 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,43 @@ | ||
Repository: plone.folder | ||
Repository: plone.z3cform | ||
|
||
|
||
Branch: refs/heads/master | ||
Date: 2020-05-19T18:20:06+02:00 | ||
Author: Jens W. Klein (jensens) <jk@kleinundpartner.at> | ||
Commit: https://github.com/plone/plone.folder/commit/ffab7d1fe4684d0a273f946e529be3d86b1846c2 | ||
Date: 2020-05-20T23:31:29+02:00 | ||
Author: ale-rt (ale-rt) <alessandro.pisa@gmail.com> | ||
Commit: https://github.com/plone/plone.z3cform/commit/d8c2a35b262eff5dd2c5cdc5a8fe1adfbc66d031 | ||
|
||
Zope 5 compatibility | ||
|
||
optimize loop in moveObjectsByDelta | ||
Copy the HTTPRequest._decode from Zope4 because it is has been removed | ||
in Zope5 | ||
|
||
Fixes #13 | ||
|
||
Files changed: | ||
A news/15.bugfix | ||
M src/plone/folder/default.py | ||
M src/plone/folder/partial.py | ||
A news/.gitkeep | ||
A news/13.bugfix | ||
M src/plone/z3cform/tests.py | ||
M src/plone/z3cform/z2.py | ||
|
||
b'diff --git a/news/15.bugfix b/news/15.bugfix\nnew file mode 100644\nindex 0000000..a5ee223\n--- /dev/null\n+++ b/news/15.bugfix\n@@ -0,0 +1,3 @@\n+Micro-optimization of often called loop in moveObjectsByDelta.\n+``x in y`` is up to 1000 times faster if y is a set and not a list.\n+[jensens]\n\\ No newline at end of file\ndiff --git a/src/plone/folder/default.py b/src/plone/folder/default.py\nindex 768911b..84d4c8d 100644\n--- a/src/plone/folder/default.py\n+++ b/src/plone/folder/default.py\n@@ -81,8 +81,12 @@ def moveObjectsByDelta(\n if delta > 0:\n subset_ids.reverse()\n idx = 0\n+ # micro-optimization 1: set is 1000 time faster on contains than list\n+ subset_ids_as_set = set(subset_ids)\n+ # micro-optimization 2: speedup on lookup in bytecode\n+ order_getitem = order.__getitem__\n for i in range(len(order)):\n- if order[i] not in subset_ids:\n+ if order_getitem(i) not in subset_ids_as_set:\n continue\n obj_id = subset_ids[idx]\n try:\ndiff --git a/src/plone/folder/partial.py b/src/plone/folder/partial.py\nindex 6891dd2..5ef625d 100644\n--- a/src/plone/folder/partial.py\n+++ b/src/plone/folder/partial.py\n@@ -15,7 +15,7 @@\n \n @implementer(IExplicitOrdering)\n class PartialOrdering(object):\n- """ this implementation uses a list ot store order information on a\n+ """ this implementation uses a list to store order information on a\n regular attribute of the folderish object; explicit ordering\n is supported """\n adapts(IOrderableFolder)\n@@ -96,8 +96,10 @@ def moveObjectsByDelta(self, ids, delta, subset_ids=None,\n if delta > 0:\n subset_ids.reverse()\n idx = 0\n+ # micro-optimization: set is 1000 time faster on contains than list\n+ subset_ids_as_set = set(subset_ids)\n for i, value in enumerate(self.order):\n- if value in subset_ids:\n+ if value in subset_ids_as_set:\n id = subset_ids[idx]\n try:\n self.order[i] = id\n' | ||
b'diff --git a/news/.gitkeep b/news/.gitkeep\nnew file mode 100644\nindex 0000000..8b13789\n--- /dev/null\n+++ b/news/.gitkeep\n@@ -0,0 +1 @@\n+\ndiff --git a/news/13.bugfix b/news/13.bugfix\nnew file mode 100644\nindex 0000000..3e3f1ae\n--- /dev/null\n+++ b/news/13.bugfix\n@@ -0,0 +1 @@\n+Copy the HTTPRequest._decode from Zope4 because it is going away in Zope5\ndiff --git a/src/plone/z3cform/tests.py b/src/plone/z3cform/tests.py\nindex 846ee2f..493a18f 100644\n--- a/src/plone/z3cform/tests.py\n+++ b/src/plone/z3cform/tests.py\n@@ -179,6 +179,39 @@ def check_output(self, want, got, optionflags):\n return doctest.OutputChecker.check_output(self, want, got, optionflags)\n \n \n+class Z2TestCase(unittest.TestCase):\n+ def test_recursive_decode(self):\n+ from plone.z3cform.z2 import _recursive_decode\n+\n+ form = _recursive_decode(\n+ {\n+ "foo": b"fo\\xc3\\xb8",\n+ "foo_list": [b"fo\\xc3\\xb8", "SPAM"],\n+ "foo_tuple": (b"fo\\xc3\\xb8", "HAM"),\n+ "foo_dict": {"foo": b"fo\\xc3\\xb8", "bar": "EGGS"},\n+ },\n+ "utf-8",\n+ )\n+ self.assertIsInstance(form["foo"], six.text_type)\n+ self.assertEqual(form["foo"], u"fo\xc3\xb8")\n+ self.assertIsInstance(form["foo_list"], list)\n+ self.assertIsInstance(form["foo_list"][0], six.text_type)\n+ self.assertIsInstance(form["foo_list"][1], six.text_type)\n+ self.assertEqual(form["foo_list"][0], u"fo\xc3\xb8")\n+ self.assertEqual(form["foo_list"][1], "SPAM")\n+ self.assertIsInstance(form["foo_tuple"], tuple)\n+ self.assertIsInstance(form["foo_tuple"][0], six.text_type)\n+ self.assertIsInstance(form["foo_tuple"][1], six.text_type)\n+ self.assertEqual(form["foo_tuple"][0], u"fo\xc3\xb8")\n+ self.assertEqual(form["foo_tuple"][1], "HAM")\n+ self.assertIsInstance(form["foo_dict"], dict)\n+ self.assertIsInstance(form["foo_dict"]["foo"], six.text_type)\n+ self.assertIsInstance(form["foo_dict"]["bar"], six.text_type)\n+ self.assertEqual(form["foo_dict"]["foo"], u"fo\xc3\xb8")\n+ self.assertEqual(form["foo_dict"]["bar"], "EGGS")\n+\n+\n+\n def test_suite():\n layout_txt = layered(\n doctest.DocFileSuite(\'layout.rst\', checker=Py23DocChecker()),\n@@ -214,8 +247,8 @@ def test_suite():\n doctest.DocFileSuite(\'traversal.txt\', checker=Py23DocChecker()),\n layer=FUNCTIONAL_TESTING,\n )\n-\n- return unittest.TestSuite(\n+ suite = unittest.defaultTestLoader.loadTestsFromTestCase(Z2TestCase)\n+ suite.addTests(\n [\n layout_txt,\n inputs_txt,\n@@ -225,3 +258,4 @@ def test_suite():\n crud_py,\n ]\n )\n+ return suite\ndiff --git a/src/plone/z3cform/z2.py b/src/plone/z3cform/z2.py\nindex d575f98..abe9db8 100644\n--- a/src/plone/z3cform/z2.py\n+++ b/src/plone/z3cform/z2.py\n@@ -62,11 +62,25 @@ def processInputs(request, charsets=None):\n interface.alsoProvides(request, IProcessedRequest)\n \n \n+def _recursive_decode(value, charset):\n+ """Recursively look for string values and decode.\n+ """\n+ if isinstance(value, list):\n+ return [_recursive_decode(v, charset) for v in value]\n+ elif isinstance(value, tuple):\n+ return tuple(_recursive_decode(v, charset) for v in value)\n+ elif isinstance(value, dict):\n+ return {k: _recursive_decode(v, charset) for k, v in value.items()}\n+ elif isinstance(value, six.binary_type):\n+ return six.text_type(value, charset, \'replace\')\n+ return value\n+\n+\n def _decode(text, charsets):\n for charset in charsets:\n try:\n # decode recursively\n- return HTTPRequest._decode(text, charset)\n+ return _recursive_decode(text, charset)\n except (UnicodeError, AttributeError):\n pass\n return text\n' | ||
|
||
Repository: plone.folder | ||
Repository: plone.z3cform | ||
|
||
|
||
Branch: refs/heads/master | ||
Date: 2020-05-19T20:24:04+02:00 | ||
Author: agitator (agitator) <agitator@users.noreply.github.com> | ||
Commit: https://github.com/plone/plone.folder/commit/658ab7c020d9e8a856d64b68006eb7d39dbdfd18 | ||
Date: 2020-05-21T23:37:26+02:00 | ||
Author: Jens W. Klein (jensens) <jk@kleinundpartner.at> | ||
Commit: https://github.com/plone/plone.z3cform/commit/93eb0f1be50f0318f7b03276d5f9617883028da4 | ||
|
||
Merge pull request #15 from plone/optimize-moveObjectsByDelta | ||
Merge pull request #14 from plone/13-recursive-decode | ||
|
||
optimize loop in moveObjectsByDelta | ||
Zope 5 compatibility | ||
|
||
Files changed: | ||
A news/15.bugfix | ||
M src/plone/folder/default.py | ||
M src/plone/folder/partial.py | ||
A news/.gitkeep | ||
A news/13.bugfix | ||
M src/plone/z3cform/tests.py | ||
M src/plone/z3cform/z2.py | ||
|
||
b'diff --git a/news/15.bugfix b/news/15.bugfix\nnew file mode 100644\nindex 0000000..a5ee223\n--- /dev/null\n+++ b/news/15.bugfix\n@@ -0,0 +1,3 @@\n+Micro-optimization of often called loop in moveObjectsByDelta.\n+``x in y`` is up to 1000 times faster if y is a set and not a list.\n+[jensens]\n\\ No newline at end of file\ndiff --git a/src/plone/folder/default.py b/src/plone/folder/default.py\nindex 768911b..84d4c8d 100644\n--- a/src/plone/folder/default.py\n+++ b/src/plone/folder/default.py\n@@ -81,8 +81,12 @@ def moveObjectsByDelta(\n if delta > 0:\n subset_ids.reverse()\n idx = 0\n+ # micro-optimization 1: set is 1000 time faster on contains than list\n+ subset_ids_as_set = set(subset_ids)\n+ # micro-optimization 2: speedup on lookup in bytecode\n+ order_getitem = order.__getitem__\n for i in range(len(order)):\n- if order[i] not in subset_ids:\n+ if order_getitem(i) not in subset_ids_as_set:\n continue\n obj_id = subset_ids[idx]\n try:\ndiff --git a/src/plone/folder/partial.py b/src/plone/folder/partial.py\nindex 6891dd2..5ef625d 100644\n--- a/src/plone/folder/partial.py\n+++ b/src/plone/folder/partial.py\n@@ -15,7 +15,7 @@\n \n @implementer(IExplicitOrdering)\n class PartialOrdering(object):\n- """ this implementation uses a list ot store order information on a\n+ """ this implementation uses a list to store order information on a\n regular attribute of the folderish object; explicit ordering\n is supported """\n adapts(IOrderableFolder)\n@@ -96,8 +96,10 @@ def moveObjectsByDelta(self, ids, delta, subset_ids=None,\n if delta > 0:\n subset_ids.reverse()\n idx = 0\n+ # micro-optimization: set is 1000 time faster on contains than list\n+ subset_ids_as_set = set(subset_ids)\n for i, value in enumerate(self.order):\n- if value in subset_ids:\n+ if value in subset_ids_as_set:\n id = subset_ids[idx]\n try:\n self.order[i] = id\n' | ||
b'diff --git a/news/.gitkeep b/news/.gitkeep\nnew file mode 100644\nindex 0000000..8b13789\n--- /dev/null\n+++ b/news/.gitkeep\n@@ -0,0 +1 @@\n+\ndiff --git a/news/13.bugfix b/news/13.bugfix\nnew file mode 100644\nindex 0000000..3e3f1ae\n--- /dev/null\n+++ b/news/13.bugfix\n@@ -0,0 +1 @@\n+Copy the HTTPRequest._decode from Zope4 because it is going away in Zope5\ndiff --git a/src/plone/z3cform/tests.py b/src/plone/z3cform/tests.py\nindex 846ee2f..493a18f 100644\n--- a/src/plone/z3cform/tests.py\n+++ b/src/plone/z3cform/tests.py\n@@ -179,6 +179,39 @@ def check_output(self, want, got, optionflags):\n return doctest.OutputChecker.check_output(self, want, got, optionflags)\n \n \n+class Z2TestCase(unittest.TestCase):\n+ def test_recursive_decode(self):\n+ from plone.z3cform.z2 import _recursive_decode\n+\n+ form = _recursive_decode(\n+ {\n+ "foo": b"fo\\xc3\\xb8",\n+ "foo_list": [b"fo\\xc3\\xb8", "SPAM"],\n+ "foo_tuple": (b"fo\\xc3\\xb8", "HAM"),\n+ "foo_dict": {"foo": b"fo\\xc3\\xb8", "bar": "EGGS"},\n+ },\n+ "utf-8",\n+ )\n+ self.assertIsInstance(form["foo"], six.text_type)\n+ self.assertEqual(form["foo"], u"fo\xc3\xb8")\n+ self.assertIsInstance(form["foo_list"], list)\n+ self.assertIsInstance(form["foo_list"][0], six.text_type)\n+ self.assertIsInstance(form["foo_list"][1], six.text_type)\n+ self.assertEqual(form["foo_list"][0], u"fo\xc3\xb8")\n+ self.assertEqual(form["foo_list"][1], "SPAM")\n+ self.assertIsInstance(form["foo_tuple"], tuple)\n+ self.assertIsInstance(form["foo_tuple"][0], six.text_type)\n+ self.assertIsInstance(form["foo_tuple"][1], six.text_type)\n+ self.assertEqual(form["foo_tuple"][0], u"fo\xc3\xb8")\n+ self.assertEqual(form["foo_tuple"][1], "HAM")\n+ self.assertIsInstance(form["foo_dict"], dict)\n+ self.assertIsInstance(form["foo_dict"]["foo"], six.text_type)\n+ self.assertIsInstance(form["foo_dict"]["bar"], six.text_type)\n+ self.assertEqual(form["foo_dict"]["foo"], u"fo\xc3\xb8")\n+ self.assertEqual(form["foo_dict"]["bar"], "EGGS")\n+\n+\n+\n def test_suite():\n layout_txt = layered(\n doctest.DocFileSuite(\'layout.rst\', checker=Py23DocChecker()),\n@@ -214,8 +247,8 @@ def test_suite():\n doctest.DocFileSuite(\'traversal.txt\', checker=Py23DocChecker()),\n layer=FUNCTIONAL_TESTING,\n )\n-\n- return unittest.TestSuite(\n+ suite = unittest.defaultTestLoader.loadTestsFromTestCase(Z2TestCase)\n+ suite.addTests(\n [\n layout_txt,\n inputs_txt,\n@@ -225,3 +258,4 @@ def test_suite():\n crud_py,\n ]\n )\n+ return suite\ndiff --git a/src/plone/z3cform/z2.py b/src/plone/z3cform/z2.py\nindex d575f98..abe9db8 100644\n--- a/src/plone/z3cform/z2.py\n+++ b/src/plone/z3cform/z2.py\n@@ -62,11 +62,25 @@ def processInputs(request, charsets=None):\n interface.alsoProvides(request, IProcessedRequest)\n \n \n+def _recursive_decode(value, charset):\n+ """Recursively look for string values and decode.\n+ """\n+ if isinstance(value, list):\n+ return [_recursive_decode(v, charset) for v in value]\n+ elif isinstance(value, tuple):\n+ return tuple(_recursive_decode(v, charset) for v in value)\n+ elif isinstance(value, dict):\n+ return {k: _recursive_decode(v, charset) for k, v in value.items()}\n+ elif isinstance(value, six.binary_type):\n+ return six.text_type(value, charset, \'replace\')\n+ return value\n+\n+\n def _decode(text, charsets):\n for charset in charsets:\n try:\n # decode recursively\n- return HTTPRequest._decode(text, charset)\n+ return _recursive_decode(text, charset)\n except (UnicodeError, AttributeError):\n pass\n return text\n' | ||
|