pyvec / elsa

Helper module for hosting Frozen-Flask based websites on GitHub pages
Other
28 stars 49 forks source link

Test on Windows #20

Closed encukou closed 7 years ago

encukou commented 7 years ago

We need to set up Windows-based CI to make sure this works there.

hroncok commented 7 years ago

I'm ready to test it locally for now. As for the CI service https://www.appveyor.com/ seems to be used widely.

hroncok commented 7 years ago
``` C:\Users\Linux\elsa>tox GLOB sdist-make: C:\Users\Linux\elsa\setup.py py35 create: C:\Users\Linux\elsa\.tox\py35 ERROR: InterpreterNotFound: python3.5 py36 inst-nodeps: C:\Users\Linux\elsa\.tox\dist\elsa-0.1.zip py36 installed: appdirs==1.4.0,click==6.7,elsa==0.1,Flask==0.12,Frozen-Flask==0. 13,ghp-import==0.5.4,itsdangerous==0.24,Jinja2==2.9.5,MarkupSafe==0.23,packaging ==16.8,pyparsing==2.1.10,six==1.10.0,Werkzeug==0.11.15 py36 runtests: PYTHONHASHSEED='202' py36 runtests: commands[0] | python setup.py test running pytest Searching for pytest-flake8 Best match: pytest-flake8 0.8.1 Processing pytest_flake8-0.8.1-py3.6.egg Using c:\users\linux\elsa\.eggs\pytest_flake8-0.8.1-py3.6.egg Searching for requests Best match: requests 2.13.0 Processing requests-2.13.0-py3.6.egg Using c:\users\linux\elsa\.eggs\requests-2.13.0-py3.6.egg Searching for pytest>=3 Best match: pytest 3.0.6 Processing pytest-3.0.6-py3.6.egg Using c:\users\linux\elsa\.eggs\pytest-3.0.6-py3.6.egg Searching for flake8>=3.0 Best match: flake8 3.3.0 Processing flake8-3.3.0-py3.6.egg Using c:\users\linux\elsa\.eggs\flake8-3.3.0-py3.6.egg Searching for colorama Best match: colorama 0.3.7 Processing colorama-0.3.7-py3.6.egg Using c:\users\linux\elsa\.eggs\colorama-0.3.7-py3.6.egg Searching for py>=1.4.29 Best match: py 1.4.32 Processing py-1.4.32-py3.6.egg Using c:\users\linux\elsa\.eggs\py-1.4.32-py3.6.egg Searching for mccabe<0.7.0,>=0.6.0 Best match: mccabe 0.6.1 Processing mccabe-0.6.1-py3.6.egg Using c:\users\linux\elsa\.eggs\mccabe-0.6.1-py3.6.egg Searching for pycodestyle<2.4.0,>=2.0.0 Best match: pycodestyle 2.3.1 Processing pycodestyle-2.3.1-py3.6.egg Using c:\users\linux\elsa\.eggs\pycodestyle-2.3.1-py3.6.egg Searching for pyflakes<1.6.0,>=1.5.0 Best match: pyflakes 1.5.0 Processing pyflakes-1.5.0-py3.6.egg Using c:\users\linux\elsa\.eggs\pyflakes-1.5.0-py3.6.egg running egg_info writing elsa.egg-info\PKG-INFO writing dependency_links to elsa.egg-info\dependency_links.txt writing requirements to elsa.egg-info\requires.txt writing top-level names to elsa.egg-info\top_level.txt reading manifest file 'elsa.egg-info\SOURCES.txt' reading manifest template 'MANIFEST.in' writing manifest file 'elsa.egg-info\SOURCES.txt' running build_ext ============================= test session starts ============================= platform win32 -- Python 3.6.0, pytest-3.0.6, py-1.4.32, pluggy-0.4.0 -- C:\User s\Linux\elsa\.tox\py36\Scripts\python.EXE cachedir: .cache rootdir: C:\Users\Linux\elsa, inifile: pytest.ini plugins: flake8-0.8.1 collected 40 items setup.py SKIPPED elsa/__init__.py SKIPPED elsa/_cli.py SKIPPED elsa/_deployment.py SKIPPED tests/test_commands.py SKIPPED tests/test_commands.py::test_elsa_fixture_bad_exit_status xfail tests/test_commands.py::test_elsa_fixture_bad_exit_status_bg xfail tests/test_commands.py::test_serve !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! KeyboardInterrupt !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! to show a full traceback on KeyboardInterrupt use --fulltrace C:\Users\Linux\AppData\Local\Programs\Python\Python36-32\Lib\threading.py:1072: KeyboardInterrupt ==================== 5 skipped, 2 xfailed in 17.75 seconds ==================== ERROR: KEYBOARDINTERRUPT ERROR: keyboardinterrupt C:\Users\Linux\elsa> ```

test_serve hangs

hroncok commented 7 years ago

Full traceback:

``` ============================= test session starts ============================= platform win32 -- Python 3.6.0, pytest-3.0.6, py-1.4.32, pluggy-0.4.0 -- C:\Users\Linux\elsa\.tox\py36\Scripts\python.exe cachedir: .cache rootdir: C:\Users\Linux\elsa, inifile: pytest.ini plugins: flake8-0.8.1 collecting ... collected 40 items setup.py SKIPPED elsa/__init__.py SKIPPED elsa/_cli.py SKIPPED elsa/_deployment.py SKIPPED tests/test_commands.py SKIPPED tests/test_commands.py::test_elsa_fixture_bad_exit_status xfail tests/test_commands.py::test_elsa_fixture_bad_exit_status_bg xfail tests/test_commands.py::test_serve !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! KeyboardInterrupt !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! self = , script = None command = ('serve',), proc = @contextmanager def run_bg(self, *command, script=None): print('COMMAND IN BACKGROUND: python website.py', *command) proc = subprocess.Popen(self.create_command(command, script), stderr=subprocess.PIPE, universal_newlines=True) # Wait for the server to start, # i.e. wait for the first line on stderr: # * Running on http://127.0.0.1:8003/ (Press CTRL+C to quit) sys.stderr.write(proc.stderr.readline()) # With the serve command, Flask is running in debug and restarts # the server, so we'll also wait for next line: # * Restarting with stat if command[0] == 'serve': sys.stderr.write(proc.stderr.readline()) yield proc os.kill(proc.pid, signal.SIGINT) # Ctrl+C try: > _, errs = proc.communicate(timeout=5) tests\test_commands.py:94: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = , input = None, timeout = 5 def communicate(self, input=None, timeout=None): """Interact with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. Wait for process to terminate. The optional "input" argument should be data to be sent to the child process (if self.universal_newlines is True, this should be a string; if it is False, "input" should be bytes), or None, if no data should be sent to the child. communicate() returns a tuple (stdout, stderr). These will be bytes or, if self.universal_newlines was True, a string. """ if self._communication_started and input: raise ValueError("Cannot send input after starting communication") # Optimization: If we are not worried about timeouts, we haven't # started communicating, and we have one or zero pipes, using select() # or threads is unnecessary. if (timeout is None and not self._communication_started and [self.stdin, self.stdout, self.stderr].count(None) >= 2): stdout = None stderr = None if self.stdin: self._stdin_write(input) elif self.stdout: stdout = self.stdout.read() self.stdout.close() elif self.stderr: stderr = self.stderr.read() self.stderr.close() self.wait() else: if timeout is not None: endtime = _time() + timeout else: endtime = None try: > stdout, stderr = self._communicate(input, endtime, timeout) ..\AppData\Local\Programs\Python\Python36-32\Lib\subprocess.py:836: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = , input = None, endtime = 1234.497 orig_timeout = 5 def _communicate(self, input, endtime, orig_timeout): # Start reader threads feeding into a list hanging off of this # object, unless they've already been started. if self.stdout and not hasattr(self, "_stdout_buff"): self._stdout_buff = [] self.stdout_thread = \ threading.Thread(target=self._readerthread, args=(self.stdout, self._stdout_buff)) self.stdout_thread.daemon = True self.stdout_thread.start() if self.stderr and not hasattr(self, "_stderr_buff"): self._stderr_buff = [] self.stderr_thread = \ threading.Thread(target=self._readerthread, args=(self.stderr, self._stderr_buff)) self.stderr_thread.daemon = True self.stderr_thread.start() if self.stdin: self._stdin_write(input) # Wait for the reader threads, or time out. If we time out, the # threads remain reading and the fds left open in case the user # calls communicate again. if self.stdout is not None: self.stdout_thread.join(self._remaining_time(endtime)) if self.stdout_thread.is_alive(): raise TimeoutExpired(self.args, orig_timeout) if self.stderr is not None: self.stderr_thread.join(self._remaining_time(endtime)) if self.stderr_thread.is_alive(): > raise TimeoutExpired(self.args, orig_timeout) E subprocess.TimeoutExpired: Command '('C:\\Users\\Linux\\elsa\\.tox\\py36\\Scripts\\python.exe', 'tests/fixtures\\website.py', 'serve')' timed out after 5 seconds ..\AppData\Local\Programs\Python\Python36-32\Lib\subprocess.py:1088: TimeoutExpired During handling of the above exception, another exception occurred: config = <_pytest.config.Config object at 0x01C5B0D0> doit = def wrap_session(config, doit): """Skeleton command line program""" session = Session(config) session.exitstatus = EXIT_OK initstate = 0 try: try: config._do_configure() initstate = 1 config.hook.pytest_sessionstart(session=session) initstate = 2 > session.exitstatus = doit(config, session) or 0 .tox\py36\lib\site-packages\_pytest\main.py:98: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ config = <_pytest.config.Config object at 0x01C5B0D0> session = def _main(config, session): """ default command line protocol for initialization, session, running tests and reporting. """ config.hook.pytest_collection(session=session) > config.hook.pytest_runtestloop(session=session) .tox\py36\lib\site-packages\_pytest\main.py:133: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_HookCaller 'pytest_runtestloop'> kwargs = {'__multicall__': <_MultiCall 0 results, 0 meths, kwargs={'session': , '__multicall__': <_MultiCall 0 results, 0 meths, kwargs={...}>}>, 'session': } def __call__(self, **kwargs): assert not self.is_historic() > return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs) .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:745: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_pytest.config.PytestPluginManager object at 0x01A24290> hook = <_HookCaller 'pytest_runtestloop'>, methods = [] kwargs = {'__multicall__': <_MultiCall 0 results, 0 meths, kwargs={'session': , '__multicall__': <_MultiCall 0 results, 0 meths, kwargs={...}>}>, 'session': } def _hookexec(self, hook, methods, kwargs): # called from all hookcaller instances. # enable_tracing will set its own wrapping function at self._inner_hookexec > return self._inner_hookexec(hook, methods, kwargs) .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:339: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ hook = <_HookCaller 'pytest_runtestloop'>, methods = [] kwargs = {'__multicall__': <_MultiCall 0 results, 0 meths, kwargs={'session': , '__multicall__': <_MultiCall 0 results, 0 meths, kwargs={...}>}>, 'session': } self._inner_hookexec = lambda hook, methods, kwargs: \ > _MultiCall(methods, kwargs, hook.spec_opts).execute() .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:334: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_MultiCall 0 results, 0 meths, kwargs={'session': , '__multicall__': <_MultiCall 0 results, 0 meths, kwargs={...}>}> def execute(self): all_kwargs = self.kwargs self.results = results = [] firstresult = self.specopts.get("firstresult") while self.hook_impls: hook_impl = self.hook_impls.pop() try: args = [all_kwargs[argname] for argname in hook_impl.argnames] except KeyError: for argname in hook_impl.argnames: if argname not in all_kwargs: raise HookCallError( "hook call must provide argument %r" % (argname,)) if hook_impl.hookwrapper: return _wrapped_call(hook_impl.function(*args), self.execute) > res = hook_impl.function(*args) .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:614: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ session = def pytest_runtestloop(session): if (session.testsfailed and not session.config.option.continue_on_collection_errors): raise session.Interrupted( "%d errors during collection" % session.testsfailed) if session.config.option.collectonly: return True for i, item in enumerate(session.items): nextitem = session.items[i+1] if i+1 < len(session.items) else None > item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem) .tox\py36\lib\site-packages\_pytest\main.py:154: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_HookCaller 'pytest_runtest_protocol'> kwargs = {'__multicall__': <_MultiCall 0 results, 0 meths, kwargs={'item': , 'nextitem': }>, 'item': , 'nextitem': } def __call__(self, **kwargs): assert not self.is_historic() > return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs) .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:745: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_pytest.config.PytestPluginManager object at 0x01A24290> hook = <_HookCaller 'pytest_runtest_protocol'>, methods = [] kwargs = {'__multicall__': <_MultiCall 0 results, 0 meths, kwargs={'item': , 'nextitem': }>, 'item': , 'nextitem': } def _hookexec(self, hook, methods, kwargs): # called from all hookcaller instances. # enable_tracing will set its own wrapping function at self._inner_hookexec > return self._inner_hookexec(hook, methods, kwargs) .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:339: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ hook = <_HookCaller 'pytest_runtest_protocol'>, methods = [] kwargs = {'__multicall__': <_MultiCall 0 results, 0 meths, kwargs={'item': , 'nextitem': }>, 'item': , 'nextitem': } self._inner_hookexec = lambda hook, methods, kwargs: \ > _MultiCall(methods, kwargs, hook.spec_opts).execute() .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:334: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_MultiCall 0 results, 0 meths, kwargs={'item': , 'nextitem': , '__multicall__': <_MultiCall 0 results, 0 meths, kwargs={...}>}> def execute(self): all_kwargs = self.kwargs self.results = results = [] firstresult = self.specopts.get("firstresult") while self.hook_impls: hook_impl = self.hook_impls.pop() try: args = [all_kwargs[argname] for argname in hook_impl.argnames] except KeyError: for argname in hook_impl.argnames: if argname not in all_kwargs: raise HookCallError( "hook call must provide argument %r" % (argname,)) if hook_impl.hookwrapper: > return _wrapped_call(hook_impl.function(*args), self.execute) .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:613: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ wrap_controller = func = , 'nextitem': , '__multicall__': <_MultiCall 0 results, 0 meths, kwargs={...}>}>> def _wrapped_call(wrap_controller, func): """ Wrap calling to a function with a generator which needs to yield exactly once. The yield point will trigger calling the wrapped function and return its _CallOutcome to the yield point. The generator then needs to finish (raise StopIteration) in order for the wrapped call to complete. """ try: next(wrap_controller) # first yield except StopIteration: _raise_wrapfail(wrap_controller, "did not yield") call_outcome = _CallOutcome(func) try: wrap_controller.send(call_outcome) _raise_wrapfail(wrap_controller, "has second yield") except StopIteration: pass > return call_outcome.get_result() .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:254: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_pytest.vendored_packages.pluggy._CallOutcome object at 0x02CF9B70> def get_result(self): if self.excinfo is None: return self.result else: ex = self.excinfo if _py3: > raise ex[1].with_traceback(ex[2]) .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:279: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_pytest.vendored_packages.pluggy._CallOutcome object at 0x02CF9B70> func = , 'nextitem': , '__multicall__': <_MultiCall 0 results, 0 meths, kwargs={...}>}>> def __init__(self, func): try: > self.result = func() .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:265: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_MultiCall 0 results, 0 meths, kwargs={'item': , 'nextitem': , '__multicall__': <_MultiCall 0 results, 0 meths, kwargs={...}>}> def execute(self): all_kwargs = self.kwargs self.results = results = [] firstresult = self.specopts.get("firstresult") while self.hook_impls: hook_impl = self.hook_impls.pop() try: args = [all_kwargs[argname] for argname in hook_impl.argnames] except KeyError: for argname in hook_impl.argnames: if argname not in all_kwargs: raise HookCallError( "hook call must provide argument %r" % (argname,)) if hook_impl.hookwrapper: return _wrapped_call(hook_impl.function(*args), self.execute) > res = hook_impl.function(*args) .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:614: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ item = , nextitem = def pytest_runtest_protocol(item, nextitem): item.ihook.pytest_runtest_logstart( nodeid=item.nodeid, location=item.location, ) > runtestprotocol(item, nextitem=nextitem) .tox\py36\lib\site-packages\_pytest\runner.py:66: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ item = , log = True nextitem = def runtestprotocol(item, log=True, nextitem=None): hasrequest = hasattr(item, "_request") if hasrequest and not item._request: item._initrequest() rep = call_and_report(item, "setup", log) reports = [rep] if rep.passed: if item.config.option.setupshow: show_test_item(item) if not item.config.option.setuponly: > reports.append(call_and_report(item, "call", log)) .tox\py36\lib\site-packages\_pytest\runner.py:79: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ item = , when = 'call', log = True, kwds = {} def call_and_report(item, when, log=True, **kwds): > call = call_runtest_hook(item, when, **kwds) .tox\py36\lib\site-packages\_pytest\runner.py:133: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ item = , when = 'call', kwds = {} hookname = 'pytest_runtest_call' def call_runtest_hook(item, when, **kwds): hookname = "pytest_runtest_" + when ihook = getattr(item.ihook, hookname) > return CallInfo(lambda: ihook(item=item, **kwds), when=when) .tox\py36\lib\site-packages\_pytest\runner.py:151: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <[AttributeError("'CallInfo' object has no attribute 'result'") raised in repr()] CallInfo object at 0x2cf9d50> func = . at 0x02674660> when = 'call' def __init__(self, func, when): #: context of invocation: one of "setup", "call", #: "teardown", "memocollect" self.when = when self.start = time() try: > self.result = func() .tox\py36\lib\site-packages\_pytest\runner.py:163: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > return CallInfo(lambda: ihook(item=item, **kwds), when=when) .tox\py36\lib\site-packages\_pytest\runner.py:151: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_HookCaller 'pytest_runtest_call'> kwargs = {'__multicall__': <_MultiCall 0 results, 0 meths, kwargs={'item': , '__multicall__': <_MultiCall 0 results, 0 meths, kwargs={...}>}>, 'item': } def __call__(self, **kwargs): assert not self.is_historic() > return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs) .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:745: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_pytest.config.PytestPluginManager object at 0x01A24290> hook = <_HookCaller 'pytest_runtest_call'>, methods = [] kwargs = {'__multicall__': <_MultiCall 0 results, 0 meths, kwargs={'item': , '__multicall__': <_MultiCall 0 results, 0 meths, kwargs={...}>}>, 'item': } def _hookexec(self, hook, methods, kwargs): # called from all hookcaller instances. # enable_tracing will set its own wrapping function at self._inner_hookexec > return self._inner_hookexec(hook, methods, kwargs) .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:339: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ hook = <_HookCaller 'pytest_runtest_call'>, methods = [] kwargs = {'__multicall__': <_MultiCall 0 results, 0 meths, kwargs={'item': , '__multicall__': <_MultiCall 0 results, 0 meths, kwargs={...}>}>, 'item': } self._inner_hookexec = lambda hook, methods, kwargs: \ > _MultiCall(methods, kwargs, hook.spec_opts).execute() .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:334: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_MultiCall 0 results, 0 meths, kwargs={'item': , '__multicall__': <_MultiCall 0 results, 0 meths, kwargs={...}>}> def execute(self): all_kwargs = self.kwargs self.results = results = [] firstresult = self.specopts.get("firstresult") while self.hook_impls: hook_impl = self.hook_impls.pop() try: args = [all_kwargs[argname] for argname in hook_impl.argnames] except KeyError: for argname in hook_impl.argnames: if argname not in all_kwargs: raise HookCallError( "hook call must provide argument %r" % (argname,)) if hook_impl.hookwrapper: > return _wrapped_call(hook_impl.function(*args), self.execute) .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:613: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ wrap_controller = func = , '__multicall__': <_MultiCall 0 results, 0 meths, kwargs={...}>}>> def _wrapped_call(wrap_controller, func): """ Wrap calling to a function with a generator which needs to yield exactly once. The yield point will trigger calling the wrapped function and return its _CallOutcome to the yield point. The generator then needs to finish (raise StopIteration) in order for the wrapped call to complete. """ try: next(wrap_controller) # first yield except StopIteration: _raise_wrapfail(wrap_controller, "did not yield") call_outcome = _CallOutcome(func) try: wrap_controller.send(call_outcome) _raise_wrapfail(wrap_controller, "has second yield") except StopIteration: pass > return call_outcome.get_result() .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:254: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_pytest.vendored_packages.pluggy._CallOutcome object at 0x02CF9D70> def get_result(self): if self.excinfo is None: return self.result else: ex = self.excinfo if _py3: > raise ex[1].with_traceback(ex[2]) .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:279: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_pytest.vendored_packages.pluggy._CallOutcome object at 0x02CF9D70> func = , '__multicall__': <_MultiCall 0 results, 0 meths, kwargs={...}>}>> def __init__(self, func): try: > self.result = func() .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:265: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_MultiCall 0 results, 0 meths, kwargs={'item': , '__multicall__': <_MultiCall 0 results, 0 meths, kwargs={...}>}> def execute(self): all_kwargs = self.kwargs self.results = results = [] firstresult = self.specopts.get("firstresult") while self.hook_impls: hook_impl = self.hook_impls.pop() try: args = [all_kwargs[argname] for argname in hook_impl.argnames] except KeyError: for argname in hook_impl.argnames: if argname not in all_kwargs: raise HookCallError( "hook call must provide argument %r" % (argname,)) if hook_impl.hookwrapper: return _wrapped_call(hook_impl.function(*args), self.execute) > res = hook_impl.function(*args) .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:614: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ item = def pytest_runtest_call(item): try: > item.runtest() .tox\py36\lib\site-packages\_pytest\runner.py:104: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def runtest(self): """ execute the underlying test function. """ > self.ihook.pytest_pyfunc_call(pyfuncitem=self) .tox\py36\lib\site-packages\_pytest\python.py:1574: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_HookCaller 'pytest_pyfunc_call'> kwargs = {'__multicall__': <_MultiCall 0 results, 0 meths, kwargs={'pyfuncitem': , '__multicall__': <_MultiCall 0 results, 0 meths, kwargs={...}>}>, 'pyfuncitem': } def __call__(self, **kwargs): assert not self.is_historic() > return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs) .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:745: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_pytest.config.PytestPluginManager object at 0x01A24290> hook = <_HookCaller 'pytest_pyfunc_call'>, methods = [] kwargs = {'__multicall__': <_MultiCall 0 results, 0 meths, kwargs={'pyfuncitem': , '__multicall__': <_MultiCall 0 results, 0 meths, kwargs={...}>}>, 'pyfuncitem': } def _hookexec(self, hook, methods, kwargs): # called from all hookcaller instances. # enable_tracing will set its own wrapping function at self._inner_hookexec > return self._inner_hookexec(hook, methods, kwargs) .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:339: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ hook = <_HookCaller 'pytest_pyfunc_call'>, methods = [] kwargs = {'__multicall__': <_MultiCall 0 results, 0 meths, kwargs={'pyfuncitem': , '__multicall__': <_MultiCall 0 results, 0 meths, kwargs={...}>}>, 'pyfuncitem': } self._inner_hookexec = lambda hook, methods, kwargs: \ > _MultiCall(methods, kwargs, hook.spec_opts).execute() .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:334: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_MultiCall 0 results, 0 meths, kwargs={'pyfuncitem': , '__multicall__': <_MultiCall 0 results, 0 meths, kwargs={...}>}> def execute(self): all_kwargs = self.kwargs self.results = results = [] firstresult = self.specopts.get("firstresult") while self.hook_impls: hook_impl = self.hook_impls.pop() try: args = [all_kwargs[argname] for argname in hook_impl.argnames] except KeyError: for argname in hook_impl.argnames: if argname not in all_kwargs: raise HookCallError( "hook call must provide argument %r" % (argname,)) if hook_impl.hookwrapper: > return _wrapped_call(hook_impl.function(*args), self.execute) .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:613: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ wrap_controller = func = , '__multicall__': <_MultiCall 0 results, 0 meths, kwargs={...}>}>> def _wrapped_call(wrap_controller, func): """ Wrap calling to a function with a generator which needs to yield exactly once. The yield point will trigger calling the wrapped function and return its _CallOutcome to the yield point. The generator then needs to finish (raise StopIteration) in order for the wrapped call to complete. """ try: next(wrap_controller) # first yield except StopIteration: _raise_wrapfail(wrap_controller, "did not yield") call_outcome = _CallOutcome(func) try: wrap_controller.send(call_outcome) _raise_wrapfail(wrap_controller, "has second yield") except StopIteration: pass > return call_outcome.get_result() .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:254: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_pytest.vendored_packages.pluggy._CallOutcome object at 0x02CF9F30> def get_result(self): if self.excinfo is None: return self.result else: ex = self.excinfo if _py3: > raise ex[1].with_traceback(ex[2]) .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:279: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_pytest.vendored_packages.pluggy._CallOutcome object at 0x02CF9F30> func = , '__multicall__': <_MultiCall 0 results, 0 meths, kwargs={...}>}>> def __init__(self, func): try: > self.result = func() .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:265: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_MultiCall 0 results, 0 meths, kwargs={'pyfuncitem': , '__multicall__': <_MultiCall 0 results, 0 meths, kwargs={...}>}> def execute(self): all_kwargs = self.kwargs self.results = results = [] firstresult = self.specopts.get("firstresult") while self.hook_impls: hook_impl = self.hook_impls.pop() try: args = [all_kwargs[argname] for argname in hook_impl.argnames] except KeyError: for argname in hook_impl.argnames: if argname not in all_kwargs: raise HookCallError( "hook call must provide argument %r" % (argname,)) if hook_impl.hookwrapper: return _wrapped_call(hook_impl.function(*args), self.execute) > res = hook_impl.function(*args) .tox\py36\lib\site-packages\_pytest\vendored_packages\pluggy.py:614: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ pyfuncitem = @pytest.hookimpl(trylast=True) def pytest_pyfunc_call(pyfuncitem): testfunction = pyfuncitem.obj if pyfuncitem._isyieldedfunction(): testfunction(*pyfuncitem._args) else: funcargs = pyfuncitem.funcargs testargs = {} for arg in pyfuncitem._fixtureinfo.argnames: testargs[arg] = funcargs[arg] > testfunction(**testargs) .tox\py36\lib\site-packages\_pytest\python.py:154: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ elsa = def test_serve(elsa): with elsa.run_bg('serve'): > assert 'SUCCESS' in requests.get('http://localhost:8003/').text tests\test_commands.py:190: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = , type = None value = None, traceback = None def __exit__(self, type, value, traceback): if type is None: try: > next(self.gen) ..\AppData\Local\Programs\Python\Python36-32\Lib\contextlib.py:89: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = , script = None command = ('serve',), proc = @contextmanager def run_bg(self, *command, script=None): print('COMMAND IN BACKGROUND: python website.py', *command) proc = subprocess.Popen(self.create_command(command, script), stderr=subprocess.PIPE, universal_newlines=True) # Wait for the server to start, # i.e. wait for the first line on stderr: # * Running on http://127.0.0.1:8003/ (Press CTRL+C to quit) sys.stderr.write(proc.stderr.readline()) # With the serve command, Flask is running in debug and restarts # the server, so we'll also wait for next line: # * Restarting with stat if command[0] == 'serve': sys.stderr.write(proc.stderr.readline()) yield proc os.kill(proc.pid, signal.SIGINT) # Ctrl+C try: _, errs = proc.communicate(timeout=5) except subprocess.TimeoutExpired: proc.kill() > _, errs = proc.communicate() tests\test_commands.py:97: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = , input = None, timeout = None def communicate(self, input=None, timeout=None): """Interact with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. Wait for process to terminate. The optional "input" argument should be data to be sent to the child process (if self.universal_newlines is True, this should be a string; if it is False, "input" should be bytes), or None, if no data should be sent to the child. communicate() returns a tuple (stdout, stderr). These will be bytes or, if self.universal_newlines was True, a string. """ if self._communication_started and input: raise ValueError("Cannot send input after starting communication") # Optimization: If we are not worried about timeouts, we haven't # started communicating, and we have one or zero pipes, using select() # or threads is unnecessary. if (timeout is None and not self._communication_started and [self.stdin, self.stdout, self.stderr].count(None) >= 2): stdout = None stderr = None if self.stdin: self._stdin_write(input) elif self.stdout: stdout = self.stdout.read() self.stdout.close() elif self.stderr: stderr = self.stderr.read() self.stderr.close() self.wait() else: if timeout is not None: endtime = _time() + timeout else: endtime = None try: > stdout, stderr = self._communicate(input, endtime, timeout) ..\AppData\Local\Programs\Python\Python36-32\Lib\subprocess.py:836: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = , input = None, endtime = None orig_timeout = None def _communicate(self, input, endtime, orig_timeout): # Start reader threads feeding into a list hanging off of this # object, unless they've already been started. if self.stdout and not hasattr(self, "_stdout_buff"): self._stdout_buff = [] self.stdout_thread = \ threading.Thread(target=self._readerthread, args=(self.stdout, self._stdout_buff)) self.stdout_thread.daemon = True self.stdout_thread.start() if self.stderr and not hasattr(self, "_stderr_buff"): self._stderr_buff = [] self.stderr_thread = \ threading.Thread(target=self._readerthread, args=(self.stderr, self._stderr_buff)) self.stderr_thread.daemon = True self.stderr_thread.start() if self.stdin: self._stdin_write(input) # Wait for the reader threads, or time out. If we time out, the # threads remain reading and the fds left open in case the user # calls communicate again. if self.stdout is not None: self.stdout_thread.join(self._remaining_time(endtime)) if self.stdout_thread.is_alive(): raise TimeoutExpired(self.args, orig_timeout) if self.stderr is not None: > self.stderr_thread.join(self._remaining_time(endtime)) ..\AppData\Local\Programs\Python\Python36-32\Lib\subprocess.py:1086: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = , timeout = None def join(self, timeout=None): """Wait until the thread terminates. This blocks the calling thread until the thread whose join() method is called terminates -- either normally or through an unhandled exception or until the optional timeout occurs. When the timeout argument is present and not None, it should be a floating point number specifying a timeout for the operation in seconds (or fractions thereof). As join() always returns None, you must call isAlive() after join() to decide whether a timeout happened -- if the thread is still alive, the join() call timed out. When the timeout argument is not present or None, the operation will block until the thread terminates. A thread can be join()ed many times. join() raises a RuntimeError if an attempt is made to join the current thread as that would cause a deadlock. It is also an error to join() a thread before it has been started and attempts to do so raises the same exception. """ if not self._initialized: raise RuntimeError("Thread.__init__() not called") if not self._started.is_set(): raise RuntimeError("cannot join thread before it is started") if self is current_thread(): raise RuntimeError("cannot join current thread") if timeout is None: > self._wait_for_tstate_lock() ..\AppData\Local\Programs\Python\Python36-32\Lib\threading.py:1056: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = , block = True, timeout = -1 def _wait_for_tstate_lock(self, block=True, timeout=-1): # Issue #18808: wait for the thread state to be gone. # At the end of the thread's life, after all knowledge of the thread # is removed from C data structures, C code releases our _tstate_lock. # This method passes its arguments to _tstate_lock.acquire(). # If the lock is acquired, the C code is done, and self._stop() is # called. That sets ._is_stopped to True, and ._tstate_lock to None. lock = self._tstate_lock if lock is None: # already determined that the C code is done assert self._is_stopped > elif lock.acquire(block, timeout): E KeyboardInterrupt ..\AppData\Local\Programs\Python\Python36-32\Lib\threading.py:1072: KeyboardInterrupt ==================== 5 skipped, 2 xfailed in 28.47 seconds ==================== ```
hroncok commented 7 years ago

BTW serving works, so I guess the problem might be in sending Ctrl+C to the process. Will google a bit.

encukou commented 7 years ago

I don't think this should block the release.

hroncok commented 7 years ago

Non-serving tests all pass ;) Yay!

hroncok commented 7 years ago

I believe we are in hell.

encukou commented 7 years ago

Hell indeed. Release without it?

I guess a solution would be adding a /shutdown/endpoint to the test apps, and accessing that. Might theoretically help #17 as well.

hroncok commented 7 years ago

I was about to say we can implement http://flask.pocoo.org/snippets/67/ :)

For serve, we just need to inject the route. For freeze, we'd need to use custom freezer redefining the make_static_app method.

hroncok commented 7 years ago

OK, I've added AppVeyor config file, but I have 2 problems:

hroncok commented 7 years ago

With my own repository, the integration works. Co I suppose @encukou would need to set up it.

hroncok commented 7 years ago

Passing https://ci.appveyor.com/project/hroncok/elsa/build/1.0.5

encukou commented 7 years ago

https://ci.appveyor.com/project/encukou/elsa is now set up. Waiting to see if the next PR triggers it.

hroncok commented 7 years ago

Last commit did.

hroncok commented 7 years ago

And PR as well. Ta dah! Thanks