Skip to content

Commit

Permalink
Merge branch 'release-v3.2.6'
Browse files Browse the repository at this point in the history
* release-v3.2.6:
  Update documentation
  Add enumerate_stats() utility
  • Loading branch information
rastern committed Jun 25, 2020
2 parents 9bde80b + c6fb26c commit ffddcb4
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 67 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ tests
*.pyc
vmtconnect.egg-info
archive
resources
41 changes: 0 additions & 41 deletions README.rst

This file was deleted.

4 changes: 2 additions & 2 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@
# built documents.
#
# The short X.Y version.
version = u'3.2.5'
version = u'3.2.6'
# The full version, including alpha/beta/rc tags.
release = u'3.2.5'
release = u'3.2.6'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
31 changes: 30 additions & 1 deletion docs/source/vmtconnect.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,52 @@ This part of the documentation covers all the interfaces of vmt-connect.
Connections
===========

Connection
^^^^^^^^^^
.. autoclass:: Connection
:members:

Session
^^^^^^^
.. autoclass:: Session
:show-inheritance:
:inherited-members:
:members:

|
Response Handlers
=================

Pager
^^^^^
.. autoclass:: Pager
:members:

|
Versioning
==========

Version
^^^^^^^
.. autoclass:: Version
:members:

VersionSpec
^^^^^^^^^^^
.. autoclass:: VersionSpec
:members:

|
Utilities
=========

enumerate_stats()
^^^^^^^^^^^^^^^^^
.. autofunction:: enumerate_stats

|
Exceptions
==========
Expand All @@ -53,3 +74,11 @@ Exceptions
.. autoexception:: vmtconnect.HTTP502Error
.. autoexception:: vmtconnect.HTTP503Error
.. autoexception:: vmtconnect.HTTPWarn

|
Deprecated Interfaces
=====================

.. autoclass:: VMTConnection
.. autoclass:: VMTVersion
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
readme = fp.read()

requires = [
'requests>=2.21.0'
'requests>=2.21.0,<3'
]

setup(
Expand Down
2 changes: 1 addition & 1 deletion vmtconnect/__about__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

__title__ = 'vmtconnect'
__description__ = 'Turbonomic API Client'
__version__ = '3.2.5'
__version__ = '3.2.6'
__author__ = 'R.A. Stern'
__author_email__ = 'richard.stern@turbonomic.com'
__license__ = 'Apache 2.0'
Expand Down
1 change: 1 addition & 0 deletions vmtconnect/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,5 @@
'VMTVersion',
'VMTVersionError',
'VMTVersionWarning',
'enumerate_stats'
]
109 changes: 88 additions & 21 deletions vmtconnect/vmtconnect.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ class HTTPWarn(Exception):
class Version:
"""Turbonomic instance version object
The :class:`~Version` object contains instance version information, and
The :py:class:`~Version` object contains instance version information, and
equivalent Turbonomic version information in the case of a white label
product.
Expand Down Expand Up @@ -303,7 +303,7 @@ class VersionSpec:
#TODO Additionally, you may use python version prefixes: >=, >, <, <=, ==
"""Turbonomic version specification object
The :class:`~VersionSpec` object contains version compatibility and
The :py:class:`~VersionSpec` object contains version compatibility and
requirements information. Versions must be in dotted format, and may
optionally have a '+' postfix to indicate versions greater than or equal
to are acceptable. If using '+', you only need to specify the minimum
Expand Down Expand Up @@ -402,10 +402,10 @@ def _check(current, versions, required=True, warn=True):
return False

def check(self, version):
"""Checks a :class:`~Version` for validity against the :class:`~VersionSpec`.
"""Checks a :py:class:`~Version` for validity against the :py:class:`~VersionSpec`.
Args:
version (obj): The :class:`~Version` to check.
version (obj): The :py:class:`~Version` to check.
Returns:
True if valid, False if the version is excluded or not found.
Expand Down Expand Up @@ -451,8 +451,8 @@ def check(self, version):
class VMTVersion(VersionSpec):
"""Alias for :py:class:`~VersionSpec` to provide backwards compatibility.
Notes:
To be removed in a future branch.
Warning:
Deprecated. Use :py:class:`~VersionSpec` instead.
"""
def __init__(self, versions=None, exclude=None, require=False):
super().__init__(versions=versions, exclude=exclude, required=require)
Expand All @@ -463,7 +463,7 @@ class Pager:
A :py:class:`~Pager` is a special request handler which permits the processing
of paged :py:meth:`~Connection.request` results, keeping state between each
successive call. Although you can instantiate a :class:`~Pager` directly,
successive call. Although you can instantiate a :py:class:`~Pager` directly,
it is strongly recommended to request one by adding ``pager=True`` to your
existing :py:class:`Connection` method call.
Expand Down Expand Up @@ -586,6 +586,7 @@ def response(self):
res = self.__response.json()
return [res] if isinstance(res, dict) else res


class Connection:
"""Turbonomic instance connection class
Expand Down Expand Up @@ -638,23 +639,28 @@ class Connection:
Notes:
The default minimum version for classic builds is 6.1.x, and for XL it
is 7.21.x Using a previous version will trigger a version warning. To
avoid this warning, you will need to explicitly pass in a :class:`~VMTVersionSpec`
avoid this warning, you will need to explicitly pass in a :py:class:`~VersionSpec`
object for the version desired.
Beginning with v6.0 of Turbonomic, HTTP redirects to a self-signed HTTPS
connection. Because of this, vmt-connect defaults to using SSL. Versions
prior to 6.0 using HTTP will need to manually set ssl to ``False``. If
verify is given a path to a directory, the directory must have been
**verify** is given a path to a directory, the directory must have been
processed using the c_rehash utility supplied with OpenSSL. For client
side certificates using **cert**: the private key to your local certificate
must be unencrypted. Currently, Requests does not support using encrypted
keys. Requests uses certificates from the package certifi.
must be unencrypted. Currently, Requests, which vmt-connect relies on,
does not support using encrypted keys. Requests uses certificates from
the package certifi.
The /api/v2 path was added in 6.4, and the /api/v3 path was added in XL
branch 7.21. The XL API is not intended to be an extension of the Classic
API, though there is extensive parity. *vmt-connect* will attempt to
detect which API you are connecting to and adjust accordingly where
possible.
XL uses OID identifiers internally instead of UUID identifiers. The
change generally does not affect the API, the UUID label is still used,
although the structure of the IDs is different.
"""
# system level markets to block certain actions
# this is done by name, and subject to breaking if names are abused
Expand Down Expand Up @@ -1133,6 +1139,12 @@ def get_entities(self, type=None, uuid=None, detail=False, market='Market',
Returns:
A list of entities in :obj:`dict` form.
Notes:
**type** filtering is performed locally and is not compatible with
responses that return a :py:class:`~Pager` object. Therefore, if you
attempt to request a :py:class:`~Pager` response, **type** will be
ignored.
"""
query = {}

Expand All @@ -1157,7 +1169,7 @@ def get_entities(self, type=None, uuid=None, detail=False, market='Market',
else:
entities = self.request(path, method='GET', query=query, **kwargs)

if type:
if type and isinstance(entities, Pager):
return [x for x in entities if x['className'] == type]

return entities
Expand Down Expand Up @@ -1222,7 +1234,7 @@ def get_entity_groups(self, uuid, **kwargs):
return self.request(f'entities/{uuid}/groups', **kwargs)

def get_entity_stats(self, scope, start_date=None, end_date=None,
stats=None, dto=None, **kwargs):
stats=None, related_type=None, dto=None, **kwargs):
"""Returns stats for the specific scope of entities.
Provides entity level stats with filtering. If using the DTO keyword,
Expand All @@ -1235,6 +1247,7 @@ def get_entity_stats(self, scope, start_date=None, end_date=None,
end_date (int, optional): Unix timestamp in miliseconds. Uses current
time if blank.
stats (list, optional): List of stats classes to retrieve.
related_type (str, optional): Related entity type to pull stats for.
dto (dict, optional): Complete JSON DTO of the stats required.
Returns:
Expand All @@ -1256,6 +1269,9 @@ def get_entity_stats(self, scope, start_date=None, end_date=None,
if period:
dto['period'] = period

if related_type:
dto['relatedType'] = related_type

dto = json.dumps(dto)

return self.request('stats', method='POST', dto=dto, **kwargs)
Expand Down Expand Up @@ -1395,7 +1411,6 @@ def get_supplychains(self, uuids, types=None, states=None, detail=None,
"""Returns a set of supplychains for the given uuid.
Args:
uuids (str): Single UUID to query.
uuids (list): List of UUIDs to query.
types (list, optional): List of entity types.
states: (list, optional): List of entity states to filter by.
Expand Down Expand Up @@ -1737,12 +1752,12 @@ def update_static_group_members(self, uuid, members, name=None, type=None):


class Session(Connection):
"""Alias for :class:`~Connection` to provide convenience.
"""Alias for :py:class:`~Connection` to provide convenience.
See :class:`~Connection` for parameter details.
See :py:class:`~Connection` for parameter details.
Notes:
The value for the :class:`~Connection.session` property will always be set to ``True`` when using :class:`~Session`
The value for the :py:class:`~Connection.session` property will always be set to ``True`` when using :py:class:`~Session`
"""
def __init__(self, *args, **kwargs):
Expand All @@ -1751,13 +1766,65 @@ def __init__(self, *args, **kwargs):


class VMTConnection(Session):
"""Alias for :class:`~Connection` to provide backwards compatibility.
"""Alias for :py:class:`~Connection` to provide backwards compatibility.
See :class:`~Connection` for parameter details.
See :py:class:`~Connection` for parameter details.
Notes:
The value for :class:`~Connection.session` will default to ``True`` when using :class:`~VMTConnection`
To be removed in 4.0.
The value for :py:class:`~Connection.session` will default to ``True``
when using :py:class:`~VMTConnection`
Warning:
Deprecated. Use :py:class:`~Connection` or :py:class:`~Session`
instead.
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)



# ----------------------------------------------------
# Utility functions
# ----------------------------------------------------
def enumerate_stats(data, entity=None, period=None, stat=None):
"""Enumerates stats endpoint results
Provides an iterator for more intuitive and cleaner parsing of nested
statistics results. Each iteration returns a tuple containing the statistics
period `date` timestamp, as well as the next individual statistic entry as
a dictionary.
Args:
data (list): Stats endpoint data results to parse.
entity (function, optional): Optional entity level filter function.
period (function, optional): Optional period level filter function.
stat (function, optional): Optional statistic level filter function.
Notes:
Filter functions must return ``True``, to continue processing, or ``False``
to skip processing the current level element.
Examples:
.. code-block:: python
# filter stats for a specific ID
desired_id = '284552108476721'
enumerate_stats(data, entity=lambda x: x['uuid'] == desired_uuid)
# filter specific stats for all IDs
blacklist = ['Ballooning']
enumerate_stats(data, stat=lambda x: x['name'] not in blacklist)
"""
for k1, v1 in enumerate(data):
if entity is not None and not entity(v1) \
or 'stats' not in v1:
continue

for k2, v2 in enumerate(v1['stats']):
if period is not None and not period(v2):
continue

for k3, v3 in enumerate(v2['statistics']):
if stat is not None and not stat(v3):
continue
yield v2['date'], v3

0 comments on commit ffddcb4

Please sign in to comment.