Skip to content

Commit d0a7775

Browse files
committed
Merge pull request #12 from browserstack/daemon_mode
Daemon mode
2 parents 42abc4a + 01a77ff commit d0a7775

File tree

4 files changed

+41
-30
lines changed

4 files changed

+41
-30
lines changed

.travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ python:
99

1010
before_install:
1111
- true && `base64 --decode <<< ZXhwb3J0IEJST1dTRVJTVEFDS19BQ0NFU1NfS0VZPUh5VmZydXJvb3dYb041eGhLZEs2Cg==`
12+
- pip install psutil
1213

1314
script: python -m unittest discover

browserstack/local.py

+24-24
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import subprocess, os, time
1+
import subprocess, os, time, json, psutil
22
from browserstack.local_binary import LocalBinary
33
from browserstack.bserrors import BrowserStackLocalError
44

@@ -17,12 +17,17 @@ def __xstr(self, key, value):
1717
return ['-' + key, value]
1818

1919
def _generate_cmd(self):
20-
cmd = [self.binary_path, '-logFile', self.local_logfile_path, self.key]
20+
cmd = [self.binary_path, '-d', 'start', '-logFile', self.local_logfile_path, self.key]
2121
for o in self.options.keys():
2222
if self.options.get(o) is not None:
2323
cmd = cmd + self.__xstr(o, self.options.get(o))
2424
return cmd
2525

26+
def _generate_stop_cmd(self):
27+
cmd = self._generate_cmd()
28+
cmd[2] = 'stop'
29+
return cmd
30+
2631
def start(self, **kwargs):
2732
self.options = kwargs
2833

@@ -43,34 +48,29 @@ def start(self, **kwargs):
4348
if "onlyCommand" in kwargs and kwargs["onlyCommand"]:
4449
return
4550

46-
self.proc = subprocess.Popen(self._generate_cmd(), stdout=subprocess.PIPE)
47-
self.stderr = self.proc.stderr
51+
self.proc = subprocess.Popen(self._generate_cmd(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
52+
(out, err) = self.proc.communicate()
4853

4954
os.system('echo "" > "'+ self.local_logfile_path +'"')
50-
with open(self.local_logfile_path, 'r') as local_logfile:
51-
while True:
52-
line = local_logfile.readline()
53-
if 'Error:' in line.strip():
54-
raise BrowserStackLocalError(line)
55-
elif line.strip() == 'Press Ctrl-C to exit':
56-
break
55+
try:
56+
if out:
57+
data = json.loads(out.decode())
58+
else:
59+
data = json.loads(err.decode())
5760

58-
while True:
59-
if self.isRunning():
60-
break
61-
time.sleep(1)
61+
if data['state'] != "connected":
62+
raise BrowserStackLocalError(data["message"])
63+
else:
64+
self.pid = data['pid']
65+
except ValueError:
66+
raise BrowserStackLocalError('Error parsing JSON output from daemon')
6267

6368
def isRunning(self):
64-
if (hasattr(self, 'proc')):
65-
return True if self.proc.poll() is None else False
66-
return False
69+
return hasattr(self, 'pid') and psutil.pid_exists(self.pid)
6770

6871
def stop(self):
6972
try:
70-
self.proc.terminate()
71-
while True:
72-
if not self.isRunning():
73-
break
74-
time.sleep(1)
73+
proc = subprocess.Popen(self._generate_stop_cmd(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
74+
(out, err) = proc.communicate()
7575
except Exception as e:
76-
return
76+
return

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
setup(
33
name = 'browserstack-local',
44
packages = ['browserstack'],
5-
version = '0.3.1',
5+
version = '1.0.0',
66
description = 'Python bindings for Browserstack Local',
77
author = 'BrowserStack',
88
author_email = '[email protected]',

tests/test_local.py

+15-5
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,21 @@ def test_start_local(self):
1212
self.local.start()
1313
self.assertNotEqual(self.local.proc.pid, 0)
1414

15+
def test_running(self):
16+
self.assertFalse(self.local.isRunning())
17+
self.local.start()
18+
self.assertTrue(self.local.isRunning())
19+
20+
def test_multiple(self):
21+
self.assertFalse(self.local.isRunning())
22+
self.local.start()
23+
self.assertTrue(self.local.isRunning())
24+
try:
25+
self.local2 = Local(os.environ['BROWSERSTACK_ACCESS_KEY'])
26+
self.local2.start()
27+
except BrowserStackLocalError as e:
28+
self.assertEqual(str(e), "Either another browserstack local client is running on your machine or some server is listening on port 45691")
29+
1530
def test_verbose(self):
1631
self.local.start(v=True, onlyCommand=True)
1732
self.assertIn('-v', self.local._generate_cmd())
@@ -64,8 +79,3 @@ def test_local_identifier(self):
6479
self.local.start(localIdentifier='mytunnel', onlyCommand=True)
6580
self.assertIn('-localIdentifier', self.local._generate_cmd())
6681
self.assertIn('mytunnel', self.local._generate_cmd())
67-
68-
def test_running(self):
69-
self.assertFalse(self.local.isRunning())
70-
self.local.start()
71-
self.assertTrue(self.local.isRunning())

0 commit comments

Comments
 (0)