Skip to content

Commit

Permalink
More promissing way to find the bddcli-bootstrapper. Added windows in…
Browse files Browse the repository at this point in the history
…to Github actions matrix
  • Loading branch information
pylover committed Sep 23, 2021
1 parent 97ebe9b commit 4ed0d76
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 78 deletions.
9 changes: 5 additions & 4 deletions .github/workflows/build.yml
Expand Up @@ -5,7 +5,7 @@ name: Build

on:
push:
branches: [ master ]
branches: [ master, platform/windows ]
tags: [ 'v*' ]

pull_request:
Expand All @@ -14,9 +14,10 @@ on:
jobs:
test:
name: Pytest
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
python-version: ['3.6', '3.7', '3.8']

steps:
Expand All @@ -31,9 +32,9 @@ jobs:
python -m pip install -r requirements-ci.txt
python -m pip install -e .
- name: Lint with PyLama
run: make lint
run: pylama
- name: Test with pytest
run: make cover
run: pytest --cov=bddcli tests
- name: Coveralls
run: coveralls
env:
Expand Down
6 changes: 3 additions & 3 deletions bddcli/authoring/given.py
Expand Up @@ -2,7 +2,7 @@

from ..context import Context
from ..calls import FirstCall, AlteredCall, Call
from ..platform_ import killpg
from ..platform_ import killpg_by_pid
from .story import Story
from .manipulation import Manipulator

Expand All @@ -22,9 +22,9 @@ def invoke(self, call):
else:
call.conclude(self.application)

def kill(self, s=signal.SIGTERM):
def kill(self, sig=signal.SIGTERM):
call = self.current_call
killpg(call.process.pid, s)
killpg_by_pid(call.process.pid, sig)

def wait(self, stdin=None, timeout=None):
call = self.current_call
Expand Down
87 changes: 46 additions & 41 deletions bddcli/platform_.py
@@ -1,55 +1,60 @@
''' A module for platform-dependent functions
'''
import os
import sys
import subprocess as sp


def killpg(pid, s):
if os.name == "nt":
# On Windows, os module can't kill processes by group
# Kill all children indiscriminately instead
sp.call(['taskkill', '/T', '/F', '/PID',
str(pid)])
else:
if os.name == 'nt':
BOOTSTRAPPER_FILENAME = 'bddcli-bootstrapper.exe'
VENV_BINDIR = 'Scripts'

# On Windows, os module can't kill processes by group
# Kill all children indiscriminately instead
def killpg_by_pid(pid, s):
# FIXME: use s here
sp.call(['taskkill', '/T', '/F', '/PID', str(pid)])

else:
BOOTSTRAPPER_FILENAME = 'bddcli-bootstrapper'
VENV_BINDIR = 'bin'

def killpg_by_pid(pid, s):
os.killpg(os.getpgid(pid), s)


def popen(command, environ, **kw):
if os.name == "nt":
# On Windows, the specified env must include a valid SystemRoot
# Use a current value
if environ is not None:
environ["SystemRoot"] = os.environ["SystemRoot"]
process = sp.Popen(
' '.join(command),
stdout=sp.PIPE,
stderr=sp.PIPE,
shell=True,
env=environ,
**kw,
)
# Find bootstrapper location
if 'VIRTUAL_ENV' in os.environ:
BOOTSTRAPPER_PATH = os.path.join(os.environ['VIRTUAL_ENV'], VENV_BINDIR)
else:
for d in sys.path:
if os.path.isfile(d):
d = os.path.dirname(d)
try:
if BOOTSTRAPPER_FILENAME in os.listdir(d):
BOOTSTRAPPER_PATH = d
break
except (FileNotFoundError, NotADirectoryError):
# Nothing guarantees a PATH entry is valid
continue

else:
process = sp.Popen(
' '.join(command),
stdout=sp.PIPE,
stderr=sp.PIPE,
shell=True,
env=environ,
preexec_fn=os.setpgrp,
**kw,
raise FileNotFoundError(
f'Cannot find {BOOTSTRAPPER_FILENAME} in your PATH '
f'environment variable: {sys.path}'
)
return process


def bootstrapper_name():
if os.name == "nt":
return 'bddcli_bootstrapper'
else:
return 'bddcli-bootstrapper'
BOOTSTRAPPER_FULLPATH = os.path.join(BOOTSTRAPPER_PATH, BOOTSTRAPPER_FILENAME)


def form_bootstrapper_path(bindir, bootstrapper):
def Popen(command, env=None, **kw):
if os.name == "nt":
return os.path.join(bindir, bootstrapper, "__init__.py")
# On Windows, the specified env must include a valid SystemRoot
# Use a current value
if env is None:
env = {}

env["SystemRoot"] = os.environ["SystemRoot"]
kw['creationflags'] = sp.CREATE_NEW_PROCESS_GROUP
else:
return os.path.join(bindir, bootstrapper)
kw['preexec_fn'] = os.setpgrp

return sp.Popen(command, env=env, **kw)
41 changes: 11 additions & 30 deletions bddcli/runners.py
@@ -1,13 +1,7 @@
import os
import abc
import sys
from os import path
import subprocess as sp

from .platform_ import (
bootstrapper_name,
form_bootstrapper_path,
popen
)
from .platform_ import Popen, BOOTSTRAPPER_FULLPATH


class Runner(metaclass=abc.ABCMeta):
Expand All @@ -18,33 +12,13 @@ def run(self, arguments=None, environ=None, **kw): # pragma: no cover

class SubprocessRunner(Runner):

def _findbindir(self):
bootstrapper = bootstrapper_name()
for d in sys.path:
try:
if bootstrapper in os.listdir(d):
return d
except FileNotFoundError or NotADirectoryError:
# Nothing guarantees a PATH entry is valid
pass

@property
def bootstrapper(self):
bootstrapper = bootstrapper_name()
if 'VIRTUAL_ENV' in os.environ:
bindir = path.join(os.environ['VIRTUAL_ENV'], 'bin')
else: # pragma: no cover
bindir = self._findbindir()

return form_bootstrapper_path(bindir, bootstrapper)

def __init__(self, application, environ=None):
self.application = application
self.environ = environ

def run(self, arguments=None, working_directory=None, environ=None, **kw):
command = [
self.bootstrapper,
BOOTSTRAPPER_FULLPATH,
self.application.name,
self.application.address,
working_directory or '.',
Expand All @@ -53,5 +27,12 @@ def run(self, arguments=None, working_directory=None, environ=None, **kw):
if arguments:
command += arguments

process = popen(command, environ, **kw)
process = Popen(
' '.join(command),
stdout=sp.PIPE,
stderr=sp.PIPE,
shell=True,
env=environ,
**kw,
)
return process

0 comments on commit 4ed0d76

Please sign in to comment.