diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..b4158b8 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,39 @@ +# Generated from: +# https://github.com/plone/meta/tree/master/config/default +# +# 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 + +[{Makefile,.gitmodules}] +# Tab indentation (no size specified, but view as 4 spaces) +indent_style = tab +indent_size = unset +tab_width = unset diff --git a/.meta.toml b/.meta.toml new file mode 100644 index 0000000..8560e56 --- /dev/null +++ b/.meta.toml @@ -0,0 +1,13 @@ +# Generated from: +# https://github.com/plone/meta/tree/master/config/default +[meta] +template = "default" +commit-id = "13d8d6c0" + +[codespell] +additional-ignores = "ist,discreet" + +[dependencies] +mappings = [ + "Zope = ['Products.Five', 'Products.PageTemplates', 'ZTUtils']", + ] diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..582f8ac --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,42 @@ +# Generated from: +# https://github.com/plone/meta/tree/master/config/default +ci: + autofix_prs: false + autoupdate_schedule: monthly + +repos: +- repo: https://github.com/asottile/pyupgrade + rev: v3.3.1 + 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.1.0 + hooks: + - id: black +- repo: https://github.com/collective/zpretty + rev: 3.0.2 + hooks: + - id: zpretty +- repo: https://github.com/PyCQA/flake8 + rev: 6.0.0 + hooks: + - id: flake8 +- repo: https://github.com/codespell-project/codespell + rev: v2.2.2 + hooks: + - id: codespell + additional_dependencies: + - tomli +- 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 diff --git a/news/13d8d6c0.internal b/news/13d8d6c0.internal new file mode 100644 index 0000000..c08f539 --- /dev/null +++ b/news/13d8d6c0.internal @@ -0,0 +1,2 @@ +Update configuration files. +[plone devs] diff --git a/pyproject.toml b/pyproject.toml index 05b615d..7415149 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,5 @@ +# Generated from: +# https://github.com/plone/meta/tree/master/config/default [tool.towncrier] filename = "CHANGES.rst" directory = "news/" @@ -18,3 +20,30 @@ 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 + +[tool.isort] +profile = "plone" + +[tool.black] +target-version = ["py38"] + +[tool.codespell] +ignore-words-list = "ist,discreet" + +[tool.dependencychecker] +Zope = ['Products.Five', 'Products.PageTemplates', 'ZTUtils'] diff --git a/setup.cfg b/setup.cfg index a72fc52..6bf840a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -30,13 +30,26 @@ python_requires = >=3.8 install_requires = setuptools # be aware to _not_ add dependencies to plone.app.* or Plones Products.* packages! + AccessControl + Acquisition + ZODB + Zope>=5 plone.batching plone.registry + plone.schema plone.z3cform Products.BTreeFolder2 Products.CMFCore Products.CMFDynamicViewFTI - Zope>=5 + transaction + zExceptions + zope.component + zope.deprecation + zope.i18n + zope.i18nmessageid + zope.interface + zope.publisher + zope.schema namespace_packages = plone @@ -47,8 +60,8 @@ zip_safe = False [options.extras_require] test = - plone.testing plone.subrequest + zope.tal [options.packages.find] where = @@ -65,14 +78,21 @@ ignore = .coveragerc .editorconfig .gitattributes + .meta.toml + .pre-commit-config.yaml + tox.ini [flake8] -exclude = docs,*.egg. -max-complexity = 15 - -[isort] -# black compatible Plone isort rules: -profile = black -force_alphabetical_sort = True -force_single_line = True -lines_after_imports = 2 +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, +per-file-ignores = + src/plone/base/interfaces/__init__.py:F401 + src/plone/base/permissions.py:F401,E402 diff --git a/src/plone/base/batch.py b/src/plone/base/batch.py index c9f56f4..ed202d7 100644 --- a/src/plone/base/batch.py +++ b/src/plone/base/batch.py @@ -5,7 +5,6 @@ class Batch(QuantumBatch): - b_start_str = "b_start" def __init__( diff --git a/src/plone/base/i18nl10n.py b/src/plone/base/i18nl10n.py index e8adf5f..f2a3efd 100644 --- a/src/plone/base/i18nl10n.py +++ b/src/plone/base/i18nl10n.py @@ -176,12 +176,12 @@ def ulocalized_time( # catalog date_format_long, date_format_short, and time_format # These msgids are translated using interpolation. # The variables used here are the same as used in the strftime - # formating. + # formatting. # Supported are: # %A, %a, %B, %b, %H, %I, %m, %d, %M, %p, %S, %Y, %y, %Z # Each used as variable in the msgstr without the %. # For example: "${A} ${d}. ${B} ${Y}, ${H}:${M} ${Z}" - # Each language dependend part is translated itself as well. + # Each language dependent part is translated itself as well. # From http://docs.python.org/lib/module-time.html # @@ -206,7 +206,7 @@ def ulocalized_time( if not IDateTime.providedBy(time): try: time = DateTime(time) - except: + except Exception: logger.debug(f"Failed to convert {time} to a DateTime object") return None diff --git a/src/plone/base/interfaces/__init__.py b/src/plone/base/interfaces/__init__.py index ad92b39..23a2530 100644 --- a/src/plone/base/interfaces/__init__.py +++ b/src/plone/base/interfaces/__init__.py @@ -1,4 +1,3 @@ -# flake8: noqa from .basetool import IPloneBaseTool from .basetool import IPloneCatalogTool from .basetool import IPloneTool diff --git a/src/plone/base/interfaces/controlpanel.py b/src/plone/base/interfaces/controlpanel.py index 4e31c21..13b092b 100644 --- a/src/plone/base/interfaces/controlpanel.py +++ b/src/plone/base/interfaces/controlpanel.py @@ -1,6 +1,5 @@ from .basetool import IPloneBaseTool from plone import schema -from plone.autoform import directives from plone.base import PloneMessageFactory as _ from Products.CMFCore.utils import getToolByName from zope.component.hooks import getSite @@ -85,7 +84,7 @@ def registerConfiglet( name, action, condition="", - permission="", # NOQA + permission="", category="Plone", visible=1, appId=None, @@ -95,25 +94,24 @@ def registerConfiglet( ): """Registration of a Configlet""" - def unregisterConfiglet(id): # NOQA + def unregisterConfiglet(id): """unregister Configlet""" - def unregisterApplication(appId): # NOQA + def unregisterApplication(appId): """unregister Application with all configlets""" - def getGroupIds(): # NOQA + def getGroupIds(): """list of the group ids""" - def getGroups(): # NOQA + def getGroups(): """list of groups as dicts with id and title""" - def enumConfiglets(group=None): # NOQA + def enumConfiglets(group=None): """lists the Configlets of a group, returns them as dicts by calling .getAction() on each of them""" class IEditingSchema(Interface): - available_editors = schema.List( title=_("Available editors"), description=_("Available editors in the portal."), @@ -327,7 +325,15 @@ class IFilterSchema(Interface): custom_attributes = schema.List( title=_("Custom attributes"), description=_("These attributes are additionally allowed."), - default=["style", "controls", "poster", "autoplay", "loading", "srcset", "sizes"], + default=[ + "style", + "controls", + "poster", + "autoplay", + "loading", + "srcset", + "sizes", + ], value_type=schema.TextLine(), missing_value=[], required=False, @@ -469,7 +475,12 @@ class ITinyMCELayoutSchema(Interface): description=_("Name|class"), value_type=schema.TextLine(), missing_value=[], - default=["Listing|listing", "Listing compact|listing-compact", "Subdued grid|plain", "Invisible Grid|invisible-grid"], + default=[ + "Listing|listing", + "Listing compact|listing-compact", + "Subdued grid|plain", + "Invisible Grid|invisible-grid", + ], ) formats = schema.Text( @@ -479,7 +490,7 @@ class ITinyMCELayoutSchema(Interface): "A format is for example the style that get applied when " "you press the bold button inside the editor. " "See https://www.tinymce.com/docs/configure/content-formatting/#formats" - ), # NOQA: E501 + ), constraint=validate_json, default=dump_json_to_text( { @@ -543,7 +554,7 @@ class ITinyMCEPluginSchema(Interface): SimpleTerm("paste", "paste", "paste"), SimpleTerm("preview", "preview", "preview"), SimpleTerm("print", "print", "print"), - # XXX disable save button since it is not implemeneted + # XXX disable save button since it is not implemented # SimpleTerm('save', 'save', u'save'), SimpleTerm("searchreplace", "searchreplace", "searchreplace"), SimpleTerm("tabfocus", "tabfocus", "tabfocus"), @@ -838,7 +849,6 @@ class ITinyMCESchema( class IMaintenanceSchema(Interface): - days = schema.Int( title=_("Days of object history to keep after packing"), description=_( @@ -855,7 +865,6 @@ class IMaintenanceSchema(Interface): class INavigationSchema(Interface): - navigation_depth = schema.Int( title=_("Navigation depth"), description=_("Number of folder levels to show in the navigation."), @@ -983,7 +992,6 @@ class INavigationSchema(Interface): class ISearchSchema(Interface): - enable_livesearch = schema.Bool( title=_("Enable LiveSearch"), description=_( @@ -1050,7 +1058,6 @@ class ISearchSchema(Interface): class ISecuritySchema(Interface): - enable_self_reg = schema.Bool( title=_("Enable self-registration"), description=_( @@ -1135,7 +1142,6 @@ class ISecuritySchema(Interface): class ISiteSchema(Interface): - site_title = schema.TextLine( title=_("Site title"), description=_( @@ -1255,7 +1261,7 @@ class ISiteSchema(Interface): title=_("No thumbs in list views"), description=_( "Suppress thumbs in all list views; " - "this default can be overriden individually" + "this default can be overridden individually" ), default=False, required=False, @@ -1265,7 +1271,7 @@ class ISiteSchema(Interface): title=_("No thumbs in summary views"), description=_( "Suppress thumbs in all summary views; " - "this default can be overriden individually" + "this default can be overridden individually" ), default=False, required=False, @@ -1275,7 +1281,7 @@ class ISiteSchema(Interface): title=_("No thumbs in table views"), description=_( "Suppress thumbs in all tableviews and in folder contents view; " - "this default can be overriden individually" + "this default can be overridden individually" ), default=False, required=False, @@ -1283,7 +1289,7 @@ class ISiteSchema(Interface): thumb_scale_portlet = schema.Choice( title=_("Thumb scale for portlets"), - description=_("This default can be overriden individually."), + description=_("This default can be overridden individually."), default="icon", vocabulary="plone.app.vocabularies.ImagesScales", required=True, @@ -1292,7 +1298,7 @@ class ISiteSchema(Interface): thumb_scale_listing = schema.Choice( title=_("Thumb scale for listings"), description=_( - "E.g. standard view; This default can be overriden individually." + "E.g. standard view; This default can be overridden individually." ), default="thumb", vocabulary="plone.app.vocabularies.ImagesScales", @@ -1303,7 +1309,7 @@ class ISiteSchema(Interface): title=_("Thumb scale for tables"), description=_( "E.g., tabular view, folder content listing;" - " This default can be overriden individually." + " This default can be overridden individually." ), default="tile", vocabulary="plone.app.vocabularies.ImagesScales", @@ -1312,7 +1318,7 @@ class ISiteSchema(Interface): thumb_scale_summary = schema.Choice( title=_("Thumb scale for summary view"), - description=_("This default can be overriden individually."), + description=_("This default can be overridden individually."), default="mini", vocabulary="plone.app.vocabularies.ImagesScales", required=True, @@ -1469,7 +1475,6 @@ class ITypesSchema(Interface): class IMailSchema(Interface): - smtp_host = schema.TextLine( title=_("label_smtp_server", default="SMTP server"), description=_( @@ -1546,7 +1551,6 @@ class IMailSchema(Interface): class IMarkupSchema(Interface): - default_type = schema.Choice( title=_("Default format"), description=_( @@ -1592,7 +1596,6 @@ class IMarkupSchema(Interface): class IUserGroupsSettingsSchema(Interface): - many_groups = schema.Bool( title=_("Many groups?"), description=_( @@ -1631,7 +1634,6 @@ def validate_twitter_username(value): class ISocialMediaSchema(Interface): - share_social_data = schema.Bool( title=_("Share social data"), description=_( @@ -1751,7 +1753,7 @@ class IImagingSchema(Interface): description=_("Enter a JSON-formatted picture variants configuration."), schema=json.dumps( { - "title": "Image srcset defintion", + "title": "Image srcset definition", "type": "object", "additionalProperties": {"$ref": "#/$defs/srcset"}, "$defs": { @@ -1799,7 +1801,13 @@ class IImagingSchema(Interface): "sourceset": [ { "scale": "larger", - "additionalScales": ["preview", "teaser", "large", "great", "huge"], + "additionalScales": [ + "preview", + "teaser", + "large", + "great", + "huge", + ], }, ], }, @@ -1837,7 +1845,6 @@ class IImagingSchema(Interface): class ILoginSchema(Interface): - auth_cookie_length = schema.Int( title=_("Auth cookie length"), default=0, required=False ) @@ -1867,7 +1874,6 @@ class ILoginSchema(Interface): class ILinkSchema(Interface): - external_links_open_new_window = schema.Bool( title=_("Open external links in new a window"), description=_(""), @@ -1899,7 +1905,6 @@ def _check_tales_expression(value): class IActionSchema(Interface): - category = schema.Choice( title=_("Category"), vocabulary="plone.app.vocabularies.PortalActionCategories", @@ -1963,7 +1968,6 @@ class IActionSchema(Interface): class INewActionSchema(Interface): - category = schema.Choice( title=_("Category"), vocabulary="plone.app.vocabularies.PortalActionCategories", @@ -2004,7 +2008,7 @@ class IPloneControlPanelForm(IPloneControlPanelView): """Forms using plone.app.controlpanel""" def _on_save(): - """Callback mehod which can be implemented by control panels to + """Callback method which can be implemented by control panels to react when the form is successfully saved. This avoids the need to re-define actions only to do some additional notification or configuration which cannot be handled by the normal schema adapter. diff --git a/src/plone/base/interfaces/password_reset.py b/src/plone/base/interfaces/password_reset.py index d8fa0f8..685b774 100644 --- a/src/plone/base/interfaces/password_reset.py +++ b/src/plone/base/interfaces/password_reset.py @@ -23,7 +23,7 @@ class IPWResetTool(Interface): reset forgotten passwords. This interface is rather sparse, but sufficient to describe the - task. (In this manner we void being dependant on a specific + task. (In this manner we void being dependent on a specific process) The details of the process are in the implementation, where they belong.""" diff --git a/src/plone/base/interfaces/resources.py b/src/plone/base/interfaces/resources.py index 2b5b5ad..54bd572 100644 --- a/src/plone/base/interfaces/resources.py +++ b/src/plone/base/interfaces/resources.py @@ -11,7 +11,6 @@ class IResourceRegistry(zope.interface.Interface): - # DEPRECATED url = schema.ASCIILine(title=_("Resources base URL"), required=False) @@ -43,7 +42,6 @@ class IResourceRegistry(zope.interface.Interface): class IBundleRegistry(zope.interface.Interface): - jscompilation = schema.ASCIILine( title=_("URL of the last js compilation"), required=False ) diff --git a/src/plone/base/interfaces/syndication.py b/src/plone/base/interfaces/syndication.py index 025bb1e..fc8f6d6 100644 --- a/src/plone/base/interfaces/syndication.py +++ b/src/plone/base/interfaces/syndication.py @@ -129,12 +129,11 @@ def file_type(): class ISiteSyndicationSettings(Interface): - allowed = schema.Bool( title=_("Allowed"), description=_("Allow syndication for collections and folders " "on site."), default=True, - required=False + required=False, ) default_enabled = schema.Bool( @@ -144,21 +143,21 @@ class ISiteSyndicationSettings(Interface): "folders and collections." ), default=False, - required=False + required=False, ) search_rss_enabled = schema.Bool( title=_("Search RSS enabled"), description=_("Allows users to subscribe to feeds of search results"), default=True, - required=False + required=False, ) show_author_info = schema.Bool( title=_("Show author info"), description=_("Should feeds include author information"), default=True, - required=False + required=False, ) render_body = schema.Bool( @@ -169,7 +168,7 @@ class ISiteSyndicationSettings(Interface): "render it, otherwise use description.", ), default=False, - required=False + required=False, ) max_items = schema.Int( @@ -215,7 +214,7 @@ class ISiteSyndicationSettings(Interface): "for particular folders and collections " ), default=False, - required=False + required=False, ) show_syndication_link = schema.Bool( @@ -224,17 +223,12 @@ class ISiteSyndicationSettings(Interface): "Enable RSS link document action on the syndication " "content item." ), default=False, - required=False + required=False, ) class IFeedSettings(Interface): - - enabled = schema.Bool( - title=_("Enabled"), - default=False, - required=False - ) + enabled = schema.Bool(title=_("Enabled"), default=False, required=False) feed_types = schema.Tuple( title=_("Feed Types"), @@ -254,7 +248,7 @@ class IFeedSettings(Interface): "render it, otherwise use description.", ), default=False, - required=False + required=False, ) max_items = schema.Int( diff --git a/src/plone/base/interfaces/translationservice.py b/src/plone/base/interfaces/translationservice.py index 6524801..e4ea7b3 100644 --- a/src/plone/base/interfaces/translationservice.py +++ b/src/plone/base/interfaces/translationservice.py @@ -6,7 +6,7 @@ class ITranslationServiceTool(Interface): def translate(*args, **kw): """Translate method to access the translation service - from resticted code like skins. + from restricted code like skins. """ def encode(m, input_encoding=None, output_encoding=None, errors="strict"): diff --git a/src/plone/base/tests/messages.rst b/src/plone/base/tests/messages.rst index b54d798..2187c65 100644 --- a/src/plone/base/tests/messages.rst +++ b/src/plone/base/tests/messages.rst @@ -25,7 +25,7 @@ You can also define a default text: >>> msg.default 'This is the text.' -And at last there is the possibility of variable substition: +And at last there is the possibility of variable substitution: >>> project = 'Plone' >>> msg = _('id', default='Hello ${name}', mapping={'name' : project}) @@ -117,7 +117,7 @@ Inform the engine of our variables. >>> engine.setLocal('msg', msg) >>> engine.setLocal('note', note) -We also need a HTMLParser and TALInterpreter and add a simple convience function +We also need a HTMLParser and TALInterpreter and add a simple convenience function to get the parsed and interpreted text. >>> from zope.tal.htmltalparser import HTMLTALParser diff --git a/src/plone/base/tests/test_i18nl10n.py b/src/plone/base/tests/test_i18nl10n.py index 5681fdc..28cd72f 100644 --- a/src/plone/base/tests/test_i18nl10n.py +++ b/src/plone/base/tests/test_i18nl10n.py @@ -1,6 +1,5 @@ """ Unit tests for plone.base.i18nl10n module. """ from contextlib import contextmanager -from unittest.mock import MagicMock from unittest.mock import patch from zope.publisher.browser import TestRequest @@ -73,7 +72,6 @@ def mock_translate(msgid, *args, **kwargs): # original translate function. This depends on the keyword arguments having # a mapping and/or a default. if override: - orig_msgid = msgid msgid = override standard = translate(msgid, *args, **kwargs) if standard == default and override: diff --git a/src/plone/base/tests/test_utils.py b/src/plone/base/tests/test_utils.py index fc61a11..3e8a4dd 100644 --- a/src/plone/base/tests/test_utils.py +++ b/src/plone/base/tests/test_utils.py @@ -67,7 +67,7 @@ def __init__(self, physical_path): if self.physical_path.split("/")[-1] in ( "PloneSite", "SubSite", - ): # noqa + ): alsoProvides(self, ISite) @property @@ -75,9 +75,7 @@ def id(self): return self.physical_path.split("/")[-1] def absolute_url(self): - return ( - self.vh_url + self.physical_path[len(self.vh_root) :] or "/" - ) # noqa + return self.vh_url + self.physical_path[len(self.vh_root) :] or "/" def restrictedTraverse(self, path): return MockContext(self.vh_root + path) @@ -111,7 +109,7 @@ def physicalPathFromURL(self, url): ctx = MockContext("/approot/PloneSite/folder/SubSite/folder") self.assertEqual(get_top_site_from_url(ctx, req).id, "PloneSite") - # Case 4, using unicode paths accidentially: + # Case 4, using unicode paths accidentally: ctx = MockContext("/approot/PloneSite/folder/SubSite/folder") self.assertEqual(get_top_site_from_url(ctx, req).id, "PloneSite") diff --git a/src/plone/base/utils.py b/src/plone/base/utils.py index bb4ffe8..08c006f 100644 --- a/src/plone/base/utils.py +++ b/src/plone/base/utils.py @@ -27,10 +27,10 @@ SIZE_CONST = { "KB": 1024, - "MB": 1024 ** 2, - "GB": 1024 ** 3, - "TB": 1024 ** 4, - "PB": 1024 ** 5, + "MB": 1024**2, + "GB": 1024**3, + "TB": 1024**4, + "PB": 1024**5, } SIZE_ORDER = ("PB", "TB", "GB", "MB", "KB") @@ -98,7 +98,6 @@ def safeToInt(value, default=0): def safe_text(value, encoding="utf-8") -> str: """Converts a value to text, even it is already a text string. - >>> from Products.CMFPlone.utils import safe_text >>> test_bytes = u'\u01b5'.encode('utf-8') >>> safe_text('spam') == u'spam' True @@ -122,7 +121,7 @@ def safe_text(value, encoding="utf-8") -> str: if isinstance(value, bytes): try: value = str(value, encoding) - except (UnicodeDecodeError): + except UnicodeDecodeError: value = value.decode("utf-8", "replace") return value @@ -161,7 +160,7 @@ def safe_callable(obj): def get_empty_title(context, translated=True): """Returns string to be used for objects with no title or id""" - # The default is an extra fancy unicode elipsis + # The default is an extra fancy unicode ellipsis, empty = b"\x5b\xc2\xb7\xc2\xb7\xc2\xb7\x5d".decode("utf8") if translated: if context is not None: @@ -341,7 +340,7 @@ def get_top_site_from_url(context, request): _path = "/".join(url_path[: _path_idx + 1]) or "/" site_path = "/".join(request.physicalPathFromURL(_path)) or "/" site = context.restrictedTraverse(site_path) - except (ValueError, AttributeError) as exc: + except (ValueError, AttributeError): # On error, just return getSite. # Refs: https://github.com/plone/plone.app.content/issues/103 # Also, TestRequest doesn't have physicalPathFromURL @@ -513,7 +512,7 @@ def _check_for_collision(contained_by, cid, **kwargs): contained_by.checkValidId(cid) except ConflictError: raise - except: # noqa: E722 + except Exception: return _("${name} is reserved.", mapping={"name": cid}) # make sure we don't collide with any parent method aliases @@ -584,9 +583,9 @@ def unrestricted_construct_instance(type_name, container, id, *args, **kw): to create the object without security checks. """ id = str(id) - typesTool = getToolByName(container, 'portal_types') + typesTool = getToolByName(container, "portal_types") fti = typesTool.getTypeInfo(type_name) if not fti: - raise ValueError('Invalid type %s' % type_name) + raise ValueError("Invalid type %s" % type_name) return fti._constructInstance(container, id, *args, **kw) diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..c079715 --- /dev/null +++ b/tox.ini @@ -0,0 +1,51 @@ +# Generated from: +# https://github.com/plone/meta/tree/master/config/default +[tox] +envlist = + format + lint + test + +[testenv] +allowlist_externals = + sh + +[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 and generate a graph out of them +deps = + z3c.dependencychecker==2.11 + pipdeptree==2.5.1 + graphviz # optional dependency of pipdeptree +commands = + dependencychecker + sh -c 'pipdeptree --exclude setuptools,pipdeptree,wheel,pipdeptree,z3c.dependencychecker,zope.interface,zope.component --graph-output svg > dependencies.svg' + +[testenv:test] +usedevelop = true +deps = + zope.testrunner + plone.portlets # undeclared dependency of plone.protect + -c https://dist.plone.org/release/6.0-dev/constraints.txt +commands = + zope-testrunner --test-path={toxinidir}/src -s plone.base +extras = + test