Merge pull request #800 from moreati/0.2-backport

Prepare 0.2.10rc1
0.2-release v0.2.10rc1
Alex Willmer 4 years ago committed by GitHub
commit 9d404e0b32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -16,7 +16,7 @@ batches = [
]
batches.extend(
['docker pull %s' % (ci_lib.image_for_distro(distro),)]
['docker pull %s' % (ci_lib.image_for_distro(distro),), 'sleep 1']
for distro in ci_lib.DISTROS
)

@ -37,9 +37,6 @@ with ci_lib.Fold('docker_setup'):
with ci_lib.Fold('job_setup'):
# Don't set -U as that will upgrade Paramiko to a non-2.6 compatible version.
run("pip install -q ansible==%s", ci_lib.ANSIBLE_VERSION)
os.chdir(TESTS_DIR)
os.chmod('../data/docker/mitogen__has_sudo_pubkey.key', int('0600', 7))
@ -69,8 +66,6 @@ with ci_lib.Fold('job_setup'):
run("sudo apt-get update")
run("sudo apt-get install -y sshpass")
run("bash -c 'sudo ln -vfs /usr/lib/python2.7/plat-x86_64-linux-gnu/_sysconfigdata_nd.py /usr/lib/python2.7 || true'")
run("bash -c 'sudo ln -vfs /usr/lib/python2.7/plat-x86_64-linux-gnu/_sysconfigdata_nd.py $VIRTUAL_ENV/lib/python2.7 || true'")
with ci_lib.Fold('ansible'):
playbook = os.environ.get('PLAYBOOK', 'all.yml')

@ -14,17 +14,25 @@ steps:
# stuff into. The virtualenv can probably be removed again, but this was a
# hard-fought battle and for now I am tired of this crap.
- script: |
# need wheel before building virtualenv because of bdist_wheel and setuptools deps
# Mac's System Integrity Protection prevents symlinking /usr/bin
# and Azure isn't allowing disabling it apparently: https://developercommunityapi.westus.cloudapp.azure.com/idea/558702/allow-disabling-sip-on-microsoft-hosted-macos-agen.html
# the || will activate when running python3 tests
# TODO: get python3 tests passing
(sudo ln -fs /usr/bin/python$(python.version) /usr/bin/python &&
/usr/bin/python -m pip install -U pip wheel setuptools &&
/usr/bin/python -m pip install -U virtualenv &&
/usr/bin/python -m virtualenv /tmp/venv -p /usr/bin/python$(python.version)) ||
(sudo /usr/bin/python$(python.version) -m pip install -U pip wheel setuptools &&
/usr/bin/python$(python.version) -m venv /tmp/venv)
set -o errexit
set -o nounset
set -o pipefail
set -x
# Ensure virtualenv is in system-wide $PATH on OSX, for Ansible test tasks
# that use it, e.g. regression/issue_152__virtualenv_python_fails.yml
if [[ -d /Library/Frameworks/Python.framework/Versions/2.7/bin ]]; then
echo $PATH
which python
python -m pip install -U pip virtualenv
ln -s /Library/Frameworks/Python.framework/Versions/2.7/bin/virtualenv /usr/local/bin/virtualenv
virtualenv --version
fi
# Create virtualenv using desired Python version, to run the testcases
python$(python.version) -m pip install -U pip wheel setuptools virtualenv
python$(python.version) -m virtualenv /tmp/venv -p python$(python.version)
echo "##vso[task.prependpath]/tmp/venv/bin"
displayName: activate venv
@ -37,3 +45,5 @@ steps:
- script: .ci/$(MODE)_tests.py
displayName: "Run $(MODE)_tests.py"
env:
NOCOVERAGE: 1

@ -13,10 +13,10 @@ jobs:
strategy:
matrix:
Mito27_27:
python.version: '2.7.18'
python.version: '2.7'
MODE: mitogen
Ans288_27:
python.version: '2.7.18'
python.version: '2.7'
MODE: localhost_ansible
VER: 2.8.8

@ -80,12 +80,28 @@ if 'TRAVIS_HOME' in os.environ:
# -----------------
def _argv(s, *args):
"""Interpolate a command line using *args, return an argv style list.
>>> _argv('git commit -m "Use frobnicate 2.0 (fixes #%d)"', 1234)
['git', commit', '-m', 'Use frobnicate 2.0 (fixes #1234)']
"""
if args:
s %= args
return shlex.split(s)
def run(s, *args, **kwargs):
""" Run a command, with arguments, and print timing information
>>> rc = run('echo "%s %s"', 'foo', 'bar')
Running: ['/usr/bin/time', '--', 'echo', 'foo bar']
foo bar
0.00user 0.00system 0:00.00elapsed ?%CPU (0avgtext+0avgdata 1964maxresident)k
0inputs+0outputs (0major+71minor)pagefaults 0swaps
Finished running: ['/usr/bin/time', '--', 'echo', 'foo bar']
>>> rc
0
"""
argv = ['/usr/bin/time', '--'] + _argv(s, *args)
print('Running: %s' % (argv,))
try:
@ -98,12 +114,36 @@ def run(s, *args, **kwargs):
return ret
def run_batches(batches):
combine = lambda batch: 'set -x; ' + (' && '.join(
def combine(batch):
"""
>>> combine(['ls -l', 'echo foo'])
'set -x; ( ls -l; ) && ( echo foo; )'
"""
return 'set -x; ' + (' && '.join(
'( %s; )' % (cmd,)
for cmd in batch
))
def run_batches(batches):
""" Run shell commands grouped into batches, showing an execution trace.
Raise AssertionError if any command has exits with a non-zero status.
>>> run_batches([['echo foo', 'true']])
+ echo foo
foo
+ true
>>> run_batches([['true', 'echo foo'], ['false']])
+ true
+ echo foo
foo
+ false
Traceback (most recent call last):
File "...", line ..., in <module>
File "...", line ..., in run_batches
AssertionError
"""
procs = [
subprocess.Popen(combine(batch), shell=True)
for batch in batches
@ -112,12 +152,28 @@ def run_batches(batches):
def get_output(s, *args, **kwargs):
"""
Print and run command line s, %-interopolated using *args. Return stdout.
>>> s = get_output('echo "%s %s"', 'foo', 'bar')
Running: ['echo', 'foo bar']
>>> s
'foo bar\n'
"""
argv = _argv(s, *args)
print('Running: %s' % (argv,))
return subprocess.check_output(argv, **kwargs)
def exists_in_path(progname):
"""
Return True if proganme exists in $PATH.
>>> exists_in_path('echo')
True
>>> exists_in_path('kwyjibo') # Only found in North American cartoons
False
"""
return any(os.path.exists(os.path.join(dirname, progname))
for dirname in os.environ['PATH'].split(os.pathsep))
@ -132,6 +188,18 @@ class TempDir(object):
class Fold(object):
"""
Bracket a section of stdout with travis_fold markers.
This allows the section to be collapsed or expanded in Travis CI web UI.
>>> with Fold('stage 1'):
... print('Frobnicate the frobnitz')
...
travis_fold:start:stage 1
Frobnicate the frobnitz
travis_fold:end:stage 1
"""
def __init__(self, name):
self.name = name
@ -171,6 +239,8 @@ os.environ['PYTHONPATH'] = '%s:%s' % (
)
def get_docker_hostname():
"""Return the hostname where the docker daemon is running.
"""
url = os.environ.get('DOCKER_HOST')
if url in (None, 'http+docker://localunixsocket'):
return 'localhost'
@ -180,10 +250,34 @@ def get_docker_hostname():
def image_for_distro(distro):
return 'mitogen/%s-test' % (distro.partition('-')[0],)
"""Return the container image name or path for a test distro name.
The returned value is suitable for use with `docker pull`.
>>> image_for_distro('centos5')
'public.ecr.aws/n5z0e8q9/centos5-test'
>>> image_for_distro('centos5-something_custom')
'public.ecr.aws/n5z0e8q9/centos5-test'
"""
return 'public.ecr.aws/n5z0e8q9/%s-test' % (distro.partition('-')[0],)
def make_containers(name_prefix='', port_offset=0):
"""
>>> import pprint
>>> BASE_PORT=2200; DISTROS=['debian', 'centos6']
>>> pprint.pprint(make_containers())
[{'distro': 'debian',
'hostname': 'localhost',
'name': 'target-debian-1',
'port': 2201,
'python_path': '/usr/bin/python'},
{'distro': 'centos6',
'hostname': 'localhost',
'name': 'target-centos6-2',
'port': 2202,
'python_path': '/usr/bin/python'}]
"""
docker_hostname = get_docker_hostname()
firstbit = lambda s: (s+'-').split('-')[0]
secondbit = lambda s: (s+'-').split('-')[1]
@ -256,6 +350,14 @@ def get_interesting_procs(container_name=None):
def start_containers(containers):
"""Run docker containers in the background, with sshd on specified ports.
>>> containers = start_containers([
... {'distro': 'debian', 'hostname': 'localhost',
... 'name': 'target-debian-1', 'port': 2201,
... 'python_path': '/usr/bin/python'},
... ])
"""
if os.environ.get('KEEP'):
return

@ -20,12 +20,15 @@ with ci_lib.Fold('unit_tests'):
with ci_lib.Fold('job_setup'):
# Don't set -U as that will upgrade Paramiko to a non-2.6 compatible version.
run("pip install -q virtualenv ansible==%s", ci_lib.ANSIBLE_VERSION)
os.chmod(KEY_PATH, int('0600', 8))
# NOTE: sshpass v1.06 causes errors so pegging to 1.05 -> "msg": "Error when changing password","out": "passwd: DS error: eDSAuthFailed\n",
# there's a checksum error with "brew install http://git.io/sshpass.rb" though, so installing manually
if not ci_lib.exists_in_path('sshpass'):
run("brew install http://git.io/sshpass.rb")
os.system("curl -O -L https://sourceforge.net/projects/sshpass/files/sshpass/1.05/sshpass-1.05.tar.gz && \
tar xvf sshpass-1.05.tar.gz && \
cd sshpass-1.05 && \
./configure && \
sudo make install")
with ci_lib.Fold('machine_prep'):

@ -43,12 +43,4 @@ if ci_lib.have_apt():
.format(pv=os.environ['PYTHONVERSION'])
])
if ci_lib.have_docker():
batches.extend(
['docker pull %s' % (ci_lib.image_for_distro(distro),)]
for distro in ci_lib.DISTROS
)
ci_lib.run_batches(batches)

@ -16,6 +16,9 @@ cache:
- directories:
- /home/travis/virtualenv
env:
- NOCOVERAGE=1
install:
- grep -Erl git-lfs\|couchdb /etc/apt | sudo xargs rm -v
- .ci/${MODE}_install.py

@ -1,4 +1,4 @@
Copyright 2019, David Wilson
Copyright 2021, the Mitogen authors
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

@ -5,8 +5,8 @@
![](https://i.imgur.com/eBM6LhJ.gif)
[![Total alerts](https://img.shields.io/lgtm/alerts/g/dw/mitogen.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/dw/mitogen/alerts/)
[![Total alerts](https://img.shields.io/lgtm/alerts/g/mitogen-hq/mitogen.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/mitogen-hq/mitogen/alerts/)
[![Build Status](https://travis-ci.org/dw/mitogen.svg?branch=master)](https://travis-ci.org/dw/mitogen)
[![Build Status](https://api.travis-ci.com/mitogen-hq/mitogen.svg?branch=master)](https://api.travis-ci.com/mitogen-hq/mitogen)
[![Pipelines Status](https://dev.azure.com/dw-mitogen/Mitogen/_apis/build/status/dw.mitogen?branchName=master)](https://dev.azure.com/dw-mitogen/Mitogen/_build/latest?definitionId=1?branchName=master)
[![Pipelines Status](https://dev.azure.com/mitogen-hq/mitogen/_apis/build/status/mitogen-hq.mitogen?branchName=master)](https://dev.azure.com/mitogen-hq/mitogen/_build/latest?definitionId=1&branchName=master)

@ -145,7 +145,7 @@ Testimonials
Noteworthy Differences
----------------------
* Ansible 2.3-2.8 are supported along with Python 2.6, 2.7, 3.6 and 3.7. Verify
* Ansible 2.3-2.9 are supported along with Python 2.6, 2.7, 3.6 and 3.7. Verify
your installation is running one of these versions by checking ``ansible
--version`` output.

@ -14,18 +14,23 @@ Release Notes
}
</style>
To avail of fixes in an unreleased version, please download a ZIP file
`directly from GitHub <https://github.com/dw/mitogen/>`_.
v0.2.10 (unreleased)
--------------------
To avail of fixes in an unreleased version, please download a ZIP file
`directly from GitHub <https://github.com/dw/mitogen/>`_.
* :gh:issue:`597` mitogen does not support Ansible 2.8 Python interpreter detection
* :gh:issue:`655` wait_for_connection gives errors
* :gh:issue:`672` cannot perform relative import error
* :gh:issue:`673` mitogen fails on RHEL8 server with bash /usr/bin/python: No such file or directory
* :gh:issue:`676` mitogen fail to run playbook without “/usr/bin/python” on target host
* :gh:issue:`716` fetch fails with "AttributeError: 'ShellModule' object has no attribute 'tmpdir'"
* :gh:issue:`756` ssh connections with `check_host_keys='accept'` would
timeout, when using recent OpenSSH client versions.
* :gh:issue:`758` fix initilialisation of callback plugins in test suite, to
to address a `KeyError` in
* :gh:issue:`758` fix initilialisation of callback plugins in test suite, to address a `KeyError` in
:method:`ansible.plugins.callback.CallbackBase.v2_runner_on_start`
* :gh:issue:`775` Add msvcrt to the default module deny list
v0.2.9 (2019-11-02)

@ -7,7 +7,7 @@ import mitogen
VERSION = '%s.%s.%s' % mitogen.__version__
author = u'Network Genomics'
copyright = u'2019, Network Genomics'
copyright = u'2021, the Mitogen authors'
exclude_patterns = ['_build', '.venv']
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinxcontrib.programoutput', 'domainrefs']

@ -35,7 +35,7 @@ be expected. On the slave, it is built dynamically during startup.
#: Library version as a tuple.
__version__ = (0, 2, 9)
__version__ = (0, 2, 10, 'rc', 1)
#: This is :data:`False` in slave contexts. Previously it was used to prevent

@ -1269,6 +1269,13 @@ class Importer(object):
# a negative round-trip.
'builtins',
'__builtin__',
# On some Python releases (e.g. 3.8, 3.9) the subprocess module tries
# to import of this Windows-only builtin module.
'msvcrt',
# Python 2.x module that was renamed to _thread in 3.x.
# This entry avoids a roundtrip on 2.x -> 3.x.
'thread',
# org.python.core imported by copy, pickle, xml.sax; breaks Jython, but
@ -3860,7 +3867,7 @@ class ExternalContext(object):
else:
core_src_fd = self.config.get('core_src_fd', 101)
if core_src_fd:
fp = os.fdopen(core_src_fd, 'rb', 1)
fp = os.fdopen(core_src_fd, 'rb', 0)
try:
core_src = fp.read()
# Strip "ExternalContext.main()" call from last line.

@ -1,3 +1,6 @@
[bdist_wheel]
universal=1
[coverage:run]
branch = true
source =

@ -37,29 +37,46 @@ def grep_version():
for line in fp:
if line.startswith('__version__'):
_, _, s = line.partition('=')
return '.'.join(map(str, eval(s)))
return '%i.%i.%i%s%i' % eval(s)
def long_description():
here = os.path.dirname(__file__)
readme_path = os.path.join(here, 'README.md')
with open(readme_path) as fp:
readme = fp.read()
return readme
setup(
name = 'mitogen',
version = grep_version(),
description = 'Library for writing distributed self-replicating programs.',
long_description = long_description(),
long_description_content_type='text/markdown',
author = 'David Wilson',
license = 'New BSD',
url = 'https://github.com/dw/mitogen/',
url = 'https://github.com/mitogen-hq/mitogen/',
packages = find_packages(exclude=['tests', 'examples']),
python_requires='>=2.4, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4',
zip_safe = False,
classifiers = [
'Environment :: Console',
'Intended Audience :: System Administrators',
'License :: OSI Approved :: BSD License',
'Operating System :: MacOS :: MacOS X',
'Operating System :: POSIX',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.4',
'Programming Language :: Python :: 2.5',
'Programming Language :: Python :: 2.6',
'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 :: 3.9',
'Programming Language :: Python :: Implementation :: CPython',
'Topic :: System :: Distributed Computing',
'Topic :: System :: Systems Administration',

@ -51,10 +51,14 @@
shell: whoami > /tmp/delegate_to.yml.txt
delegate_to: localhost
become: true
tags:
- requires_local_sudo
- name: "delegate_to, sudo"
assert:
that: "lookup('file', '/tmp/delegate_to.yml.txt') == 'root'"
tags:
- requires_local_sudo
- name: "delegate_to, sudo"
file:
@ -62,6 +66,8 @@
state: absent
delegate_to: localhost
become: true
tags:
- requires_local_sudo
#
@ -71,10 +77,14 @@
shell: whoami > /tmp/delegate_to.yml.txt
connection: local
become: true
tags:
- requires_local_sudo
- name: "connection:local, sudo"
assert:
that: "lookup('file', '/tmp/delegate_to.yml.txt') == 'root'"
tags:
- requires_local_sudo
- name: "connection:local, sudo"
file:
@ -82,3 +92,5 @@
state: absent
connection: local
become: true
tags:
- requires_local_sudo

@ -15,7 +15,7 @@
content: |
#!/bin/bash
export CUSTOM_INTERPRETER=1
exec python2.7 "$@"
exec python "$@"
- custom_python_detect_environment:
vars:

@ -1,4 +1,4 @@
paramiko==2.3.2 # Last 2.6-compat version.
hdrhistogram==0.6.1
PyYAML==3.11; python_version < '2.7'
PyYAML==3.13; python_version >= '2.7'
PyYAML==5.3.1; python_version >= '2.7' # Latest release (Jan 2021)

@ -308,7 +308,6 @@ if sys.version_info > (2, 6):
# AttributeError: module 'html.parser' has no attribute
# 'HTMLParseError'
#
import pkg_resources._vendor.six
from django.utils.six.moves import html_parser as _html_parser
_html_parser.HTMLParseError = Exception

@ -3,7 +3,7 @@ coverage==4.5.1
Django==1.6.11 # Last version supporting 2.6.
mock==2.0.0
pytz==2018.5
cffi==1.11.2 # Random pin to try and fix pyparser==2.18 not having effect
cffi==1.14.3 # Random pin to try and fix pyparser==2.18 not having effect
pycparser==2.18 # Last version supporting 2.6.
faulthandler==3.1; python_version < '3.3' # used by testlib
pytest-catchlog==1.2.2

@ -103,6 +103,18 @@ if hasattr(subprocess.Popen, 'terminate'):
Popen__terminate = subprocess.Popen.terminate
def threading__thread_is_alive(thread):
"""Return whether the thread is alive (Python version compatibility shim).
On Python >= 3.8 thread.isAlive() is deprecated (removed in Python 3.9).
On Python <= 2.5 thread.is_alive() isn't present (added in Python 2.6).
"""
try:
return thread.is_alive()
except AttributeError:
return thread.isAlive()
def wait_for_port(
host,
port,
@ -334,7 +346,9 @@ class TestCase(unittest2.TestCase):
for thread in threading.enumerate():
name = thread.getName()
# Python 2.4: enumerate() may return stopped threads.
assert (not thread.isAlive()) or name in self.ALLOWED_THREADS, \
assert \
not threading__thread_is_alive(thread) \
or name in self.ALLOWED_THREADS, \
'Found thread %r still running after tests.' % (name,)
counts[name] = counts.get(name, 0) + 1

@ -31,14 +31,14 @@ class RunWithRouterTest(testlib.TestCase):
def test_run_with_broker(self):
router = mitogen.utils.run_with_router(func0)
self.assertIsInstance(router, mitogen.master.Router)
self.assertFalse(router.broker._thread.isAlive())
self.assertFalse(testlib.threading__thread_is_alive(router.broker._thread))
class WithRouterTest(testlib.TestCase):
def test_with_broker(self):
router = func()
self.assertIsInstance(router, mitogen.master.Router)
self.assertFalse(router.broker._thread.isAlive())
self.assertFalse(testlib.threading__thread_is_alive(router.broker._thread))
class Dict(dict): pass

@ -1,44 +1,89 @@
# This file is a local convenience. It is not a substitute for the full CI
# suite, and does not cover the full range of Python versions for Mitogen.
# I use this on Ubuntu 20.04, with the following additions
#
# sudo add-apt-repository ppa:deadsnakes/ppa
# sudo apt update
# sudo apt install python3.5 python3.6 python3.7 python3.9 tox libsasl2-dev libldap2-dev libssl-dev ssh-pass
# Last version to support each python version
#
# tox vir'env pip ansible coverage
# ========== ======== ======== ======== ======== ========
# python2.4 1.4 1.8 1.1 ???
# python2.5 1.6.1 1.9.1 1.3.1 ???
# python2.6 2.9.1 15.2.0 9.0.3 2.6.20 4.5.4
[tox]
envlist =
init,
py26,
py27,
py35,
py36,
py37,
py{27,36,39}-mode_ansible,
py{27,36,39}-mode_mitogen,
py{27,36,39}-mode_mitogen-distro_centos7,
report,
requires =
tox-factor
[testenv]
usedevelop = True
deps =
-r{toxinidir}/dev_requirements.txt
-r{toxinidir}/tests/ansible/requirements.txt
basepython =
py26: python2.6
py27: python2.7
py36: python3.6
py37: python3.7
py38: python3.8
py39: python3.9
commands_pre =
mode_ansible: {toxinidir}/.ci/ansible_install.py
mode_debops_common: {toxinidir}/.ci/debops_common_install.py
mode_mitogen: {toxinidir}/.ci/mitogen_install.py
commands =
{posargs:bash run_tests}
whitelist_externals =
bash
mode_ansible: {toxinidir}/.ci/ansible_tests.py
mode_debops_common: {toxinidir}/.ci/debops_common_tests.py
mode_mitogen: {toxinidir}/.ci/mitogen_tests.py
passenv =
ANSIBLE_*
HOME
setenv =
ANSIBLE_SKIP_TAGS = requires_local_sudo
NOCOVERAGE_ERASE = 1
NOCOVERAGE_REPORT = 1
ansible2.3: VER=2.3.3.0
ansible2.4: VER=2.4.6.0
ansible2.8: VER=2.8.3
ansible2.9: VER=2.9.6
ansible2.10: VER=2.10.0
distro_centos5: DISTRO=centos5
distro_centos6: DISTRO=centos6
distro_centos7: DISTRO=centos7
distro_debian: DISTRO=debian
distro_debianpy3: DISTRO=debian-py3
distros_centos5: DISTROS=centos5
distros_debian: DISTROS=debian
mode_ansible: MODE=ansible
mode_debops_common: MODE=debops_common
mode_mitogen: MODE=mitogen
strategy_linear: STRATEGY=linear
[testenv:init]
basepython = python3
commands =
coverage erase
deps =
coverage
coverage==4.5.4
[testenv:report]
basepython = python3
commands =
coverage html
echo "coverage report is at file://{toxinidir}/htmlcov/index.html"
deps =
coverage
coverage==4.5.4
whitelist_externals =
echo
[testenv:docs]
basepython = python
basepython = python3
changedir = docs
commands =
sphinx-build -W -b html -d {envtmpdir}/doctrees . {envtmpdir}/html

Loading…
Cancel
Save