From c4c60d3a1f8d61cd80308cc3e5a7c21726ed975e Mon Sep 17 00:00:00 2001 From: Sylvain Viollon Date: Wed, 10 Jan 2018 14:25:06 +0100 Subject: [PATCH] Come back from the dead. --- .gitignore | 11 ++ CHANGES.txt | 88 +++++------- MANIFEST.in | 3 + README.txt | 2 - bootstrap.py | 279 ++++++++++++++---------------------- buildout.cfg | 6 +- setup.py | 25 ++-- src/hurry/workflow/tests.py | 22 +-- 8 files changed, 179 insertions(+), 257 deletions(-) create mode 100644 .gitignore create mode 100644 MANIFEST.in diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a0bff50 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +*.py[co] +__pycache__/ +build/ +dist/ +*.egg-info/ +.tox/ +bin/ +eggs/ +develop-eggs/ +parts/ +.installed.cfg diff --git a/CHANGES.txt b/CHANGES.txt index 96434ec..42c65d4 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,108 +1,90 @@ -====================== -hurry.workflow changes -====================== +CHANGES +======= 0.14 (unreleased) -================= - -- Nothing changed yet. +----------------- +- Update dependencies not to rely on ZODB 3 anymore. 0.13.1 (2013-01-17) -=================== +------------------- -* Make the exceptions also display more informative messages. +- Make the exceptions also display more informative messages. 0.13 (2013-01-17) -================= +----------------- -* ``NoTransitionAvailableError`` gained a ``source`` and ``destination`` +- ``NoTransitionAvailableError`` gained a ``source`` and ``destination`` attribute indicating what transition wasn't available. -* ``AmbiguousTransitionError`` also gained a ``source`` and ``destination`` +- ``AmbiguousTransitionError`` also gained a ``source`` and ``destination`` attribute indicating what transition was ambiguous. - -* ``InvalidTransitionError`` gained a ``source`` attribute indicating + +- ``InvalidTransitionError`` gained a ``source`` attribute indicating the source state of the attempted invalid transition. -* Newer ``bootstrap.py`` +- Newer ``bootstrap.py`` 0.12 (2012-02-10) -================= +----------------- -* Make the info() and state() functions on the WorkflowInfo class into +- Make the info() and state() functions on the WorkflowInfo class into classmethods as they are not of much use otherwise. -* fireTransitionToward already accepted a check_security=False +- fireTransitionToward already accepted a check_security=False argument, but it would not allow a transition that a user didn't have the permission for to be fired after all, because the transition wouldn't even be found in the first place. Now it works. 0.11 (2010-04-16) -================= +----------------- -* Do IAnnotations(self.context) only once in WorkflowState. +- Do IAnnotations(self.context) only once in WorkflowState. -* An IWorkflowVersions implementation is now optional. +- An IWorkflowVersions implementation is now optional. -* Added multiple workflows support. +- Added multiple workflows support. 0.10 (2009-11-19) -================= +----------------- -* Moved to svn.zope.org for development. +- Moved to svn.zope.org for development. -* Added a buildout.cfg, bootstrap.py +- Added a buildout.cfg, bootstrap.py -* Minimized dependencies. Note that ``Workflow`` does not inherit from +- Minimized dependencies. Note that ``Workflow`` does not inherit from ``Persistent`` and ``zope.container.contained.Contained`` anymore. If you need persistent workflow, you need to subclass this in your own code. This breaks backwards compatibility, as persistent workflows would need to be re-initialized. 0.9.2.1 (2007-08-15) -==================== +-------------------- -Bug fixes ---------- - -* Oops, the patches in 0.9.2 were not actually applied. Fixed them +- Oops, the patches in 0.9.2 were not actually applied. Fixed them now. 0.9.2 (2007-08-15) -================== - -Bug fixes ---------- +------------------ -* zope.security changes broke imports in hurry.workflow. +- zope.security changes broke imports in hurry.workflow. -* localUtility directive is now deprecated, so don't use it anymore. +- localUtility directive is now deprecated, so don't use it anymore. 0.9.1 (2006-09-22) -================== +------------------ -Feature changes ---------------- - -* first cheesehop release. +- first cheesehop release. 0.9 (2006-06-15) -================ - -Feature changes ---------------- +---------------- +- separate out from hurry package into hurry.workflow -* separate out from hurry package into hurry.workflow +- eggification work -* eggification work - -* Zope 3.3 compatibility work +- Zope 3.3 compatibility work 0.8 (2006-05-01) -================ - -Feature changes ---------------- +---------------- Initial public release. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..abc9717 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,3 @@ +recursive-include src *.* +include * +global-exclude *.pyc diff --git a/README.txt b/README.txt index defb965..9b92b28 100644 --- a/README.txt +++ b/README.txt @@ -1,5 +1,3 @@ -************** hurry.workflow -************** A simple but quite nifty workflow system for Zope 3. diff --git a/bootstrap.py b/bootstrap.py index 5f2cb08..a629566 100644 --- a/bootstrap.py +++ b/bootstrap.py @@ -18,74 +18,14 @@ use the -c option to specify an alternate configuration file. """ -import os, shutil, sys, tempfile, textwrap, urllib, urllib2, subprocess +import os +import shutil +import sys +import tempfile + from optparse import OptionParser -if sys.platform == 'win32': - def quote(c): - if ' ' in c: - return '"%s"' % c # work around spawn lamosity on windows - else: - return c -else: - quote = str - -# See zc.buildout.easy_install._has_broken_dash_S for motivation and comments. -stdout, stderr = subprocess.Popen( - [sys.executable, '-Sc', - 'try:\n' - ' import ConfigParser\n' - 'except ImportError:\n' - ' print 1\n' - 'else:\n' - ' print 0\n'], - stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() -has_broken_dash_S = bool(int(stdout.strip())) - -# In order to be more robust in the face of system Pythons, we want to -# run without site-packages loaded. This is somewhat tricky, in -# particular because Python 2.6's distutils imports site, so starting -# with the -S flag is not sufficient. However, we'll start with that: -if not has_broken_dash_S and 'site' in sys.modules: - # We will restart with python -S. - args = sys.argv[:] - args[0:0] = [sys.executable, '-S'] - args = map(quote, args) - os.execv(sys.executable, args) -# Now we are running with -S. We'll get the clean sys.path, import site -# because distutils will do it later, and then reset the path and clean -# out any namespace packages from site-packages that might have been -# loaded by .pth files. -clean_path = sys.path[:] -import site -sys.path[:] = clean_path -for k, v in sys.modules.items(): - if k in ('setuptools', 'pkg_resources') or ( - hasattr(v, '__path__') and - len(v.__path__)==1 and - not os.path.exists(os.path.join(v.__path__[0],'__init__.py'))): - # This is a namespace package. Remove it. - sys.modules.pop(k) - -is_jython = sys.platform.startswith('java') - -setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py' -distribute_source = 'http://python-distribute.org/distribute_setup.py' - -# parsing arguments -def normalize_to_url(option, opt_str, value, parser): - if value: - if '://' not in value: # It doesn't smell like a URL. - value = 'file://%s' % ( - urllib.pathname2url( - os.path.abspath(os.path.expanduser(value))),) - if opt_str == '--download-base' and not value.endswith('/'): - # Download base needs a trailing slash to make the world happy. - value += '/' - else: - value = None - name = opt_str[2:].replace('-', '_') - setattr(parser.values, name, value) +tmpeggs = tempfile.mkdtemp() usage = '''\ [DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options] @@ -95,31 +35,13 @@ def normalize_to_url(option, opt_str, value, parser): 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 --setup-source and --download-base to point to -local resources, you can keep this script from going over the network. +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", dest="version", - help="use a specific zc.buildout version") -parser.add_option("-d", "--distribute", - action="store_true", dest="use_distribute", default=False, - help="Use Distribute rather than Setuptools.") -parser.add_option("--setup-source", action="callback", dest="setup_source", - callback=normalize_to_url, nargs=1, type="string", - help=("Specify a URL or file location for the setup file. " - "If you use Setuptools, this will default to " + - setuptools_source + "; if you use Distribute, this " - "will default to " + distribute_source +".")) -parser.add_option("--download-base", action="callback", dest="download_base", - callback=normalize_to_url, nargs=1, type="string", - help=("Specify a URL or directory for downloading " - "zc.buildout and either Setuptools or Distribute. " - "Defaults to PyPI.")) -parser.add_option("--eggs", - help=("Specify a directory for storing eggs. Defaults to " - "a temporary directory that is deleted when the " - "bootstrap script completes.")) +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, @@ -129,81 +51,80 @@ def normalize_to_url(option, opt_str, value, parser): "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", None, action="store", dest="config_file", - help=("Specify the path to the buildout configuration " - "file to be used.")) +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() -# if -c was provided, we push it back into args for buildout's main function -if options.config_file is not None: - args += ['-c', options.config_file] +###################################################################### +# load/install setuptools -if options.eggs: - eggs_dir = os.path.abspath(os.path.expanduser(options.eggs)) -else: - eggs_dir = tempfile.mkdtemp() +try: + if options.allow_site_packages: + import setuptools + import pkg_resources + from urllib.request import urlopen +except ImportError: + from urllib2 import urlopen -if options.setup_source is None: - if options.use_distribute: - options.setup_source = distribute_source - else: - options.setup_source = setuptools_source +ez = {} +exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez) -if options.accept_buildout_test_releases: - args.append('buildout:accept-buildout-test-releases=true') -args.append('bootstrap') +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] -try: - import pkg_resources - import setuptools # A flag. Sometimes pkg_resources is installed alone. - if not hasattr(pkg_resources, '_distribute'): - raise ImportError -except ImportError: - ez_code = urllib2.urlopen( - options.setup_source).read().replace('\r\n', '\n') - ez = {} - exec ez_code in ez - setup_args = dict(to_dir=eggs_dir, download_delay=0) - if options.download_base: - setup_args['download_base'] = options.download_base - if options.use_distribute: - setup_args['no_fake'] = True - ez['use_setuptools'](**setup_args) - if 'pkg_resources' in sys.modules: - reload(sys.modules['pkg_resources']) - 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) - -cmd = [quote(sys.executable), - '-c', - quote('from setuptools.command.easy_install import main; main()'), - '-mqNxd', - quote(eggs_dir)] - -if not has_broken_dash_S: - cmd.insert(1, '-S') - -find_links = options.download_base -if not find_links: - find_links = os.environ.get('bootstrap-testing-find-links') -if find_links: - cmd.extend(['-f', quote(find_links)]) +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 -if options.use_distribute: - setup_requirement = 'distribute' -else: - setup_requirement = 'setuptools' ws = pkg_resources.working_set -setup_requirement_path = ws.find( - pkg_resources.Requirement.parse(setup_requirement)).location -env = dict( - os.environ, - PYTHONPATH=setup_requirement_path) + +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 @@ -211,13 +132,19 @@ def normalize_to_url(option, opt_str, value, parser): # Figure out the most recent final version of zc.buildout. import setuptools.package_index _final_parts = '*final-', '*final' + def _final_version(parsed_version): - for part in parsed_version: - if (part[:1] == '*') and (part not in _final_parts): - return False - return True + 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=[setup_requirement_path]) + search_path=[setuptools_path]) if find_links: index.add_find_links((find_links,)) req = pkg_resources.Requirement.parse(requirement) @@ -239,22 +166,24 @@ def _final_version(parsed_version): requirement = '=='.join((requirement, version)) cmd.append(requirement) -if is_jython: - import subprocess - exitcode = subprocess.Popen(cmd, env=env).wait() -else: # Windows prefers this, apparently; otherwise we would prefer subprocess - exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env])) -if exitcode != 0: - sys.stdout.flush() - sys.stderr.flush() - print ("An error occurred when trying to install zc.buildout. " - "Look above this message for any errors that " - "were output by easy_install.") - sys.exit(exitcode) - -ws.add_entry(eggs_dir) +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) -if not options.eggs: # clean up temporary egg directory - shutil.rmtree(eggs_dir) +shutil.rmtree(tmpeggs) diff --git a/buildout.cfg b/buildout.cfg index d71383b..ab5b654 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -1,10 +1,12 @@ [buildout] develop = . parts = test releaser -newest = false +versions = versions + +[versions] [releaser] -recipe = z3c.recipe.scripts +recipe = zc.recipe.egg eggs = zest.releaser [test] diff --git a/setup.py b/setup.py index 72faee9..d761593 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,7 @@ import os from setuptools import setup, find_packages + def read(*rnames): return open(os.path.join(os.path.dirname(__file__), *rnames)).read() @@ -22,14 +23,11 @@ def read(*rnames): name="hurry.workflow", version='0.14.dev0', packages=find_packages('src'), - - package_dir= {'':'src'}, - + package_dir={'': 'src'}, namespace_packages=['hurry'], - package_data = { - '': ['*.txt', '*.zcml'], + package_data={ + '': ['*.txt', '*.zcml'], }, - zip_safe=False, author='Martijn Faassen (at Infrae)', author_email='faassen@startifact.com', @@ -40,20 +38,17 @@ def read(*rnames): long_description=long_description, license='ZPL 2.1', keywords="zope zope3", - classifiers = ['Framework :: Zope3'], - extras_require = dict( - test = ['zope.testing'], - ), + classifiers=['Framework :: Zope3'], + extras_require=dict( + test=[], + ), install_requires=[ 'setuptools', 'zope.interface', 'zope.component', - # this is an indirect dependency through zope.annotation, but - # this at the time of working didn't yet declare this - # dependency itself - 'ZODB3', 'zope.event', 'zope.security', 'zope.annotation', - 'zope.lifecycleevent'], + 'zope.lifecycleevent' + ], ) diff --git a/src/hurry/workflow/tests.py b/src/hurry/workflow/tests.py index 4f54467..011bc68 100644 --- a/src/hurry/workflow/tests.py +++ b/src/hurry/workflow/tests.py @@ -1,12 +1,13 @@ +import doctest import unittest -from zope.testing import doctest from zope import component from zope.component import testing from zope.annotation import interfaces as annotation_interfaces from zope.annotation import attribute from hurry.workflow import interfaces, workflow + class WorkflowVersions(workflow.WorkflowVersions): """Simplistic implementation that keeps track of versions. @@ -14,15 +15,15 @@ class WorkflowVersions(workflow.WorkflowVersions): """ def __init__(self): self.versions = [] - + def addVersion(self, obj): self.versions.append(obj) - + def getVersions(self, state, id): result = [] for version in self.versions: - state_adapter = interfaces.IWorkflowState(version) - if state_adapter.getId() == id and state_adapter.getState() == state: + adapter = interfaces.IWorkflowState(version) + if adapter.getId() == id and adapter.getState() == state: result.append(version) return result @@ -32,7 +33,7 @@ def getVersionsWithAutomaticTransitions(self): if interfaces.IWorkflowInfo(version).hasAutomaticTransitions(): result.append(version) return result - + def hasVersion(self, state, id): return bool(self.getVersions(state, id)) @@ -42,10 +43,11 @@ def hasVersionId(self, id): if state_adapter.getId() == id: return True return False - + def clear(self): self.versions = [] - + + def workflowSetUp(doctest): testing.setUp(doctest) component.provideAdapter( @@ -63,7 +65,8 @@ def workflowSetUp(doctest): component.provideUtility( WorkflowVersions(), interfaces.IWorkflowVersions) - + + def test_suite(): return unittest.TestSuite(( doctest.DocFileSuite( @@ -74,4 +77,3 @@ def test_suite(): if __name__ == '__main__': unittest.main(defaultTest='test_suite') -