rbx 3.29.2.dev219__tar.gz → 3.30.0.dev220__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.
- {rbx-3.29.2.dev219/rbx.egg-info → rbx-3.30.0.dev220}/PKG-INFO +1 -1
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/pyproject.toml +2 -2
- rbx-3.30.0.dev220/rbx/__init__.py +1 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220/rbx.egg-info}/PKG-INFO +1 -1
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx.egg-info/SOURCES.txt +0 -1
- rbx-3.29.2.dev219/rbx/__init__.py +0 -1
- rbx-3.29.2.dev219/rbx/clients/adsquare.py +0 -146
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/LICENSE +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/README.md +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/auth/__init__.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/auth/decorators.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/auth/id_token.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/auth/keystore.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/auth/mock.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/aws/__init__.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/aws/s3.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/buildtools/__init__.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/buildtools/cli.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/buildtools/tasks/__init__.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/buildtools/tasks/ec2.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/buildtools/tasks/image.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/buildtools/tasks/misc.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/clients/__init__.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/clients/broadsign.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/clients/oxr.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/clients/panels.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/clients/place_exchange.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/clients/reporting.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/clients/retry.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/exceptions.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/gcp/__init__.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/gcp/cloud_tasks.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/gcp/pubsub.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/gcp/storage.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/logging.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/settings.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/utils/__init__.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/utils/mdm.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/utils/vast.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/web/__init__.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx/web/handlers.py +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx.egg-info/dependency_links.txt +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx.egg-info/entry_points.txt +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx.egg-info/requires.txt +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/rbx.egg-info/top_level.txt +0 -0
- {rbx-3.29.2.dev219 → rbx-3.30.0.dev220}/setup.cfg +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "rbx"
|
|
7
|
-
version = "3.
|
|
7
|
+
version = "3.30.0.dev220"
|
|
8
8
|
description = "A collection of common tools for Scoota services."
|
|
9
9
|
authors = [
|
|
10
10
|
{ name = "The Scoota Engineering Team", email = "engineering@scoota.com" }
|
|
@@ -73,7 +73,7 @@ homepage = "https://github.com/rockabox/rbx"
|
|
|
73
73
|
repository = "https://github.com/rockabox/rbx.git"
|
|
74
74
|
|
|
75
75
|
[tool.bumpversion]
|
|
76
|
-
current_version = "3.
|
|
76
|
+
current_version = "3.30.0.dev220"
|
|
77
77
|
commit = true
|
|
78
78
|
parse = """
|
|
79
79
|
(?P<major>\\d+)\\.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "3.30.0.dev220"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "3.29.2.dev219"
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import csv
|
|
2
|
-
from io import StringIO
|
|
3
|
-
import logging
|
|
4
|
-
|
|
5
|
-
import arrow
|
|
6
|
-
|
|
7
|
-
from ..exceptions import ClientException
|
|
8
|
-
from . import Client, HttpAuth, retry
|
|
9
|
-
|
|
10
|
-
logger = logging.getLogger(__name__)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class AdsquareClient(Client):
|
|
14
|
-
"""Client for adsquare API.
|
|
15
|
-
|
|
16
|
-
The API documentation can be found on the Platform wiki:
|
|
17
|
-
https://github.com/rockabox/rbx/wiki/adsquare
|
|
18
|
-
|
|
19
|
-
"""
|
|
20
|
-
|
|
21
|
-
AUTH_PATH = "auth/login"
|
|
22
|
-
ENDPOINT = "https://amp.adsquare.com/api/v1/"
|
|
23
|
-
STANDARD_COMPANY_ID = "588b6428e4b0d7d5f6895bd1"
|
|
24
|
-
TIME_FORMAT = "YYYY-MM-DDTHH:mm:ss.SSS[Z]"
|
|
25
|
-
|
|
26
|
-
def __init__(self, company_id, dsp_id):
|
|
27
|
-
super().__init__()
|
|
28
|
-
self.company_id = company_id
|
|
29
|
-
self.dsp_id = dsp_id
|
|
30
|
-
|
|
31
|
-
@property
|
|
32
|
-
def auth(self):
|
|
33
|
-
"""adsquare uses Digest Authentication."""
|
|
34
|
-
return HttpAuth(self.token, key="X-AUTH-TOKEN")
|
|
35
|
-
|
|
36
|
-
@retry.Retry(deadline=300.0)
|
|
37
|
-
def create_config(self, country_code, name, start_date, end_date):
|
|
38
|
-
"""Create a new observation configuration.
|
|
39
|
-
|
|
40
|
-
The start and end date are expected to be in ISO 8601, though any format understood by
|
|
41
|
-
Arrow will work.
|
|
42
|
-
"""
|
|
43
|
-
path = f"measurement/configs/byCompany/{self.company_id}"
|
|
44
|
-
response = self.request(
|
|
45
|
-
"post",
|
|
46
|
-
path,
|
|
47
|
-
data={
|
|
48
|
-
"dspId": self.dsp_id,
|
|
49
|
-
"countryCode": country_code,
|
|
50
|
-
"name": name,
|
|
51
|
-
"active": True,
|
|
52
|
-
"observationMode": "full",
|
|
53
|
-
"radiusInMeter": 50,
|
|
54
|
-
"validFrom": arrow.get(start_date).format(self.TIME_FORMAT),
|
|
55
|
-
"validTo": arrow.get(end_date).format(self.TIME_FORMAT),
|
|
56
|
-
},
|
|
57
|
-
)
|
|
58
|
-
return response["id"]
|
|
59
|
-
|
|
60
|
-
def disable_webhook(self, config_id):
|
|
61
|
-
"""Disable the registered webhook for the given configuration ID."""
|
|
62
|
-
self.register_webhook(config_id, disable=True)
|
|
63
|
-
|
|
64
|
-
@retry.Retry(deadline=300.0)
|
|
65
|
-
def download_config(self, config_id):
|
|
66
|
-
"""Download the list of site locations uploaded to the given configuration.
|
|
67
|
-
|
|
68
|
-
The points are returned as a dictionary of (lat, long) tuples keyed by assigned ID.
|
|
69
|
-
"""
|
|
70
|
-
data = self.request(
|
|
71
|
-
"get",
|
|
72
|
-
f"measurement/configs/{config_id}/dataset/poi",
|
|
73
|
-
content_type="text/plain",
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
pois = {}
|
|
77
|
-
reader = csv.DictReader(StringIO(data))
|
|
78
|
-
for row in reader:
|
|
79
|
-
pois[row["id"]] = (row["lat"], row["lon"])
|
|
80
|
-
|
|
81
|
-
return pois
|
|
82
|
-
|
|
83
|
-
def pause_config(self, config_id):
|
|
84
|
-
"""Pause the given configuration."""
|
|
85
|
-
self.update_config(config_id=config_id, active=False)
|
|
86
|
-
|
|
87
|
-
@retry.Retry(deadline=300.0)
|
|
88
|
-
def register_webhook(self, config_id, disable=False, feedback_url=None):
|
|
89
|
-
"""Register a Feedback URL webhook with adsquare for the given configuration ID.
|
|
90
|
-
|
|
91
|
-
The same method can be used to re-enable an existing/disabled webhook.
|
|
92
|
-
"""
|
|
93
|
-
data = {
|
|
94
|
-
"enabled": not disable,
|
|
95
|
-
"method": "post",
|
|
96
|
-
"contentType": "csv",
|
|
97
|
-
}
|
|
98
|
-
if feedback_url:
|
|
99
|
-
data["feedbackURL"] = feedback_url
|
|
100
|
-
|
|
101
|
-
if not disable and not feedback_url:
|
|
102
|
-
raise ClientException("Cannot register a webhook without a URL")
|
|
103
|
-
|
|
104
|
-
return self.request(
|
|
105
|
-
"post", f"measurement/configs/{config_id}/feedback", data=data
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
def resume_config(self, config_id):
|
|
109
|
-
"""Resume the given configuration."""
|
|
110
|
-
self.update_config(config_id=config_id, active=True)
|
|
111
|
-
|
|
112
|
-
@retry.Retry(deadline=300.0)
|
|
113
|
-
def update_config(self, config_id, active=None, start_date=None, end_date=None):
|
|
114
|
-
"""Update the given configuration ID.
|
|
115
|
-
|
|
116
|
-
Only active and start/end dates can be changed.
|
|
117
|
-
"""
|
|
118
|
-
data = {}
|
|
119
|
-
|
|
120
|
-
if active is not None:
|
|
121
|
-
data["active"] = active
|
|
122
|
-
|
|
123
|
-
if start_date:
|
|
124
|
-
data["validFrom"] = arrow.get(start_date).format(self.TIME_FORMAT)
|
|
125
|
-
|
|
126
|
-
if end_date:
|
|
127
|
-
data["validTo"] = arrow.get(end_date).format(self.TIME_FORMAT)
|
|
128
|
-
|
|
129
|
-
return self.request("post", f"measurement/configs/{config_id}", data=data)
|
|
130
|
-
|
|
131
|
-
@retry.Retry(deadline=300.0)
|
|
132
|
-
def upload_config(self, config_id, points):
|
|
133
|
-
"""Upload a list of site locations to the given configuration.
|
|
134
|
-
|
|
135
|
-
The points is expected to be a list of (lat, long) tuples as floating values.
|
|
136
|
-
"""
|
|
137
|
-
data = ["id,lon,lat"]
|
|
138
|
-
for i, point in enumerate(points):
|
|
139
|
-
data.append(f"{i},{point[1]},{point[0]}")
|
|
140
|
-
|
|
141
|
-
# Make sure the payload has a trailing newline
|
|
142
|
-
data.append("")
|
|
143
|
-
|
|
144
|
-
self.request(
|
|
145
|
-
"put", f"measurement/configs/{config_id}/dataset/poi", data="\n".join(data)
|
|
146
|
-
)
|
|
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
|
|
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
|