Skip to content

Commit

Permalink
Add tracking headers
Browse files Browse the repository at this point in the history
Add Archivist-User-Agent and Archivist-Partner-ID headers.

Fixes AB#9572
  • Loading branch information
eccles committed Jul 3, 2024
1 parent 25a228c commit 03d1228
Show file tree
Hide file tree
Showing 46 changed files with 559 additions and 60 deletions.
8 changes: 7 additions & 1 deletion archivist/archivist.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,15 @@ def __init__(
fixtures: "dict[str,dict[Any,Any]]|None" = None,
verify: bool = True,
max_time: float = MAX_TIME,
partner_id: str = "",
user_agent: str = "",
):
super().__init__(
fixtures=fixtures,
verify=verify,
max_time=max_time,
partner_id=partner_id,
user_agent=user_agent,
)

if isinstance(auth, tuple):
Expand Down Expand Up @@ -214,10 +218,12 @@ def __copy__(self) -> "Archivist":
fixtures=deepcopy(self._fixtures),
verify=self._verify,
max_time=self._max_time,
partner_id=self._partner_id,
user_agent=self._user_agent,
)

def _add_headers(self, headers: "dict[str,str]|None") -> "dict[str,Any]":
newheaders = {**headers} if isinstance(headers, dict) else {}
newheaders = super()._add_headers(headers)

auth = self.auth # this may trigger a refetch so only do it once here
# for appidp endpoint there may not be an authtoken
Expand Down
34 changes: 34 additions & 0 deletions archivist/archivistpublic.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,16 @@
from requests.models import Response


from .about import __version__ as VERSION
from .assetattachments import _AssetAttachmentsClient
from .assets import _AssetsPublic
from .confirmer import MAX_TIME
from .constants import (
HEADERS_REQUEST_TOTAL_COUNT,
HEADERS_TOTAL_COUNT,
PARTNER_ID,
USER_AGENT,
USER_AGENT_PREFIX,
)
from .dictmerge import _deepmerge, _dotdict
from .errors import (
Expand Down Expand Up @@ -82,12 +86,16 @@ def __init__(
fixtures: "dict[str, Any]|None" = None,
verify: bool = True,
max_time: float = MAX_TIME,
partner_id: str = "",
user_agent: str = "",
):
self._verify = verify
self._response_ring_buffer = deque(maxlen=self.RING_BUFFER_MAX_LEN)
self._session = None
self._max_time = max_time
self._fixtures = fixtures or {}
self._partner_id = partner_id
self._user_agent = user_agent

# Type hints for IDE autocomplete, keep in sync with CLIENTS map above
self.assets: _AssetsPublic
Expand Down Expand Up @@ -151,6 +159,21 @@ def max_time(self) -> float:
"""bool: Returns maximum time in seconds to wait for confirmation"""
return self._max_time

@property
def version(self) -> str:
"""str: Returns version of the archivist package"""
return VERSION

@property
def partner_id(self) -> str:
"""str: Returns partner id if set when initialising an instance of this class"""
return self._partner_id

@property
def user_agent(self) -> str:
"""str: Returns partner id if set when initialising an instance of this class"""
return self._user_agent

@property
def fixtures(self) -> "dict[str, Any]":
"""dict: Contains predefined attributes for each endpoint"""
Expand All @@ -170,6 +193,17 @@ def __copy__(self):

def _add_headers(self, headers: "dict[str, str]|None") -> "dict[str, str]":
newheaders = {**headers} if headers is not None else {}
u = self.user_agent
if u:
newheaders[USER_AGENT] = (
f"{self.user_agent} {USER_AGENT_PREFIX}{self.version}"
)
else:
newheaders[USER_AGENT] = f"{USER_AGENT_PREFIX}{self.version}"

p = self.partner_id
if p:
newheaders[PARTNER_ID] = p

return newheaders

Expand Down
4 changes: 4 additions & 0 deletions archivist/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
"RecordEvidence",
]

USER_AGENT = "DataTrails-User-Agent"
USER_AGENT_PREFIX = "pysdk/"
PARTNER_ID = "DataTrails-Partner-ID"

# define in MIME canonical form
HEADERS_REQUEST_TOTAL_COUNT = "X-Request-Total-Count"
HEADERS_TOTAL_COUNT = "X-Total-Count"
Expand Down
16 changes: 15 additions & 1 deletion archivist/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,15 @@ def common_parser(description: str):
default=None,
help="namespace of item population",
)
parser.add_argument(
"-p",
"--partner_id",
type=str,
dest="partner_id",
action="store",
default=None,
help="partner id",
)

return parser

Expand Down Expand Up @@ -171,7 +180,12 @@ def endpoint(args):
LOGGER.error("Critical error. Aborting.")
sys_exit(1)

arch = Archivist(args.url, auth, fixtures=fixtures)
arch = Archivist(
args.url,
auth,
fixtures=fixtures,
partner_id=args.partner_id,
)
if arch is None:
LOGGER.error("Critical error. Aborting.")
sys_exit(1)
Expand Down
6 changes: 5 additions & 1 deletion examples/create_asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def main():
create an example archivist connection and create an asset.
"""
# optional call to set the logger level for all subsystems. The argumant can
# optional call to set the logger level for all subsystems. The argument can
# be either "INFO" or "DEBUG". For more sophisticated logging control see the
# documentation.
set_logger("INFO")
Expand All @@ -97,10 +97,14 @@ def main():
# Initialize connection to Archivist. max_time is the time to wait for confirmation
# of an asset or event creation - the default is 300 seconds but one can optionally
# specify a different value.
# The optional partner id field is allocated by Datatrails to partners - partners are then
# expected to specify this value when submitting any request to the archivist product.
# Leave blank if if you do not have a partner ID.
with Archivist(
"https://app.datatrails.ai",
auth,
max_time=300,
partner_id="acme/f7a6beef-f01c-4b39-a494-3fa6b45d6bf4",
) as arch:
# Create a new asset
asset = create_asset(arch)
Expand Down
6 changes: 5 additions & 1 deletion functests/constants.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
"""
hide docstringss
constantss
"""

# pylint: disable=missing-docstring

import unittest

PARTNER_ID_VALUE = "acmecorp"
USER_AGENT_VALUE = "functests/v0.1.0"


class TestCase(unittest.TestCase):
# ....
Expand Down
21 changes: 17 additions & 4 deletions functests/execaccess_policies.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@
from archivist.constants import ASSET_BEHAVIOURS
from archivist.utils import get_auth

from .constants import TestCase
from .constants import (
PARTNER_ID_VALUE,
USER_AGENT_VALUE,
TestCase,
)

# pylint: disable=fixme
# pylint: disable=missing-docstring
Expand Down Expand Up @@ -117,7 +121,12 @@ def setUp(self):
client_secret=getenv("DATATRAILS_APPREG_SECRET"),
client_secret_filename=getenv("DATATRAILS_APPREG_SECRET_FILENAME"),
)
self.arch = Archivist(getenv("DATATRAILS_URL"), auth)
self.arch = Archivist(
getenv("DATATRAILS_URL"),
auth,
partner_id=PARTNER_ID_VALUE,
user_agent=USER_AGENT_VALUE,
)

# these are for access_policies
self.ac_props = deepcopy(PROPS)
Expand Down Expand Up @@ -298,8 +307,12 @@ def setUp(self):
super().setUp()
with open(getenv("DATATRAILS_AUTHTOKEN_FILENAME_2"), encoding="utf-8") as fd:
auth_2 = fd.read().strip()
self.arch_2 = Archivist(getenv("DATATRAILS_URL"), auth_2)

self.arch_2 = Archivist(
getenv("DATATRAILS_URL"),
auth_2,
partner_id=PARTNER_ID_VALUE,
user_agent=USER_AGENT_VALUE,
)
# creates reciprocal subjects for arch 1 and arch 2.
# subject 1 contains details of subject 2 to be shared
self.subject_1, self.subject_2 = self.arch.subjects.share(
Expand Down
13 changes: 11 additions & 2 deletions functests/execapplications.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@
from archivist.errors import ArchivistUnauthenticatedError
from archivist.utils import get_auth

from .constants import TestCase
from .constants import (
PARTNER_ID_VALUE,
USER_AGENT_VALUE,
TestCase,
)

# pylint: disable=fixme
# pylint: disable=missing-docstring
Expand Down Expand Up @@ -54,7 +58,12 @@ def setUp(self):
client_secret=getenv("DATATRAILS_APPREG_SECRET"),
client_secret_filename=getenv("DATATRAILS_APPREG_SECRET_FILENAME"),
)
self.arch = Archivist(getenv("DATATRAILS_URL"), auth)
self.arch = Archivist(
getenv("DATATRAILS_URL"),
auth,
partner_id=PARTNER_ID_VALUE,
user_agent=USER_AGENT_VALUE,
)
self.display_name = f"{DISPLAY_NAME} {uuid4()}"

def tearDown(self):
Expand Down
22 changes: 19 additions & 3 deletions functests/execassets.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@
from archivist.proof_mechanism import ProofMechanism
from archivist.utils import get_auth

from .constants import TestCase
from .constants import (
PARTNER_ID_VALUE,
USER_AGENT_VALUE,
TestCase,
)

# pylint: disable=fixme
# pylint: disable=missing-docstring
Expand Down Expand Up @@ -87,7 +91,13 @@ def setUp(self):
client_secret=getenv("DATATRAILS_APPREG_SECRET"),
client_secret_filename=getenv("DATATRAILS_APPREG_SECRET_FILENAME"),
)
self.arch = Archivist(getenv("DATATRAILS_URL"), auth, max_time=30)
self.arch = Archivist(
getenv("DATATRAILS_URL"),
auth,
max_time=30,
partner_id=PARTNER_ID_VALUE,
user_agent=USER_AGENT_VALUE,
)
self.attrs = deepcopy(ATTRS)
self.traffic_light = deepcopy(ATTRS)
self.traffic_light["arc_display_type"] = "Traffic light with violation camera"
Expand Down Expand Up @@ -233,7 +243,13 @@ def setUp(self):
client_secret=getenv("DATATRAILS_APPREG_SECRET"),
client_secret_filename=getenv("DATATRAILS_APPREG_SECRET_FILENAME"),
)
self.arch = Archivist(getenv("DATATRAILS_URL"), auth, max_time=600)
self.arch = Archivist(
getenv("DATATRAILS_URL"),
auth,
max_time=30,
partner_id=PARTNER_ID_VALUE,
user_agent=USER_AGENT_VALUE,
)

def tearDown(self):
self.arch.close()
Expand Down
20 changes: 17 additions & 3 deletions functests/execattachments.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@
from archivist.errors import ArchivistBadRequestError
from archivist.utils import get_auth, get_url

from .constants import TestCase
from .constants import (
PARTNER_ID_VALUE,
USER_AGENT_VALUE,
TestCase,
)

if getenv("DATATRAILS_LOGLEVEL") is not None:
logger.set_logger(getenv("DATATRAILS_LOGLEVEL"))
Expand Down Expand Up @@ -46,7 +50,12 @@ def setUp(self):
client_secret=getenv("DATATRAILS_APPREG_SECRET"),
client_secret_filename=getenv("DATATRAILS_APPREG_SECRET_FILENAME"),
)
self.arch = Archivist(getenv("DATATRAILS_URL"), auth)
self.arch = Archivist(
getenv("DATATRAILS_URL"),
auth,
partner_id=PARTNER_ID_VALUE,
user_agent=USER_AGENT_VALUE,
)
self.file_uuid: str = ""

with suppress(FileNotFoundError):
Expand Down Expand Up @@ -208,7 +217,12 @@ def setUp(self):
client_secret=getenv("DATATRAILS_APPREG_SECRET"),
client_secret_filename=getenv("DATATRAILS_APPREG_SECRET_FILENAME"),
)
self.arch = Archivist(getenv("DATATRAILS_URL"), auth)
self.arch = Archivist(
getenv("DATATRAILS_URL"),
auth,
partner_id=PARTNER_ID_VALUE,
user_agent=USER_AGENT_VALUE,
)

def tearDown(self):
self.arch.close()
Expand Down
13 changes: 11 additions & 2 deletions functests/execcompliance_policies.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@
from archivist.compliance_policy_type import CompliancePolicyType
from archivist.utils import get_auth

from .constants import TestCase
from .constants import (
PARTNER_ID_VALUE,
USER_AGENT_VALUE,
TestCase,
)

# pylint: disable=fixme
# pylint: disable=missing-docstring
Expand Down Expand Up @@ -99,7 +103,12 @@ def setUp(self):
client_secret=getenv("DATATRAILS_APPREG_SECRET"),
client_secret_filename=getenv("DATATRAILS_APPREG_SECRET_FILENAME"),
)
self.arch = Archivist(getenv("DATATRAILS_URL"), auth)
self.arch = Archivist(
getenv("DATATRAILS_URL"),
auth,
partner_id=PARTNER_ID_VALUE,
user_agent=USER_AGENT_VALUE,
)
self.identities = []

def tearDown(self):
Expand Down
13 changes: 11 additions & 2 deletions functests/execnotebooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@
from archivist import logger
from archivist.archivist import Archivist

from .constants import TestCase
from .constants import (
PARTNER_ID_VALUE,
USER_AGENT_VALUE,
TestCase,
)

if getenv("DATATRAILS_LOGLEVEL") is not None:
logger.set_logger(getenv("DATATRAILS_LOGLEVEL"))
Expand All @@ -37,7 +41,12 @@ def setUp(self):
self.client_id = getenv("DATATRAILS_APPREG_CLIENT")
self.client_secret = getenv("DATATRAILS_APPREG_SECRET")
self.url = getenv("DATATRAILS_URL")
self.arch = Archivist(self.url, (self.client_id, self.client_secret))
self.arch = Archivist(
self.url,
(self.client_id, self.client_secret),
partner_id=PARTNER_ID_VALUE,
user_agent=USER_AGENT_VALUE,
)

def tearDown(self):
self.arch.close()
Expand Down
Loading

0 comments on commit 03d1228

Please sign in to comment.