Improved inline documentation

This commit is contained in:
Matthew Connelly 2019-05-22 18:01:15 +01:00
parent 6f771fce0c
commit c4869200db
1 changed files with 137 additions and 2 deletions

View File

@ -99,9 +99,27 @@ class TransactionalObject(APIObject):
class Py3CX: class Py3CX:
class _Call(ReadOnlyObject): class _Call(ReadOnlyObject):
def __init__(self, tcx, callid): def __init__(self, tcx, callid):
"""Returns a Py3CX.Call object
Returns a Py3CX.Call object representing a currently-ongoing or historical call on a 3CX system
Parameters
---
tcx: Required, Py3CX object representing an authenticated 3CX API session
callid: Required, integer representing the unique identifier of a given call
"""
super().__init__(tcx, 'activeCalls') super().__init__(tcx, 'activeCalls')
self.params=callid self.params=callid
def refresh(self): def refresh(self):
"""Initialises or updates the properties of the current Py3CX.Call object
Loads in and stores the properties of the current Py3CX.Call object by performing a GET request to the 'activeCalls' API endpoint, filtering the resulting list by the Call ID.
Future: Calls not present in the activeCalls API call results should be queried against the call history database
>>> cl=tcx._Call(tcx, 1234)
>>> cl.state
Dialing
"""
self.refresh() self.refresh()
self.timestamp=self._result.headers.get('date') self.timestamp=self._result.headers.get('date')
res=list(filter(lambda cid: cid['Id'] == self.params, self._result.json()['list'])) res=list(filter(lambda cid: cid['Id'] == self.params, self._result.json()['list']))
@ -117,11 +135,40 @@ class Py3CX:
def __repr__(self): def __repr__(self):
return '<Py3CX.Call [%s %s]>' % (self.id, self.state) return '<Py3CX.Call [%s %s]>' % (self.id, self.state)
def hangup(self): def hangup(self):
"""Terminates the current call
If the call represented by this object is an ongoing call, drops the call by performing a POST request to 'activeCalls/drop' with the Call ID as the Id parameter in the JSON payload
>>> cl=tcx._Call(tcx, 1234)
>>> cl.state
Connected
>>> cl.hangup()
>>> cl.state
Terminated
"""
self.refresh()
if self.state is 'Terminated':
return
self.tcx.rq.post('activeCalls/drop', params={ self.tcx.rq.post('activeCalls/drop', params={
'Id': self.params}) 'Id': self.params})
self.params=None self.refresh()
class _User(TransactionalObject): class _User(TransactionalObject):
def __init__(self, parent, params): def __init__(self, parent, params):
"""Returns a Py3CX.User object
Returns a Py3CX.User object which represents a given user account (Extension) on a 3CX system, including more advanced attributes.
Parameters
---
parent: Required, Py3CX object representing an authenticated 3CX API session
params: Required, string representing the extension number of a given user
>>> user=tcx._User(tcx, '1234')
>>> user.enabled
True
>>> user.extension
<Py3CX.Extension [1234]>
"""
super().__init__(parent, 'ExtensionList/set') super().__init__(parent, 'ExtensionList/set')
self.params=params self.params=params
self.load() self.load()
@ -146,6 +193,23 @@ class Py3CX:
self.cancel() self.cancel()
class _Extension(ReadOnlyObject): class _Extension(ReadOnlyObject):
def __init__(self, parent, params, populate=True): def __init__(self, parent, params, populate=True):
"""Returns a Py3CX.Extension object
Returns a Py3CX.Extension object representing information about the specified extension number.
Parameters
---
parent: Required, Py3CX object representing the authenticated 3CX session
params: Required, string representing the extension number to select
populate: Optional, boolean indicator as to whether the object should be populated during instantiation
>>> extension=tcx.system.list_extensions[0]
>>> extension
<Py3CX.Extension [1234]>
>>> extension=tcx._Extension(tcx, '1234')
>>> extension.number
'1234'
"""
super().__init__(parent, api='ExtensionList') super().__init__(parent, api='ExtensionList')
self.params=params self.params=params
if populate: if populate:
@ -153,6 +217,15 @@ class Py3CX:
def __repr__(self): def __repr__(self):
return '<Py3CX.Extension [%s]>' % self.number return '<Py3CX.Extension [%s]>' % self.number
def load(self): def load(self):
"""Initialises or updates the Py3CX.Extension object with the latest properties from the server
Performs a GET request to 'ExtensionList', filtering the response by matches against the specified extension number, populating the object's properties with the filtered results
>>> extension=tcx._Extension(tcx, '1234', populate=False)
>>> extension.load()
>>> extension.number
'1234'
"""
self.refresh(params=self.params) self.refresh(params=self.params)
res=self._result res=self._result
self.timestamp=res.headers.get('date') self.timestamp=res.headers.get('date')
@ -176,7 +249,18 @@ class Py3CX:
pass pass
class Status(object): class Status(object):
pass pass
def __init__(self, tcx): def __init__(self, tcx : 'Py3CX'):
"""Returns a Py3CX.System object
Returns a Py3CX.System object, which contains functionality for obtaining or acting on system-wide components of a 3CX system
Parameters
---
tcx: Required, Py3CX instance considered the parent object
>>> tcx._PhoneSystem(tcx)
<Py3CX.System [http://myinstance.3cx.com]>
"""
self.tcx=tcx self.tcx=tcx
self.calllist=None self.calllist=None
self.extlist=None self.extlist=None
@ -238,6 +322,13 @@ class Py3CX:
self.refresh_sysstat() self.refresh_sysstat()
@property @property
def list_extensions(self) -> typing.List['Py3CX._Extension']: def list_extensions(self) -> typing.List['Py3CX._Extension']:
"""Returns a list of Py3CX.Extension objects
Returns a list of Py3CX.Extension objects representing every configured extension on a 3CX phone system
>>> tcx.system.list_extensions
[<Py3CX.Extension[0000]>, <Py3CX.Extension[1234]>]
"""
if self.extlist is None: if self.extlist is None:
self.extlist=ReadOnlyObject(self.tcx, api='ExtensionList') self.extlist=ReadOnlyObject(self.tcx, api='ExtensionList')
self.extlist.refresh() self.extlist.refresh()
@ -259,6 +350,13 @@ class Py3CX:
return ret return ret
@property @property
def list_calls(self) -> typing.List['Py3CX._Call']: def list_calls(self) -> typing.List['Py3CX._Call']:
"""Returns a list of Py3CX.Call objects
Returns a list of Py3CX.Call objects representing all current active calls on the phone system
>>> tcx.system.list_calls
[<Py3CX.Call [1234 Dialing]>]
"""
if self.calllist is None: if self.calllist is None:
self.calllist=ReadOnlyObject(self.tcx, api='activeCalls') self.calllist=ReadOnlyObject(self.tcx, api='activeCalls')
self.calllist.refresh() self.calllist.refresh()
@ -276,6 +374,17 @@ class Py3CX:
ret.append(this) ret.append(this)
return ret return ret
def __init__(self, uri=None, tls_verify=True): def __init__(self, uri=None, tls_verify=True):
"""Returns a Py3CX class object instance
Returns an instance of the Py3CX class, which is the primary entrypoint of this module.
Parameters
---
uri: Optional HTTP/HTTPS URI to your 3CX FQDN. Do not include the /api/. If not explicitly specified, this can instead be set through environment variables
tls_verify: Optional boolean attribute indicating whether the TLS certificate presented by the 3CX phone system should be validated against internal root trust
>>> tcx=Py3CX(uri='http://myinstance.3cx.com')
"""
self.cnf=Py3CXEnvironmentVars() self.cnf=Py3CXEnvironmentVars()
self._tcxsystem=None self._tcxsystem=None
if uri is not None: if uri is not None:
@ -285,6 +394,14 @@ class Py3CX:
def __repr__(self): def __repr__(self):
return '<Py3CX [%s@%s]>' % (self.cnf.auth_user, self.cnf.uri) return '<Py3CX [%s@%s]>' % (self.cnf.auth_user, self.cnf.uri)
def authenticate(self, username=None, password=None): def authenticate(self, username=None, password=None):
"""Authenticates against the given API, optionally using explicit credentials.
Performs a POST request to the 'login' endpoint of the current API server, using either credentials gleaned through the execution environment, or explicitly specified during the function invocation.
>>> tcx.authenticate()
>>> tcx.authenticate(username='admin', password='password')
"""
if username is not None: if username is not None:
self.cnf.auth_user=username self.cnf.auth_user=username
if password is not None: if password is not None:
@ -296,6 +413,17 @@ class Py3CX:
self.rq.sess.headers.update({'x-xsrf-token':rs.cookies['XSRF-TOKEN']}) self.rq.sess.headers.update({'x-xsrf-token':rs.cookies['XSRF-TOKEN']})
@property @property
def authenticated(self) -> bool: def authenticated(self) -> bool:
"""Boolean property noting if the current session is logged-in.
Returns a boolean value indicating whether the Py3CX instance is authenticated against the configured 3CX server, by performing a GET request to the 'CurrentUser' API endpoint.
The expected response code is HTTP 200. If that expectation is not met, an exception is thrown which this function translates to a boolean value.
>>> tcx.authenticated
False
>>> tcx.authenticate()
>>> tcx.authenticated
True
"""
try: try:
self.rq.get('CurrentUser') self.rq.get('CurrentUser')
except APIError: except APIError:
@ -303,6 +431,13 @@ class Py3CX:
return True return True
@property @property
def system(self) -> 'Py3CX._PhoneSystem': def system(self) -> 'Py3CX._PhoneSystem':
"""Returns a Py3CX.System object
Returns the current instance of (and initialises a new instance of, if one does not exist yet) the Py3CX System class, which contains functionality for system-wide 3CX APIs
>>> tcx.system
<Py3CX.System [http://myinstance.3cx.com]>
"""
assert self.authenticated, "Py3CX not authenticated yet!" assert self.authenticated, "Py3CX not authenticated yet!"
if self._tcxsystem is None: if self._tcxsystem is None:
self._tcxsystem=Py3CX._PhoneSystem(self) self._tcxsystem=Py3CX._PhoneSystem(self)