Skip to content

Commit

Permalink
[fc] Repository: plone.app.upgrade
Browse files Browse the repository at this point in the history
Branch: refs/heads/master
Date: 2019-02-12T20:45:42+01:00
Author: Maurits van Rees (mauritsvanrees) <maurits@vanrees.org>
Commit: plone/plone.app.upgrade@94e8413

Fixed permission error while removing old resource registries.

Fixes plone/plone.app.upgrade#197

Files changed:
A news/197.bugfix
M plone/app/upgrade/v52/betas.py
Repository: plone.app.upgrade

Branch: refs/heads/master
Date: 2019-02-19T11:57:28+01:00
Author: Jens W. Klein (jensens) <jk@kleinundpartner.at>
Commit: plone/plone.app.upgrade@2659b44

Merge pull request #198 from plone/maurits-fix-remove_legacy_resource_registries

Fixed permission error while removing old resource registries.

Files changed:
A news/197.bugfix
M plone/app/upgrade/v52/betas.py
  • Loading branch information
jensens committed Feb 19, 2019
1 parent 5fef577 commit cce9cc4
Showing 1 changed file with 28 additions and 22 deletions.
50 changes: 28 additions & 22 deletions last_commit.txt
Original file line number Diff line number Diff line change
@@ -1,30 +1,36 @@
Repository: plone.api
Repository: plone.app.upgrade


Branch: refs/heads/master
Date: 2019-02-14T10:12:07+01:00
Author: Harald Friessnegger (frisi) <friessnegger@lovelysystems.com>
Commit: https://github.com/plone/plone.api/commit/548aafea844325a63399da08a2229795dd2e8c44
Date: 2019-02-12T20:45:42+01:00
Author: Maurits van Rees (mauritsvanrees) <maurits@vanrees.org>
Commit: https://github.com/plone/plone.app.upgrade/commit/94e8413d8e5be5a909addd73d94f0bd0d302081b

fix content.find(object_provides) for 'and' query (#427)
Fixed permission error while removing old resource registries.

this fixes https://github.com/plone/plone.api/issues/426

* Fixed flake8 warning W605 invalid escape sequence.

* Flake8: fixed W504 line break after binary operator.

And ignore its reverse: W503 line break before binary operator.
See https://github.com/plone/plone.api/pull/427#issuecomment-462925931
Fixes https://github.com/plone/plone.app.upgrade/issues/197

Files changed:
A news/426.bugfix
M src/plone/api/content.py
M src/plone/api/portal.py
M src/plone/api/tests/test_content.py
M src/plone/api/tests/test_doctests.py
M src/plone/api/tests/test_env.py
M tox.ini

b'diff --git a/news/426.bugfix b/news/426.bugfix\nnew file mode 100644\nindex 0000000..9c806a9\n--- /dev/null\n+++ b/news/426.bugfix\n@@ -0,0 +1,2 @@\n+Fix querying ``object_provides`` for multiple interfaces using \'and\' operator.\n+[fRiSi]\ndiff --git a/src/plone/api/content.py b/src/plone/api/content.py\nindex f11a299..9931599 100644\n--- a/src/plone/api/content.py\n+++ b/src/plone/api/content.py\n@@ -586,6 +586,28 @@ def get_uuid(obj=None):\n return IUUID(obj)\n \n \n+def _parse_object_provides_query(query):\n+ """Create a query for the object_provides index.\n+\n+ :param query: [required]\n+ :type query: Single (or list of) Interface or Identifier or a KeywordIndex\n+ query for multiple values\n+ (eg. `{\'query\': [Iface1, Iface2], \'operator\': \'or\'}`)\n+ """\n+ operator = \'or\'\n+ ifaces = query\n+ if isinstance(query, dict):\n+ operator = query.get(\'operator\', operator)\n+ ifaces = query.get(\'query\', [])\n+ elif not isinstance(query, (list, tuple)):\n+ ifaces = [query]\n+\n+ return {\n+ \'query\': [getattr(x, \'__identifier__\', x) for x in ifaces],\n+ \'operator\': operator,\n+ }\n+\n+\n def find(context=None, depth=None, **kwargs):\n """Find content in the portal.\n \n@@ -631,10 +653,17 @@ def find(context=None, depth=None, **kwargs):\n >>> find(path={\'query\': \'/plone/about/team\', \'depth\': 1})\n \n The `object_provides` index/argument allows Interface objects as well as\n- identifiers.\n+ identifiers. It also supports querying multiple interfaces combined with\n+ `and` or `or`.\n >>> find(object_provides=IATDocument)\n - or -\n >>> find(object_provides=IATDocument.__identifier__)\n+ - or -\n+ >>> find(object_provides={\n+ ... \'query\': [IATFolder, INavigationRoot],\n+ ... \'operator\': \'and\',\n+ ... })\n+\n \n An empty resultset is returned if no valid indexes are queried.\n >>> len(find())\n@@ -668,14 +697,11 @@ def find(context=None, depth=None, **kwargs):\n if context is not None:\n query[\'path\'][\'query\'] = \'/\'.join(context.getPhysicalPath())\n \n- # Convert interfaces to their identifiers\n- object_provides = query.get(\'object_provides\', [])\n- if object_provides:\n- if not isinstance(object_provides, (list, tuple)):\n- object_provides = [object_provides]\n- query[\'object_provides\'] = [\n- getattr(x, \'__identifier__\', x) for x in object_provides\n- ]\n+ # Convert interfaces to their identifiers and also allow to query\n+ # multiple values using {\'query:[], \'operator\':\'and|or\'}\n+ obj_provides = query.get(\'object_provides\', [])\n+ if obj_provides:\n+ query[\'object_provides\'] = _parse_object_provides_query(obj_provides)\n \n # Make sure we don\'t dump the whole catalog.\n catalog = portal.get_tool(\'portal_catalog\')\ndiff --git a/src/plone/api/portal.py b/src/plone/api/portal.py\nindex 8d1791b..0a3e477 100644\n--- a/src/plone/api/portal.py\n+++ b/src/plone/api/portal.py\n@@ -42,13 +42,13 @@\n if not PrintingMailHost:\n PRINTINGMAILHOST_ENABLED = False\n elif (\n- PrintingMailHost.ENABLED is not None and\n- PrintingMailHost.ENABLED.lower() in PrintingMailHost.TRUISMS\n+ PrintingMailHost.ENABLED is not None\n+ and PrintingMailHost.ENABLED.lower() in PrintingMailHost.TRUISMS\n ):\n PRINTINGMAILHOST_ENABLED = True\n elif (\n- PrintingMailHost.ENABLED is None and\n- PrintingMailHost.DevelopmentMode is True\n+ PrintingMailHost.ENABLED is None\n+ and PrintingMailHost.DevelopmentMode is True\n ):\n PRINTINGMAILHOST_ENABLED = True\n else:\ndiff --git a/src/plone/api/tests/test_content.py b/src/plone/api/tests/test_content.py\nindex d575457..795a8c2 100644\n--- a/src/plone/api/tests/test_content.py\n+++ b/src/plone/api/tests/test_content.py\n@@ -8,6 +8,7 @@\n from plone import api\n from plone.api.content import NEW_LINKINTEGRITY\n from plone.api.tests.base import INTEGRATION_TESTING\n+from plone.app.layout.navigation.interfaces import INavigationRoot\n from plone.app.linkintegrity.exceptions import LinkIntegrityNotificationException # NOQA: E501\n from plone.app.textfield import RichTextValue\n from plone.dexterity.interfaces import IDexterityContent\n@@ -21,6 +22,7 @@\n from zope.component import getGlobalSiteManager\n from zope.component import getUtility\n from zope.container.contained import ContainerModifiedEvent\n+from zope.interface import alsoProvides\n from zope.lifecycleevent import IObjectModifiedEvent\n from zope.lifecycleevent import IObjectMovedEvent\n from zope.lifecycleevent import modified\n@@ -503,8 +505,8 @@ def test_move(self):\n \n # Move contact to the same folder (basically a rename)\n nucontact = api.content.move(source=self.contact, id=\'nu-contact\')\n- assert (container[\'about\'][\'nu-contact\'] and\n- container[\'about\'][\'nu-contact\'] == nucontact)\n+ assert (container[\'about\'][\'nu-contact\']\n+ and container[\'about\'][\'nu-contact\'] == nucontact)\n assert \'contact\' not in container[\'about\'].keys()\n \n # Move team page to portal root\n@@ -519,8 +521,8 @@ def test_move(self):\n target=self.about,\n id=\'our-team\',\n )\n- assert (container[\'about\'][\'our-team\'] and\n- container[\'about\'][\'our-team\'] == ourteam)\n+ assert (container[\'about\'][\'our-team\']\n+ and container[\'about\'][\'our-team\'] == ourteam)\n assert \'team\' not in container.keys()\n \n # Test with safe_id option when moving content\n@@ -533,8 +535,8 @@ def test_move(self):\n id=\'link-to-blog\',\n safe_id=True,\n )\n- assert (container[\'about\'][\'link-to-blog-1\'] and\n- container[\'about\'][\'link-to-blog-1\'] == linktoblog1)\n+ assert (container[\'about\'][\'link-to-blog-1\']\n+ and container[\'about\'][\'link-to-blog-1\'] == linktoblog1)\n assert \'link-to-blog\' not in container.keys()\n \n api.content.move(source=self.conference, id=\'conference-renamed\')\n@@ -546,8 +548,8 @@ def test_move(self):\n target=container.events,\n )\n assert (\n- container[\'events\'][\'about\'] and\n- container[\'events\'][\'about\'] == about\n+ container[\'events\'][\'about\']\n+ and container[\'events\'][\'about\'] == about\n )\n \n def test_move_no_move_if_target_is_source_parent(self):\n@@ -591,8 +593,8 @@ def recordEvent(event):\n \n # Rename contact\n nucontact = api.content.rename(obj=self.contact, new_id=\'nu-contact\')\n- assert (container[\'about\'][\'nu-contact\'] and\n- container[\'about\'][\'nu-contact\'] == nucontact)\n+ assert (container[\'about\'][\'nu-contact\']\n+ and container[\'about\'][\'nu-contact\'] == nucontact)\n assert \'contact\' not in container[\'about\'].keys()\n \n if six.PY2:\n@@ -620,8 +622,8 @@ def recordEvent(event):\n new_id=\'link-to-blog\',\n safe_id=True,\n )\n- assert (container[\'about\'][\'link-to-blog-1\'] and\n- container[\'about\'][\'link-to-blog-1\'] == linktoblog1)\n+ assert (container[\'about\'][\'link-to-blog-1\']\n+ and container[\'about\'][\'link-to-blog-1\'] == linktoblog1)\n assert \'link-to-blog\' not in container.keys()\n \n # Rename to existing id\n@@ -639,8 +641,8 @@ def recordEvent(event):\n new_id=\'link-to-blog-1\',\n safe_id=True,\n )\n- assert (container[\'about\'][\'link-to-blog-1-1\'] and\n- container[\'about\'][\'link-to-blog-1-1\'] == linktoblog11)\n+ assert (container[\'about\'][\'link-to-blog-1-1\']\n+ and container[\'about\'][\'link-to-blog-1-1\'] == linktoblog11)\n assert \'link-to-blog\' not in container.keys()\n \n def test_rename_same_id(self):\n@@ -686,8 +688,8 @@ def test_copy(self):\n team = api.content.copy(source=self.team, target=container)\n assert container[\'team\'] and container[\'team\'] == team\n assert (\n- container[\'about\'][\'team\'] and\n- container[\'about\'][\'team\'] != team\n+ container[\'about\'][\'team\']\n+ and container[\'about\'][\'team\'] != team\n ) # old content still available\n \n # When copying objects we can change the id\n@@ -697,8 +699,8 @@ def test_copy(self):\n id=\'our-team\',\n )\n assert(\n- container[\'about\'][\'our-team\'] and\n- container[\'about\'][\'our-team\'] == ourteam\n+ container[\'about\'][\'our-team\']\n+ and container[\'about\'][\'our-team\'] == ourteam\n )\n \n # When copying whithout target parameter should take source parent\n@@ -717,8 +719,8 @@ def test_copy(self):\n safe_id=True,\n )\n assert(\n- container[\'about\'][\'link-to-blog-1\'] and\n- container[\'about\'][\'link-to-blog-1\'] == linktoblog1\n+ container[\'about\'][\'link-to-blog-1\']\n+ and container[\'about\'][\'link-to-blog-1\'] == linktoblog1\n )\n \n # Copy folderish content under target\n@@ -727,8 +729,8 @@ def test_copy(self):\n target=container.events,\n )\n assert(\n- container[\'events\'][\'about\'] and\n- container[\'events\'][\'about\'] == about\n+ container[\'events\'][\'about\']\n+ and container[\'events\'][\'about\'] == about\n )\n \n # When copying with safe_id=True, the prior created item should not be\n@@ -1020,6 +1022,33 @@ def test_find_interface(self):\n \n self.assertEqual(by_identifier, by_interface)\n \n+ def test_find_interface_dict(self):\n+ # Find documents by interface combined with \'and\'\n+\n+ alsoProvides(self.portal.events, INavigationRoot)\n+ self.portal.events.reindexObject(idxs=[\'object_provides\'])\n+\n+ # standard catalog query using identifiers\n+ brains = api.content.find(\n+ object_provides={\n+ \'query\': [\n+ IContentish.__identifier__,\n+ INavigationRoot.__identifier__,\n+ ],\n+ \'operator\': \'and\',\n+ },\n+ )\n+ self.assertEqual(len(brains), 1)\n+\n+ # plone.api query using interfaces\n+ brains = api.content.find(\n+ object_provides={\n+ \'query\': [IContentish, INavigationRoot],\n+ \'operator\': \'and\',\n+ },\n+ )\n+ self.assertEqual(len(brains), 1)\n+\n def test_find_dict(self):\n # Pass arguments using dict\n path = \'/\'.join(self.portal.about.getPhysicalPath())\n@@ -1056,6 +1085,63 @@ def test_find_dict(self):\n documents = api.content.find(**query)\n self.assertEqual(len(documents), 0)\n \n+ def test_find_parse_object_provides_query(self):\n+\n+ parse = api.content._parse_object_provides_query\n+\n+ # single interface\n+ self.assertDictEqual(\n+ parse(IContentish),\n+ {\n+ \'query\': [IContentish.__identifier__],\n+ \'operator\': \'or\',\n+ },\n+ )\n+ # single identifier\n+ self.assertDictEqual(\n+ parse(IContentish.__identifier__),\n+ {\n+ \'query\': [IContentish.__identifier__],\n+ \'operator\': \'or\',\n+ },\n+ )\n+ # multiple interfaces/identifiers (mixed as list)\n+ self.assertDictEqual(\n+ parse([INavigationRoot, IContentish.__identifier__]),\n+ {\n+ \'query\': [\n+ INavigationRoot.__identifier__,\n+ IContentish.__identifier__,\n+ ],\n+ \'operator\': \'or\',\n+ },\n+ )\n+ # multiple interfaces/identifiers (mixed as tuple)\n+ self.assertDictEqual(\n+ parse((INavigationRoot, IContentish.__identifier__)),\n+ {\n+ \'query\': [\n+ INavigationRoot.__identifier__,\n+ IContentish.__identifier__,\n+ ],\n+ \'operator\': \'or\',\n+ },\n+ )\n+ # full blown query - interfaces/identifiers mixed\n+ self.assertDictEqual(\n+ parse({\n+ \'query\': [INavigationRoot, IContentish.__identifier__],\n+ \'operator\': \'and\',\n+ }),\n+ {\n+ \'query\': [\n+ INavigationRoot.__identifier__,\n+ IContentish.__identifier__,\n+ ],\n+ \'operator\': \'and\',\n+ },\n+ )\n+\n def test_get_state(self):\n """Test retrieving the workflow state of a content item."""\n \ndiff --git a/src/plone/api/tests/test_doctests.py b/src/plone/api/tests/test_doctests.py\nindex c946d40..c95b3f7 100644\n--- a/src/plone/api/tests/test_doctests.py\n+++ b/src/plone/api/tests/test_doctests.py\n@@ -32,10 +32,10 @@\n HAS_PA_CONTENTTYPES = True\n \n FLAGS = (\n- doctest.NORMALIZE_WHITESPACE |\n- doctest.ELLIPSIS |\n- doctest.REPORT_NDIFF |\n- doctest.REPORT_ONLY_FIRST_FAILURE\n+ doctest.NORMALIZE_WHITESPACE\n+ | doctest.ELLIPSIS\n+ | doctest.REPORT_NDIFF\n+ | doctest.REPORT_ONLY_FIRST_FAILURE\n )\n \n CHECKER = renormalizing.RENormalizing([\ndiff --git a/src/plone/api/tests/test_env.py b/src/plone/api/tests/test_env.py\nindex bef8168..49d5cc9 100644\n--- a/src/plone/api/tests/test_env.py\n+++ b/src/plone/api/tests/test_env.py\n@@ -25,7 +25,7 @@ class ExampleException(Exception):\n # \'X.Y\' or \'X.Y.Z\' or \'X.Y.Z.A\'\n # It could also include a package status id (Alpha, Beta or RC).\n # When run against coredev, we may have a .devN suffix as well.\n-version_regexp = \'^(\\d+(\\.\\d+){1,3})(a\\d+|b\\d+|rc\\d+)?(\\.dev\\d)?$\'\n+version_regexp = r\'^(\\d+(\\.\\d+){1,3})(a\\d+|b\\d+|rc\\d+)?(\\.dev\\d)?$\'\n \n \n class HasProtectedMethods(SimpleItem):\ndiff --git a/tox.ini b/tox.ini\nindex 631d453..71dbccb 100644\n--- a/tox.ini\n+++ b/tox.ini\n@@ -79,8 +79,8 @@ deps =\n \n commands =\n mkdir -p {toxinidir}/reports/flake8\n- - flake8 --format=html --htmldir={toxinidir}/reports/flake8 src setup.py\n- flake8 src setup.py\n+ - flake8 --ignore=W503 --format=html --htmldir={toxinidir}/reports/flake8 src setup.py\n+ flake8 --ignore=W503 src setup.py\n \n whitelist_externals =\n mkdir\n'
A news/197.bugfix
M plone/app/upgrade/v52/betas.py

b'diff --git a/news/197.bugfix b/news/197.bugfix\nnew file mode 100644\nindex 00000000..4603befd\n--- /dev/null\n+++ b/news/197.bugfix\n@@ -0,0 +1,2 @@\n+Fixed permission error while removing old resource registries.\n+[maurits]\ndiff --git a/plone/app/upgrade/v52/betas.py b/plone/app/upgrade/v52/betas.py\nindex 925ef0e9..8ba2c9fc 100644\n--- a/plone/app/upgrade/v52/betas.py\n+++ b/plone/app/upgrade/v52/betas.py\n@@ -43,9 +43,10 @@ def remove_legacy_resource_registries(context):\n ]\n \n # remove obsolete tools\n- tools = [t for t in tools_to_remove if t in portal]\n- if tools:\n- portal.manage_delObjects(tools)\n+ for tool in tools_to_remove:\n+ if tool not in portal:\n+ continue\n+ portal._delObject(tool)\n \n cleanUpToolRegistry(context)\n \n'

Repository: plone.app.upgrade


Branch: refs/heads/master
Date: 2019-02-19T11:57:28+01:00
Author: Jens W. Klein (jensens) <jk@kleinundpartner.at>
Commit: https://github.com/plone/plone.app.upgrade/commit/2659b4470ca43530c02d2d765cd37050c6510926

Merge pull request #198 from plone/maurits-fix-remove_legacy_resource_registries

Fixed permission error while removing old resource registries.

Files changed:
A news/197.bugfix
M plone/app/upgrade/v52/betas.py

b'diff --git a/news/197.bugfix b/news/197.bugfix\nnew file mode 100644\nindex 00000000..4603befd\n--- /dev/null\n+++ b/news/197.bugfix\n@@ -0,0 +1,2 @@\n+Fixed permission error while removing old resource registries.\n+[maurits]\ndiff --git a/plone/app/upgrade/v52/betas.py b/plone/app/upgrade/v52/betas.py\nindex 925ef0e9..8ba2c9fc 100644\n--- a/plone/app/upgrade/v52/betas.py\n+++ b/plone/app/upgrade/v52/betas.py\n@@ -43,9 +43,10 @@ def remove_legacy_resource_registries(context):\n ]\n \n # remove obsolete tools\n- tools = [t for t in tools_to_remove if t in portal]\n- if tools:\n- portal.manage_delObjects(tools)\n+ for tool in tools_to_remove:\n+ if tool not in portal:\n+ continue\n+ portal._delObject(tool)\n \n cleanUpToolRegistry(context)\n \n'

0 comments on commit cce9cc4

Please sign in to comment.