From 7aaed915d6bbf0e414c585a5fd462fb2193f09ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Aguiar?= Date: Fri, 28 Sep 2018 19:47:36 -0300 Subject: [PATCH 01/40] Add Triangle class to __init__.py --- stylo/shape/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stylo/shape/__init__.py b/stylo/shape/__init__.py index 867c0f73..20984c2f 100644 --- a/stylo/shape/__init__.py +++ b/stylo/shape/__init__.py @@ -1,2 +1,2 @@ -from .basic import Rectangle, Square, Ellipse, Circle # noqa: F401 +from .basic import Rectangle, Square, Ellipse, Circle, Triangle # noqa: F401 from .shape import Shape # noqa: F401 From 5fdca9748f4792a8a93239d958d1ffd938d74564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Aguiar?= Date: Fri, 28 Sep 2018 20:11:51 -0300 Subject: [PATCH 02/40] Add Triangle shape to the shape library --- stylo/shape/basic.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/stylo/shape/basic.py b/stylo/shape/basic.py index 1456cd90..34148dec 100644 --- a/stylo/shape/basic.py +++ b/stylo/shape/basic.py @@ -99,3 +99,39 @@ def rectangle(x, y): class Square(Rectangle): def __init__(self, x, y, size): super().__init__(x, y, size, size) + + +class Triangle(Shape): + def __init__(self, a, b, c): + self.a = a + self.b = b + self.c = c + + def draw(self): + + a = self.a + b = self.b + c = self.c + + def triangle(x, y): + q = ( + 1 + / 2 + * ( + -b[1] * c[0] + + a[1] * (-b[0] + c[0]) + + a[0] * (b[1] - c[1]) + + b[0] * c[1] + ) + ) + sign = -1 if q < 0 else 1 + s = ( + a[1] * c[0] - a[0] * c[1] + (c[1] - a[1]) * x + (a[0] - c[0]) * y + ) * sign + t = ( + a[0] * b[1] - a[1] * b[0] + (a[1] - b[1]) * x + (b[0] - a[0]) * y + ) * sign + + return np.logical_and(s > 0, np.logical_and(t > 0, (s + t) < 2 * q * sign)) + + return triangle From d9d36efd30eb04ae2005128a5579bd072dfa0ed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Aguiar?= Date: Fri, 28 Sep 2018 21:40:10 -0300 Subject: [PATCH 03/40] Add docstring for Triangle shape --- stylo/shape/basic.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stylo/shape/basic.py b/stylo/shape/basic.py index 34148dec..3009b20d 100644 --- a/stylo/shape/basic.py +++ b/stylo/shape/basic.py @@ -102,6 +102,9 @@ def __init__(self, x, y, size): class Triangle(Shape): + """ + A Triangle can be defined by picking three non-collinear points :math:`(a, b, c)`. + """ def __init__(self, a, b, c): self.a = a self.b = b From fe90a934daf474ace7301a7ca4c915685faf2ed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Aguiar?= Date: Fri, 28 Sep 2018 22:50:00 -0300 Subject: [PATCH 04/40] Make the docs a little more explicit --- stylo/shape/basic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stylo/shape/basic.py b/stylo/shape/basic.py index 3009b20d..3587a0a6 100644 --- a/stylo/shape/basic.py +++ b/stylo/shape/basic.py @@ -103,7 +103,7 @@ def __init__(self, x, y, size): class Triangle(Shape): """ - A Triangle can be defined by picking three non-collinear points :math:`(a, b, c)`. + A Triangle can be defined by picking three non-collinear points :math:`(a, b, c)` in the form of a tuple each. """ def __init__(self, a, b, c): self.a = a From fa7a046906ea1096d998833bd90e0ab265b39c24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Aguiar?= Date: Fri, 28 Sep 2018 22:51:16 -0300 Subject: [PATCH 05/40] Add black to Pipfile --- Pipfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Pipfile b/Pipfile index 15faaae0..fdac03dc 100644 --- a/Pipfile +++ b/Pipfile @@ -15,6 +15,7 @@ pytest-benchmark = "*" tox = "*" pre-commit = "*" jupyter = "*" +black = "*" [scripts] test = "tox -q -e py36,py37 -- -n auto" From 620b3ec26b171672dd2107fa5157a217d7758653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Aguiar?= Date: Fri, 28 Sep 2018 22:54:01 -0300 Subject: [PATCH 06/40] black code style --- stylo/shape/basic.py | 1 + 1 file changed, 1 insertion(+) diff --git a/stylo/shape/basic.py b/stylo/shape/basic.py index 3587a0a6..f2c50669 100644 --- a/stylo/shape/basic.py +++ b/stylo/shape/basic.py @@ -105,6 +105,7 @@ class Triangle(Shape): """ A Triangle can be defined by picking three non-collinear points :math:`(a, b, c)` in the form of a tuple each. """ + def __init__(self, a, b, c): self.a = a self.b = b From 7ac463332d8f2d2130577a9ddc6d42e2afb8e664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Aguiar?= Date: Sat, 29 Sep 2018 00:07:12 -0300 Subject: [PATCH 07/40] Style the docstring --- stylo/shape/basic.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stylo/shape/basic.py b/stylo/shape/basic.py index f2c50669..19dd8daf 100644 --- a/stylo/shape/basic.py +++ b/stylo/shape/basic.py @@ -103,7 +103,8 @@ def __init__(self, x, y, size): class Triangle(Shape): """ - A Triangle can be defined by picking three non-collinear points :math:`(a, b, c)` in the form of a tuple each. + A Triangle can be defined by picking three non-collinear points + :math:`(a, b, c)` in the form of a tuple each. """ def __init__(self, a, b, c): From 39f44c926eb16f2cd57fa344318bce652b158a3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Aguiar=20Figueiredo?= Date: Sat, 29 Sep 2018 16:22:57 -0300 Subject: [PATCH 08/40] Add Triangle to shape tests --- tests/shape/test_basic.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/shape/test_basic.py b/tests/shape/test_basic.py index 7f77d148..9f21c140 100644 --- a/tests/shape/test_basic.py +++ b/tests/shape/test_basic.py @@ -1,7 +1,7 @@ import pytest from unittest import TestCase -from stylo.shape import Ellipse, Circle, Rectangle, Square +from stylo.shape import Ellipse, Circle, Rectangle, Square, Triangle from stylo.testing.shape import BaseShapeTest @@ -35,3 +35,10 @@ class TestSquare(TestCase, BaseShapeTest): def setUp(self): self.shape = Square(0, 0, 0.75) + +@pytest.mark.shape +class TestTriangle(TestCase, BaseShapeTest): + """Tests for the :code:`Triangle` shape.""" + + def setUp(self): + self.shape = Triangle((1,.5),(.2,1),(.4,.5)) From d1fdd66112889860adf1e6533aea26fd823445b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Aguiar=20Figueiredo?= Date: Sat, 29 Sep 2018 16:23:54 -0300 Subject: [PATCH 09/40] Refactor draw function --- stylo/shape/basic.py | 56 ++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/stylo/shape/basic.py b/stylo/shape/basic.py index 19dd8daf..3867175e 100644 --- a/stylo/shape/basic.py +++ b/stylo/shape/basic.py @@ -112,31 +112,47 @@ def __init__(self, a, b, c): self.b = b self.c = c - def draw(self): - + def get_q(self): a = self.a b = self.b c = self.c + q = ( + 1 + / 2 + * ( + -b[1] * c[0] + + a[1] * (-b[0] + c[0]) + + a[0] * (b[1] - c[1]) + + b[0] * c[1] + ) + ) + return q + + def get_s(self, x, y): + a = self.a + c = self.c + sign = -1 if self.get_q() < 0 else 1 + s = (a[1] * c[0] - a[0] * c[1] + (c[1] - a[1]) * x + (a[0] - c[0]) * y) * sign + return s + def get_t(self, x, y): + a = self.a + b = self.b + sign = -1 if self.get_q() < 0 else 1 + t = (a[0] * b[1] - a[1] * b[0] + (a[1] - b[1]) * x + (b[0] - a[0]) * y) * sign + return t + + def draw(self): def triangle(x, y): - q = ( - 1 - / 2 - * ( - -b[1] * c[0] - + a[1] * (-b[0] + c[0]) - + a[0] * (b[1] - c[1]) - + b[0] * c[1] - ) + sign = -1 if self.get_q() < 0 else 1 + first_condition = self.get_s(x, y) > 0 + second_condition = self.get_t(x, y) > 0 + third_condition = ( + self.get_s(x, y) + self.get_t(x, y) < 2 * self.get_q() * sign + ) + + return np.logical_and( + first_condition, np.logical_and(second_condition, third_condition) ) - sign = -1 if q < 0 else 1 - s = ( - a[1] * c[0] - a[0] * c[1] + (c[1] - a[1]) * x + (a[0] - c[0]) * y - ) * sign - t = ( - a[0] * b[1] - a[1] * b[0] + (a[1] - b[1]) * x + (b[0] - a[0]) * y - ) * sign - - return np.logical_and(s > 0, np.logical_and(t > 0, (s + t) < 2 * q * sign)) return triangle From 7050bb6e0d5694cfff5109bda61eab4be1470aac Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Sun, 30 Sep 2018 17:11:05 +0100 Subject: [PATCH 10/40] Add the ability to invert shapes - Added a new shape :code:`InvertedShape` which given any shape will return the inverse of that shape by calling :code:`np.logical_not` on the given shape's mask. - Gave all the composite shapes a proper :code:`__repr__` method so that you can (hopefully) easily see the combination of the various logical operators. --- stylo/shape/shape.py | 48 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/stylo/shape/shape.py b/stylo/shape/shape.py index f12575b9..875bba36 100644 --- a/stylo/shape/shape.py +++ b/stylo/shape/shape.py @@ -1,5 +1,6 @@ import numpy as np from abc import ABC, abstractmethod +from textwrap import indent from stylo.domain import RealDomain from stylo.utils import get_parameters @@ -14,6 +15,9 @@ def __new__(cls, *args, **kwargs): return instance + def __invert__(self): + return InvertedShape(self) + def __and__(self, other): return self._logical_op(ANDedShape, other) @@ -78,15 +82,43 @@ def draw(self): pass -def composite_shape_factory(op, name): +class InvertedShape(Shape): + """A shape that has been inverted.""" + + def __init__(self, shape): + self.shape = shape + + def __repr__(self): + return "NOT [ " + repr(self.shape) + " ]" + + def _render_domain(self, *args): + mask = self.shape._render_domain(*args) + return np.logical_not(mask) + + def _render_args(self, **kwargs): + mask = self.shape._render_args(**kwargs) + return np.logical_not(mask) + + def draw(self): + pass + + @property + def parameters(self): + return self.shape.parameters + + +def composite_shape_factory(op, name, op_name): """A factory function that returns class definitions for composite shapes - constructed using logical operations such as AND, OR, etc. + constructed using binary logical operations such as AND, OR, etc. :param op: The function that implements the operation in question :param name: The name to give the composite class. + :param op_name: The name of the logical operation, this will be used in the objcet's + __repr__ :type op: callable :type name: str + :type op_name: str :rtype: class """ @@ -98,6 +130,12 @@ def __init__(self, a, b): self.a = a self.b = b + def __repr__(self): + a_repr = indent("-- " + repr(self.a), "| ") + b_repr = indent("-- " + repr(self.b), "| ") + + return "\n".join([op_name, a_repr, b_repr]) + def _render_domain(self, *args): a = self.a._render_domain(*args) b = self.b._render_domain(*args) @@ -131,6 +169,6 @@ def draw(self): return CompositeShape -ANDedShape = composite_shape_factory(np.logical_and, "ANDedShape") -ORedShape = composite_shape_factory(np.logical_or, "ORedShape") -XORedShape = composite_shape_factory(np.logical_xor, "XORedShape") +ANDedShape = composite_shape_factory(np.logical_and, "ANDedShape", "AND") +ORedShape = composite_shape_factory(np.logical_or, "ORedShape", "OR") +XORedShape = composite_shape_factory(np.logical_xor, "XORedShape", "XOR") From f69f3eff78d86d660f019c934ac53815db4b2a22 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Sun, 30 Sep 2018 17:22:26 +0100 Subject: [PATCH 11/40] Adding __repr__ to each of the basic shapes - Each of the basic shapes now define a :code:`__repr__` method --- stylo/shape/basic.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/stylo/shape/basic.py b/stylo/shape/basic.py index 1456cd90..93964f27 100644 --- a/stylo/shape/basic.py +++ b/stylo/shape/basic.py @@ -31,6 +31,9 @@ def __init__(self, x, y, a, b, r): self.b = b self.r = r + def __repr__(self): + return "Ellipse(x={0.x}, y={0.y}, a={0.a}, b={0.b}, r={0.r})".format(self) + def draw(self): r = self.r * self.r @@ -65,6 +68,9 @@ class Circle(Ellipse): def __init__(self, x, y, r): super().__init__(x, y, 1, 1, r) + def __repr__(self): + return "Circle(x={0.x},y={0.y},r={0.r})".format(self) + class Rectangle(Shape): """ @@ -80,6 +86,10 @@ def __init__(self, x, y, width, height): self.width = width self.height = height + def __repr__(self): + arg_string = "x={0.x},y={0.y},width={0.width},height={0.height}".format(self) + return "Rectangle({})".format(arg_string) + def draw(self): left = self.x - (self.width / 2) @@ -99,3 +109,6 @@ def rectangle(x, y): class Square(Rectangle): def __init__(self, x, y, size): super().__init__(x, y, size, size) + + def __repr__(self): + return "Sqaure(x={0.x},y={0.y},size={0.width})".format(self) From 37f69326b6eb4fa82ea7fd064ca3b778c91ec684 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Sun, 30 Sep 2018 17:30:51 +0100 Subject: [PATCH 12/40] Update changelog --- CHANGES.rst | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index cd161b55..1283c072 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,31 @@ +v0.5.1 [Unreleased] +------------------- + +Added +^^^^^ + +Users +""""" + +- Shapes can now be inverted using the :code:`~` operator. + +Contributors +"""""""""""" + +- Added new shape :code:`InvertedShape` which handles the inversion of a shape behind + the scenes. + +Changed +^^^^^^^ + +Users +""""" + +- Shapes now have defined :code:`__repr__` methods, including shapes that have been + combined, where a representation of a tree will be produced showing how the various + shapes have been combined together. + + v0.5.0 2018-09-27 ----------------- @@ -27,6 +55,7 @@ Contributors interval :math:`[ymin, ymax]` - We now make use of the :code:`[scripts]` section of :code:`Pipfile` so running common commands is now easier to remember + + :code:`pipenv run test`: to run the test suite + :code:`pipenv run lint`: to lint the codebase + :code:`pipenv run docs`: to run a full build of the documentation From a2fe80e2444ac58851e3bcca5e920ddc47417d5f Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Sun, 30 Sep 2018 20:08:09 +0100 Subject: [PATCH 13/40] Add tests for composite shapes There are now tests for the :code:`ANDedShape`, :code:`XORedShape`, :code:`ORedShape` and :code:`InvertedShape` classes. As well as tests to verify that a shape has provided implementations of the :code:`~`, :code:`&`, :code:`|` and :code:`^` operators --- stylo/testing/shape.py | 44 ++++++++- tests/shape/test_shape.py | 189 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 tests/shape/test_shape.py diff --git a/stylo/testing/shape.py b/stylo/testing/shape.py index cca4f089..2136fd47 100644 --- a/stylo/testing/shape.py +++ b/stylo/testing/shape.py @@ -2,6 +2,7 @@ from hypothesis import given from stylo.domain import UnitSquare, RealDomain +from stylo.shape.shape import InvertedShape, ANDedShape, ORedShape, XORedShape from stylo.testing.strategies import dimension from stylo.utils import get_parameters @@ -55,7 +56,7 @@ def test_render_with_domain(self, width, height): @given(width=dimension, height=dimension) def test_render_with_args(self, width, height): """Ensure that a shape can be called with keyword arguments. Each of the - arguments should be numpy arrays of the same shape with names corresponding to + arguments should be numpy arrays of the same shape with names corresponding to each of the coordinate names the shape is defined with. The result must: - Be a numpy array @@ -74,6 +75,47 @@ def test_render_with_args(self, width, height): self.assertEqual((height, width), mask.shape) self.assertTrue(mask.dtype == np.bool, "Expected boolean array.") + def test_shape_can_be_inverted(self): + """Ensure that a shape can be inverted by checking that an instance of + :code:`InvertedShape` is returned when the :code:`~` operator is used on the + shape. + """ + + inverted_shape = ~self.shape + + assert isinstance(inverted_shape, (InvertedShape,)), "Expected inverted shape." + assert inverted_shape.shape == self.shape + + def test_shape_can_be_anded(self): + """Ensure that a shape can be ANDed by checking that an instance of + :code:`ANDedShape` is returned when the :code:`&` operator is used.""" + + anded_shape = self.shape & self.shape + + assert isinstance(anded_shape, (ANDedShape,)), "Expected anded shape" + assert anded_shape.a == self.shape + assert anded_shape.b == self.shape + + def test_shape_can_be_ored(self): + """Ensure that a shape can be ored by checking that an instance of + :code:`ORedShape` is returned when the :code:`|` operator is used.""" + + ored_shape = self.shape | self.shape + + assert isinstance(ored_shape, (ORedShape,)), "Expected ored shape" + assert ored_shape.a == self.shape + assert ored_shape.b == self.shape + + def test_shape_can_be_xored(self): + """Ensure that a shape can be xored by checking that an instance of + :code:`XORedShape` is returned when the :code:`^` operator is used.""" + + xored_shape = self.shape ^ self.shape + + assert isinstance(xored_shape, (XORedShape,)), "Expected xored shape" + assert xored_shape.a == self.shape + assert xored_shape.b == self.shape + def test_parameters_property(self): """Ensure that the :code:`parameters` property returns the coordinates that the shape is defined with. The parameters must diff --git a/tests/shape/test_shape.py b/tests/shape/test_shape.py new file mode 100644 index 00000000..e49f530c --- /dev/null +++ b/tests/shape/test_shape.py @@ -0,0 +1,189 @@ +import pytest +import numpy as np +from unittest import TestCase +from hypothesis import given + +from stylo.domain import UnitSquare +from stylo.shape import Circle, Shape +from stylo.shape.shape import InvertedShape, ANDedShape, ORedShape, XORedShape +from stylo.testing.strategies import dimension +from stylo.testing.shape import BaseShapeTest + + +class MyShape(Shape): + """A shape that depends on something other than x and y. This should be replaced + with a shape from the library when such a shape is available. + """ + + def draw(self): + return lambda r, t: r < t + + +@pytest.mark.shape +class TestInvertedShape(TestCase, BaseShapeTest): + """Tests for the :code:`InvertedShape` class.""" + + def setUp(self): + self.baseshape = Circle(0, 0, 0.8) + self.shape = InvertedShape(self.baseshape) + + self.domain = UnitSquare() + + def test_exposes_parameters(self): + """Ensure that the :code:`InvertedShape` class exposes the parameters defined + by the underlying shape. + """ + assert self.shape.parameters == self.baseshape.parameters + + @given(width=dimension, height=dimension) + def test_shape_is_inverted(self, width, height): + """Ensure that an :code:`InvertedShape` is inverted by checking that a shape + anded with its inversion should be False everywhere. + """ + + mask = self.baseshape(self.domain, width, height) + inverted_mask = self.shape(self.domain, width, height) + + assert (np.logical_and(mask, inverted_mask) == False).all() + + @given(width=dimension, height=dimension) + def test_double_inversion(self, width, height): + """Ensure that an inverted :code:`InvertedShape` is the same as the shape + itself. + """ + + double_inversion = InvertedShape(self.shape) + + mask = self.baseshape(self.domain, width, height) + inverted_mask = double_inversion(self.domain, width, height) + + assert (mask == inverted_mask).all() + + def test_draw_method(self): + """Rightly or wrongly, :code:`InvertedShape` currently doesn't make use of the + draw method. So we'll override and disable this test from the base class.""" + pass + + +@pytest.mark.shape +class TestANDedShape(TestCase, BaseShapeTest): + """Tests for the :code:`ANDedShape` class.""" + + def setUp(self): + self.a = Circle(0, 0, 0.8) + self.not_a = InvertedShape(self.a) + self.b = MyShape() + + self.shape = ANDedShape(self.a, self.not_a) + self.domain = UnitSquare() + + def test_exposes_parameters(self): + """Ensure that the parameters needed to define both a and b are exposed.""" + + composite = ANDedShape(self.a, self.b) + + for p in self.a.parameters: + assert p in composite.parameters, "Expected parameter: {}".format(p) + + for p in self.b.parameters: + assert p in composite.parameters, "Expected parameter: {}".format(p) + + @given(width=dimension, height=dimension) + def test_shapes_are_anded(self, width, height): + """Ensure that the shapes are anded together. This is done by checking that the + circle and its inversion results in False everywhere.""" + + mask = self.shape(self.domain, width, height) + + assert (mask == False).all() + + def test_draw_method(self): + """Rightly or wrongly, :code:`ANDedShape` currently doesn't make use of the + draw method. So we'll override and disable this test from the base class.""" + pass + + +@pytest.mark.shape +class TestANDedShape(TestCase, BaseShapeTest): + """Tests for the :code:`ORedShape` class.""" + + def setUp(self): + self.a = Circle(0, 0, 0.8) + self.not_a = InvertedShape(self.a) + self.b = MyShape() + + self.shape = ORedShape(self.a, self.not_a) + self.domain = UnitSquare() + + def test_exposes_parameters(self): + """Ensure that the parameters needed to define both a and b are exposed.""" + + composite = ORedShape(self.a, self.b) + + for p in self.a.parameters: + assert p in composite.parameters, "Expected parameter: {}".format(p) + + for p in self.b.parameters: + assert p in composite.parameters, "Expected parameter: {}".format(p) + + @given(width=dimension, height=dimension) + def test_shapes_are_ored(self, width, height): + """Ensure that the shapes are ored together. This is done by checking that the + circle and its inversion results in True everywhere.""" + + mask = self.shape(self.domain, width, height) + + assert mask.all() + + def test_draw_method(self): + """Rightly or wrongly, :code:`ORedShape` currently doesn't make use of the + draw method. So we'll override and disable this test from the base class.""" + pass + + +@pytest.mark.shape +class TestANDedShape(TestCase, BaseShapeTest): + """Tests for the :code:`XORedShape` class.""" + + def setUp(self): + self.a = Circle(0, 0, 0.8) + self.not_a = InvertedShape(self.a) + self.b = MyShape() + + self.shape = XORedShape(self.a, self.not_a) + self.domain = UnitSquare() + + def test_exposes_parameters(self): + """Ensure that the parameters needed to define both a and b are exposed.""" + + composite = XORedShape(self.a, self.b) + + for p in self.a.parameters: + assert p in composite.parameters, "Expected parameter: {}".format(p) + + for p in self.b.parameters: + assert p in composite.parameters, "Expected parameter: {}".format(p) + + @given(width=dimension, height=dimension) + def test_shapes_are_xored(self, width, height): + """Ensure that the shapes are xored together. This is done by checking that the + circle and its inversion results in True everywhere.""" + + mask = self.shape(self.domain, width, height) + + assert mask.all() + + @given(width=dimension, height=dimension) + def test_shapes_are_xored_part2(self, width, height): + """Ensure that the shapes are xored together. This is done by checking that the + circle and itself results in False everywhere.""" + + composite = XORedShape(self.a, self.a) + mask = composite(self.domain, width, height) + + assert (mask == False).all() + + def test_draw_method(self): + """Rightly xor wrongly, :code:`XORedShape` currently doesn't make use of the + draw method. So we'll override and disable this test from the base class.""" + pass From 24c28a58a8f2a38bbf5e8fc7708e61d81923b1f2 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Sun, 30 Sep 2018 20:12:09 +0100 Subject: [PATCH 14/40] Update changelog --- CHANGES.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 1283c072..5baf4778 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -12,8 +12,9 @@ Users Contributors """""""""""" -- Added new shape :code:`InvertedShape` which handles the inversion of a shape behind - the scenes. +- Added new shape :code:`InvertedShape` which handles the inversion of a shape + behind the scenes. +- Tests for all the composite shapes and operators. Changed ^^^^^^^ @@ -21,9 +22,9 @@ Changed Users """"" -- Shapes now have defined :code:`__repr__` methods, including shapes that have been - combined, where a representation of a tree will be produced showing how the various - shapes have been combined together. +- Shapes now have defined :code:`__repr__` methods, including shapes that have + been combined, where a representation of a tree will be produced showing how + the various shapes have been combined together. v0.5.0 2018-09-27 From bc1d47282bc0d687502622d6be33c67914540238 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Mon, 1 Oct 2018 17:50:12 +0100 Subject: [PATCH 15/40] Fix lint errors and hypothesis warnings --- stylo/testing/strategies.py | 2 +- tests/shape/test_shape.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/stylo/testing/strategies.py b/stylo/testing/strategies.py index 4749df58..08d75229 100644 --- a/stylo/testing/strategies.py +++ b/stylo/testing/strategies.py @@ -16,7 +16,7 @@ real = floats(min_value=-1e6, max_value=1e6) angle = floats(min_value=-pi, max_value=pi) dimension = integers(min_value=4, max_value=1024) -small_dimension = integers(min_value=4, max_value=256) +small_dimension = integers(min_value=4, max_value=128) image_size = tuples(small_dimension, small_dimension) # Stylo data diff --git a/tests/shape/test_shape.py b/tests/shape/test_shape.py index e49f530c..5eed54b3 100644 --- a/tests/shape/test_shape.py +++ b/tests/shape/test_shape.py @@ -44,7 +44,7 @@ def test_shape_is_inverted(self, width, height): mask = self.baseshape(self.domain, width, height) inverted_mask = self.shape(self.domain, width, height) - assert (np.logical_and(mask, inverted_mask) == False).all() + assert np.logical_not(np.logical_and(mask, inverted_mask)).all() @given(width=dimension, height=dimension) def test_double_inversion(self, width, height): @@ -95,7 +95,7 @@ def test_shapes_are_anded(self, width, height): mask = self.shape(self.domain, width, height) - assert (mask == False).all() + assert np.logical_not(mask).all() def test_draw_method(self): """Rightly or wrongly, :code:`ANDedShape` currently doesn't make use of the @@ -104,7 +104,7 @@ def test_draw_method(self): @pytest.mark.shape -class TestANDedShape(TestCase, BaseShapeTest): +class TestORedShape(TestCase, BaseShapeTest): """Tests for the :code:`ORedShape` class.""" def setUp(self): @@ -142,7 +142,7 @@ def test_draw_method(self): @pytest.mark.shape -class TestANDedShape(TestCase, BaseShapeTest): +class TestXORedShape(TestCase, BaseShapeTest): """Tests for the :code:`XORedShape` class.""" def setUp(self): @@ -181,7 +181,7 @@ def test_shapes_are_xored_part2(self, width, height): composite = XORedShape(self.a, self.a) mask = composite(self.domain, width, height) - assert (mask == False).all() + assert np.logical_not(mask).all() def test_draw_method(self): """Rightly xor wrongly, :code:`XORedShape` currently doesn't make use of the From c32fabaabfce536d4f7a36faa7f280f2493a9274 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Aguiar=20Figueiredo?= Date: Wed, 3 Oct 2018 22:32:54 -0300 Subject: [PATCH 16/40] Refactor third condition and docstring --- stylo/shape/basic.py | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/stylo/shape/basic.py b/stylo/shape/basic.py index 3867175e..e29a0c60 100644 --- a/stylo/shape/basic.py +++ b/stylo/shape/basic.py @@ -105,6 +105,10 @@ class Triangle(Shape): """ A Triangle can be defined by picking three non-collinear points :math:`(a, b, c)` in the form of a tuple each. + Points inside the triangle are determined using the + barycentric coordinate system method, which is further explained + `here` and the first method + `here`. """ def __init__(self, a, b, c): @@ -116,16 +120,8 @@ def get_q(self): a = self.a b = self.b c = self.c - q = ( - 1 - / 2 - * ( - -b[1] * c[0] - + a[1] * (-b[0] + c[0]) - + a[0] * (b[1] - c[1]) - + b[0] * c[1] - ) - ) + q = -b[1] * c[0] + a[1] * (-b[0] + c[0]) + a[0] * (b[1] - c[1]) + b[0] * c[1] + return q def get_s(self, x, y): @@ -147,9 +143,7 @@ def triangle(x, y): sign = -1 if self.get_q() < 0 else 1 first_condition = self.get_s(x, y) > 0 second_condition = self.get_t(x, y) > 0 - third_condition = ( - self.get_s(x, y) + self.get_t(x, y) < 2 * self.get_q() * sign - ) + third_condition = self.get_s(x, y) + self.get_t(x, y) < self.get_q() * sign return np.logical_and( first_condition, np.logical_and(second_condition, third_condition) From 078cba26150e80f48847f41804336fbca5e8b7fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Aguiar=20Figueiredo?= Date: Wed, 3 Oct 2018 23:08:17 -0300 Subject: [PATCH 17/40] Lintering file --- tests/shape/test_basic.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/shape/test_basic.py b/tests/shape/test_basic.py index 9f21c140..ce1a4019 100644 --- a/tests/shape/test_basic.py +++ b/tests/shape/test_basic.py @@ -36,9 +36,10 @@ class TestSquare(TestCase, BaseShapeTest): def setUp(self): self.shape = Square(0, 0, 0.75) + @pytest.mark.shape class TestTriangle(TestCase, BaseShapeTest): """Tests for the :code:`Triangle` shape.""" def setUp(self): - self.shape = Triangle((1,.5),(.2,1),(.4,.5)) + self.shape = Triangle((1, 0.5), (0.2, 1), (0.4, 0.5)) From 17907471cc024c065a133f0f3752451947315b56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Aguiar=20Figueiredo?= Date: Wed, 3 Oct 2018 23:38:29 -0300 Subject: [PATCH 18/40] Better documentation for each method --- stylo/shape/basic.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/stylo/shape/basic.py b/stylo/shape/basic.py index e29a0c60..0ffbbcee 100644 --- a/stylo/shape/basic.py +++ b/stylo/shape/basic.py @@ -107,8 +107,8 @@ class Triangle(Shape): :math:`(a, b, c)` in the form of a tuple each. Points inside the triangle are determined using the barycentric coordinate system method, which is further explained - `here` and the first method - `here`. + `in this answer `_ + and the first method `here `_. """ def __init__(self, a, b, c): @@ -117,6 +117,11 @@ def __init__(self, a, b, c): self.c = c def get_q(self): + """ + Returns the denominator for calculating both the barycentric + coordinates, which absolute value is the double of the area + of the triangle. + """ a = self.a b = self.b c = self.c @@ -125,6 +130,10 @@ def get_q(self): return q def get_s(self, x, y): + """ + Returns one of the barycentric coordinates of the triangle using both + :math:`a` and :math:`c` points. + """ a = self.a c = self.c sign = -1 if self.get_q() < 0 else 1 @@ -132,6 +141,10 @@ def get_s(self, x, y): return s def get_t(self, x, y): + """ + Returns one of the barycentric coordinates of the triangle using both + :math:`a` and :math:`b` points. + """ a = self.a b = self.b sign = -1 if self.get_q() < 0 else 1 From 1f3e5f72cabd03dc38eaf388829fde8acf33c91c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Aguiar=20Figueiredo?= Date: Thu, 4 Oct 2018 00:15:01 -0300 Subject: [PATCH 19/40] Add noqa E501 to display long url --- stylo/shape/basic.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stylo/shape/basic.py b/stylo/shape/basic.py index 0ffbbcee..2dda8c42 100644 --- a/stylo/shape/basic.py +++ b/stylo/shape/basic.py @@ -108,8 +108,9 @@ class Triangle(Shape): Points inside the triangle are determined using the barycentric coordinate system method, which is further explained `in this answer `_ - and the first method `here `_. - """ + and the first method + `here `_. + """ # noqa E501 def __init__(self, a, b, c): self.a = a From 5b1fe15363dba0f0c942a9ce48cc91ccb9394471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Aguiar=20Figueiredo?= Date: Thu, 4 Oct 2018 00:48:17 -0300 Subject: [PATCH 20/40] Add __repr__ for Triangle shape --- stylo/shape/basic.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stylo/shape/basic.py b/stylo/shape/basic.py index 2dda8c42..d9dcfd18 100644 --- a/stylo/shape/basic.py +++ b/stylo/shape/basic.py @@ -117,6 +117,9 @@ def __init__(self, a, b, c): self.b = b self.c = c + def __repr__(self): + return "Triangle(a={0.a}, b={0.b}, c={0.c})".format(self) + def get_q(self): """ Returns the denominator for calculating both the barycentric From 3d9d8f785aa9fc7c8668fb4b8ea3623739260f96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Aguiar=20Figueiredo?= Date: Thu, 4 Oct 2018 00:51:30 -0300 Subject: [PATCH 21/40] Black the file --- stylo/shape/basic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stylo/shape/basic.py b/stylo/shape/basic.py index d9dcfd18..53545883 100644 --- a/stylo/shape/basic.py +++ b/stylo/shape/basic.py @@ -110,7 +110,7 @@ class Triangle(Shape): `in this answer `_ and the first method `here `_. - """ # noqa E501 + """ # noqa E501 def __init__(self, a, b, c): self.a = a From 038fd3f31fd5ea90865c0457827fbf007d5f9b31 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Thu, 4 Oct 2018 19:38:57 +0100 Subject: [PATCH 22/40] Update changelog --- CHANGES.rst | 1 + stylo/shape/shape.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 5baf4778..6e134a97 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -7,6 +7,7 @@ Added Users """"" +- New :code:`Triangle` shape - Shapes can now be inverted using the :code:`~` operator. Contributors diff --git a/stylo/shape/shape.py b/stylo/shape/shape.py index 875bba36..1b3fe2ea 100644 --- a/stylo/shape/shape.py +++ b/stylo/shape/shape.py @@ -113,7 +113,7 @@ def composite_shape_factory(op, name, op_name): :param op: The function that implements the operation in question :param name: The name to give the composite class. - :param op_name: The name of the logical operation, this will be used in the objcet's + :param op_name: The name of the logical operation, this will be used in the object's __repr__ :type op: callable From 66aceb8e71bfbbe487222e78518cef1054fc845c Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Thu, 4 Oct 2018 19:24:34 +0100 Subject: [PATCH 23/40] Make preview images bigger by default --- CHANGES.rst | 1 + stylo/image/image.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 6e134a97..eba4ee83 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -26,6 +26,7 @@ Users - Shapes now have defined :code:`__repr__` methods, including shapes that have been combined, where a representation of a tree will be produced showing how the various shapes have been combined together. +- Preview images in Jupyter notebooks are now larger by default v0.5.0 2018-09-27 diff --git a/stylo/image/image.py b/stylo/image/image.py index b71711d4..4ccb0b43 100644 --- a/stylo/image/image.py +++ b/stylo/image/image.py @@ -25,7 +25,7 @@ def __call__(self, width, height, filename=None, plot_size=None): return if plot_size is None: - plot_size = 4 + plot_size = 12 fig, ax = plt.subplots(1, figsize=(plot_size, plot_size)) ax.imshow(image) From 66694a789e21697624c62fc591016b2eeb563b56 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Mon, 1 Oct 2018 19:07:54 +0100 Subject: [PATCH 24/40] Updating the README - Add an example image - why would people want to use stylo? - Link to the documentation - At least mention the fact we are open to contributions! --- CHANGES.rst | 4 +-- README.rst | 60 ++++++++++++++++++++++++++++++++++++------ docs/index.rst | 3 +++ stylo/testing/shape.py | 2 +- 4 files changed, 58 insertions(+), 11 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index eba4ee83..de1ea3fc 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -29,8 +29,8 @@ Users - Preview images in Jupyter notebooks are now larger by default -v0.5.0 2018-09-27 ------------------ +v0.5.0 - 2018-09-27 +------------------- Added ^^^^^ diff --git a/README.rst b/README.rst index 5872427d..68d5a897 100644 --- a/README.rst +++ b/README.rst @@ -35,20 +35,64 @@ About :alt: Join the chat at https://gitter.im/stylo-py/Lobby :target: https://gitter.im/stylo-py/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge -**DISCLAIMER!: Stylo is still in its early stages, many of the core -concepts are yet to be decided on. The interface can change without warning and -features may be added or removed without warning!** +**Stylo is in early development, while it is useable we cannot make any +stability guarantees.** + +Stylo is a Python library that allows you to create images and animations +powered by your imagination and a little mathematics. While mathematics is very +much at the core you do not have to be a mathematician to use it! + +For example here is an eye, drawn with just a few lines of python + +.. image:: /_static/examples/readme-eye.png + :width: 75% + :align: center + +.. testcode:: readme-eye + + from stylo.image import LayeredImage + from stylo.color import FillColor + from stylo.shape import Circle + + outer_eye = Circle(0, 0.5, 1) & Circle(0, -0.5, 1) + inner_eye = Circle(0, 0.5, .9) & Circle(0, -0.5, 0.9) + eye = outer_eye & ~inner_eye + + iris = Circle(0, 0, 0.4) + pupil = Circle(0, 0, 0.15) + + blue = FillColor("0000ff") + black = FillColor("000000") + + image = LayeredImage(scale=1.5) + + image.add_layer(iris, blue) + image.add_layer(pupil, black) + image.add_layer(eye, black) + + image(1920, 1080, filename="docs/_static/examples/readme-eye.png") -Stylo is library that provides a number of tools that aim to make the process of creating -images and animations using nothing but some code and some mathematics possible. Since my -drawing abilities are very limited I created stylo as a way of me trying to close the gap -between my imagination and my artistic ability. Installation ^^^^^^^^^^^^ -Stylo is available on PyPi and can easily be installed using Pip: +Stylo is available for Python 3.5+ and can be installed using Pip: .. code:: $ pip install stylo + +Be sure to check out the `documentation `_ +(under construction) for details on how to get started with stylo. + +Contributing +^^^^^^^^^^^^ + +Contributions are welcome! Be sure to checkout the `Contributing +`_ section of the documentation +to get started. + +**Note:** While :code:`stylo` itself supports Python 3.5+, due to some of the +development tools we use you need to have Python 3.6+ in order to contribute +**code** to the library. Other versions of Python work just as well if you are +looking to contribute documentation. diff --git a/docs/index.rst b/docs/index.rst index 4a767080..9e18ff05 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -4,6 +4,9 @@ Be sure to check out the :ref:`about_docs` page for a guide on how to get the most of the documentation! +Contents +^^^^^^^^ + .. toctree:: :maxdepth: 2 diff --git a/stylo/testing/shape.py b/stylo/testing/shape.py index 2136fd47..eeaba439 100644 --- a/stylo/testing/shape.py +++ b/stylo/testing/shape.py @@ -56,7 +56,7 @@ def test_render_with_domain(self, width, height): @given(width=dimension, height=dimension) def test_render_with_args(self, width, height): """Ensure that a shape can be called with keyword arguments. Each of the - arguments should be numpy arrays of the same shape with names corresponding to + arguments should be numpy arrays of the same shape with names corresponding to each of the coordinate names the shape is defined with. The result must: - Be a numpy array From 8ffca15e484d8ca49404e2eb4c12359a9a076c5f Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Mon, 1 Oct 2018 20:54:34 +0100 Subject: [PATCH 25/40] Hacky way to have the image in both README and docs --- README.rst | 6 +++++- docs/index.rst | 28 ++++++++++++++++++++++++++++ tox.ini | 12 ++++++------ 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/README.rst b/README.rst index 68d5a897..669f3c6e 100644 --- a/README.rst +++ b/README.rst @@ -48,7 +48,11 @@ For example here is an eye, drawn with just a few lines of python :width: 75% :align: center -.. testcode:: readme-eye +.. image:: img/readme-eye.png + :width: 75% + :align: center + +.. code-block:: python from stylo.image import LayeredImage from stylo.color import FillColor diff --git a/docs/index.rst b/docs/index.rst index 9e18ff05..9eeaeef7 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,9 +1,37 @@ +.. The code below won't show up on the page, but it will be run as part of the doctests + to ensure that is works. + +.. testsetup:: readme-eye + + from stylo.image import LayeredImage + from stylo.color import FillColor + from stylo.shape import Circle + + outer_eye = Circle(0, 0.5, 1) & Circle(0, -0.5, 1) + inner_eye = Circle(0, 0.5, .9) & Circle(0, -0.5, 0.9) + eye = outer_eye & ~inner_eye + + iris = Circle(0, 0, 0.4) + pupil = Circle(0, 0, 0.15) + + blue = FillColor("0000ff") + black = FillColor("000000") + + image = LayeredImage(scale=1.5) + + image.add_layer(iris, blue) + image.add_layer(pupil, black) + image.add_layer(eye, black) + + image(1920, 1080, filename="docs/_static/examples/readme-eye.png") + .. include:: ../README.rst Be sure to check out the :ref:`about_docs` page for a guide on how to get the most of the documentation! + Contents ^^^^^^^^ diff --git a/tox.ini b/tox.ini index 2c1df355..cf02d4dd 100644 --- a/tox.ini +++ b/tox.ini @@ -28,9 +28,9 @@ whitelist_externals = echo commands = echo -e "\n==> Building documentation \n" - sphinx-build -M linkcheck ./docs ./docs/_build -q -E -a -j auto - sphinx-build -M doctest ./docs ./docs/_build -q -E -a -j auto - sphinx-build -M html ./docs ./docs/_build -q -E -a -j auto + sphinx-build -M linkcheck ./docs ./docs/_build -E -a -j auto + sphinx-build -M doctest ./docs ./docs/_build -E -a -j auto + sphinx-build -M html ./docs ./docs/_build -E -a -j auto [testenv:docs-build] deps = @@ -49,9 +49,9 @@ commands = python scripts/apidoc.py -m stylo -o docs/api echo -e "\n==> Building documentation \n" - sphinx-build -M linkcheck ./docs ./docs/_build -q -E -a -j auto - sphinx-build -M doctest ./docs ./docs/_build -q -E -a -j auto - sphinx-build -M html ./docs ./docs/_build -q -E -a -j auto + sphinx-build -M linkcheck ./docs ./docs/_build -E -a -j auto + sphinx-build -M doctest ./docs ./docs/_build -E -a -j auto + sphinx-build -M html ./docs ./docs/_build -E -a -j auto [testenv:benchmark] deps = From 42f52c9170db0d0b70ff501670670b915f2a1813 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Mon, 1 Oct 2018 20:55:16 +0100 Subject: [PATCH 26/40] Remove uneeded jobs --- .travis.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8a22279b..9903497f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,12 +15,6 @@ matrix: - env: "TOXENV=lint" python: "3.6" - - env: "TOXENV=benchmark" - python: "3.6" - - - env: "TOXENV=docs-check" - python: "3.6" - - env: "TOXENV=docs-build" python: "3.6" From a62cc4d27e9a2136df18404c00c721d7bdd1d52c Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Mon, 1 Oct 2018 20:56:24 +0100 Subject: [PATCH 27/40] Fix syntax? --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9903497f..a4a99d9c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,8 @@ after_success: notifications: webhooks: - url: https://webhooks.gitter.im/e/4bfa4fbff35ebee0a9d2 + urls: + - https://webhooks.gitter.im/e/4bfa4fbff35ebee0a9d2 deploy: - provider: pages From 5d071f09140615226705a0c33fa30a6796e049b6 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Tue, 2 Oct 2018 17:12:18 +0100 Subject: [PATCH 28/40] Dont forget the image --- .gitignore | 1 + img/readme-eye.png | Bin 0 -> 18275 bytes 2 files changed, 1 insertion(+) create mode 100644 img/readme-eye.png diff --git a/.gitignore b/.gitignore index 3f9a9c0b..5f121ade 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ docs/_static/examples *.png !docs/**/*.png +!img/*.png .eggs/ *.egg-info/ diff --git a/img/readme-eye.png b/img/readme-eye.png new file mode 100644 index 0000000000000000000000000000000000000000..5588d4adb5fbe805a2a90f50ff2d361f7ee61cfa GIT binary patch literal 18275 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 literal 0 HcmV?d00001 From ea6d159879daf6f28388dd6e1343d08ddfd320c8 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Tue, 2 Oct 2018 17:22:09 +0100 Subject: [PATCH 29/40] Try it smaller --- img/readme-eye.png | Bin 18275 -> 2956 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/img/readme-eye.png b/img/readme-eye.png index 5588d4adb5fbe805a2a90f50ff2d361f7ee61cfa..c9790be0123814825f7ef2ceaacb53f7dc92e9df 100644 GIT binary patch literal 2956 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 From 4aad97cd9c7d6e4c864600a5c9b63549ebb7ba3b Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Tue, 2 Oct 2018 19:12:19 +0100 Subject: [PATCH 30/40] Forget the image until I have a better example --- README.rst | 35 ----------------------------------- img/readme-eye.png | Bin 2956 -> 0 bytes 2 files changed, 35 deletions(-) delete mode 100644 img/readme-eye.png diff --git a/README.rst b/README.rst index 669f3c6e..a4f4ed0d 100644 --- a/README.rst +++ b/README.rst @@ -42,41 +42,6 @@ Stylo is a Python library that allows you to create images and animations powered by your imagination and a little mathematics. While mathematics is very much at the core you do not have to be a mathematician to use it! -For example here is an eye, drawn with just a few lines of python - -.. image:: /_static/examples/readme-eye.png - :width: 75% - :align: center - -.. image:: img/readme-eye.png - :width: 75% - :align: center - -.. code-block:: python - - from stylo.image import LayeredImage - from stylo.color import FillColor - from stylo.shape import Circle - - outer_eye = Circle(0, 0.5, 1) & Circle(0, -0.5, 1) - inner_eye = Circle(0, 0.5, .9) & Circle(0, -0.5, 0.9) - eye = outer_eye & ~inner_eye - - iris = Circle(0, 0, 0.4) - pupil = Circle(0, 0, 0.15) - - blue = FillColor("0000ff") - black = FillColor("000000") - - image = LayeredImage(scale=1.5) - - image.add_layer(iris, blue) - image.add_layer(pupil, black) - image.add_layer(eye, black) - - image(1920, 1080, filename="docs/_static/examples/readme-eye.png") - - Installation ^^^^^^^^^^^^ diff --git a/img/readme-eye.png b/img/readme-eye.png deleted file mode 100644 index c9790be0123814825f7ef2ceaacb53f7dc92e9df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2956 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 z Date: Wed, 3 Oct 2018 18:52:15 +0100 Subject: [PATCH 31/40] Initial draft of the docs build explanation --- .../get-started/branching-policy.rst | 14 ++ docs/contributing/get-started/index.rst | 20 ++ .../get-started/release-process.rst | 32 +++ docs/contributing/index.rst | 1 + .../reference/documentation-build.rst | 184 ++++++++++++++++++ docs/contributing/reference/index.rst | 1 + docs/glossary.rst | 17 ++ 7 files changed, 269 insertions(+) create mode 100644 docs/contributing/get-started/branching-policy.rst create mode 100644 docs/contributing/get-started/index.rst create mode 100644 docs/contributing/get-started/release-process.rst create mode 100644 docs/contributing/reference/documentation-build.rst diff --git a/docs/contributing/get-started/branching-policy.rst b/docs/contributing/get-started/branching-policy.rst new file mode 100644 index 00000000..a20f1c4f --- /dev/null +++ b/docs/contributing/get-started/branching-policy.rst @@ -0,0 +1,14 @@ +.. _contribute_get_started_git: + +Working with Git +================ + +Code, tests and documentation are all held in a single git repository that is +hosted on `Github` + +.. _contribute_get_started_git_branching: + +Branching Policy +---------------- + + diff --git a/docs/contributing/get-started/index.rst b/docs/contributing/get-started/index.rst new file mode 100644 index 00000000..e94cf9f4 --- /dev/null +++ b/docs/contributing/get-started/index.rst @@ -0,0 +1,20 @@ +.. _contribute_get_started: + +Getting Started +=============== + +This section of the documentation is all about giving new contributors the +information they need to get stuck in with making their first contribution. +This section is broken down into a number of smaller sections with the first +section containing information that every contributor should know and is where +we recommend new contributors to start. The remaining sections are then +organised by what kind of contribution you want to make. + + +New Contributors - Start Here +----------------------------- + +.. toctree:: + + branching-policy + release-process diff --git a/docs/contributing/get-started/release-process.rst b/docs/contributing/get-started/release-process.rst new file mode 100644 index 00000000..51d58c90 --- /dev/null +++ b/docs/contributing/get-started/release-process.rst @@ -0,0 +1,32 @@ +.. _contribute_get_started_releases: + +The Release Process +=================== + +This page outlines the release process, what has to be done before a release, +how a release is triggered and how a release actually works. While it's not +essential for every contributor to know the inner workings of this process it is +certainly useful to know as it has an impact on other areas such as the +:ref:`contribute_get_started_git_branching` + +There are currently 2 dictinct release processes in :code:`stylo` there is the +release that publishes the documentation you are reading now and there is the +package release that publishes :code:`stylo` to PyPi and makes it generally +available. + +Documentation Release +--------------------- + +The documentation release is not as formal as the package release as there is +less ceremony around making a release. At its core the release is as simple as +it can get, the docs are written and the docs are published. + +A documentation release is triggered everytime a commit is made on the +:code:`develop` branch on the main repository and is handled by :term:`Travis` + +.. note:: + + There is currently no concept of version in the documentation the published + version always reflects the most recent state of the repository and therefore + can contain information on features not currently available. This should + probably be changed sometime in the future. diff --git a/docs/contributing/index.rst b/docs/contributing/index.rst index 45c4e53f..546c6450 100644 --- a/docs/contributing/index.rst +++ b/docs/contributing/index.rst @@ -6,6 +6,7 @@ Contributing .. toctree:: :maxdepth: 2 + get-started/index docs/index code/index reference/index diff --git a/docs/contributing/reference/documentation-build.rst b/docs/contributing/reference/documentation-build.rst new file mode 100644 index 00000000..5e55450d --- /dev/null +++ b/docs/contributing/reference/documentation-build.rst @@ -0,0 +1,184 @@ +.. _contribute_ref_docs_build: + +The Documentation Build Process +=============================== + +This page describes the build process for the documentation in detail. If you +are only looking for the command to build the documentation it is the following: + +.. code-block:: sh + + $ pipenv run docs + +If however you need to know more details about the build process or are simply +curious then please read on! + +Introducing tox +--------------- + +We use :term:`tox` to build our documentation as it will handle the installation +of the dependencies and give us more control over the environment in which they +are built. + +The build is handled by the :code:`docs-build` environment and is defined in the +:code:`tox.ini` file at the root of the repository. The command given at the top +of this page is a shortcut for the real but more cryptic command to build the +documentation which is: + +.. code-block:: sh + + $ pipenv run tox -q -e docs-build + +Below is the complete build definition. + +.. literalinclude:: ../../../tox.ini + :start-after: # + :end-before: # + +.. note:: + + Unlike the rest of this document, the box above is extracted from the current + version of :code:`tox.ini` and will always be up to date. If what you read + on this page doesn't match, that's most likely a sign that this page is + out of date and an `issue `_ + should be raised. + +Declaring Dependencies +---------------------- + +Using the :code:`deps` variable we declare to tox which dependencies we need +installed into the environment in order to build the documentation. + +- `Sphinx`_: This does the bulk of the work, compiling :code:`.rst` files in the + :code:`docs/` folder into a HTML website that we can publish. +- `topos-theme`_: Sphinx can be extended in a number of ways, one of these is + via custom HTML themes. :code:`topos-theme` extends Sphinx to provide the + theme that controls how this site appears. +- `pytest`_: Not something you would typically see in a docs build, pytest + is used to run a number of test files that generate most of the example images + you see on this site. +- `pytest-benchmark[histogram]`_: This is not currently used but the hope + is to eventually include benchmark information alongside the examples in the + documentation. + +We also make use of the :code:`whitelist_externals` variable to suppress +warnings about using the :code:`echo` command that is not part of the +environment. + +Build Overview +-------------- + +The build breaks down into the following stages. + +1. The examples are tested, image files are generated and the example pages are + written +2. The :term:`docstrings` are converted into the :ref:`api_reference` section +3. All the links are checked to ensure that they are not broken +4. Any :code:`testsetup::`, :code:`testcode::` or :code:`doctest::` sections are + executed to ensure that they work. +5. Finally the documentation is built into a HTML website ready for publishing. + + +Building the Examples +^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: sh + + pytest tests/examples -q --benchmark-autosave --benchmark-group-by=func + python scripts/exampledoc.py -e tests.examples + +These two steps combine to produce all the example pages in the documentation. +For details on how to write your own example page be sure to check out the +:ref:`contribute_tutorial_add_example` tutorial. + +The first command takes the examples defined in the :code:`tests/examples` +directory and executes them to ensure that they work. It also produces an image +file and saves it in the :code:`docs/_static/examples` directory. Finally +:code:`pytest-benchmark` produces performance data that we can use to track +performance over time. The plan is to incorporate this information into the +documentation at some point but currently it is unused. + +.. todo: + + Link to the page that explains how the :code:`define_benchmared_example` + function works. + +Next :code:`exampledoc.py` script is called and writes the reStructuredText +files that Sphinx will compile into the HTML that you see on the website. This +includes inserting the example image into the page, including the example code +and saving the file into the appropriate section of the documentation. For full +details on this script see the :ref:`contribute_reference_exampledoc` page. + + +Building the API Reference +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: sh + + python scripts/apidoc.py -m stylo -o docs/api + +Writing the :ref:`api_reference` section is entirely automated. The +:code:`apidoc.py` searches through the :code:`stylo` package for all the python +modules and generates an rst file for each one containing an +:code:`.. automodule::` definition. + +The `autodoc`_ Sphinx extension then extracts the docstrings from each item in +those modules and uses them to write the documentation you see in the API +Reference section. + +For full details on the :code:`apidoc.py` script please see the +:ref:`contribute_reference_apidoc` page. + +.. note:: + + While Sphinx does come with an :code:`sphinx-apidoc` command that acheives + the same goal as this script it produces an output that doesn't quite work + with the format of this site. By writing our own script we have more control + over the output can can modify it as needed. + + +Building the Documentation +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: sh + + sphinx-build -M linkcheck ./docs ./docs/_build -E -a -j auto + sphinx-build -M doctest ./docs ./docs/_build -E -a -j auto + sphinx-build -M html ./docs ./docs/_build -E -a -j auto + +This is where the bulk of the work happens, everything up until now has been +prep work. If you were to stop the build before these commands run you would +still only have a :code:`docs/` folder full of images and rst files. The only +thing the previous commands are doing is generating the rst files we don't have +to write by hand. With these three commands we pass everything off to Sphinx and +let it generate the website. + +Sphinx comes with a number of `builders`_ a builder takes your documentation and +performs a task with it. These tasks can be anything from generating an +:code:`epub` to an XML representation of your documents. + +Our build uses 3 builders: + +- :code:`linkcheck`: This looks at all the links in the documentation and checks + to ensure that they are not broken +- :code:`doctest`: The looks for code examples contained in the following + directives: + + + :code:`.. testsetup::` + + :code:`.. testcode::` + + :code:`.. testoutput::` + + :code:`.. testcleanup::` + + :code:`.. doctest::` + + It then runs all the code it can find and will fail the build if the code does + not work as described. +- :code:`html`: The main event, this produces the HTML website found in the + :code:`docs/_build/html` directory which we publish to GitHub Pages. + + +.. _autodoc: http://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html +.. _builders: http://www.sphinx-doc.org/en/stable/usage/builders/ +.. _Sphinx: http://www.sphinx-doc.org/en/master/ +.. _pytest-benchmark[histogram]: https://pytest-benchmark.readthedocs.io/en/latest/ +.. _pytest: https://docs.pytest.org/en/latest/ +.. _topos-theme: https://topos-theme.readthedocs.io/en/latest/ diff --git a/docs/contributing/reference/index.rst b/docs/contributing/reference/index.rst index 6724c94f..90b9dbd5 100644 --- a/docs/contributing/reference/index.rst +++ b/docs/contributing/reference/index.rst @@ -7,5 +7,6 @@ Reference .. toctree:: apidoc + documentation-build exampledoc tox diff --git a/docs/glossary.rst b/docs/glossary.rst index 63e375d3..eb867719 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -9,6 +9,12 @@ Glossary to address a point in space. Can be thought of as going *"along the corridor and up the stairs"*. See :ref:`math_cartesian_coordinates` + docstrings + docstrings are a special kind of comment in Python and are typically found + at the start of functions and classes. They outline what the purpose of + the object/class is, what input it expects and what it returns along with + any errors it may raise. + polar coordinates An alternate coordinate system that (in 2D) uses two variables :math:`(r, \theta)` to address a point in space. Useful for curves and circular objects. @@ -25,3 +31,14 @@ Glossary transpose Transposing a matrix is the act of flipping the matrix around its principal diagonal. *All the columns become rows and the rows become columns*. + + tox + `tox `_ is tool commonly found in + Python projects that automates the process of running various tasks + against multiple Python versions or environments. + + Travis + `Travis `_ is a continuous integration service that + will automatically run the tests whenever changes are made to the + repository and will report on any failures. It can also be configured to + handle releases. From fad9735126cf7786e4cb72f2f123cccfedb70100 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Thu, 4 Oct 2018 19:23:59 +0100 Subject: [PATCH 32/40] More changes --- docs/_static/new-issue.png | Bin 0 -> 47817 bytes docs/contributing/index.rst | 25 +++++++ docs/contributing/tutorials/fork-the-repo.rst | 26 +++++++ docs/contributing/tutorials/index.rst | 3 + docs/contributing/tutorials/open-an-issue.rst | 68 ++++++++++++++++++ tox.ini | 3 + 6 files changed, 125 insertions(+) create mode 100644 docs/_static/new-issue.png create mode 100644 docs/contributing/tutorials/fork-the-repo.rst create mode 100644 docs/contributing/tutorials/open-an-issue.rst diff --git a/docs/_static/new-issue.png b/docs/_static/new-issue.png new file mode 100644 index 0000000000000000000000000000000000000000..608ed61206dfc374c6b409213b5cf1a4e10fe136 GIT binary patch literal 47817 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 WM`_ + +2. Give your issue a descriptive title + +3. Explain your issue in detail, the more detail the better as it will help us + figure out what is wrong. See :ref:`contribute_tutorial_open_issue_content` + +4. When you are happy with your report click the green :code:`Submit new issue` + and wait until someone responds - Hopefully you won't have to wait too long! + +.. _contribute_tutorial_open_issue_content: + +What should I say? +------------------ + +What you should include in your issue depends on what your issue is about. Below +are a number of sections that aim to cover the most common kinds of issues and +the information that would help us help you resolve the issue. + +I found a bug +^^^^^^^^^^^^^ + +- What code were you running? +- What did you expect to see? +- What version of :code:`stylo` are you using? +- What version of :code:`python` are you using? +- If there was an error message include that as well + +There is a Problem with the Documentation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Where on the documentation? Can you include a link? +- Try to be as specific as possible just saying "it doesn't make sense" isn't + very helpful to us. +- Which parts do make sense? +- Is there a particular step that is unclear? +- If you were writing the documentation how would you phrase it? +- If you were using code from the documentation include that as well - it may be + broken. + + +.. _GitHub: https://github.com +.. _repository: https://github.com/alcarney/stylo + diff --git a/tox.ini b/tox.ini index cf02d4dd..f2b29049 100644 --- a/tox.ini +++ b/tox.ini @@ -32,6 +32,7 @@ commands = sphinx-build -M doctest ./docs ./docs/_build -E -a -j auto sphinx-build -M html ./docs ./docs/_build -E -a -j auto +# [testenv:docs-build] deps = sphinx @@ -53,6 +54,8 @@ commands = sphinx-build -M doctest ./docs ./docs/_build -E -a -j auto sphinx-build -M html ./docs ./docs/_build -E -a -j auto +# + [testenv:benchmark] deps = pytest From 7c5d65894c478eaecb040a2cf87a16445df5b82d Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Thu, 4 Oct 2018 20:52:55 +0100 Subject: [PATCH 33/40] Add a readme image again --- README.rst | 44 ++++++++++++++++++++++++++++++++++++++++++++ img/a-boat.png | Bin 0 -> 11459 bytes 2 files changed, 44 insertions(+) create mode 100644 img/a-boat.png diff --git a/README.rst b/README.rst index a4f4ed0d..567e8901 100644 --- a/README.rst +++ b/README.rst @@ -42,6 +42,50 @@ Stylo is a Python library that allows you to create images and animations powered by your imagination and a little mathematics. While mathematics is very much at the core you do not have to be a mathematician to use it! +For example here is a simple image of a boat that can be made with just a few +lines of Python + +.. image:: /img/a-boat.png + :align: center + :width: 75% + +.. testcode:: readme-boat + + from stylo.image import LayeredImage + from stylo.color import FillColor + from stylo.shape import Circle, Rectangle, Triangle + from stylo.domain.transform import translate + + # Let's define some colours + black = FillColor("000000") + seablue = FillColor("0000ff") + white = FillColor("ffffff") + yellow = FillColor("ffff00") + red = FillColor("dd2300") + + # Now for the shapes we will draw + sun = Circle(-7, 3.4, 1.5) + sea = Circle(0, -55, 55) + sails = Triangle((0.1, 0.6), (2.5, 0.6), (0.1, 3.5)) | Triangle((-0.1, 0.6), (-1.5, 0.6), (-0.1, 3.5)) + boat = Rectangle(0, 0, 3.5, 1) | Triangle((1.75, -0.5), (1.75, 0.5), (2.25, 0.5)) + mast = Rectangle(0, 2, 0.125, 3) + + # Move some into position + boat = boat >> translate(0, -2) + sails = sails >> translate(0, -2) + mast = mast >> translate(0, -2) + + # Finally let's bring it all together + image = LayeredImage(background="99ddee", scale=8) + + image.add_layer(sun, yellow) + image.add_layer(sea, seablue) + image.add_layer(boat, red) + image.add_layer(mast, black) + image.add_layer(sails, white) + + image(1920, 1080, filename="img/a-boat.png"); + Installation ^^^^^^^^^^^^ diff --git a/img/a-boat.png b/img/a-boat.png new file mode 100644 index 0000000000000000000000000000000000000000..fd707a32bbeadae3cb53dcda3a4da7ff6e241900 GIT binary patch literal 11459 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 literal 0 HcmV?d00001 From 951e19e31d2e1806c41c4971010deb4dd0183c45 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Fri, 5 Oct 2018 19:52:49 +0100 Subject: [PATCH 34/40] Finished initial draft of the branching policy page --- docs/_static/the-repo.png | Bin 0 -> 69307 bytes .../get-started/branching-policy.rst | 14 ----- docs/contributing/get-started/index.rst | 4 -- docs/contributing/index.rst | 15 +++-- .../reference/branching-policy.rst | 59 ++++++++++++++++++ docs/contributing/reference/index.rst | 2 + .../release-process.rst | 6 +- docs/contributing/tutorials/fork-the-repo.rst | 49 ++++++++++++++- docs/glossary.rst | 13 ++++ 9 files changed, 135 insertions(+), 27 deletions(-) create mode 100644 docs/_static/the-repo.png delete mode 100644 docs/contributing/get-started/branching-policy.rst create mode 100644 docs/contributing/reference/branching-policy.rst rename docs/contributing/{get-started => reference}/release-process.rst (89%) diff --git a/docs/_static/the-repo.png b/docs/_static/the-repo.png new file mode 100644 index 0000000000000000000000000000000000000000..911e3926074c4d374e758cfbadc1501e394342ff GIT binary patch literal 69307 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 literal 0 HcmV?d00001 diff --git a/docs/contributing/get-started/branching-policy.rst b/docs/contributing/get-started/branching-policy.rst deleted file mode 100644 index a20f1c4f..00000000 --- a/docs/contributing/get-started/branching-policy.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. _contribute_get_started_git: - -Working with Git -================ - -Code, tests and documentation are all held in a single git repository that is -hosted on `Github` - -.. _contribute_get_started_git_branching: - -Branching Policy ----------------- - - diff --git a/docs/contributing/get-started/index.rst b/docs/contributing/get-started/index.rst index e94cf9f4..ac99e80c 100644 --- a/docs/contributing/get-started/index.rst +++ b/docs/contributing/get-started/index.rst @@ -14,7 +14,3 @@ organised by what kind of contribution you want to make. New Contributors - Start Here ----------------------------- -.. toctree:: - - branching-policy - release-process diff --git a/docs/contributing/index.rst b/docs/contributing/index.rst index 83cae6ab..f8c6ef52 100644 --- a/docs/contributing/index.rst +++ b/docs/contributing/index.rst @@ -10,11 +10,7 @@ links below just click on the one you feel matches you the most and it should take you where you need to go. - :ref:`contribute_how_to` - -.. _contribute_i_want: - -I want to ..? -------------- +- :ref:`contribute_ref` .. _contribute_how_to: @@ -25,6 +21,15 @@ How do I ..? - How do I :ref:`contribute_tutorial_fork_repository`? +.. _contribute_ref: + +Tell me more about .. +--------------------- + +- Tell me more about the :ref:`Documentation Build ` +- Tell me more about the :ref:`Branching Policy ` +- Tell me more about the :ref:`Release Process ` + Index ----- diff --git a/docs/contributing/reference/branching-policy.rst b/docs/contributing/reference/branching-policy.rst new file mode 100644 index 00000000..ab62ad8d --- /dev/null +++ b/docs/contributing/reference/branching-policy.rst @@ -0,0 +1,59 @@ +.. _contribute_ref_branching: + +The Branching Policy +==================== + +.. attention:: + + This page assumes that you are confortable with using git. + +The Golden Rule +--------------- + +If there is one thing you take away from this page it is this **we never work on +master**. + +We never do any work directly on the :code:`master` branch because the release +process (explained in much greater detail :ref:`here `) +is set up to automatically package and publish code that is committed to the +:code:`master` branch. + +So that we don't accidentally publish broken or work in progress code we do all +our work based on the :code:`develop` branch. The only time a commit is made to +the master branch is when a new release of :code:`stylo` is made. Again it's +recommended that you read :ref:`contribute_ref_release` page for more information +on this process. + +Our Recommendations +------------------- + +.. todo:: + + Link to various articles explaining some of these steps in more detail when + they are written. + +.. tip:: + + Git can get very scary, very quickly. If you are having trouble with it at any + stage you can always drop a message in the + `chatroom `_ we'll always be happy to help. + +With that out of the way here is the recommended workflow when making changes to +the repository. + +1. Make sure you have the :code:`develop` branch checked out and that it is up + to date with the latest in the main repository. +2. Create a new branch to do your work on. It helps if you choose name that + indicates the sort of work you intend to do e.g. :code:`add-new-shape` or + :code:`fix-issue-123` +3. Make whatever changes and commits you need to complete the task. +4. When you have finished, update your :code:`develop` branch to the + latest and rebase your work on top of it. +5. Push your changes up to your fork and open a PR against the :code:`develop` + branch on the main repository. + +Don't worry if you're not using git "perfectly" at the end of the day it is a +tool used for bookkeeping and the process outlined above is only a +recommendation. What's more important is your contribution so focus on that we +can always guide you through the bookkeeping steps when it comes to getting your +contribution merged. diff --git a/docs/contributing/reference/index.rst b/docs/contributing/reference/index.rst index 90b9dbd5..848564b4 100644 --- a/docs/contributing/reference/index.rst +++ b/docs/contributing/reference/index.rst @@ -7,6 +7,8 @@ Reference .. toctree:: apidoc + branching-policy documentation-build exampledoc + release-process tox diff --git a/docs/contributing/get-started/release-process.rst b/docs/contributing/reference/release-process.rst similarity index 89% rename from docs/contributing/get-started/release-process.rst rename to docs/contributing/reference/release-process.rst index 51d58c90..9632076d 100644 --- a/docs/contributing/get-started/release-process.rst +++ b/docs/contributing/reference/release-process.rst @@ -1,4 +1,4 @@ -.. _contribute_get_started_releases: +.. _contribute_ref_release: The Release Process =================== @@ -7,9 +7,9 @@ This page outlines the release process, what has to be done before a release, how a release is triggered and how a release actually works. While it's not essential for every contributor to know the inner workings of this process it is certainly useful to know as it has an impact on other areas such as the -:ref:`contribute_get_started_git_branching` +:ref:`contribute_ref_branching` -There are currently 2 dictinct release processes in :code:`stylo` there is the +There are currently 2 distinct release processes in :code:`stylo` there is the release that publishes the documentation you are reading now and there is the package release that publishes :code:`stylo` to PyPi and makes it generally available. diff --git a/docs/contributing/tutorials/fork-the-repo.rst b/docs/contributing/tutorials/fork-the-repo.rst index 2276ef39..e78a6fba 100644 --- a/docs/contributing/tutorials/fork-the-repo.rst +++ b/docs/contributing/tutorials/fork-the-repo.rst @@ -18,9 +18,56 @@ You **do** need a fork if you want to: Before We Start --------------- -In order to fork the repository you need to have created an account on `GitHub`_ +In order to fork the repository you need to: + +- Have created an account on `GitHub`_ +- Have :term:`git` installed +- Be comfortable using the command line Forking the Repository ---------------------- +.. image:: /_static/the-repo.png + :align: center + :width: 75% + +1. Find the main `repository `_ on GitHub + +2. Click the :code:`Fork` button that should be just underneath your profile + picture. + +3. If you are a member of an organisation GitHub will ask you where you want to + Fork to repository to, you should probably choose your personal account. + +GitHub will redirect you to your own copy of the repository we will then +use git to copy (clone) your fork onto your own machine. + +1. Click the Green :code:`Clone or download` button that should be just above + the list of files on the right. A popup box should then appear and provide + you with the address of your repository, highlight the address and copy it. + +2. Open your terminal application and navigate to a folder where you want the + repository to be located and run the following command. + +.. code-block:: sh + + $ git clone + +Git will then download the repository onto your machine and store it in a folder +called :code:`stylo`. + +That's it! If everything went smoothly you will have successfully forked the +repository! + + +Next Steps +---------- + +Forking the repository is just the first step on the journey into making your +first major contribution, here are some tasks that you will want to do next. + +.. todo:: + + Link to the various tutorials when they exist. + .. _GitHub: https://github.com/alcarney/stylo diff --git a/docs/glossary.rst b/docs/glossary.rst index eb867719..30b7933d 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -15,6 +15,13 @@ Glossary the object/class is, what input it expects and what it returns along with any errors it may raise. + git + `Git `_ is a tool used to manage multiple versions + of documents stored on multile computers. It allows us to see the history + of every file in the repository and be able to copy changes between each + other without going insane. While very powerful it does have a reputation + for being hard to understand. + polar coordinates An alternate coordinate system that (in 2D) uses two variables :math:`(r, \theta)` to address a point in space. Useful for curves and circular objects. @@ -37,6 +44,12 @@ Glossary Python projects that automates the process of running various tasks against multiple Python versions or environments. +Software Development +-------------------- + +.. glossary:: + :sorted: + Travis `Travis `_ is a continuous integration service that will automatically run the tests whenever changes are made to the From ca63c419e322f346a77ea065f8077fe939c8d45a Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Sat, 6 Oct 2018 00:05:31 +0100 Subject: [PATCH 35/40] Initial draft explaining the release process --- .travis.yml | 4 + CHANGES.rst | 5 + README.rst | 7 +- docs/_static/new-release.png | Bin 0 -> 82502 bytes .../reference/release-process.rst | 182 ++++++++++++++++-- docs/glossary.rst | 41 ++-- 6 files changed, 205 insertions(+), 34 deletions(-) create mode 100644 docs/_static/new-release.png diff --git a/.travis.yml b/.travis.yml index a4a99d9c..0c4fcb01 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,6 +33,7 @@ notifications: - https://webhooks.gitter.im/e/4bfa4fbff35ebee0a9d2 deploy: + # - provider: pages skip-cleanup: true github-token: $GH_TOKEN @@ -42,7 +43,9 @@ deploy: branch: develop condition: $TOXENV = docs-build python: 3.6 + # + # - provider: pypi distributions: "sdist bdist_wheel" user: alcarney @@ -51,3 +54,4 @@ deploy: on: condition: $TOXENV = py36 python: 3.6 + # diff --git a/CHANGES.rst b/CHANGES.rst index de1ea3fc..653541e6 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -28,6 +28,11 @@ Users the various shapes have been combined together. - Preview images in Jupyter notebooks are now larger by default +This release of :code:`stylo` was brought to you thanks to contributions from +the following awesome people! + +- `mvinoba `_ + v0.5.0 - 2018-09-27 ------------------- diff --git a/README.rst b/README.rst index 567e8901..c8b243f7 100644 --- a/README.rst +++ b/README.rst @@ -45,6 +45,11 @@ much at the core you do not have to be a mathematician to use it! For example here is a simple image of a boat that can be made with just a few lines of Python + +.. image:: /_static/examples/a-boat.png + :align: center + :width: 75% + .. image:: /img/a-boat.png :align: center :width: 75% @@ -84,7 +89,7 @@ lines of Python image.add_layer(mast, black) image.add_layer(sails, white) - image(1920, 1080, filename="img/a-boat.png"); + image(1920, 1080, filename="docs/_static/examples/a-boat.png"); Installation ^^^^^^^^^^^^ diff --git a/docs/_static/new-release.png b/docs/_static/new-release.png new file mode 100644 index 0000000000000000000000000000000000000000..ca853b5825cd9d8252c1226cb7ab986129da8e42 GIT binary patch literal 82502 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

t^@-?u|)MCN@bhDdYV|NVO3bc9=e1pK6_&A2%j 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

dHpBIEN?cC( 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⁡7mS8?6Q?pb$C@exXY6}R=xa6V1HKr4F1CdGDc<5$Y6A}+{jHIx2kf(H=cm`BRjaErOqirD8WzZqhL0=I0gf$NP$_XLpg^ z0<@VvJ5(UqvAzV-#z5xv8auJLN0Co+-DSewHZ2VZHJSrFV4f0u+Y74ht zwlMLHuHFtodV0IE%4>&(ETB4jgn`A}d^}GJ`WkbZ+C>MtZ|-_uCu;BTKuWB!(AfDx z9KR4s=EeAN?q>k0)y%k7!^+8=i+hrb)YV0i>;^T8a*5grF{3OLp(4#a4TZ6H{T2e6~jvV;fv8OXM=R z_;&(rb9l?~$pc(I*g8x=saTG_$vx%p^1&LVUz9fu}b;5I=Mv#LM|18Z*-JV9#H=m0m3f&K{IA3>DM5TO1h04^0IGTTz<>9T9w1EgHf$a>`}q73{^8q8S3$=#$BPB` zR|^-4(}O_j=qt(}&uT8_zx@R2O+5j4Z3DQ6;#zzKJb*@-maIYj{+eF3t?pT}U(8jv zvphe)AFH=E7F{<-^M3gG0g5G{7Evxs^X)nk=2n_hH2WPXvR6|P&Zq`LtP4du+VE_L ze6`fH^VaJW@i7A@Lt82tHjWBLu^4pA{qfl{pm~E&1aDO4!phEpmZhzu@O@?4JL0_e zNHdDTqD9zDPb`?HoQ8_vJ?)gOn~wUYs-eL=u+&XEpxWwERliiSR{li4zKC_=y*x7i c2P_xPeWAhRl!Of#`OEs{WnM#zU%vhHU%XWu`v3p{ literal 0 HcmV?d00001 diff --git a/docs/contributing/reference/release-process.rst b/docs/contributing/reference/release-process.rst index 9632076d..6ad4a6c8 100644 --- a/docs/contributing/reference/release-process.rst +++ b/docs/contributing/reference/release-process.rst @@ -5,28 +5,178 @@ The Release Process This page outlines the release process, what has to be done before a release, how a release is triggered and how a release actually works. While it's not -essential for every contributor to know the inner workings of this process it is -certainly useful to know as it has an impact on other areas such as the -:ref:`contribute_ref_branching` +essential for every contributor to know the inner workings of a release it is +certainly useful to know as it provides context for some of the decisions made +in our processes such as :ref:`contribute_ref_branching` -There are currently 2 distinct release processes in :code:`stylo` there is the -release that publishes the documentation you are reading now and there is the -package release that publishes :code:`stylo` to PyPi and makes it generally -available. +There are currently 2 distinct release processes in :code:`stylo`: + +- :ref:`contribute_ref_release_docs`: This builds, tests and deploys the + documentation to `GitHub Pages`_ +- :ref:`contribute_ref_release_package`: This builds, tests and deploys + :code:`stylo` itself to :term:`PyPi` + +.. _contribute_ref_release_docs: Documentation Release --------------------- -The documentation release is not as formal as the package release as there is -less ceremony around making a release. At its core the release is as simple as -it can get, the docs are written and the docs are published. - A documentation release is triggered everytime a commit is made on the -:code:`develop` branch on the main repository and is handled by :term:`Travis` +:code:`develop` branch of the main repository. :term:`Travis` will run all the +tests as normal, then as long as the :code:`docs-build` task completes +successfully it will proceed to publish the new version of the documentation. + +For full details on the documentation build process please see +:ref:`this ` article + +Below is the current Travis deployment configuration: + +.. literalinclude:: ../../../.travis.yml + :language: yaml + :start-after: # + :end-before: # + :dedent: 4 + +.. attention:: + + The box above is extracted from the current :code:`.travis.yml` file. If what + you read here doesn't match what is shown above, it's most likely that this + documentation is out of date and an issue should be raised. + +- :code:`provider: pages`: We tell Travis that we are deploying a website to + GitHub Pages +- :code:`skip-cleanup: true`: By default Travis will delete any files generated + during the build - we obviously don't want that so we skip that step. +- :code:`github-token`: The keys to GitHub +- :code:`local-dir`: Which directory contains the site +- :code:`verbose`: Tell Travis to print more about what it is doing. +- :code:`on`: Only do the release when the following conditions are met. + + - :code:`branch`: The build is running on the develop branch + - :code:`condition: $TOXENV = docs-build`: It only makes sense to publish when + we have built the documentation. + - :code:`python`: Only on the given version of python. + +It's also worth mentioning that the way Travis deploys the website is by force +pushing the generated HTML to the :code:`gh-pages` branch on the main +repository. I assume that's a good thing since it is the default. + +.. note:: + + Currently the documentation is unversioned, whenever an update is available + it is published. This probably doesn't matter too much right now as the + documentation is still very much under development. However this does mean + that the documentation may pull ahead of the version of :code:`stylo` that is + generally available which would lead to confusion. This should be changed + sometime in the future. + + +.. _contribute_ref_release_package: + +Package Release +--------------- + +A package release is triggered whenever a commit it made on the :code:`master` +branch of the main repository. :term:`Travis` will run all the tests as normal +and if the :code:`py36` task completes successfully then it will package and +publish :code:`stylo` to :term:`PyPi`. + +However unlike the documentation release which is quite informal, there are a +number of things that need to be done before and after a package release + +Drafting a Release +^^^^^^^^^^^^^^^^^^ + +A draft release is made by opening a PR from the :code:`develop` branch onto the +:code:`master` branch of the main repository. In order for this PR to become a +proper release the following must be satisfied + +- All the code, docs, tests etc that are to be included in the release have been + merged onto the :code:`develop` branch. +- The :code:`stylo/_version.py` has been updated to the latest version number. +- The :code:`CHANGES.rst` file has been updated to include a summary of the + changes included in the release. **On the day of the merge the release + title is updated to include the date and version of the release** +- All the tests pass and Travis is happy. + +If all is well and whoever is looking after the release is happy, then the PR +can be merged which will kick off the release process. + +The Release +^^^^^^^^^^^ + +The process from when the PR is merged to the moment the latest :code:`stylo` +package turns up on PyPi is entirely automated. Travis will rerun all the tests +after the merge and then proceed to package and publish the new version. + +.. todo:: + + Link to the article explaining the code related build processes, when it is + available. + +Below is the current Travis configuration + +.. literalinclude:: ../../../.travis.yml + :language: yaml + :start-after: # + :end-before: # + :dedent: 4 + +.. attention:: + + The box above is extracted from the current :code:`.travis.yml` file. If what + you read here doesn't match what is shown above, it's most likely that this + documentation is out of date and an issue should be raised. + +- :code:`provider: pypi`: Tell Travis that we are publishing a package to PyPi +- :code:`distributions`: We want to publish both the source and a compiled wheel +- :code:`user`, :code:`password`: PyPi credentials. +- :code:`on`: Only do the release if the following conditions are met. + + + :code:`condition: py36`: We only need to publish the package once, so we're + currently using the Python 3.6 build. + + :code:`python: 3.6`: Possibly a redundant condition? But since it works it + doesn't seem worth the risk to take it out. + + The build is on the master branch (an implicit default). + +The package and its contents are defined by the :code:`setup.py` file at the +root of the repository. + +.. todo:: + + Link to the article explaining the setup file when it's written. + +After the Release +^^^^^^^^^^^^^^^^^ + +.. image:: /_static/new-release.png + :align: center + :width: 75% + +After the PR has been merged there is one last manual step to be done and that +is to create a `release `_ on +GitHub. + +After clicking on the :code:`Draft a new release` button on the releases page +you are taken to a page as shown above where the following fields need to be +filled in. + +- The version string needs to be put in the tag name box +- **The branch needs to be changed to master** +- The title of the release needs to be copied over from the :code:`CHANGES.rst` + file +- The changes for the release need to be copied over from the :code:`CHANGES.rst` + and pasted into the body. *Note: You will need to convert the text from rst to + markdown* + +Once it has been filled out click the green :code:`Publish release` button and +you are done! .. note:: - There is currently no concept of version in the documentation the published - version always reflects the most recent state of the repository and therefore - can contain information on features not currently available. This should - probably be changed sometime in the future. + It is the hope that this step can also be automated, by having something like + a webhook trigger on the merge to master we can use the GitHub API to + automatically create the release notice. + + +.. _GitHub Pages: https://pages.github.com/ diff --git a/docs/glossary.rst b/docs/glossary.rst index 30b7933d..3022e27d 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -1,6 +1,9 @@ Glossary ======== +Mathematics +----------- + .. glossary:: :sorted: @@ -9,6 +12,24 @@ Glossary to address a point in space. Can be thought of as going *"along the corridor and up the stairs"*. See :ref:`math_cartesian_coordinates` + polar coordinates + An alternate coordinate system that (in 2D) uses two variables :math:`(r, \theta)` + to address a point in space. Useful for curves and circular objects. + See :ref:`math_polar_coordinates` + + linear interpolation + TBW + + transpose + Transposing a matrix is the act of flipping the matrix around its principal + diagonal. *All the columns become rows and the rows become columns*. + +Software Development +-------------------- + +.. glossary:: + :sorted: + docstrings docstrings are a special kind of comment in Python and are typically found at the start of functions and classes. They outline what the purpose of @@ -22,34 +43,20 @@ Glossary other without going insane. While very powerful it does have a reputation for being hard to understand. - polar coordinates - An alternate coordinate system that (in 2D) uses two variables :math:`(r, \theta)` - to address a point in space. Useful for curves and circular objects. - See :ref:`math_polar_coordinates` - linting Linting in software development is the process of running one or more tools against a codebase that search for potential issues. Examples include undefined variables or enforcing stylistic conventions such as line length. - linear interpolation - TBW - - transpose - Transposing a matrix is the act of flipping the matrix around its principal - diagonal. *All the columns become rows and the rows become columns*. + PyPi + `PyPi `_ is the Python Package Index. Any python + package that you can :code:`pip install` is hosted here. tox `tox `_ is tool commonly found in Python projects that automates the process of running various tasks against multiple Python versions or environments. -Software Development --------------------- - -.. glossary:: - :sorted: - Travis `Travis `_ is a continuous integration service that will automatically run the tests whenever changes are made to the From 7d4c90436739c0b25032476953c59a78d48c3999 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Sat, 6 Oct 2018 00:20:48 +0100 Subject: [PATCH 36/40] These no longer fit --- docs/contributing/code/code-style.rst | 20 ------------------- docs/contributing/code/index.rst | 8 -------- .../code/reference/domain-system.rst | 4 ---- docs/contributing/docs/index.rst | 14 ------------- docs/contributing/docs/the-build.rst | 18 ----------------- docs/contributing/index.rst | 2 -- 6 files changed, 66 deletions(-) delete mode 100644 docs/contributing/code/code-style.rst delete mode 100644 docs/contributing/code/index.rst delete mode 100644 docs/contributing/code/reference/domain-system.rst delete mode 100644 docs/contributing/docs/index.rst delete mode 100644 docs/contributing/docs/the-build.rst diff --git a/docs/contributing/code/code-style.rst b/docs/contributing/code/code-style.rst deleted file mode 100644 index 61f395df..00000000 --- a/docs/contributing/code/code-style.rst +++ /dev/null @@ -1,20 +0,0 @@ -Code Style -========== - -One of the checks your code must pass in order to make Travis happy is the -:term:`linting` test. This test checks two things: - -1. That the `black`_ code formatter wouldn't make any changes to your code's formatting. -2. That the `flake8`_ linter doesn't see any issues with your code. - -You can easily run the same tests that Travis would by running the following command - -.. code-block:: sh - - $ pipenv run tox -e lint - -Which will run the two tools against the code in both the :code:`stylo/` directory and -the :code:`tests/` directory. - -.. _black: https://black.readthedocs.io/en/stable/ -.. _flake8: http://flake8.pycqa.org/en/latest/ \ No newline at end of file diff --git a/docs/contributing/code/index.rst b/docs/contributing/code/index.rst deleted file mode 100644 index de674ecc..00000000 --- a/docs/contributing/code/index.rst +++ /dev/null @@ -1,8 +0,0 @@ -Code -==== - -.. toctree:: - :maxdepth: 2 - - code-style - reference/domain-system diff --git a/docs/contributing/code/reference/domain-system.rst b/docs/contributing/code/reference/domain-system.rst deleted file mode 100644 index a8ed6c34..00000000 --- a/docs/contributing/code/reference/domain-system.rst +++ /dev/null @@ -1,4 +0,0 @@ -The Domain System -================= - -.. automodule:: stylo.domain._factory diff --git a/docs/contributing/docs/index.rst b/docs/contributing/docs/index.rst deleted file mode 100644 index 75b45c82..00000000 --- a/docs/contributing/docs/index.rst +++ /dev/null @@ -1,14 +0,0 @@ -Documentation -============= - -.. toctree:: - - the-build - -TodoList --------- - -If there are any todo notes scattered throughout the documentation, they will also be -listed here. - -.. todolist:: diff --git a/docs/contributing/docs/the-build.rst b/docs/contributing/docs/the-build.rst deleted file mode 100644 index 38c35d57..00000000 --- a/docs/contributing/docs/the-build.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. _contribute_docs_build: - -Building the Documentation -========================== - -.. note:: - - You **do not** have to understand how the docs are built in order to contribute to - them! We have a single command to take care of it for you :code:`tox -e docs`. Check - out this page for more information. - -If you have looked at the :ref:`contribute_reference_tox_ini` file, you might have -noticed that the documentation build is the most complicated. This is due to the fact a -number of tasks have been automated - at the cost of being more complicated to build. - -Building the documentation involves the following steps: - -1. Generating the :ref:`api_reference` section using the :ref:`contribute_reference_apidoc` diff --git a/docs/contributing/index.rst b/docs/contributing/index.rst index f8c6ef52..7cdd844c 100644 --- a/docs/contributing/index.rst +++ b/docs/contributing/index.rst @@ -37,8 +37,6 @@ Index :maxdepth: 2 get-started/index - docs/index - code/index reference/index tutorials/index From 5a866bf72f78f7ee1a921f3bead00be67223c01b Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Sat, 6 Oct 2018 19:05:33 +0100 Subject: [PATCH 37/40] Initial draft of setting up dev env --- docs/contributing/index.rst | 1 + docs/contributing/tutorials/index.rst | 1 + docs/contributing/tutorials/set-up-devenv.rst | 139 ++++++++++++++++++ docs/glossary.rst | 8 + 4 files changed, 149 insertions(+) create mode 100644 docs/contributing/tutorials/set-up-devenv.rst diff --git a/docs/contributing/index.rst b/docs/contributing/index.rst index 7cdd844c..c678a1e4 100644 --- a/docs/contributing/index.rst +++ b/docs/contributing/index.rst @@ -19,6 +19,7 @@ How do I ..? - How do I :ref:`contribute_tutorial_open_issue`? - How do I :ref:`contribute_tutorial_fork_repository`? +- How do I :ref:`contribute_tutorial_devenv_setup`? .. _contribute_ref: diff --git a/docs/contributing/tutorials/index.rst b/docs/contributing/tutorials/index.rst index 70be4491..ef04716f 100644 --- a/docs/contributing/tutorials/index.rst +++ b/docs/contributing/tutorials/index.rst @@ -8,4 +8,5 @@ Tutorials add-an-example fork-the-repo open-an-issue + set-up-devenv diff --git a/docs/contributing/tutorials/set-up-devenv.rst b/docs/contributing/tutorials/set-up-devenv.rst new file mode 100644 index 00000000..92fe40fc --- /dev/null +++ b/docs/contributing/tutorials/set-up-devenv.rst @@ -0,0 +1,139 @@ +.. _contribute_tutorial_devenv_setup: + +Setup the Development Environment +================================= + +Before you can build the documentation or run the code and the tests you need to +have setup your development environment so that all the tools you need are +installed and configured. + +.. todo:: + + This guide is currently heavily biased towards UNIX style systems chances are + portions of this guide won't work on Windows. We probably should have a + Windows setup guide at some point. + +Before we Start +--------------- + +This guide assumes that: + +- You have :ref:`forked ` the repository +- You have Python 3.6 or newer installed. +- You are comfortable using the command line. + +There are currently two supported methods of setting up your development +environment. + +- :ref:`contribute_tutorial_devenv_setup_script` +- :ref:`contribute_tutorial_devenv_manual` + +The goal of the script is to lower the barrier to getting people contributing to +:code:`stylo`. Having a single command to run can be much more approachable than +having to run half a dozen of them. Additionally by using a script everyone +should end up with exactly the same setup - at least that is the theory. + +On the other hand the script may not work for you or some people may feel better +doing the setup by hand as they want to know how things fit together or don't +like the idea of running some script they found on the internet. That is why we +also have the manual process, it does exactly the same steps as the script but +it's a lot more transparent. + +At the end of the day, whichever approach you take we will happily support you +either way - everyone's system is different so there are bound to be a few +issues now and then. + +.. _contribute_tutorial_devenv_setup_script: + +Using a Script +-------------- + +To setup your environment using the script from the root of the repository run +the following command. + +.. code-block:: sh + + $ ./scripts/devenv-setup.sh + +The script will do the following: + +- Check to see that you have a compatible version of Python installed. +- If you don't have `Pipenv`_ installed it will install it using the command + :code:`pip install --user pipenv` +- It will then use pipenv to create a virtual environment and install all the + runtime and development dependencies into it. +- One of these dependencies is `pre-commit`_ the script configures it to + run some checks automatically whenever you make a commit. +- Finally as a check to make sure everything is setup correctly, the script will + do a complete build of the documentation. See :ref:`contribute_ref_docs_build` + for more details on this process. + +.. _contribute_tutorial_devenv_manual: + +Manually +-------- + +The manual setup follows the same process as the script above, the only +difference is that you will be running each of the commands and not the script. + +1. The first step is to make sure you have `Pipenv`_ installed. Pipenv is a tool + that brings together the management of :term:`virtual environments` and + project dependencies into a single command. + + Pipenv can be installed using the following command. + + .. code-block:: sh + + $ pip install --user pipenv + +2. Next use pipenv to create a virtual environment for the project and install + all the runtime and development dependencies into it with the following + command. This should be run from the root of the repository + + .. code-block:: sh + + $ pipenv install --dev + +3. The next two commands need to be run from inside your virtual environment so + we can activate it as follows: + + .. code-block:: sh + + $ pipenv shell + +4. Next we need to setup `pre-commit`_ to run a few checks for us each time we + make a commit. But we need to tell it your Python version so open up the + :code:`.pre-commit-config.yaml` file and change the following line + + .. code-block:: yaml + + language_version: python3.7 + + to match your installed version of Python and then setup pre-commit with the + command + + .. code-block:: sh + + (stylo-xyz123) $ pre-commit install + + .. note:: + + Your prompt should look similar to the above as it indicates that your + virtual environment is active. You can deactivate your virtual environment + by running the command :code:`exit` + +5. Finally start a build of the documentation to ensure everything is working as + expected + + .. code-block:: sh + + (stylo-xyz123) $ tox -q -e docs-build + + +That's it! You should now have a functioning development environment and you can +start working on your contribution! Be sure to check out +:ref:`contribute_ref_branching` so that there are no surprises when it comes to +merging in your work when it is ready + +.. _Pipenv: https://github.com/pypa/pipenv +.. _pre-commit: https://pre-commit.com/ diff --git a/docs/glossary.rst b/docs/glossary.rst index 3022e27d..64703d25 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -62,3 +62,11 @@ Software Development will automatically run the tests whenever changes are made to the repository and will report on any failures. It can also be configured to handle releases. + + virtual environments + A virtual environment is an isolated installation of Python that can have + its own collection of packages installed and is completely independent of + the host machine's Python installation. They are highly recommended when + working on projects as they stop conflicts when you need multiple versions + of the same package installed. + installed From 916b37b1370e1ffa50c625eaba2598f5d42d74fa Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Sat, 6 Oct 2018 20:03:46 +0100 Subject: [PATCH 38/40] Initial draft explaining the setup.py file --- docs/contributing/index.rst | 1 + docs/contributing/reference/index.rst | 1 + docs/contributing/reference/setup-py.rst | 95 ++++++++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 docs/contributing/reference/setup-py.rst diff --git a/docs/contributing/index.rst b/docs/contributing/index.rst index c678a1e4..f53526ec 100644 --- a/docs/contributing/index.rst +++ b/docs/contributing/index.rst @@ -30,6 +30,7 @@ Tell me more about .. - Tell me more about the :ref:`Documentation Build ` - Tell me more about the :ref:`Branching Policy ` - Tell me more about the :ref:`Release Process ` +- Tell me more about the :ref:`Setup.py file ` Index ----- diff --git a/docs/contributing/reference/index.rst b/docs/contributing/reference/index.rst index 848564b4..04e5a0f3 100644 --- a/docs/contributing/reference/index.rst +++ b/docs/contributing/reference/index.rst @@ -11,4 +11,5 @@ Reference documentation-build exampledoc release-process + setup-py tox diff --git a/docs/contributing/reference/setup-py.rst b/docs/contributing/reference/setup-py.rst new file mode 100644 index 00000000..e9f72f92 --- /dev/null +++ b/docs/contributing/reference/setup-py.rst @@ -0,0 +1,95 @@ +.. _contribute_ref_setup_py: + +The Setup.py File +================= + +The :code:`setup.py` file is what the packaging tools use to determine what +should go into :code:`stylo` when it is packaged as well as define any metadata +about the project itself. + +Here is the contents of that file + +.. literalinclude:: ../../../setup.py + :language: python + +While we won't go through absolutely everything, here are some of the highlights + +.. attention:: + + The box above contains the current version of :code:`setup.py` extracted from + the file itself. If what you read below doesn't match up then it's an + indication that this page is out of date and an issue should be raised. + +Package Metadata +---------------- + +Name, Version, Description +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Some standard info about the project, such as its :code:`name`. The +:code:`version` is set to the value of the :code:`__version__` string from the +:code:`stylo/_version.py` file so that it is always up to date. There is also a +one line :code:`description` about what :code:`stylo` does. + +There is also a :code:`long_description` field, this is what will be displayed +on the `project `_ page on :term:`PyPi` this is +generally a project's README file. Since the :code:`setup.py` is just regular +python code we write a :code:`readme()` function to read the contents of the +:code:`README.rst` file so that this field is always up to date. + +Authors, License, Classifiers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The :code:`author` and :code:`author_email` fields give you some idea about the +people behind the project and a way to get in touch. + +The :code:`license` field tells you what license :code:`stylo` is available +under and dictates what you can and can't do with the code. :code:`stylo` is +available under the `MIT License`_ and since I'm not a lawyer I recommend you +follow the link if you want to know what the terms of the license are all about. + +Then we have a number of :code:`classifiers`, these are tags that help indicate +the current state of the project. This can range from anything from the versions +of Python that are supported to the license the project is available under. +There are *many* classifiers to choose from +`here `_ is a full list for +those who are interested. + +.. note:: + + There needs to be a conversation about when people are considered to be + "core" contributors and therefore should be added to the authors list. + +Packages & Requirements +^^^^^^^^^^^^^^^^^^^^^^^ + +Here we get into what is included in the package, we use the +:code:`find_packages` function to automatically discover the python files inside +the :code:`stylo` folder that need to be included. + +We also need to specify our dependencies in the :code:`install_requires` field +so that when people :code:`pip install stylo` all of the required packages are +discovered and installed. + +Those with a keen eye should notice that packages like :code:`hypothesis` and +:code:`pytest` are not typically installation requirements as they are testing +tools and only required by developers. Normally you would be right, however +:code:`stylo` does distribute a number of tests as part of the +:code:`stylo.testing` package as part of our extension guarantee. Since these +packages are required to import objects from this package we include them as +installation dependencies. + +Finally the :code:`python_requires` field specifies the minimum version that we +support. + +Miscellaneous Fields +^^^^^^^^^^^^^^^^^^^^ + +The :code:`setup-requires` and :code:`test_suite` fields are a holdover from +previous versions of :code:`stylo` where the tests were run using the command +:code:`python setup.py test`. I am not sure if they are required anymore. + +I am not sure what the :code:`zip_safe` and :code:`include_package_data` fields +are for. + +.. _MIT License: https://opensource.org/licenses/MIT From 61646ba87f4bd365fa3484eb8f4c9174e20ecf65 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Sat, 6 Oct 2018 21:00:30 +0100 Subject: [PATCH 39/40] Initial draft of code style and linting docs --- docs/contributing/index.rst | 1 + docs/contributing/reference/code-style.rst | 70 ++++++++++++++++++++++ docs/contributing/reference/index.rst | 1 + docs/glossary.rst | 5 ++ setup.py | 4 +- tox.ini | 2 + 6 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 docs/contributing/reference/code-style.rst diff --git a/docs/contributing/index.rst b/docs/contributing/index.rst index f53526ec..e5ab43da 100644 --- a/docs/contributing/index.rst +++ b/docs/contributing/index.rst @@ -29,6 +29,7 @@ Tell me more about .. - Tell me more about the :ref:`Documentation Build ` - Tell me more about the :ref:`Branching Policy ` +- Tell me more about the :ref:`contribute_ref_code_style` - Tell me more about the :ref:`Release Process ` - Tell me more about the :ref:`Setup.py file ` diff --git a/docs/contributing/reference/code-style.rst b/docs/contributing/reference/code-style.rst new file mode 100644 index 00000000..9a573abc --- /dev/null +++ b/docs/contributing/reference/code-style.rst @@ -0,0 +1,70 @@ +.. _contribute_ref_code_style: + +Code Style +========== + +In order for your code to be accepted into the library as well as any tests on +its functionality it also has to pass the :code:`lint` test task. + +What is Linting? +---------------- + +Linting is the term applied to a class of :term:`static analysis` tools +which look for stylistic errors (such as line lengths that are too long) and +sources of potential errors (you defined a variable called :code:`x` but didn't +use it). + +These tools won't catch everything since they don't run your code so subtle +errors will pass you by but obvious mistakes such as typos can be caught before +your code is even run. + +The Lint Test +------------- + +Our :code:`lint` tox task is defined as follows. + +.. literalinclude:: ../../../tox.ini + :start-after: # + :end-before: # + + +.. attention:: + + The box above is extracted from the current version of :code:`tox.ini`. If + what you read here doesn't match what is above then it is a sign that this + page is out of date and an issue should be raised. + +This subjects everyone's code to the following standard. + +- The automatic formatting tool `black`_ doesn't want to rewrite anything +- The linting tool `flake8`_ doesn't find any issues. + +Why Black? +^^^^^^^^^^ + +`black`_ is a tool that will rewrite your code so that it is formatted in a +certain way. We use this so that all code in the library is formatted in a +consistent way so is easier to read (at least that's the theory). + +It also has the added benefit of formatting your code in a way that will pass +most of :code:`flake8`'s checks automatically. + +Why Flake8? +^^^^^^^^^^^ + +In addition to ensuring that your code follows the :pep:`8` style guide +:code:`flake8` will check for a number of "obvious" errors e.g. +variable names that are not spelt correctly. So by passing its checks you can be +reasonably confident that your code is at least consistent, being a static +analysis tool it can't make any guarantees about the correctness of your code +though. + +When they don't get along +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Unfortunately there is an occasional edge case where :code:`black` and +:code:`flake8` don't get along. If you encounter one of these don't worry too +much about we'll work through it together and come up with a work around. + +.. _black: https://github.com/ambv/black +.. _flake8: http://flake8.pycqa.org/en/latest/ diff --git a/docs/contributing/reference/index.rst b/docs/contributing/reference/index.rst index 04e5a0f3..a8635182 100644 --- a/docs/contributing/reference/index.rst +++ b/docs/contributing/reference/index.rst @@ -8,6 +8,7 @@ Reference apidoc branching-policy + code-style documentation-build exampledoc release-process diff --git a/docs/glossary.rst b/docs/glossary.rst index 64703d25..f0df8c3a 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -52,6 +52,11 @@ Software Development `PyPi `_ is the Python Package Index. Any python package that you can :code:`pip install` is hosted here. + static analysis + Static analysis tools such as `flake8 `_ + are tools that try to detect errors in your code simply by reading the + source code. + tox `tox `_ is tool commonly found in Python projects that automates the process of running various tasks diff --git a/setup.py b/setup.py index 701457c0..c341429b 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ def readme(): "Programming Language :: Python :: 3 :: Only", "Topic :: Multimedia :: Graphics", ], - author="Alex, Carney", + author="Alex Carney", author_email="alcarneyme@gmail.com", license="MIT", packages=find_packages(".", exclude="tests"), @@ -34,9 +34,9 @@ def readme(): "pytest", "pytest-benchmark", ], + python_requires=">=3.5", setup_requires=["pytest-runner"], test_suite="tests", - python_requires=">=3.0", include_package_data=True, zip_safe=False, ) diff --git a/tox.ini b/tox.ini index f2b29049..03d7ffb3 100644 --- a/tox.ini +++ b/tox.ini @@ -10,6 +10,7 @@ deps = commands = pytest --cov=stylo --ignore=tests/examples/ -q {posargs} +# [testenv:lint] deps = flake8 @@ -19,6 +20,7 @@ commands = black --check tests flake8 stylo/ flake8 tests/ +# [testenv:docs-check] deps = From c2eecc5b3747d2a5e516ba6904b5e32d4a2f9e03 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Sun, 7 Oct 2018 12:52:30 +0100 Subject: [PATCH 40/40] Update changelog and bump version --- CHANGES.rst | 3 ++- stylo/_version.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 653541e6..05747840 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,4 +1,4 @@ -v0.5.1 [Unreleased] +v0.6.0 - 2018-10-07 ------------------- Added @@ -16,6 +16,7 @@ Contributors - Added new shape :code:`InvertedShape` which handles the inversion of a shape behind the scenes. - Tests for all the composite shapes and operators. +- More documentation on how to get involved Changed ^^^^^^^ diff --git a/stylo/_version.py b/stylo/_version.py index 3d187266..906d362f 100644 --- a/stylo/_version.py +++ b/stylo/_version.py @@ -1 +1 @@ -__version__ = "0.5.0" +__version__ = "0.6.0"