diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml
new file mode 100644
index 0000000..9b23c02
--- /dev/null
+++ b/.github/workflows/black.yml
@@ -0,0 +1,35 @@
+name: Black
+on: [push]
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ python-version: [3.8]
+
+ steps:
+ # git checkout
+ - uses: actions/checkout@v2
+
+ # python setup
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v1
+ with:
+ python-version: ${{ matrix.python-version }}
+
+ # python cache
+ - uses: actions/cache@v1
+ with:
+ path: ~/.cache/pip
+ key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
+ restore-keys: |
+ ${{ runner.os }}-pip-
+
+ # install black
+ - name: install black
+ run: pip install black
+
+ # run black
+ - name: run black
+ run: black src/ --check --diff
diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml
new file mode 100644
index 0000000..97c7dfa
--- /dev/null
+++ b/.github/workflows/flake8.yml
@@ -0,0 +1,35 @@
+name: Flake8
+on: [push]
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ python-version: [3.8]
+
+ steps:
+ # git checkout
+ - uses: actions/checkout@v2
+
+ # python setup
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v1
+ with:
+ python-version: ${{ matrix.python-version }}
+
+ # python cache
+ - uses: actions/cache@v1
+ with:
+ path: ~/.cache/pip
+ key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
+ restore-keys: |
+ ${{ runner.os }}-pip-
+
+ # install flake8
+ - name: install flake8
+ run: pip install flake8
+
+ # run black
+ - name: run flake8
+ run: flake8 src/ setup.py
diff --git a/.github/workflows/isort.yaml b/.github/workflows/isort.yaml
new file mode 100644
index 0000000..039aeb0
--- /dev/null
+++ b/.github/workflows/isort.yaml
@@ -0,0 +1,10 @@
+name: Run isort
+on:
+ - push
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - uses: isort/isort-action@v1
diff --git a/.github/workflows/pyroma.yml b/.github/workflows/pyroma.yml
new file mode 100644
index 0000000..bbad3c2
--- /dev/null
+++ b/.github/workflows/pyroma.yml
@@ -0,0 +1,35 @@
+name: Pyroma
+on: [push]
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ python-version: [3.8]
+
+ steps:
+ # git checkout
+ - uses: actions/checkout@v2
+
+ # python setup
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v1
+ with:
+ python-version: ${{ matrix.python-version }}
+
+ # python cache
+ - uses: actions/cache@v1
+ with:
+ path: ~/.cache/pip
+ key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
+ restore-keys: |
+ ${{ runner.os }}-pip-
+
+ # install pyroma
+ - name: install pyroma
+ run: pip install pyroma
+
+ # run pyroma
+ - name: run pyroma
+ run: pyroma -n 10 -d .
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
new file mode 100644
index 0000000..4d9c4d1
--- /dev/null
+++ b/.github/workflows/tests.yml
@@ -0,0 +1,67 @@
+name: Tests
+
+on:
+ push:
+ paths-ignore:
+ - '**.md'
+ - '**.rst'
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ max-parallel: 4
+ matrix:
+ python: ["3.8", "3.9", "3.10", "3.11"]
+ plone: ["52", "60"]
+ tz: ["UTC", "Europe/Rome"]
+ exclude:
+ - python: "3.10"
+ plone: "52"
+ - python: "3.11"
+ plone: "52"
+ steps:
+ - uses: actions/checkout@v3
+ - name: Cache eggs
+ uses: actions/cache@v3
+ with:
+ path: eggs
+ key: ${{ runner.OS }}-build-python${{ matrix.python }}-${{ matrix.plone }}
+ - name: Set up Python ${{ matrix.python }}
+ uses: actions/setup-python@v3
+ with:
+ python-version: ${{ matrix.python }}
+ - name: Install dependencies
+ run: |
+ pip install -r requirements.txt -c constraints_plone${{ matrix.plone }}.txt
+ cp test_plone${{ matrix.plone }}.cfg buildout.cfg
+ - name: Install buildout
+ run: |
+ buildout -N code-analysis:return-status-codes=True
+ - name: Code analysis
+ run: |
+ bin/code-analysis
+ - name: Run tests
+ run: |
+ bin/test-coverage
+ env:
+ PROXY_BEARER_AUTH: on
+ TZ: ${{ matrix.tz }}
+ - name: Upload coverage data to coveralls.io
+ run: |
+ pip install coveralls
+ coveralls --service=github
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ COVERALLS_FLAG_NAME: py${{ matrix.python }}-plone${{ matrix.plone }}-tz${{ matrix.tz }}
+ COVERALLS_PARALLEL: true
+
+ coveralls_finish:
+ needs: build
+ runs-on: ubuntu-latest
+ steps:
+ - name: Finished
+ run: |
+ pip install --upgrade coveralls
+ coveralls --service=github --finish
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/zpretty.yml b/.github/workflows/zpretty.yml
new file mode 100644
index 0000000..180f0e9
--- /dev/null
+++ b/.github/workflows/zpretty.yml
@@ -0,0 +1,40 @@
+name: zpretty
+on: [push]
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ python-version: [3.8]
+
+ steps:
+ # git checkout
+ - uses: actions/checkout@v2
+
+ # python setup
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v1
+ with:
+ python-version: ${{ matrix.python-version }}
+
+ # python cache
+ - uses: actions/cache@v1
+ with:
+ path: ~/.cache/pip
+ key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
+ restore-keys: |
+ ${{ runner.os }}-pip-
+
+ # install zpretty
+ - name: install zpretty
+ run: pip install zpretty
+
+ # run zpretty
+ - name: run zpretty
+ run: find src -name '*.zcml' | xargs zpretty -i
+
+ # XXX: this doesn't work on gh actions (https://github.com/plone/plone.restapi/pull/1119/checks?check_run_id=2686474411)
+ # run git diff
+ - name: run git diff
+ run: git diff --exit-code
diff --git a/.gitignore b/.gitignore
index def23af..0bf387c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,13 +1,16 @@
+__pycache__
+.DS_Store
+pyvenv.cfg
.coverage
+coverage.json
+.python-version
*.egg-info
-*.EGG-INFO
-*.egg
-*.EGG
*.log
*.mo
*.py?
*.swp
# dirs
+__pycache__
bin/
buildout-cache/
develop-eggs/
@@ -16,8 +19,10 @@ htmlcov/
include/
lib/
local/
+node_modules/
parts/
src/*
+dist/*
test.plone_addon/
var/
# files
@@ -28,6 +33,9 @@ log.html
output.xml
pip-selfcheck.json
report.html
+.vscode/
+.tox/
+reports/
# excludes
!.coveragerc
!.editorconfig
@@ -35,5 +43,5 @@ report.html
!.gitignore
!.gitkeep
!.travis.yml
-!src/rer
-.DS_Store
+!src/redturtle
+.idea/
diff --git a/base.cfg b/base.cfg
index 331cad6..a18af18 100644
--- a/base.cfg
+++ b/base.cfg
@@ -17,8 +17,11 @@ parts =
omelette
robot
plone-helper-scripts
-develop = .
+develop = .
+sources-dir = extras
+auto-checkout = *
+always-checkout = force
[instance]
recipe = plone.recipe.zope2instance
@@ -29,12 +32,24 @@ environment-vars =
eggs =
Plone
Pillow
- rer.externalnews [test]
-
+ rer.externalnews[test]
+
+zcml-additional =
+
+
+
[code-analysis]
-recipe = plone.recipe.codeanalysis[recommended]
-directory = ${buildout:directory}/src/collective
+recipe = plone.recipe.codeanalysis
+directory = ${buildout:directory}/src/rer
return-status-codes = False
@@ -46,8 +61,6 @@ eggs = ${instance:eggs}
[test]
recipe = zc.recipe.testrunner
eggs = ${instance:eggs}
-initialization =
- os.environ['TZ'] = 'UTC'
defaults = ['-s', 'rer.externalnews', '--auto-color', '--auto-progress']
@@ -60,10 +73,12 @@ eggs = coverage
recipe = collective.recipe.template
input = inline:
#!/bin/bash
+ set -e
export TZ=UTC
${buildout:directory}/bin/coverage run bin/test $*
${buildout:directory}/bin/coverage html
- ${buildout:directory}/bin/coverage report -m --fail-under=90
+ ${buildout:directory}/bin/coverage report -m --fail-under=60
+ # ${buildout:directory}/bin/coverage report -m --fail-under=90
# Fail (exit status 1) if coverage returns exit status 2 (this happens
# when test coverage is below 100%.
output = ${buildout:directory}/bin/test-coverage
@@ -104,6 +119,4 @@ scripts =
[versions]
# Don't use a released version of rer.externalnews
rer.externalnews =
-
-[sources]
-plone.formwidget.contenttree = git https://github.com/plone/plone.formwidget.contenttree.git
+setuptools =
diff --git a/buildout.cfg b/buildout.cfg
index 1672439..d7db038 100644
--- a/buildout.cfg
+++ b/buildout.cfg
@@ -2,7 +2,4 @@
# use this extend one of the buildout configuration:
extends =
-# test_plone43.cfg
-# test_plone50.cfg
-# test_plone51.cfg
- test_plone52.cfg
+ test_plone60.cfg
diff --git a/constraints.txt b/constraints.txt
index 24cbf87..c1fb3a1 100644
--- a/constraints.txt
+++ b/constraints.txt
@@ -1 +1 @@
--c constraints_plone52.txt
+-c constraints_plone60.txt
diff --git a/constraints_plone50.txt b/constraints_plone50.txt
deleted file mode 100644
index f3a36b2..0000000
--- a/constraints_plone50.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-setuptools==27.3.0
-zc.buildout==2.5.3
diff --git a/constraints_plone51.txt b/constraints_plone51.txt
deleted file mode 100644
index b57e577..0000000
--- a/constraints_plone51.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-setuptools==40.2.0
-zc.buildout==2.12.2
diff --git a/constraints_plone52.txt b/constraints_plone52.txt
index b57e577..3dd8048 100644
--- a/constraints_plone52.txt
+++ b/constraints_plone52.txt
@@ -1,2 +1,3 @@
-setuptools==40.2.0
-zc.buildout==2.12.2
+-c https://dist.plone.org/release/5.2-latest/requirements.txt
+# setuptools==40.2.0
+# zc.buildout==2.13.2
diff --git a/constraints_plone60.txt b/constraints_plone60.txt
new file mode 100644
index 0000000..005e694
--- /dev/null
+++ b/constraints_plone60.txt
@@ -0,0 +1 @@
+-c https://dist.plone.org/release/6.0-latest/requirements.txt
diff --git a/requirements.txt b/requirements.txt
index fa2f614..af90416 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,4 @@
--c constraints_plone52.txt
+pip
setuptools
zc.buildout
+wheel
diff --git a/setup.cfg b/setup.cfg
index f1aa06c..5029d67 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -4,13 +4,32 @@ ignore =
.coveragerc
.editorconfig
.gitattributes
- bootstrap-buildout.py
[isort]
-# for details see
-# http://docs.plone.org/develop/styleguide/python.html#grouping-and-sorting
+# black compatible isort rules:
force_alphabetical_sort = True
-force_single_line = True
+multi_line_output=3
+include_trailing_comma=True
+force_grid_wrap=0
+use_parentheses = True
lines_after_imports = 2
-line_length = 200
-not_skip = __init__.py
+line_length = 88
+not_skip =
+ __init__.py
+skip =
+
+[flake8]
+# black compatible flake8 rules:
+ignore =
+ W503,
+ C812,
+ E501
+ T001
+ C813
+# E203, E266
+exclude = bootstrap.py,docs,*.egg.,omelette
+max-line-length = 88
+max-complexity = 18
+select = B,C,E,F,W,T4,B9
+
+builtins = unicode,basestring
diff --git a/setup.py b/setup.py
index 35d1927..ccb17b3 100644
--- a/setup.py
+++ b/setup.py
@@ -1,57 +1,61 @@
# -*- coding: utf-8 -*-
"""Installer for the rer.externalnews package."""
-from setuptools import find_packages
-from setuptools import setup
+from setuptools import find_packages, setup
-long_description = '\n\n'.join([
- open('README.rst').read(),
- open('CONTRIBUTORS.rst').read(),
- open('CHANGES.rst').read(),
-])
+long_description = "\n\n".join(
+ [
+ open("README.rst").read(),
+ open("CONTRIBUTORS.rst").read(),
+ open("CHANGES.rst").read(),
+ ]
+)
setup(
- name='rer.externalnews',
- version='1.1.1.dev0',
+ name="rer.externalnews",
+ version="1.1.1.dev0",
description="A Plone add-on for Regione Emilia Romagna",
long_description=long_description,
# Get more from https://pypi.python.org/pypi?%3Aaction=list_classifiers
classifiers=[
+ "Development Status :: 5 - Production/Stable",
"Environment :: Web Environment",
"Framework :: Plone",
- "Framework :: Plone :: 5.0",
+ "Framework :: Plone :: 6.0",
"Programming Language :: Python",
- "Programming Language :: Python :: 2.7",
+ "Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.10",
"Operating System :: OS Independent",
"License :: OSI Approved :: GNU General Public License v2 (GPLv2)",
],
- keywords='Python Plone',
- author='RedTurtle Technology',
- author_email='sviluppoplone@redturtle.it',
- url='https://pypi.python.org/pypi/rer.externalnews',
- license='GPL version 2',
- packages=find_packages('src', exclude=['ez_setup']),
- namespace_packages=['rer'],
- package_dir={'': 'src'},
+ keywords="Python Plone",
+ author="RedTurtle Technology",
+ author_email="sviluppoplone@redturtle.it",
+ url="https://pypi.python.org/pypi/rer.externalnews",
+ license="GPL version 2",
+ packages=find_packages("src", exclude=["ez_setup"]),
+ namespace_packages=["rer"],
+ python_requires=">=3.8",
+ package_dir={"": "src"},
include_package_data=True,
zip_safe=False,
install_requires=[
- 'plone.api',
- 'Products.GenericSetup>=1.8.2',
- 'setuptools',
- 'plone.app.dexterity',
+ "plone.api",
+ "Products.GenericSetup>=1.8.2",
+ "setuptools",
+ "plone.app.dexterity",
],
extras_require={
- 'test': [
- 'plone.app.testing',
+ "test": [
+ "plone.app.testing",
# Plone KGS does not use this version, because it would break
# Remove if your package shall be part of coredev.
# plone_coredev tests as of 2016-04-01.
- 'plone.testing>=5.0.0',
- 'plone.app.contenttypes',
- 'plone.app.robotframework[debug]',
+ "plone.testing>=5.0.0",
+ "plone.app.contenttypes",
+ "plone.app.robotframework[debug]",
],
},
entry_points="""
diff --git a/src/rer/__init__.py b/src/rer/__init__.py
index 68c04af..03d08ff 100644
--- a/src/rer/__init__.py
+++ b/src/rer/__init__.py
@@ -1,2 +1,2 @@
# -*- coding: utf-8 -*-
-__import__('pkg_resources').declare_namespace(__name__)
+__import__("pkg_resources").declare_namespace(__name__)
diff --git a/src/rer/externalnews/__init__.py b/src/rer/externalnews/__init__.py
index 74a5038..6acc03e 100644
--- a/src/rer/externalnews/__init__.py
+++ b/src/rer/externalnews/__init__.py
@@ -3,4 +3,4 @@
from zope.i18nmessageid import MessageFactory
-_ = MessageFactory('rer.externalnews')
+_ = MessageFactory("rer.externalnews")
diff --git a/src/rer/externalnews/browser/configure.zcml b/src/rer/externalnews/browser/configure.zcml
index 84cff83..4ffe661 100644
--- a/src/rer/externalnews/browser/configure.zcml
+++ b/src/rer/externalnews/browser/configure.zcml
@@ -2,18 +2,19 @@
xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser"
xmlns:plone="http://namespaces.plone.org/plone"
- i18n_domain="rer.externalnews">
+ i18n_domain="rer.externalnews"
+ >
diff --git a/src/rer/externalnews/browser/externalnews_view.py b/src/rer/externalnews/browser/externalnews_view.py
index 0aa87ed..63f0b28 100644
--- a/src/rer/externalnews/browser/externalnews_view.py
+++ b/src/rer/externalnews/browser/externalnews_view.py
@@ -11,19 +11,20 @@
# links starting with these URL scheme should not be redirected to
NON_REDIRECTABLE_URL_SCHEMES = [
- 'mailto:',
- 'tel:',
- 'callto:', # nonstandard according to RFC 3966. used for skype.
- 'webdav:',
- 'caldav:'
+ "mailto:",
+ "tel:",
+ "callto:", # nonstandard according to RFC 3966. used for skype.
+ "webdav:",
+ "caldav:",
]
# links starting with these URL scheme should not be resolved to paths
NON_RESOLVABLE_URL_SCHEMES = NON_REDIRECTABLE_URL_SCHEMES + [
- 'file:',
- 'ftp:',
+ "file:",
+ "ftp:",
]
+
class ExternalNewsRedirectView(BrowserView):
"""Redirect to the Link target URL, if and only if:
- redirect_links property is enabled in
@@ -31,41 +32,38 @@ class ExternalNewsRedirectView(BrowserView):
- the link is of a redirectable type (no mailto:, etc)
- AND current user doesn't have permission to edit the Link"""
- index = ViewPageTemplateFile('templates/externalnews.pt')
+ index = ViewPageTemplateFile("templates/externalnews.pt")
def _url_uses_scheme(self, schemes, url=None):
url = url or self.context.externalUrl
for scheme in schemes:
if url.startswith(scheme):
- return True
+ return True
return False
-
def __call__(self):
context = self.context
- mtool = getToolByName(context, 'portal_membership')
+ mtool = getToolByName(context, "portal_membership")
registry = getUtility(IRegistry)
- settings = registry.forInterface(ITypesSchema, prefix='plone')
+ settings = registry.forInterface(ITypesSchema, prefix="plone")
redirect_links = settings.redirect_links
- can_edit = mtool.checkPermission('Modify portal content', context)
- redirect_links = redirect_links\
- and not self._url_uses_scheme(NON_REDIRECTABLE_URL_SCHEMES)
+ can_edit = mtool.checkPermission("Modify portal content", context)
+ redirect_links = redirect_links and not self._url_uses_scheme(
+ NON_REDIRECTABLE_URL_SCHEMES
+ )
if redirect_links and not can_edit:
return self.request.RESPONSE.redirect(
- self.absolute_target_url().encode('utf-8'))
+ self.absolute_target_url().encode("utf-8")
+ )
else:
return self.index()
def url(self):
- """Returns the url with link variables replaced.
- """
- url = replace_link_variables_by_paths(
- self.context,
- self.context.externalUrl
- )
+ """Returns the url with link variables replaced."""
+ url = replace_link_variables_by_paths(self.context, self.context.externalUrl)
return url
def absolute_target_url(self):
@@ -76,19 +74,14 @@ def absolute_target_url(self):
# For non http/https url schemes, there is no path to resolve.
return url
- if url.startswith('.'):
+ if url.startswith("."):
# we just need to adapt ../relative/links, /absolute/ones work
# anyway -> this requires relative links to start with ./ or
# ../
- context_state = self.context.restrictedTraverse(
- '@@plone_context_state'
- )
- url = '/'.join([
- context_state.canonical_object_url(),
- url
- ])
+ context_state = self.context.restrictedTraverse("@@plone_context_state")
+ url = "/".join([context_state.canonical_object_url(), url])
else:
- if not (url.startswith('http://') or url.startswith('https://')):
+ if not (url.startswith("http://") or url.startswith("https://")):
url = self.request.physicalPathToURL(url)
return url
diff --git a/src/rer/externalnews/browser/restapi/configure.zcml b/src/rer/externalnews/browser/restapi/configure.zcml
index 38ce5e3..6bcb6a0 100644
--- a/src/rer/externalnews/browser/restapi/configure.zcml
+++ b/src/rer/externalnews/browser/restapi/configure.zcml
@@ -1,6 +1,7 @@
+ i18n_domain="rer.externalnews"
+ >
diff --git a/src/rer/externalnews/browser/restapi/serializers/configure.zcml b/src/rer/externalnews/browser/restapi/serializers/configure.zcml
index 67d486e..6fa4c88 100644
--- a/src/rer/externalnews/browser/restapi/serializers/configure.zcml
+++ b/src/rer/externalnews/browser/restapi/serializers/configure.zcml
@@ -1,6 +1,7 @@
+ i18n_domain="rer.externalnews"
+ >
diff --git a/src/rer/externalnews/browser/restapi/serializers/externalnews.py b/src/rer/externalnews/browser/restapi/serializers/externalnews.py
index 1eb25ff..d0901f3 100644
--- a/src/rer/externalnews/browser/restapi/serializers/externalnews.py
+++ b/src/rer/externalnews/browser/restapi/serializers/externalnews.py
@@ -3,10 +3,8 @@
from plone.restapi.interfaces import ISerializeToJson
from plone.restapi.serializer.dxcontent import SerializeFolderToJson as Base
from rer.externalnews.interfaces import IExternalNews
-from zope.component import adapter
-from zope.component import getMultiAdapter
-from zope.interface import implementer
-from zope.interface import Interface
+from zope.component import adapter, getMultiAdapter
+from zope.interface import implementer, Interface
@implementer(ISerializeToJson)
@@ -16,7 +14,7 @@ def __call__(self, version=None, include_items=True):
res = super(SerializeToJson, self).__call__(version, include_items)
steps = self.get_steps()
res["steps"] = steps
- res['remoteUrl'] = res['externalUrl']
+ res["remoteUrl"] = res["externalUrl"]
return res
def get_steps(self):
diff --git a/src/rer/externalnews/configure.zcml b/src/rer/externalnews/configure.zcml
index 9d0367b..4377262 100644
--- a/src/rer/externalnews/configure.zcml
+++ b/src/rer/externalnews/configure.zcml
@@ -2,7 +2,8 @@
xmlns="http://namespaces.zope.org/zope"
xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
xmlns:i18n="http://namespaces.zope.org/i18n"
- i18n_domain="rer.externalnews">
+ i18n_domain="rer.externalnews"
+ >
@@ -12,23 +13,29 @@
+ name="rer.externalnews-hiddenprofiles"
+ />
+
+
diff --git a/src/rer/externalnews/indexers.py b/src/rer/externalnews/indexers.py
new file mode 100644
index 0000000..25ee514
--- /dev/null
+++ b/src/rer/externalnews/indexers.py
@@ -0,0 +1,8 @@
+# -*- coding: utf-8 -*-
+from plone.indexer.decorator import indexer
+from rer.externalnews.interfaces import IExternalNews
+
+
+@indexer(IExternalNews)
+def getRemoteUrl(obj):
+ return getattr(obj, "externalUrl", "")
diff --git a/src/rer/externalnews/interfaces.py b/src/rer/externalnews/interfaces.py
index f9a7d60..2d70355 100644
--- a/src/rer/externalnews/interfaces.py
+++ b/src/rer/externalnews/interfaces.py
@@ -12,22 +12,23 @@ class IRerExternalnewsLayer(IDefaultBrowserLayer):
class IExternalNews(Interface):
- """ Interfaccia per il content type: External News"""
+ """Interfaccia per il content type: External News"""
externalUrl = schema.TextLine(
- title=_(u'rer_externalnews_externalurl', default=u'External url'),
+ title=_("rer_externalnews_externalurl", default="External url"),
description=_(
- u'rer_ernews_externalurl_help',
- default=u'Insert a valid link to an external resource'),
- default=u'',
+ "rer_ernews_externalurl_help",
+ default="Insert a valid link to an external resource",
+ ),
+ default="",
required=True,
)
externalSource = schema.TextLine(
- title=_(u'rer_externalnews_externalsource', default=u'Source'),
+ title=_("rer_externalnews_externalsource", default="Source"),
description=_(
- u'rer_externalnews_externalsource_help',
- default=u"Where the URL is from."),
- default=u'',
+ "rer_externalnews_externalsource_help", default="Where the URL is from."
+ ),
+ default="",
required=False,
)
diff --git a/src/rer/externalnews/profiles/default/metadata.xml b/src/rer/externalnews/profiles/default/metadata.xml
index c68c27d..749280d 100644
--- a/src/rer/externalnews/profiles/default/metadata.xml
+++ b/src/rer/externalnews/profiles/default/metadata.xml
@@ -1,6 +1,6 @@
- 1100
+ 1200
profile-plone.app.dexterity:default
diff --git a/src/rer/externalnews/setuphandlers.py b/src/rer/externalnews/setuphandlers.py
index d9f7842..669c712 100644
--- a/src/rer/externalnews/setuphandlers.py
+++ b/src/rer/externalnews/setuphandlers.py
@@ -5,11 +5,10 @@
@implementer(INonInstallable)
class HiddenProfiles(object):
-
def getNonInstallableProfiles(self):
"""Hide uninstall profile from site-creation and quickinstaller"""
return [
- 'rer.externalnews:uninstall',
+ "rer.externalnews:uninstall",
]
diff --git a/src/rer/externalnews/testing.py b/src/rer/externalnews/testing.py
index 01e1aa0..f81b9e1 100644
--- a/src/rer/externalnews/testing.py
+++ b/src/rer/externalnews/testing.py
@@ -1,17 +1,18 @@
# -*- coding: utf-8 -*-
from plone.app.contenttypes.testing import PLONE_APP_CONTENTTYPES_FIXTURE
from plone.app.robotframework.testing import REMOTE_LIBRARY_BUNDLE_FIXTURE
-from plone.app.testing import applyProfile
-from plone.app.testing import FunctionalTesting
-from plone.app.testing import IntegrationTesting
-from plone.app.testing import PloneSandboxLayer
+from plone.app.testing import (
+ applyProfile,
+ FunctionalTesting,
+ IntegrationTesting,
+ PloneSandboxLayer,
+)
from plone.testing import z2
import rer.externalnews
class RerExternalnewsLayer(PloneSandboxLayer):
-
defaultBases = (PLONE_APP_CONTENTTYPES_FIXTURE,)
def setUpZope(self, app, configurationContext):
@@ -21,29 +22,23 @@ def setUpZope(self, app, configurationContext):
self.loadZCML(package=rer.externalnews)
def setUpPloneSite(self, portal):
- applyProfile(portal, 'rer.externalnews:default')
+ applyProfile(portal, "rer.externalnews:default")
RER_EXTERNALNEWS_FIXTURE = RerExternalnewsLayer()
RER_EXTERNALNEWS_INTEGRATION_TESTING = IntegrationTesting(
- bases=(RER_EXTERNALNEWS_FIXTURE,),
- name='RerExternalnewsLayer:IntegrationTesting'
+ bases=(RER_EXTERNALNEWS_FIXTURE,), name="RerExternalnewsLayer:IntegrationTesting"
)
RER_EXTERNALNEWS_FUNCTIONAL_TESTING = FunctionalTesting(
- bases=(RER_EXTERNALNEWS_FIXTURE,),
- name='RerExternalnewsLayer:FunctionalTesting'
+ bases=(RER_EXTERNALNEWS_FIXTURE,), name="RerExternalnewsLayer:FunctionalTesting"
)
RER_EXTERNALNEWS_ACCEPTANCE_TESTING = FunctionalTesting(
- bases=(
- RER_EXTERNALNEWS_FIXTURE,
- REMOTE_LIBRARY_BUNDLE_FIXTURE,
- z2.ZSERVER_FIXTURE
- ),
- name='RerExternalnewsLayer:AcceptanceTesting'
+ bases=(RER_EXTERNALNEWS_FIXTURE, REMOTE_LIBRARY_BUNDLE_FIXTURE, z2.ZSERVER_FIXTURE),
+ name="RerExternalnewsLayer:AcceptanceTesting",
)
diff --git a/src/rer/externalnews/tests/robot/test_example.robot b/src/rer/externalnews/tests/robot/test_example.robot
deleted file mode 100644
index cc36da1..0000000
--- a/src/rer/externalnews/tests/robot/test_example.robot
+++ /dev/null
@@ -1,66 +0,0 @@
-# ============================================================================
-# EXAMPLE ROBOT TESTS
-# ============================================================================
-#
-# Run this robot test stand-alone:
-#
-# $ bin/test -s rer.externalnews -t test_example.robot --all
-#
-# Run this robot test with robot server (which is faster):
-#
-# 1) Start robot server:
-#
-# $ bin/robot-server --reload-path src rer.externalnews.testing.RER_EXTERNALNEWS_ACCEPTANCE_TESTING
-#
-# 2) Run robot tests:
-#
-# $ bin/robot src/rer/externalnews/tests/robot/test_example.robot
-#
-# See the http://docs.plone.org for further details (search for robot
-# framework).
-#
-# ============================================================================
-
-*** Settings *****************************************************************
-
-Resource plone/app/robotframework/selenium.robot
-Resource plone/app/robotframework/keywords.robot
-
-Library Remote ${PLONE_URL}/RobotRemote
-
-Test Setup Open test browser
-Test Teardown Close all browsers
-
-
-*** Test Cases ***************************************************************
-
-Scenario: As a member I want to be able to log into the website
- [Documentation] Example of a BDD-style (Behavior-driven development) test.
- Given a login form
- When I enter valid credentials
- Then I am logged in
-
-
-*** Keywords *****************************************************************
-
-# --- Given ------------------------------------------------------------------
-
-a login form
- Go To ${PLONE_URL}/login_form
- Wait until page contains Login Name
- Wait until page contains Password
-
-
-# --- WHEN -------------------------------------------------------------------
-
-I enter valid credentials
- Input Text __ac_name admin
- Input Text __ac_password secret
- Click Button Log in
-
-
-# --- THEN -------------------------------------------------------------------
-
-I am logged in
- Wait until page contains You are now logged in
- Page should contain You are now logged in
diff --git a/src/rer/externalnews/tests/robot/test_externalnews.robot b/src/rer/externalnews/tests/robot/test_externalnews.robot
deleted file mode 100644
index fdac326..0000000
--- a/src/rer/externalnews/tests/robot/test_externalnews.robot
+++ /dev/null
@@ -1,87 +0,0 @@
-# ============================================================================
-# DEXTERITY ROBOT TESTS
-# ============================================================================
-#
-# Run this robot test stand-alone:
-#
-# $ bin/test -s rer.externalnews -t test_externalnews.robot --all
-#
-# Run this robot test with robot server (which is faster):
-#
-# 1) Start robot server:
-#
-# $ bin/robot-server --reload-path src rer.externalnews.testing.RER_EXTERNALNEWS_ACCEPTANCE_TESTING
-#
-# 2) Run robot tests:
-#
-# $ bin/robot src/plonetraining/testing/tests/robot/test_externalnews.robot
-#
-# See the http://docs.plone.org for further details (search for robot
-# framework).
-#
-# ============================================================================
-
-*** Settings *****************************************************************
-
-Resource plone/app/robotframework/selenium.robot
-Resource plone/app/robotframework/keywords.robot
-
-Library Remote ${PLONE_URL}/RobotRemote
-
-Test Setup Open test browser
-Test Teardown Close all browsers
-
-
-*** Test Cases ***************************************************************
-
-Scenario: As a site administrator I can add a ExternalNews
- Given a logged-in site administrator
- and an add externalnews form
- When I type 'My ExternalNews' into the title field
- and I submit the form
- Then a externalnews with the title 'My ExternalNews' has been created
-
-Scenario: As a site administrator I can view a ExternalNews
- Given a logged-in site administrator
- and a externalnews 'My ExternalNews'
- When I go to the externalnews view
- Then I can see the externalnews title 'My ExternalNews'
-
-
-*** Keywords *****************************************************************
-
-# --- Given ------------------------------------------------------------------
-
-a logged-in site administrator
- Enable autologin as Site Administrator
-
-an add externalnews form
- Go To ${PLONE_URL}/++add++ExternalNews
-
-a externalnews 'My ExternalNews'
- Create content type=ExternalNews id=my-externalnews title=My ExternalNews
-
-
-# --- WHEN -------------------------------------------------------------------
-
-I type '${title}' into the title field
- Input Text name=form.widgets.title ${title}
-
-I submit the form
- Click Button Save
-
-I go to the externalnews view
- Go To ${PLONE_URL}/my-externalnews
- Wait until page contains Site Map
-
-
-# --- THEN -------------------------------------------------------------------
-
-a externalnews with the title '${title}' has been created
- Wait until page contains Site Map
- Page should contain ${title}
- Page should contain Item created
-
-I can see the externalnews title '${title}'
- Wait until page contains Site Map
- Page should contain ${title}
diff --git a/src/rer/externalnews/tests/test_externalnews.py b/src/rer/externalnews/tests/test_externalnews.py
index 8a77173..26b0fd1 100644
--- a/src/rer/externalnews/tests/test_externalnews.py
+++ b/src/rer/externalnews/tests/test_externalnews.py
@@ -1,45 +1,26 @@
# -*- coding: utf-8 -*-
from plone import api
-from plone.app.testing import setRoles
-from plone.app.testing import TEST_USER_ID
-from plone.dexterity.interfaces import IDexterityFTI
-from rer.externalnews.interfaces import IExternalNews
-from rer.externalnews.testing import RER_EXTERNALNEWS_INTEGRATION_TESTING # noqa
-from zope.component import createObject
-from zope.component import queryUtility
+from plone.app.testing import setRoles, TEST_USER_ID
+from rer.externalnews.testing import RER_EXTERNALNEWS_INTEGRATION_TESTING
import unittest
class ExternalNewsIntegrationTest(unittest.TestCase):
-
layer = RER_EXTERNALNEWS_INTEGRATION_TESTING
def setUp(self):
"""Custom shared utility setup for tests."""
- self.portal = self.layer['portal']
- setRoles(self.portal, TEST_USER_ID, ['Manager'])
- self.installer = api.portal.get_tool('portal_quickinstaller')
-
- def test_schema(self):
- fti = queryUtility(IDexterityFTI, name='ExternalNews')
- schema = fti.lookupSchema()
- self.assertEqual(IExternalNews, schema)
-
- def test_fti(self):
- fti = queryUtility(IDexterityFTI, name='ExternalNews')
- self.assertTrue(fti)
+ self.portal = self.layer["portal"]
+ setRoles(self.portal, TEST_USER_ID, ["Manager"])
- def test_factory(self):
- fti = queryUtility(IDexterityFTI, name='ExternalNews')
- factory = fti.factory
- obj = createObject(factory)
- self.assertTrue(IExternalNews.providedBy(obj))
-
- def test_adding(self):
- obj = api.content.create(
+ def test_getRemoteUrl_metadata_set(self):
+ news = api.content.create(
container=self.portal,
- type='ExternalNews',
- id='ExternalNews',
+ type="ExternalNews",
+ id="ExternalNews",
+ externalUrl="http://www.plone.org",
)
- self.assertTrue(IExternalNews.providedBy(obj))
+
+ res = api.content.find(UID=news.UID())[0]
+ self.assertEqual(res.getRemoteUrl, news.externalUrl)
diff --git a/src/rer/externalnews/tests/test_robot.py b/src/rer/externalnews/tests/test_robot.py
deleted file mode 100644
index 6e1f07b..0000000
--- a/src/rer/externalnews/tests/test_robot.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# -*- coding: utf-8 -*-
-from plone.app.testing import ROBOT_TEST_LEVEL
-from plone.testing import layered
-from rer.externalnews.testing import RER_EXTERNALNEWS_ACCEPTANCE_TESTING # noqa
-
-import os
-import robotsuite
-import unittest
-
-
-def test_suite():
- suite = unittest.TestSuite()
- current_dir = os.path.abspath(os.path.dirname(__file__))
- robot_dir = os.path.join(current_dir, 'robot')
- robot_tests = [
- os.path.join('robot', doc) for doc in os.listdir(robot_dir)
- if doc.endswith('.robot') and doc.startswith('test_')
- ]
- for robot_test in robot_tests:
- robottestsuite = robotsuite.RobotTestSuite(robot_test)
- robottestsuite.level = ROBOT_TEST_LEVEL
- suite.addTests([
- layered(
- robottestsuite,
- layer=RER_EXTERNALNEWS_ACCEPTANCE_TESTING
- ),
- ])
- return suite
diff --git a/src/rer/externalnews/tests/test_setup.py b/src/rer/externalnews/tests/test_setup.py
deleted file mode 100644
index 4162ea3..0000000
--- a/src/rer/externalnews/tests/test_setup.py
+++ /dev/null
@@ -1,67 +0,0 @@
-# -*- coding: utf-8 -*-
-"""Setup tests for this package."""
-from plone import api
-from rer.externalnews.testing import RER_EXTERNALNEWS_INTEGRATION_TESTING # noqa
-
-import unittest
-
-
-try:
- from Products.CMFPlone.utils import get_installer
-except ImportError:
- get_installer = None
-
-
-class TestSetup(unittest.TestCase):
- """Test that rer.externalnews is properly installed."""
-
- layer = RER_EXTERNALNEWS_INTEGRATION_TESTING
-
- def setUp(self):
- """Custom shared utility setup for tests."""
- self.portal = self.layer['portal']
- if get_installer:
- self.installer = get_installer(self.portal, self.layer['request'])
- else:
- self.installer = api.portal.get_tool('portal_quickinstaller')
-
- def test_product_installed(self):
- """Test if rer.externalnews is installed."""
- self.assertTrue(self.installer.isProductInstalled(
- 'rer.externalnews'))
-
- def test_browserlayer(self):
- """Test that IRerExternalnewsLayer is registered."""
- from rer.externalnews.interfaces import (
- IRerExternalnewsLayer)
- from plone.browserlayer import utils
- self.assertIn(
- IRerExternalnewsLayer,
- utils.registered_layers())
-
-
-class TestUninstall(unittest.TestCase):
-
- layer = RER_EXTERNALNEWS_INTEGRATION_TESTING
-
- def setUp(self):
- self.portal = self.layer['portal']
- if get_installer:
- self.installer = get_installer(self.portal, self.layer['request'])
- else:
- self.installer = api.portal.get_tool('portal_quickinstaller')
- self.installer.uninstallProducts(['rer.externalnews'])
-
- def test_product_uninstalled(self):
- """Test if rer.externalnews is cleanly uninstalled."""
- self.assertFalse(self.installer.isProductInstalled(
- 'rer.externalnews'))
-
- def test_browserlayer_removed(self):
- """Test that IRerExternalnewsLayer is removed."""
- from rer.externalnews.interfaces import \
- IRerExternalnewsLayer
- from plone.browserlayer import utils
- self.assertNotIn(
- IRerExternalnewsLayer,
- utils.registered_layers())
diff --git a/src/rer/externalnews/upgrades/configure.zcml b/src/rer/externalnews/upgrades/configure.zcml
index 06c680a..3e14f43 100644
--- a/src/rer/externalnews/upgrades/configure.zcml
+++ b/src/rer/externalnews/upgrades/configure.zcml
@@ -1,15 +1,24 @@
+ i18n_domain="rer.externalnews"
+ >
+ title="Upgrade rer.externalnews to 1100"
+ description="Migrates rer.externalnews to 1100"
+ profile="rer.externalnews:default"
+ source="1000"
+ destination="1100"
+ handler=".upgrades.to_1100"
+ sortkey="1"
+ />
+
diff --git a/src/rer/externalnews/upgrades/upgrades.py b/src/rer/externalnews/upgrades/upgrades.py
index a8e16ab..c18f4ed 100644
--- a/src/rer/externalnews/upgrades/upgrades.py
+++ b/src/rer/externalnews/upgrades/upgrades.py
@@ -1,20 +1,33 @@
# -*- coding: utf-8 -*-
+from plone import api
+
import logging
logger = logging.getLogger(__name__)
-default_profile = 'profile-rer.externalnews:default'
+default_profile = "profile-rer.externalnews:default"
def to_1100(context):
- """
- """
- logger.info('Upgrading rer.externalnews to version 1100')
- context.runImportStepFromProfile(default_profile, 'repositorytool')
- context.runImportStepFromProfile(default_profile, 'difftool')
- context.runImportStepFromProfile(
- default_profile,
- 'typeinfo',
- run_dependencies=True)
+ """ """
+ logger.info("Upgrading rer.externalnews to version 1100")
+ context.runImportStepFromProfile(default_profile, "repositorytool")
+ context.runImportStepFromProfile(default_profile, "difftool")
+ context.runImportStepFromProfile(default_profile, "typeinfo", run_dependencies=True)
+
+
+def to_1200(context):
+ """ """
+ logger.info("Upgrading rer.externalnews to version 1200")
+ brains = api.content.find(portal_type="ExternalNews")
+ tot = len(brains)
+ i = 0
+ for brain in brains:
+ i += 1
+ if i % 100 == 0:
+ logger.info(f"Progress: {i}/{tot}")
+
+ news = brain.getObject()
+ news.reindexObject(idxs=["getRemoteUrl"])
diff --git a/test_plone52.cfg b/test_plone52.cfg
index 0c2bca4..146d479 100644
--- a/test_plone52.cfg
+++ b/test_plone52.cfg
@@ -7,50 +7,27 @@ extends =
update-versions-file = test_plone52.cfg
-sources-dir = extras
-auto-checkout = *
-always-checkout = force
-
[versions]
+# https://raw.githubusercontent.com/RedTurtle/dist.design.plone/main/versions.cfg
+plone.app.iterate = 4.0.2
+plone.app.versioningbehavior = 1.4.6
+plone.app.vocabularies = 4.3.0
+plone.patternslib = 1.1.1
+plone.rest = 2.0.0
+plone.restapi = >=9.6.0
+plone.volto = 4.0.0
+pycountry = 19.8.18
+collective.purgebyid = 1.1.1
+Products.AdvancedQuery = 4.2.1
+dm.plone.advancedquery = 1.0
+# plone.app.caching > 3.0.0a13 requires plone.base
+plone.app.caching = 3.0.0a13
+
+# testing
plone.testing = 7.0.1
-
-# Added by buildout at 2019-04-14 16:01:26.533376
-PyYAML = 3.13
-argh = 0.26.2
-createcoverage = 1.5
-flake8-blind-except = 0.1.1
-flake8-coding = 1.3.1
-flake8-commas = 2.0.0
-flake8-debugger = 3.1.0
-flake8-deprecated = 1.3
-flake8-isort = 2.6.0
-flake8-pep3101 = 1.2.1
-flake8-plone-api = 1.4
-flake8-plone-hasattr = 0.2.post0
-flake8-print = 3.1.0
-flake8-quotes = 1.0.0
-flake8-string-format = 0.2.3
-flake8-todo = 0.7
-isort = 4.3.10
-mccabe = 0.6.1
-pathtools = 0.1.2
-plone.recipe.codeanalysis = 3.0.1
-prompt-toolkit = 1.0.15
-watchdog = 0.9.0
-
-# Required by:
-# plone.recipe.codeanalysis==3.0.1
-check-manifest = 0.37
-
-# Required by:
-# flake8-isort==2.6.0
-testfixtures = 6.6.0
-
-# Required by:
-# prompt-toolkit==1.0.15
-wcwidth = 0.1.7
-
-# Added by buildout at 2021-08-24 11:11:01.831732
flake8 = 3.9.2
pycodestyle = 2.7.0
pyflakes = 2.3.1
+createcoverage = 1.5
+mccabe = 0.6.1
+plone.recipe.codeanalysis = 3.0.1
diff --git a/test_plone60.cfg b/test_plone60.cfg
new file mode 100644
index 0000000..241cc1e
--- /dev/null
+++ b/test_plone60.cfg
@@ -0,0 +1,20 @@
+[buildout]
+
+extends =
+ https://raw.github.com/collective/buildout.plonetest/master/test-6.0.x.cfg
+ https://raw.githubusercontent.com/collective/buildout.plonetest/master/qa.cfg
+ base.cfg
+
+[versions]
+
+# Added by buildout at 2023-03-10 11:55:21.122842
+Products.AdvancedQuery = 4.2.1
+createcoverage = 1.5
+dm.plone.advancedquery = 1.0
+flake8 = 6.0.0
+mccabe = 0.7.0
+plone.recipe.codeanalysis = 3.0.1
+pycodestyle = 2.10.0
+pyflakes = 3.0.1
+plone.stringinterp = 2.0.0
+plone.restapi = >=9.6.0