Repository: DataDog/datadogpy

Issue:
Fails to install with pip 8.1.1
**Describe the bug**
A minor issue, since it only happens with very old pip versions, but datadogpy fails to install because configparser>=5 is not compatible with any python2. [Their documentation ](https://github.com/jaraco/configparser/blob/master/CHANGES.rst#v500) says "this should be automatic with pip 9" but there's no harm in being explicit and adding compatibility for older versions. I h

**To Reproduce**
pip install --upgrade pip==8.1.1
pip install datadog

**Expected behavior**
datadogpy installs successfully 

**Actual behavior**
```
Collecting datadog
  Using cached https://files.pythonhosted.org/packages/53/a2/44813679fbb1f3203b2b2aba35a01123da6e32d6f09fbe503f781b8c2fcb/datadog-0.37.1-py2.py3-none-any.whl
Collecting requests>=2.6.0 (from datadog)
  Using cached https://files.pythonhosted.org/packages/45/1e/0c169c6a5381e241ba7404532c16a21d86ab872c9bed8bdcd4c423954103/requests-2.24.0-py2.py3-none-any.whl
Collecting decorator>=3.3.2 (from datadog)
  Using cached https://files.pythonhosted.org/packages/ed/1b/72a1821152d07cf1d8b6fce298aeb06a7eb90f4d6d41acec9861e7cc6df0/decorator-4.4.2-py2.py3-none-any.whl
Collecting configparser; python_version < "3.0" (from datadog)
Collecting typing; python_version < "3.5" (from datadog)
  Using cached https://files.pythonhosted.org/packages/22/30/64ca29543375759dc589ade14a6cd36382abf2bec17d67de8481bc9814d7/typing-3.7.4.1-py2-none-any.whl
Collecting chardet<4,>=3.0.2 (from requests>=2.6.0->datadog)
  Using cached https://files.pythonhosted.org/packages/bc/a9/01ffebfb562e4274b6487b4bb1ddec7ca55ec7510b22e4c51f14098443b8/chardet-3.0.4-py2.py3-none-any.whl
Collecting urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 (from requests>=2.6.0->datadog)
  Using cached https://files.pythonhosted.org/packages/e1/e5/df302e8017440f111c11cc41a6b432838672f5a70aa29227bf58149dc72f/urllib3-1.25.9-py2.py3-none-any.whl
Collecting idna<3,>=2.5 (from requests>=2.6.0->datadog)
  Using cached https://files.pythonhosted.org/packages/a2/38/928ddce2273eaa564f6f50de919327bf3a00f091b5baba8dfa9460f3a8a8/idna-2.10-py2.py3-none-any.whl
Collecting certifi>=2017.4.17 (from requests>=2.6.0->datadog)
  Using cached https://files.pythonhosted.org/packages/5e/c4/6c4fe722df5343c33226f0b4e0bb042e4dc13483228b4718baf286f86d87/certifi-2020.6.20-py2.py3-none-any.whl
Installing collected packages: chardet, urllib3, idna, certifi, requests, decorator, configparser, typing, datadog
Exception:
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/pip/basecommand.py", line 209, in main
    status = self.run(options, args)
  File "/usr/lib/python2.7/dist-packages/pip/commands/install.py", line 335, in run
    prefix=options.prefix_path,
  File "/usr/lib/python2.7/dist-packages/pip/req/req_set.py", line 732, in install
    **kwargs
  File "/usr/lib/python2.7/dist-packages/pip/req/req_install.py", line 837, in install
    self.move_wheel_files(self.source_dir, root=root, prefix=prefix)
  File "/usr/lib/python2.7/dist-packages/pip/req/req_install.py", line 1039, in move_wheel_files
    isolated=self.isolated,
  File "/usr/lib/python2.7/dist-packages/pip/wheel.py", line 346, in move_wheel_files
    assert info_dir, "%s .dist-info directory not found" % req
AssertionError: configparser; python_version < "3.0" .dist-info directory not found
You are using pip version 8.1.1, however version 20.1.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
```
**Environment and Versions (please complete the following information):**
datadogpy version 0.37.1 being installed through an ansible task on an Ubuntu 16.04 AWS EC2 machine. Though the issue was also replicable calling pip directly instead of through ansible.

**Additional context**
N/A


Discussion:
zippolyte: /azp run DataDog.datadogpy.integration
azure-pipelines[bot]: <samp>
Azure Pipelines successfully started running 1 pipeline(s).<br>

</samp>
zippolyte: LGTM, thanks for the fix 🙇‍♂️ 

Patch:
diff --git a/datadog/api/http_client.py b/datadog/api/http_client.py
index fa5be42..6d1f599 100644
--- a/datadog/api/http_client.py
+++ b/datadog/api/http_client.py
@@ -9,7 +9,9 @@ Priority:
 2. `urlfetch` 3p module - Google App Engine only
 """
 # stdlib
+import copy
 import logging
+import platform
 import urllib
 from threading import Lock
 
@@ -32,6 +34,16 @@ from datadog.api.exceptions import ProxyError, ClientError, HTTPError, HttpTimeo
 log = logging.getLogger('datadog.api')
 
 
+def _get_user_agent_header():
+    from datadog import version
+    return 'datadogpy/{version} (python {pyver}; os {os}; arch {arch})'.format(
+        version=version.__version__,
+        pyver=platform.python_version(),
+        os=platform.system().lower(),
+        arch=platform.machine().lower(),
+    )
+
+
 def _remove_context(exc):
     """Python3: remove context from chained exceptions to prevent leaking API keys in tracebacks."""
     exc.__cause__ = None
@@ -79,6 +91,7 @@ class RequestClient(HTTPClient):
                     cls._session = requests.Session()
                     http_adapter = requests.adapters.HTTPAdapter(max_retries=max_retries)
                     cls._session.mount('https://', http_adapter)
+                    cls._session.headers.update({'User-Agent': _get_user_agent_header()})
 
             result = cls._session.request(
                 method, url,
@@ -130,12 +143,14 @@ class URLFetchClient(HTTPClient):
             url=url,
             params=urllib.urlencode(params)
         )
+        newheaders = copy.deepcopy(headers)
+        newheaders['User-Agent'] = _get_user_agent_header()
 
         try:
             result = urlfetch.fetch(
                 url=url_with_params,
                 method=method,
-                headers=headers,
+                headers=newheaders,
                 validate_certificate=validate_certificate,
                 deadline=timeout,
                 payload=data,
diff --git a/setup.py b/setup.py
index 0b8d4e1..9668c8b 100644
--- a/setup.py
+++ b/setup.py
@@ -28,7 +28,7 @@ install_reqs = [
     "decorator>=3.3.2",
     "requests>=2.6.0",
     'typing;python_version<"3.5"',
-    'configparser;python_version<"3.0"',
+    'configparser<5;python_version<"3.0"',
 ]
 
 if sys.version_info < (2, 7):
diff --git a/tox.ini b/tox.ini
index 31e054a..37ddc06 100644
--- a/tox.ini
+++ b/tox.ini
@@ -11,9 +11,9 @@ envlist =
 passenv = DD_TEST_CLIENT*
 usedevelop = true
 deps =
-    !integration: mock
     click
     freezegun
+    mock
     pytest
     pytest-vcr
     python-dateutil
@@ -28,6 +28,7 @@ usedevelop = true
 deps =
     click
     freezegun
+    mock
     pytest
     pytest-vcr
     python-dateutil


Test patch:
diff --git a/tests/integration/api/cassettes/TestDatadog.test_user_agent.yaml b/tests/integration/api/cassettes/TestDatadog.test_user_agent.yaml
new file mode 100644
index 0000000..6990a10
--- /dev/null
+++ b/tests/integration/api/cassettes/TestDatadog.test_user_agent.yaml
@@ -0,0 +1,51 @@
+interactions:
+- request:
+    body: null
+    headers:
+      Accept:
+      - '*/*'
+      Accept-Encoding:
+      - gzip, deflate
+      Connection:
+      - keep-alive
+      User-Agent:
+      - datadogpy/0.38.0.dev (python 3.7.7; os darwin; arch x86_64)
+    method: GET
+    uri: https://api.datadoghq.com/api/v1/validate
+  response:
+    body:
+      string: '{"valid":true}'
+    headers:
+      Cache-Control:
+      - no-cache
+      Connection:
+      - keep-alive
+      Content-Length:
+      - '14'
+      Content-Security-Policy:
+      - frame-ancestors 'self'; report-uri https://api.datadoghq.com/csp-report
+      Content-Type:
+      - application/json
+      DD-POOL:
+      - dogweb
+      Date:
+      - Wed, 01 Jul 2020 17:22:12 GMT
+      Pragma:
+      - no-cache
+      Set-Cookie:
+      - DD-PSHARD=89; Max-Age=604800; Path=/; expires=Wed, 08-Jul-2020 17:22:12 GMT;
+        secure; HttpOnly
+      Strict-Transport-Security:
+      - max-age=15724800;
+      X-Content-Type-Options:
+      - nosniff
+      X-DD-Debug:
+      - SaHvyR/hQzhMjBxXmmuM76vwlwfocpgL0LhX3u6R0CFONYqUGm7Xe/7/HyTliTFX
+      X-DD-VERSION:
+      - '35.2688709'
+      X-Frame-Options:
+      - SAMEORIGIN
+    status:
+      code: 200
+      message: OK
+version: 1
diff --git a/tests/integration/api/test_api.py b/tests/integration/api/test_api.py
index 8bce7a6..b69c7a4 100644
--- a/tests/integration/api/test_api.py
+++ b/tests/integration/api/test_api.py
@@ -4,7 +4,9 @@
 # python
 import datetime
 import json
+import mock
 import os
+import re
 import time
 
 import requests
@@ -959,3 +961,8 @@ class TestDatadog:
         # check if new role is deleted successfully
         res = dog.Roles.get(role_uuid)
         assert "errors" in res
+
+    @mock.patch('datadog.api._return_raw_response', True)
+    def test_user_agent(self, dog):
+        _, resp = dog.api_client.APIClient.submit('GET', 'validate')
+        assert re.match(r'^datadogpy\/[^\s]+ \(python [^\s]+; os [^\s]+; arch [^\s]+\)$', resp.request.headers['User-Agent'])