[Zope3-checkins] SVN: zdaemon/trunk/ Merge the py3 branch.
Marius Gedminas
cvs-admin at zope.org
Fri Feb 15 13:24:53 UTC 2013
Log message for revision 129432:
Merge the py3 branch.
svn merge -r 129325:129415 svn+ssh://svn.zope.org/repos/main/zdaemon/branches/py3 .
Changed:
_U zdaemon/trunk/
U zdaemon/trunk/CHANGES.txt
A zdaemon/trunk/MANIFEST.in
U zdaemon/trunk/bootstrap.py
U zdaemon/trunk/buildout.cfg
U zdaemon/trunk/setup.py
U zdaemon/trunk/src/zdaemon/README.txt
U zdaemon/trunk/src/zdaemon/tests/parent.py
U zdaemon/trunk/src/zdaemon/tests/tests.py
U zdaemon/trunk/src/zdaemon/tests/testuser.py
U zdaemon/trunk/src/zdaemon/tests/testzdoptions.py
U zdaemon/trunk/src/zdaemon/tests/testzdrun.py
U zdaemon/trunk/src/zdaemon/zdctl.py
U zdaemon/trunk/src/zdaemon/zdoptions.py
U zdaemon/trunk/src/zdaemon/zdrun.py
A zdaemon/trunk/tox.ini
-=-
Property changes on: zdaemon/trunk
___________________________________________________________________
Modified: svn:ignore
- .installed.cfg
build
develop-eggs
dist
eggs
bin
parts
+ .coverage
.installed.cfg
.tox
build
coverage
develop-eggs
dist
eggs
bin
parts
*.xml
Modified: zdaemon/trunk/CHANGES.txt
===================================================================
--- zdaemon/trunk/CHANGES.txt 2013-02-15 12:53:25 UTC (rev 129431)
+++ zdaemon/trunk/CHANGES.txt 2013-02-15 13:24:52 UTC (rev 129432)
@@ -2,6 +2,13 @@
Change log
==========
+4.0.0 (unreleased)
+==================
+
+- Added tox support and MANIFEST.in for proper releasing.
+
+- Drop Python 2.4 and 2.5 support.
+
3.0.5 (2012-11-27)
==================
Copied: zdaemon/trunk/MANIFEST.in (from rev 129415, zdaemon/branches/py3/MANIFEST.in)
===================================================================
--- zdaemon/trunk/MANIFEST.in (rev 0)
+++ zdaemon/trunk/MANIFEST.in 2013-02-15 13:24:52 UTC (rev 129432)
@@ -0,0 +1,9 @@
+include *.rst
+include *.txt
+include tox.ini
+include bootstrap.py
+include buildout.cfg
+
+recursive-include src *
+
+global-exclude *.pyc
Modified: zdaemon/trunk/bootstrap.py
===================================================================
--- zdaemon/trunk/bootstrap.py 2013-02-15 12:53:25 UTC (rev 129431)
+++ zdaemon/trunk/bootstrap.py 2013-02-15 13:24:52 UTC (rev 129432)
@@ -16,51 +16,150 @@
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.
-
-$Id: bootstrap.py 68905 2006-06-29 10:46:56Z jim $
"""
-import os, shutil, sys, tempfile, urllib2
+import os, shutil, sys, tempfile
+from optparse import OptionParser
tmpeggs = tempfile.mkdtemp()
-ez = {}
-exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
- ).read() in ez
-ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+usage = '''\
+[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
-import pkg_resources
+Bootstraps a buildout-based project.
-is_jython = sys.platform.startswith('java')
+Simply run this script in a directory containing a buildout.cfg, using the
+Python that you want bin/buildout to use.
-if is_jython:
- import subprocess
+Note that by using --setup-source and --download-base to point to
+local resources, you can keep this script from going over the network.
+'''
-ws = pkg_resources.working_set
+parser = OptionParser(usage=usage)
+parser.add_option("-v", "--version", help="use a specific zc.buildout version")
-if is_jython:
- assert subprocess.Popen(
- [sys.executable] + ['-c',
- 'from setuptools.command.easy_install import main; main()',
- '-mqNxd', tmpeggs, 'zc.buildout'],
- env = dict(
- PYTHONPATH =
- ws.find(pkg_resources.Requirement.parse('setuptools')).location
- ),
- ).wait() == 0
+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"))
-else:
- assert os.spawnle(
- os.P_WAIT, sys.executable, sys.executable,
- '-c', 'from setuptools.command.easy_install import main; main()',
- '-mqNxd', tmpeggs, 'zc.buildout',
- {'PYTHONPATH':
- ws.find(pkg_resources.Requirement.parse('setuptools')).location
- },
- ) == 0
+options, args = parser.parse_args()
+
+######################################################################
+# load/install distribute
+
+to_reload = False
+try:
+ import pkg_resources, setuptools
+ if not hasattr(pkg_resources, '_distribute'):
+ to_reload = True
+ raise ImportError
+except ImportError:
+ ez = {}
+
+ try:
+ from urllib.request import urlopen
+ except ImportError:
+ from urllib2 import urlopen
+
+ exec(urlopen('http://python-distribute.org/distribute_setup.py').read(), ez)
+ setup_args = dict(to_dir=tmpeggs, download_delay=0, no_fake=True)
+ ez['use_setuptools'](**setup_args)
+
+ if to_reload:
+ reload(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)
+
+######################################################################
+# 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])
+
+distribute_path = ws.find(
+ pkg_resources.Requirement.parse('distribute')).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):
+ 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=[distribute_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=distribute_path)) != 0:
+ raise Exception(
+ "Failed to execute command:\n%s",
+ repr(cmd)[1:-1])
+
+######################################################################
+# Import and run buildout
+
ws.add_entry(tmpeggs)
-ws.require('zc.buildout')
+ws.require(requirement)
import zc.buildout.buildout
-zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+
+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)
Modified: zdaemon/trunk/buildout.cfg
===================================================================
--- zdaemon/trunk/buildout.cfg 2013-02-15 12:53:25 UTC (rev 129431)
+++ zdaemon/trunk/buildout.cfg 2013-02-15 13:24:52 UTC (rev 129432)
@@ -1,7 +1,8 @@
[buildout]
develop = .
-parts = test scripts coverage-test coverage-report
-find-links = http://download.zope.org/distribution/
+ ../ZConfig
+parts = test scripts coverage-test
+ coverage-report
[test]
recipe = zc.recipe.testrunner
@@ -10,13 +11,14 @@
[coverage-test]
recipe = zc.recipe.testrunner
eggs = ${test:eggs}
-defaults = ['--coverage', '../../coverage']
+defaults = ['--coverage', '${buildout:directory}/coverage']
[coverage-report]
recipe = zc.recipe.egg
eggs = z3c.coverage
-scripts = coverage=coverage-report
-arguments = ('coverage', 'coverage/report')
+scripts = coveragereport=coverage-report
+arguments = ('${buildout:directory}/coverage',
+ '${buildout:directory}/coverage/report')
[scripts]
recipe = zc.recipe.egg
Modified: zdaemon/trunk/setup.py
===================================================================
--- zdaemon/trunk/setup.py 2013-02-15 12:53:25 UTC (rev 129431)
+++ zdaemon/trunk/setup.py 2013-02-15 13:24:52 UTC (rev 129432)
@@ -11,10 +11,11 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
+import os
-version = '0.0.0'
+tests_require = ['zope.testing', 'zope.testrunner', 'manuel', 'mock',
+ 'zc.customdoctests']
-import os
entry_points = """
[console_scripts]
@@ -24,6 +25,21 @@
def read(*rnames):
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+def alltests():
+ import os
+ import sys
+ import unittest
+ # use the zope.testrunner machinery to find all the
+ # test suites we've put under ourselves
+ import zope.testrunner.find
+ import zope.testrunner.options
+ here = os.path.abspath(os.path.join(os.path.dirname(__file__), 'src'))
+ args = sys.argv[:]
+ defaults = ["--test-path", here]
+ options = zope.testrunner.options.get_options(args, defaults)
+ suites = list(zope.testrunner.find.find_suites(options))
+ return unittest.TestSuite(suites)
+
try:
from setuptools import setup
setuptools_options = dict(
@@ -31,17 +47,17 @@
entry_points=entry_points,
include_package_data = True,
install_requires=["ZConfig"],
- extras_require=dict(
- test=['zope.testing', 'manuel', 'zc.customdoctests', 'mock']),
+ extras_require=dict(test=tests_require),
+ test_suite='__main__.alltests',
+ tests_require=tests_require
)
except ImportError:
from distutils.core import setup
setuptools_options = {}
-name = "zdaemon"
setup(
- name=name,
- version = version,
+ name="zdaemon",
+ version = "4.0.0dev",
url="http://www.python.org/pypi/zdaemon",
license="ZPL 2.1",
description=
@@ -65,8 +81,15 @@
'Intended Audience :: Developers',
'Intended Audience :: System Administrators',
'License :: OSI Approved :: Zope Public License',
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 2',
+ 'Programming Language :: Python :: 2.6',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.3',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Operating System :: POSIX',
'Topic :: Utilities',
- 'Operating System :: POSIX',
],
**setuptools_options)
Modified: zdaemon/trunk/src/zdaemon/README.txt
===================================================================
--- zdaemon/trunk/src/zdaemon/README.txt 2013-02-15 12:53:25 UTC (rev 129431)
+++ zdaemon/trunk/src/zdaemon/README.txt 2013-02-15 13:24:52 UTC (rev 129432)
@@ -83,7 +83,8 @@
.. -> text
- >>> open('conf', 'w').write(text)
+ >>> with open('conf', 'w') as file:
+ ... _ = file.write(text)
Now, we can run with the -C option to read the configuration file:
@@ -115,7 +116,8 @@
.. -> text
- >>> open('conf', 'w').write(text.replace('/tmp', tmpdir))
+ >>> with open('conf', 'w') as file:
+ ... _ = file.write(text.replace('/tmp', tmpdir))
Now, when we run zdaemon:
@@ -149,7 +151,8 @@
.. -> text
- >>> open('conf', 'w').write(text.replace('/tmp', tmpdir))
+ >>> with open('conf', 'w') as file:
+ ... _ = file.write(text.replace('/tmp', tmpdir))
Then we can pass the program argument on the command line:
@@ -184,7 +187,8 @@
.. -> text
- >>> open('conf', 'w').write(text.replace('/tmp', tmpdir))
+ >>> with open('conf', 'w') as file:
+ ... _ = file.write(text.replace('/tmp', tmpdir))
Now, when we run the command, we'll see out environment settings reflected:
@@ -215,9 +219,9 @@
Let's look at an example. We'll have a long-running process that
simple tails a data file:
- >>> f = open('data', 'w', 0)
+ >>> f = open('data', 'w', 1)
>>> import os
- >>> f.write('rec 1\n'); os.fsync(f.fileno())
+ >>> _ = f.write('rec 1\n'); f.flush(); os.fsync(f.fileno())
Now, here's out zdaemon configuration::
@@ -228,7 +232,8 @@
.. -> text
- >>> open('conf', 'w').write(text)
+ >>> with open('conf', 'w') as file:
+ ... _ = file.write(text)
Now we'll start:
@@ -243,7 +248,8 @@
After waiting a bit, if we look at the log file, it contains the tail output:
- >>> open('log').read()
+ >>> with open('log') as file:
+ ... file.read()
'rec 1\n'
We can rotate the transcript log by renaming it and telling zdaemon to
@@ -254,7 +260,7 @@
If we generate more output:
- >>> f.write('rec 2\n'); os.fsync(f.fileno())
+ >>> _ = f.write('rec 2\n'); f.flush(); os.fsync(f.fileno())
.. Wait a little bit to make sure tail has a chance to work
@@ -263,7 +269,8 @@
The output will appear in the old file, because zdaemon still has it
open:
- >>> open('log.1').read()
+ >>> with open('log.1') as file:
+ ... file.read()
'rec 1\nrec 2\n'
Now, if we tell zdaemon to reopen the file:
@@ -272,7 +279,7 @@
and generate some output:
- >>> f.write('rec 3\n'); os.fsync(f.fileno())
+ >>> _ = f.write('rec 3\n'); f.flush(); os.fsync(f.fileno())
.. Wait a little bit to make sure tail has a chance to work
@@ -280,12 +287,18 @@
the output will show up in the new file, not the old:
- >>> open('log').read()
+ >>> with open('log') as file:
+ ... file.read()
'rec 3\n'
- >>> open('log.1').read()
+ >>> with open('log.1') as file:
+ ... file.read()
'rec 1\nrec 2\n'
+Close files:
+
+ >>> f.close()
+
Start test program and timeout
==============================
Modified: zdaemon/trunk/src/zdaemon/tests/parent.py
===================================================================
--- zdaemon/trunk/src/zdaemon/tests/parent.py 2013-02-15 12:53:25 UTC (rev 129431)
+++ zdaemon/trunk/src/zdaemon/tests/parent.py 2013-02-15 13:24:52 UTC (rev 129432)
@@ -18,15 +18,13 @@
zctldir = os.path.dirname(dir)
zdrun = os.path.join(zctldir, 'zdrun.py')
donothing = os.path.join(tmp, 'donothing.sh')
- fd = os.open(donothing, os.O_WRONLY|os.O_CREAT, 0700)
- os.write(fd, donothing_contents)
+ fd = os.open(donothing, os.O_WRONLY|os.O_CREAT, 0o700)
+ os.write(fd, donothing_contents.encode())
os.close(fd)
args = [sys.executable, zdrun]
args += ['-d', '-b', '10', '-s', os.path.join(tmp, 'testsock'),
'-x', '0,2', '-z', dir, donothing]
flag = os.P_NOWAIT
- #cmd = ' '.join([sys.executable] + args)
- #print cmd
os.spawnvpe(flag, args[0], args,
dict(os.environ, PYTHONPATH=':'.join(sys.path)),
)
Modified: zdaemon/trunk/src/zdaemon/tests/tests.py
===================================================================
--- zdaemon/trunk/src/zdaemon/tests/tests.py 2013-02-15 12:53:25 UTC (rev 129431)
+++ zdaemon/trunk/src/zdaemon/tests/tests.py 2013-02-15 13:24:52 UTC (rev 129432)
@@ -11,19 +11,23 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
+from __future__ import print_function
import doctest
-import manuel.capture
-import manuel.doctest
-import manuel.testing
import os
import re
+import signal
import shutil
import subprocess
import sys
import tempfile
import unittest
+from contextlib import contextmanager
+
import ZConfig
+import manuel.capture
+import manuel.doctest
+import manuel.testing
import zc.customdoctests
import zdaemon
from zope.testing import renormalizing
@@ -38,6 +42,7 @@
zdaemon_loc = os.path.dirname(os.path.dirname(zdaemon.__file__))
zconfig_loc = os.path.dirname(os.path.dirname(ZConfig.__file__))
+
def write(name, text):
with open(name, 'w') as f:
f.write(text)
@@ -46,6 +51,7 @@
with open(name) as f:
return f.read()
+
def make_sure_non_daemon_mode_doesnt_hang_when_program_exits():
"""
The whole awhile bit that waits for a program to start
@@ -84,12 +90,11 @@
def allow_duplicate_arguments():
"""
+ Wrapper scripts will often embed configuration arguments. This could
+ cause a problem when zdaemon reinvokes itself, passing it's own set of
+ configuration arguments. To deal with this, we'll allow duplicate
+ arguments that have the same values.
-Wrapper scripts will often embed configuration arguments. This could
-cause a problem when zdaemon reinvokes itself, passing it's own set of
-configuration arguments. To deal with this, we'll allow duplicate
-arguments that have the same values.
-
>>> write('conf',
... '''
... <runner>
@@ -105,7 +110,7 @@
. .
daemon process stopped
-"""
+ """
def test_stop_timeout():
r"""
@@ -153,7 +158,7 @@
... '''
... import time
... time.sleep(1)
- ... open('x', 'w')
+ ... open('x', 'w').close()
... time.sleep(99)
... ''')
@@ -186,7 +191,7 @@
... '''
... import time
... time.sleep(1)
- ... open('x', 'w')
+ ... open('x', 'w').close()
... time.sleep(99)
... ''')
@@ -269,7 +274,7 @@
True
"""
-def nonzeo_exit_on_program_failure():
+def nonzero_exit_on_program_failure():
"""
>>> write('conf',
... '''
@@ -322,44 +327,70 @@
workspace = tempfile.mkdtemp()
td.append(lambda : shutil.rmtree(workspace))
os.chdir(workspace)
- open('zdaemon', 'w').write(zdaemon_template % dict(
- python = sys.executable,
- zdaemon = zdaemon_loc,
- ZConfig = zconfig_loc,
- ))
- os.chmod('zdaemon', 0755)
- test.globs.update(dict(
- system = system
- ))
+ write('zdaemon', zdaemon_template % dict(
+ python=sys.executable,
+ zdaemon=zdaemon_loc,
+ ZConfig=zconfig_loc,
+ ))
+ os.chmod('zdaemon', 0o755)
+ test.globs['system'] = system
def tearDown(test):
for f in test.globs['_td']:
f()
+
+class Timeout(BaseException):
+ pass
+
+
+ at contextmanager
+def timeout(seconds):
+ this_frame = sys._getframe()
+ def raiseTimeout(signal, frame):
+ # the if statement here is meant to prevent an exception in the
+ # finally: clause before clean up can take place
+ if frame is not this_frame:
+ raise Timeout('timed out after %s seconds' % seconds)
+ try:
+ prev_handler = signal.signal(signal.SIGALRM, raiseTimeout)
+ except ValueError:
+ # signal only works in main thread
+ # let's ignore the request for a timeout and hope the test doesn't hang
+ yield
+ else:
+ try:
+ signal.alarm(seconds)
+ yield
+ finally:
+ signal.alarm(0)
+ signal.signal(signal.SIGALRM, prev_handler)
+
+
def system(command, input='', quiet=False, echo=False):
if echo:
- print command
+ print(command)
p = subprocess.Popen(
command, shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
- if input:
- p.stdin.write(input)
- p.stdin.close()
- data = p.stdout.read()
+ with timeout(60):
+ data = p.communicate(input)[0]
if not quiet:
- print data,
+ print(data.decode(), end='')
r = p.wait()
if r:
- print 'Failed:', r
+ print('Failed:', r)
+
def checkenv(match):
match = [a for a in match.group(1).split('\n')[:-1]
if a.split('=')[0] in ('HOME', 'LD_LIBRARY_PATH')]
match.sort()
return '\n'.join(match) + '\n'
+
zdaemon_template = """#!%(python)s
import sys
@@ -387,20 +418,18 @@
checker=renormalizing.RENormalizing([
(re.compile('pid=\d+'), 'pid=NNN'),
(re.compile('(\. )+\.?'), '<BLANKLINE>'),
- ])
- ),
+ ])),
manuel.testing.TestSuite(
- manuel.doctest.Manuel(
- parser=zc.customdoctests.DocTestParser(
- ps1='sh>',
- transform=lambda s: 'system("%s")\n' % s.rstrip()
- ),
- checker=README_checker,
- ) +
- manuel.doctest.Manuel(checker=README_checker) +
- manuel.capture.Manuel(),
- '../README.txt',
- setUp=setUp, tearDown=tearDown,
- ),
+ manuel.doctest.Manuel(
+ parser=zc.customdoctests.DocTestParser(
+ ps1='sh>',
+ transform=lambda s: 'system("%s")\n' % s.rstrip()
+ ),
+ checker=README_checker,
+ ) +
+ manuel.doctest.Manuel(checker=README_checker) +
+ manuel.capture.Manuel(),
+ '../README.txt',
+ setUp=setUp, tearDown=tearDown),
))
Modified: zdaemon/trunk/src/zdaemon/tests/testuser.py
===================================================================
--- zdaemon/trunk/src/zdaemon/tests/testuser.py 2013-02-15 12:53:25 UTC (rev 129431)
+++ zdaemon/trunk/src/zdaemon/tests/testuser.py 2013-02-15 13:24:52 UTC (rev 129432)
@@ -50,7 +50,7 @@
... except SystemExit:
... pass
... else:
- ... print 'oops'
+ ... print('oops')
... # doctest: +ELLIPSIS
Error: only root can use -u USER to change users
For help, use ... -h
Modified: zdaemon/trunk/src/zdaemon/tests/testzdoptions.py
===================================================================
--- zdaemon/trunk/src/zdaemon/tests/testzdoptions.py 2013-02-15 12:53:25 UTC (rev 129431)
+++ zdaemon/trunk/src/zdaemon/tests/testzdoptions.py 2013-02-15 13:24:52 UTC (rev 129432)
@@ -19,7 +19,6 @@
import tempfile
import shutil
import unittest
-from StringIO import StringIO
import ZConfig
import zdaemon
@@ -27,6 +26,12 @@
ZDOptions, RunnerOptions,
existing_parent_directory, existing_parent_dirpath)
+try:
+ from StringIO import StringIO
+except:
+ # Python 3 support.
+ from io import StringIO
+
class ZDOptionsTestBase(unittest.TestCase):
OptionsClass = ZDOptions
@@ -47,7 +52,7 @@
sys.stderr = StringIO()
try:
options.realize(args)
- except SystemExit, err:
+ except SystemExit as err:
self.assertEqual(err.code, 2)
else:
self.fail("SystemExit expected")
@@ -96,7 +101,7 @@
options.realize([arg],**kw)
finally:
self.restore_streams()
- except SystemExit, err:
+ except SystemExit as err:
self.assertEqual(err.code, 0)
else:
self.fail("%s didn't call sys.exit()" % repr(arg))
@@ -199,7 +204,7 @@
L = []
options.add("setting", None, "a:", "append=", handler=L.append)
options.realize(["-a2", "--append", "3"])
- self.assert_(options.setting is None)
+ self.assertTrue(options.setting is None)
self.assertEqual(L, ["2", "3"])
def test_handler_with_bad_value(self):
@@ -307,7 +312,7 @@
options.realize([])
finally:
self.restore_streams()
- except SystemExit, e:
+ except SystemExit as e:
self.assertEqual(e.code, 2)
else:
self.fail("expected SystemExit")
@@ -368,7 +373,7 @@
options = self.OptionsClass()
path = os.path.join(self.root, 'will-be-created')
options.realize(["-z", path])
- self.assertEquals(path, options.directory)
+ self.assertEqual(path, options.directory)
socket = os.path.join(path, 'socket')
options = self.OptionsClass()
options.realize(["-s", socket])
Modified: zdaemon/trunk/src/zdaemon/tests/testzdrun.py
===================================================================
--- zdaemon/trunk/src/zdaemon/tests/testzdrun.py 2013-02-15 12:53:25 UTC (rev 129431)
+++ zdaemon/trunk/src/zdaemon/tests/testzdrun.py 2013-02-15 13:24:52 UTC (rev 129432)
@@ -1,4 +1,5 @@
"""Test suite for zdrun.py."""
+from __future__ import print_function
import os
import sys
@@ -9,7 +10,11 @@
import unittest
import socket
-from StringIO import StringIO
+try:
+ from StringIO import StringIO
+except:
+ # Python 3 support.
+ from io import StringIO
import ZConfig
@@ -105,7 +110,7 @@
def testCmdclassOverride(self):
class MyCmd(zdctl.ZDCmd):
def do_sproing(self, rest):
- print rest
+ print(rest)
self._run("-p echo sproing expected", cmdclass=MyCmd)
self.expect = "expected\n"
@@ -146,8 +151,8 @@
options = zdrun.ZDRunOptions()
try:
options.realize(["-h"], doc=zdrun.__doc__)
- except SystemExit, err:
- self.failIf(err.code)
+ except SystemExit as err:
+ self.assertEqual(err.code, 0)
else:
self.fail("SystemExit expected")
self.expect = zdrun.__doc__
@@ -217,7 +222,7 @@
)
)
# Wait for it to start, but no longer than a minute.
- deadline = time.time() + 6000
+ deadline = time.time() + 60
is_started = False
while time.time() < deadline:
response = send_action('status\n', zdrun_socket)
@@ -226,14 +231,16 @@
else:
is_started = True
break
- self.assert_(is_started,
- "spawned process failed to start in a minute")
+ self.assertTrue(is_started,
+ "spawned process failed to start in a minute")
# Kill it, and wait a little to ensure it's dead.
os.kill(zdctlpid, signal.SIGINT)
time.sleep(0.25)
# Make sure the child is still responsive.
- response = send_action('status\n', zdrun_socket)
- self.assert_(response is not None and '\n' in response)
+ response = send_action('status\n', zdrun_socket,
+ raise_on_error=True)
+ self.assertTrue(b'\n' in response,
+ 'no newline in response: ' + repr(response))
# Kill the process.
send_action('exit\n', zdrun_socket)
finally:
@@ -277,8 +284,8 @@
for i in range(5):
if not os.path.exists(path):
time.sleep(0.1)
- self.assert_(os.path.exists(path))
- self.assert_(not os.access(path, os.W_OK))
+ self.assertTrue(os.path.exists(path))
+ self.assertTrue(not os.access(path, os.W_OK))
finally:
if os.path.exists(path):
os.remove(path)
@@ -305,7 +312,7 @@
sys.stdout = self.save_stdout
sys.stderr = self.save_stderr
if err:
- print >>sys.stderr, err,
+ print(err, end='', file=sys.stderr)
self.assertEqual(self.expect, got)
super(TestRunnerDirectory, self).tearDown()
@@ -319,7 +326,7 @@
def testCtlRunDirectoryCreation(self):
path = os.path.join(self.root, 'rundir')
self.run_ctl(['-z', path, '-p', self.cmd])
- self.assert_(os.path.exists(path))
+ self.assertTrue(os.path.exists(path))
def testCtlRunDirectoryCreationFromConfigFile(self):
path = os.path.join(self.root, 'rundir')
@@ -328,7 +335,7 @@
config = self.writeConfig(
'<runner>\n%s\n</runner>' % '\n'.join(options))
self.run_ctl(['-C', config])
- self.assert_(os.path.exists(path))
+ self.assertTrue(os.path.exists(path))
def testCtlRunDirectoryCreationOnlyOne(self):
path = os.path.join(self.root, 'rundir', 'not-created')
@@ -342,13 +349,13 @@
def testCtlSocketDirectoryCreation(self):
path = os.path.join(self.root, 'rundir', 'sock')
self.run_ctl(['-s', path, '-p', self.cmd])
- self.assert_(os.path.exists(os.path.dirname(path)))
+ self.assertTrue(os.path.exists(os.path.dirname(path)))
def testCtlSocketDirectoryCreationRelativePath(self):
path = os.path.join('rundir', 'sock')
self.run_ctl(['-s', path, '-p', self.cmd])
- self.assert_(os.path.exists(os.path.dirname(os.path.join(os.getcwd(),
- path))))
+ self.assertTrue(os.path.exists(os.path.dirname(os.path.join(os.getcwd(),
+ path))))
def testCtlSocketDirectoryCreationOnlyOne(self):
path = os.path.join(self.root, 'rundir', 'not-created', 'sock')
@@ -366,7 +373,7 @@
config = self.writeConfig(
'<runner>\n%s\n</runner>' % '\n'.join(options))
self.run_ctl(['-C', config])
- self.assert_(os.path.exists(path))
+ self.assertTrue(os.path.exists(path))
def testCtlSocketDirectoryCreationFromConfigFileRelativePath(self):
path = 'rel-rundir'
@@ -375,11 +382,12 @@
config = self.writeConfig(
'<runner>\n%s\n</runner>' % '\n'.join(options))
self.run_ctl(['-C', config])
- self.assert_(os.path.exists(os.path.join(os.getcwd(), path)))
+ self.assertTrue(os.path.exists(os.path.join(os.getcwd(), path)))
def writeConfig(self, config):
config_file = os.path.join(self.root, 'config')
- open(config_file, 'w').write(config)
+ with open(config_file, 'w') as f:
+ f.write(config)
return config_file
def testDirectoryChown(self):
@@ -407,7 +415,7 @@
self.assertEqual([('chown', path, 27, 28)], calls)
-def send_action(action, sockname):
+def send_action(action, sockname, raise_on_error=False):
"""Send an action to the zdrun server and return the response.
Return None if the server is not up or any other error happened.
@@ -415,9 +423,9 @@
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
try:
sock.connect(sockname)
- sock.send(action + "\n")
+ sock.send(action.encode() + b"\n")
sock.shutdown(1) # We're not writing any more
- response = ""
+ response = b""
while 1:
data = sock.recv(1000)
if not data:
@@ -425,13 +433,17 @@
response += data
sock.close()
return response
- except socket.error, msg:
+ except socket.error as msg:
if str(msg) == 'AF_UNIX path too long':
# MacOS has apparent small limits on the length of a UNIX
# domain socket filename, we want to make MacOS users aware
# of the actual problem
raise
+ if raise_on_error:
+ raise
return None
+ finally:
+ sock.close()
def test_suite():
suite = unittest.TestSuite()
Modified: zdaemon/trunk/src/zdaemon/zdctl.py
===================================================================
--- zdaemon/trunk/src/zdaemon/zdctl.py 2013-02-15 12:53:25 UTC (rev 129431)
+++ zdaemon/trunk/src/zdaemon/zdctl.py 2013-02-15 13:24:52 UTC (rev 129432)
@@ -37,6 +37,7 @@
Actions are commands like "start", "stop" and "status". Use the
action "help" to find out about available actions.
"""
+from __future__ import print_function
import os
import os.path
@@ -127,9 +128,9 @@
args = eval(s, {"__builtins__": {}})
program = self.options.program
if args[:len(program)] != program:
- print "WARNING! zdrun is managing a different program!"
- print "our program =", program
- print "daemon's args =", args
+ print("WARNING! zdrun is managing a different program!")
+ print("our program =", program)
+ print("daemon's args =", args)
if options.configroot is not None:
env = getattr(options.configroot, 'environment', None)
@@ -216,18 +217,19 @@
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
try:
sock.connect(self.options.sockname)
- sock.send(action + "\n")
+ sock.send(action.encode() + b"\n")
sock.shutdown(1) # We're not writing any more
- response = ""
+ response = b""
while 1:
data = sock.recv(1000)
if not data:
break
response += data
+ return response.decode()
+ except socket.error as msg:
+ return None
+ finally:
sock.close()
- return response
- except socket.error, msg:
- return None
zd_testing = 0
def get_status(self):
@@ -266,21 +268,21 @@
if self.get_status():
was_running = True
elif (was_running or n > 10) and not cond(n):
- print "\ndaemon manager not running"
+ print("\ndaemon manager not running")
return 1
except KeyboardInterrupt:
- print "^C"
- print "\n" + msg % self.__dict__
+ print("^C")
+ print("\n" + msg % self.__dict__)
def help_help(self):
- print "help -- Print a list of available actions."
- print "help <action> -- Print help for <action>."
+ print("help -- Print a list of available actions.")
+ print("help <action> -- Print help for <action>.")
def _start_cond(self, n):
if (n > self.options.start_timeout):
- print '\nProgram took too long to start'
+ print('\nProgram took too long to start')
sys.exit(1)
return self.zd_pid and not self.zd_testing
@@ -315,7 +317,7 @@
elif not self.zd_pid:
self.send_action("start")
else:
- print "daemon process already running; pid=%d" % self.zd_pid
+ print("daemon process already running; pid=%d" % self.zd_pid)
return
if self.options.daemon:
return self.awhile(
@@ -349,30 +351,30 @@
return args
def help_start(self):
- print "start -- Start the daemon process."
- print " If it is already running, do nothing."
+ print("start -- Start the daemon process.")
+ print(" If it is already running, do nothing.")
def do_stop(self, arg):
self.get_status()
if not self.zd_up:
- print "daemon manager not running"
+ print("daemon manager not running")
elif not self.zd_pid:
- print "daemon process not running"
+ print("daemon process not running")
else:
self.send_action("stop")
self.awhile(lambda n: not self.zd_pid, "daemon process stopped")
def do_reopen_transcript(self, arg):
if not self.zd_up:
- print "daemon manager not running"
+ print("daemon manager not running")
elif not self.zd_pid:
- print "daemon process not running"
+ print("daemon process not running")
else:
self.send_action("reopen_transcript")
def help_stop(self):
- print "stop -- Stop the daemon process."
- print " If it is not running, do nothing."
+ print("stop -- Stop the daemon process.")
+ print(" If it is not running, do nothing.")
def do_restart(self, arg):
self.get_status()
@@ -385,7 +387,7 @@
"daemon process restarted, pid=%(zd_pid)d")
def help_restart(self):
- print "restart -- Stop and then start the daemon process."
+ print("restart -- Stop and then start the daemon process.")
def do_kill(self, arg):
if not arg:
@@ -394,149 +396,149 @@
try:
sig = int(arg)
except: # int() can raise any number of exceptions
- print "invalid signal number", `arg`
+ print("invalid signal number", repr(arg))
return
self.get_status()
if not self.zd_pid:
- print "daemon process not running"
+ print("daemon process not running")
return
- print "kill(%d, %d)" % (self.zd_pid, sig)
+ print("kill(%d, %d)" % (self.zd_pid, sig))
try:
os.kill(self.zd_pid, sig)
- except os.error, msg:
- print "Error:", msg
+ except os.error as msg:
+ print("Error:", msg)
else:
- print "signal %d sent to process %d" % (sig, self.zd_pid)
+ print("signal %d sent to process %d" % (sig, self.zd_pid))
def help_kill(self):
- print "kill [sig] -- Send signal sig to the daemon process."
- print " The default signal is SIGTERM."
+ print("kill [sig] -- Send signal sig to the daemon process.")
+ print(" The default signal is SIGTERM.")
def do_wait(self, arg):
self.awhile(lambda n: not self.zd_pid, "daemon process stopped")
self.do_status()
def help_wait(self):
- print "wait -- Wait for the daemon process to exit."
+ print("wait -- Wait for the daemon process to exit.")
def do_status(self, arg=""):
status = 0
if arg not in ["", "-l"]:
- print "status argument must be absent or -l"
+ print("status argument must be absent or -l")
return 1
self.get_status()
if not self.zd_up:
- print "daemon manager not running"
+ print("daemon manager not running")
status = 3
elif not self.zd_pid:
- print "daemon manager running; daemon process not running"
+ print("daemon manager running; daemon process not running")
else:
- print "program running; pid=%d" % self.zd_pid
+ print("program running; pid=%d" % self.zd_pid)
if arg == "-l" and self.zd_status:
- print self.zd_status
+ print(self.zd_status)
return status
def help_status(self):
- print "status [-l] -- Print status for the daemon process."
- print " With -l, show raw status output as well."
+ print("status [-l] -- Print status for the daemon process.")
+ print(" With -l, show raw status output as well.")
def do_show(self, arg):
if not arg:
arg = "options"
try:
method = getattr(self, "show_" + arg)
- except AttributeError, err:
- print err
+ except AttributeError as err:
+ print(err)
self.help_show()
return
method()
def show_options(self):
- print "zdctl/zdrun options:"
- print "schemafile: ", repr(self.options.schemafile)
- print "configfile: ", repr(self.options.configfile)
- print "zdrun: ", repr(self.options.zdrun)
- print "python: ", repr(self.options.python)
- print "program: ", repr(self.options.program)
- print "backofflimit:", repr(self.options.backofflimit)
- print "daemon: ", repr(self.options.daemon)
- print "forever: ", repr(self.options.forever)
- print "sockname: ", repr(self.options.sockname)
- print "exitcodes: ", repr(self.options.exitcodes)
- print "user: ", repr(self.options.user)
+ print("zdctl/zdrun options:")
+ print("schemafile: ", repr(self.options.schemafile))
+ print("configfile: ", repr(self.options.configfile))
+ print("zdrun: ", repr(self.options.zdrun))
+ print("python: ", repr(self.options.python))
+ print("program: ", repr(self.options.program))
+ print("backofflimit:", repr(self.options.backofflimit))
+ print("daemon: ", repr(self.options.daemon))
+ print("forever: ", repr(self.options.forever))
+ print("sockname: ", repr(self.options.sockname))
+ print("exitcodes: ", repr(self.options.exitcodes))
+ print("user: ", repr(self.options.user))
umask = self.options.umask
if not umask:
# Here we're just getting the current umask so we can report it:
- umask = os.umask(0777)
+ umask = os.umask(0o777)
os.umask(umask)
- print "umask: ", oct(umask)
- print "directory: ", repr(self.options.directory)
- print "logfile: ", repr(self.options.logfile)
+ print("umask: ", oct(umask))
+ print("directory: ", repr(self.options.directory))
+ print("logfile: ", repr(self.options.logfile))
def show_python(self):
- print "Python info:"
+ print("Python info:")
version = sys.version.replace("\n", "\n ")
- print "Version: ", version
- print "Platform: ", sys.platform
- print "Executable: ", repr(sys.executable)
- print "Arguments: ", repr(sys.argv)
- print "Directory: ", repr(os.getcwd())
- print "Path:"
+ print("Version: ", version)
+ print("Platform: ", sys.platform)
+ print("Executable: ", repr(sys.executable))
+ print("Arguments: ", repr(sys.argv))
+ print("Directory: ", repr(os.getcwd()))
+ print("Path:")
for dir in sys.path:
- print " " + repr(dir)
+ print(" " + repr(dir))
def show_all(self):
self.show_options()
- print
+ print()
self.show_python()
def help_show(self):
- print "show options -- show zdctl options"
- print "show python -- show Python version and details"
- print "show all -- show all of the above"
+ print("show options -- show zdctl options")
+ print("show python -- show Python version and details")
+ print("show all -- show all of the above")
def do_logtail(self, arg):
if not arg:
arg = self.options.logfile
if not arg:
- print "No default log file specified; use logtail <logfile>"
+ print("No default log file specified; use logtail <logfile>")
return
try:
helper = TailHelper(arg)
helper.tailf()
except KeyboardInterrupt:
- print
- except IOError, msg:
- print msg
- except OSError, msg:
- print msg
+ print()
+ except IOError as msg:
+ print(msg)
+ except OSError as msg:
+ print(msg)
def help_logtail(self):
- print "logtail [logfile] -- Run tail -f on the given logfile."
- print " A default file may exist."
- print " Hit ^C to exit this mode."
+ print("logtail [logfile] -- Run tail -f on the given logfile.")
+ print(" A default file may exist.")
+ print(" Hit ^C to exit this mode.")
def do_foreground(self, arg):
self.get_status()
pid = self.zd_pid
if pid:
- print "To run the program in the foreground, please stop it first."
+ print("To run the program in the foreground, please stop it first.")
return
program = self.options.program + self.options.args[1:]
- print " ".join(program)
+ print(" ".join(program))
sys.stdout.flush()
try:
os.spawnlp(os.P_WAIT, program[0], *program)
except KeyboardInterrupt:
- print
+ print()
def do_fg(self, arg):
self.do_foreground(arg)
def help_foreground(self):
- print "foreground -- Run the program in the forground."
- print "fg -- an alias for foreground."
+ print("foreground -- Run the program in the forground.")
+ print("fg -- an alias for foreground.")
def help_fg(self):
self.help_foreground()
@@ -559,7 +561,7 @@
bytes_added = newsz - sz
if bytes_added < 0:
sz = 0
- print "==> File truncated <=="
+ print("==> File truncated <==")
bytes_added = newsz
if bytes_added > 0:
self.f.seek(-bytes_added, 2)
Modified: zdaemon/trunk/src/zdaemon/zdoptions.py
===================================================================
--- zdaemon/trunk/src/zdaemon/zdoptions.py 2013-02-15 12:53:25 UTC (rev 129431)
+++ zdaemon/trunk/src/zdaemon/zdoptions.py 2013-02-15 13:24:52 UTC (rev 129432)
@@ -11,9 +11,8 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-
"""Option processing for zdaemon and related code."""
-
+from __future__ import print_function
import os
import sys
import getopt
@@ -78,7 +77,7 @@
doc = "No help available."
elif doc.find("%s") > 0:
doc = doc.replace("%s", self.progname)
- print doc,
+ print(doc, end='')
sys.exit(0)
def usage(self, msg):
@@ -98,9 +97,9 @@
for n, cn in self.names_list[:]:
if n == name:
self.names_list.remove((n, cn))
- if self.default_map.has_key(name):
+ if name in self.default_map:
del self.default_map[name]
- if self.required_map.has_key(name):
+ if name in self.required_map:
del self.required_map[name]
if confname:
for n, cn in self.names_list[:]:
@@ -108,13 +107,13 @@
self.names_list.remove((n, cn))
if short:
key = "-" + short[0]
- if self.options_map.has_key(key):
+ if key in self.options_map:
del self.options_map[key]
if long:
key = "--" + long
if key[-1] == "=":
key = key[:-1]
- if self.options_map.has_key(key):
+ if key in self.options_map:
del self.options_map[key]
def add(self,
@@ -173,7 +172,7 @@
if rest not in ("", ":"):
raise ValueError("short option should be 'x' or 'x:'")
key = "-" + key
- if self.options_map.has_key(key):
+ if key in self.options_map:
raise ValueError("duplicate short option key '%s'" % key)
self.options_map[key] = (name, handler)
self.short_options.append(short)
@@ -185,7 +184,7 @@
if key[-1] == "=":
key = key[:-1]
key = "--" + key
- if self.options_map.has_key(key):
+ if key in self.options_map:
raise ValueError("duplicate long option key '%s'" % key)
self.options_map[key] = (name, handler)
self.long_options.append(long)
@@ -239,7 +238,7 @@
try:
self.options, self.args = getopt.getopt(
args, "".join(self.short_options), self.long_options)
- except getopt.error, msg:
+ except getopt.error as msg:
if raise_getopt_errs:
self.usage(msg)
@@ -253,7 +252,7 @@
if handler is not None:
try:
arg = handler(arg)
- except ValueError, msg:
+ except ValueError as msg:
self.usage("invalid value for %s %r: %s" % (opt, arg, msg))
if name and arg is not None:
if getattr(self, name) is not None:
@@ -269,12 +268,12 @@
name, handler = self.environ_map[envvar]
if name and getattr(self, name, None) is not None:
continue
- if os.environ.has_key(envvar):
+ if envvar in os.environ:
value = os.environ[envvar]
if handler is not None:
try:
value = handler(value)
- except ValueError, msg:
+ except ValueError as msg:
self.usage("invalid environment value for %s %r: %s"
% (envvar, value, msg))
if name and value is not None:
@@ -290,7 +289,7 @@
self.load_schema()
try:
self.load_configfile()
- except ZConfig.ConfigurationError, msg:
+ except ZConfig.ConfigurationError as msg:
self.usage(str(msg))
# Copy config options to attributes of self. This only fills
@@ -371,7 +370,7 @@
list_of_ints, default=[0, 2])
self.add("user", "runner.user", "u:", "user=")
self.add("umask", "runner.umask", "m:", "umask=", octal_type,
- default=022)
+ default=0o22)
self.add("directory", "runner.directory", "z:", "directory=",
existing_parent_directory)
@@ -382,7 +381,7 @@
if not arg:
return []
else:
- return map(int, arg.split(","))
+ return list(map(int, arg.split(",")))
def octal_type(arg):
return int(arg, 8)
@@ -416,12 +415,12 @@
# Stupid test program
z = ZDOptions()
z.add("program", "zdctl.program", "p:", "program=")
- print z.names_list
+ print(z.names_list)
z.realize()
names = z.names_list[:]
names.sort()
for name, confname in names:
- print "%-20s = %.56r" % (name, getattr(z, name))
+ print("%-20s = %.56r" % (name, getattr(z, name)))
if __name__ == "__main__":
__file__ = sys.argv[0]
Modified: zdaemon/trunk/src/zdaemon/zdrun.py
===================================================================
--- zdaemon/trunk/src/zdaemon/zdrun.py 2013-02-15 12:53:25 UTC (rev 129431)
+++ zdaemon/trunk/src/zdaemon/zdrun.py 2013-02-15 13:24:52 UTC (rev 129432)
@@ -135,7 +135,7 @@
except os.error:
continue
mode = st[ST_MODE]
- if mode & 0111:
+ if mode & 0o111:
break
else:
self.options.usage("can't find program %r on PATH %s" %
@@ -188,9 +188,10 @@
pass
try:
os.execv(self.filename, self.args)
- except os.error, err:
+ except os.error as err:
sys.stderr.write("can't exec %r: %s\n" %
(self.filename, err))
+ sys.stderr.flush() # just in case
finally:
os._exit(127)
# Does not return
@@ -205,7 +206,7 @@
return "no subprocess running"
try:
os.kill(self.pid, sig)
- except os.error, msg:
+ except os.error as msg:
return str(msg)
return None
@@ -251,7 +252,7 @@
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
try:
sock.bind(tempname)
- os.chmod(tempname, 0700)
+ os.chmod(tempname, 0o700)
try:
os.link(tempname, sockname)
break
@@ -261,6 +262,7 @@
# Stale socket -- delete, sleep, and try again.
msg = "Unlinking stale socket %s; sleep 1" % sockname
sys.stderr.write(msg + "\n")
+ sys.stderr.flush() # just in case
self.logger.warn(msg)
self.unlink_quietly(sockname)
sock.close()
@@ -282,17 +284,17 @@
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
try:
s.connect(self.options.sockname)
- s.send("status\n")
- data = s.recv(1000)
+ s.send(b"status\n")
+ data = s.recv(1000).decode()
s.close()
except socket.error:
pass
else:
- while data.endswith("\n"):
- data = data[:-1]
+ data = data.rstrip("\n")
msg = ("Another zrdun is already up using socket %r:\n%s" %
(self.options.sockname, data))
sys.stderr.write(msg + "\n")
+ sys.stderr.flush() # just in case
self.logger.critical(msg)
sys.exit(1)
@@ -351,7 +353,7 @@
if self.options.directory:
try:
os.chdir(self.options.directory)
- except os.error, err:
+ except os.error as err:
self.logger.warn("can't chdir into %r: %s"
% (self.options.directory, err))
else:
@@ -396,8 +398,8 @@
self.delay = time.time() + self.options.backofflimit
try:
r, w, x = select.select(r, w, x, timeout)
- except select.error, err:
- if err[0] != errno.EINTR:
+ except select.error as err:
+ if err.args[0] != errno.EINTR:
raise
r = w = x = []
if self.waitstatus:
@@ -405,14 +407,14 @@
if self.commandsocket and self.commandsocket in r:
try:
self.dorecv()
- except socket.error, msg:
+ except socket.error as msg:
self.logger.exception("socket.error in dorecv(): %s"
% str(msg))
self.commandsocket = None
if self.mastersocket in r:
try:
self.doaccept()
- except socket.error, msg:
+ except socket.error as msg:
self.logger.exception("socket.error in doaccept(): %s"
% str(msg))
self.commandsocket = None
@@ -471,7 +473,7 @@
self.commandsocket.close()
self.commandsocket = None
self.commandsocket, addr = self.mastersocket.accept()
- self.commandbuffer = ""
+ self.commandbuffer = b""
def dorecv(self):
data = self.commandsocket.recv(1000)
@@ -480,7 +482,7 @@
self.commandsocket.close()
self.commandsocket = None
self.commandbuffer += data
- if "\n" in self.commandbuffer:
+ if b"\n" in self.commandbuffer:
self.docommand()
self.commandsocket.close()
self.commandsocket = None
@@ -490,18 +492,18 @@
self.commandsocket = None
def docommand(self):
- lines = self.commandbuffer.split("\n")
+ lines = self.commandbuffer.split(b"\n")
args = lines[0].split()
if not args:
self.sendreply("Empty command")
return
- command = args[0]
+ command = args[0].decode()
methodname = "cmd_" + command
method = getattr(self, methodname, None)
if method:
- method(args)
+ method([a.decode() for a in args])
else:
- self.sendreply("Unknown command %r; 'help' for a list" % args[0])
+ self.sendreply("Unknown command %r; 'help' for a list" % command)
def cmd_start(self, args):
self.should_be_up = True
@@ -585,6 +587,7 @@
try:
if not msg.endswith("\n"):
msg = msg + "\n"
+ msg = msg.encode()
if hasattr(self.commandsocket, "sendall"):
self.commandsocket.sendall(msg)
else:
@@ -592,7 +595,7 @@
while msg:
sent = self.commandsocket.send(msg)
msg = msg[sent:]
- except socket.error, msg:
+ except socket.error as msg:
self.logger.warn("Error sending reply: %s" % str(msg))
@@ -601,11 +604,11 @@
def __init__(self, filename):
self.read_from, w = os.pipe()
os.dup2(w, 1)
- sys.stdout = sys.__stdout__ = os.fdopen(1, "a", 0)
+ sys.stdout = sys.__stdout__ = os.fdopen(1, "w", 1)
os.dup2(w, 2)
- sys.stderr = sys.__stderr__ = os.fdopen(2, "a", 0)
+ sys.stderr = sys.__stderr__ = os.fdopen(2, "w", 1)
self.filename = filename
- self.file = open(filename, 'a', 0)
+ self.file = open(filename, 'ab', 0)
self.write = self.file.write
self.lock = threading.Lock()
thread = threading.Thread(target=self.copy)
@@ -626,7 +629,7 @@
def reopen(self):
self.lock.acquire()
self.file.close()
- self.file = open(self.filename, 'a', 0)
+ self.file = open(self.filename, 'ab', 0)
self.write = self.file.write
self.lock.release()
@@ -685,7 +688,7 @@
def get_path():
"""Return a list corresponding to $PATH, or a default."""
path = ["/bin", "/usr/bin", "/usr/local/bin"]
- if os.environ.has_key("PATH"):
+ if "PATH" in os.environ:
p = os.environ["PATH"]
if p:
path = p.split(os.pathsep)
Copied: zdaemon/trunk/tox.ini (from rev 129415, zdaemon/branches/py3/tox.ini)
===================================================================
--- zdaemon/trunk/tox.ini (rev 0)
+++ zdaemon/trunk/tox.ini 2013-02-15 13:24:52 UTC (rev 129432)
@@ -0,0 +1,30 @@
+[tox]
+envlist = py26,py27,py33
+
+[testenv]
+commands =
+ python setup.py test -q
+# without explicit deps, setup.py test will download a bunch of eggs into $PWD
+deps =
+ zc.customdoctests
+ zope.testing
+ zope.testrunner
+ manuel
+ mock
+
+
+[testenv:coverage]
+basepython =
+ python2.7
+commands =
+# The installed version messes up nose's test discovery / coverage reporting
+# So, we uninstall that from the environment, and then install the editable
+# version, before running nosetests.
+ pip uninstall -y zdaemon
+ pip install -e .
+ nosetests --with-xunit --with-xcoverage
+deps =
+ {[testenv]deps}
+ nose
+ coverage
+ nosexcover
More information about the Zope3-Checkins
mailing list