Skip to content

Commit f7d04a0

Browse files
committed
Solves #109, extended User-Agent data
1 parent c0cdea6 commit f7d04a0

File tree

2 files changed

+84
-3
lines changed

2 files changed

+84
-3
lines changed

webexteamssdk/api/__init__.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
from .team_memberships import TeamMembershipsAPI
4848
from .teams import TeamsAPI
4949
from .webhooks import WebhooksAPI
50+
import os
5051

5152

5253
class WebexTeamsAPI(object):
@@ -68,7 +69,9 @@ def __init__(self, access_token=None, base_url=DEFAULT_BASE_URL,
6869
client_secret=None,
6970
oauth_code=None,
7071
redirect_uri=None,
71-
proxies=None):
72+
proxies=None,
73+
be_geo_id=None,
74+
caller=None):
7275
"""Create a new WebexTeamsAPI object.
7376
7477
An access token must be used when interacting with the Webex Teams API.
@@ -112,6 +115,12 @@ def __init__(self, access_token=None, base_url=DEFAULT_BASE_URL,
112115
OAuth process.
113116
proxies(dict): Dictionary of proxies passed on to the requests
114117
session.
118+
be_geo_id(basestring): Optional partner identifier for API usage
119+
tracking. Defaults to checking for a BE_GEO_ID environment
120+
variable.
121+
caller(basestring): Optional identifier for API usage tracking.
122+
Defaults to checking for a WEBEX_PYTHON_SDK_CALLER environment
123+
variable.
115124
116125
Returns:
117126
WebexTeamsAPI: A new WebexTeamsAPI object.
@@ -131,6 +140,8 @@ def __init__(self, access_token=None, base_url=DEFAULT_BASE_URL,
131140
check_type(oauth_code, basestring, optional=True)
132141
check_type(redirect_uri, basestring, optional=True)
133142
check_type(proxies, dict, optional=True)
143+
check_type(be_geo_id, basestring, optional=True)
144+
check_type(caller, basestring, optional=True)
134145

135146
access_token = access_token or WEBEX_TEAMS_ACCESS_TOKEN
136147

@@ -150,6 +161,10 @@ def __init__(self, access_token=None, base_url=DEFAULT_BASE_URL,
150161
redirect_uri=redirect_uri
151162
).access_token
152163

164+
# Set optional API metrics tracking variables from env vars if there
165+
be_geo_id = be_geo_id or os.environ.get('BE_GEO_ID')
166+
caller = caller or os.environ.get('WEBEX_PYTHON_SDK_CALLER')
167+
153168
# If an access token hasn't been provided as a parameter, environment
154169
# variable, or obtained via an OAuth exchange raise an error.
155170
if not access_token:
@@ -168,7 +183,9 @@ def __init__(self, access_token=None, base_url=DEFAULT_BASE_URL,
168183
base_url=base_url,
169184
single_request_timeout=single_request_timeout,
170185
wait_on_rate_limit=wait_on_rate_limit,
171-
proxies=proxies
186+
proxies=proxies,
187+
be_geo_id=be_geo_id,
188+
caller=caller
172189
)
173190

174191
# API wrappers

webexteamssdk/restsession.py

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@
3939
from builtins import *
4040

4141
import requests
42+
import urllib
43+
import platform
44+
import sys
45+
import json
4246
from past.builtins import basestring
4347

4448
from .config import DEFAULT_SINGLE_REQUEST_TIMEOUT, DEFAULT_WAIT_ON_RATE_LIMIT
@@ -48,6 +52,7 @@
4852
check_response_code, check_type, extract_and_parse_json, validate_base_url,
4953
)
5054

55+
from webexteamssdk._version import get_versions
5156

5257
# Helper Functions
5358
def _fix_next_url(next_url):
@@ -100,7 +105,9 @@ class RestSession(object):
100105
def __init__(self, access_token, base_url,
101106
single_request_timeout=DEFAULT_SINGLE_REQUEST_TIMEOUT,
102107
wait_on_rate_limit=DEFAULT_WAIT_ON_RATE_LIMIT,
103-
proxies=None):
108+
proxies=None,
109+
be_geo_id=None,
110+
caller=None):
104111
"""Initialize a new RestSession object.
105112
106113
Args:
@@ -114,6 +121,12 @@ def __init__(self, access_token, base_url,
114121
handling.
115122
proxies(dict): Dictionary of proxies passed on to the requests
116123
session.
124+
be_geo_id(basestring): Optional partner identifier for API usage
125+
tracking. Defaults to checking for a BE_GEO_ID environment
126+
variable.
127+
caller(basestring): Optional identifier for API usage tracking.
128+
Defaults to checking for a WEBEX_PYTHON_SDK_CALLER environment
129+
variable.
117130
118131
Raises:
119132
TypeError: If the parameter types are incorrect.
@@ -139,9 +152,60 @@ def __init__(self, access_token, base_url,
139152
if proxies is not None:
140153
self._req_session.proxies.update(proxies)
141154

155+
# Build a User-Agent header
156+
ua_base = 'python-webexteams/' + get_versions()['version'] + ' '
157+
158+
# Generate extended portion of the User-Agent
159+
ua_ext = {}
160+
161+
# Mimic pip system data collection per
162+
# https://github.com/pypa/pip/blob/master/src/pip/_internal/network/session.py
163+
ua_ext['implementation'] = {
164+
"name": platform.python_implementation(),
165+
}
166+
167+
if ua_ext["implementation"]["name"] == 'CPython':
168+
ua_ext["implementation"]["version"] = platform.python_version()
169+
elif ua_ext["implementation"]["name"] == 'PyPy':
170+
if sys.pypy_version_info.releaselevel == 'final':
171+
pypy_version_info = sys.pypy_version_info[:3]
172+
else:
173+
pypy_version_info = sys.pypy_version_info
174+
ua_ext["implementation"]["version"] = ".".join(
175+
[str(x) for x in pypy_version_info]
176+
)
177+
elif ua_ext["implementation"]["name"] == 'Jython':
178+
ua_ext["implementation"]["version"] = platform.python_version()
179+
elif ua_ext["implementation"]["name"] == 'IronPython':
180+
ua_ext["implementation"]["version"] = platform.python_version()
181+
182+
if sys.platform.startswith("darwin") and platform.mac_ver()[0]:
183+
dist = {"name": "macOS", "version": platform.mac_ver()[0]}
184+
ua_ext["distro"] = dist
185+
186+
if platform.system():
187+
ua_ext.setdefault("system", {})["name"] = platform.system()
188+
189+
if platform.release():
190+
ua_ext.setdefault("system", {})["release"] = platform.release()
191+
192+
if platform.machine():
193+
ua_ext["cpu"] = platform.machine()
194+
195+
if be_geo_id:
196+
ua_ext["be_geo_id"] = be_geo_id
197+
198+
if caller:
199+
ua_ext["caller"] = caller
200+
201+
# Override the default requests User-Agent but not other headers
202+
new_ua = ua_base + urllib.parse.quote(json.dumps(ua_ext))
203+
self._req_session.headers['User-Agent'] = new_ua
204+
142205
# Update the headers of the `requests` session
143206
self.update_headers({'Authorization': 'Bearer ' + access_token,
144207
'Content-type': 'application/json;charset=utf-8'})
208+
print(self._req_session.headers)
145209

146210
@property
147211
def base_url(self):

0 commit comments

Comments
 (0)