libmozdata 0.2.15__tar.gz → 0.2.18__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.
- {libmozdata-0.2.15/libmozdata.egg-info → libmozdata-0.2.18}/PKG-INFO +1 -1
- libmozdata-0.2.18/VERSION +1 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/HGFileInfo.py +1 -3
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/bugzilla.py +16 -21
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/connection.py +2 -1
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/hgmozilla.py +2 -4
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/lando.py +5 -6
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/phabricator.py +7 -27
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/redash.py +1 -3
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/socorro.py +3 -5
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/utils.py +50 -7
- {libmozdata-0.2.15 → libmozdata-0.2.18/libmozdata.egg-info}/PKG-INFO +1 -1
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata.egg-info/requires.txt +1 -1
- {libmozdata-0.2.15 → libmozdata-0.2.18}/requirements.txt +1 -1
- libmozdata-0.2.15/VERSION +0 -1
- {libmozdata-0.2.15 → libmozdata-0.2.18}/MANIFEST.in +0 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/README.md +0 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/BZInfo.py +0 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/FXRevision.py +0 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/FileStats.py +0 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/__init__.py +0 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/buildhub.py +0 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/clouseau.py +0 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/config.py +0 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/fx_trains.py +0 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/handler.py +0 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/modules.json +0 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/modules.py +0 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/patchanalysis.py +0 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/vcs_map.py +0 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/versions.py +0 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata/wiki_parser.py +0 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata.egg-info/SOURCES.txt +0 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata.egg-info/dependency_links.txt +0 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata.egg-info/not-zip-safe +0 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/libmozdata.egg-info/top_level.txt +0 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/setup.cfg +0 -0
- {libmozdata-0.2.15 → libmozdata-0.2.18}/setup.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.2.18
|
|
@@ -5,8 +5,6 @@
|
|
|
5
5
|
import logging
|
|
6
6
|
import re
|
|
7
7
|
|
|
8
|
-
import six
|
|
9
|
-
|
|
10
8
|
from . import hgmozilla
|
|
11
9
|
from .connection import Query
|
|
12
10
|
|
|
@@ -32,7 +30,7 @@ class HGFileInfo(object):
|
|
|
32
30
|
self.node = node
|
|
33
31
|
self.date_type = "date" if date_type == "creation" else "pushdate"
|
|
34
32
|
self.data = {}
|
|
35
|
-
self.paths = [paths] if isinstance(paths,
|
|
33
|
+
self.paths = [paths] if isinstance(paths, str) else paths
|
|
36
34
|
for p in self.paths:
|
|
37
35
|
self.data[p] = []
|
|
38
36
|
self.bug_pattern = re.compile(r"[\t ]*[Bb][Uu][Gg][\t ]*([0-9]+)")
|
|
@@ -6,7 +6,6 @@ import functools
|
|
|
6
6
|
import re
|
|
7
7
|
|
|
8
8
|
import requests
|
|
9
|
-
import six
|
|
10
9
|
from requests import HTTPError
|
|
11
10
|
|
|
12
11
|
import libmozdata.versions
|
|
@@ -75,7 +74,7 @@ class Bugzilla(BugzillaBase):
|
|
|
75
74
|
super(Bugzilla, self).__init__(Bugzilla.URL, queries=queries, **kwargs)
|
|
76
75
|
else:
|
|
77
76
|
super(Bugzilla, self).__init__(Bugzilla.URL, **kwargs)
|
|
78
|
-
if isinstance(bugids,
|
|
77
|
+
if isinstance(bugids, str) or isinstance(bugids, dict):
|
|
79
78
|
self.bugids = [bugids]
|
|
80
79
|
elif isinstance(bugids, int):
|
|
81
80
|
self.bugids = [str(bugids)]
|
|
@@ -196,9 +195,9 @@ class Bugzilla(BugzillaBase):
|
|
|
196
195
|
|
|
197
196
|
def __merge_fields(f1, f2):
|
|
198
197
|
if f1:
|
|
199
|
-
f1 = {f1} if isinstance(f1,
|
|
198
|
+
f1 = {f1} if isinstance(f1, str) else set(f1)
|
|
200
199
|
if f2:
|
|
201
|
-
f2 = {f2} if isinstance(f2,
|
|
200
|
+
f2 = {f2} if isinstance(f2, str) else set(f2)
|
|
202
201
|
return list(f1.union(f2))
|
|
203
202
|
else:
|
|
204
203
|
return f1
|
|
@@ -257,7 +256,7 @@ class Bugzilla(BugzillaBase):
|
|
|
257
256
|
|
|
258
257
|
@staticmethod
|
|
259
258
|
def get_links(bugids):
|
|
260
|
-
if isinstance(bugids,
|
|
259
|
+
if isinstance(bugids, str) or isinstance(bugids, int):
|
|
261
260
|
return "https://bugzilla.mozilla.org/" + str(bugids)
|
|
262
261
|
else:
|
|
263
262
|
return ["https://bugzilla.mozilla.org/" + str(bugid) for bugid in bugids]
|
|
@@ -594,7 +593,7 @@ class Bugzilla(BugzillaBase):
|
|
|
594
593
|
header = self.get_header()
|
|
595
594
|
specials = {"count_only", "limit", "order", "offset"}
|
|
596
595
|
for query in self.bugids:
|
|
597
|
-
if isinstance(query,
|
|
596
|
+
if isinstance(query, str):
|
|
598
597
|
url = Bugzilla.API_URL + "?" + query
|
|
599
598
|
self.bugs_results.append(
|
|
600
599
|
self.session.get(
|
|
@@ -730,7 +729,7 @@ class Bugzilla(BugzillaBase):
|
|
|
730
729
|
bugs = json["bugs"]
|
|
731
730
|
if bugs:
|
|
732
731
|
for key in bugs.keys():
|
|
733
|
-
if isinstance(key,
|
|
732
|
+
if isinstance(key, str) and key.isdigit():
|
|
734
733
|
comments = bugs[key]
|
|
735
734
|
self.commenthandler.handle(comments, key)
|
|
736
735
|
elif self.RAISE_ERROR:
|
|
@@ -775,7 +774,7 @@ class Bugzilla(BugzillaBase):
|
|
|
775
774
|
bugs = json["bugs"]
|
|
776
775
|
if bugs:
|
|
777
776
|
for key in bugs.keys():
|
|
778
|
-
if isinstance(key,
|
|
777
|
+
if isinstance(key, str) and key.isdigit():
|
|
779
778
|
attachments = bugs[key]
|
|
780
779
|
self.attachmenthandler.handle(attachments, key)
|
|
781
780
|
elif self.RAISE_ERROR:
|
|
@@ -861,7 +860,7 @@ class BugzillaUser(BugzillaBase):
|
|
|
861
860
|
self.fault_user_handler = Handler.get(fault_user_handler, user_data)
|
|
862
861
|
|
|
863
862
|
if user_names is not None:
|
|
864
|
-
if isinstance(user_names,
|
|
863
|
+
if isinstance(user_names, str) or isinstance(user_names, int):
|
|
865
864
|
user_names = [user_names]
|
|
866
865
|
|
|
867
866
|
params = [
|
|
@@ -870,8 +869,7 @@ class BugzillaUser(BugzillaBase):
|
|
|
870
869
|
"names": [
|
|
871
870
|
user_name
|
|
872
871
|
for user_name in user_names
|
|
873
|
-
if isinstance(user_name,
|
|
874
|
-
and not user_name.isdigit()
|
|
872
|
+
if isinstance(user_name, str) and not user_name.isdigit()
|
|
875
873
|
],
|
|
876
874
|
"ids": [
|
|
877
875
|
str(user_id)
|
|
@@ -891,7 +889,7 @@ class BugzillaUser(BugzillaBase):
|
|
|
891
889
|
**kwargs,
|
|
892
890
|
)
|
|
893
891
|
elif search_strings is not None:
|
|
894
|
-
if isinstance(search_strings,
|
|
892
|
+
if isinstance(search_strings, str):
|
|
895
893
|
search_strings = [search_strings]
|
|
896
894
|
|
|
897
895
|
queries = []
|
|
@@ -952,9 +950,9 @@ class BugzillaProduct(BugzillaBase):
|
|
|
952
950
|
|
|
953
951
|
if include_fields:
|
|
954
952
|
if "include_fields" in params:
|
|
955
|
-
if isinstance(include_fields,
|
|
953
|
+
if isinstance(include_fields, str):
|
|
956
954
|
include_fields = [include_fields]
|
|
957
|
-
if isinstance(params.get("include_fields"),
|
|
955
|
+
if isinstance(params.get("include_fields"), str):
|
|
958
956
|
params["include_fields"] = [params["include_fields"]]
|
|
959
957
|
|
|
960
958
|
params["include_fields"] = list(
|
|
@@ -965,9 +963,9 @@ class BugzillaProduct(BugzillaBase):
|
|
|
965
963
|
|
|
966
964
|
if product_types:
|
|
967
965
|
if "type" in params:
|
|
968
|
-
if isinstance(product_types,
|
|
966
|
+
if isinstance(product_types, str):
|
|
969
967
|
product_types = [product_types]
|
|
970
|
-
if isinstance(params.get("type"),
|
|
968
|
+
if isinstance(params.get("type"), str):
|
|
971
969
|
params["type"] = [params["type"]]
|
|
972
970
|
|
|
973
971
|
params["type"] = list(set(params["type"]).union(product_types))
|
|
@@ -975,9 +973,7 @@ class BugzillaProduct(BugzillaBase):
|
|
|
975
973
|
params["type"] = product_types
|
|
976
974
|
|
|
977
975
|
elif product_names is not None:
|
|
978
|
-
if isinstance(product_names,
|
|
979
|
-
product_names, int
|
|
980
|
-
):
|
|
976
|
+
if isinstance(product_names, str) or isinstance(product_names, int):
|
|
981
977
|
product_names = [product_names]
|
|
982
978
|
|
|
983
979
|
params = {
|
|
@@ -986,8 +982,7 @@ class BugzillaProduct(BugzillaBase):
|
|
|
986
982
|
"names": [
|
|
987
983
|
product_name
|
|
988
984
|
for product_name in product_names
|
|
989
|
-
if isinstance(product_name,
|
|
990
|
-
and not product_name.isdigit()
|
|
985
|
+
if isinstance(product_name, str) and not product_name.isdigit()
|
|
991
986
|
],
|
|
992
987
|
"ids": [
|
|
993
988
|
str(product_id)
|
|
@@ -61,7 +61,8 @@ class Connection(object):
|
|
|
61
61
|
)
|
|
62
62
|
|
|
63
63
|
# Error 429 is for 'Too many requests' => we retry
|
|
64
|
-
|
|
64
|
+
# Also retry on server errors.
|
|
65
|
+
STATUS_FORCELIST = [429, 500, 502, 503, 504]
|
|
65
66
|
|
|
66
67
|
def __init__(self, base_url, queries=None, **kwargs):
|
|
67
68
|
"""Constructor
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
3
3
|
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
4
4
|
|
|
5
|
-
import six
|
|
6
|
-
|
|
7
5
|
from . import config
|
|
8
6
|
from .connection import Connection, Query
|
|
9
7
|
|
|
@@ -244,7 +242,7 @@ class FileInfo(Mercurial):
|
|
|
244
242
|
|
|
245
243
|
__base = {"node": node, "file": None}
|
|
246
244
|
|
|
247
|
-
if isinstance(paths,
|
|
245
|
+
if isinstance(paths, str):
|
|
248
246
|
__base["file"] = paths
|
|
249
247
|
_dict = {}
|
|
250
248
|
data[paths] = _dict
|
|
@@ -334,7 +332,7 @@ class Annotate(Mercurial):
|
|
|
334
332
|
|
|
335
333
|
__base = {"node": node, "file": None}
|
|
336
334
|
|
|
337
|
-
if isinstance(paths,
|
|
335
|
+
if isinstance(paths, str):
|
|
338
336
|
__base["file"] = paths
|
|
339
337
|
_dict = {}
|
|
340
338
|
data[paths] = _dict
|
|
@@ -6,9 +6,8 @@
|
|
|
6
6
|
from collections import namedtuple
|
|
7
7
|
from urllib.parse import urljoin
|
|
8
8
|
|
|
9
|
-
import requests
|
|
10
|
-
|
|
11
9
|
from . import config
|
|
10
|
+
from .utils import get_session
|
|
12
11
|
|
|
13
12
|
|
|
14
13
|
class LandoWarnings(object):
|
|
@@ -28,7 +27,7 @@ class LandoWarnings(object):
|
|
|
28
27
|
for warning in warnings:
|
|
29
28
|
warning_id = warning["id"]
|
|
30
29
|
|
|
31
|
-
response =
|
|
30
|
+
response = get_session("lando").delete(
|
|
32
31
|
f"{self.api_url}{warning_id}",
|
|
33
32
|
headers={
|
|
34
33
|
"X-Phabricator-API-Key": self.api_key,
|
|
@@ -45,7 +44,7 @@ class LandoWarnings(object):
|
|
|
45
44
|
"""
|
|
46
45
|
Adds a warning to Lando
|
|
47
46
|
"""
|
|
48
|
-
response =
|
|
47
|
+
response = get_session("lando").post(
|
|
49
48
|
self.api_url,
|
|
50
49
|
json={
|
|
51
50
|
"revision_id": revision_id,
|
|
@@ -67,7 +66,7 @@ class LandoWarnings(object):
|
|
|
67
66
|
"""
|
|
68
67
|
Gets a list of warnings
|
|
69
68
|
"""
|
|
70
|
-
response =
|
|
69
|
+
response = get_session("lando").get(
|
|
71
70
|
self.api_url,
|
|
72
71
|
params={
|
|
73
72
|
"revision_id": revision_id,
|
|
@@ -122,7 +121,7 @@ class LandoCommitMapAPI:
|
|
|
122
121
|
with both full hashes
|
|
123
122
|
"""
|
|
124
123
|
url = urljoin(self.api_url, f"{method}/{repository}/{revision}")
|
|
125
|
-
resp =
|
|
124
|
+
resp = get_session("lando").get(
|
|
126
125
|
url,
|
|
127
126
|
headers={
|
|
128
127
|
"User-Agent": self.USER_AGENT,
|
|
@@ -7,15 +7,13 @@ import collections
|
|
|
7
7
|
import enum
|
|
8
8
|
import json
|
|
9
9
|
import logging
|
|
10
|
-
import math
|
|
11
|
-
import time
|
|
12
10
|
from functools import cached_property
|
|
13
11
|
from urllib.parse import urlencode, urlparse
|
|
14
12
|
|
|
15
13
|
import hglib
|
|
16
|
-
import requests
|
|
17
14
|
|
|
18
15
|
from . import config
|
|
16
|
+
from .utils import get_session
|
|
19
17
|
|
|
20
18
|
HGMO_JSON_REV_URL_TEMPLATE = "https://hg.mozilla.org/mozilla-central/json-rev/{}"
|
|
21
19
|
MOZILLA_PHABRICATOR_PROD = "https://phabricator.services.mozilla.com/api/"
|
|
@@ -210,18 +208,12 @@ class PhabricatorAPI(object):
|
|
|
210
208
|
Phabricator Rest API client
|
|
211
209
|
"""
|
|
212
210
|
|
|
213
|
-
def __init__(self, api_key, url=MOZILLA_PHABRICATOR_PROD
|
|
211
|
+
def __init__(self, api_key, url=MOZILLA_PHABRICATOR_PROD):
|
|
214
212
|
self.USER_AGENT = config.get("User-Agent", "name", required=True)
|
|
215
213
|
self.api_key = api_key
|
|
216
214
|
self.url = url
|
|
217
215
|
assert self.url.endswith("/api/"), "Phabricator API must end with /api/"
|
|
218
216
|
|
|
219
|
-
# Number of API calls retries on 50x before raising an error
|
|
220
|
-
self.max_retries = max_retries
|
|
221
|
-
assert (
|
|
222
|
-
isinstance(self.max_retries, int) and self.max_retries > 0
|
|
223
|
-
), "Invalid max_retries parameter"
|
|
224
|
-
|
|
225
217
|
@cached_property
|
|
226
218
|
def user(self):
|
|
227
219
|
"""
|
|
@@ -669,23 +661,11 @@ class PhabricatorAPI(object):
|
|
|
669
661
|
# Add api token to payload
|
|
670
662
|
payload["__conduit__"] = {"token": self.api_key}
|
|
671
663
|
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
data=urlencode({"params": json.dumps(payload), "output": "json"}),
|
|
678
|
-
)
|
|
679
|
-
if response.status_code >= 500:
|
|
680
|
-
# Retry after a while on 50x using exponential backoff
|
|
681
|
-
backoff = math.exp(nb_try)
|
|
682
|
-
logger.info(
|
|
683
|
-
f"Phabricator failed with status code {response.status_code}, retrying in {backoff:.1f} seconds..."
|
|
684
|
-
)
|
|
685
|
-
time.sleep(backoff)
|
|
686
|
-
else:
|
|
687
|
-
# Stop retrying on the first successful try or other HTTP errors
|
|
688
|
-
break
|
|
664
|
+
response = get_session("phabricator").post(
|
|
665
|
+
self.url + path,
|
|
666
|
+
headers=self.get_header(),
|
|
667
|
+
data=urlencode({"params": json.dumps(payload), "output": "json"}),
|
|
668
|
+
)
|
|
689
669
|
|
|
690
670
|
# Raise immediate 40x errors or out-of-retries 50x
|
|
691
671
|
response.raise_for_status()
|
|
@@ -6,8 +6,6 @@ import functools
|
|
|
6
6
|
import re
|
|
7
7
|
from datetime import timedelta
|
|
8
8
|
|
|
9
|
-
import six
|
|
10
|
-
|
|
11
9
|
from . import config, utils
|
|
12
10
|
from .connection import Connection, Query
|
|
13
11
|
|
|
@@ -93,7 +91,7 @@ class Redash(Connection):
|
|
|
93
91
|
dict: containing result in json for each query
|
|
94
92
|
"""
|
|
95
93
|
data = {}
|
|
96
|
-
if isinstance(query_ids,
|
|
94
|
+
if isinstance(query_ids, str):
|
|
97
95
|
url = Redash.API_URL + "/" + query_ids + "/results.json"
|
|
98
96
|
Redash(
|
|
99
97
|
Query(
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
3
3
|
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
4
4
|
|
|
5
|
-
import six
|
|
6
|
-
|
|
7
5
|
from . import config, utils
|
|
8
6
|
from .connection import Connection, Query
|
|
9
7
|
|
|
@@ -85,7 +83,7 @@ class SuperSearch(Socorro):
|
|
|
85
83
|
"url" in k
|
|
86
84
|
or "email" in k
|
|
87
85
|
or (
|
|
88
|
-
(isinstance(v, list) or isinstance(v,
|
|
86
|
+
(isinstance(v, list) or isinstance(v, str))
|
|
89
87
|
and ("url" in v or "email" in v)
|
|
90
88
|
)
|
|
91
89
|
):
|
|
@@ -175,7 +173,7 @@ class ProcessedCrash(Socorro):
|
|
|
175
173
|
data = {}
|
|
176
174
|
__base = {"crash_id": None, "datatype": "processed"}
|
|
177
175
|
|
|
178
|
-
if isinstance(crashids,
|
|
176
|
+
if isinstance(crashids, str):
|
|
179
177
|
__base["crash_id"] = crashids
|
|
180
178
|
_dict = {}
|
|
181
179
|
data[crashids] = _dict
|
|
@@ -243,7 +241,7 @@ class Bugs(Socorro):
|
|
|
243
241
|
if signature in data:
|
|
244
242
|
data[signature].add(hit["id"])
|
|
245
243
|
|
|
246
|
-
if isinstance(signatures,
|
|
244
|
+
if isinstance(signatures, str):
|
|
247
245
|
data = {signatures: set()}
|
|
248
246
|
Bugs(
|
|
249
247
|
params={"signatures": signatures},
|
|
@@ -8,17 +8,60 @@ import operator
|
|
|
8
8
|
import os.path
|
|
9
9
|
import random
|
|
10
10
|
from datetime import date, datetime, timedelta, timezone
|
|
11
|
+
from functools import cache
|
|
11
12
|
from itertools import count
|
|
12
13
|
|
|
13
14
|
import dateutil.parser
|
|
14
15
|
import pytz
|
|
15
|
-
import
|
|
16
|
+
import requests
|
|
16
17
|
from dateutil.relativedelta import relativedelta
|
|
17
18
|
from requests.utils import quote
|
|
19
|
+
from urllib3.util.retry import Retry
|
|
18
20
|
|
|
19
21
|
__pacific = pytz.timezone("US/Pacific")
|
|
20
22
|
|
|
21
23
|
|
|
24
|
+
@cache
|
|
25
|
+
def get_session(name: str) -> requests.Session:
|
|
26
|
+
"""Get a `requests` session with retries enabled on connection errors and
|
|
27
|
+
50x HTTP error codes, using exponential backoff.
|
|
28
|
+
|
|
29
|
+
Sessions are cached by name, so calling this function multiple times with
|
|
30
|
+
the same name will return the same session.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
name (str): an arbitrary name identifying the caller, used to cache
|
|
34
|
+
the session
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
requests.Session: a session with retries enabled
|
|
38
|
+
"""
|
|
39
|
+
session = requests.Session()
|
|
40
|
+
|
|
41
|
+
retry = Retry(
|
|
42
|
+
total=8,
|
|
43
|
+
backoff_factor=1,
|
|
44
|
+
status_forcelist=[429, 500, 502, 503, 504],
|
|
45
|
+
# Also retry non-idempotent methods (e.g. POST), since urllib3
|
|
46
|
+
# excludes them by default.
|
|
47
|
+
allowed_methods=None,
|
|
48
|
+
# Return the last response instead of raising, once retries are
|
|
49
|
+
# exhausted, so callers can keep inspecting status_code/text.
|
|
50
|
+
raise_on_status=False,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# Default HTTPAdapter uses 10 connections. Mount custom adapter to increase
|
|
54
|
+
# that limit. Connections are established as needed, so using a large value
|
|
55
|
+
# should not negatively impact performance.
|
|
56
|
+
http_adapter = requests.adapters.HTTPAdapter(
|
|
57
|
+
pool_connections=50, pool_maxsize=50, max_retries=retry
|
|
58
|
+
)
|
|
59
|
+
session.mount("https://", http_adapter)
|
|
60
|
+
session.mount("http://", http_adapter)
|
|
61
|
+
|
|
62
|
+
return session
|
|
63
|
+
|
|
64
|
+
|
|
22
65
|
def get_best(stats):
|
|
23
66
|
"""Get the key which has the higher value
|
|
24
67
|
|
|
@@ -43,7 +86,7 @@ def get_timestamp(dt):
|
|
|
43
86
|
Returns:
|
|
44
87
|
int: the corresponding timestamp
|
|
45
88
|
"""
|
|
46
|
-
if isinstance(dt,
|
|
89
|
+
if isinstance(dt, str):
|
|
47
90
|
dt = datetime.now(timezone.utc) if dt == "now" else get_date_ymd(dt)
|
|
48
91
|
return int(calendar.timegm(dt.timetuple()))
|
|
49
92
|
|
|
@@ -118,7 +161,7 @@ def get_date(_date, delta=None):
|
|
|
118
161
|
Returns:
|
|
119
162
|
str: the date as a string 'Year-month-day'
|
|
120
163
|
"""
|
|
121
|
-
if isinstance(_date,
|
|
164
|
+
if isinstance(_date, str):
|
|
122
165
|
_date = get_date_ymd(_date)
|
|
123
166
|
if delta:
|
|
124
167
|
_date -= timedelta(delta)
|
|
@@ -307,16 +350,16 @@ def get_channels():
|
|
|
307
350
|
|
|
308
351
|
|
|
309
352
|
def get_str_list(x):
|
|
310
|
-
if isinstance(x,
|
|
353
|
+
if isinstance(x, str):
|
|
311
354
|
return [x]
|
|
312
|
-
if isinstance(x,
|
|
355
|
+
if isinstance(x, int):
|
|
313
356
|
return [str[x]]
|
|
314
357
|
if isinstance(x, list) or isinstance(x, set):
|
|
315
|
-
return [str(y) if isinstance(y,
|
|
358
|
+
return [str(y) if isinstance(y, int) else y for y in x]
|
|
316
359
|
|
|
317
360
|
|
|
318
361
|
def get_x_fwed_for_str(s):
|
|
319
|
-
if isinstance(s,
|
|
362
|
+
if isinstance(s, str):
|
|
320
363
|
return ", ".join(map(lambda x: x.strip(" \t"), s.split(",")))
|
|
321
364
|
else:
|
|
322
365
|
return ", ".join(map(lambda x: x.strip(" \t"), s))
|
libmozdata-0.2.15/VERSION
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0.2.15
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|