Skip to content

Commit

Permalink
Merge pull request #27 from octue/v0.0.9
Browse files Browse the repository at this point in the history
V0.0.9
  • Loading branch information
thclark committed Jun 18, 2020
2 parents 320f41e + 71c3b5e commit 1a68d68
Show file tree
Hide file tree
Showing 31 changed files with 596 additions and 105 deletions.
7 changes: 7 additions & 0 deletions .isort.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[settings]
line_length = 120
multi_line_output = 3
include_trailing_comma = False
known_standard_library = pkg_resources
known_third_party = jsonschema
known_first_party = twined
34 changes: 34 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
exclude: 'build|docs|node_modules|.git|.tox|dist|docs|octue.egg-info|twined.egg-info'
include: 'twined'
default_stages: [commit]
fail_fast: true
default_language_version:
python: python3 # force all unspecified python hooks to run python3
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: master
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
language_version: python3

- repo: https://github.com/pre-commit/mirrors-isort
rev: v4.3.21
hooks:
- id: isort

- repo: https://github.com/psf/black
rev: 19.10b0
hooks:
- id: black
args: ['--line-length', '120']
language_version: python3

- repo: https://gitlab.com/pycqa/flake8
rev: 3.8.1
hooks:
- id: flake8
# args: ['--config=setup.cfg']
additional_dependencies: [flake8-isort]
language_version: python3
1 change: 0 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@ include twined/schema/children_schema.json
include twined/schema/manifest_schema.json
include twined/schema/twine_schema.json
recursive-include twined *
recursive-include docs *
67 changes: 65 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,70 @@
# twined

A library to help digital twins talk to one another. Read more at [twined.readthedocs.io](https://twined.readthedocs.io)
A library to help digital twins and data services talk to one another. Read more at [twined.readthedocs.io](https://twined.readthedocs.io)

[![Build Status](https://travis-ci.com/octue/twined.svg?branch=master)](https://travis-ci.com/octue/twined)
[![codecov](https://codecov.io/gh/octue/twined/branch/master/graph/badge.svg)](https://codecov.io/gh/octue/twined)
[![Documentation Status](https://readthedocs.org/projects/twined/badge/?version=latest)](https://twined.readthedocs.io/en/latest/?badge=latest)

[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)
[![black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)

## Developer notes

**You don't need to pay attention to this unless you plan to develop Twined.**

### Contributing

- Please raise an issue on the board (or add your $0.02 to an existing issue) so the maintainers know
what's happening and can advise / steer you.

- Create a fork of twined, undertake your changes on a new branch (call it whatever you want). To run tests and make commits,
you'll need to do something like:
```
git clone <your_forked_repo_address> # fetches the repo to your local machine
cd twined # move into the repo directory
pyenv virtualenv 3.6.9 twinedenv # Makes a virtual environment for you to install the dev tools into. Use any python >= 3.6
pyend activate twinedenv # Activates the virtual environment so you don't screw up other installations
pip install -r requirements-dev.txt # Installs the testing and code formatting utilities
pre-commit install # Installs the pre-commit code formatting hooks in the git repo
tox # Runs the tests with coverage. NB you can also just set up pycharm or vscode to run these.
```

- If you don't know what TDD is, go away and find out. We practice TDD here and it'll be glaringly obvious if you don't.

- Ask the `twined` maintainers *where* to make your pull request. We'll create a version branch, according to the
roadmap, into which you can make your PR. We'll help review the changes and improve the PR.

- Once checks have passed, test coverage of the new code is >=95%, documentation is updated and the Review is passed, we'll merge into the version branch.

- Once all the roadmapped features for that version are done, we'll release.


### Release process

The process for creating a new release is as follows:

1. Check out a branch for the next version, called `vX.Y.Z`
2. Create a Pull Request into the `master` branch.
3. Undertake your changes, committing and pushing to branch `vX.Y.Z`
4. Ensure that documentation is updated to match changes, and increment the changelog. **Pull requests which do not update documentation will be refused.**
5. Ensure that test coverage is sufficient. **Pull requests that decrease test coverage will be refused.**
6. Ensure code meets style guidelines (pre-commit scripts and flake8 tests will fail otherwise)
7. Address Review Comments on the PR
8. Ensure the version in `setup.py` is correct and matches the branch version.
9. Merge to master. Successful test, doc build, flake8 and a new version number will automatically create the release on pypi.
10. Go to code > releases and create a new release on GitHub at the same SHA.


### Building documents locally

Install `doxgen`. On a mac, that's `brew install doxygen`; other systems may differ.

Install sphinx and other requirements for building the docs:
```
pip install -r docs/requirements.txt
```

Run the build process:
```
sphinx-build -b html docs/source docs/build
```
1 change: 1 addition & 0 deletions docs/source/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,4 @@ copied straight from the unit test cases, so you can always check there to see h
}
}
}
2 changes: 1 addition & 1 deletion docs/source/schema.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ About Twines (Schema)
The core of **twined** is to provide and use schemas for digital twins.

Below, we set out requirements and a framework for creating a *schema* to represent a digital twin.
We call these schema "twines". To just get started building a **twine**, check out the :ref:`_quick_start`.
We call these schema "twines". To just get started building a **twine**, check out the :ref:`quick_start`.


.. _requirements:
Expand Down
12 changes: 12 additions & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

# Testing
# ------------------------------------------------------------------------------
tox
pluggy

# Code quality
# ------------------------------------------------------------------------------
flake8==3.8.3 # https://github.com/PyCQA/flake8
flake8-isort==3.0.0 # https://github.com/gforcada/flake8-isort
black==19.10.b0 # https://github.com/ambv/black
pre-commit # https://github.com/pre-commit/pre-commit
38 changes: 19 additions & 19 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from setuptools import setup, find_packages
from setuptools import find_packages, setup

# Note:
# The Hitchiker's guide to python provides an excellent, standard, method for creating python packages:
Expand All @@ -7,34 +7,34 @@
# To deploy on PYPI follow the instructions at the bottom of:
# https://packaging.python.org/tutorials/distributing-packages/#uploading-your-project-to-pypi

with open('README.md') as f:
with open("README.md") as f:
readme_text = f.read()

with open('LICENSE') as f:
with open("LICENSE") as f:
license_text = f.read()

setup(
name='twined',
version='0.0.8',
name="twined",
version="0.0.9",
py_modules=[],
install_requires=['jsonschema ~= 3.2.0'],
url='https://www.github.com/octue/twined',
install_requires=["jsonschema ~= 3.2.0"],
url="https://www.github.com/octue/twined",
license=license_text,
author='Octue (github: octue)',
description='A library to help digital twins talk to one another.',
author="Octue (github: octue)",
description="A library to help digital twins talk to one another.",
long_description=readme_text,
long_description_content_type="text/markdown",
packages=find_packages(exclude=('tests', 'docs')),
packages=find_packages(exclude=("tests", "docs")),
include_package_data=True,
classifiers=[
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
'Topic :: Software Development :: Libraries :: Python Modules',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Operating System :: OS Independent'
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Topic :: Software Development :: Libraries :: Python Modules",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Operating System :: OS Independent",
],
python_requires='>=3.6',
keywords=['digital', 'twins', 'python', 'schema']
python_requires=">=3.6",
keywords=["digital", "twins", "python", "schema"],
)
2 changes: 1 addition & 1 deletion tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ class BaseTestCase(unittest.TestCase):
"""

def setUp(self):
self.path = str(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data', ''))
self.path = str(os.path.join(os.path.dirname(os.path.abspath(__file__)), "data", ""))
super().setUp()
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"n_iterations": 16
}
}
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
"x_range": [-1.5, 0.6],
"y_range": [-1.26, 1.26],
"type": "png"
}
}
File renamed without changes.
Empty file.
3 changes: 3 additions & 0 deletions tests/data/configurations/incorrect.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"n_iterations": "should not be a string, this field requires an integer"
}
3 changes: 3 additions & 0 deletions tests/data/configurations/valid.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"n_iterations": 1
}
4 changes: 4 additions & 0 deletions tests/data/configurations/valid_with_extra.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"n_iterations": 1,
"another_field": "may or may not be quietly ignored"
}
1 change: 1 addition & 0 deletions tests/data/inputs/missing_required.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
3 changes: 3 additions & 0 deletions tests/data/inputs/valid.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"height": 40
}
1 change: 1 addition & 0 deletions tests/data/outputs/missing_not_required.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
3 changes: 3 additions & 0 deletions tests/data/outputs/valid.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"width": 36
}
3 changes: 3 additions & 0 deletions tests/data/twines/incorrect_version_twine.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"twined_version": "0.0.0"
}
43 changes: 43 additions & 0 deletions tests/data/twines/valid_schema_twine.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"configuration_schema": {
"$schema": "http://json-schema.org/2019-09/schema#",
"title": "The example configuration form",
"description": "The configuration strand of an example twine",
"type": "object",
"properties": {
"n_iterations": {
"description": "An example of an integer configuration variable, called 'n_iterations'.",
"type": "integer",
"minimum": 1,
"maximum": 10,
"default": 5
}
}
},
"input_values_schema": {
"$schema": "http://json-schema.org/2019-09/schema#",
"title": "Input Values",
"description": "The input values strand of an example twine, with a required height value",
"type": "object",
"properties": {
"height": {
"description": "An example of an integer value called 'height'",
"type": "integer",
"minimum": 2
}
},
"required": ["height"]
},
"output_values_schema": {
"title": "Output Values",
"description": "The output values strand of an example twine",
"type": "object",
"properties": {
"width": {
"description": "An example of an integer value called 'result'",
"type": "integer",
"minimum": 2
}
}
}
}
12 changes: 7 additions & 5 deletions tests/test_children.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import unittest

from twined import Twine, exceptions

from .base import BaseTestCase


Expand All @@ -12,24 +14,24 @@ def test_invalid_children_dict_not_array(self):
""" Ensures InvalidTwine exceptions are raised when instantiating twines where `children` entry is incorrectly
specified as a dict, not an array
"""
twine_file = self.path + 'twines/invalid_children_dict_not_array_twine.json'
twine_file = self.path + "twines/invalid_children_dict_not_array_twine.json"
with self.assertRaises(exceptions.InvalidTwine):
Twine(file=twine_file)

def test_invalid_children_no_key(self):
""" Ensures InvalidTwine exceptions are raised when instantiating twines where a child
is specified without the required `key` field
"""
twine_file = self.path + 'twines/invalid_children_no_key_twine.json'
twine_file = self.path + "twines/invalid_children_no_key_twine.json"
with self.assertRaises(exceptions.InvalidTwine):
Twine(file=twine_file)

def test_valid_children(self):
""" Ensures that a twine can be instantiated with correctly specified children
"""
twine_file = self.path + 'twines/valid_children_twine.json'
twine_file = self.path + "twines/valid_children_twine.json"
twine = Twine(file=twine_file)
self.assertEqual(len(twine._raw['children']), 1)
self.assertEqual(len(twine._raw["children"]), 1)


# class TestChildrenValidation(unittest.TestCase):
Expand Down Expand Up @@ -57,5 +59,5 @@ def test_valid_children(self):
# raise exceptions.NotImplementedYet()


if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()
12 changes: 7 additions & 5 deletions tests/test_credentials.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import unittest

from twined import Twine, exceptions

from .base import BaseTestCase


Expand All @@ -12,28 +14,28 @@ def test_fails_on_no_name(self):
""" Ensures InvalidTwine exceptions are raised when instantiating twines
with a missing `name` field in a credential
"""
twine_file = self.path + 'twines/invalid_credentials_no_name_twine.json'
twine_file = self.path + "twines/invalid_credentials_no_name_twine.json"
with self.assertRaises(exceptions.InvalidTwine):
Twine(file=twine_file)

def test_fails_on_lowercase_name(self):
""" Ensures InvalidTwine exceptions are raised when instantiating twines
with lowercase letters in the `name` field
"""
twine_file = self.path + 'twines/invalid_credentials_lowercase_name_twine.json'
twine_file = self.path + "twines/invalid_credentials_lowercase_name_twine.json"
with self.assertRaises(exceptions.InvalidTwine):
Twine(file=twine_file)

def test_fails_on_dict(self):
""" Ensures InvalidTwine exceptions are raised when instantiating twines
with invalid `credentials` entries (given as a dict, not an array)
"""
twine_file = self.path + 'twines/invalid_credentials_dict_not_array_twine.json'
twine_file = self.path + "twines/invalid_credentials_dict_not_array_twine.json"
with self.assertRaises(exceptions.InvalidTwine):
Twine(file=twine_file)

def test_fails_on_name_whitespace(self):
twine_file = self.path + 'twines/invalid_credentials_space_in_name_twine.json'
twine_file = self.path + "twines/invalid_credentials_space_in_name_twine.json"
with self.assertRaises(exceptions.InvalidTwine):
Twine(file=twine_file)

Expand All @@ -59,5 +61,5 @@ def test_fails_on_name_whitespace(self):
# raise exceptions.NotImplementedYet()


if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()

0 comments on commit 1a68d68

Please sign in to comment.