Skip to content

Commit

Permalink
[fc] Repository: plone.z3cform
Browse files Browse the repository at this point in the history
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
jensens committed May 21, 2020
1 parent 25ea14c commit fa8ebbf
Showing 1 changed file with 26 additions and 19 deletions.
45 changes: 26 additions & 19 deletions last_commit.txt
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'

0 comments on commit fa8ebbf

Please sign in to comment.