-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #46 from IABTechLab/ccm-UID2-3497-implement-identi…
…ty-buckets UID2-3497: Support for /identity/buckets
- Loading branch information
Showing
7 changed files
with
149 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import sys | ||
from datetime import datetime | ||
|
||
from uid2_client import IdentityMapClient | ||
|
||
|
||
# this sample client takes timestamp string as input and generates an IdentityBucketsResponse object which contains | ||
# a list of buckets, the timestamp string in the format YYYY-MM-DD[*HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]], | ||
# for example: UTC: 2024-07-02, 2024-07-02T14:30:15.123456+00:00 and EST: 2024-07-02T14:30:15.123456-05:00 | ||
|
||
def _usage(): | ||
print('Usage: python3 sample_get_identity_buckets.py <base_url> <api_key> <client_secret> <timestamp>' | ||
, file=sys.stderr) | ||
sys.exit(1) | ||
|
||
|
||
if len(sys.argv) <= 4: | ||
_usage() | ||
|
||
base_url = sys.argv[1] | ||
api_key = sys.argv[2] | ||
client_secret = sys.argv[3] | ||
timestamp = sys.argv[4] | ||
|
||
client = IdentityMapClient(base_url, api_key, client_secret) | ||
|
||
identity_buckets_response = client.get_identity_buckets(datetime.fromisoformat(timestamp)) | ||
|
||
if identity_buckets_response.buckets: | ||
for bucket in identity_buckets_response.buckets: | ||
print("The bucket id of the bucket: ", bucket.get_bucket_id()) | ||
print("The last updated timestamp of the bucket: ", bucket.get_last_updated()) | ||
else: | ||
print("No bucket was returned") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
import datetime as dt | ||
import os | ||
import unittest | ||
|
||
from urllib.error import URLError, HTTPError | ||
|
||
from uid2_client import IdentityMapClient, IdentityMapInput, normalize_and_hash_email, normalize_and_hash_phone | ||
|
@@ -130,24 +132,29 @@ def test_identity_map_hashed_phones(self): | |
|
||
self.assert_unmapped(response, "optout", hashed_opted_out_phone) | ||
|
||
def test_identity_map_bad_url(self): | ||
def test_identity_map_client_bad_url(self): | ||
identity_map_input = IdentityMapInput.from_emails( | ||
["[email protected]", "[email protected]", "[email protected]"]) | ||
client = IdentityMapClient("https://operator-bad-url.uidapi.com", os.getenv("UID2_API_KEY"), os.getenv("UID2_SECRET_KEY")) | ||
self.assertRaises(URLError, client.generate_identity_map, identity_map_input) | ||
self.assertRaises(URLError, client.get_identity_buckets, dt.datetime.now()) | ||
|
||
def test_identity_map_bad_api_key(self): | ||
def test_identity_map_client_bad_api_key(self): | ||
identity_map_input = IdentityMapInput.from_emails( | ||
["[email protected]", "[email protected]", "[email protected]"]) | ||
client = IdentityMapClient(os.getenv("UID2_BASE_URL"), "bad-api-key", os.getenv("UID2_SECRET_KEY")) | ||
self.assertRaises(HTTPError, client.generate_identity_map,identity_map_input) | ||
self.assertRaises(HTTPError, client.get_identity_buckets, dt.datetime.now()) | ||
|
||
def test_identity_map_bad_secret(self): | ||
def test_identity_map_client_bad_secret(self): | ||
identity_map_input = IdentityMapInput.from_emails( | ||
["[email protected]", "[email protected]", "[email protected]"]) | ||
|
||
client = IdentityMapClient(os.getenv("UID2_BASE_URL"), os.getenv("UID2_API_KEY"), "wJ0hP19QU4hmpB64Y3fV2dAed8t/mupw3sjN5jNRFzg=") | ||
self.assertRaises(HTTPError, client.generate_identity_map, | ||
identity_map_input) | ||
self.assertRaises(HTTPError, client.get_identity_buckets, | ||
dt.datetime.now()) | ||
|
||
def assert_mapped(self, response, dii): | ||
mapped_identity = response.mapped_identities.get(dii) | ||
|
@@ -165,6 +172,15 @@ def assert_unmapped(self, response, reason, dii): | |
mapped_identity = response.mapped_identities.get(dii) | ||
self.assertIsNone(mapped_identity) | ||
|
||
def test_identity_buckets(self): | ||
response = self.identity_map_client.get_identity_buckets(dt.datetime.now() - dt.timedelta(days=90)) | ||
self.assertTrue(len(response.buckets) > 0) | ||
self.assertTrue(response.is_success) | ||
|
||
def test_identity_buckets_empty_response(self): | ||
response = self.identity_map_client.get_identity_buckets(dt.datetime.now() + dt.timedelta(days=1)) | ||
self.assertTrue(len(response.buckets) == 0) | ||
self.assertTrue(response.is_success) | ||
|
||
if __name__ == '__main__': | ||
unittest.main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import unittest | ||
import datetime as dt | ||
|
||
from uid2_client import IdentityMapClient, get_datetime_utc_iso_format | ||
|
||
|
||
class IdentityMapUnitTests(unittest.TestCase): | ||
identity_map_client = IdentityMapClient("UID2_BASE_URL", "UID2_API_KEY", "wJ0hP19QU4hmpB64Y3fV2dAed8t/mupw3sjN5jNRFzg=") | ||
|
||
def test_identity_buckets_invalid_timestamp(self): | ||
test_cases = ["1234567890", | ||
1234567890, | ||
2024.7, | ||
"2024-7-1", | ||
"2024-07-01T12:00:00", | ||
[2024, 7, 1, 12, 0, 0], | ||
None] | ||
for timestamp in test_cases: | ||
self.assertRaises(AttributeError, self.identity_map_client.get_identity_buckets, | ||
timestamp) | ||
|
||
def test_get_datetime_utc_iso_format_timestamp(self): | ||
expected_timestamp = "2024-07-02T14:30:15.123456" | ||
test_cases = ["2024-07-02T14:30:15.123456+00:00", "2024-07-02 09:30:15.123456-05:00", | ||
"2024-07-02T08:30:15.123456-06:00", "2024-07-02T10:30:15.123456-04:00", | ||
"2024-07-02T06:30:15.123456-08:00", "2024-07-02T23:30:15.123456+09:00", | ||
"2024-07-03T00:30:15.123456+10:00", "2024-07-02T20:00:15.123456+05:30"] | ||
for timestamp_str in test_cases: | ||
timestamp = dt.datetime.fromisoformat(timestamp_str) | ||
iso_format_timestamp = get_datetime_utc_iso_format(timestamp) | ||
self.assertEqual(expected_timestamp, iso_format_timestamp) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import json | ||
|
||
|
||
class IdentityBucketsResponse: | ||
def __init__(self, response): | ||
self._buckets = [] | ||
response_json = json.loads(response) | ||
self._status = response_json["status"] | ||
|
||
if not self.is_success(): | ||
raise ValueError("Got unexpected identity buckets status: " + self._status) | ||
|
||
body = response_json["body"] | ||
|
||
for bucket in body: | ||
self._buckets.append(Bucket.from_json(bucket)) | ||
|
||
def is_success(self): | ||
return self._status == "success" | ||
|
||
@property | ||
def buckets(self): | ||
return self._buckets | ||
|
||
@property | ||
def status(self): | ||
return self._status | ||
|
||
|
||
class Bucket: | ||
def __init__(self, bucket_id, last_updated): | ||
self._bucket_id = bucket_id | ||
self._last_updated = last_updated | ||
|
||
def get_bucket_id(self): | ||
return self._bucket_id | ||
|
||
def get_last_updated(self): | ||
return self._last_updated | ||
|
||
@staticmethod | ||
def from_json(json_obj): | ||
return Bucket( | ||
json_obj.get("bucket_id"), | ||
json_obj.get("last_updated") | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters