Skip to content

Commit aec2384

Browse files
authored
Merge pull request #65 from common-workflow-language/terminate-process-cleanup
If a test process didn't end on its own, terminate it.
2 parents 65ec76c + 9b7fa7a commit aec2384

File tree

4 files changed

+333
-5
lines changed

4 files changed

+333
-5
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ MODULE=cwltest
2828
PYSOURCES=$(wildcard ${MODULE}/**.py tests/*.py) setup.py
2929
DEVPKGS=pep8 diff_cover autopep8 pylint coverage pep257 flake8 pytest
3030
DEBDEVPKGS=pep8 python-autopep8 pylint python-coverage pep257 sloccount python-flake8
31-
VERSION=1.0.$(shell date +%Y%m%d%H%M%S --date=`git log --first-parent \
31+
VERSION=1.0.$(shell date +%Y%m%d%H%M%S --utc --date=`git log --first-parent \
3232
--max-count=1 --format=format:%cI`)
3333
mkfile_dir := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
3434

cwltest/__init__.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from six.moves import range
2222
from six.moves import zip
2323
from typing import Any, Dict, List
24+
import pkg_resources # part of setuptools
2425

2526
import junit_xml
2627
from cwltest.utils import compare, CompareFail, TestResult, REQUIRED, get_test_number_by_key
@@ -84,6 +85,7 @@ def run_test(args, i, tests, timeout):
8485
else:
8586
suffix = "\n"
8687
try:
88+
process = None # type: subprocess.Popen
8789
test_command = prepare_test_command(args, i, tests)
8890

8991
if t.get("short_name"):
@@ -129,6 +131,16 @@ def run_test(args, i, tests, timeout):
129131
_logger.error(u"""Test timed out: %s""", " ".join([pipes.quote(tc) for tc in test_command]))
130132
_logger.error(t.get("doc"))
131133
return TestResult(2, outstr, outerr, timeout, args.classname, "Test timed out")
134+
finally:
135+
if process is not None and process.returncode is None:
136+
_logger.error(u"""Terminating lingering process""")
137+
process.terminate()
138+
for a in range(0, 3):
139+
time.sleep(1)
140+
if process.poll() is not None:
141+
break
142+
if process.returncode is None:
143+
process.kill()
132144

133145
fail_message = ''
134146

@@ -153,7 +165,7 @@ def run_test(args, i, tests, timeout):
153165

154166

155167
def arg_parser(): # type: () -> argparse.ArgumentParser
156-
parser = argparse.ArgumentParser(description='Compliance tests for cwltool')
168+
parser = argparse.ArgumentParser(description='Common Workflow Language testing framework')
157169
parser.add_argument("--test", type=str, help="YAML file describing test cases", required=True)
158170
parser.add_argument("--basedir", type=str, help="Basedir to use for tests", default=".")
159171
parser.add_argument("-l", action="store_true", help="List tests then exit")
@@ -172,8 +184,16 @@ def arg_parser(): # type: () -> argparse.ArgumentParser
172184
parser.add_argument("--verbose", action="store_true", help="More verbose output during test run.")
173185
parser.add_argument("--classname", type=str, default="", help="Specify classname for the Test Suite.")
174186
parser.add_argument("--timeout", type=int, default=DEFAULT_TIMEOUT, help="Time of execution in seconds after "
175-
"which the test will be skipped."
187+
"which the test will be skipped. "
176188
"Defaults to 900 sec (15 minutes)")
189+
190+
pkg = pkg_resources.require("cwltest")
191+
if pkg:
192+
ver = u"%s %s" % (sys.argv[0], pkg[0].version)
193+
else:
194+
ver = u"%s %s" % (sys.argv[0], "unknown version")
195+
parser.add_argument('--version', action='version', version=ver)
196+
177197
return parser
178198

179199

Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
# Stubs for pkg_resources (Python 2)
2+
#
3+
# NOTE: This dynamically typed stub was automatically generated by stubgen.
4+
5+
from typing import Any, Text
6+
from os import open as os_open
7+
from collections import namedtuple
8+
9+
require = ... # type: Any
10+
working_set = ... # type: Any
11+
12+
class PEP440Warning(RuntimeWarning): ...
13+
14+
class _SetuptoolsVersionMixin:
15+
def __hash__(self): ...
16+
def __lt__(self, other): ...
17+
def __le__(self, other): ...
18+
def __eq__(self, other): ...
19+
def __ge__(self, other): ...
20+
def __gt__(self, other): ...
21+
def __ne__(self, other): ...
22+
def __getitem__(self, key): ...
23+
def __iter__(self): ...
24+
25+
def parse_version(v): ...
26+
27+
class ResolutionError(Exception): ...
28+
29+
class VersionConflict(ResolutionError):
30+
@property
31+
def dist(self): ...
32+
@property
33+
def req(self): ...
34+
def report(self): ...
35+
def with_context(self, required_by): ...
36+
37+
class ContextualVersionConflict(VersionConflict):
38+
@property
39+
def required_by(self): ...
40+
41+
class DistributionNotFound(ResolutionError):
42+
@property
43+
def req(self): ...
44+
@property
45+
def requirers(self): ...
46+
@property
47+
def requirers_str(self): ...
48+
def report(self): ...
49+
50+
class UnknownExtra(ResolutionError): ...
51+
52+
EGG_DIST = ... # type: Any
53+
BINARY_DIST = ... # type: Any
54+
SOURCE_DIST = ... # type: Any
55+
CHECKOUT_DIST = ... # type: Any
56+
DEVELOP_DIST = ... # type: Any
57+
58+
def register_loader_type(loader_type, provider_factory): ...
59+
def get_provider(moduleOrReq): ...
60+
61+
get_platform = ... # type: Any
62+
63+
def compatible_platforms(provided, required): ...
64+
def run_script(dist_spec, script_name): ...
65+
66+
run_main = ... # type: Any
67+
68+
def get_distribution(dist): ...
69+
def load_entry_point(dist, group, name): ...
70+
def get_entry_map(dist, group=None): ...
71+
def get_entry_info(dist, group, name): ...
72+
73+
class IMetadataProvider:
74+
def has_metadata(name): ...
75+
def get_metadata(name): ...
76+
def get_metadata_lines(name): ...
77+
def metadata_isdir(name): ...
78+
def metadata_listdir(name): ...
79+
def run_script(script_name, namespace): ...
80+
81+
class IResourceProvider(IMetadataProvider):
82+
def get_resource_filename(manager, resource_name): ...
83+
def get_resource_stream(manager, resource_name): ...
84+
def get_resource_string(manager, resource_name): ...
85+
def has_resource(resource_name): ...
86+
def resource_isdir(resource_name): ...
87+
def resource_listdir(resource_name): ...
88+
89+
class WorkingSet:
90+
entries = ... # type: Any
91+
entry_keys = ... # type: Any
92+
by_key = ... # type: Any
93+
callbacks = ... # type: Any
94+
def __init__(self, entries=None): ...
95+
def add_entry(self, entry): ...
96+
def __contains__(self, dist): ...
97+
def find(self, req): ...
98+
def iter_entry_points(self, group, name=None): ...
99+
def run_script(self, requires, script_name): ...
100+
def __iter__(self): ...
101+
def add(self, dist, entry=None, insert=True, replace=False): ...
102+
def resolve(self, requirements, env=None, installer=None, replace_conflicting=False): ...
103+
def find_plugins(self, plugin_env, full_env=None, installer=None, fallback=True): ...
104+
def require(self, *requirements): ...
105+
def subscribe(self, callback): ...
106+
107+
class _ReqExtras(dict):
108+
def markers_pass(self, req): ...
109+
110+
class Environment:
111+
platform = ... # type: Any
112+
python = ... # type: Any
113+
def __init__(self, search_path=None, platform=..., python=...): ...
114+
def can_add(self, dist): ...
115+
def remove(self, dist): ...
116+
def scan(self, search_path=None): ...
117+
def __getitem__(self, project_name): ...
118+
def add(self, dist): ...
119+
def best_match(self, req, working_set, installer=None): ...
120+
def obtain(self, requirement, installer=None): ...
121+
def __iter__(self): ...
122+
def __iadd__(self, other): ...
123+
def __add__(self, other): ...
124+
125+
AvailableDistributions = ... # type: Any
126+
127+
class ExtractionError(RuntimeError): ...
128+
129+
class ResourceManager:
130+
extraction_path = ... # type: Any
131+
cached_files = ... # type: Any
132+
def __init__(self): ...
133+
def resource_exists(self, package_or_requirement, resource_name): ...
134+
def resource_isdir(self, package_or_requirement, resource_name): ...
135+
def resource_filename(self, package_or_requirement, resource_name): ...
136+
def resource_stream(self, package_or_requirement, resource_name): ...
137+
def resource_string(self, package_or_requirement, resource_name): ...
138+
def resource_listdir(self, package_or_requirement, resource_name): ...
139+
def extraction_error(self): ...
140+
def get_cache_path(self, archive_name, names=...): ...
141+
def postprocess(self, tempname, filename): ...
142+
def set_extraction_path(self, path): ...
143+
def cleanup_resources(self, force=False): ...
144+
145+
def get_default_cache(): ...
146+
def safe_name(name): ...
147+
def safe_version(version): ...
148+
def safe_extra(extra): ...
149+
def to_filename(name): ...
150+
def invalid_marker(text): ...
151+
def evaluate_marker(text, extra=None): ...
152+
153+
class NullProvider:
154+
egg_name = ... # type: Any
155+
egg_info = ... # type: Any
156+
loader = ... # type: Any
157+
module_path = ... # type: Any
158+
def __init__(self, module): ...
159+
def get_resource_filename(self, manager, resource_name): ...
160+
def get_resource_stream(self, manager, resource_name): ...
161+
def get_resource_string(self, manager, resource_name): ...
162+
def has_resource(self, resource_name): ...
163+
def has_metadata(self, name): ...
164+
def get_metadata(self, name): ...
165+
def get_metadata_lines(self, name): ...
166+
def resource_isdir(self, resource_name): ...
167+
def metadata_isdir(self, name): ...
168+
def resource_listdir(self, resource_name): ...
169+
def metadata_listdir(self, name): ...
170+
def run_script(self, script_name, namespace): ...
171+
172+
class EggProvider(NullProvider):
173+
def __init__(self, module): ...
174+
175+
class DefaultProvider(EggProvider):
176+
def get_resource_stream(self, manager, resource_name): ...
177+
178+
class EmptyProvider(NullProvider):
179+
module_path = ... # type: Any
180+
def __init__(self): ...
181+
182+
empty_provider = ... # type: Any
183+
184+
class ZipManifests(dict):
185+
@classmethod
186+
def build(cls, path): ...
187+
load = ... # type: Any
188+
189+
class ZipProvider(EggProvider):
190+
eagers = ... # type: Any
191+
zip_pre = ... # type: Any
192+
def __init__(self, module): ...
193+
@property
194+
def zipinfo(self): ...
195+
def get_resource_filename(self, manager, resource_name): ...
196+
197+
class FileMetadata(EmptyProvider):
198+
path = ... # type: Any
199+
def __init__(self, path): ...
200+
def has_metadata(self, name): ...
201+
def get_metadata(self, name): ...
202+
def get_metadata_lines(self, name): ...
203+
204+
class PathMetadata(DefaultProvider):
205+
module_path = ... # type: Any
206+
egg_info = ... # type: Any
207+
def __init__(self, path, egg_info): ...
208+
209+
class EggMetadata(ZipProvider):
210+
zip_pre = ... # type: Any
211+
loader = ... # type: Any
212+
module_path = ... # type: Any
213+
def __init__(self, importer): ...
214+
215+
def register_finder(importer_type, distribution_finder): ...
216+
def find_distributions(path_item, only=False): ...
217+
def register_namespace_handler(importer_type, namespace_handler): ...
218+
def declare_namespace(packageName): ...
219+
def fixup_namespace_packages(path_item, parent=None): ...
220+
def normalize_path(filename): ...
221+
def yield_lines(strs): ...
222+
223+
class EntryPoint:
224+
name = ... # type: Any
225+
module_name = ... # type: Any
226+
attrs = ... # type: Any
227+
extras = ... # type: Any
228+
dist = ... # type: Any
229+
def __init__(self, name, module_name, attrs=..., extras=..., dist=None): ...
230+
def load(self, require=True, *args, **kwargs): ...
231+
def resolve(self): ...
232+
def require(self, env=None, installer=None): ...
233+
pattern = ... # type: Any
234+
@classmethod
235+
def parse(cls, src, dist=None): ...
236+
@classmethod
237+
def parse_group(cls, group, lines, dist=None): ...
238+
@classmethod
239+
def parse_map(cls, data, dist=None): ...
240+
241+
class Distribution:
242+
PKG_INFO = ... # type: Any
243+
project_name = ... # type: Any
244+
py_version = ... # type: Any
245+
platform = ... # type: Any
246+
location = ... # type: Any
247+
precedence = ... # type: Any
248+
def __init__(self, location=None, metadata=None, project_name=None, version=None, py_version=..., platform=None, precedence=...): ...
249+
@classmethod
250+
def from_location(cls, location, basename, metadata=None, **kw): ...
251+
@property
252+
def hashcmp(self): ...
253+
def __hash__(self): ...
254+
def __lt__(self, other): ...
255+
def __le__(self, other): ...
256+
def __gt__(self, other): ...
257+
def __ge__(self, other): ...
258+
def __eq__(self, other): ...
259+
def __ne__(self, other): ...
260+
@property
261+
def key(self): ...
262+
@property
263+
def parsed_version(self): ...
264+
@property
265+
def version(self): ...
266+
def requires(self, extras=...): ...
267+
def activate(self, path=None): ...
268+
def egg_name(self): ...
269+
def __getattr__(self, attr): ...
270+
@classmethod
271+
def from_filename(cls, filename, metadata=None, **kw): ...
272+
def as_requirement(self): ...
273+
def load_entry_point(self, group, name): ...
274+
def get_entry_map(self, group=None): ...
275+
def get_entry_info(self, group, name): ...
276+
def insert_on(self, path, loc=None, replace=False): ...
277+
def check_version_conflict(self): ...
278+
def has_version(self): ...
279+
def clone(self, **kw): ...
280+
@property
281+
def extras(self): ...
282+
283+
class EggInfoDistribution(Distribution): ...
284+
285+
class DistInfoDistribution(Distribution):
286+
PKG_INFO = ... # type: Any
287+
EQEQ = ... # type: Any
288+
289+
class RequirementParseError(ValueError): ...
290+
291+
def parse_requirements(strs): ...
292+
293+
def ensure_directory(path): ...
294+
def split_sections(s): ...
295+
296+
def resource_stream(package_or_requirement: Text, resource_name: Text): ...
297+
298+
# Names in __all__ with no definition:
299+
# add_activation_listener
300+
# cleanup_resources
301+
# iter_entry_points
302+
# resource_exists
303+
# resource_filename
304+
# resource_isdir
305+
# resource_listdir
306+
# resource_stream
307+
# resource_string
308+
# set_extraction_path

typeshed/2.7/subprocess32.pyi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,5 @@ class Popen:
4949
def poll(self) -> int: ...
5050
def wait(self, timeout: Optional[Any] = ..., endtime: Optional[Any] = ...): ...
5151
def send_signal(self, sig): ...
52-
def terminate(self): ...
53-
def kill(self): ...
52+
def terminate(self) -> None: ...
53+
def kill(self) -> None: ...

0 commit comments

Comments
 (0)