Module intercom_python_sdk.core.api_base
API Base Module
core/api_base.py
Contains the core base classes and methodsfor all API classes in the Intercom Python SDK.
Expand source code
"""
# API Base Module
`core/api_base.py`
Contains the core base classes and methodsfor all API classes in the Intercom Python SDK.
"""
# Third-Party Imports
from uplink import (
Consumer,
json
)
# Local Imports
from .configuration import Configuration
from .model_base import ModelBase
class APIProxyInterface:
"""
A proxy class that functions as an interface to API client / consumer objects.
This allows for interception of API calls and modification of the results.
In practice, this is how the model instance objects are captured and injected
with the API client object.
Given the nature of the Uplink library, it is not possible to inject a reference
to the API client object into the model instance objects from within the API client
itself.
Args:
api_class: The API class to proxy.
config: The configuration settings for the API.
Attributes:
All attributes and methods are passed through to the API object. It will be as if
you are accessing the API object directly.
Returns:
A proxy class that functions as an interface to API client / consumer objects.
"""
def __init__(self, api_class, config):
"""
Set the API object for the API we are proxying
Args:
api_class: The API class to proxy.
config: The configuration settings for the API.
"""
self.api_object = api_class(config)
def __dir__(self):
""" Proxy the dir() method to the API object. """
return dir(self.api_object)
def __getattribute__(self, item):
""" Proxy all attribute access to the API object (except for api_object itself). """
api_object = object.__getattribute__(self, 'api_object')
if item == 'api_object':
return api_object
attr = getattr(api_object, item)
if callable(attr):
# This is where we wrap the callable to intercept the result
return object.__getattribute__(self, '_wrap_callable')(attr)
else:
return attr
def __setattr__(self, item, value):
""" Proxy all attribute setting to the API object (except for api_object itself). """
if item == 'api_object':
return object.__setattr__(self, item, value)
api_object = object.__getattribute__(self, 'api_object')
setattr(api_object, item, value)
def __call__(self, *args, **kwargs):
raise NotImplementedError("Direct method calls on APIProxyInterface are not supported. \
Access methods through api_object.")
def __repr__(self):
return repr(f"<{object.__getattribute__(self, '__class__').__name__}> - {self.api_object}")
def _wrap_callable(self, method):
"""
Wraps callable method to intercept the result.
If the result is a model object, inject the API client into the model object.
"""
def wrapped(*args, **kwargs):
result = method(*args, **kwargs)
inject_into_instances = object.__getattribute__(self, '_inject_into_instances')
inject_into_instances(result, ModelBase, 'api_client', self.api_object)
return result
return wrapped
def _inject_into_instances(self, obj, cls, attribute_name, attribute_value, visited=None):
"""
Allows us to inject an attribute into all instances of a class, contained
within an arbitrary data structure of unknown depth.
This is useful for injecting the API client instance into Model Objects
that may be contained within some nested data structure (like a list of objects).
"""
if visited is None:
visited = set()
if id(obj) in visited:
return
visited.add(id(obj))
inject_into_instances_method = object.__getattribute__(self, '_inject_into_instances')
inject = lambda obj: inject_into_instances_method(obj, cls, attribute_name, attribute_value, visited) # noqa
if isinstance(obj, cls):
obj.__setattr__(attribute_name, attribute_value)
if isinstance(obj, dict):
for value in obj.values():
inject(value)
elif isinstance(obj, (list, set, tuple)):
for item in obj:
inject(item)
elif hasattr(obj, '__dict__'):
for attr in vars(obj).values():
inject(attr)
@json # type: ignore
class APIBase(Consumer):
"""
The base class for all API classes in the Intercom Python SDK.
"""
URI = ""
def __init__(self, config: Configuration, **kwargs):
"""
Initializes a new instance of the APIBase class.
Overrides the Consumer class from the Uplink library to
configure the Consumer instance using a Configuration object.
Args:
config: The configuration settings for the API.
"""
self.config = config
self.base_url = config.base_url + self.URI
super().__init__(
base_url=self.base_url,
converters=config.converters,
hooks=config.hooks,
auth=config.auth,
client=config.session
)
def make_subapi(self, api_tag, api_cls, api_config):
# api_tag is the name of the subapi
# api_cls class
# api_config is the config object
if not hasattr(self, api_tag):
# If the subapi has not been created yet, create it
setattr(self, api_tag, create_api_client(api_cls, api_config))
else:
# If the subapi has already been created, return it
return getattr(self, api_tag)
# Functions
def create_api_client(api_class: 'APIBase', config: Configuration) -> APIProxyInterface: # type: ignore
"""
Creates a proxy interface for an API client for the provided API class.
Args:
api_class: The API class to create a client for.
config: The configuration settings for the API.
Returns:
An proxy interface to the instance of the API class with an API client attached to each model object.
"""
return APIProxyInterface(api_class, config)
Functions
def create_api_client(api_class: APIBase, config: Configuration) ‑> APIProxyInterface
-
Creates a proxy interface for an API client for the provided API class.
Args
api_class
- The API class to create a client for.
config
- The configuration settings for the API.
Returns
An proxy interface to the instance of the API class with an API client attached to each model object.
Expand source code
def create_api_client(api_class: 'APIBase', config: Configuration) -> APIProxyInterface: # type: ignore """ Creates a proxy interface for an API client for the provided API class. Args: api_class: The API class to create a client for. config: The configuration settings for the API. Returns: An proxy interface to the instance of the API class with an API client attached to each model object. """ return APIProxyInterface(api_class, config)
Classes
class APIBase (config: Configuration, **kwargs)
-
The base class for all API classes in the Intercom Python SDK.
Initializes a new instance of the APIBase class. Overrides the Consumer class from the Uplink library to configure the Consumer instance using a Configuration object.
Args
config
- The configuration settings for the API.
Expand source code
@json # type: ignore class APIBase(Consumer): """ The base class for all API classes in the Intercom Python SDK. """ URI = "" def __init__(self, config: Configuration, **kwargs): """ Initializes a new instance of the APIBase class. Overrides the Consumer class from the Uplink library to configure the Consumer instance using a Configuration object. Args: config: The configuration settings for the API. """ self.config = config self.base_url = config.base_url + self.URI super().__init__( base_url=self.base_url, converters=config.converters, hooks=config.hooks, auth=config.auth, client=config.session ) def make_subapi(self, api_tag, api_cls, api_config): # api_tag is the name of the subapi # api_cls class # api_config is the config object if not hasattr(self, api_tag): # If the subapi has not been created yet, create it setattr(self, api_tag, create_api_client(api_cls, api_config)) else: # If the subapi has already been created, return it return getattr(self, api_tag)
Ancestors
- uplink.builder.Consumer
- uplink.interfaces.Consumer
- uplink.builder._Consumer
Subclasses
- AdminsAPI
- ArticlesAPI
- ConversationAPI
- DataAttributesAPI
- DataEventsAPI
- DataExportAPI
- HelpCenterAPI
- TeamsAPI
Class variables
var URI
Methods
def make_subapi(self, api_tag, api_cls, api_config)
-
Expand source code
def make_subapi(self, api_tag, api_cls, api_config): # api_tag is the name of the subapi # api_cls class # api_config is the config object if not hasattr(self, api_tag): # If the subapi has not been created yet, create it setattr(self, api_tag, create_api_client(api_cls, api_config)) else: # If the subapi has already been created, return it return getattr(self, api_tag)
class APIProxyInterface (api_class, config)
-
A proxy class that functions as an interface to API client / consumer objects. This allows for interception of API calls and modification of the results. In practice, this is how the model instance objects are captured and injected with the API client object.
Given the nature of the Uplink library, it is not possible to inject a reference to the API client object into the model instance objects from within the API client itself.
Args
api_class
- The API class to proxy.
config
- The configuration settings for the API.
Attributes
All attributes and methods are passed through to the API object. It will be as if you are accessing the API object directly.
Returns
A proxy class that functions as an interface to API client / consumer objects. Set the API object for the API we are proxying
Args
api_class
- The API class to proxy.
config
- The configuration settings for the API.
Expand source code
class APIProxyInterface: """ A proxy class that functions as an interface to API client / consumer objects. This allows for interception of API calls and modification of the results. In practice, this is how the model instance objects are captured and injected with the API client object. Given the nature of the Uplink library, it is not possible to inject a reference to the API client object into the model instance objects from within the API client itself. Args: api_class: The API class to proxy. config: The configuration settings for the API. Attributes: All attributes and methods are passed through to the API object. It will be as if you are accessing the API object directly. Returns: A proxy class that functions as an interface to API client / consumer objects. """ def __init__(self, api_class, config): """ Set the API object for the API we are proxying Args: api_class: The API class to proxy. config: The configuration settings for the API. """ self.api_object = api_class(config) def __dir__(self): """ Proxy the dir() method to the API object. """ return dir(self.api_object) def __getattribute__(self, item): """ Proxy all attribute access to the API object (except for api_object itself). """ api_object = object.__getattribute__(self, 'api_object') if item == 'api_object': return api_object attr = getattr(api_object, item) if callable(attr): # This is where we wrap the callable to intercept the result return object.__getattribute__(self, '_wrap_callable')(attr) else: return attr def __setattr__(self, item, value): """ Proxy all attribute setting to the API object (except for api_object itself). """ if item == 'api_object': return object.__setattr__(self, item, value) api_object = object.__getattribute__(self, 'api_object') setattr(api_object, item, value) def __call__(self, *args, **kwargs): raise NotImplementedError("Direct method calls on APIProxyInterface are not supported. \ Access methods through api_object.") def __repr__(self): return repr(f"<{object.__getattribute__(self, '__class__').__name__}> - {self.api_object}") def _wrap_callable(self, method): """ Wraps callable method to intercept the result. If the result is a model object, inject the API client into the model object. """ def wrapped(*args, **kwargs): result = method(*args, **kwargs) inject_into_instances = object.__getattribute__(self, '_inject_into_instances') inject_into_instances(result, ModelBase, 'api_client', self.api_object) return result return wrapped def _inject_into_instances(self, obj, cls, attribute_name, attribute_value, visited=None): """ Allows us to inject an attribute into all instances of a class, contained within an arbitrary data structure of unknown depth. This is useful for injecting the API client instance into Model Objects that may be contained within some nested data structure (like a list of objects). """ if visited is None: visited = set() if id(obj) in visited: return visited.add(id(obj)) inject_into_instances_method = object.__getattribute__(self, '_inject_into_instances') inject = lambda obj: inject_into_instances_method(obj, cls, attribute_name, attribute_value, visited) # noqa if isinstance(obj, cls): obj.__setattr__(attribute_name, attribute_value) if isinstance(obj, dict): for value in obj.values(): inject(value) elif isinstance(obj, (list, set, tuple)): for item in obj: inject(item) elif hasattr(obj, '__dict__'): for attr in vars(obj).values(): inject(attr)