diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 417be10..0000000 --- a/.coveragerc +++ /dev/null @@ -1,8 +0,0 @@ -[run] -branch = True -source = $COVERAGE_HOME/src/plone/recipe/zeoserver -parallel = true -data_file = $COVERAGE_HOME/.coverage - -[report] -precision = 2 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/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..5f29c12 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,51 @@ +name: Windows and MacOS + +on: + push: + branches: + - master + pull_request: + branches: + - master + workflow_dispatch: + +jobs: + build: + strategy: + # We want to see all failures: + fail-fast: false + matrix: + os: + - ["windows", "windows-latest"] + - ["macos", "macos-11"] + config: + # [Python version, tox env] + - ["3.9", "test"] + + runs-on: ${{ matrix.os[1] }} + name: ${{ matrix.os[0] }}-${{ matrix.config[1] }} + steps: + - uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.config[0] }} + + - name: Pip cache + uses: actions/cache@v3 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ matrix.config[0] }}-${{ hashFiles('setup.*', 'tox.ini') }} + restore-keys: | + ${{ runner.os }}-pip-${{ matrix.config[0] }}- + ${{ runner.os }}-pip- + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install tox + + - name: Test + run: | + tox -e ${{ matrix.config[1] }} diff --git a/.meta.toml b/.meta.toml new file mode 100644 index 0000000..99342b2 --- /dev/null +++ b/.meta.toml @@ -0,0 +1,5 @@ +# Generated from: +# https://github.com/plone/meta/tree/master/config/default +[meta] +template = "default" +commit-id = "2a4ba395" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..fdafec1 --- /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.3.0 + hooks: + - id: black +- repo: https://github.com/collective/zpretty + rev: 3.0.3 + 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.4 + 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/.travis.yml b/.travis.yml deleted file mode 100644 index 2ad0449..0000000 --- a/.travis.yml +++ /dev/null @@ -1,23 +0,0 @@ -language: python -dist: xenial -python: - - 2.7 - - 3.6 - - 3.7 - - 3.8 -before_install: - - pip install -U setuptools pip - - pip install -U coverage coveralls zope.testrunner -install: - - pip install -U -e .[zrs] -script: - - export COVERAGE_HOME=$(pwd) - - export COVERAGE_PROCESS_START=$COVERAGE_HOME/.coveragerc - - coverage run -m zope.testrunner --test-path=src --all -v1 -notifications: - email: false -after_success: - - coverage combine - - coveralls -cache: - pip: true diff --git a/README.rst b/README.rst index cdda1f7..ddf8222 100644 --- a/README.rst +++ b/README.rst @@ -239,6 +239,13 @@ zeopack "#" is the number of days to keep. +Version Information +------------------- + +- 3.x -> Plone 6, Zope 5, Python 3.8+ +- 2.x -> Plone 5, Zope 4, Python 2.7 + + Reporting bugs or asking questions ---------------------------------- diff --git a/bootstrap.py b/bootstrap.py deleted file mode 100644 index a629566..0000000 --- a/bootstrap.py +++ /dev/null @@ -1,189 +0,0 @@ -############################################################################## -# -# Copyright (c) 2006 Zope Foundation and Contributors. -# All Rights Reserved. -# -# This software is subject to the provisions of the Zope Public License, -# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. -# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED -# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS -# FOR A PARTICULAR PURPOSE. -# -############################################################################## -"""Bootstrap a buildout-based project - -Simply run this script in a directory containing a buildout.cfg. -The script accepts buildout command-line options, so you can -use the -c option to specify an alternate configuration file. -""" - -import os -import shutil -import sys -import tempfile - -from optparse import OptionParser - -tmpeggs = tempfile.mkdtemp() - -usage = '''\ -[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options] - -Bootstraps a buildout-based project. - -Simply run this script in a directory containing a buildout.cfg, using the -Python that you want bin/buildout to use. - -Note that by using --find-links to point to local resources, you can keep -this script from going over the network. -''' - -parser = OptionParser(usage=usage) -parser.add_option("-v", "--version", help="use a specific zc.buildout version") - -parser.add_option("-t", "--accept-buildout-test-releases", - dest='accept_buildout_test_releases', - action="store_true", default=False, - help=("Normally, if you do not specify a --version, the " - "bootstrap script and buildout gets the newest " - "*final* versions of zc.buildout and its recipes and " - "extensions for you. If you use this flag, " - "bootstrap and buildout will get the newest releases " - "even if they are alphas or betas.")) -parser.add_option("-c", "--config-file", - help=("Specify the path to the buildout configuration " - "file to be used.")) -parser.add_option("-f", "--find-links", - help=("Specify a URL to search for buildout releases")) -parser.add_option("--allow-site-packages", - action="store_true", default=False, - help=("Let bootstrap.py use existing site packages")) -parser.add_option("--setuptools-version", - help="use a specific setuptools version") - - -options, args = parser.parse_args() - -###################################################################### -# load/install setuptools - -try: - if options.allow_site_packages: - import setuptools - import pkg_resources - from urllib.request import urlopen -except ImportError: - from urllib2 import urlopen - -ez = {} -exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez) - -if not options.allow_site_packages: - # ez_setup imports site, which adds site packages - # this will remove them from the path to ensure that incompatible versions - # of setuptools are not in the path - import site - # inside a virtualenv, there is no 'getsitepackages'. - # We can't remove these reliably - if hasattr(site, 'getsitepackages'): - for sitepackage_path in site.getsitepackages(): - sys.path[:] = [x for x in sys.path if sitepackage_path not in x] - -setup_args = dict(to_dir=tmpeggs, download_delay=0) - -if options.setuptools_version is not None: - setup_args['version'] = options.setuptools_version - -ez['use_setuptools'](**setup_args) -import setuptools -import pkg_resources - -# This does not (always?) update the default working set. We will -# do it. -for path in sys.path: - if path not in pkg_resources.working_set.entries: - pkg_resources.working_set.add_entry(path) - -###################################################################### -# Install buildout - -ws = pkg_resources.working_set - -cmd = [sys.executable, '-c', - 'from setuptools.command.easy_install import main; main()', - '-mZqNxd', tmpeggs] - -find_links = os.environ.get( - 'bootstrap-testing-find-links', - options.find_links or - ('http://downloads.buildout.org/' - if options.accept_buildout_test_releases else None) - ) -if find_links: - cmd.extend(['-f', find_links]) - -setuptools_path = ws.find( - pkg_resources.Requirement.parse('setuptools')).location - -requirement = 'zc.buildout' -version = options.version -if version is None and not options.accept_buildout_test_releases: - # Figure out the most recent final version of zc.buildout. - import setuptools.package_index - _final_parts = '*final-', '*final' - - def _final_version(parsed_version): - try: - return not parsed_version.is_prerelease - except AttributeError: - # Older setuptools - for part in parsed_version: - if (part[:1] == '*') and (part not in _final_parts): - return False - return True - - index = setuptools.package_index.PackageIndex( - search_path=[setuptools_path]) - if find_links: - index.add_find_links((find_links,)) - req = pkg_resources.Requirement.parse(requirement) - if index.obtain(req) is not None: - best = [] - bestv = None - for dist in index[req.project_name]: - distv = dist.parsed_version - if _final_version(distv): - if bestv is None or distv > bestv: - best = [dist] - bestv = distv - elif distv == bestv: - best.append(dist) - if best: - best.sort() - version = best[-1].version -if version: - requirement = '=='.join((requirement, version)) -cmd.append(requirement) - -import subprocess -if subprocess.call(cmd, env=dict(os.environ, PYTHONPATH=setuptools_path)) != 0: - raise Exception( - "Failed to execute command:\n%s" % repr(cmd)[1:-1]) - -###################################################################### -# Import and run buildout - -ws.add_entry(tmpeggs) -ws.require(requirement) -import zc.buildout.buildout - -if not [a for a in args if '=' not in a]: - args.append('bootstrap') - -# if -c was provided, we push it back into args for buildout' main function -if options.config_file is not None: - args[0:0] = ['-c', options.config_file] - -zc.buildout.buildout.main(args) -shutil.rmtree(tmpeggs) diff --git a/buildout.cfg b/buildout.cfg deleted file mode 100644 index 9890e2b..0000000 --- a/buildout.cfg +++ /dev/null @@ -1,11 +0,0 @@ -[buildout] -develop = . -parts = test zeo - -[test] -recipe = zc.recipe.testrunner -eggs = - plone.recipe.zeoserver[zrs] - -[zeo] -recipe = plone.recipe.zeoserver diff --git a/news/45.bugfix b/news/45.bugfix new file mode 100644 index 0000000..b1e692a --- /dev/null +++ b/news/45.bugfix @@ -0,0 +1,3 @@ +- Fix lost dependencies when defining additional `eggs` in buildout part. +- Update Codebase to python 3.8+ +[petschki] diff --git a/pyproject.toml b/pyproject.toml index 05b615d..639f77a 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,65 @@ 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.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'] diff --git a/setup.cfg b/setup.cfg index faceec3..0da8f8f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,8 +1,23 @@ -[check-manifest] +# Generated from: +# https://github.com/plone/meta/tree/master/config/default +[bdist_wheel] +universal = 0 + +[flake8] +doctests = 1 ignore = - *.cfg - .coveragerc - bootstrap.py + # 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, -[bdist_wheel] -universal = 1 +[check-manifest] +ignore = + .editorconfig + .meta.toml + .pre-commit-config.yaml + tox.ini diff --git a/setup.py b/setup.py index b267cbc..a8a8def 100644 --- a/setup.py +++ b/setup.py @@ -1,70 +1,54 @@ -# -*- coding: utf-8 -*- from setuptools import find_packages from setuptools import setup -import sys - -version = '2.0.4.dev0' - -additional_install_requires = [] - -if sys.platform[:3].lower() == 'win': - additional_install_requires += ['nt_svcutils'] +version = "3.0.0.dev0" setup( name="plone.recipe.zeoserver", version=version, - author='Hanno Schlichting', - author_email='hannosch@plone.org', - description='ZC Buildout recipe for installing a ZEO server', - long_description=( - open('README.rst').read() + - '\n' + - open('CHANGES.rst').read() - ), - license='ZPL 2.1', - keywords='zope2 zeo zodb buildout', - url='https://github.com/plone/plone.recipe.zeoserver', - download_url='https://pypi.org/project/plone.recipe.zeoserver', + author="Hanno Schlichting", + author_email="hannosch@plone.org", + description="ZC Buildout recipe for installing a ZEO server", + long_description=(open("README.rst").read() + "\n" + open("CHANGES.rst").read()), + license="ZPL 2.1", + keywords="zope2 zeo zodb buildout", + url="https://github.com/plone/plone.recipe.zeoserver", + download_url="https://pypi.org/project/plone.recipe.zeoserver", classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'License :: OSI Approved :: Zope Public License', - 'Framework :: Buildout', - 'Framework :: Plone', - 'Framework :: Plone :: 5.1', - 'Framework :: Plone :: 5.2', - 'Framework :: Plone :: Core', - 'Framework :: Zope', - 'Framework :: Zope :: 4', - 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: Implementation', - 'Programming Language :: Python :: Implementation :: CPython', + "Development Status :: 5 - Production/Stable", + "License :: OSI Approved :: Zope Public License", + "Framework :: Buildout", + "Framework :: Plone", + "Framework :: Plone :: 6.0", + "Framework :: Zope", + "Framework :: Zope :: 5", + "Programming Language :: Python", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: Implementation", + "Programming Language :: Python :: Implementation :: CPython", ], - packages=find_packages('src'), + python_requires=">=3.8", + packages=find_packages("src"), include_package_data=True, - package_dir={'': 'src'}, - namespace_packages=['plone', 'plone.recipe'], + package_dir={"": "src"}, + namespace_packages=["plone", "plone.recipe"], install_requires=[ - 'setuptools', - 'zc.buildout', - 'zc.recipe.egg', - 'ZODB >= 5', - 'zope.mkzeoinstance >=4.1', - 'ZopeUndo', - ] + additional_install_requires, - extras_require={ - 'zrs': ['zc.zrs'] - }, + "setuptools", + "zc.buildout", + "zc.recipe.egg", + "ZEO", + "ZODB >= 5", + "zope.mkzeoinstance >=4.1", + "ZopeUndo", + ], + extras_require={"zrs": ["zc.zrs"]}, zip_safe=False, entry_points={ - 'zc.buildout': ['default = plone.recipe.zeoserver.recipe:Recipe'], + "zc.buildout": ["default = plone.recipe.zeoserver.recipe:Recipe"], }, ) diff --git a/src/plone/__init__.py b/src/plone/__init__.py index 85880ef..05f0beb 100644 --- a/src/plone/__init__.py +++ b/src/plone/__init__.py @@ -1,7 +1,7 @@ -# -*- coding: utf-8 -*- # See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages try: - __import__('pkg_resources').declare_namespace(__name__) + __import__("pkg_resources").declare_namespace(__name__) except ImportError: from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) diff --git a/src/plone/recipe/__init__.py b/src/plone/recipe/__init__.py index 85880ef..05f0beb 100644 --- a/src/plone/recipe/__init__.py +++ b/src/plone/recipe/__init__.py @@ -1,7 +1,7 @@ -# -*- coding: utf-8 -*- # See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages try: - __import__('pkg_resources').declare_namespace(__name__) + __import__("pkg_resources").declare_namespace(__name__) except ImportError: from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) diff --git a/src/plone/recipe/zeoserver/ctl.py b/src/plone/recipe/zeoserver/ctl.py index 638c9b6..4430245 100644 --- a/src/plone/recipe/zeoserver/ctl.py +++ b/src/plone/recipe/zeoserver/ctl.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """zeocltl -- control a ZEO server using zdaemon. Usage: zeocltl [options] [action [arguments]] @@ -10,7 +9,6 @@ no action is specified on the command line, a "shell" interpreting actions typed interactively is started. Use the action "help" to find out about available actions. """ -from __future__ import print_function from ZEO import runzeo from ZEO import zeoctl @@ -20,16 +18,16 @@ if sys.platform[:3].lower() == "win": - print('For win32 platforms, runzeo.bat or zeoservice.exe should be used') - print('%s is based on zdaemon, which is Linux specific' % sys.argv[0]) - print('Aborting...') + print("For win32 platforms, runzeo.bat or zeoservice.exe should be used") + print("%s is based on zdaemon, which is Linux specific" % sys.argv[0]) + print("Aborting...") sys.exit(0) def main(args=None): # When we detect Supervisord we need to make sure we do not fork a # sub process since Supervisord does not like that - if 'SUPERVISOR_ENABLED' in os.environ: + if "SUPERVISOR_ENABLED" in os.environ: # We will ignore any command sent and always start in foreground mode args = args[:2] runzeo.main(args) diff --git a/src/plone/recipe/zeoserver/pack.py b/src/plone/recipe/zeoserver/pack.py index 4098112..218efbe 100644 --- a/src/plone/recipe/zeoserver/pack.py +++ b/src/plone/recipe/zeoserver/pack.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from ZEO.ClientStorage import ClientStorage from ZEO.Exceptions import ClientDisconnected @@ -9,8 +8,18 @@ import time -def _main(host, port, unix=None, days=1, username=None, password=None, - realm=None, blob_dir=None, storage='1', shared_blob_dir=True): +def _main( + host, + port, + unix=None, + days=1, + username=None, + password=None, + realm=None, + blob_dir=None, + storage="1", + shared_blob_dir=True, +): if unix is not None: addr = unix else: @@ -27,17 +36,24 @@ def _main(host, port, unix=None, days=1, username=None, password=None, # We do not want to wait until a zeoserver is up and running; it # should already be running, so wait=False cs = ClientStorage( - addr, storage=storage, wait=False, read_only=True, - username=username, password=password, realm=realm, - blob_dir=blob_dir, shared_blob_dir=shared_blob_dir, + addr, + storage=storage, + wait=False, + read_only=True, + username=username, + password=password, + realm=realm, + blob_dir=blob_dir, + shared_blob_dir=shared_blob_dir, ) for i in range(60): if cs.is_connected(): break time.sleep(1) else: - logger.error("Could not connect to zeoserver. Please make sure it " - "is running.") + logger.error( + "Could not connect to zeoserver. Please make sure it " "is running." + ) cs.close() sys.exit(1) try: @@ -45,8 +61,9 @@ def _main(host, port, unix=None, days=1, username=None, password=None, # => wait=True cs.pack(wait=True, days=int(days)) except ClientDisconnected: - logger.error("Disconnected from zeoserver. Please make sure it " - "is still running.") + logger.error( + "Disconnected from zeoserver. Please make sure it " "is still running." + ) sys.exit(1) finally: if cs is not None: @@ -58,8 +75,7 @@ def main(*args, **kw): old_level = root_logger.getEffectiveLevel() logging.getLogger().setLevel(logging.WARNING) handler = logging.StreamHandler(sys.stdout) - handler.setFormatter(logging.Formatter( - "%(name)s %(levelname)s %(message)s")) + handler.setFormatter(logging.Formatter("%(name)s %(levelname)s %(message)s")) logging.getLogger().addHandler(handler) try: _main(*args, **kw) diff --git a/src/plone/recipe/zeoserver/recipe.py b/src/plone/recipe/zeoserver/recipe.py index 7074006..66192bc 100644 --- a/src/plone/recipe/zeoserver/recipe.py +++ b/src/plone/recipe/zeoserver/recipe.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging import os import shutil @@ -9,6 +8,7 @@ try: import zc.zrs + HAS_ZRS = True except ImportError: HAS_ZRS = False @@ -17,74 +17,81 @@ curdir = os.path.dirname(__file__) -class Recipe(object): - +class Recipe: def __init__(self, buildout, name, options): - self.egg = zc.recipe.egg.Egg(buildout, options['recipe'], options) + self.egg = zc.recipe.egg.Egg(buildout, options["recipe"], options) self.buildout, self.options, self.name = buildout, options, name - options['location'] = os.path.join( - buildout['buildout']['parts-directory'], + if self.options.get("eggs") and options["recipe"] not in self.options["eggs"]: + # make sure we do not loose our own dependencies if additional eggs are provided + self.options["eggs"] += "\n%s" % options["recipe"] + + options["location"] = os.path.join( + buildout["buildout"]["parts-directory"], self.name, ) - options['bin-directory'] = buildout['buildout']['bin-directory'] - options['scripts'] = '' # suppress script generation. + options["bin-directory"] = buildout["buildout"]["bin-directory"] + options["scripts"] = "" # suppress script generation. # Relative path support for the generated scripts relative_paths = options.get( - 'relative-paths', - buildout['buildout'].get('relative-paths', 'false')) - if relative_paths == 'true': - options['buildout-directory'] = buildout['buildout']['directory'] - self._relative_paths = options['buildout-directory'] + "relative-paths", buildout["buildout"].get("relative-paths", "false") + ) + if relative_paths == "true": + options["buildout-directory"] = buildout["buildout"]["directory"] + self._relative_paths = options["buildout-directory"] else: - self._relative_paths = '' - assert relative_paths == 'false' + self._relative_paths = "" + assert relative_paths == "false" _ws_locations = None + @property def ws_locations(self): if self._ws_locations is None: - self._ws_locations = [d.location for d in self.zodb_ws] + self._ws_locations = {d.location for d in self.zodb_ws} return self._ws_locations - ws_locations = property(ws_locations) def install(self): _, self.zodb_ws = self.egg.working_set() options = self.options - location = options['location'] + location = options["location"] if os.path.exists(location): shutil.rmtree(location) - self.module_paths = self.options.get('extra-paths', []) + self.module_paths = self.options.get("extra-paths", []) if self.module_paths: # Filter out empty directories - self.module_paths = [p for p in self.module_paths.split('\n') if p] + self.module_paths = [p for p in self.module_paths.split("\n") if p] # this was taken from mkzeoinstance.py import zdaemon + zdaemon_home = os.path.split(zdaemon.__path__[0])[0] import ZEO + self.zodb_home = os.path.dirname(os.path.dirname(ZEO.__file__)) params = { "package": "zeo", "PACKAGE": "ZEO", "zodb_home": self.zodb_home, - 'zdaemon_home': zdaemon_home, + "zdaemon_home": zdaemon_home, "instance_home": location, - "address": '8100', # will be overwritten later - "python": options['executable'], + "address": "8100", # will be overwritten later + "python": options["executable"], } from zope.mkzeoinstance import ZEOInstanceBuilder + ZEOInstanceBuilder().create(location, params) try: # Save the working set: - open(os.path.join(location, 'etc', '.eggs'), 'w').write( - '\n'.join(self.ws_locations)) + open(os.path.join(location, "etc", ".eggs"), "w").write( + "\n".join(self.ws_locations) + ) # Make a new zeo.conf based on options in buildout.cfg self.build_zeo_conf() @@ -95,7 +102,7 @@ def install(self): # Install extra scripts self.install_scripts() - except Exception: # clean up + except Exception: # clean up shutil.rmtree(location) raise @@ -105,14 +112,14 @@ def update(self): _, self.zodb_ws = self.egg.working_set() options = self.options - location = options['location'] + location = options["location"] if os.path.exists(location): # See if we can stop. We need to see if the working set path # has changed. - saved_path = os.path.join(location, 'etc', '.eggs') + saved_path = os.path.join(location, "etc", ".eggs") if os.path.isfile(saved_path): - if (open(saved_path).read() != '\n'.join(self.ws_locations)): + if open(saved_path).read() != "\n".join(self.ws_locations): # Something has changed. Blow away the instance. self.install() @@ -125,108 +132,109 @@ def update(self): return location def build_zeo_conf(self): - """Create a zeo.conf file - """ + """Create a zeo.conf file""" options = self.options - location = options['location'] + location = options["location"] instance_home = location - base_dir = self.buildout['buildout']['directory'] - var_dir = options.get('var', os.path.join(base_dir, 'var')) + base_dir = self.buildout["buildout"]["directory"] + var_dir = options.get("var", os.path.join(base_dir, "var")) if not os.path.exists(var_dir): os.makedirs(var_dir) self.pid_file = options.get( - 'pid-file', - os.path.join(var_dir, self.name + '.pid')) + "pid-file", os.path.join(var_dir, self.name + ".pid") + ) - zeo_conf_path = options.get('zeo-conf', None) + zeo_conf_path = options.get("zeo-conf", None) if zeo_conf_path is not None: zeo_conf = "%%include %s" % os.path.abspath(zeo_conf_path) else: - zeo_address = options.get('zeo-address', '8100') - zeo_conf_additional = options.get('zeo-conf-additional', '') - storage_number = options.get('storage-number', '1') + zeo_address = options.get("zeo-address", "8100") + zeo_conf_additional = options.get("zeo-conf-additional", "") + storage_number = options.get("storage-number", "1") - monitor_address = options.get('monitor-address', '') + monitor_address = options.get("monitor-address", "") if monitor_address: - monitor_address = 'monitor-address %s' % monitor_address + monitor_address = "monitor-address %s" % monitor_address - effective_user = options.get('effective-user', '') + effective_user = options.get("effective-user", "") if effective_user: - effective_user = 'user %s' % effective_user + effective_user = "user %s" % effective_user - invalidation_queue_size = options.get('invalidation-queue-size', - '100') + invalidation_queue_size = options.get("invalidation-queue-size", "100") - socket_name = options.get('socket-name', - '%s/zeo.zdsock' % var_dir) + socket_name = options.get("socket-name", "%s/zeo.zdsock" % var_dir) socket_dir = os.path.dirname(socket_name) if not os.path.exists(socket_dir): os.makedirs(socket_dir) - z_log_name = os.path.sep.join(('log', self.name + '.log')) - zeo_log_level = options.get('zeo-log-level', 'info') - zeo_log_custom = options.get('zeo-log-custom', None) + z_log_name = os.path.sep.join(("log", self.name + ".log")) + zeo_log_level = options.get("zeo-log-level", "info") + zeo_log_custom = options.get("zeo-log-custom", None) # if zeo-log is given, we use it to set the runner # logfile value in any case - z_log_filename = options.get('zeo-log', z_log_name) + z_log_filename = options.get("zeo-log", z_log_name) z_log_filename = os.path.join(var_dir, z_log_filename) z_log_dir = os.path.dirname(z_log_filename) if not os.path.exists(z_log_dir): os.makedirs(z_log_dir) # zeo-log-custom superseeds zeo-log - logformat = options.get( - 'zeo-log-format', '%(asctime)s %(message)s') + logformat = options.get("zeo-log-format", "%(asctime)s %(message)s") if zeo_log_custom is None: - zeo_log_rotate = '' - zeo_log_max_size = options.get('zeo-log-max-size', None) + zeo_log_rotate = "" + zeo_log_max_size = options.get("zeo-log-max-size", None) if zeo_log_max_size: - zeo_log_old_files = options.get('zeo-log-old-files', 1) - zeo_log_rotate = '\n'.join(( - "max-size %s" % zeo_log_max_size, - " old-files %s" % zeo_log_old_files)) + zeo_log_old_files = options.get("zeo-log-old-files", 1) + zeo_log_rotate = "\n".join( + ( + "max-size %s" % zeo_log_max_size, + " old-files %s" % zeo_log_old_files, + ) + ) z_log = z_log_file % { - 'filename': z_log_filename, - 'logformat': logformat, - 'zeo_log_rotate': zeo_log_rotate} + "filename": z_log_filename, + "logformat": logformat, + "zeo_log_rotate": zeo_log_rotate, + } else: z_log = zeo_log_custom - file_storage = os.path.sep.join(('filestorage', 'Data.fs')) - file_storage = options.get('file-storage', file_storage) + file_storage = os.path.sep.join(("filestorage", "Data.fs")) + file_storage = options.get("file-storage", file_storage) file_storage = os.path.join(var_dir, file_storage) file_storage_dir = os.path.dirname(file_storage) if not os.path.exists(file_storage_dir): os.makedirs(file_storage_dir) - if options.get('authentication-database', ''): - authentication = authentication_template % \ - dict(database=options.get('authentication-database'), - realm=options.get('authentication-realm', 'ZEO')) + if options.get("authentication-database", ""): + authentication = authentication_template % dict( + database=options.get("authentication-database"), + realm=options.get("authentication-realm", "ZEO"), + ) else: - authentication = '' + authentication = "" - blob_storage = options.get('blob-storage', 'blobstorage') + blob_storage = options.get("blob-storage", "blobstorage") if blob_storage: blob_storage = os.path.join(var_dir, blob_storage) storage_template = blob_storage_template else: storage_template = file_storage_template - effective_user = options.get('effective-user', '') + effective_user = options.get("effective-user", "") if effective_user: - effective_user = 'user %s' % effective_user + effective_user = "user %s" % effective_user - pack_gc = options.get('pack-gc', '') - if pack_gc.lower() == 'false': - pack_gc = 'pack-gc false' + pack_gc = options.get("pack-gc", "") + if pack_gc.lower() == "false": + pack_gc = "pack-gc false" - pack_keep_old = options.get('pack-keep-old', '') - if pack_keep_old.lower() == 'false': - pack_keep_old = 'pack-keep-old false' + pack_keep_old = options.get("pack-keep-old", "") + if pack_keep_old.lower() == "false": + pack_keep_old = "pack-keep-old false" storage = storage_template % dict( storage_number=storage_number, @@ -237,23 +245,23 @@ def build_zeo_conf(self): ) # ZRS config - rfrom = options.get('replicate-from') - rto = options.get('replicate-to') + rfrom = options.get("replicate-from") + rto = options.get("replicate-to") if HAS_ZRS and (rfrom or rto): - replicate = '' + replicate = "" if rfrom: replicate += "\nreplicate-from %s" % rfrom if rto: replicate += "\nreplicate-to %s" % rto - keep_alive = options.get('keep-alive-delay', '60') + keep_alive = options.get("keep-alive-delay", "60") storage = zrs_template % dict( storage=storage, keep_alive=keep_alive, replicate=replicate, - storage_number=storage_number + storage_number=storage_number, ) - read_only = options.get('read-only', 'false') + read_only = options.get("read-only", "false") zeo_conf = zeo_conf_template % dict( instance_home=instance_home, effective_user=effective_user, @@ -268,78 +276,74 @@ def build_zeo_conf(self): zeo_conf_additional=zeo_conf_additional, monitor_address=monitor_address, zeo_log_level=zeo_log_level, - read_only=read_only + read_only=read_only, ) - zeo_conf_path = os.path.join(location, 'etc', 'zeo.conf') - open(zeo_conf_path, 'w').write(zeo_conf) + zeo_conf_path = os.path.join(location, "etc", "zeo.conf") + open(zeo_conf_path, "w").write(zeo_conf) def patch_binaries(self): - location = self.options['location'] + location = self.options["location"] # XXX We need to patch the windows specific batch scripts - # and they need a different path seperator + # and they need a different path separator path = ( - os.path.pathsep.join(self.ws_locations) + - os.path.pathsep + - os.path.pathsep.join(self.module_paths) + os.path.pathsep.join(self.ws_locations) + + os.path.pathsep + + os.path.pathsep.join(self.module_paths) ) - - for script_name in ('runzeo', 'zeoctl'): - script_path = os.path.join(location, 'bin', script_name) + for script_name in ("runzeo", "zeoctl"): + script_path = os.path.join(location, "bin", script_name) script = open(script_path).read() - script = script.replace('PYTHONPATH="$ZODB3_HOME"', - 'PYTHONPATH="%s"' % path) - f = open(script_path, 'w') + script = script.replace( + 'PYTHONPATH="$ZODB3_HOME"', 'PYTHONPATH="%s"' % path + ) + f = open(script_path, "w") f.write(script) f.close() def install_scripts(self): options = self.options - location = options['location'] + location = options["location"] - self.zeo_conf = options.get('zeo-conf', None) + self.zeo_conf = options.get("zeo-conf", None) if self.zeo_conf is None: - self.zeo_conf = os.path.join(location, 'etc', 'zeo.conf') + self.zeo_conf = os.path.join(location, "etc", "zeo.conf") - _, ws = self.egg.working_set(['plone.recipe.zeoserver']) + _, ws = self.egg.working_set(["plone.recipe.zeoserver"]) - path = ( - os.path.pathsep.join(self.ws_locations) + - os.path.pathsep + - os.path.pathsep.join(self.module_paths) - ) - initialization = """ - import os; os.environ['PYTHONPATH'] = %r - """.strip() % path zc.buildout.easy_install.scripts( - [(self.name, 'plone.recipe.zeoserver.ctl', 'main')], - ws, options['executable'], options['bin-directory'], - initialization='\n'.join( - [initialization, options.get('initialization', ''), '']), - arguments=('\n ["-C", %r]' - '\n + sys.argv[1:]' - % self.zeo_conf), + [(self.name, "plone.recipe.zeoserver.ctl", "main")], + ws, + options["executable"], + options["bin-directory"], + initialization=options.get("initialization", ""), + arguments=( + '\n ["-C", %r]' "\n + sys.argv[1:]" % self.zeo_conf + ), extra_paths=self.module_paths, - relative_paths=self._relative_paths) + relative_paths=self._relative_paths, + ) # zeopack.py - zeopack = options.get('zeopack', None) - zeopack_script_name = options.get('zeopack-script-name', 'zeopack') + zeopack = options.get("zeopack", None) + zeopack_script_name = options.get("zeopack-script-name", "zeopack") zeopack_scripts = dict(zeopack=zeopack_script_name) if zeopack is not None: directory, filename = os.path.split(zeopack) if zeopack and os.path.exists(zeopack): zc.buildout.easy_install.scripts( - [('zeopack', os.path.splitext(filename)[0], 'main')], - ws, options['executable'], options['bin-directory'], + [("zeopack", os.path.splitext(filename)[0], "main")], + ws, + options["executable"], + options["bin-directory"], scripts=zeopack_scripts, extra_paths=ws + [directory] + self.module_paths, relative_paths=self._relative_paths, ) else: - host = port = socket_path = '' - zeo_address = options.get('zeo-address', '8100') - parts = zeo_address.split(':') + host = port = socket_path = "" + zeo_address = options.get("zeo-address", "8100") + parts = zeo_address.split(":") if len(parts) == 1: try: @@ -351,145 +355,154 @@ def install_scripts(self): # a path to a Unix socket file socket_path = zeo_address else: - host = '127.0.0.1' + host = "127.0.0.1" port = zeo_address else: host, port = parts - username = options.get('pack-user', None) - password = options.get('pack-password', None) + username = options.get("pack-user", None) + password = options.get("pack-password", None) if username is not None: - realm = options.get('authentication-realm', 'ZEO') + realm = options.get("authentication-realm", "ZEO") else: realm = None - storage = options.get('storage-number', '1') + storage = options.get("storage-number", "1") arg_list = [ - 'host', 'port', 'unix', 'days', - 'username', 'password', 'realm', 'blob_dir', 'storage', + "host", + "port", + "unix", + "days", + "username", + "password", + "realm", + "blob_dir", + "storage", ] arguments = dict( address=zeo_address, host=host, port=port, unix=socket_path, - days=options.get('pack-days', 1), + days=options.get("pack-days", 1), username=username, password=password, realm=realm, storage=storage, - blob_dir=options.get('blob-storage', None), + blob_dir=options.get("blob-storage", None), ) - arguments_info = '' + arguments_info = "" for k, v in arguments.items(): if not v: - arguments_info += '%s = None\n' % k + arguments_info += "%s = None\n" % k else: - arguments_info += '%s = "%s"\n' % (k, v) - - arguments_info += ("import getopt; opts = " - "getopt.getopt(sys.argv[1:], 'S:B:D:W1')[0];\n" - "opts = dict(opts)\n" - "storage = opts.get('-S') and " - "opts['-S'] or storage\n" - "blob_dir = opts.get('-B') and " - "opts['-B'] or blob_dir\n" - "days = opts.get('-D') and " - "opts['-D'] or days\n" - ) + arguments_info += f'{k} = "{v}"\n' + + arguments_info += ( + "import getopt; opts = " + "getopt.getopt(sys.argv[1:], 'S:B:D:W1')[0];\n" + "opts = dict(opts)\n" + "storage = opts.get('-S') and " + "opts['-S'] or storage\n" + "blob_dir = opts.get('-B') and " + "opts['-B'] or blob_dir\n" + "days = opts.get('-D') and " + "opts['-D'] or days\n" + ) # Make sure the recipe itself and its dependencies are on the path - extra_paths = [ - ws.by_key[options['recipe'].replace('[zrs]', '')].location] + extra_paths = [ws.by_key[options["recipe"].replace("[zrs]", "")].location] try: - extra_paths.append(ws.by_key['zc.buildout'].location) + extra_paths.append(ws.by_key["zc.buildout"].location) except KeyError: # XXX Buildout installed with Pip? pass - extra_paths.append(ws.by_key['zc.recipe.egg'].location) + extra_paths.append(ws.by_key["zc.recipe.egg"].location) zc.buildout.easy_install.scripts( - [('zeopack', 'plone.recipe.zeoserver.pack', 'main')], - self.zodb_ws, options['executable'], options['bin-directory'], + [("zeopack", "plone.recipe.zeoserver.pack", "main")], + self.zodb_ws, + options["executable"], + options["bin-directory"], scripts=zeopack_scripts, initialization=arguments_info, - arguments=', '.join(arg_list), + arguments=", ".join(arg_list), relative_paths=self._relative_paths, extra_paths=extra_paths + self.module_paths, ) # The backup script, pointing to repozo.py - repozo = options.get('repozo', None) - repozo_script_name = options.get('repozo-script-name', 'repozo') + repozo = options.get("repozo", None) + repozo_script_name = options.get("repozo-script-name", "repozo") repozo_scripts = dict(repozo=repozo_script_name) if repozo is None: - repozo = 'ZODB.scripts.repozo' + repozo = "ZODB.scripts.repozo" extra_paths = [] else: if not os.path.exists(repozo): - raise AssertionError( - 'Custom repozo script not found: %s' % repozo) + raise AssertionError("Custom repozo script not found: %s" % repozo) directory, filename = os.path.split(repozo) repozo = os.path.splitext(filename)[0] extra_paths = [directory] zc.buildout.easy_install.scripts( - [('repozo', repozo, 'main')], - self.zodb_ws, options['executable'], options['bin-directory'], + [("repozo", repozo, "main")], + self.zodb_ws, + options["executable"], + options["bin-directory"], scripts=repozo_scripts, extra_paths=extra_paths + self.module_paths, relative_paths=self._relative_paths, ) - if sys.platform == 'win32': + if sys.platform == "win32": self.install_win32_scripts() def install_win32_scripts(self): - path = self.ws_locations + self.module_paths - location = self.options['location'] + path = list(self.ws_locations) + self.module_paths + location = self.options["location"] - arguments = {'PYTHON': self.options['executable'], - 'zodb_home': self.zodb_home, - 'INSTANCE_HOME': location, - 'PYTHONPATH': os.path.pathsep.join(path), - 'PACKAGE': 'zeo', - 'PID_FILENAME': self.pid_file} + arguments = { + "PYTHON": self.options["executable"], + "zodb_home": self.zodb_home, + "INSTANCE_HOME": location, + "PYTHONPATH": os.path.pathsep.join(path), + "PACKAGE": "zeo", + "PID_FILENAME": self.pid_file, + } # runzeo.bat - runzeo_filename = '%s_runzeo.bat' % self.name - runzeo = open(join(curdir, 'runzeo.bat')).read() - self._write_file(os.path.join(self.options['bin-directory'], - runzeo_filename), runzeo % arguments) + runzeo_filename = "%s_runzeo.bat" % self.name + runzeo = open(join(curdir, "runzeo.bat")).read() + self._write_file( + os.path.join(self.options["bin-directory"], runzeo_filename), + runzeo % arguments, + ) # zeoservice.py - zeo_filename = '%s_service' % self.name - zeo_service = open(join(curdir, 'zeoservice.py.in')).read() - zeo_file = os.path.join(self.options['bin-directory'], - '%s.py' % zeo_filename) + zeo_filename = "%s_service" % self.name + zeo_service = open(join(curdir, "zeoservice.py.in")).read() + zeo_file = os.path.join(self.options["bin-directory"], "%s.py" % zeo_filename) self._write_file(zeo_file, zeo_service % arguments) - initialization = """ - import os; os.environ['PYTHONPATH'] = %r - """.strip() % os.path.pathsep.join(path) - zc.buildout.easy_install.scripts( - [(zeo_filename, zeo_filename, 'main')], + [(zeo_filename, zeo_filename, "main")], self.zodb_ws, - self.options['executable'], - self.options['bin-directory'], + self.options["executable"], + self.options["bin-directory"], extra_paths=path, relative_paths=self._relative_paths, - initialization=initialization, + initialization=self.options.get("initialization", ""), ) def _write_file(self, path, content): - logger = logging.getLogger('zc.buildout.easy_install') - f = open(path, 'w') + logger = logging.getLogger("zc.buildout.easy_install") + f = open(path, "w") try: f.write(content) finally: f.close() - logger.debug('Wrote file %s' % path) + logger.debug("Wrote file %s" % path) os.chmod(path, 0o755) - logger.warning('Changed mode for %s to 755' % path) + logger.warning("Changed mode for %s to 755" % path) # the template used to build a regular file storage entry for zeo.conf diff --git a/src/plone/recipe/zeoserver/tests/__init__.py b/src/plone/recipe/zeoserver/tests/__init__.py index ec51c5a..792d600 100644 --- a/src/plone/recipe/zeoserver/tests/__init__.py +++ b/src/plone/recipe/zeoserver/tests/__init__.py @@ -1,2 +1 @@ -# -*- coding: utf-8 -*- # diff --git a/src/plone/recipe/zeoserver/tests/test_docs.py b/src/plone/recipe/zeoserver/tests/test_docs.py index 84dba40..81b3642 100644 --- a/src/plone/recipe/zeoserver/tests/test_docs.py +++ b/src/plone/recipe/zeoserver/tests/test_docs.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - from zc.buildout.testing import buildoutSetUp from zc.buildout.testing import buildoutTearDown from zc.buildout.testing import install @@ -8,28 +6,24 @@ import doctest import pkg_resources import shutil -import sys import unittest def setUp(test): buildoutSetUp(test) - install_develop('plone.recipe.zeoserver', test) - install('zc.recipe.egg', test) - if sys.platform[:3].lower() == "win": - install('nt_svcutils', test) - install('zope.mkzeoinstance', test) - install('ZopeUndo', test) - install('zc.zrs', test) - install('Automat', test) - install('incremental', test) - install('constantly', test) - install('attrs', test) - install('Twisted', test) - install('hyperlink', test) - install('idna', test) - install('PyHamcrest', test) - dependencies = pkg_resources.working_set.require('ZODB') + install_develop("plone.recipe.zeoserver", test) + install("zc.recipe.egg", test) + install("zope.mkzeoinstance", test) + install("ZopeUndo", test) + install("zc.zrs", test) + install("Automat", test) + install("incremental", test) + install("constantly", test) + install("attrs", test) + install("Twisted", test) + install("hyperlink", test) + install("idna", test) + dependencies = pkg_resources.working_set.require("ZODB") for dep in dependencies: try: install(dep.project_name, test) @@ -41,15 +35,18 @@ def setUp(test): def tearDown(test): buildoutTearDown(test) - sample_buildout = test.globs['sample_buildout'] + sample_buildout = test.globs["sample_buildout"] shutil.rmtree(sample_buildout, ignore_errors=True) def test_suite(): suite = [] - flags = (doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE) + flags = doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE - suite.append(doctest.DocFileSuite('zeoserver.txt', optionflags=flags, - setUp=setUp, tearDown=buildoutTearDown)) + suite.append( + doctest.DocFileSuite( + "zeoserver.txt", optionflags=flags, setUp=setUp, tearDown=buildoutTearDown + ) + ) return unittest.TestSuite(suite) diff --git a/src/plone/recipe/zeoserver/tests/zeoserver.txt b/src/plone/recipe/zeoserver/tests/zeoserver.txt index 080a4a8..9cfd184 100644 --- a/src/plone/recipe/zeoserver/tests/zeoserver.txt +++ b/src/plone/recipe/zeoserver/tests/zeoserver.txt @@ -272,7 +272,8 @@ We should have a zeo.conf with log file rotation enabled:: >>> zeo = os.path.join(sample_buildout, 'parts', 'zeo') >>> with open(os.path.join(zeo, 'etc', 'zeo.conf')) as f: - ... print(f.read()) + ... output = f.read() + >>> print(output.replace('\\', '/')) %define INSTANCE ... ... @@ -474,7 +475,7 @@ be different and correspond as the buildout specified:: >>> zeopack_scripts = ('first-zeopack', 'second-zeopack') >>> zeopack_paths = [os.path.join(sample_buildout, 'bin', script) for script in zeopack_scripts] >>> if WINDOWS: - ... zeopack_paths = [zeopack + '-script.py' for zeopack in zeopacks] + ... zeopack_paths = [zeopack + '-script.py' for zeopack in zeopack_paths] >>> with open(zeopack_paths[0], 'r') as f: ... first_zeopack = f.read() >>> with open(zeopack_paths[1], 'r') as f: @@ -632,3 +633,30 @@ The main script should have the initialization. >>> with open(join('bin', 'zeo' + suffix)) as f: ... 'foo = 1' in f.read() True + +Additional eggs +=============== + +The recipe support additional eggs. + + >>> write('buildout.cfg', + ... ''' + ... [buildout] + ... parts = zeo + ... find-links = %(sample_buildout)s/eggs + ... + ... [zeo] + ... recipe = plone.recipe.zeoserver + ... zeo-address = /path/to/zeo.socket + ... eggs = ZEO + ... ''' % globals()) + >>> print(system(join('bin', 'buildout'))), + Uninstalling zeo. + Installing zeo. + ... + +The main script should have the initialization. + + >>> with open(join('parts', 'zeo', 'bin', 'zeoctl')) as f: + ... 'plone.recipe.zeoserver' in f.read() + True diff --git a/tox.ini b/tox.ini index d7c0507..c7235fd 100644 --- a/tox.ini +++ b/tox.ini @@ -1,38 +1,76 @@ +# Generated from: +# https://github.com/plone/meta/tree/master/config/default [tox] +# We need 4.4.0 for constrain_package_deps. +min_version = 4.4.0 envlist = - py27, - py36, - py37, - py38, - flake8, - coverage - -skip_missing_interpreters = False + format + lint + test [testenv] -usedevelop = true +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 +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 package's dependencies +deps = + pipdeptree==2.5.1 + graphviz # optional dependency of pipdeptree commands = - zope-testrunner --test-path=src --all {posargs:-vc} -extras = zrs + sh -c 'pipdeptree --exclude setuptools,wheel,pipdeptree,zope.interface,zope.component --graph-output svg > dependencies.svg' + +[testenv:test] +use_develop = true +constrain_package_deps = true +set_env = ROBOT_BROWSER=headlesschrome deps = zope.testrunner + -c https://dist.plone.org/release/6.0-dev/constraints.txt +commands = + zope-testrunner --all --test-path={toxinidir}/src -s plone.recipe.zeoserver {posargs} +extras = + zrs [testenv:coverage] -basepython = python3.6 +use_develop = true +constrain_package_deps = true +set_env = ROBOT_BROWSER=headlesschrome deps = - zope.testrunner coverage -setenv = - COVERAGE_HOME={toxinidir} - COVERAGE_PROCESS_START={toxinidir}/.coveragerc + zope.testrunner + -c https://dist.plone.org/release/6.0-dev/constraints.txt commands = - coverage run -m zope.testrunner --test-path=src {posargs:-vc} - coverage combine - coverage html - coverage report --fail-under=62 - -[testenv:flake8] -basepython = python3.6 -skip_install = true -deps = flake8 -commands = flake8 --doctests src setup.py + coverage run {envbindir}/zope-testrunner --all --test-path={toxinidir}/src -s plone.recipe.zeoserver {posargs} + coverage report -m --format markdown +extras = + zrs