We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Setup cron job to test against dependencies from source
Travis (and possibly appveyor too) allow the creation of cron jobs. Some of the ETS packages now have cron jobs setup to test against dependencies which are installed from source - instead of testing against the released versions.

See examples : 

- https://github.com/enthought/envisage/pull/162
- https://github.com/enthought/traitsui/pull/914
- https://github.com/enthought/pyface/pull/549

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ci/edmtool.py`
Content:
```
1 #
2 #  Copyright (c) 2017, Enthought, Inc.
3 #  All rights reserved.
4 #
5 #  This software is provided without warranty under the terms of the BSD
6 #  license included in enthought/LICENSE.txt and may be redistributed only
7 #  under the conditions described in the aforementioned license.  The license
8 #  is also available online at http://www.enthought.com/licenses/BSD.txt
9 #
10 #  Thanks for using Enthought open source!
11 #
12 """
13 Tasks for Test Runs
14 ===================
15 This file is intended to be used with a python environment with the
16 click library to automate the process of setting up test environments
17 and running the test within them.  This improves repeatability and
18 reliability of tests be removing many of the variables around the
19 developer's particular Python environment.  Test environment setup and
20 package management is performed using `EDM http://docs.enthought.com/edm/`_
21 
22 To use this to run you tests, you will need to install EDM and click
23 into your working environment.  You will also need to have git
24 installed to access required source code from github repositories.
25 
26 You can then do::
27     python edmtool.py install --runtime=... --toolkit=...
28 to create a test environment from the current codebase and::
29     python edmtool.py test --runtime=... --toolkit=...
30 to run tests in that environment.  You can remove the environment with::
31     python edmtool.py cleanup --runtime=... --toolkit=...
32 
33 If you make changes you will either need to remove and re-install the
34 environment or manually update the environment using ``edm``, as
35 the install performs a ``python setup.py install`` rather than a ``develop``,
36 so changes in your code will not be automatically mirrored in the test
37 environment.  You can update with a command like::
38     edm run --environment ... -- python setup.py install
39 You can run all three tasks at once with::
40     python edmtool.py test_clean --runtime=... --toolkit=...
41 which will create, install, run tests, and then clean-up the environment.  And
42 you can run tests in all supported runtimes and toolkits (with cleanup)
43 using::
44     python edmtool.py test_all
45 
46 Currently supported runtime values are ``3.6``, and currently
47 supported toolkits are ``null``, ``pyqt``, ``pyqt5`` and ``pyside2``.  Not all
48 combinations of toolkits and runtimes will work, but the tasks will fail with
49 a clear error if that is the case. Tests can still be run via the usual means
50 in other environments if that suits a developer's purpose.
51 
52 Changing This File
53 ------------------
54 To change the packages installed during a test run, change the dependencies
55 variable below.  To install a package from github, or one which is not yet
56 available via EDM, add it to the `ci/requirements.txt` file (these will be
57 installed by `pip`).
58 
59 Other changes to commands should be a straightforward change to the listed
60 commands for each task. See the EDM documentation for more information about
61 how to run commands within an EDM enviornment.
62 """
63 import glob
64 import os
65 import subprocess
66 import sys
67 from shutil import rmtree, copy as copyfile
68 from tempfile import mkdtemp
69 from contextlib import contextmanager
70 
71 import click
72 
73 supported_combinations = {
74     '3.6': {'pyside2', 'pyqt', 'pyqt5', 'null'},
75 }
76 
77 dependencies = {
78     "six",
79     "mock",
80     "numpy",
81     "pandas",
82     "pygments",
83     "pyparsing",
84     "cython",
85     # Needed to install enable from source
86     "swig",
87 }
88 
89 extra_dependencies = {
90     'pyside2': set(),  # pyside2 is pip-installed during the install step
91     'pyqt': {'pyqt'},
92     'pyqt5': {'pyqt5'},
93     'null': set()
94 }
95 
96 environment_vars = {
97     'pyside2': {'ETS_TOOLKIT': 'qt4', 'QT_API': 'pyside2'},
98     'pyqt': {'ETS_TOOLKIT': 'qt4', 'QT_API': 'pyqt'},
99     'pyqt5': {'ETS_TOOLKIT': 'qt4', 'QT_API': 'pyqt5'},
100     'null': {'ETS_TOOLKIT': 'null.image'},
101 }
102 
103 
104 def normalize(name):
105     return name.replace("_", "-")
106 
107 
108 @click.group(context_settings={"token_normalize_func": normalize})
109 def cli():
110     pass
111 
112 
113 @cli.command()
114 @click.option('--runtime', default='3.6')
115 @click.option('--toolkit', default='null')
116 @click.option('--environment', default=None)
117 def install(runtime, toolkit, environment):
118     """ Install project and dependencies into a clean EDM environment.
119     """
120     parameters = get_parameters(runtime, toolkit, environment)
121     parameters['packages'] = ' '.join(
122         dependencies | extra_dependencies.get(toolkit, set()))
123     # edm commands to setup the development environment
124     commands = [
125         "edm environments create {environment} --force --version={runtime}",
126         "edm install -y -e {environment} {packages}",
127         ("edm run -e {environment} -- pip install -r ci/requirements.txt"
128          " --no-dependencies"),
129         # Note that enable dependencies will be installed implicitly using pip
130         ("edm run -e {environment} -- "
131          "pip install git+https://git@github.com/enthought/enable.git"),
132         "edm run -e {environment} -- pip install . --no-deps",
133     ]
134     # pip install pyside2, because we don't have it in EDM yet
135     if toolkit == 'pyside2':
136         commands.append(
137             "edm run -e {environment} -- pip install pyside2==5.11"
138         )
139     
140     click.echo("Creating environment '{environment}'".format(**parameters))
141     execute(commands, parameters)
142     click.echo('Done install')
143 
144 
145 @cli.command()
146 @click.option('--runtime', default='3.6')
147 @click.option('--toolkit', default='null')
148 @click.option('--environment', default=None)
149 def test(runtime, toolkit, environment):
150     """ Run the test suite in a given environment with the specified toolkit.
151     """
152     parameters = get_parameters(runtime, toolkit, environment)
153     environ = environment_vars.get(toolkit, {}).copy()
154 
155     environ['PYTHONUNBUFFERED'] = "1"
156     commands = [
157         "edm run -e {environment} -- coverage run -m unittest discover -v chaco"
158     ]
159 
160     cwd = os.getcwd()
161 
162     # We run in a tempdir to avoid accidentally picking up wrong traitsui
163     # code from a local dir.  We need to ensure a good .coveragerc is in
164     # that directory, plus coverage has a bug that means a non-local coverage
165     # file doesn't get populated correctly.
166     click.echo("Running tests in '{environment}'".format(**parameters))
167     with do_in_tempdir(files=['.coveragerc'], capture_files=['./.coverage*']):
168         os.environ.update(environ)
169         execute(commands, parameters)
170 
171     click.echo('Done test')
172 
173 
174 @cli.command()
175 @click.option('--runtime', default='3.6')
176 @click.option('--toolkit', default='null')
177 @click.option('--environment', default=None)
178 def cleanup(runtime, toolkit, environment):
179     """ Remove a development environment.
180     """
181     parameters = get_parameters(runtime, toolkit, environment)
182     commands = [
183         "edm run -e {environment} -- python setup.py clean",
184         "edm environments remove {environment} --purge -y",
185     ]
186     click.echo("Cleaning up environment '{environment}'".format(**parameters))
187     execute(commands, parameters)
188     click.echo('Done cleanup')
189 
190 
191 @cli.command()
192 @click.option('--runtime', default='3.6')
193 @click.option('--toolkit', default='null')
194 def test_clean(runtime, toolkit):
195     """ Run tests in a clean environment, cleaning up afterwards
196     """
197     args = ['--toolkit={}'.format(toolkit),
198             '--runtime={}'.format(runtime)]
199     try:
200         install(args=args, standalone_mode=False)
201         test(args=args, standalone_mode=False)
202     finally:
203         cleanup(args=args, standalone_mode=False)
204 
205 
206 @cli.command()
207 @click.option('--runtime', default='3.6')
208 @click.option('--toolkit', default='null')
209 @click.option('--environment', default=None)
210 def update(runtime, toolkit, environment):
211     """ Update/Reinstall package into environment.
212     """
213     parameters = get_parameters(runtime, toolkit, environment)
214     commands = [
215         "edm run -e {environment} -- python setup.py install"]
216     click.echo("Re-installing in  '{environment}'".format(**parameters))
217     execute(commands, parameters)
218     click.echo('Done update')
219 
220 
221 @cli.command()
222 def test_all():
223     """ Run test_clean across all supported environment combinations.
224     """
225     for runtime, toolkits in supported_combinations.items():
226         for toolkit in toolkits:
227             args = ['--toolkit={}'.format(toolkit),
228                     '--runtime={}'.format(runtime)]
229             test_clean(args, standalone_mode=True)
230 
231 
232 # ----------------------------------------------------------------------------
233 # Utility routines
234 # ----------------------------------------------------------------------------
235 
236 def get_parameters(runtime, toolkit, environment):
237     """Set up parameters dictionary for format() substitution
238     """
239     parameters = {'runtime': runtime, 'toolkit': toolkit,
240                   'environment': environment}
241     if toolkit not in supported_combinations[runtime]:
242         msg = ("Python {runtime!r}, toolkit {toolkit!r}, "
243                "not supported by test environments ({available})")
244         available = ", ".join(
245             repr(tk) for tk in sorted(supported_combinations[runtime])
246         )
247         raise RuntimeError(msg.format(available=available, **parameters))
248     if environment is None:
249         tmpl = 'chaco-test-{runtime}-{toolkit}'
250         environment = tmpl.format(**parameters)
251         parameters['environment'] = environment
252     return parameters
253 
254 
255 @contextmanager
256 def do_in_tempdir(files=(), capture_files=()):
257     """ Create a temporary directory, cleaning up after done.
258     Creates the temporary directory, and changes into it.  On exit returns to
259     original directory and removes temporary dir.
260     Parameters
261     ----------
262     files : sequence of filenames
263         Files to be copied across to temporary directory.
264     capture_files : sequence of filenames
265         Files to be copied back from temporary directory.
266     """
267     path = mkdtemp()
268     old_path = os.getcwd()
269 
270     # send across any files we need
271     for filepath in files:
272         click.echo('copying file to tempdir: {}'.format(filepath))
273         copyfile(filepath, path)
274 
275     os.chdir(path)
276     try:
277         yield path
278         # retrieve any result files we want
279         for pattern in capture_files:
280             for filepath in glob.iglob(pattern):
281                 click.echo('copying file back: {}'.format(filepath))
282                 copyfile(filepath, old_path)
283     finally:
284         os.chdir(old_path)
285         rmtree(path)
286 
287 
288 def execute(commands, parameters):
289     for command in commands:
290         print("[EXECUTING]", command.format(**parameters))
291         try:
292             subprocess.check_call(command.format(**parameters).split())
293         except subprocess.CalledProcessError:
294             sys.exit(1)
295 
296 
297 if __name__ == '__main__':
298     cli()
299
```

Path: `chaco/__init__.py`
Content:
```
1 #  Copyright (c) 2005-2014 by Enthought, Inc.
2 #  All rights reserved.
3 """ Two-dimensional plotting application toolkit.
4     Part of the Chaco project of the Enthought Tool Suite.
5 """
6 from ._version import full_version as __version__  # noqa
7 
8 __requires__ = [
9    'enable',
10    'six'
11 ]
12
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/chaco/__init__.py b/chaco/__init__.py
--- a/chaco/__init__.py
+++ b/chaco/__init__.py
@@ -6,6 +6,10 @@
 from ._version import full_version as __version__  # noqa
 
 __requires__ = [
+   'traits',
+   'traitsui',
+   'pyface',
+   'numpy',
    'enable',
    'six'
 ]
diff --git a/ci/edmtool.py b/ci/edmtool.py
--- a/ci/edmtool.py
+++ b/ci/edmtool.py
@@ -79,13 +79,27 @@
     "mock",
     "numpy",
     "pandas",
+    "pyface",
     "pygments",
     "pyparsing",
+    "traits",
+    "traitsui",
     "cython",
+    "enable",
     # Needed to install enable from source
     "swig",
 }
 
+# Dependencies we install from source for cron tests
+source_dependencies = {
+    "enable",
+    "pyface",
+    "traits",
+    "traitsui",
+}
+
+github_url_fmt = "git+http://github.com/enthought/{0}.git#egg={0}"
+
 extra_dependencies = {
     'pyside2': set(),  # pyside2 is pip-installed during the install step
     'pyqt': {'pyqt'},
@@ -114,7 +128,12 @@
 @click.option('--runtime', default='3.6')
 @click.option('--toolkit', default='null')
 @click.option('--environment', default=None)
-def install(runtime, toolkit, environment):
+@click.option(
+    "--source/--no-source",
+    default=False,
+    help="Install ETS packages from source",
+)
+def install(runtime, toolkit, environment, source):
     """ Install project and dependencies into a clean EDM environment.
     """
     parameters = get_parameters(runtime, toolkit, environment)
@@ -126,9 +145,6 @@
         "edm install -y -e {environment} {packages}",
         ("edm run -e {environment} -- pip install -r ci/requirements.txt"
          " --no-dependencies"),
-        # Note that enable dependencies will be installed implicitly using pip
-        ("edm run -e {environment} -- "
-         "pip install git+https://git@github.com/enthought/enable.git"),
         "edm run -e {environment} -- pip install . --no-deps",
     ]
     # pip install pyside2, because we don't have it in EDM yet
@@ -139,6 +155,26 @@
     
     click.echo("Creating environment '{environment}'".format(**parameters))
     execute(commands, parameters)
+
+    if source:
+        # Remove EDM ETS packages and install them from source
+        cmd_fmt = (
+            "edm plumbing remove-package "
+            "--environment {environment} --force "
+        )
+        commands = [cmd_fmt + source_pkg for source_pkg in source_dependencies]
+        execute(commands, parameters)
+        source_pkgs = [
+            github_url_fmt.format(pkg) for pkg in source_dependencies
+        ]
+        commands = [
+            "python -m pip install {pkg} --no-deps".format(pkg=pkg)
+            for pkg in source_pkgs
+        ]
+        commands = [
+            "edm run -e {environment} -- " + command for command in commands
+        ]
+        execute(commands, parameters)
     click.echo('Done install')

{"golden_diff": "diff --git a/chaco/__init__.py b/chaco/__init__.py\n--- a/chaco/__init__.py\n+++ b/chaco/__init__.py\n@@ -6,6 +6,10 @@\n from ._version import full_version as __version__  # noqa\n \n __requires__ = [\n+   'traits',\n+   'traitsui',\n+   'pyface',\n+   'numpy',\n    'enable',\n    'six'\n ]\ndiff --git a/ci/edmtool.py b/ci/edmtool.py\n--- a/ci/edmtool.py\n+++ b/ci/edmtool.py\n@@ -79,13 +79,27 @@\n     \"mock\",\n     \"numpy\",\n     \"pandas\",\n+    \"pyface\",\n     \"pygments\",\n     \"pyparsing\",\n+    \"traits\",\n+    \"traitsui\",\n     \"cython\",\n+    \"enable\",\n     # Needed to install enable from source\n     \"swig\",\n }\n \n+# Dependencies we install from source for cron tests\n+source_dependencies = {\n+    \"enable\",\n+    \"pyface\",\n+    \"traits\",\n+    \"traitsui\",\n+}\n+\n+github_url_fmt = \"git+http://github.com/enthought/{0}.git#egg={0}\"\n+\n extra_dependencies = {\n     'pyside2': set(),  # pyside2 is pip-installed during the install step\n     'pyqt': {'pyqt'},\n@@ -114,7 +128,12 @@\n @click.option('--runtime', default='3.6')\n @click.option('--toolkit', default='null')\n @click.option('--environment', default=None)\n-def install(runtime, toolkit, environment):\n+@click.option(\n+    \"--source/--no-source\",\n+    default=False,\n+    help=\"Install ETS packages from source\",\n+)\n+def install(runtime, toolkit, environment, source):\n     \"\"\" Install project and dependencies into a clean EDM environment.\n     \"\"\"\n     parameters = get_parameters(runtime, toolkit, environment)\n@@ -126,9 +145,6 @@\n         \"edm install -y -e {environment} {packages}\",\n         (\"edm run -e {environment} -- pip install -r ci/requirements.txt\"\n          \" --no-dependencies\"),\n-        # Note that enable dependencies will be installed implicitly using pip\n-        (\"edm run -e {environment} -- \"\n-         \"pip install git+https://git@github.com/enthought/enable.git\"),\n         \"edm run -e {environment} -- pip install . --no-deps\",\n     ]\n     # pip install pyside2, because we don't have it in EDM yet\n@@ -139,6 +155,26 @@\n     \n     click.echo(\"Creating environment '{environment}'\".format(**parameters))\n     execute(commands, parameters)\n+\n+    if source:\n+        # Remove EDM ETS packages and install them from source\n+        cmd_fmt = (\n+            \"edm plumbing remove-package \"\n+            \"--environment {environment} --force \"\n+        )\n+        commands = [cmd_fmt + source_pkg for source_pkg in source_dependencies]\n+        execute(commands, parameters)\n+        source_pkgs = [\n+            github_url_fmt.format(pkg) for pkg in source_dependencies\n+        ]\n+        commands = [\n+            \"python -m pip install {pkg} --no-deps\".format(pkg=pkg)\n+            for pkg in source_pkgs\n+        ]\n+        commands = [\n+            \"edm run -e {environment} -- \" + command for command in commands\n+        ]\n+        execute(commands, parameters)\n     click.echo('Done install')\n", "issue": "Setup cron job to test against dependencies from source\nTravis (and possibly appveyor too) allow the creation of cron jobs. Some of the ETS packages now have cron jobs setup to test against dependencies which are installed from source - instead of testing against the released versions.\r\n\r\nSee examples : \r\n\r\n- https://github.com/enthought/envisage/pull/162\r\n- https://github.com/enthought/traitsui/pull/914\r\n- https://github.com/enthought/pyface/pull/549\n", "before_files": [{"content": "#\n#  Copyright (c) 2017, Enthought, Inc.\n#  All rights reserved.\n#\n#  This software is provided without warranty under the terms of the BSD\n#  license included in enthought/LICENSE.txt and may be redistributed only\n#  under the conditions described in the aforementioned license.  The license\n#  is also available online at http://www.enthought.com/licenses/BSD.txt\n#\n#  Thanks for using Enthought open source!\n#\n\"\"\"\nTasks for Test Runs\n===================\nThis file is intended to be used with a python environment with the\nclick library to automate the process of setting up test environments\nand running the test within them.  This improves repeatability and\nreliability of tests be removing many of the variables around the\ndeveloper's particular Python environment.  Test environment setup and\npackage management is performed using `EDM http://docs.enthought.com/edm/`_\n\nTo use this to run you tests, you will need to install EDM and click\ninto your working environment.  You will also need to have git\ninstalled to access required source code from github repositories.\n\nYou can then do::\n    python edmtool.py install --runtime=... --toolkit=...\nto create a test environment from the current codebase and::\n    python edmtool.py test --runtime=... --toolkit=...\nto run tests in that environment.  You can remove the environment with::\n    python edmtool.py cleanup --runtime=... --toolkit=...\n\nIf you make changes you will either need to remove and re-install the\nenvironment or manually update the environment using ``edm``, as\nthe install performs a ``python setup.py install`` rather than a ``develop``,\nso changes in your code will not be automatically mirrored in the test\nenvironment.  You can update with a command like::\n    edm run --environment ... -- python setup.py install\nYou can run all three tasks at once with::\n    python edmtool.py test_clean --runtime=... --toolkit=...\nwhich will create, install, run tests, and then clean-up the environment.  And\nyou can run tests in all supported runtimes and toolkits (with cleanup)\nusing::\n    python edmtool.py test_all\n\nCurrently supported runtime values are ``3.6``, and currently\nsupported toolkits are ``null``, ``pyqt``, ``pyqt5`` and ``pyside2``.  Not all\ncombinations of toolkits and runtimes will work, but the tasks will fail with\na clear error if that is the case. Tests can still be run via the usual means\nin other environments if that suits a developer's purpose.\n\nChanging This File\n------------------\nTo change the packages installed during a test run, change the dependencies\nvariable below.  To install a package from github, or one which is not yet\navailable via EDM, add it to the `ci/requirements.txt` file (these will be\ninstalled by `pip`).\n\nOther changes to commands should be a straightforward change to the listed\ncommands for each task. See the EDM documentation for more information about\nhow to run commands within an EDM enviornment.\n\"\"\"\nimport glob\nimport os\nimport subprocess\nimport sys\nfrom shutil import rmtree, copy as copyfile\nfrom tempfile import mkdtemp\nfrom contextlib import contextmanager\n\nimport click\n\nsupported_combinations = {\n    '3.6': {'pyside2', 'pyqt', 'pyqt5', 'null'},\n}\n\ndependencies = {\n    \"six\",\n    \"mock\",\n    \"numpy\",\n    \"pandas\",\n    \"pygments\",\n    \"pyparsing\",\n    \"cython\",\n    # Needed to install enable from source\n    \"swig\",\n}\n\nextra_dependencies = {\n    'pyside2': set(),  # pyside2 is pip-installed during the install step\n    'pyqt': {'pyqt'},\n    'pyqt5': {'pyqt5'},\n    'null': set()\n}\n\nenvironment_vars = {\n    'pyside2': {'ETS_TOOLKIT': 'qt4', 'QT_API': 'pyside2'},\n    'pyqt': {'ETS_TOOLKIT': 'qt4', 'QT_API': 'pyqt'},\n    'pyqt5': {'ETS_TOOLKIT': 'qt4', 'QT_API': 'pyqt5'},\n    'null': {'ETS_TOOLKIT': 'null.image'},\n}\n\n\ndef normalize(name):\n    return name.replace(\"_\", \"-\")\n\n\n@click.group(context_settings={\"token_normalize_func\": normalize})\ndef cli():\n    pass\n\n\n@cli.command()\n@click.option('--runtime', default='3.6')\n@click.option('--toolkit', default='null')\n@click.option('--environment', default=None)\ndef install(runtime, toolkit, environment):\n    \"\"\" Install project and dependencies into a clean EDM environment.\n    \"\"\"\n    parameters = get_parameters(runtime, toolkit, environment)\n    parameters['packages'] = ' '.join(\n        dependencies | extra_dependencies.get(toolkit, set()))\n    # edm commands to setup the development environment\n    commands = [\n        \"edm environments create {environment} --force --version={runtime}\",\n        \"edm install -y -e {environment} {packages}\",\n        (\"edm run -e {environment} -- pip install -r ci/requirements.txt\"\n         \" --no-dependencies\"),\n        # Note that enable dependencies will be installed implicitly using pip\n        (\"edm run -e {environment} -- \"\n         \"pip install git+https://git@github.com/enthought/enable.git\"),\n        \"edm run -e {environment} -- pip install . --no-deps\",\n    ]\n    # pip install pyside2, because we don't have it in EDM yet\n    if toolkit == 'pyside2':\n        commands.append(\n            \"edm run -e {environment} -- pip install pyside2==5.11\"\n        )\n    \n    click.echo(\"Creating environment '{environment}'\".format(**parameters))\n    execute(commands, parameters)\n    click.echo('Done install')\n\n\n@cli.command()\n@click.option('--runtime', default='3.6')\n@click.option('--toolkit', default='null')\n@click.option('--environment', default=None)\ndef test(runtime, toolkit, environment):\n    \"\"\" Run the test suite in a given environment with the specified toolkit.\n    \"\"\"\n    parameters = get_parameters(runtime, toolkit, environment)\n    environ = environment_vars.get(toolkit, {}).copy()\n\n    environ['PYTHONUNBUFFERED'] = \"1\"\n    commands = [\n        \"edm run -e {environment} -- coverage run -m unittest discover -v chaco\"\n    ]\n\n    cwd = os.getcwd()\n\n    # We run in a tempdir to avoid accidentally picking up wrong traitsui\n    # code from a local dir.  We need to ensure a good .coveragerc is in\n    # that directory, plus coverage has a bug that means a non-local coverage\n    # file doesn't get populated correctly.\n    click.echo(\"Running tests in '{environment}'\".format(**parameters))\n    with do_in_tempdir(files=['.coveragerc'], capture_files=['./.coverage*']):\n        os.environ.update(environ)\n        execute(commands, parameters)\n\n    click.echo('Done test')\n\n\n@cli.command()\n@click.option('--runtime', default='3.6')\n@click.option('--toolkit', default='null')\n@click.option('--environment', default=None)\ndef cleanup(runtime, toolkit, environment):\n    \"\"\" Remove a development environment.\n    \"\"\"\n    parameters = get_parameters(runtime, toolkit, environment)\n    commands = [\n        \"edm run -e {environment} -- python setup.py clean\",\n        \"edm environments remove {environment} --purge -y\",\n    ]\n    click.echo(\"Cleaning up environment '{environment}'\".format(**parameters))\n    execute(commands, parameters)\n    click.echo('Done cleanup')\n\n\n@cli.command()\n@click.option('--runtime', default='3.6')\n@click.option('--toolkit', default='null')\ndef test_clean(runtime, toolkit):\n    \"\"\" Run tests in a clean environment, cleaning up afterwards\n    \"\"\"\n    args = ['--toolkit={}'.format(toolkit),\n            '--runtime={}'.format(runtime)]\n    try:\n        install(args=args, standalone_mode=False)\n        test(args=args, standalone_mode=False)\n    finally:\n        cleanup(args=args, standalone_mode=False)\n\n\n@cli.command()\n@click.option('--runtime', default='3.6')\n@click.option('--toolkit', default='null')\n@click.option('--environment', default=None)\ndef update(runtime, toolkit, environment):\n    \"\"\" Update/Reinstall package into environment.\n    \"\"\"\n    parameters = get_parameters(runtime, toolkit, environment)\n    commands = [\n        \"edm run -e {environment} -- python setup.py install\"]\n    click.echo(\"Re-installing in  '{environment}'\".format(**parameters))\n    execute(commands, parameters)\n    click.echo('Done update')\n\n\n@cli.command()\ndef test_all():\n    \"\"\" Run test_clean across all supported environment combinations.\n    \"\"\"\n    for runtime, toolkits in supported_combinations.items():\n        for toolkit in toolkits:\n            args = ['--toolkit={}'.format(toolkit),\n                    '--runtime={}'.format(runtime)]\n            test_clean(args, standalone_mode=True)\n\n\n# ----------------------------------------------------------------------------\n# Utility routines\n# ----------------------------------------------------------------------------\n\ndef get_parameters(runtime, toolkit, environment):\n    \"\"\"Set up parameters dictionary for format() substitution\n    \"\"\"\n    parameters = {'runtime': runtime, 'toolkit': toolkit,\n                  'environment': environment}\n    if toolkit not in supported_combinations[runtime]:\n        msg = (\"Python {runtime!r}, toolkit {toolkit!r}, \"\n               \"not supported by test environments ({available})\")\n        available = \", \".join(\n            repr(tk) for tk in sorted(supported_combinations[runtime])\n        )\n        raise RuntimeError(msg.format(available=available, **parameters))\n    if environment is None:\n        tmpl = 'chaco-test-{runtime}-{toolkit}'\n        environment = tmpl.format(**parameters)\n        parameters['environment'] = environment\n    return parameters\n\n\n@contextmanager\ndef do_in_tempdir(files=(), capture_files=()):\n    \"\"\" Create a temporary directory, cleaning up after done.\n    Creates the temporary directory, and changes into it.  On exit returns to\n    original directory and removes temporary dir.\n    Parameters\n    ----------\n    files : sequence of filenames\n        Files to be copied across to temporary directory.\n    capture_files : sequence of filenames\n        Files to be copied back from temporary directory.\n    \"\"\"\n    path = mkdtemp()\n    old_path = os.getcwd()\n\n    # send across any files we need\n    for filepath in files:\n        click.echo('copying file to tempdir: {}'.format(filepath))\n        copyfile(filepath, path)\n\n    os.chdir(path)\n    try:\n        yield path\n        # retrieve any result files we want\n        for pattern in capture_files:\n            for filepath in glob.iglob(pattern):\n                click.echo('copying file back: {}'.format(filepath))\n                copyfile(filepath, old_path)\n    finally:\n        os.chdir(old_path)\n        rmtree(path)\n\n\ndef execute(commands, parameters):\n    for command in commands:\n        print(\"[EXECUTING]\", command.format(**parameters))\n        try:\n            subprocess.check_call(command.format(**parameters).split())\n        except subprocess.CalledProcessError:\n            sys.exit(1)\n\n\nif __name__ == '__main__':\n    cli()\n", "path": "ci/edmtool.py"}, {"content": "#  Copyright (c) 2005-2014 by Enthought, Inc.\n#  All rights reserved.\n\"\"\" Two-dimensional plotting application toolkit.\n    Part of the Chaco project of the Enthought Tool Suite.\n\"\"\"\nfrom ._version import full_version as __version__  # noqa\n\n__requires__ = [\n   'enable',\n   'six'\n]\n", "path": "chaco/__init__.py"}], "after_files": [{"content": "#\n#  Copyright (c) 2017, Enthought, Inc.\n#  All rights reserved.\n#\n#  This software is provided without warranty under the terms of the BSD\n#  license included in enthought/LICENSE.txt and may be redistributed only\n#  under the conditions described in the aforementioned license.  The license\n#  is also available online at http://www.enthought.com/licenses/BSD.txt\n#\n#  Thanks for using Enthought open source!\n#\n\"\"\"\nTasks for Test Runs\n===================\nThis file is intended to be used with a python environment with the\nclick library to automate the process of setting up test environments\nand running the test within them.  This improves repeatability and\nreliability of tests be removing many of the variables around the\ndeveloper's particular Python environment.  Test environment setup and\npackage management is performed using `EDM http://docs.enthought.com/edm/`_\n\nTo use this to run you tests, you will need to install EDM and click\ninto your working environment.  You will also need to have git\ninstalled to access required source code from github repositories.\n\nYou can then do::\n    python edmtool.py install --runtime=... --toolkit=...\nto create a test environment from the current codebase and::\n    python edmtool.py test --runtime=... --toolkit=...\nto run tests in that environment.  You can remove the environment with::\n    python edmtool.py cleanup --runtime=... --toolkit=...\n\nIf you make changes you will either need to remove and re-install the\nenvironment or manually update the environment using ``edm``, as\nthe install performs a ``python setup.py install`` rather than a ``develop``,\nso changes in your code will not be automatically mirrored in the test\nenvironment.  You can update with a command like::\n    edm run --environment ... -- python setup.py install\nYou can run all three tasks at once with::\n    python edmtool.py test_clean --runtime=... --toolkit=...\nwhich will create, install, run tests, and then clean-up the environment.  And\nyou can run tests in all supported runtimes and toolkits (with cleanup)\nusing::\n    python edmtool.py test_all\n\nCurrently supported runtime values are ``3.6``, and currently\nsupported toolkits are ``null``, ``pyqt``, ``pyqt5`` and ``pyside2``.  Not all\ncombinations of toolkits and runtimes will work, but the tasks will fail with\na clear error if that is the case. Tests can still be run via the usual means\nin other environments if that suits a developer's purpose.\n\nChanging This File\n------------------\nTo change the packages installed during a test run, change the dependencies\nvariable below.  To install a package from github, or one which is not yet\navailable via EDM, add it to the `ci/requirements.txt` file (these will be\ninstalled by `pip`).\n\nOther changes to commands should be a straightforward change to the listed\ncommands for each task. See the EDM documentation for more information about\nhow to run commands within an EDM enviornment.\n\"\"\"\nimport glob\nimport os\nimport subprocess\nimport sys\nfrom shutil import rmtree, copy as copyfile\nfrom tempfile import mkdtemp\nfrom contextlib import contextmanager\n\nimport click\n\nsupported_combinations = {\n    '3.6': {'pyside2', 'pyqt', 'pyqt5', 'null'},\n}\n\ndependencies = {\n    \"six\",\n    \"mock\",\n    \"numpy\",\n    \"pandas\",\n    \"pyface\",\n    \"pygments\",\n    \"pyparsing\",\n    \"traits\",\n    \"traitsui\",\n    \"cython\",\n    \"enable\",\n    # Needed to install enable from source\n    \"swig\",\n}\n\n# Dependencies we install from source for cron tests\nsource_dependencies = {\n    \"enable\",\n    \"pyface\",\n    \"traits\",\n    \"traitsui\",\n}\n\ngithub_url_fmt = \"git+http://github.com/enthought/{0}.git#egg={0}\"\n\nextra_dependencies = {\n    'pyside2': set(),  # pyside2 is pip-installed during the install step\n    'pyqt': {'pyqt'},\n    'pyqt5': {'pyqt5'},\n    'null': set()\n}\n\nenvironment_vars = {\n    'pyside2': {'ETS_TOOLKIT': 'qt4', 'QT_API': 'pyside2'},\n    'pyqt': {'ETS_TOOLKIT': 'qt4', 'QT_API': 'pyqt'},\n    'pyqt5': {'ETS_TOOLKIT': 'qt4', 'QT_API': 'pyqt5'},\n    'null': {'ETS_TOOLKIT': 'null.image'},\n}\n\n\ndef normalize(name):\n    return name.replace(\"_\", \"-\")\n\n\n@click.group(context_settings={\"token_normalize_func\": normalize})\ndef cli():\n    pass\n\n\n@cli.command()\n@click.option('--runtime', default='3.6')\n@click.option('--toolkit', default='null')\n@click.option('--environment', default=None)\n@click.option(\n    \"--source/--no-source\",\n    default=False,\n    help=\"Install ETS packages from source\",\n)\ndef install(runtime, toolkit, environment, source):\n    \"\"\" Install project and dependencies into a clean EDM environment.\n    \"\"\"\n    parameters = get_parameters(runtime, toolkit, environment)\n    parameters['packages'] = ' '.join(\n        dependencies | extra_dependencies.get(toolkit, set()))\n    # edm commands to setup the development environment\n    commands = [\n        \"edm environments create {environment} --force --version={runtime}\",\n        \"edm install -y -e {environment} {packages}\",\n        (\"edm run -e {environment} -- pip install -r ci/requirements.txt\"\n         \" --no-dependencies\"),\n        \"edm run -e {environment} -- pip install . --no-deps\",\n    ]\n    # pip install pyside2, because we don't have it in EDM yet\n    if toolkit == 'pyside2':\n        commands.append(\n            \"edm run -e {environment} -- pip install pyside2==5.11\"\n        )\n    \n    click.echo(\"Creating environment '{environment}'\".format(**parameters))\n    execute(commands, parameters)\n\n    if source:\n        # Remove EDM ETS packages and install them from source\n        cmd_fmt = (\n            \"edm plumbing remove-package \"\n            \"--environment {environment} --force \"\n        )\n        commands = [cmd_fmt + source_pkg for source_pkg in source_dependencies]\n        execute(commands, parameters)\n        source_pkgs = [\n            github_url_fmt.format(pkg) for pkg in source_dependencies\n        ]\n        commands = [\n            \"python -m pip install {pkg} --no-deps\".format(pkg=pkg)\n            for pkg in source_pkgs\n        ]\n        commands = [\n            \"edm run -e {environment} -- \" + command for command in commands\n        ]\n        execute(commands, parameters)\n    click.echo('Done install')\n\n\n@cli.command()\n@click.option('--runtime', default='3.6')\n@click.option('--toolkit', default='null')\n@click.option('--environment', default=None)\ndef test(runtime, toolkit, environment):\n    \"\"\" Run the test suite in a given environment with the specified toolkit.\n    \"\"\"\n    parameters = get_parameters(runtime, toolkit, environment)\n    environ = environment_vars.get(toolkit, {}).copy()\n\n    environ['PYTHONUNBUFFERED'] = \"1\"\n    commands = [\n        \"edm run -e {environment} -- coverage run -m unittest discover -v chaco\"\n    ]\n\n    cwd = os.getcwd()\n\n    # We run in a tempdir to avoid accidentally picking up wrong traitsui\n    # code from a local dir.  We need to ensure a good .coveragerc is in\n    # that directory, plus coverage has a bug that means a non-local coverage\n    # file doesn't get populated correctly.\n    click.echo(\"Running tests in '{environment}'\".format(**parameters))\n    with do_in_tempdir(files=['.coveragerc'], capture_files=['./.coverage*']):\n        os.environ.update(environ)\n        execute(commands, parameters)\n\n    click.echo('Done test')\n\n\n@cli.command()\n@click.option('--runtime', default='3.6')\n@click.option('--toolkit', default='null')\n@click.option('--environment', default=None)\ndef cleanup(runtime, toolkit, environment):\n    \"\"\" Remove a development environment.\n    \"\"\"\n    parameters = get_parameters(runtime, toolkit, environment)\n    commands = [\n        \"edm run -e {environment} -- python setup.py clean\",\n        \"edm environments remove {environment} --purge -y\",\n    ]\n    click.echo(\"Cleaning up environment '{environment}'\".format(**parameters))\n    execute(commands, parameters)\n    click.echo('Done cleanup')\n\n\n@cli.command()\n@click.option('--runtime', default='3.6')\n@click.option('--toolkit', default='null')\ndef test_clean(runtime, toolkit):\n    \"\"\" Run tests in a clean environment, cleaning up afterwards\n    \"\"\"\n    args = ['--toolkit={}'.format(toolkit),\n            '--runtime={}'.format(runtime)]\n    try:\n        install(args=args, standalone_mode=False)\n        test(args=args, standalone_mode=False)\n    finally:\n        cleanup(args=args, standalone_mode=False)\n\n\n@cli.command()\n@click.option('--runtime', default='3.6')\n@click.option('--toolkit', default='null')\n@click.option('--environment', default=None)\ndef update(runtime, toolkit, environment):\n    \"\"\" Update/Reinstall package into environment.\n    \"\"\"\n    parameters = get_parameters(runtime, toolkit, environment)\n    commands = [\n        \"edm run -e {environment} -- python setup.py install\"]\n    click.echo(\"Re-installing in  '{environment}'\".format(**parameters))\n    execute(commands, parameters)\n    click.echo('Done update')\n\n\n@cli.command()\ndef test_all():\n    \"\"\" Run test_clean across all supported environment combinations.\n    \"\"\"\n    for runtime, toolkits in supported_combinations.items():\n        for toolkit in toolkits:\n            args = ['--toolkit={}'.format(toolkit),\n                    '--runtime={}'.format(runtime)]\n            test_clean(args, standalone_mode=True)\n\n\n# ----------------------------------------------------------------------------\n# Utility routines\n# ----------------------------------------------------------------------------\n\ndef get_parameters(runtime, toolkit, environment):\n    \"\"\"Set up parameters dictionary for format() substitution\n    \"\"\"\n    parameters = {'runtime': runtime, 'toolkit': toolkit,\n                  'environment': environment}\n    if toolkit not in supported_combinations[runtime]:\n        msg = (\"Python {runtime!r}, toolkit {toolkit!r}, \"\n               \"not supported by test environments ({available})\")\n        available = \", \".join(\n            repr(tk) for tk in sorted(supported_combinations[runtime])\n        )\n        raise RuntimeError(msg.format(available=available, **parameters))\n    if environment is None:\n        tmpl = 'chaco-test-{runtime}-{toolkit}'\n        environment = tmpl.format(**parameters)\n        parameters['environment'] = environment\n    return parameters\n\n\n@contextmanager\ndef do_in_tempdir(files=(), capture_files=()):\n    \"\"\" Create a temporary directory, cleaning up after done.\n    Creates the temporary directory, and changes into it.  On exit returns to\n    original directory and removes temporary dir.\n    Parameters\n    ----------\n    files : sequence of filenames\n        Files to be copied across to temporary directory.\n    capture_files : sequence of filenames\n        Files to be copied back from temporary directory.\n    \"\"\"\n    path = mkdtemp()\n    old_path = os.getcwd()\n\n    # send across any files we need\n    for filepath in files:\n        click.echo('copying file to tempdir: {}'.format(filepath))\n        copyfile(filepath, path)\n\n    os.chdir(path)\n    try:\n        yield path\n        # retrieve any result files we want\n        for pattern in capture_files:\n            for filepath in glob.iglob(pattern):\n                click.echo('copying file back: {}'.format(filepath))\n                copyfile(filepath, old_path)\n    finally:\n        os.chdir(old_path)\n        rmtree(path)\n\n\ndef execute(commands, parameters):\n    for command in commands:\n        print(\"[EXECUTING]\", command.format(**parameters))\n        try:\n            subprocess.check_call(command.format(**parameters).split())\n        except subprocess.CalledProcessError:\n            sys.exit(1)\n\n\nif __name__ == '__main__':\n    cli()\n", "path": "ci/edmtool.py"}, {"content": "#  Copyright (c) 2005-2014 by Enthought, Inc.\n#  All rights reserved.\n\"\"\" Two-dimensional plotting application toolkit.\n    Part of the Chaco project of the Enthought Tool Suite.\n\"\"\"\nfrom ._version import full_version as __version__  # noqa\n\n__requires__ = [\n   'traits',\n   'traitsui',\n   'pyface',\n   'numpy',\n   'enable',\n   'six'\n]\n", "path": "chaco/__init__.py"}]}