diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..8ae05aaa --- /dev/null +++ b/.editorconfig @@ -0,0 +1,54 @@ +# Generated from: +# https://github.com/plone/meta/tree/master/config/default +# See the inline comments on how to expand/tweak this configuration file +# +# EditorConfig Configuration file, for more details see: +# http://EditorConfig.org +# EditorConfig is a convention description, that could be interpreted +# by multiple editors to enforce common coding conventions for specific +# file types + +# top-most EditorConfig file: +# Will ignore other EditorConfig files in Home directory or upper tree level. +root = true + + +[*] # For All Files +# Unix-style newlines with a newline ending every file +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +# Set default charset +charset = utf-8 +# Indent style default +indent_style = space +# Max Line Length - a hard line wrap, should be disabled +max_line_length = off + +[*.{py,cfg,ini}] +# 4 space indentation +indent_size = 4 + +[*.{yml,zpt,pt,dtml,zcml}] +# 2 space indentation +indent_size = 2 + +[*.{json,jsonl,js,jsx,ts,tsx,css,less,scss,html}] # Frontend development +# 2 space indentation +indent_size = 2 +max_line_length = 80 + +[{Makefile,.gitmodules}] +# Tab indentation (no size specified, but view as 4 spaces) +indent_style = tab +indent_size = unset +tab_width = unset + + +## +# Add extra configuration options in .meta.toml: +# [editorconfig] +# extra_lines = """ +# _your own configuration lines_ +# """ +## diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..7ef4f64d --- /dev/null +++ b/.flake8 @@ -0,0 +1,22 @@ +# Generated from: +# https://github.com/plone/meta/tree/master/config/default +# See the inline comments on how to expand/tweak this configuration file +[flake8] +doctests = 1 +ignore = + # black takes care of line length + E501, + # black takes care of where to break lines + W503, + # black takes care of spaces within slicing (list[:]) + E203, + # black takes care of spaces after commas + E231, + +## +# Add extra configuration options in .meta.toml: +# [flake8] +# extra_lines = """ +# _your own configuration lines_ +# """ +## diff --git a/.github/workflows/meta.yml b/.github/workflows/meta.yml new file mode 100644 index 00000000..aa2345cf --- /dev/null +++ b/.github/workflows/meta.yml @@ -0,0 +1,70 @@ +# Generated from: +# https://github.com/plone/meta/tree/master/config/default +# See the inline comments on how to expand/tweak this configuration file +name: Meta +on: + push: + branches: + - master + - main + pull_request: + branches: + - master + - main + workflow_dispatch: + +## +# To set environment variables for all jobs, add in .meta.toml: +# [github] +# env = """ +# debug: 1 +# image-name: 'org/image' +# image-tag: 'latest' +# """ +## + +jobs: + qa: + uses: plone/meta/.github/workflows/qa.yml@main + test: + uses: plone/meta/.github/workflows/test.yml@main + coverage: + uses: plone/meta/.github/workflows/coverage.yml@main + dependencies: + uses: plone/meta/.github/workflows/dependencies.yml@main + release_ready: + uses: plone/meta/.github/workflows/release_ready.yml@main + +# TODO: enable the circular dependencies check once the circular +# dependency with plone.app.dexterity is fixed. +# See https://github.com/plone/Products.CMFPlone/issues/3858 + +## +# To modify the list of default jobs being created add in .meta.toml: +# [github] +# jobs = [ +# "qa", +# "test", +# "coverage", +# "dependencies", +# "release_ready", +# "circular", +# ] +## + +## +# To request that some OS level dependencies get installed +# when running tests/coverage jobs, add in .meta.toml: +# [github] +# os_dependencies = "git libxml2 libxslt" +## + + +## +# Specify additional jobs in .meta.toml: +# [github] +# extra_lines = """ +# another: +# uses: org/repo/.github/workflows/file.yml@main +# """ +## diff --git a/.gitignore b/.gitignore index d12b524c..503e47c5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,23 +1,55 @@ -/develop-eggs -/eggs -/fake-eggs -/bin -/parts -/downloads -/var -/build -/dist -/local.cfg -/*.egg-info -/.installed.cfg -/.mr.developer.cfg +# Generated from: +# https://github.com/plone/meta/tree/master/config/default +# See the inline comments on how to expand/tweak this configuration file +# python related +*.egg-info *.pyc -/.Python -/include -/lib -/src/* +*.pyo + +# translation related *.mo -/.coverage + +# tools related +build/ +.coverage +.*project coverage.xml -zptlint.log -.DS_Store +dist/ +docs/_build +__pycache__/ +.tox +.vscode/ +node_modules/ + +# venv / buildout related +bin/ +develop-eggs/ +eggs/ +.eggs/ +etc/ +.installed.cfg +include/ +lib/ +lib64 +.mr.developer.cfg +parts/ +pyvenv.cfg +var/ + +# mxdev +/instance/ +/.make-sentinels/ +/*-mxdev.txt +/reports/ +/sources/ +/venv/ +.installed.txt + + +## +# Add extra configuration options in .meta.toml: +# [gitignore] +# extra_lines = """ +# _your own configuration lines_ +# """ +## diff --git a/.meta.toml b/.meta.toml new file mode 100644 index 00000000..d5d5bc47 --- /dev/null +++ b/.meta.toml @@ -0,0 +1,26 @@ +# Generated from: +# https://github.com/plone/meta/tree/master/config/default +# See the inline comments on how to expand/tweak this configuration file +[meta] +template = "default" +commit-id = "68cda6e4" + +[github] +jobs = [ + "qa", + "test", + "coverage", + "dependencies", + "release_ready", + ] + +[pre_commit] +zpretty_extra_lines = """ + exclude: plone/app/content/browser/contents/templates +""" +i18ndude_extra_lines = """ + exclude: plone/app/content/browser/contents +""" + +[pyproject] +dependencies_ignores = "['tus', ]" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..fac51902 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,96 @@ +# Generated from: +# https://github.com/plone/meta/tree/master/config/default +# See the inline comments on how to expand/tweak this configuration file +ci: + autofix_prs: false + autoupdate_schedule: monthly + +repos: +- repo: https://github.com/asottile/pyupgrade + rev: v3.14.0 + hooks: + - id: pyupgrade + args: [--py38-plus] +- repo: https://github.com/pycqa/isort + rev: 5.12.0 + hooks: + - id: isort +- repo: https://github.com/psf/black + rev: 23.9.1 + hooks: + - id: black +- repo: https://github.com/collective/zpretty + rev: 3.1.0 + hooks: + - id: zpretty + exclude: plone/app/content/browser/contents/templates + +## +# Add extra configuration options in .meta.toml: +# [pre_commit] +# zpretty_extra_lines = """ +# _your own configuration lines_ +# """ +## +- repo: https://github.com/PyCQA/flake8 + rev: 6.1.0 + hooks: + - id: flake8 + +## +# Add extra configuration options in .meta.toml: +# [pre_commit] +# flake8_extra_lines = """ +# _your own configuration lines_ +# """ +## +- repo: https://github.com/codespell-project/codespell + rev: v2.2.6 + hooks: + - id: codespell + additional_dependencies: + - tomli + +## +# Add extra configuration options in .meta.toml: +# [pre_commit] +# codespell_extra_lines = """ +# _your own configuration lines_ +# """ +## +- repo: https://github.com/mgedmin/check-manifest + rev: "0.49" + hooks: + - id: check-manifest +- repo: https://github.com/regebro/pyroma + rev: "4.2" + hooks: + - id: pyroma +- repo: https://github.com/mgedmin/check-python-versions + rev: "0.21.3" + hooks: + - id: check-python-versions + args: ['--only', 'setup.py,pyproject.toml'] +- repo: https://github.com/collective/i18ndude + rev: "6.1.0" + hooks: + - id: i18ndude + exclude: plone/app/content/browser/contents + + +## +# Add extra configuration options in .meta.toml: +# [pre_commit] +# i18ndude_extra_lines = """ +# _your own configuration lines_ +# """ +## + + +## +# Add extra configuration options in .meta.toml: +# [pre_commit] +# extra_lines = """ +# _your own configuration lines_ +# """ +## diff --git a/CHANGES.rst b/CHANGES.rst index 531f0cee..ae998b28 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -8,6 +8,26 @@ Changelog .. towncrier release notes start +4.0.3 (2023-10-25) +------------------ + +Bug fixes: + + +- Fix cut / delete for content with lock created by current user. [laulaz] (#266) +- Fixed inapproriate ``sort()`` in ``folderfactories.py``. [ajung] (#268) + + +Internal: + + +- Update configuration files. + [plone devs] (5cdbd962) +- chore: move tests from `plone.app.dexterity` + + To avoid a circular dependency between the two of them. (#3858) + + 4.0.2 (2023-06-16) ------------------ @@ -210,7 +230,7 @@ Bug fixes: Bug fixes: -- Call fileUpload view explict with @@ to avoid possible plone.rest clashes. +- Call fileUpload view explicit with @@ to avoid possible plone.rest clashes. [jensens] (#225) @@ -552,7 +572,7 @@ Bug fixes: [thet] - Fix issue where some actions (copy, delete, paste) on contents view did not - work if there were any private (innaccessible for the current user) levels the + work if there were any private (inaccessible for the current user) levels the current path [datakurre] @@ -908,7 +928,7 @@ Fixes: - When clicking cancel on the delete_confirmation got to the view_url. [ale-rt] -- Fix deletion of objects with unicode charaters in the title. +- Fix deletion of objects with unicode characters in the title. [cillianderoiste] @@ -988,7 +1008,7 @@ Fixes: - Translate folder contents add menu [vangheem] -- use same columns title in results and in displayed colums configuration +- use same columns title in results and in displayed columns configuration [vincent] diff --git a/news/266.bugfix b/news/266.bugfix deleted file mode 100644 index 571aae7d..00000000 --- a/news/266.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix cut / delete for content with lock created by current user. [laulaz] diff --git a/news/268.bugfix b/news/268.bugfix deleted file mode 100644 index 4b5d893d..00000000 --- a/news/268.bugfix +++ /dev/null @@ -1 +0,0 @@ -- fixed inapproriate sort() in folderfactories.py [ajung] diff --git a/news/3858.internal b/news/3858.internal deleted file mode 100644 index 0f724014..00000000 --- a/news/3858.internal +++ /dev/null @@ -1,3 +0,0 @@ -chore: move tests from `plone.app.dexterity` - -To avoid a circular dependency between the two of them. diff --git a/plone/app/content/browser/actions.py b/plone/app/content/browser/actions.py index b939b341..6f16e535 100644 --- a/plone/app/content/browser/actions.py +++ b/plone/app/content/browser/actions.py @@ -38,7 +38,6 @@ def is_locked(self): class DeleteConfirmationForm(form.Form, LockingBase): - fields = field.Fields() template = ViewPageTemplateFile("templates/delete_confirmation.pt") enableCSRFProtection = True @@ -140,7 +139,6 @@ class IRenameForm(Interface): class RenameForm(form.Form): - fields = field.Fields(IRenameForm) template = ViewPageTemplateFile("templates/object_rename.pt") enableCSRFProtection = True diff --git a/plone/app/content/browser/configure.zcml b/plone/app/content/browser/configure.zcml index b69207b9..f2762e98 100644 --- a/plone/app/content/browser/configure.zcml +++ b/plone/app/content/browser/configure.zcml @@ -1,204 +1,213 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + xmlns:five="http://namespaces.zope.org/five" + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plone/app/content/browser/constraintypes.pt b/plone/app/content/browser/constraintypes.pt index ead1a965..2cb548d3 100644 --- a/plone/app/content/browser/constraintypes.pt +++ b/plone/app/content/browser/constraintypes.pt @@ -1,20 +1,24 @@ - - -
- -
+ + - + -

Title

+

Title

@@ -64,4 +70,3 @@
- diff --git a/plone/app/content/browser/constraintypes.py b/plone/app/content/browser/constraintypes.py index 6d8fd04d..1b83a091 100644 --- a/plone/app/content/browser/constraintypes.py +++ b/plone/app/content/browser/constraintypes.py @@ -1,5 +1,4 @@ from plone.autoform.form import AutoExtensibleForm -from plone.base import PloneMessageFactory as _ from plone.base.interfaces import ISelectableConstrainTypes from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile from z3c.form import button @@ -61,7 +60,6 @@ def __call__(self, context): class IConstrainForm(Interface): - constrain_types_mode = Choice( title=_("label_type_restrictions", default="Type restrictions"), description=_( @@ -140,7 +138,6 @@ def secondary_types(self): class ConstrainsFormView(AutoExtensibleForm, form.EditForm): - schema = IConstrainForm label = _( "heading_set_content_type_restrictions", diff --git a/plone/app/content/browser/content_status_history.py b/plone/app/content/browser/content_status_history.py index b2882b97..d1810771 100644 --- a/plone/app/content/browser/content_status_history.py +++ b/plone/app/content/browser/content_status_history.py @@ -48,7 +48,6 @@ class ContentStatusHistoryDatesForm(form.Form): class ContentStatusHistoryView(BrowserView): - template = ViewPageTemplateFile("templates/content_status_history.pt") def __init__(self, context, request): @@ -66,9 +65,8 @@ def __call__( effective_date=None, expiration_date=None, include_children=False, - *args + *args, ): - data = self.dates_form.extractData() if self.request.get("form.widgets.effective_date-calendar", None) and data: effective_date = data[0]["effective_date"].strftime("%Y-%m-%d %H:%M") diff --git a/plone/app/content/browser/contents/__init__.py b/plone/app/content/browser/contents/__init__.py index eaafd1c1..66b8f221 100644 --- a/plone/app/content/browser/contents/__init__.py +++ b/plone/app/content/browser/contents/__init__.py @@ -26,7 +26,6 @@ class ContentsBaseAction(BrowserView): - success_msg = _("Success") failure_msg = _("Failure") required_obj_permission = None @@ -183,7 +182,7 @@ def get_thumb_scale(self): registry = getUtility(IRegistry) settings = registry.forInterface(ISiteSchema, prefix="plone", check=False) if settings.no_thumbs_tables: - # thumbs to be supressed + # thumbs to be suppressed return None thumb_scale_table = settings.thumb_scale_table return thumb_scale_table @@ -293,7 +292,6 @@ def __call__(self): class ContextInfo(BrowserView): - attributes = [ "CreationDate", "Creator", diff --git a/plone/app/content/browser/contents/configure.zcml b/plone/app/content/browser/contents/configure.zcml index d6773cb5..931d4b90 100644 --- a/plone/app/content/browser/contents/configure.zcml +++ b/plone/app/content/browser/contents/configure.zcml @@ -1,123 +1,140 @@ + > + name="folder_contents" + for="Products.CMFCore.interfaces._content.IFolderish" + class=".FolderContentsView" + template="templates/folder_contents.pt" + permission="cmf.ListFolderContents" + /> + name="fc-contextInfo" + for="Products.CMFCore.interfaces._content.IFolderish" + class=".ContextInfo" + permission="cmf.ListFolderContents" + /> + name="fc-setDefaultPage" + for="Products.CMFCore.interfaces._content.IFolderish" + class=".defaultpage.SetDefaultPageActionView" + permission="cmf.ModifyPortalContent" + /> + name="fc-itemOrder" + for="Products.CMFCore.interfaces._content.IFolderish" + class=".rearrange.ItemOrderActionView" + permission="cmf.ModifyPortalContent" + /> + name="fc-rearrange" + for="Products.CMFCore.interfaces._content.IFolderish" + class=".rearrange.RearrangeActionView" + permission="cmf.ModifyPortalContent" + /> - + name="fc-rename" + for="Products.CMFCore.interfaces._content.IFolderish" + class=".rename.RenameActionView" + permission="cmf.ListFolderContents" + /> + - + name="fc-tags" + for="Products.CMFCore.interfaces._content.IFolderish" + class=".tags.TagsActionView" + permission="cmf.ListFolderContents" + /> + - + name="fc-delete" + for="Products.CMFCore.interfaces._content.IFolderish" + class=".delete.DeleteActionView" + permission="cmf.ListFolderContents" + /> + - + name="fc-workflow" + for="Products.CMFCore.interfaces._content.IFolderish" + class=".workflow.WorkflowActionView" + permission="cmf.ListFolderContents" + /> + - + name="fc-properties" + for="Products.CMFCore.interfaces._content.IFolderish" + class=".properties.PropertiesActionView" + permission="cmf.ListFolderContents" + /> + - + name="fc-copy" + for="Products.CMFCore.interfaces._content.IFolderish" + class=".copy.CopyActionView" + permission="cmf.ListFolderContents" + /> + - + name="fc-cut" + for="Products.CMFCore.interfaces._content.IFolderish" + class=".cut.CutActionView" + permission="cmf.ListFolderContents" + /> + - + name="fc-paste" + for="Products.CMFCore.interfaces._content.IFolderish" + class=".paste.PasteActionView" + permission="cmf.ListFolderContents" + /> + diff --git a/plone/app/content/browser/contents/copy.py b/plone/app/content/browser/contents/copy.py index 015b995d..4259bd7b 100644 --- a/plone/app/content/browser/contents/copy.py +++ b/plone/app/content/browser/contents/copy.py @@ -10,7 +10,6 @@ @implementer(IStructureAction) class CopyAction: - order = 2 def __init__(self, context, request): diff --git a/plone/app/content/browser/contents/cut.py b/plone/app/content/browser/contents/cut.py index e785931f..d7233305 100644 --- a/plone/app/content/browser/contents/cut.py +++ b/plone/app/content/browser/contents/cut.py @@ -11,7 +11,6 @@ @implementer(IStructureAction) class CutAction: - order = 1 def __init__(self, context, request): diff --git a/plone/app/content/browser/contents/delete.py b/plone/app/content/browser/contents/delete.py index 5adac14a..8eb6018e 100644 --- a/plone/app/content/browser/contents/delete.py +++ b/plone/app/content/browser/contents/delete.py @@ -16,7 +16,6 @@ @implementer(IStructureAction) class DeleteAction: - template = ViewPageTemplateFile("templates/delete.pt") order = 4 diff --git a/plone/app/content/browser/contents/paste.py b/plone/app/content/browser/contents/paste.py index 0250760d..52c09653 100644 --- a/plone/app/content/browser/contents/paste.py +++ b/plone/app/content/browser/contents/paste.py @@ -9,7 +9,6 @@ @implementer(IStructureAction) class PasteAction: - order = 3 def __init__(self, context, request): diff --git a/plone/app/content/browser/contents/properties.py b/plone/app/content/browser/contents/properties.py index aba47250..c51e8a70 100644 --- a/plone/app/content/browser/contents/properties.py +++ b/plone/app/content/browser/contents/properties.py @@ -5,9 +5,7 @@ from plone.app.widgets.utils import get_datetime_options from plone.base import PloneMessageFactory as _ from plone.base.defaultpage import check_default_page_via_view -from plone.dexterity.interfaces import IDexterityContent from Products.CMFCore.interfaces._content import IFolderish -from Products.CMFCore.utils import getToolByName from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile from zope.component import getUtility from zope.component.hooks import getSite @@ -20,7 +18,6 @@ @implementer(IStructureAction) class PropertiesAction: - template = ViewPageTemplateFile("templates/properties.pt") order = 8 @@ -54,7 +51,6 @@ class PropertiesActionView(ContentsBaseAction): required_obj_permission = "Modify portal content" def __call__(self): - if self.request.form.get("render") == "yes": lang_factory = getUtility( IVocabularyFactory, "plone.app.vocabularies.SupportedContentLanguages" @@ -95,7 +91,6 @@ def __call__(self): return super().__call__() def action(self, obj, bypass_recurse=False): - if check_default_page_via_view(obj, self.request): self.action(obj.aq_parent, bypass_recurse=True) recurse = self.recurse and not bypass_recurse diff --git a/plone/app/content/browser/contents/rename.py b/plone/app/content/browser/contents/rename.py index 25ad37f0..eb2a9d45 100644 --- a/plone/app/content/browser/contents/rename.py +++ b/plone/app/content/browser/contents/rename.py @@ -23,7 +23,6 @@ @implementer(IStructureAction) class RenameAction: - template = ViewPageTemplateFile("templates/rename.pt") order = 5 diff --git a/plone/app/content/browser/contents/tags.py b/plone/app/content/browser/contents/tags.py index 01e8f141..fe18d205 100644 --- a/plone/app/content/browser/contents/tags.py +++ b/plone/app/content/browser/contents/tags.py @@ -9,7 +9,6 @@ @implementer(IStructureAction) class TagsAction: - template = ViewPageTemplateFile("templates/tags.pt") order = 6 diff --git a/plone/app/content/browser/contents/workflow.py b/plone/app/content/browser/contents/workflow.py index a2a90a0b..8b5a5bb3 100644 --- a/plone/app/content/browser/contents/workflow.py +++ b/plone/app/content/browser/contents/workflow.py @@ -14,7 +14,6 @@ @implementer(IStructureAction) class WorkflowAction: - template = ViewPageTemplateFile("templates/workflow.pt") order = 7 diff --git a/plone/app/content/browser/folderfactories.pt b/plone/app/content/browser/folderfactories.pt index 7767a653..c2305f58 100644 --- a/plone/app/content/browser/folderfactories.pt +++ b/plone/app/content/browser/folderfactories.pt @@ -1,74 +1,104 @@ - + xml:lang="en" + i18n:domain="plone" +> - + - + tal:define=" + dummy python:request.set('disable_border',1); + disable_column_one python:request.set('disable_plone.leftcolumn',1); + disable_column_two python:request.set('disable_plone.rightcolumn',1); + " + /> + - + - + -

Add new item

+

Add new item

-
+
Select the type of item you want to add to your folder. -
+
-
+

- + Click to configure what type of items can be added here… - +

-
+ -
    - -
  • - - - Type description -
  • -
    -
+
    + +
  • + + + Type description +
  • +
    +
-
- -
-
+
+ +
+
-
+
-
+
- + diff --git a/plone/app/content/browser/full_review_list.pt b/plone/app/content/browser/full_review_list.pt index 25549e75..8fd2c8ec 100644 --- a/plone/app/content/browser/full_review_list.pt +++ b/plone/app/content/browser/full_review_list.pt @@ -1,31 +1,40 @@ - + xml:lang="en" + i18n:domain="plone" +> - + - - -

Full review list:

+ + +

Full review list:

-
-
-
- +
+ +
+ -
+
-
- +
+ diff --git a/plone/app/content/browser/i18n.py b/plone/app/content/browser/i18n.py index 415508af..ebabfc1a 100644 --- a/plone/app/content/browser/i18n.py +++ b/plone/app/content/browser/i18n.py @@ -35,7 +35,6 @@ def _gettext_catalog(self, domain, language): return _catalog def __call__(self, domain=None, language=None): - if domain is None: catalog = {} else: diff --git a/plone/app/content/browser/interfaces.py b/plone/app/content/browser/interfaces.py index 4cdfc356..5f300c3e 100644 --- a/plone/app/content/browser/interfaces.py +++ b/plone/app/content/browser/interfaces.py @@ -2,7 +2,7 @@ class IFolderContentsView(Interface): - """Interface, which provides methods for folder contens""" + """Interface, which provides methods for folder contents""" def test(a, b, c): """A simple replacement of python's test.""" diff --git a/plone/app/content/browser/selection.py b/plone/app/content/browser/selection.py index 1d5a7327..aaf5c566 100644 --- a/plone/app/content/browser/selection.py +++ b/plone/app/content/browser/selection.py @@ -49,7 +49,9 @@ def __call__(self): self.request.response.redirect(context_view_url) if self.request.form.get("form.button.Save") and not template_id: - IStatusMessage(self.request).add("Please select a template.", type="warning") + IStatusMessage(self.request).add( + "Please select a template.", type="warning" + ) if self.request.form.get("form.button.Save") and template_id: # Make sure this is a valid template diff --git a/plone/app/content/browser/table.pt b/plone/app/content/browser/table.pt index 5a79f199..939d107e 100644 --- a/plone/app/content/browser/table.pt +++ b/plone/app/content/browser/table.pt @@ -1,175 +1,303 @@
- - - - - + i18n:domain="plone" +> + + + + + - + tal:attributes=" + value item/path|item/id|item/getId; + " + />

+ i18n:translate="description_no_visible_items_add_paste" + > This folder has no visible items. To add content, press the add button, or paste content from another location.

+ tal:define=" + nosortclass view/get_nosort_class; + " + > -
+
-
+
+ > - + - - + tal:condition="view/show_select_column" + >  + id="foldercontents-title-column" + > Title  + tal:condition="view/show_size_column" + > Size  + tal:condition="view/show_modified_column" + > Modified  + tal:condition="view/show_status_column" + > State  - + - - - @@ -177,30 +305,47 @@ - -
Select: AllSelect: + All
- - All items on this + + + All + + items on this page are selected. - Select all - items in this folder. + Select all + + items in this folder.
- - All items in this folder + + + All + + items in this folder are selected. - Clear selection + Clear selection
+ tal:condition="view/show_sort_column" + >    Title   Size   Modified   State 
- - + + + ▲ - +   - + ▼ - - + + - + + - - - - - - + + + + ■ - - + + expired + i18n:translate="time_expired" + >expired -   + +   + size + tal:attributes=" + class item/state_class|nothing; + " + > + size + + tal:attributes=" + class string:${state_class} ${modified_sortable}; + " + > 08/19/2001 03:01 AM - + tal:attributes=" + class item/state_class|nothing; + " + i18n:translate="" + >  
- + Show all items + >Show all items
- + Show batched + >Show batched
-
+
+ />
diff --git a/plone/app/content/browser/table.txt b/plone/app/content/browser/table.txt index f3337872..ae906a27 100644 --- a/plone/app/content/browser/table.txt +++ b/plone/app/content/browser/table.txt @@ -3,7 +3,7 @@ Table ===== The table class can render a table like used in the folder contents view. It is -abstracted into a seperate class for reuse with other views like the review +abstracted into a separate class for reuse with other views like the review list. A table can be parameterized at creation time. @@ -31,11 +31,11 @@ One of the table's main virtues is that it batches. A template can use the True The table automatically adds keys for making layout easier. One of these is -indication wheter an item is `checked`. +indication whether an item is `checked`. >>> list(table.batch)[0]['checked'] -Wheter or not an item is checked depends on request variables. If either the +Whether or not an item is checked depends on request variables. If either the whole batch or the current screen is selected the item we be marked as checked. Below we will demonstrate this by selecting the items on screen. @@ -129,8 +129,8 @@ The same goes for selecting the screen and the whole batch. 'http://plone/view?pagenumber=1&pagesize=20&select=all' A template may want to display only one of these urls at the same time. -Therefore the table has a boolean property to query wheter or not to show the -select all option. The display of this depends on wheter the whole batch is +Therefore the table has a boolean property to query whether or not to show the +select all option. The display of this depends on whether the whole batch is selected (don't show) or the screen has not been selected (don't show then). >>> table = Table({}, base_url, view_url, items=items) diff --git a/plone/app/content/browser/templates/content_status_history.pt b/plone/app/content/browser/templates/content_status_history.pt index 6edd7a9d..ed967ddf 100644 --- a/plone/app/content/browser/templates/content_status_history.pt +++ b/plone/app/content/browser/templates/content_status_history.pt @@ -1,384 +1,529 @@ - + xml:lang="en" + i18n:domain="plone" +> - + - + - + + tal:attributes=" + src string:${portal_url}/jscalendar/calendar-en.js; + " + > -
- Note - This form is used in two different ways - from folder_contents, +
+ Note + This form is used in two different ways - from folder_contents, allowing you to publish several things at once, and from the state drop-down. In the first case, the 'paths' request parameter is set; in the second case, giving the relative paths to the content object to manipulate; in the second case, this parameter is omitted and the - path of the context is used. + path of the context is used.
- + + tal:replace="view/redirect_to_referrer" + />

Publishing process

+ i18n:translate="heading_publishing_process" + >Publishing process -
+
An item's status (also called its review state) determines who can see it. Another way to control the visibility of an item is - with its Publishing Date. An item is not publicly + with its + Publishing Date. An item is not publicly searchable before its publishing date. This will prevent the item from showing up in portlets and folder listings, although the item will still be available if accessed directly via its URL.
-
- -
- -
Validation error output
-
- - - - - - + + + + + +
- - + + +
+ +
Validation error output
+
+ + + + + + - + - + - + - - - - - - - - - - - + + + + + + + + + + - - - + + + - - - - - - -
+ + Title - + Size - + Modified - + State -
- - - - - - - - -
+ + + + + + + + + - - - - expired - -   - size - + + + + + expired + + +   + + + size + + 08/19/2001 03:01 AM - - -   -
-
-
- -
- - -
+ +   +
+
+
+ +
+ + + + -
+
If checked, this will attempt to modify the status of all content in any selected folders and their subfolders. -
- -
- -
- -
+
+ +
+ +
+ +
The date when the item will be published. If no date is selected the item will be published immediately. -
- -
Validation error output
- -
- -
+
+ +
Validation error output
+ +
+ +
calendar pop-up -
- -
-
- -
+
+
+ +
+ +
The date when the item expires. This will automatically make the item invisible for others at the given date. If no date is chosen, it will never expire. -
- -
Validation error output
- -
-
- -
+
+ +
Validation error output
+ +
+
+ +
calendar pop-up -
-
+
+
-
- +
+ -
+
Will be added to the publishing history. If multiple items are selected, this comment will be attached to all of them. -
- -
- -
- -
+
+ +
+ +
+ +
Select the transition to be used for modifying the items state. -
- -
- -
- Error -
-
+
+ +
+ +
+ Error +
+
- + For usability we will want to signify what state we are currently in. DCWorkflow only returns what transitions are available. But we want to visually represent what *state* we are currently in along with possible transitions. - - - - -
- - - - -
-
- -
- -
- -
- - - -
- - - - - + + + + +
+ + + + +
+
+ +
+ +
+ +
+ + + +
+ + + + +
diff --git a/plone/app/content/browser/templates/delete_confirmation.pt b/plone/app/content/browser/templates/delete_confirmation.pt index f9348d69..29241d53 100644 --- a/plone/app/content/browser/templates/delete_confirmation.pt +++ b/plone/app/content/browser/templates/delete_confirmation.pt @@ -1,55 +1,73 @@ - + xml:lang="en" + i18n:domain="plone" +> - + - + - + -

+

This item can not be deleted because it is currently locked by another user. -

+ - -

- + +

+ Do you really want to delete this folder and all its contents? - - - (This will delete a total of 22 items.) - -

- -

+ + + (This will delete a total of + 22 + items.) + +

+ +

Do you really want to delete this item? -

-
+

+
-
- - +
+ + -
    -
  • The item title (ID)
  • -
+
    +
  • The item title (ID)
  • +
-
-
+ +
-
- +
+ diff --git a/plone/app/content/browser/templates/object_rename.pt b/plone/app/content/browser/templates/object_rename.pt index 9c95d7b8..e951e4f3 100644 --- a/plone/app/content/browser/templates/object_rename.pt +++ b/plone/app/content/browser/templates/object_rename.pt @@ -1,28 +1,35 @@ - + xml:lang="en" + i18n:domain="plone" +> - + - + - + -
+
-

Rename item

+

Rename item

-
-
-
+
+ +
-
- +
+
- + diff --git a/plone/app/content/browser/templates/select_default_page.pt b/plone/app/content/browser/templates/select_default_page.pt index 6686c398..302fbd13 100644 --- a/plone/app/content/browser/templates/select_default_page.pt +++ b/plone/app/content/browser/templates/select_default_page.pt @@ -1,91 +1,124 @@ - + xml:lang="en" + i18n:domain="plone" +> - +

Select default page

+ i18n:translate="heading_select_default_page" + >Select default page -
+
Please select item which will be displayed as the default page of the folder.
-
+ - + - - -
- -
- -
+
Item Description -
-
+ + -
+
+ name="form.buttons.Save" + type="submit" + value="Save" + i18n:attributes="value label_save;" + i18n:translate="label_save" + >Save + name="form.buttons.Cancel" + type="submit" + value="Cancel" + i18n:attributes="value label_cancel;" + i18n:translate="label_cancel" + >Cancel
-
+
There are no items in this folder that can be selected as a default view page.
- +
-
+ -
+
diff --git a/plone/app/content/browser/templates/select_default_view.pt b/plone/app/content/browser/templates/select_default_view.pt index 6776969c..b7ccdbb9 100644 --- a/plone/app/content/browser/templates/select_default_view.pt +++ b/plone/app/content/browser/templates/select_default_view.pt @@ -1,89 +1,131 @@ - + xml:lang="en" + i18n:domain="plone" +> - +

Select default view

+ i18n:translate="heading_select_default_view" + >Select default view -
+
Please select which template should be used as the default view of the folder.
-
+ - + -
- - - -
-
- - -
+
+ + +
-
+
diff --git a/plone/app/content/browser/vocabulary.py b/plone/app/content/browser/vocabulary.py index f7693cd7..9464947e 100644 --- a/plone/app/content/browser/vocabulary.py +++ b/plone/app/content/browser/vocabulary.py @@ -3,12 +3,12 @@ from logging import getLogger from plone.app.content.utils import json_dumps from plone.app.content.utils import json_loads -from plone.app.layout.navigation.interfaces import INavigationRoot -from plone.app.layout.navigation.root import getNavigationRoot from plone.app.querystring import queryparser from plone.app.z3cform.interfaces import IFieldPermissionChecker from plone.autoform.interfaces import WRITE_PERMISSIONS_KEY from plone.base import PloneMessageFactory as _ +from plone.base.interfaces.siteroot import INavigationRoot +from plone.base.navigationroot import get_navigation_root from plone.base.utils import safe_text from plone.memoize.view import memoize from plone.supermodel.utils import mergedTaggedValueDict @@ -125,7 +125,7 @@ def get_translated_ignored(self): return TRANSLATED_IGNORED def get_base_path(self, context): - return getNavigationRoot(context) + return get_navigation_root(context) def __call__(self): """ @@ -139,7 +139,7 @@ def __call__(self): sort_on: index, sort_order: (asc|reversed) } - attributes: comma seperated, or json object list + attributes: comma separated, or json object list batch: { page: 1-based page of results, size: size of paged results @@ -183,7 +183,7 @@ def __call__(self): if batch and ("size" not in batch or "page" not in batch): batch = None # batching not providing correct options if batch: - # must be slicable for batching support + # must be sliceable for batching support page = int(batch["page"]) size = int(batch["size"]) if size > MAX_BATCH_SIZE: diff --git a/plone/app/content/configure.zcml b/plone/app/content/configure.zcml index 60466f64..615fd613 100644 --- a/plone/app/content/configure.zcml +++ b/plone/app/content/configure.zcml @@ -1,23 +1,24 @@ + xmlns:plone="http://namespaces.plone.org/plone" + > - - + + - - + - - + + diff --git a/plone/app/content/namechooser.py b/plone/app/content/namechooser.py index 8ce17835..5950f0d0 100644 --- a/plone/app/content/namechooser.py +++ b/plone/app/content/namechooser.py @@ -83,7 +83,7 @@ def _findUniqueName(self, name, obj): return new_name raise ValueError( - "Cannot find a unique name based on %s after %d attemps." + "Cannot find a unique name based on %s after %d attempts." % ( name, ATTEMPTS, diff --git a/plone/app/content/testing.py b/plone/app/content/testing.py index b5a85ce1..20d1670b 100644 --- a/plone/app/content/testing.py +++ b/plone/app/content/testing.py @@ -45,7 +45,6 @@ def ExampleFunctionVocabulary(context, query=None): class PloneAppContent(PloneSandboxLayer): - defaultBases = (PLONE_FIXTURE,) USER_NAME = "johndoe" diff --git a/plone/app/content/tests/profiles/non-ascii-workflow-profile/workflows.xml b/plone/app/content/tests/profiles/non-ascii-workflow-profile/workflows.xml index 12fd9c2e..8f49355d 100644 --- a/plone/app/content/tests/profiles/non-ascii-workflow-profile/workflows.xml +++ b/plone/app/content/tests/profiles/non-ascii-workflow-profile/workflows.xml @@ -1,6 +1,10 @@ - - + + - + diff --git a/plone/app/content/tests/profiles/non-ascii-workflow-profile/workflows/non-ascii-workflow/definition.xml b/plone/app/content/tests/profiles/non-ascii-workflow-profile/workflows/non-ascii-workflow/definition.xml index 308dc6a3..cbd432e7 100644 --- a/plone/app/content/tests/profiles/non-ascii-workflow-profile/workflows/non-ascii-workflow/definition.xml +++ b/plone/app/content/tests/profiles/non-ascii-workflow-profile/workflows/non-ascii-workflow/definition.xml @@ -1,55 +1,72 @@ - + + state_variable="review_state" + title="Workflow for non-ascii characters" + workflow_id="non-ascii-workflow" + i18n:attributes="title" + i18n:domain="plone.app.content.tests" +> - View + View - - - - Manager - - + + + + Manager + + - - - - Manager - - + + + + Manager + + - - To Äfter! - - Modify portal content - - + + To Äfter! + + Modify portal content + + - - To Ïnitial! - - Modify portal content - - + + To Ïnitial! + + Modify portal content + + diff --git a/plone/app/content/tests/profiles/non-ascii-workflow.zcml b/plone/app/content/tests/profiles/non-ascii-workflow.zcml index 1f2ac79a..5b84eb18 100644 --- a/plone/app/content/tests/profiles/non-ascii-workflow.zcml +++ b/plone/app/content/tests/profiles/non-ascii-workflow.zcml @@ -1,14 +1,15 @@ + i18n_domain="plone.app.content.tests" + > - + diff --git a/plone/app/content/tests/test_actions.py b/plone/app/content/tests/test_actions.py index 62108fda..121b9e33 100644 --- a/plone/app/content/tests/test_actions.py +++ b/plone/app/content/tests/test_actions.py @@ -8,7 +8,8 @@ from plone.locking.interfaces import ILockable from plone.testing.zope import Browser from z3c.form.interfaces import IFormLayer -from zExceptions import Unauthorized, NotFound +from zExceptions import NotFound +from zExceptions import Unauthorized from zope.component import getMultiAdapter from zope.interface import alsoProvides @@ -37,7 +38,7 @@ def setUp(self): self.browser = Browser(self.layer["app"]) self.browser.handleErrors = False self.browser.addHeader( - "Authorization", "Basic {}:{}".format(TEST_USER_NAME, TEST_USER_PASSWORD) + "Authorization", f"Basic {TEST_USER_NAME}:{TEST_USER_PASSWORD}" ) def tearDown(self): @@ -124,7 +125,7 @@ def prepare_for_acquisition_tests(self): browser_2 = Browser(self.layer["app"]) browser_2.handleErrors = False browser_2.addHeader( - "Authorization", "Basic {}:{}".format(TEST_USER_NAME, TEST_USER_PASSWORD) + "Authorization", f"Basic {TEST_USER_NAME}:{TEST_USER_PASSWORD}" ) # return the id of the root page, the nested page itself, and the diff --git a/plone/app/content/tests/test_adding.py b/plone/app/content/tests/test_adding.py index b5b9bfb4..b813c5e8 100644 --- a/plone/app/content/tests/test_adding.py +++ b/plone/app/content/tests/test_adding.py @@ -5,7 +5,6 @@ class AddingTests(unittest.TestCase): - layer = PLONE_APP_CONTENT_INTEGRATION_TESTING def setUp(self): diff --git a/plone/app/content/tests/test_content_status_modify.py b/plone/app/content/tests/test_content_status_modify.py index e1e782e0..7b53a48c 100644 --- a/plone/app/content/tests/test_content_status_modify.py +++ b/plone/app/content/tests/test_content_status_modify.py @@ -124,7 +124,6 @@ def testEditorCanSubmitButNotPublish(self): class TestContentStatusModifyFunctional(unittest.TestCase): - layer = PLONE_APP_CONTENT_DX_FUNCTIONAL_TESTING def setUp(self): diff --git a/plone/app/content/tests/test_contents.py b/plone/app/content/tests/test_contents.py index f7402fac..80ba2ecd 100644 --- a/plone/app/content/tests/test_contents.py +++ b/plone/app/content/tests/test_contents.py @@ -90,8 +90,8 @@ def setUp(self): @mock.patch( "plone.app.content.browser.contents.ContentsBaseAction.protect", lambda x: True ) # noqa - def test_delete_success_with_private_anchestor(self): - """Delete content item from a folder with private anchestor""" + def test_delete_success_with_private_ancestor(self): + """Delete content item from a folder with private ancestor""" # Create test content /it1/it2/it3 self.portal.invokeFactory("type1", id="it1", title="Item 1") self.portal.it1.invokeFactory("type1", id="it2", title="Item 2") @@ -222,8 +222,8 @@ def test_paste_fail_constraint(self): @mock.patch( "plone.app.content.browser.contents.ContentsBaseAction.protect", lambda x: True ) # noqa - def test_paste_success_with_private_anchestor(self): - """Copy content item and paste into a folder with private anchestor""" + def test_paste_success_with_private_ancestor(self): + """Copy content item and paste into a folder with private ancestor""" # Create test content /it2/it3 self.portal.invokeFactory("type1", id="it2", title="Item 2") self.portal.it2.invokeFactory("type1", id="it3", title="Item 3") @@ -274,8 +274,8 @@ def setUp(self): @mock.patch( "plone.app.content.browser.contents.ContentsBaseAction.protect", lambda x: True ) # noqa - def test_rename_success_with_private_anchestor(self): - """Rename content item from a folder with private anchestor""" + def test_rename_success_with_private_ancestor(self): + """Rename content item from a folder with private ancestor""" # Create test content /it1/it2/it3 self.portal.invokeFactory("type1", id="it1", title="Item 1") self.portal.it1.invokeFactory("type1", id="it2", title="Item 2") diff --git a/plone/app/content/tests/test_folder.py b/plone/app/content/tests/test_folder.py index 01d2764f..eef41bfe 100644 --- a/plone/app/content/tests/test_folder.py +++ b/plone/app/content/tests/test_folder.py @@ -51,7 +51,6 @@ def setUp(self): class DXBaseTest(BaseTest): - layer = PLONE_APP_CONTENT_DX_INTEGRATION_TESTING def setUp(self): @@ -126,7 +125,6 @@ def testCreators(self): class WorkflowTest(BaseTest): - layer = PLONE_APP_CONTENT_DX_FUNCTIONAL_TESTING def convertDateTimeToIndexRepr(self, date): @@ -166,7 +164,6 @@ def testStateChange(self): class RenameTest(BaseTest): - layer = PLONE_APP_CONTENT_DX_INTEGRATION_TESTING def test_folder_rename_objects(self): @@ -204,7 +201,6 @@ def test_default_page_updated_on_rename_objects(self): class ContextInfoTest(BaseTest): - layer = PLONE_APP_CONTENT_DX_INTEGRATION_TESTING def testStateChange(self): diff --git a/plone/app/content/tests/test_namechooser_unit.py b/plone/app/content/tests/test_namechooser_unit.py index ec3df752..d9d3f660 100644 --- a/plone/app/content/tests/test_namechooser_unit.py +++ b/plone/app/content/tests/test_namechooser_unit.py @@ -13,7 +13,6 @@ class NameChooserTest(unittest.TestCase): - layer = PLONE_APP_CONTENT_INTEGRATION_TESTING def setUp(self): diff --git a/plone/app/content/tests/test_non_ascii_characters_in_workflow_state.py b/plone/app/content/tests/test_non_ascii_characters_in_workflow_state.py index 386e0697..cef6398e 100644 --- a/plone/app/content/tests/test_non_ascii_characters_in_workflow_state.py +++ b/plone/app/content/tests/test_non_ascii_characters_in_workflow_state.py @@ -11,7 +11,6 @@ class TestNonAsciiCharactersWorkflow(unittest.TestCase): - layer = PLONE_APP_CONTENT_NON_ASCII_INTEGRATION_TESTING def setUp(self): diff --git a/plone/app/content/tests/test_selectdefaultpage.py b/plone/app/content/tests/test_selectdefaultpage.py index 3af4f1ce..ff3a2857 100644 --- a/plone/app/content/tests/test_selectdefaultpage.py +++ b/plone/app/content/tests/test_selectdefaultpage.py @@ -28,12 +28,13 @@ class SelectDefaultPageDXTestCase(unittest.TestCase): - layer = PLONE_APP_CONTENT_DX_FUNCTIONAL_TESTING def setUp(self): self.portal = self.layer["portal"] - self.portal.acl_users.userFolderAddUser("editor", TEST_USER_PASSWORD, ["Editor"], []) + self.portal.acl_users.userFolderAddUser( + "editor", TEST_USER_PASSWORD, ["Editor"], [] + ) self._create_structure() transaction.commit() diff --git a/plone/app/content/tests/test_widgets.py b/plone/app/content/tests/test_widgets.py index c3577139..d87b6193 100644 --- a/plone/app/content/tests/test_widgets.py +++ b/plone/app/content/tests/test_widgets.py @@ -69,7 +69,6 @@ def _disable_permission_checker(context): class BrowserTest(unittest.TestCase): - layer = PLONE_APP_CONTENT_DX_INTEGRATION_TESTING def setUp(self): @@ -664,7 +663,6 @@ def testGetMimeIcon(self): class FunctionalBrowserTest(unittest.TestCase): - layer = PLONE_APP_CONTENT_DX_FUNCTIONAL_TESTING def setUp(self): diff --git a/plone/app/content/utils.py b/plone/app/content/utils.py index d61cf028..a6131bba 100644 --- a/plone/app/content/utils.py +++ b/plone/app/content/utils.py @@ -8,6 +8,7 @@ # use simplejson because it's ahead of stdlib and supports more types import simplejson + try: from z3c.relationfield.relation import RelationValue except ImportError: diff --git a/pyproject.toml b/pyproject.toml index 05b615de..0e84fbc5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,9 @@ +# Generated from: +# https://github.com/plone/meta/tree/master/config/default +# See the inline comments on how to expand/tweak this configuration file [tool.towncrier] -filename = "CHANGES.rst" directory = "news/" +filename = "CHANGES.rst" title_format = "{version} ({project_date})" underlines = ["-", ""] @@ -18,3 +21,137 @@ showcontent = true directory = "bugfix" name = "Bug fixes:" showcontent = true + +[[tool.towncrier.type]] +directory = "internal" +name = "Internal:" +showcontent = true + +[[tool.towncrier.type]] +directory = "documentation" +name = "Documentation:" +showcontent = true + +[[tool.towncrier.type]] +directory = "tests" +name = "Tests" +showcontent = true + +## +# Add extra configuration options in .meta.toml: +# [pyproject] +# towncrier_extra_lines = """ +# extra_configuration +# """ +## + +[tool.isort] +profile = "plone" + +## +# Add extra configuration options in .meta.toml: +# [pyproject] +# isort_extra_lines = """ +# extra_configuration +# """ +## + +[tool.black] +target-version = ["py38"] + +## +# Add extra configuration options in .meta.toml: +# [pyproject] +# black_extra_lines = """ +# extra_configuration +# """ +## + +[tool.codespell] +ignore-words-list = "discreet," +skip = "*.po," +## +# Add extra configuration options in .meta.toml: +# [pyproject] +# codespell_ignores = "foo,bar" +# codespell_skip = "*.po,*.map,package-lock.json" +## + +[tool.dependencychecker] +Zope = [ + # Zope own provided namespaces + 'App', 'OFS', 'Products.Five', 'Products.OFSP', 'Products.PageTemplates', + 'Products.SiteAccess', 'Shared', 'Testing', 'ZPublisher', 'ZTUtils', + 'Zope2', 'webdav', 'zmi', + # ExtensionClass own provided namespaces + 'ExtensionClass', 'ComputedAttribute', 'MethodObject', + # Zope dependencies + 'AccessControl', 'Acquisition', 'AuthEncoding', 'beautifulsoup4', 'BTrees', + 'cffi', 'Chameleon', 'DateTime', 'DocumentTemplate', + 'MultiMapping', 'multipart', 'PasteDeploy', 'Persistence', 'persistent', + 'pycparser', 'python-gettext', 'pytz', 'RestrictedPython', 'roman', + 'soupsieve', 'transaction', 'waitress', 'WebOb', 'WebTest', 'WSGIProxy2', + 'z3c.pt', 'zc.lockfile', 'ZConfig', 'zExceptions', 'ZODB', 'zodbpickle', + 'zope.annotation', 'zope.browser', 'zope.browsermenu', 'zope.browserpage', + 'zope.browserresource', 'zope.cachedescriptors', 'zope.component', + 'zope.configuration', 'zope.container', 'zope.contentprovider', + 'zope.contenttype', 'zope.datetime', 'zope.deferredimport', + 'zope.deprecation', 'zope.dottedname', 'zope.event', 'zope.exceptions', + 'zope.filerepresentation', 'zope.globalrequest', 'zope.hookable', + 'zope.i18n', 'zope.i18nmessageid', 'zope.interface', 'zope.lifecycleevent', + 'zope.location', 'zope.pagetemplate', 'zope.processlifetime', 'zope.proxy', + 'zope.ptresource', 'zope.publisher', 'zope.schema', 'zope.security', + 'zope.sequencesort', 'zope.site', 'zope.size', 'zope.structuredtext', + 'zope.tal', 'zope.tales', 'zope.testbrowser', 'zope.testing', + 'zope.traversing', 'zope.viewlet' +] +'Products.CMFCore' = [ + 'docutils', 'five.localsitemanager', 'Missing', 'Products.BTreeFolder2', + 'Products.GenericSetup', 'Products.MailHost', 'Products.PythonScripts', + 'Products.StandardCacheManagers', 'Products.ZCatalog', 'Record', + 'zope.sendmail', 'Zope' +] +'plone.base' = [ + 'plone.batching', 'plone.registry', 'plone.schema','plone.z3cform', + 'Products.CMFCore', 'Products.CMFDynamicViewFTI', +] +python-dateutil = ['dateutil'] +ignore-packages = ['tus', ] + +## +# Add extra configuration options in .meta.toml: +# [pyproject] +# dependencies_ignores = "['zestreleaser.towncrier']" +# dependencies_mappings = [ +# "gitpython = ['git']", +# "pygithub = ['github']", +# ] +## + +[tool.check-manifest] +ignore = [ + ".editorconfig", + ".meta.toml", + ".pre-commit-config.yaml", + "tox.ini", + ".flake8", + "mx.ini", + +] +## +# Add extra configuration options in .meta.toml: +# [pyproject] +# check_manifest_ignores = """ +# "*.map.js", +# "*.pyc", +# """ +## + + +## +# Add extra configuration options in .meta.toml: +# [pyproject] +# extra_lines = """ +# _your own configuration lines_ +# """ +## diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 3e076fd9..00000000 --- a/setup.cfg +++ /dev/null @@ -1,9 +0,0 @@ -[bdist_wheel] -universal = 0 - -[isort] -# black compatible Plone isort rules: -profile = black -force_alphabetical_sort = True -force_single_line = True -lines_after_imports = 2 diff --git a/setup.py b/setup.py index fc1f1425..be16065b 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup -version = "4.0.3.dev0" +version = "4.0.4.dev0" setup( name="plone.app.content", @@ -38,23 +38,41 @@ namespace_packages=["plone", "plone.app"], include_package_data=True, zip_safe=False, + python_requires=">=3.8", extras_require=dict( test=[ - "plone.app.contenttypes", + "plone.app.contenttypes[test]", "plone.app.testing", + "plone.dexterity", + "plone.namedfile", + "plone.testing", + "zope.annotation", + "Products.GenericSetup", ] ), install_requires=[ + "plone.app.dexterity", + "plone.app.querystring", + "plone.app.uuid", + "plone.app.vocabularies>4.1.2", "plone.app.widgets", + "plone.app.z3cform", + "plone.autoform", "plone.base", "plone.i18n", + "plone.folder", + "plone.locking", "plone.memoize", "plone.protect", + "plone.supermodel", + "plone.uuid", + "Missing", + "Products.MimetypesRegistry", + "Products.PortalTransforms", "Products.statusmessages", - "Products.CMFDynamicViewFTI", # required for cmf.ModifyViewTemplate - "plone.app.vocabularies>4.1.2", - "setuptools", "simplejson", + "z3c.relationfield", "z3c.form", + "zope.browsermenu", ], ) diff --git a/tox.ini b/tox.ini new file mode 100644 index 00000000..cbb3425e --- /dev/null +++ b/tox.ini @@ -0,0 +1,208 @@ +# Generated from: +# https://github.com/plone/meta/tree/master/config/default +# See the inline comments on how to expand/tweak this configuration file +[tox] +# We need 4.4.0 for constrain_package_deps. +min_version = 4.4.0 +envlist = + lint + test + dependencies + + +## +# Add extra configuration options in .meta.toml: +# [tox] +# envlist_lines = """ +# my_other_environment +# """ +# config_lines = """ +# my_extra_top_level_tox_configuration_lines +# """ +## + +[testenv] +skip_install = true +allowlist_externals = + echo + false +# Make sure typos like `tox -e formaat` are caught instead of silently doing nothing. +# See https://github.com/tox-dev/tox/issues/2858. +commands = + echo "Unrecognized environment name {envname}" + false + +[testenv:init] +description = Prepare environment +skip_install = true +commands = + echo "Initial setup complete" + + +[testenv:format] +description = automatically reformat code +skip_install = true +deps = + pre-commit +commands = + pre-commit run -a pyupgrade + pre-commit run -a isort + pre-commit run -a black + pre-commit run -a zpretty + +[testenv:lint] +description = run linters that will help improve the code style +skip_install = true +deps = + pre-commit +commands = + pre-commit run -a + +[testenv:dependencies] +description = check if the package defines all its dependencies +skip_install = true +deps = + build + z3c.dependencychecker==2.11 +commands = + python -m build --sdist --no-isolation + dependencychecker + +[testenv:dependencies-graph] +description = generate a graph out of the dependencies of the package +skip_install = false +allowlist_externals = + sh +deps = + pipdeptree==2.5.1 + graphviz # optional dependency of pipdeptree +commands = + sh -c 'pipdeptree --exclude setuptools,wheel,pipdeptree,zope.interface,zope.component --graph-output svg > dependencies.svg' + +[testenv:test] +description = run the distribution tests +use_develop = true +skip_install = false +constrain_package_deps = true +set_env = + ROBOT_BROWSER=headlesschrome + +## +# Specify extra test environment variables in .meta.toml: +# [tox] +# test_environment_variables = """ +# PIP_EXTRA_INDEX_URL=https://my-pypi.my-server.com/ +# """ +# +# Set constrain_package_deps .meta.toml: +# [tox] +# constrain_package_deps = "false" +## +deps = + zope.testrunner + -c https://dist.plone.org/release/6.0-dev/constraints.txt + +## +# Specify additional deps in .meta.toml: +# [tox] +# test_deps_additional = "-esources/plonegovbr.portal_base[test]" +# +# Specify a custom constraints file in .meta.toml: +# [tox] +# constraints_file = "https://my-server.com/constraints.txt" +## +commands = + zope-testrunner --all --test-path={toxinidir} -s plone.app.content {posargs} +extras = + test + +## +# Add extra configuration options in .meta.toml: +# [tox] +# test_extras = """ +# tests +# widgets +# """ +## + +[testenv:coverage] +description = get a test coverage report +use_develop = true +skip_install = false +constrain_package_deps = true +set_env = + ROBOT_BROWSER=headlesschrome + +## +# Specify extra test environment variables in .meta.toml: +# [tox] +# test_environment_variables = """ +# PIP_EXTRA_INDEX_URL=https://my-pypi.my-server.com/ +# """ +## +deps = + coverage + zope.testrunner + -c https://dist.plone.org/release/6.0-dev/constraints.txt + +commands = + coverage run --branch --source plone.app.content {envbindir}/zope-testrunner --quiet --all --test-path={toxinidir} -s plone.app.content {posargs} + coverage report -m --format markdown + coverage xml +extras = + test + + +[testenv:release-check] +description = ensure that the distribution is ready to release +skip_install = true +deps = + twine + build + towncrier + -c https://dist.plone.org/release/6.0-dev/constraints.txt + +commands = + # fake version to not have to install the package + # we build the change log as news entries might break + # the README that is displayed on PyPI + towncrier build --version=100.0.0 --yes + python -m build --sdist --no-isolation + twine check dist/* + +[testenv:circular] +description = ensure there are no cyclic dependencies +use_develop = true +skip_install = false +set_env = + +## +# Specify extra test environment variables in .meta.toml: +# [tox] +# test_environment_variables = """ +# PIP_EXTRA_INDEX_URL=https://my-pypi.my-server.com/ +# """ +## +allowlist_externals = + sh +deps = + pipdeptree + pipforester + -c https://dist.plone.org/release/6.0-dev/constraints.txt + +commands = + # Generate the full dependency tree + sh -c 'pipdeptree -j > forest.json' + # Generate a DOT graph with the circular dependencies, if any + pipforester -i forest.json -o forest.dot --cycles + # Report if there are any circular dependencies, i.e. error if there are any + pipforester -i forest.json --check-cycles -o /dev/null + + +## +# Add extra configuration options in .meta.toml: +# [tox] +# extra_lines = """ +# _your own configuration lines_ +# """ +##