diff --git a/ChangeLog.md b/ChangeLog.md index 0d3d104..464b4b4 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -11,6 +11,8 @@ Versioning](http://semver.org/spec/v2.0.0.html). ### Added - This ChangeLog! - Example code +- Add better context to `DataApiException`s +- Telemetry support ### Security fixes: - Bump requests to 2.21.0 (CVE-2018-18074) diff --git a/Makefile b/Makefile index c083503..cb5d6d6 100644 --- a/Makefile +++ b/Makefile @@ -47,11 +47,11 @@ dist: distclean $(PYTHON) setup.py sdist; \ $(PYTHON) setup.py bdist_wheel --universal dist-upload: dist-check-version clean test dist-upload-twine -dist-check-version: PKG_VER=v$(shell sed -n "s/^.*VERSION\s\+=\s\+'\([^']\+\)'.*$$/\1/p" setup.py) +dist-check-version: PKG_VER=v$(shell sed -n "s/^.*__version__\s\+=\s\+'\([^']\+\)'.*$$/\1/p" learnosity_sdk/_version.py) dist-check-version: GIT_TAG=$(shell git describe --tags) dist-check-version: ifeq ('$(shell echo $(GIT_TAG) | grep -qw "$(PKG_VER)")', '') - $(error Version number $(PKG_VER) in setup.py does not match git tag $(GIT_TAG)) + $(error Version number $(PKG_VER) in learnosity_sdk/_version.py does not match git tag $(GIT_TAG)) endif dist-upload-twine: pip-requirements-dev dist # This target doesn't do any safety check! $(call venv-activate); \ diff --git a/README.md b/README.md index 0695ce0..4818db4 100644 --- a/README.md +++ b/README.md @@ -246,10 +246,20 @@ Alternatively, if you only care about the version you're currently running, you # Deploying to PyPi -1. Update the version number in `setup.py` -2. Install the dev requirements `pip install -r requirements-dev.txt` -3. Run `python setup.py sdist` to create the source distribution -4. Run `python setup.py bdist_wheel --universal` to create the binary distribution -5. Run `twine upload dist/*` to deploy the distributions to PyPi +1. Install the dev requirements `pip install -r requirements-dev.txt` +2. Run `python setup.py sdist` to create the source distribution +3. Run `python setup.py bdist_wheel --universal` to create the binary distribution +4. Run `twine upload dist/*` to deploy the distributions to PyPi You will need to be set up as a maintainer in order to do this. + + +## Tracking +In version v0.3.0 we introduced code to track the following information by adding it to the request being signed: +- SDK version +- SDK language +- SDK language version +- Host platform (OS) +- Platform version + +We use this data to enable better support and feature planning. All subsequent versions of the SDK shall include this usage tracking. diff --git a/learnosity_sdk/__init__.py b/learnosity_sdk/__init__.py index 408195c..7e46375 100644 --- a/learnosity_sdk/__init__.py +++ b/learnosity_sdk/__init__.py @@ -1,6 +1,7 @@ import learnosity_sdk.request import learnosity_sdk.exceptions import learnosity_sdk.utils +from learnosity_sdk._version import __version__ __all__ = [ "exceptions", diff --git a/learnosity_sdk/_version.py b/learnosity_sdk/_version.py new file mode 100644 index 0000000..614bae8 --- /dev/null +++ b/learnosity_sdk/_version.py @@ -0,0 +1 @@ +__version__ = '0.2.1pre' diff --git a/learnosity_sdk/request/dataapi.py b/learnosity_sdk/request/dataapi.py index 8a3c6f4..ad66317 100644 --- a/learnosity_sdk/request/dataapi.py +++ b/learnosity_sdk/request/dataapi.py @@ -102,7 +102,9 @@ def request_iter(self, endpoint, security_packet, action ) if not res.ok: - raise DataApiException(res.text) + raise DataApiException( + 'server returned HTTP status ' + str(res.status_code) + + ': ' + res.text) try: data = res.json() except ValueError: @@ -115,7 +117,8 @@ def request_iter(self, endpoint, security_packet, data_end = True if not data['meta']['status']: - raise DataApiException(res.text) + raise DataApiException( + 'server returned unsuccessful status: ' + res.text) else: yield data diff --git a/learnosity_sdk/request/init.py b/learnosity_sdk/request/init.py index dd260c2..0c0a686 100644 --- a/learnosity_sdk/request/init.py +++ b/learnosity_sdk/request/init.py @@ -2,6 +2,8 @@ import datetime import hashlib import json +import platform +from learnosity_sdk._version import __version__ from learnosity_sdk.exceptions import ValidationException @@ -45,6 +47,12 @@ def __init__( self.security['signature'] = self.generate_signature() + """ + We use telemetry to enable better support and feature planning. It is + however not advised to disable it, and it will not interfere with any usage. + """ + self.__telemetry_enabled = True + def generate(self, encode=True): """ Generate the data necessary to make a request to one of the Learnosity @@ -93,11 +101,28 @@ def generate(self, encode=True): if self.action is not None: output['action'] = self.action + if self.__telemetry_enabled: + output['meta'] = self.get_meta() + if encode: return json.dumps(output) else: return output + def get_meta(self): + return { + 'sdk': { + 'version': self.get_sdk_version(), + 'lang': 'python', + 'lang_version': platform.python_version(), + 'platform': platform.system(), + 'platform_version': platform.release() + } + } + + def get_sdk_version(self): + return 'v' + __version__ + def generate_request_string(self): if self.request is None: return "" @@ -220,3 +245,8 @@ def hash_list(self, l): "Hash a list by concatenating values with an underscore" return hashlib.sha256("_".join(l).encode('utf-8')).hexdigest() + def disable_telemetry(self): + self.__telemetry_enabled = False + + def enable_telemetry(self): + self.__telemetry_enabled = True diff --git a/release.sh b/release.sh index 7815856..a6e9593 100755 --- a/release.sh +++ b/release.sh @@ -1,6 +1,6 @@ #!/bin/bash -e -VERSION_FILE="setup.py" +VERSION_FILE="learnosity_sdk/_version.py" CHANGELOG="ChangeLog.md" REQUIREMENTS="requirements.txt" @@ -90,7 +90,7 @@ update_requirements() { update_version () { # update and commit local version file used by tracking telemetry echo -e "\\nWriting version file..." - sed -i "s/^VERSION *=.*/VERSION = '${new_version}'/" ${VERSION_FILE} + sed -i "s/^__version__ *=.*/__version__ = '${new_version}'/" ${VERSION_FILE} echo -e "Updating ${CHANGELOG}..." sed -i "s/^## \[Unreleased]$/&\n\n## [${new_version}] - $(date +%Y-%m-%d)/" "${CHANGELOG}" diff --git a/setup.py b/setup.py index 1063f5b..f1b5bbb 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,12 @@ from pip.req import parse_requirements import setuptools -VERSION = '0.2.1pre' +# Loads __version__ using exec as setup.py can't import its own package +version = {} +version_file = 'learnosity_sdk/_version.py' +exec(open(version_file).read(), { '__builtins__': None }, version) +if '__version__' not in version: + raise Exception('__version__ not found in file %s' % version_file) def test_reqs(): reqs = parse_requirements('requirements-dev.txt', session=False) @@ -17,15 +22,15 @@ def test_reqs(): author='Cera Davies', author_email='cera.davies@learnosity.com', url='https://github.com/Learnosity/learnosity-sdk-python', - version=VERSION, + version=version['__version__'], name='learnosity_sdk', description='Learnosity SDK for Python', packages=setuptools.find_packages(exclude=('tests')), install_requires=[ - 'requests>=2.20', - 'urllib3>1.23', + 'requests>=2.21.0', + 'urllib3>=1.24.3', ], tests_require=test_reqs(), )