browserstack-local 1.2.9__tar.gz → 1.2.11__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {browserstack-local-1.2.9 → browserstack-local-1.2.11}/PKG-INFO +1 -1
- {browserstack-local-1.2.9 → browserstack-local-1.2.11}/browserstack/local.py +7 -1
- {browserstack-local-1.2.9 → browserstack-local-1.2.11}/browserstack/local_binary.py +81 -18
- {browserstack-local-1.2.9 → browserstack-local-1.2.11}/browserstack_local.egg-info/PKG-INFO +1 -1
- {browserstack-local-1.2.9 → browserstack-local-1.2.11}/setup.py +1 -1
- {browserstack-local-1.2.9 → browserstack-local-1.2.11}/tests/test_local.py +1 -1
- {browserstack-local-1.2.9 → browserstack-local-1.2.11}/LICENSE.txt +0 -0
- {browserstack-local-1.2.9 → browserstack-local-1.2.11}/MANIFEST.in +0 -0
- {browserstack-local-1.2.9 → browserstack-local-1.2.11}/README +0 -0
- {browserstack-local-1.2.9 → browserstack-local-1.2.11}/README.md +0 -0
- {browserstack-local-1.2.9 → browserstack-local-1.2.11}/browserstack/__init__.py +0 -0
- {browserstack-local-1.2.9 → browserstack-local-1.2.11}/browserstack/bserrors.py +0 -0
- {browserstack-local-1.2.9 → browserstack-local-1.2.11}/browserstack_local.egg-info/SOURCES.txt +0 -0
- {browserstack-local-1.2.9 → browserstack-local-1.2.11}/browserstack_local.egg-info/dependency_links.txt +0 -0
- {browserstack-local-1.2.9 → browserstack-local-1.2.11}/browserstack_local.egg-info/requires.txt +0 -0
- {browserstack-local-1.2.9 → browserstack-local-1.2.11}/browserstack_local.egg-info/top_level.txt +0 -0
- {browserstack-local-1.2.9 → browserstack-local-1.2.11}/setup.cfg +0 -0
- {browserstack-local-1.2.9 → browserstack-local-1.2.11}/tests/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: browserstack-local
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.11
|
|
4
4
|
Summary: Python bindings for Browserstack Local
|
|
5
5
|
Home-page: https://github.com/browserstack/browserstack-local-python
|
|
6
6
|
Download-URL: https://github.com/browserstack/browserstack-local-python/archive/master.zip
|
|
@@ -15,6 +15,7 @@ class Local:
|
|
|
15
15
|
self.key = os.environ['BROWSERSTACK_ACCESS_KEY'] if 'BROWSERSTACK_ACCESS_KEY' in os.environ else key
|
|
16
16
|
self.options = kwargs
|
|
17
17
|
self.local_logfile_path = os.path.join(os.getcwd(), 'local.log')
|
|
18
|
+
LocalBinary.set_version(self.get_package_version())
|
|
18
19
|
|
|
19
20
|
def __xstr(self, key, value):
|
|
20
21
|
if key is None:
|
|
@@ -72,7 +73,12 @@ class Local:
|
|
|
72
73
|
self.binary_path = self.options['binarypath']
|
|
73
74
|
del self.options['binarypath']
|
|
74
75
|
else:
|
|
75
|
-
|
|
76
|
+
l = LocalBinary(self.key)
|
|
77
|
+
try:
|
|
78
|
+
self.binary_path = l.get_binary()
|
|
79
|
+
except Exception as e:
|
|
80
|
+
l = LocalBinary(self.key, e)
|
|
81
|
+
self.binary_path = l.get_binary()
|
|
76
82
|
|
|
77
83
|
if 'logfile' in self.options:
|
|
78
84
|
self.local_logfile_path = self.options['logfile']
|
|
@@ -1,29 +1,37 @@
|
|
|
1
1
|
import platform, os, sys, stat, tempfile, re, subprocess
|
|
2
2
|
from browserstack.bserrors import BrowserStackLocalError
|
|
3
|
+
import gzip
|
|
4
|
+
import json
|
|
3
5
|
|
|
4
6
|
try:
|
|
5
|
-
from urllib.request import urlopen
|
|
7
|
+
from urllib.request import urlopen, Request
|
|
6
8
|
except ImportError:
|
|
7
|
-
from urllib2 import urlopen
|
|
9
|
+
from urllib2 import urlopen, Request
|
|
8
10
|
|
|
9
11
|
class LocalBinary:
|
|
10
|
-
|
|
12
|
+
_version = None
|
|
13
|
+
|
|
14
|
+
def __init__(self, key, error_object=None):
|
|
15
|
+
self.key = key
|
|
16
|
+
self.error_object = error_object
|
|
11
17
|
is_64bits = sys.maxsize > 2**32
|
|
12
18
|
self.is_windows = False
|
|
13
19
|
osname = platform.system()
|
|
20
|
+
source_url = self.fetch_source_url() + '/'
|
|
21
|
+
|
|
14
22
|
if osname == 'Darwin':
|
|
15
|
-
self.http_path = "
|
|
23
|
+
self.http_path = source_url + "BrowserStackLocal-darwin-x64"
|
|
16
24
|
elif osname == 'Linux':
|
|
17
25
|
if self.is_alpine():
|
|
18
|
-
self.http_path = "
|
|
26
|
+
self.http_path = source_url + "BrowserStackLocal-alpine"
|
|
19
27
|
else:
|
|
20
28
|
if is_64bits:
|
|
21
|
-
self.http_path = "
|
|
29
|
+
self.http_path = source_url + "BrowserStackLocal-linux-x64"
|
|
22
30
|
else:
|
|
23
|
-
self.http_path = "
|
|
31
|
+
self.http_path = source_url + "BrowserStackLocal-linux-ia32"
|
|
24
32
|
else:
|
|
25
33
|
self.is_windows = True
|
|
26
|
-
self.http_path = "
|
|
34
|
+
self.http_path = source_url + "BrowserStackLocal.exe"
|
|
27
35
|
|
|
28
36
|
self.ordered_paths = [
|
|
29
37
|
os.path.join(os.path.expanduser('~'), '.browserstack'),
|
|
@@ -32,11 +40,38 @@ class LocalBinary:
|
|
|
32
40
|
]
|
|
33
41
|
self.path_index = 0
|
|
34
42
|
|
|
43
|
+
def fetch_source_url(self):
|
|
44
|
+
url = "https://local.browserstack.com/binary/api/v1/endpoint"
|
|
45
|
+
headers = {
|
|
46
|
+
"Content-Type": "application/json",
|
|
47
|
+
"Accept": "application/json"
|
|
48
|
+
}
|
|
49
|
+
data = {"auth_token": self.key}
|
|
50
|
+
|
|
51
|
+
if self.error_object is not None:
|
|
52
|
+
data["error_message"] = str(self.error_object)
|
|
53
|
+
headers["X-Local-Fallback-Cloudflare"] = "true"
|
|
54
|
+
|
|
55
|
+
req = Request(url, data=json.dumps(data).encode("utf-8"))
|
|
56
|
+
for key, value in headers.items():
|
|
57
|
+
req.add_header(key, value)
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
with urlopen(req) as response:
|
|
61
|
+
resp_bytes = response.read()
|
|
62
|
+
resp_str = resp_bytes.decode('utf-8')
|
|
63
|
+
resp_json = json.loads(resp_str)
|
|
64
|
+
return resp_json["data"]["endpoint"]
|
|
65
|
+
except Exception as e:
|
|
66
|
+
raise BrowserStackLocalError('Error trying to fetch the source url for downloading the binary: {}'.format(e))
|
|
67
|
+
|
|
68
|
+
@staticmethod
|
|
69
|
+
def set_version(version):
|
|
70
|
+
LocalBinary._version = version
|
|
71
|
+
|
|
35
72
|
def is_alpine(self):
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return True
|
|
39
|
-
return False
|
|
73
|
+
response = subprocess.check_output(["grep", "-w", "NAME", "/etc/os-release"])
|
|
74
|
+
return response.decode('utf-8').find('Alpine') > -1
|
|
40
75
|
|
|
41
76
|
def __make_path(self, dest_path):
|
|
42
77
|
try:
|
|
@@ -54,36 +89,64 @@ class LocalBinary:
|
|
|
54
89
|
return final_path
|
|
55
90
|
else:
|
|
56
91
|
self.path_index += 1
|
|
57
|
-
raise BrowserStackLocalError('Error trying to download BrowserStack Local binary')
|
|
92
|
+
raise BrowserStackLocalError('Error trying to download BrowserStack Local binary, exhausted user directories to download to.')
|
|
58
93
|
|
|
59
94
|
def download(self, chunk_size=8192, progress_hook=None):
|
|
60
|
-
|
|
95
|
+
headers = {
|
|
96
|
+
'User-Agent': '/'.join(('browserstack-local-python', LocalBinary._version)),
|
|
97
|
+
'Accept-Encoding': 'gzip, *',
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if sys.version_info < (3, 2):
|
|
101
|
+
# lack of support for gzip decoding for stream, response is expected to have a tell() method
|
|
102
|
+
headers.pop('Accept-Encoding', None)
|
|
103
|
+
|
|
104
|
+
response = urlopen(Request(self.http_path, headers=headers))
|
|
61
105
|
try:
|
|
62
|
-
total_size = int(response.info().
|
|
106
|
+
total_size = int(response.info().get('Content-Length', '').strip() or '0')
|
|
63
107
|
except:
|
|
64
|
-
total_size = int(response.info().get_all('Content-Length')[0].strip())
|
|
108
|
+
total_size = int(response.info().get_all('Content-Length')[0].strip() or '0')
|
|
65
109
|
bytes_so_far = 0
|
|
66
110
|
|
|
111
|
+
# Limits retries to the number of directories
|
|
67
112
|
dest_parent_dir = self.__available_dir()
|
|
68
113
|
dest_binary_name = 'BrowserStackLocal'
|
|
69
114
|
if self.is_windows:
|
|
70
115
|
dest_binary_name += '.exe'
|
|
71
116
|
|
|
117
|
+
content_encoding = response.info().get('Content-Encoding', '')
|
|
118
|
+
gzip_file = gzip.GzipFile(fileobj=response, mode='rb') if content_encoding.lower() == 'gzip' else None
|
|
119
|
+
|
|
120
|
+
if os.getenv('BROWSERSTACK_LOCAL_DEBUG_GZIP') and gzip_file:
|
|
121
|
+
print('using gzip in ' + headers['User-Agent'])
|
|
122
|
+
|
|
123
|
+
def read_chunk(chunk_size):
|
|
124
|
+
if gzip_file:
|
|
125
|
+
return gzip_file.read(chunk_size)
|
|
126
|
+
else:
|
|
127
|
+
return response.read(chunk_size)
|
|
128
|
+
|
|
72
129
|
with open(os.path.join(dest_parent_dir, dest_binary_name), 'wb') as local_file:
|
|
73
130
|
while True:
|
|
74
|
-
chunk =
|
|
131
|
+
chunk = read_chunk(chunk_size)
|
|
75
132
|
bytes_so_far += len(chunk)
|
|
76
133
|
|
|
77
134
|
if not chunk:
|
|
78
135
|
break
|
|
79
136
|
|
|
80
|
-
if progress_hook:
|
|
137
|
+
if total_size > 0 and progress_hook:
|
|
81
138
|
progress_hook(bytes_so_far, chunk_size, total_size)
|
|
82
139
|
|
|
83
140
|
try:
|
|
84
141
|
local_file.write(chunk)
|
|
85
142
|
except:
|
|
86
143
|
return self.download(chunk_size, progress_hook)
|
|
144
|
+
|
|
145
|
+
if gzip_file:
|
|
146
|
+
gzip_file.close()
|
|
147
|
+
|
|
148
|
+
if callable(getattr(response, 'close', None)):
|
|
149
|
+
response.close()
|
|
87
150
|
|
|
88
151
|
final_path = os.path.join(dest_parent_dir, dest_binary_name)
|
|
89
152
|
st = os.stat(final_path)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: browserstack-local
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.11
|
|
4
4
|
Summary: Python bindings for Browserstack Local
|
|
5
5
|
Home-page: https://github.com/browserstack/browserstack-local-python
|
|
6
6
|
Download-URL: https://github.com/browserstack/browserstack-local-python/archive/master.zip
|
|
@@ -5,7 +5,7 @@ except ImportError:
|
|
|
5
5
|
setup(
|
|
6
6
|
name = 'browserstack-local',
|
|
7
7
|
packages = ['browserstack'],
|
|
8
|
-
version = '1.2.
|
|
8
|
+
version = '1.2.11',
|
|
9
9
|
description = 'Python bindings for Browserstack Local',
|
|
10
10
|
long_description=open('README.md').read(),
|
|
11
11
|
long_description_content_type='text/markdown',
|
|
@@ -70,7 +70,7 @@ class TestLocal(unittest.TestCase):
|
|
|
70
70
|
self.assertIn('-proxyHost', self.local._generate_cmd())
|
|
71
71
|
self.assertIn('localhost', self.local._generate_cmd())
|
|
72
72
|
self.assertIn('-proxyPort', self.local._generate_cmd())
|
|
73
|
-
self.assertIn(2000, self.local._generate_cmd())
|
|
73
|
+
self.assertIn('2000', self.local._generate_cmd())
|
|
74
74
|
self.assertIn('-proxyUser', self.local._generate_cmd())
|
|
75
75
|
self.assertIn('hello', self.local._generate_cmd())
|
|
76
76
|
self.assertIn('-proxyPass', self.local._generate_cmd())
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{browserstack-local-1.2.9 → browserstack-local-1.2.11}/browserstack_local.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{browserstack-local-1.2.9 → browserstack-local-1.2.11}/browserstack_local.egg-info/requires.txt
RENAMED
|
File without changes
|
{browserstack-local-1.2.9 → browserstack-local-1.2.11}/browserstack_local.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|