Repository: Unleash/unleash-client-python (python)

Issue:
client.initialize_client() doesn't throw an exception when connection failed to establish
When trying to initialize connection to an invalid address, error is being printed to screen but exception isn't thrown and code continues running.

Would expect to be able to catch an error and decide what I want to do with it (continue running or exit) 

Error:
```
Unleash Client registration failed due to exception: Invalid URL 'foo/client/register': No schema supplied. Perhaps you meant http://foo/client/register?
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/UnleashClient/api/register.py", line 45, in register_client
    resp = requests.post(url + REGISTER_URL,
  File "/usr/local/lib/python3.9/dist-packages/requests/api.py", line 119, in post
    return request('post', url, data=data, json=json, **kwargs)
  File "/usr/local/lib/python3.9/dist-packages/requests/api.py", line 61, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/lib/python3.9/dist-packages/requests/sessions.py", line 528, in request
    prep = self.prepare_request(req)
  File "/usr/local/lib/python3.9/dist-packages/requests/sessions.py", line 456, in prepare_request
    p.prepare(
  File "/usr/local/lib/python3.9/dist-packages/requests/models.py", line 316, in prepare
    self.prepare_url(url, params)
  File "/usr/local/lib/python3.9/dist-packages/requests/models.py", line 390, in prepare_url
    raise MissingSchema(error)
requests.exceptions.MissingSchema: Invalid URL 'foo/client/register': No schema supplied. Perhaps you meant http://foo/client/register?
Unleash Client feature fetch failed due to exception: Invalid URL 'foo/client/features': No schema supplied. Perhaps you meant http://foo/client/features?
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/UnleashClient/api/features.py", line 42, in get_feature_toggles
    resp = requests.get(base_url,
  File "/usr/local/lib/python3.9/dist-packages/requests/api.py", line 76, in get
    return request('get', url, params=params, **kwargs)
  File "/usr/local/lib/python3.9/dist-packages/requests/api.py", line 61, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/lib/python3.9/dist-packages/requests/sessions.py", line 528, in request
    prep = self.prepare_request(req)
  File "/usr/local/lib/python3.9/dist-packages/requests/sessions.py", line 456, in prepare_request
    p.prepare(
  File "/usr/local/lib/python3.9/dist-packages/requests/models.py", line 316, in prepare
    self.prepare_url(url, params)
  File "/usr/local/lib/python3.9/dist-packages/requests/models.py", line 390, in prepare_url
    raise MissingSchema(error)
requests.exceptions.MissingSchema: Invalid URL 'foo/client/features': No schema supplied. Perhaps you meant http://foo/client/features?
Unable to get feature flag toggles, using cached provisioning.
Cache Exception: '/client/features'
Unleash client does not have cached features. Please make sure client can communicate with Unleash server!
```

Pull request description:
Raises exception on registration if client is initialized with invalid URL
# Description

Raises a requests exception if registration is attempted with an invalid URL so users can decide what to do.

Fixes #154 

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update

# How Has This Been Tested?

Please describe the tests that you ran to verify your changes.

- [x] Unit tests
- [x] Spec Tests
- [x] Integration tests / Manual Tests

# Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my own code
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules

Patch:
diff --git a/UnleashClient/api/register.py b/UnleashClient/api/register.py
index 60a66ea..e7fca2f 100644
--- a/UnleashClient/api/register.py
+++ b/UnleashClient/api/register.py
@@ -1,6 +1,7 @@
 import json
 from datetime import datetime, timezone
 import requests
+from requests.exceptions import MissingSchema, InvalidSchema, InvalidURL, InvalidHeader
 from UnleashClient.constants import SDK_NAME, SDK_VERSION, REQUEST_TIMEOUT, APPLICATION_HEADERS, REGISTER_URL
 from UnleashClient.utils import LOGGER, log_resp_info
 
@@ -55,6 +56,9 @@ def register_client(url: str,
         LOGGER.info("Unleash Client successfully registered!")
 
         return True
+    except (MissingSchema, InvalidSchema, InvalidHeader, InvalidURL) as exc:
+        LOGGER.exception("Unleash Client registration failed fatally due to exception: %s", exc)
+        raise exc
     except requests.RequestException as exc:
         LOGGER.exception("Unleash Client registration failed due to exception: %s", exc)
 
diff --git a/docs/changelog.md b/docs/changelog.md
index c12b26e..1802611 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -1,6 +1,8 @@
 ## Next version
 
 ## Upcoming
+* (Minor) `initialize_client()` will raise exception if UnleashClient is configured with an invalid URL.
+* (Minor) Exclude test package from dist & wheel.  Thanks @ameyajoshi99!
 * (Minor) Allow users to specify log-level for when `is_enabled()` or `get_varients()` calls fail.
 
 ## v4.2.0
diff --git a/docs/unleashclient.md b/docs/unleashclient.md
index 7b8aac1..ec19c7e 100644
--- a/docs/unleashclient.md
+++ b/docs/unleashclient.md
@@ -33,6 +33,8 @@ This kicks off:
 * Provisioning poll
 * Stats poll
 
+This will raise an exception on registration if the URL is invalid.
+
 ### `destroy()`
 Gracefully shuts down the Unleash client by stopping jobs, stopping the scheduler, and deleting the cache.
 


Test patch:
diff --git a/tests/unit_tests/test_client.py b/tests/unit_tests/test_client.py
index 098de79..ef20468 100644
--- a/tests/unit_tests/test_client.py
+++ b/tests/unit_tests/test_client.py
@@ -362,3 +362,17 @@ def test_uc_server_error_recovery(unleash_client):
     responses.add(responses.GET, URL + FEATURES_URL, json=MOCK_FEATURE_RESPONSE, status=200)
     time.sleep(20)
     assert unleash_client.is_enabled("testFlag")
+
+
+def test_uc_with_invalid_url():
+    unleash_client = UnleashClient("thisisnotavalidurl", APP_NAME)
+
+    with pytest.raises(ValueError):
+        unleash_client.initialize_client()
+
+
+def test_uc_with_network_error():
+    unleash_client = UnleashClient("https://thisisavalidurl.com", APP_NAME)
+    unleash_client.initialize_client()
+
+    assert unleash_client.is_enabled