Skip to content

Commit

Permalink
Migrate mock cloud from iotile_analytics to python_iotile_cloud (#19)
Browse files Browse the repository at this point in the history
* Add support for testing using a mock iotile cloud

The mock cloud spins up a local http server and answers api requests
in a compatible manner to the real iotile cloud.  Two pytest fixtures
are registered for use in any package that depends on
python_iotile_cloud:

- mock_cloud
- mock_cloud_nossl

In order to use the first mock_cloud that serves over SSL (with a
self-signed certificate), you must also have pyOpenSSL installed.
See: requirements-test.txt

Closes #18

* Bump version to 0.7.4 for release and update changelog

* Increase appveyor test speed.

We already use tox to run tests against each python version,
specifying a matrix of python versions just changes what version
of python is used to invoke tox the first time, and for each
python version specified it still ran against all specified versions
in tox.

* Fix copy-paste and update version to 0.8.0

* Add ability to quickly mock device, project, streamer, org

See the functions quick_add_{device, project, org, streamer}
for descriptions of the functionality.  There is also a new
fixture mock_cloud_private[_nossl] that resets the cloud after
each test.

Closes #20

* Update fixtures for consistency

* Fix spelling

* Add support for listing device api with project filter

* Add support for including fleets in the mock cloud

* Remove debug print

* Fix python 3 compatibility of mock_cloud
  • Loading branch information
timburke authored Jan 26, 2018
1 parent 89149fc commit c6d0161
Show file tree
Hide file tree
Showing 21 changed files with 2,085 additions and 11 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
.env
*.log
*.json
!/tests/**/*.json

# Setup/Build
build/
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
### v0.8.0 (2018-01-26)

* Add utils.mock_cloud module to allow for testing python functions that depend on cloud apis
* Register two pytest fixtures using the mock cloud: mock_cloud and mock_cloud_nossl

### v0.7.3 (2017-11-29)

* Add utils.mdo.MdoHelper class to help with raw stream data conversions
Expand Down
6 changes: 0 additions & 6 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
environment:

matrix:

# For Python versions available on Appveyor, see
# http://www.appveyor.com/docs/installed-software#python
# The list here is complete (excluding Python 2.6, which
# isn't covered by this document) at the time of writing.

- PYTHON: "C:\\Python27"
- PYTHON: "C:\\Python27-x64"
- PYTHON: "C:\\Python34"
- PYTHON: "C:\\Python34-x64"

install:
# We need wheel installed to build wheels
Expand Down
61 changes: 57 additions & 4 deletions iotile_cloud/utils/gid.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
int2pid = lambda n: int32gid(n)
int2vid = lambda n: int16gid(n)
int2bid = lambda n: int16gid(n)
int2fid = lambda n: int48gid(n)

gid_split = lambda val: val.split('--')

Expand Down Expand Up @@ -46,18 +47,18 @@ def formatted_id(self):
return gid_join(parts[1:])

def set_from_single_id_slug(self, type, terms, id):
assert(type in ['p', 'd', 'b'])
assert(type in ['p', 'd', 'b', 'g'])
assert (isinstance(id, str))
parts = gid_split(id)
if parts[0] in ['p', 'd', 'b']:
if parts[0] in ['p', 'd', 'b', 'g']:
id = parts[1]
id = fix_gid(id, terms)
self._slug = gid_join([type, id])

def get_id(self):
parts = gid_split(self._slug)
assert(len(parts) == 2)
assert(parts[0] in ['p', 'd'])
assert(parts[0] in ['p', 'd', 'g'])
return gid2int(parts[1])


Expand All @@ -76,13 +77,28 @@ class IOTileDeviceSlug(IOTileCloudSlug):
"""Formatted Global Device ID: d--0000-0000-0000-0001"""

def __init__(self, id):
if isinstance(id, IOTileDeviceSlug):
self._slug = id._slug
return

if isinstance(id, int):
did = int2did(id)
did = int2did(id)
else:
did = id
self.set_from_single_id_slug('d', 4, did)


class IOTileFleetSlug(IOTileCloudSlug):
"""Formatted Global Fleet ID: g--0000-0000-0001"""

def __init__(self, id):
if isinstance(id, int):
fid = int2fid(id)
else:
fid = id
self.set_from_single_id_slug('g', 3, fid)


class IOTileBlockSlug(IOTileCloudSlug):
"""Formatted Global DataBlock ID: b--0001-0000-0000-0001"""
_block = None
Expand Down Expand Up @@ -125,6 +141,43 @@ def get_block(self):
return gid2int(self._block)


class IOTileStreamerSlug(IOTileCloudSlug):
"""Formatted Global Streamer ID: t--0000-0000-0000-0000--0000.
Args:
device (str, int or IOTileDeviceSlug): The device that this streamer corresponds with.
index (int): The sub-index of the stream in the device, typically a small number in [0, 8)
"""

def __init__(self, device, index):
if isinstance(device, int):
device_id = device
elif isinstance(device, IOTileDeviceSlug):
device_id = device.get_id()
elif isinstance(device, str):
device_id = IOTileDeviceSlug(device).get_id()
else:
raise ValueError("Unknown device specifier, must be string, int or IOTileDeviceSlug")

index = int(index)

device_gid48 = int2did(device_id)
index_gid = int16gid(index)
device_gid = fix_gid(device_gid48, 4)

self._slug = gid_join(['t', device_gid, index_gid])
self._device = gid_join(['d', device_gid])
self._index = index_gid

def get_device(self):
"""Get the device slug as a string."""
return self._device

def get_index(self):
"""Get the streamer index in the device as a padded string."""
return self._index


class IOTileVariableSlug(IOTileCloudSlug):
"""Formatted Global Variable ID: v--0000-0001--5000"""

Expand Down
Loading

0 comments on commit c6d0161

Please sign in to comment.