From 820dc4d476c87efc13cbcb1ce167ebd3bb91c427 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Sat, 23 Mar 2019 14:12:13 -0400 Subject: [PATCH 01/70] Run sphinx-quickstart --- docs/.gitignore | 1 + docs/Makefile | 19 +++++ docs/conf.py | 179 ++++++++++++++++++++++++++++++++++++++++++++++++ docs/index.rst | 20 ++++++ docs/make.bat | 35 ++++++++++ 5 files changed, 254 insertions(+) create mode 100644 docs/.gitignore create mode 100644 docs/Makefile create mode 100644 docs/conf.py create mode 100644 docs/index.rst create mode 100644 docs/make.bat diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 00000000..ba65b13a --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1 @@ +/_build/ diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..298ea9e2 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,19 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 00000000..66d94d92 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +# +# Configuration file for the Sphinx documentation builder. +# +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/master/config + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'ppb-vector' +copyright = '2019, Piper Thunstrom, Jamie Bliss' +author = 'Piper Thunstrom, Jamie Bliss' + +# The short X.Y version +version = '' +# The full version, including alpha/beta/rc tags +release = '' + + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.mathjax', + 'sphinx.ext.viewcode', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = None + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', +# 'searchbox.html']``. +# +# html_sidebars = {} + + +# -- Options for HTMLHelp output --------------------------------------------- + +# Output file base name for HTML help builder. +htmlhelp_basename = 'ppb-vectordoc' + + +# -- Options for LaTeX output ------------------------------------------------ + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'ppb-vector.tex', 'ppb-vector Documentation', + 'Piper Thunstrom, Jamie Bliss', 'manual'), +] + + +# -- Options for manual page output ------------------------------------------ + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'ppb-vector', 'ppb-vector Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ---------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'ppb-vector', 'ppb-vector Documentation', + author, 'ppb-vector', 'One line description of project.', + 'Miscellaneous'), +] + + +# -- Options for Epub output ------------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = project + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +# +# epub_identifier = '' + +# A unique identification for the text. +# +# epub_uid = '' + +# A list of files that should not be packed into the epub file. +epub_exclude_files = ['search.html'] + + +# -- Extension configuration ------------------------------------------------- diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 00000000..0de89a00 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,20 @@ +.. ppb-vector documentation master file, created by + sphinx-quickstart on Sat Mar 23 14:10:03 2019. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to ppb-vector's documentation! +====================================== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 00000000..7893348a --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% + +:end +popd From a866e64f798d739b50ad38cc77286dddf9c73d82 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 19 Jan 2019 19:41:44 +0100 Subject: [PATCH 02/70] README: Miscellaneous improvements in API description --- README.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index dc597138..5185887b 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ Also iterable for translation between Vector2 and other sequence types. ## Mathematical operators -In addition to `Vector2`, operators also accepts, as second operand, +In addition to `Vector2`s, operators also accept, as second operand, vector-like objects such as `tuple`, `list`, and `dict`. >>> Vector2(1, 1) + [1, 3] @@ -114,7 +114,8 @@ Multiply a `Vector2` by another `Vector2` to get the dot product. ### Negation -Negating a `Vector2` is equivalent to multiplying it by -1. +Negating a `Vector2` produces one with identical length and opposite +direction. It is equivalent to multiplying it by -1. >>> -Vector2(1, 1) Vector2(-1.0, -1.0) @@ -155,7 +156,7 @@ Positive rotation is counter/anti-clockwise. ### angle(vector) -Compute the angle between two vectors, expressed as a scalar in degrees. +Compute the angle between two vectors, expressed in degrees. >>> Vector2(1, 0).angle( (0, 1) ) 90.0 @@ -174,7 +175,7 @@ Return a vector with the same direction, and unit length. ### scale(scalar) -Scale given `Vector2` to a given length. +Scale a given `Vector2` to a certain length. >>> Vector2(7, 24).scale(2) Vector2(0.56, 1.92) @@ -193,8 +194,10 @@ Scale a given `Vector2` down to a given length, if it is larger. >>> Vector2(7, 24).truncate(3) Vector2(0.84, 2.88) -Note that `Vector2.scale` is equivalent to `Vector2.truncate` when `scalar` is -less than length. +It produces a vector with the same direction, but possibly a different length. + +Note that `vector.scale(max_length)` is equivalent to +`vector.truncate(max_length)` when `max_length < vector.length`. >>> Vector2(3, 4).scale(4) Vector2(2.4, 3.2) @@ -211,7 +214,8 @@ Note: `x.truncate(max_length)` may sometimes be slightly-larger than ### reflect(surface_normal) -Reflect a `Vector2` based on a given surface normal. +Compute the reflection of a `Vector2` on a surface going through the origin, +described by its normal vector. >>> Vector2(5, 3).reflect( (-1, 0) ) Vector2(-5.0, 3.0) From c8ecf0c85f3afa2ea91d6c594e57a8f384cf3e7f Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 19 Jan 2019 19:53:52 +0100 Subject: [PATCH 03/70] Start moving API documentation from README to docstrings --- README.md | 109 ------------------------------------------ ppb_vector/vector2.py | 103 +++++++++++++++++++++++++++++++++++++-- test.sh | 2 +- 3 files changed, 100 insertions(+), 114 deletions(-) diff --git a/README.md b/README.md index 5185887b..f831e82e 100644 --- a/README.md +++ b/README.md @@ -64,23 +64,6 @@ vector-like objects such as `tuple`, `list`, and `dict`. Vector2(4.0, 6.0) -### Addition - - >>> Vector2(1, 0) + (0, 1) - Vector2(1.0, 1.0) - -### Subtraction - - >>> Vector2(3, 3) - (1, 1) - Vector2(2.0, 2.0) - -### Equality - -Vectors are equal if their coordinates are equal. - - >>> Vector2(1, 0) == (0, 1) - False - ### Scalar Multiplication Multiply a `Vector2` by a scalar to get a scaled `Vector2`: @@ -107,20 +90,6 @@ Multiply a `Vector2` by another `Vector2` to get the dot product. >>> Vector2(1, 1) * (-1, -1) -2.0 -### Vector Length - - >>> Vector2(45, 60).length - 75.0 - -### Negation - -Negating a `Vector2` produces one with identical length and opposite -direction. It is equivalent to multiplying it by -1. - - >>> -Vector2(1, 1) - Vector2(-1.0, -1.0) - - ## Methods Useful functions for game development. @@ -144,81 +113,3 @@ Perform an approximate comparison of two vectors. `rel_tol`) is compared to the length of the difference vector. By default, `abs_tol = 1e-3`, `rel_tol = 1e-6`, and `rel_to = []`. - -### rotate(deg) - -Rotate a vector in relation to its own origin and return a new `Vector2`. - - >>> Vector2(1, 0).rotate(90) - Vector2(0.0, 1.0) - -Positive rotation is counter/anti-clockwise. - -### angle(vector) - -Compute the angle between two vectors, expressed in degrees. - - >>> Vector2(1, 0).angle( (0, 1) ) - 90.0 - -As with `rotate()`, angles are signed, and refer to a direct coordinate system -(i.e. positive rotations are counter-clockwise). - -`Vector2.angle` is guaranteed to produce an angle between -180° and 180°. - -### normalize() - -Return a vector with the same direction, and unit length. - - >>> Vector2(3, 4).normalize() - Vector2(0.6, 0.8) - -### scale(scalar) - -Scale a given `Vector2` to a certain length. - - >>> Vector2(7, 24).scale(2) - Vector2(0.56, 1.92) - -Note that `Vector2.normalize()` is equivalent to `Vector2.scale(1)`. - - >>> Vector2(7, 24).normalize() - Vector2(0.28, 0.96) - >>> Vector2(7, 24).scale(1) - Vector2(0.28, 0.96) - -### truncate(scalar) - -Scale a given `Vector2` down to a given length, if it is larger. - - >>> Vector2(7, 24).truncate(3) - Vector2(0.84, 2.88) - -It produces a vector with the same direction, but possibly a different length. - -Note that `vector.scale(max_length)` is equivalent to -`vector.truncate(max_length)` when `max_length < vector.length`. - - >>> Vector2(3, 4).scale(4) - Vector2(2.4, 3.2) - >>> Vector2(3, 4).truncate(4) - Vector2(2.4, 3.2) - - >>> Vector2(3, 4).scale(6) - Vector2(3.6, 4.8) - >>> Vector2(3, 4).truncate(6) - Vector2(3.0, 4.0) - -Note: `x.truncate(max_length)` may sometimes be slightly-larger than - `max_length`, due to floating-point rounding effects. - -### reflect(surface_normal) - -Compute the reflection of a `Vector2` on a surface going through the origin, -described by its normal vector. - - >>> Vector2(5, 3).reflect( (-1, 0) ) - Vector2(-5.0, 3.0) - - >>> Vector2(5, 3).reflect( Vector2(-1, -2).normalize() ) - Vector2(0.5999999999999996, -5.800000000000001) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index b77cd30e..1fa4571c 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -117,6 +117,11 @@ def convert(cls: typing.Type[VectorOrSub], value: VectorLike) -> VectorOrSub: @property def length(self) -> float: + """Compute the length of a vector. + + >>> Vector2(45, 60).length + 75.0 + """ # Surprisingly, caching this value provides no descernable performance # benefit, according to microbenchmarks. return hypot(self.x, self.y) @@ -128,6 +133,11 @@ def __len__(self: VectorOrSub) -> int: return 2 def __add__(self: VectorOrSub, other: VectorLike) -> VectorOrSub: + """Add two vectors. + + >>> Vector2(1, 0) + (0, 1) + Vector2(1.0, 1.0) + """ rtype = _find_lowest_vector(type(other), type(self)) try: other = Vector2.convert(other) @@ -136,6 +146,11 @@ def __add__(self: VectorOrSub, other: VectorLike) -> VectorOrSub: return rtype(self.x + other.x, self.y + other.y) def __sub__(self: VectorOrSub, other: VectorLike) -> VectorOrSub: + """Subtract one vector from another. + + >>> Vector2(3, 3) - (1, 1) + Vector2(2.0, 2.0) + """ rtype = _find_lowest_vector(type(other), type(self)) try: other = Vector2.convert(other) @@ -213,6 +228,13 @@ def __repr__(self: VectorOrSub) -> str: return f"{type(self).__name__}({self.x}, {self.y})" def __eq__(self: VectorOrSub, other: typing.Any) -> bool: + """Test wheter two vectors are equal. + + Vectors are equal if their coordinates are equal. + + >>> Vector2(1, 0) == (0, 1) + False + """ try: other = Vector2.convert(other) except (TypeError, ValueError): @@ -225,9 +247,27 @@ def __iter__(self: VectorOrSub) -> typing.Iterator[float]: yield self.y def __neg__(self: VectorOrSub) -> VectorOrSub: + """Negate a vector. + + Negating a `Vector2` produces one with identical length and opposite + direction. It is equivalent to multiplying it by -1. + + >>> -Vector2(1, 1) + Vector2(-1.0, -1.0) + """ return self.scale_by(-1) def angle(self: VectorOrSub, other: VectorLike) -> float: + """Compute the angle between two vectors, expressed in degrees. + + >>> Vector2(1, 0).angle( (0, 1) ) + 90.0 + + As with `rotate()`, angles are signed, and refer to a direct coordinate + system (i.e. positive rotations are counter-clockwise). + + `Vector2.angle` is guaranteed to produce an angle between -180° and 180°. + """ other = Vector2.convert(other) rv = degrees(atan2(other.x, -other.y) - atan2(self.x, -self.y)) @@ -294,6 +334,15 @@ def _trig(angle: typing.SupportsFloat) -> typing.Tuple[float, float]: return r_cos, r_sin def rotate(self: VectorOrSub, angle: typing.SupportsFloat) -> VectorOrSub: + """Rotate a vector. + + Rotate a vector in relation to the origin and return a new `Vector2`. + + >>> Vector2(1, 0).rotate(90) + Vector2(0.0, 1.0) + + Positive rotation is counter/anti-clockwise. + """ r_cos, r_sin = Vector2._trig(angle) x = self.x * r_cos - self.y * r_sin @@ -301,9 +350,40 @@ def rotate(self: VectorOrSub, angle: typing.SupportsFloat) -> VectorOrSub: return type(self)(x, y) def normalize(self: VectorOrSub) -> VectorOrSub: + """Return a vector with the same direction, and unit length. + + >>> Vector2(3, 4).normalize() + Vector2(0.6, 0.8) + + Note that `Vector2.normalize()` is equivalent to `Vector2.scale(1)`. + """ return self.scale(1) def truncate(self: VectorOrSub, max_length: typing.SupportsFloat) -> VectorOrSub: + """Scale a given `Vector2` down to a given length, if it is larger. + + >>> Vector2(7, 24).truncate(3) + Vector2(0.84, 2.88) + + It produces a vector with the same direction, but possibly a different + length. + + Note that `vector.scale(max_length)` is equivalent to + `vector.truncate(max_length)` when `max_length < vector.length`. + + >>> Vector2(3, 4).scale(4) + Vector2(2.4, 3.2) + >>> Vector2(3, 4).truncate(4) + Vector2(2.4, 3.2) + + >>> Vector2(3, 4).scale(6) + Vector2(3.6, 4.8) + >>> Vector2(3, 4).truncate(6) + Vector2(3.0, 4.0) + + Note: `x.truncate(max_length)` may sometimes be slightly-larger than + `max_length`, due to floating-point rounding effects. + """ max_length = float(max_length) if self.length <= max_length: return self @@ -311,8 +391,15 @@ def truncate(self: VectorOrSub, max_length: typing.SupportsFloat) -> VectorOrSub return self.scale_to(max_length) def scale_to(self: VectorOrSub, length: typing.SupportsFloat) -> VectorOrSub: - """ - Scale the vector to the given length + """Scale a given `Vector2` to a certain length. + + >>> Vector2(7, 24).scale(2) + Vector2(0.56, 1.92) + + >>> Vector2(7, 24).normalize() + Vector2(0.28, 0.96) + >>> Vector2(7, 24).scale(1) + Vector2(0.28, 0.96) """ length = float(length) if length < 0: @@ -326,8 +413,16 @@ def scale_to(self: VectorOrSub, length: typing.SupportsFloat) -> VectorOrSub: scale = scale_to def reflect(self: VectorOrSub, surface_normal: VectorLike) -> VectorOrSub: - """ - Calculate the reflection of the vector against a given surface normal + """Reflect a vector against a surface. + + Compute the reflection of a `Vector2` on a surface going through the + origin, described by its normal vector. + + >>> Vector2(5, 3).reflect( (-1, 0) ) + Vector2(-5.0, 3.0) + + >>> Vector2(5, 3).reflect( Vector2(-1, -2).normalize() ) + Vector2(0.5999999999999996, -5.800000000000001) """ surface_normal = Vector2.convert(surface_normal) if not isclose(surface_normal.length, 1): diff --git a/test.sh b/test.sh index b7cd0700..f3340ded 100755 --- a/test.sh +++ b/test.sh @@ -10,5 +10,5 @@ else fi -run ${PY} -m doctest README.md +run ${PY} -m doctest README.md ppb_vector/vector2.py run ${PY} -m pytest "${PYTEST_OPTIONS[@]}" From da864828bd514f91de4c60d58fdf17eda0ec185d Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 19 Jan 2019 21:17:25 +0100 Subject: [PATCH 04/70] README: Slight improvement --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f831e82e..9b2b63e4 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # ppb-vector -The 2D Vector Class for the PursuedPyBear project. +The immutable, 2D vector class for the PursuedPyBear project. + +`Vector2` implements many convenience features, as well as +useful mathematical operations for 2D geometry. ## Install @@ -17,8 +20,6 @@ pip install 'ppb-vector' >>> Vector2(3, 4) Vector2(3.0, 4.0) -`Vector2` implements many convenience features, as well as -useful mathematical operations for 2D geometry and linear algebra. ## Convenience functions From 05158516833823751cb2f2fc31592ae892c625e1 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 19 Jan 2019 21:19:53 +0100 Subject: [PATCH 05/70] Vector2: Add a class docstring --- ppb_vector/vector2.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index 1fa4571c..3dfd41b3 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -51,6 +51,25 @@ def _find_lowest_vector(left: typing.Type, right: typing.Type) -> typing.Type: @dataclass(eq=False, frozen=True, init=False, repr=False) class Vector2: + """The immutable, 2D vector class of the PursuedPyBear project. + + `Vector2` is an immutable 2D Vector, which can be instantiated as expected: + + >>> from ppb_vector import Vector2 + >>> Vector2(3, 4) + Vector2(3.0, 4.0) + + `Vector2` implements many convenience features, as well as + useful mathematical operations for 2D geometry and linear algebra. + + ## Installation + + `Vector2` is part of the `ppb-vector` package; if you use pip, install using + + ```bash + pip install 'ppb-vector' + ``` + """ x: float y: float From b8dd9054693c93ad7e9b9fbe4fa70ed9bd29795a Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 19 Jan 2019 21:20:38 +0100 Subject: [PATCH 06/70] Vector2.convert: Improve docstring --- ppb_vector/vector2.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index 3dfd41b3..b4432f0d 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -118,8 +118,15 @@ def __init__(self, *args, **kwargs): @classmethod def convert(cls: typing.Type[VectorOrSub], value: VectorLike) -> VectorOrSub: - """ - Constructs a vector from a vector-like. Does not perform a copy. + """Constructs a vector from a vector-like. + + A vector-like can be: + + - a length-2 `Sequence`, whose contents are interpreted as the `x` and `y` coordinates; + - a length-2 `Mapping`, whose keys are `x` and `y`; + - or any instance of `Vector2` (or its subclasses). + + `convert` does not perform a copy when `value` already has the right type. """ # Use Vector2.convert() instead of type(self).convert() so that # _find_lowest_vector() can resolve things well. From f24a6cb144d953eec715574ea3433f763a849d22 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Sat, 23 Mar 2019 14:35:11 -0400 Subject: [PATCH 07/70] Use RTD theme --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 66d94d92..9a7f3e6c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -77,7 +77,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'alabaster' +html_theme = 'sphinx_rtd_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the From 7de90f5ba92ba569308bd823ebab615265f59f38 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Sat, 23 Mar 2019 14:46:46 -0400 Subject: [PATCH 08/70] Add docs requirements --- docs-requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs-requirements.txt diff --git a/docs-requirements.txt b/docs-requirements.txt new file mode 100644 index 00000000..6966869c --- /dev/null +++ b/docs-requirements.txt @@ -0,0 +1 @@ +sphinx From cb0b0b68e9448e35d9f373180ff10c2368c82ede Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 19:54:29 +0100 Subject: [PATCH 09/70] docs: Generate docs for Vector2 using autoclass Also, remove the useless Table of Contents --- docs/index.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 0de89a00..a170570b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -6,10 +6,8 @@ Welcome to ppb-vector's documentation! ====================================== -.. toctree:: - :maxdepth: 2 - :caption: Contents: - +.. autoclass:: ppb_vector.Vector2 + :members: Indices and tables From 131d34b8c7529f098107081fdbf90a533bfdbd7e Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 19:55:11 +0100 Subject: [PATCH 10/70] Vector2: Remove installation instructions from the class docstring --- ppb_vector/vector2.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index b4432f0d..32525e63 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -61,14 +61,6 @@ class Vector2: `Vector2` implements many convenience features, as well as useful mathematical operations for 2D geometry and linear algebra. - - ## Installation - - `Vector2` is part of the `ppb-vector` package; if you use pip, install using - - ```bash - pip install 'ppb-vector' - ``` """ x: float y: float From 9c78c0fff613b872a3f3513c04a683f21ae0a5f2 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 20:07:41 +0100 Subject: [PATCH 11/70] Vector2: Start converting docstrings to rst markup --- ppb_vector/vector2.py | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index 32525e63..ae5ad106 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -53,14 +53,16 @@ def _find_lowest_vector(left: typing.Type, right: typing.Type) -> typing.Type: class Vector2: """The immutable, 2D vector class of the PursuedPyBear project. - `Vector2` is an immutable 2D Vector, which can be instantiated as expected: + :py:class:`Vector2` is an immutable 2D Vector, which can be instantiated as + expected: >>> from ppb_vector import Vector2 >>> Vector2(3, 4) Vector2(3.0, 4.0) - `Vector2` implements many convenience features, as well as + :py:class:`Vector2` implements many convenience features, as well as useful mathematical operations for 2D geometry and linear algebra. + """ x: float y: float @@ -114,11 +116,12 @@ def convert(cls: typing.Type[VectorOrSub], value: VectorLike) -> VectorOrSub: A vector-like can be: - - a length-2 `Sequence`, whose contents are interpreted as the `x` and `y` coordinates; - - a length-2 `Mapping`, whose keys are `x` and `y`; - - or any instance of `Vector2` (or its subclasses). + - a length-2 :py:class:`Sequence`, whose contents are interpreted as + the `x` and `y` coordinates; + - a length-2 :py:class:`Mapping`, whose keys are `x` and `y`; + - or any instance of :py:class:`Vector2` (or its subclasses). - `convert` does not perform a copy when `value` already has the right type. + :py:meth:`convert` does not perform a copy when `value` already has the right type. """ # Use Vector2.convert() instead of type(self).convert() so that # _find_lowest_vector() can resolve things well. @@ -267,7 +270,7 @@ def __iter__(self: VectorOrSub) -> typing.Iterator[float]: def __neg__(self: VectorOrSub) -> VectorOrSub: """Negate a vector. - Negating a `Vector2` produces one with identical length and opposite + Negating a :py:class:`Vector2` produces one with identical length and opposite direction. It is equivalent to multiplying it by -1. >>> -Vector2(1, 1) @@ -281,10 +284,10 @@ def angle(self: VectorOrSub, other: VectorLike) -> float: >>> Vector2(1, 0).angle( (0, 1) ) 90.0 - As with `rotate()`, angles are signed, and refer to a direct coordinate - system (i.e. positive rotations are counter-clockwise). + As with :py:meth:`rotate`, angles are signed, and refer to a direct + coordinate system (i.e. positive rotations are counter-clockwise). - `Vector2.angle` is guaranteed to produce an angle between -180° and 180°. + :py:meth:`angle` is guaranteed to produce an angle between -180° and 180°. """ other = Vector2.convert(other) @@ -354,7 +357,7 @@ def _trig(angle: typing.SupportsFloat) -> typing.Tuple[float, float]: def rotate(self: VectorOrSub, angle: typing.SupportsFloat) -> VectorOrSub: """Rotate a vector. - Rotate a vector in relation to the origin and return a new `Vector2`. + Rotate a vector in relation to the origin and return a new :py:class:`Vector2`. >>> Vector2(1, 0).rotate(90) Vector2(0.0, 1.0) @@ -378,7 +381,7 @@ def normalize(self: VectorOrSub) -> VectorOrSub: return self.scale(1) def truncate(self: VectorOrSub, max_length: typing.SupportsFloat) -> VectorOrSub: - """Scale a given `Vector2` down to a given length, if it is larger. + """Scale a given :py:class:`Vector2` down to a given length, if it is larger. >>> Vector2(7, 24).truncate(3) Vector2(0.84, 2.88) @@ -409,7 +412,7 @@ def truncate(self: VectorOrSub, max_length: typing.SupportsFloat) -> VectorOrSub return self.scale_to(max_length) def scale_to(self: VectorOrSub, length: typing.SupportsFloat) -> VectorOrSub: - """Scale a given `Vector2` to a certain length. + """Scale a given :py:class:`Vector2` to a certain length. >>> Vector2(7, 24).scale(2) Vector2(0.56, 1.92) @@ -433,7 +436,7 @@ def scale_to(self: VectorOrSub, length: typing.SupportsFloat) -> VectorOrSub: def reflect(self: VectorOrSub, surface_normal: VectorLike) -> VectorOrSub: """Reflect a vector against a surface. - Compute the reflection of a `Vector2` on a surface going through the + Compute the reflection of a :py:class:`Vector2` on a surface going through the origin, described by its normal vector. >>> Vector2(5, 3).reflect( (-1, 0) ) From 54ecf230f9c277a1f8305fd1d98490705460033a Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Sat, 23 Mar 2019 15:07:52 -0400 Subject: [PATCH 12/70] Add intersphinx to core python docs --- docs/conf.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/conf.py b/docs/conf.py index 9a7f3e6c..e260ec73 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -42,6 +42,7 @@ 'sphinx.ext.autodoc', 'sphinx.ext.mathjax', 'sphinx.ext.viewcode', + 'sphinx.ext.intersphinx', ] # Add any paths that contain templates here, relative to this directory. @@ -72,6 +73,10 @@ pygments_style = None +intersphinx_mapping = { + 'python': ('https://docs.python.org/3', None), +} + # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for From c60537c28776e9859b6543f7e443a90492b034d7 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Sat, 23 Mar 2019 15:08:55 -0400 Subject: [PATCH 13/70] Add sphinx_autodoc_annotation --- docs-requirements.txt | 1 + docs/conf.py | 1 + 2 files changed, 2 insertions(+) diff --git a/docs-requirements.txt b/docs-requirements.txt index 6966869c..483e5b6f 100644 --- a/docs-requirements.txt +++ b/docs-requirements.txt @@ -1 +1,2 @@ sphinx +sphinx-autodoc-annotation diff --git a/docs/conf.py b/docs/conf.py index e260ec73..9b5ffab2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -43,6 +43,7 @@ 'sphinx.ext.mathjax', 'sphinx.ext.viewcode', 'sphinx.ext.intersphinx', + 'sphinx_autodoc_annotation', ] # Add any paths that contain templates here, relative to this directory. From 8856b7b2cd7bbf5e3c1ea5ca2e970cc1584b2884 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 20:13:26 +0100 Subject: [PATCH 14/70] docs: Add missing dependency on sphinx_rtd_theme --- docs-requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs-requirements.txt b/docs-requirements.txt index 483e5b6f..f1b2b6a6 100644 --- a/docs-requirements.txt +++ b/docs-requirements.txt @@ -1,2 +1,3 @@ sphinx sphinx-autodoc-annotation +sphinx_rtd_theme From 0e9b47f2fca700ffed1eecc2d7e846bfa4e03714 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 20:36:52 +0100 Subject: [PATCH 15/70] Vector2: Add markup for references in the docstrings --- ppb_vector/vector2.py | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index ae5ad106..72002c10 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -304,22 +304,21 @@ def angle(self: VectorOrSub, other: VectorLike) -> float: def isclose(self: VectorOrSub, other: VectorLike, *, abs_tol: typing.SupportsFloat = 1e-09, rel_tol: typing.SupportsFloat = 1e-09, rel_to: typing.Sequence[VectorLike] = ()) -> bool: - """ - Determine whether two vectors are close in value. + """Determine whether two vectors are close in value. + + :param rel_tol: maximum difference for being considered "close", + relative to the magnitude of the input values - rel_tol - maximum difference for being considered "close", relative to the - magnitude of the input values - rel_to - additional input values to consider in rel_tol - abs_tol - maximum difference for being considered "close", regardless of the - magnitude of the input values + :param rel_to: additional input values to consider in rel_tol - Return True if self is close in value to other, and False otherwise. + :param abs_tol: maximum difference for being considered "close", + regardless of the magnitude of the input values + + Return True if `self` is close in value to `other`, and False otherwise. For the values to be considered close, the difference between them must be smaller than at least one of the tolerances. + """ abs_tol, rel_tol = float(abs_tol), float(rel_tol) if abs_tol < 0 or rel_tol < 0: @@ -376,7 +375,7 @@ def normalize(self: VectorOrSub) -> VectorOrSub: >>> Vector2(3, 4).normalize() Vector2(0.6, 0.8) - Note that `Vector2.normalize()` is equivalent to `Vector2.scale(1)`. + Note that :py:meth:`normalize()` is equivalent to :py:meth:`scale(1) `. """ return self.scale(1) @@ -389,8 +388,9 @@ def truncate(self: VectorOrSub, max_length: typing.SupportsFloat) -> VectorOrSub It produces a vector with the same direction, but possibly a different length. - Note that `vector.scale(max_length)` is equivalent to - `vector.truncate(max_length)` when `max_length < vector.length`. + Note that :py:meth:`vector.scale(max_length) ` is equivalent to + :py:meth:`vector.truncate(max_length) ` when + :py:meth:`max_length \< vector.length `. >>> Vector2(3, 4).scale(4) Vector2(2.4, 3.2) @@ -402,8 +402,9 @@ def truncate(self: VectorOrSub, max_length: typing.SupportsFloat) -> VectorOrSub >>> Vector2(3, 4).truncate(6) Vector2(3.0, 4.0) - Note: `x.truncate(max_length)` may sometimes be slightly-larger than - `max_length`, due to floating-point rounding effects. + Note: :py:meth:`x.truncate(max_length) ` may sometimes be + slightly-larger than `max_length`, due to floating-point rounding + effects. """ max_length = float(max_length) if self.length <= max_length: @@ -431,6 +432,7 @@ def scale_to(self: VectorOrSub, length: typing.SupportsFloat) -> VectorOrSub: return (length * self) / self.length + # TODO: Don't repeat in the documentation scale = scale_to def reflect(self: VectorOrSub, surface_normal: VectorLike) -> VectorOrSub: From 14cb33f33d8b11634355f495c6e9c14189b21768 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Sat, 23 Mar 2019 16:07:15 -0400 Subject: [PATCH 16/70] docs: Vector2: Add special members, because operators are pretty important to this type --- docs/index.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/index.rst b/docs/index.rst index a170570b..24fbb3eb 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -8,6 +8,8 @@ Welcome to ppb-vector's documentation! .. autoclass:: ppb_vector.Vector2 :members: + :special-members: + :exclude-members: __weakref__, __init__ Indices and tables From da9fff0afa249df2001269025be3831692eb72f7 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Sat, 23 Mar 2019 16:08:55 -0400 Subject: [PATCH 17/70] Better docs for Vector2.update --- ppb_vector/vector2.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index 72002c10..07a6ee13 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -108,6 +108,7 @@ def __init__(self, *args, **kwargs): except ValueError: raise TypeError(f"{type(y).__name__} object not convertable to float") + #: Return a new :py:class:`Vector2` replacing specified fields with new values. update = dataclasses.replace @classmethod From 01360754af5802e554acf8d14b2f9c1601eabeef Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 20:47:55 +0100 Subject: [PATCH 18/70] Rename the VectorOrSub type variable to Vector --- ppb_vector/vector2.py | 50 +++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index 07a6ee13..a973d4d5 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -9,11 +9,11 @@ # Vector or subclass -VectorOrSub = typing.TypeVar('VectorOrSub', bound='Vector2') +Vector = typing.TypeVar('Vector', bound='Vector2') # Anything convertable to a Vector, including lists, tuples, and dicts VectorLike = typing.Union[ - 'Vector2', # Or subclasses, unconnected to the VectorOrSub typevar above + 'Vector2', # Or subclasses, unconnected to the Vector typevar above typing.Tuple[typing.SupportsFloat, typing.SupportsFloat], typing.Sequence[typing.SupportsFloat], # TODO: Length 2 typing.Mapping[str, typing.SupportsFloat], # TODO: Length 2, keys 'x', 'y' @@ -112,7 +112,7 @@ def __init__(self, *args, **kwargs): update = dataclasses.replace @classmethod - def convert(cls: typing.Type[VectorOrSub], value: VectorLike) -> VectorOrSub: + def convert(cls: typing.Type[Vector], value: VectorLike) -> Vector: """Constructs a vector from a vector-like. A vector-like can be: @@ -151,10 +151,10 @@ def length(self) -> float: def asdict(self) -> typing.Mapping[str, float]: return {'x': self.x, 'y': self.y} - def __len__(self: VectorOrSub) -> int: + def __len__(self: Vector) -> int: return 2 - def __add__(self: VectorOrSub, other: VectorLike) -> VectorOrSub: + def __add__(self: Vector, other: VectorLike) -> Vector: """Add two vectors. >>> Vector2(1, 0) + (0, 1) @@ -167,7 +167,7 @@ def __add__(self: VectorOrSub, other: VectorLike) -> VectorOrSub: return NotImplemented return rtype(self.x + other.x, self.y + other.y) - def __sub__(self: VectorOrSub, other: VectorLike) -> VectorOrSub: + def __sub__(self: Vector, other: VectorLike) -> Vector: """Subtract one vector from another. >>> Vector2(3, 3) - (1, 1) @@ -180,14 +180,14 @@ def __sub__(self: VectorOrSub, other: VectorLike) -> VectorOrSub: return NotImplemented return rtype(self.x - other.x, self.y - other.y) - def dot(self: VectorOrSub, other: VectorLike) -> float: + def dot(self: Vector, other: VectorLike) -> float: """ Return the dot product of two vectors. """ other = Vector2.convert(other) return self.x * other.x + self.y * other.y - def scale_by(self: VectorOrSub, other: typing.SupportsFloat) -> VectorOrSub: + def scale_by(self: Vector, other: typing.SupportsFloat) -> Vector: """ Scale by the given amount. """ @@ -195,10 +195,10 @@ def scale_by(self: VectorOrSub, other: typing.SupportsFloat) -> VectorOrSub: return type(self)(self.x * other, self.y * other) @typing.overload - def __mul__(self: VectorOrSub, other: VectorLike) -> float: pass + def __mul__(self: Vector, other: VectorLike) -> float: pass @typing.overload - def __mul__(self: VectorOrSub, other: typing.SupportsFloat) -> VectorOrSub: pass + def __mul__(self: Vector, other: typing.SupportsFloat) -> Vector: pass def __mul__(self, other): """ @@ -213,20 +213,20 @@ def __mul__(self, other): return NotImplemented @typing.overload - def __rmul__(self: VectorOrSub, other: VectorLike) -> float: pass + def __rmul__(self: Vector, other: VectorLike) -> float: pass @typing.overload - def __rmul__(self: VectorOrSub, other: typing.SupportsFloat) -> VectorOrSub: pass + def __rmul__(self: Vector, other: typing.SupportsFloat) -> Vector: pass def __rmul__(self, other): return self.__mul__(other) - def __truediv__(self: VectorOrSub, other: typing.SupportsFloat) -> VectorOrSub: + def __truediv__(self: Vector, other: typing.SupportsFloat) -> Vector: """Perform a division between a vector and a scalar.""" other = float(other) return type(self)(self.x / other, self.y / other) - def __getitem__(self: VectorOrSub, item: typing.Union[str, int]) -> float: + def __getitem__(self: Vector, item: typing.Union[str, int]) -> float: if hasattr(item, '__index__'): item = item.__index__() # type: ignore if isinstance(item, str): @@ -246,10 +246,10 @@ def __getitem__(self: VectorOrSub, item: typing.Union[str, int]) -> float: else: raise TypeError - def __repr__(self: VectorOrSub) -> str: + def __repr__(self: Vector) -> str: return f"{type(self).__name__}({self.x}, {self.y})" - def __eq__(self: VectorOrSub, other: typing.Any) -> bool: + def __eq__(self: Vector, other: typing.Any) -> bool: """Test wheter two vectors are equal. Vectors are equal if their coordinates are equal. @@ -264,11 +264,11 @@ def __eq__(self: VectorOrSub, other: typing.Any) -> bool: else: return self.x == other.x and self.y == other.y - def __iter__(self: VectorOrSub) -> typing.Iterator[float]: + def __iter__(self: Vector) -> typing.Iterator[float]: yield self.x yield self.y - def __neg__(self: VectorOrSub) -> VectorOrSub: + def __neg__(self: Vector) -> Vector: """Negate a vector. Negating a :py:class:`Vector2` produces one with identical length and opposite @@ -279,7 +279,7 @@ def __neg__(self: VectorOrSub) -> VectorOrSub: """ return self.scale_by(-1) - def angle(self: VectorOrSub, other: VectorLike) -> float: + def angle(self: Vector, other: VectorLike) -> float: """Compute the angle between two vectors, expressed in degrees. >>> Vector2(1, 0).angle( (0, 1) ) @@ -302,7 +302,7 @@ def angle(self: VectorOrSub, other: VectorLike) -> float: return rv - def isclose(self: VectorOrSub, other: VectorLike, *, + def isclose(self: Vector, other: VectorLike, *, abs_tol: typing.SupportsFloat = 1e-09, rel_tol: typing.SupportsFloat = 1e-09, rel_to: typing.Sequence[VectorLike] = ()) -> bool: """Determine whether two vectors are close in value. @@ -354,7 +354,7 @@ def _trig(angle: typing.SupportsFloat) -> typing.Tuple[float, float]: return r_cos, r_sin - def rotate(self: VectorOrSub, angle: typing.SupportsFloat) -> VectorOrSub: + def rotate(self: Vector, angle: typing.SupportsFloat) -> Vector: """Rotate a vector. Rotate a vector in relation to the origin and return a new :py:class:`Vector2`. @@ -370,7 +370,7 @@ def rotate(self: VectorOrSub, angle: typing.SupportsFloat) -> VectorOrSub: y = self.x * r_sin + self.y * r_cos return type(self)(x, y) - def normalize(self: VectorOrSub) -> VectorOrSub: + def normalize(self: Vector) -> Vector: """Return a vector with the same direction, and unit length. >>> Vector2(3, 4).normalize() @@ -380,7 +380,7 @@ def normalize(self: VectorOrSub) -> VectorOrSub: """ return self.scale(1) - def truncate(self: VectorOrSub, max_length: typing.SupportsFloat) -> VectorOrSub: + def truncate(self: Vector, max_length: typing.SupportsFloat) -> Vector: """Scale a given :py:class:`Vector2` down to a given length, if it is larger. >>> Vector2(7, 24).truncate(3) @@ -413,7 +413,7 @@ def truncate(self: VectorOrSub, max_length: typing.SupportsFloat) -> VectorOrSub return self.scale_to(max_length) - def scale_to(self: VectorOrSub, length: typing.SupportsFloat) -> VectorOrSub: + def scale_to(self: Vector, length: typing.SupportsFloat) -> Vector: """Scale a given :py:class:`Vector2` to a certain length. >>> Vector2(7, 24).scale(2) @@ -436,7 +436,7 @@ def scale_to(self: VectorOrSub, length: typing.SupportsFloat) -> VectorOrSub: # TODO: Don't repeat in the documentation scale = scale_to - def reflect(self: VectorOrSub, surface_normal: VectorLike) -> VectorOrSub: + def reflect(self: Vector, surface_normal: VectorLike) -> Vector: """Reflect a vector against a surface. Compute the reflection of a :py:class:`Vector2` on a surface going through the From 7267ce8790db92a5ccd30d555ea84d9cd04400e5 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 20:56:27 +0100 Subject: [PATCH 19/70] Vector2.convert: Fix inter-Sphinx references to Mapping and Sequence --- ppb_vector/vector2.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index a973d4d5..ad44e3eb 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -117,10 +117,13 @@ def convert(cls: typing.Type[Vector], value: VectorLike) -> Vector: A vector-like can be: - - a length-2 :py:class:`Sequence`, whose contents are interpreted as - the `x` and `y` coordinates; - - a length-2 :py:class:`Mapping`, whose keys are `x` and `y`; - - or any instance of :py:class:`Vector2` (or its subclasses). + - a length-2 :py:class:`Sequence `, whose + contents are interpreted as the `x` and `y` coordinates; + + - a length-2 :py:class:`Mapping `, whose keys + are `x` and `y`; or + + - any instance of :py:class:`Vector2` (or its subclasses). :py:meth:`convert` does not perform a copy when `value` already has the right type. """ From 08bde427e725fff6efd3c39b8b178256fe3e9967 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 20:59:30 +0100 Subject: [PATCH 20/70] Vector2.scale_by: Rename parameter to `scalar` (from `other`) --- ppb_vector/vector2.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index ad44e3eb..72888230 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -190,12 +190,12 @@ def dot(self: Vector, other: VectorLike) -> float: other = Vector2.convert(other) return self.x * other.x + self.y * other.y - def scale_by(self: Vector, other: typing.SupportsFloat) -> Vector: + def scale_by(self: Vector, scalar: typing.SupportsFloat) -> Vector: """ Scale by the given amount. """ other = float(other) - return type(self)(self.x * other, self.y * other) + return type(self)(scalar * self.x, scalar * self.y) @typing.overload def __mul__(self: Vector, other: VectorLike) -> float: pass From f9260e4eaade590801e30d52334a03043dcf51d5 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 21:03:37 +0100 Subject: [PATCH 21/70] README: Bring back dunder operators (Sphinx doesn't render them) --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index 9b2b63e4..d0b3ca98 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,23 @@ vector-like objects such as `tuple`, `list`, and `dict`. Vector2(4.0, 6.0) +### Addition + + >>> Vector2(1, 0) + (0, 1) + Vector2(1.0, 1.0) + +### Subtraction + + >>> Vector2(3, 3) - (1, 1) + Vector2(2.0, 2.0) + +### Equality + +Vectors are equal if their coordinates are equal. + + >>> Vector2(1, 0) == (0, 1) + False + ### Scalar Multiplication Multiply a `Vector2` by a scalar to get a scaled `Vector2`: From 8d573265b59818e778bf367f3a4c25d5922e402e Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 21:05:48 +0100 Subject: [PATCH 22/70] fixup! Vector2.scale_by: Rename parameter to `scalar` (from `other`) --- ppb_vector/vector2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index 72888230..3f6fbaf5 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -194,7 +194,7 @@ def scale_by(self: Vector, scalar: typing.SupportsFloat) -> Vector: """ Scale by the given amount. """ - other = float(other) + scalar = float(scalar) return type(self)(scalar * self.x, scalar * self.y) @typing.overload From 53930fc312eea13fffb35c508801fc33ac5f5fd6 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 21:06:14 +0100 Subject: [PATCH 23/70] README: Use more operators for examples introducing vector-likes --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d0b3ca98..c90bedab 100644 --- a/README.md +++ b/README.md @@ -58,11 +58,11 @@ vector-like objects such as `tuple`, `list`, and `dict`. >>> Vector2(1, 1) + [1, 3] Vector2(2.0, 4.0) - >>> Vector2(1, 1) + (2, 4) - Vector2(3.0, 5.0) + >>> Vector2(1, 1) - (2, 4) + Vector2(-1.0, -3.0) - >>> Vector2(1, 1) + {"x": 3, "y": 5} - Vector2(4.0, 6.0) + >>> Vector2(1, 1) * {"x": 3, "y": 5} + 8.0 ### Addition From b106a7de74609263673191a4996ba2cf6dff54c7 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 21:13:10 +0100 Subject: [PATCH 24/70] Revert "README: Bring back dunder operators (Sphinx doesn't render them)" This reverts commit f9260e4eaade590801e30d52334a03043dcf51d5. --- README.md | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/README.md b/README.md index c90bedab..effe889f 100644 --- a/README.md +++ b/README.md @@ -65,23 +65,6 @@ vector-like objects such as `tuple`, `list`, and `dict`. 8.0 -### Addition - - >>> Vector2(1, 0) + (0, 1) - Vector2(1.0, 1.0) - -### Subtraction - - >>> Vector2(3, 3) - (1, 1) - Vector2(2.0, 2.0) - -### Equality - -Vectors are equal if their coordinates are equal. - - >>> Vector2(1, 0) == (0, 1) - False - ### Scalar Multiplication Multiply a `Vector2` by a scalar to get a scaled `Vector2`: From 2ccc387ec39091d292c8b4a50f08ea0441308432 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Sat, 23 Mar 2019 16:15:42 -0400 Subject: [PATCH 25/70] docs: Vector2: Document .x and .y --- docs/index.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/index.rst b/docs/index.rst index 24fbb3eb..5f6613d0 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -11,6 +11,14 @@ Welcome to ppb-vector's documentation! :special-members: :exclude-members: __weakref__, __init__ + .. autoattribute:: x + + The X coordinate of the vector + + .. autoattribute:: y + + The Y coordinate of the vector + Indices and tables ================== From ad478244372419de895b892a6266c44737659b82 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Sat, 23 Mar 2019 16:26:58 -0400 Subject: [PATCH 26/70] Remove .scale from docs --- docs/index.rst | 2 +- ppb_vector/vector2.py | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 5f6613d0..ee793a38 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -9,7 +9,7 @@ Welcome to ppb-vector's documentation! .. autoclass:: ppb_vector.Vector2 :members: :special-members: - :exclude-members: __weakref__, __init__ + :exclude-members: __weakref__, __init__, scale .. autoattribute:: x diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index 3f6fbaf5..4274b189 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -419,12 +419,12 @@ def truncate(self: Vector, max_length: typing.SupportsFloat) -> Vector: def scale_to(self: Vector, length: typing.SupportsFloat) -> Vector: """Scale a given :py:class:`Vector2` to a certain length. - >>> Vector2(7, 24).scale(2) + >>> Vector2(7, 24).scale_to(2) Vector2(0.56, 1.92) >>> Vector2(7, 24).normalize() Vector2(0.28, 0.96) - >>> Vector2(7, 24).scale(1) + >>> Vector2(7, 24).scale_to(1) Vector2(0.28, 0.96) """ length = float(length) @@ -436,7 +436,6 @@ def scale_to(self: Vector, length: typing.SupportsFloat) -> Vector: return (length * self) / self.length - # TODO: Don't repeat in the documentation scale = scale_to def reflect(self: Vector, surface_normal: VectorLike) -> Vector: From 66c0af3152d94ee3e28a21910b3af26d6059aeb3 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 21:23:34 +0100 Subject: [PATCH 27/70] Vector2.isclose: Grab the documentation from the README The pre-existing docstring was noticeably less good than the README. --- README.md | 24 ------------------------ ppb_vector/vector2.py | 23 +++++++++++++---------- 2 files changed, 13 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index effe889f..f8f77ff1 100644 --- a/README.md +++ b/README.md @@ -90,27 +90,3 @@ Multiply a `Vector2` by another `Vector2` to get the dot product. >>> Vector2(1, 1) * (-1, -1) -2.0 - -## Methods - -Useful functions for game development. - -### isclose(vector) - -Perform an approximate comparison of two vectors. - - >>> Vector2(1, 0).isclose((1, 1e-10)) - True - -`Vector2.isclose` takes optional, keyword arguments, akin to those of -`math.isclose`: -- `abs_tol` (absolute tolerance) is the minimum magnitude (of the difference - vector) under which two inputs are considered close, without consideration for - (the magnitude of) the input values. -- `rel_tol` (relative tolerance) is the relative error: if the length of the - difference vector is less than `rel_tol * input.length` for any `input`, - the two vectors are considered close. -- `rel_to` is an iterable of additional vector-likes whose length (times - `rel_tol`) is compared to the length of the difference vector. - -By default, `abs_tol = 1e-3`, `rel_tol = 1e-6`, and `rel_to = []`. diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index 4274b189..a67b0bab 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -308,21 +308,24 @@ def angle(self: Vector, other: VectorLike) -> float: def isclose(self: Vector, other: VectorLike, *, abs_tol: typing.SupportsFloat = 1e-09, rel_tol: typing.SupportsFloat = 1e-09, rel_to: typing.Sequence[VectorLike] = ()) -> bool: - """Determine whether two vectors are close in value. + """Perform an approximate comparison of two vectors. - :param rel_tol: maximum difference for being considered "close", - relative to the magnitude of the input values + >>> Vector2(1, 0).isclose((1, 1e-10)) + True - :param rel_to: additional input values to consider in rel_tol + :py:meth:`isclose` takes optional, keyword arguments, akin to those of + :py:func:`math.isclose`: - :param abs_tol: maximum difference for being considered "close", - regardless of the magnitude of the input values + :param abs_tol: the absolute tolerance is the minimum magnitude (of the + difference vector) under which two inputs are considered close, + without consideration for (the magnitude of) the input values. - Return True if `self` is close in value to `other`, and False otherwise. - - For the values to be considered close, the difference between them - must be smaller than at least one of the tolerances. + :param rel_tol: the relative tolerance: if the length of the difference + vector is less than ``rel_tol * input.length`` for any ``input``, the + two vectors are considered close. + :param rel_to: an iterable of additional vector-likes which are + considered to be inputs, for the purpose of the relative tolerance. """ abs_tol, rel_tol = float(abs_tol), float(rel_tol) if abs_tol < 0 or rel_tol < 0: From edb9733d1f6329d30fd6db4a9a12b5887d1ac0e6 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 21:28:30 +0100 Subject: [PATCH 28/70] Vector2: Properly format variable names in docstrings --- ppb_vector/vector2.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index a67b0bab..cadd1d8c 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -118,14 +118,15 @@ def convert(cls: typing.Type[Vector], value: VectorLike) -> Vector: A vector-like can be: - a length-2 :py:class:`Sequence `, whose - contents are interpreted as the `x` and `y` coordinates; + contents are interpreted as the ``x`` and ``y`` coordinates; - a length-2 :py:class:`Mapping `, whose keys - are `x` and `y`; or + are ``x`` and ``y``; or - any instance of :py:class:`Vector2` (or its subclasses). - :py:meth:`convert` does not perform a copy when `value` already has the right type. + :py:meth:`convert` does not perform a copy when ``value`` already has the + right type. """ # Use Vector2.convert() instead of type(self).convert() so that # _find_lowest_vector() can resolve things well. @@ -410,7 +411,7 @@ def truncate(self: Vector, max_length: typing.SupportsFloat) -> Vector: Vector2(3.0, 4.0) Note: :py:meth:`x.truncate(max_length) ` may sometimes be - slightly-larger than `max_length`, due to floating-point rounding + slightly-larger than ``max_length``, due to floating-point rounding effects. """ max_length = float(max_length) From 739d5af2d86b71d68fea56c2e8f89c82097d78ff Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Sat, 23 Mar 2019 16:37:12 -0400 Subject: [PATCH 29/70] docs: Annotate types of .x and .y --- docs/index.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index ee793a38..0e55e02e 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -12,12 +12,14 @@ Welcome to ppb-vector's documentation! :exclude-members: __weakref__, __init__, scale .. autoattribute:: x + :annotation: : float - The X coordinate of the vector + The X coordinate of the vector .. autoattribute:: y + :annotation: : float - The Y coordinate of the vector + The Y coordinate of the vector Indices and tables From b8da55f1901b90c2e82101fb11d42b8e4a6e3d6e Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 21:36:51 +0100 Subject: [PATCH 30/70] docs: Document the Vector typevar --- docs/index.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/index.rst b/docs/index.rst index 0e55e02e..33756c20 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -6,6 +6,13 @@ Welcome to ppb-vector's documentation! ====================================== +.. py:data:: ppb_vector.vector2.Vector + +In the following, :py:data:`Vector` is a type variable that denotes either +:py:class:`Vector2` or any of its subclasses. Implicitely, it is the type of +``self``. + + .. autoclass:: ppb_vector.Vector2 :members: :special-members: From 36cabf3c5e5cc66d51a4c28f0aa2433d8c8fbcb4 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 21:37:11 +0100 Subject: [PATCH 31/70] docs/Vector2: Sort the exclude-members list --- docs/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index 33756c20..82d0610b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -16,7 +16,7 @@ In the following, :py:data:`Vector` is a type variable that denotes either .. autoclass:: ppb_vector.Vector2 :members: :special-members: - :exclude-members: __weakref__, __init__, scale + :exclude-members: __init__, __weakref__, scale .. autoattribute:: x :annotation: : float From e25920b92b970a4558a4efb246ff72d144bd802a Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 21:37:34 +0100 Subject: [PATCH 32/70] docs/Vector2: Do not autogenerate doc for __repr__ --- docs/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index 82d0610b..7f9dea92 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -16,7 +16,7 @@ In the following, :py:data:`Vector` is a type variable that denotes either .. autoclass:: ppb_vector.Vector2 :members: :special-members: - :exclude-members: __init__, __weakref__, scale + :exclude-members: __init__, __repr__, __weakref__, scale .. autoattribute:: x :annotation: : float From e86e8c2129007a8f6755040ac4630ba1095d17df Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 21:41:29 +0100 Subject: [PATCH 33/70] Vector2.__truediv__: Add example in docstring --- ppb_vector/vector2.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index cadd1d8c..107b7548 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -226,7 +226,11 @@ def __rmul__(self, other): return self.__mul__(other) def __truediv__(self: Vector, other: typing.SupportsFloat) -> Vector: - """Perform a division between a vector and a scalar.""" + """Perform a division between a vector and a scalar. + + >>> Vector2(3, 3) / 3 + Vector2(1.0, 1.0) + """ other = float(other) return type(self)(self.x / other, self.y / other) From 24ddea26c6f75efae409a93743fd039c2b9d53cd Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Sat, 23 Mar 2019 16:52:16 -0400 Subject: [PATCH 34/70] Add examples for .convert() --- ppb_vector/vector2.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index 107b7548..a362886a 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -118,12 +118,12 @@ def convert(cls: typing.Type[Vector], value: VectorLike) -> Vector: A vector-like can be: - a length-2 :py:class:`Sequence `, whose - contents are interpreted as the ``x`` and ``y`` coordinates; + contents are interpreted as the ``x`` and ``y`` coordinates like ``(4, 2)`` - a length-2 :py:class:`Mapping `, whose keys - are ``x`` and ``y``; or + are ``x`` and ``y`` like ``{'x': 4, 'y': 2}`` - - any instance of :py:class:`Vector2` (or its subclasses). + - any instance of :py:class:`Vector2` or any subclass. :py:meth:`convert` does not perform a copy when ``value`` already has the right type. From bdb974fe7bb95d84c1d9b47b9fb3ed80b4a8326e Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 21:52:52 +0100 Subject: [PATCH 35/70] Vector2.__mul__: Move the documentation to a docstring --- README.md | 27 --------------------------- ppb_vector/vector2.py | 28 ++++++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index f8f77ff1..67f00faa 100644 --- a/README.md +++ b/README.md @@ -63,30 +63,3 @@ vector-like objects such as `tuple`, `list`, and `dict`. >>> Vector2(1, 1) * {"x": 3, "y": 5} 8.0 - - -### Scalar Multiplication - -Multiply a `Vector2` by a scalar to get a scaled `Vector2`: - - >>> 3 * Vector2(1, 1) - Vector2(3.0, 3.0) - - >>> Vector2(1, 1) * 3 - Vector2(3.0, 3.0) - - >>> Vector2(1, 1).scale_by(3) - Vector2(3.0, 3.0) - - -It is also possible to divide a `Vector2` by a scalar: - - >>> Vector2(3, 3) / 3 - Vector2(1.0, 1.0) - -### Dot Product - -Multiply a `Vector2` by another `Vector2` to get the dot product. - - >>> Vector2(1, 1) * (-1, -1) - -2.0 diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index a362886a..7367e8fa 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -205,8 +205,32 @@ def __mul__(self: Vector, other: VectorLike) -> float: pass def __mul__(self: Vector, other: typing.SupportsFloat) -> Vector: pass def __mul__(self, other): - """ - Performs a dot product or scale based on other. + """Performs a dot product or scalar product, based on the parameter type. + + :param other: If ``other`` is a scalar (an instance of + :py:class:`typing.SupportsFloat`), return + :py:meth:`self.scale_by(other) `. + + >>> 3 * Vector2(1, 1) + Vector2(3.0, 3.0) + + >>> Vector2(1, 1) * 3 + Vector2(3.0, 3.0) + + >>> Vector2(1, 1).scale_by(3) + Vector2(3.0, 3.0) + + It is also possible to divide a :py:class:`Vector2` by a scalar: + + >>> Vector2(3, 3) / 3 + Vector2(1.0, 1.0) + + + :param other: If ``other`` is a vector (an instance of + :py:class:`Vector2`), return :py:meth:`self.dot(other) `. + + >>> Vector2(1, 1) * (-1, -1) + -2.0 """ if isinstance(other, (float, int)): return self.scale_by(other) From 3dc443ca998773831a96f78dec8a97a1bd35a6eb Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 21:55:12 +0100 Subject: [PATCH 36/70] README: Link to the RTD documentation --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 67f00faa..83a98d17 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,10 @@ pip install 'ppb-vector' Vector2(3.0, 4.0) +See the [online documentation] for an overview of the functionality. + +[online documentation]: https://ppb-vector.readthedocs.io/en/latest/ + ## Convenience functions From 2a63fd698a6fa76514331377ecea86e7ffdcfc08 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Sat, 23 Mar 2019 17:08:08 -0400 Subject: [PATCH 37/70] Add docs about Vector2 being sequence-ish and mapping-ish --- ppb_vector/vector2.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index 7367e8fa..c4f6d991 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -63,6 +63,10 @@ class Vector2: :py:class:`Vector2` implements many convenience features, as well as useful mathematical operations for 2D geometry and linear algebra. + :py:class:`Vector2` acts as an iterable and sequence, allowing usage like + unpacking (``x, y = Vector2(1, 2)``, ``myfunc( *Vector2(1, 2) )``). + It also acts mostly like a mapping, when it does not conflict with being a + sequence. The coordinates may be accessed by the keys ``"x"`` and ``"y"``. """ x: float y: float From 9692fd9ef0310ea963bc07e0af5a9dde030fdb39 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Sat, 23 Mar 2019 17:12:48 -0400 Subject: [PATCH 38/70] normalize: Remove errant comma --- ppb_vector/vector2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index c4f6d991..da52c438 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -410,7 +410,7 @@ def rotate(self: Vector, angle: typing.SupportsFloat) -> Vector: return type(self)(x, y) def normalize(self: Vector) -> Vector: - """Return a vector with the same direction, and unit length. + """Return a vector with the same direction and unit length. >>> Vector2(3, 4).normalize() Vector2(0.6, 0.8) From 73543f1b335179e19f39268a454b84be1928b938 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 22:10:49 +0100 Subject: [PATCH 39/70] Vector2: Reference vector-likes in each relevant method docstring --- ppb_vector/vector2.py | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index da52c438..60919f24 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -165,6 +165,9 @@ def __len__(self: Vector) -> int: def __add__(self: Vector, other: VectorLike) -> Vector: """Add two vectors. + :param other: A :py:class:`Vector2` or a vector-like. + For a description of vector-likes, see :py:func:`convert`. + >>> Vector2(1, 0) + (0, 1) Vector2(1.0, 1.0) """ @@ -178,6 +181,9 @@ def __add__(self: Vector, other: VectorLike) -> Vector: def __sub__(self: Vector, other: VectorLike) -> Vector: """Subtract one vector from another. + :param other: A :py:class:`Vector2` or a vector-like. + For a description of vector-likes, see :py:func:`convert`. + >>> Vector2(3, 3) - (1, 1) Vector2(2.0, 2.0) """ @@ -189,8 +195,10 @@ def __sub__(self: Vector, other: VectorLike) -> Vector: return rtype(self.x - other.x, self.y - other.y) def dot(self: Vector, other: VectorLike) -> float: - """ - Return the dot product of two vectors. + """Return the dot product of two vectors. + + :param other: A :py:class:`Vector2` or a vector-like. + For a description of vector-likes, see :py:func:`convert`. """ other = Vector2.convert(other) return self.x * other.x + self.y * other.y @@ -230,11 +238,13 @@ def __mul__(self, other): Vector2(1.0, 1.0) - :param other: If ``other`` is a vector (an instance of - :py:class:`Vector2`), return :py:meth:`self.dot(other) `. + :param other: If ``other`` is a vector-like, return + :py:meth:`self.dot(other) `. >>> Vector2(1, 1) * (-1, -1) -2.0 + + Vector-likes are defined in :py:meth:`convert`. """ if isinstance(other, (float, int)): return self.scale_by(other) @@ -318,6 +328,9 @@ def __neg__(self: Vector) -> Vector: def angle(self: Vector, other: VectorLike) -> float: """Compute the angle between two vectors, expressed in degrees. + :param other: A :py:class:`Vector2` or a vector-like. + For a description of vector-likes, see :py:func:`convert`. + >>> Vector2(1, 0).angle( (0, 1) ) 90.0 @@ -343,6 +356,9 @@ def isclose(self: Vector, other: VectorLike, *, rel_to: typing.Sequence[VectorLike] = ()) -> bool: """Perform an approximate comparison of two vectors. + :param other: A :py:class:`Vector2` or a vector-like. + For a description of vector-likes, see :py:func:`convert`. + >>> Vector2(1, 0).isclose((1, 1e-10)) True @@ -477,6 +493,9 @@ def scale_to(self: Vector, length: typing.SupportsFloat) -> Vector: def reflect(self: Vector, surface_normal: VectorLike) -> Vector: """Reflect a vector against a surface. + :param other: A :py:class:`Vector2` or a vector-like. + For a description of vector-likes, see :py:func:`convert`. + Compute the reflection of a :py:class:`Vector2` on a surface going through the origin, described by its normal vector. From 1b87499893fe4a6bfbf27ef888e2e03715d4480a Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 22:11:49 +0100 Subject: [PATCH 40/70] Vector2.dot: Terser description --- ppb_vector/vector2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index 60919f24..076a9dba 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -195,7 +195,7 @@ def __sub__(self: Vector, other: VectorLike) -> Vector: return rtype(self.x - other.x, self.y - other.y) def dot(self: Vector, other: VectorLike) -> float: - """Return the dot product of two vectors. + """Dot product of two vectors. :param other: A :py:class:`Vector2` or a vector-like. For a description of vector-likes, see :py:func:`convert`. From b82b5976afdafad80eda0536523254cb713773bb Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 22:12:24 +0100 Subject: [PATCH 41/70] Vector2.scale_by: Add example, document infix notation --- ppb_vector/vector2.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index 076a9dba..fd3299c3 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -204,8 +204,15 @@ def dot(self: Vector, other: VectorLike) -> float: return self.x * other.x + self.y * other.y def scale_by(self: Vector, scalar: typing.SupportsFloat) -> Vector: - """ - Scale by the given amount. + """Scalar multiplication. + + >>> Vector2(1, 2).scale_by(3) + Vector2(3.0, 6.0) + + Can also be expressed with :py:meth:`* <__mul__>`: + + >>> 3 * Vector(1, 2) + Vector2(3.0, 6.0) """ scalar = float(scalar) return type(self)(scalar * self.x, scalar * self.y) From aa6e7230b078c22d5606d6db3a4677b8aea7a63f Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 22:13:04 +0100 Subject: [PATCH 42/70] Vector2.reflect: Reflow text in docstring --- ppb_vector/vector2.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index fd3299c3..86babc61 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -503,8 +503,8 @@ def reflect(self: Vector, surface_normal: VectorLike) -> Vector: :param other: A :py:class:`Vector2` or a vector-like. For a description of vector-likes, see :py:func:`convert`. - Compute the reflection of a :py:class:`Vector2` on a surface going through the - origin, described by its normal vector. + Compute the reflection of a :py:class:`Vector2` on a surface going + through the origin, described by its normal vector. >>> Vector2(5, 3).reflect( (-1, 0) ) Vector2(-5.0, 3.0) From 2f05e62288712f54d3be951b594ec599329cd13e Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 22:20:49 +0100 Subject: [PATCH 43/70] fixup! Vector2.scale_by: Add example, document infix notation --- ppb_vector/vector2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index 86babc61..2c83b3e4 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -211,7 +211,7 @@ def scale_by(self: Vector, scalar: typing.SupportsFloat) -> Vector: Can also be expressed with :py:meth:`* <__mul__>`: - >>> 3 * Vector(1, 2) + >>> 3 * Vector2(1, 2) Vector2(3.0, 6.0) """ scalar = float(scalar) From d74cdaba49bfa11f3b861782f285565180bf8485 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 22:22:10 +0100 Subject: [PATCH 44/70] Vector2: Provide proper code examples for unpacking, and accessing --- ppb_vector/vector2.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index 2c83b3e4..e6e14610 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -64,9 +64,26 @@ class Vector2: useful mathematical operations for 2D geometry and linear algebra. :py:class:`Vector2` acts as an iterable and sequence, allowing usage like - unpacking (``x, y = Vector2(1, 2)``, ``myfunc( *Vector2(1, 2) )``). + unpacking and indexing: + + >>> x, y = Vector2(1, 2) + >>> x + 1.0 + + >>> print( *Vector2(1, 2) ) + 1.0 2.0 + + >>> v = Vector2(-3, -5) + >>> v[0] + -3.0 + It also acts mostly like a mapping, when it does not conflict with being a - sequence. The coordinates may be accessed by the keys ``"x"`` and ``"y"``. + sequence. In particular, the coordinates may be accessed by subscripting: + + >>> v["y"] + -5.0 + >>> v["x"] + -3.0 """ x: float y: float From 54336e90cac9b51fe0a8508f362e1b301fc5d8df Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 22:24:07 +0100 Subject: [PATCH 45/70] =?UTF-8?q?README:=20Drop=20the=20documentation=20of?= =?UTF-8?q?=20=E2=80=9Cconvenience=20functions=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those are now documented in the class-level docstring. --- README.md | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/README.md b/README.md index 83a98d17..8e3f2e28 100644 --- a/README.md +++ b/README.md @@ -26,34 +26,6 @@ See the [online documentation] for an overview of the functionality. [online documentation]: https://ppb-vector.readthedocs.io/en/latest/ -## Convenience functions - -### Unpacking - - >>> x, y = Vector2(1, 3) - >>> print(x) - 1.0 - >>> print(y) - 3.0 - -### Access Values - -Convenient access to `Vector2` members via dot notation, indexes, or keys. - - >>> my_vector = Vector2(2, 3) - >>> my_vector.x - 2.0 - >>> my_vector[1] - 3.0 - >>> my_vector["x"] - 2.0 - -Also iterable for translation between Vector2 and other sequence types. - - >>> tuple(Vector2(2, 3)) - (2.0, 3.0) - - ## Mathematical operators In addition to `Vector2`s, operators also accept, as second operand, From dea1c9e38060e88d81f75a1287c639fb4790d2f7 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Sat, 23 Mar 2019 17:24:14 -0400 Subject: [PATCH 46/70] Work on the Vector typevar --- docs/index.rst | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 7f9dea92..2b84666e 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,16 +1,12 @@ -.. ppb-vector documentation master file, created by - sphinx-quickstart on Sat Mar 23 14:10:03 2019. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to ppb-vector's documentation! -====================================== +PPB 2D Vector +============= .. py:data:: ppb_vector.vector2.Vector -In the following, :py:data:`Vector` is a type variable that denotes either -:py:class:`Vector2` or any of its subclasses. Implicitely, it is the type of -``self``. + In the following, :py:data:`Vector` is a type variable that denotes either + :py:class:`Vector2` or any of its subclasses. Implicitely, it is the type of + ``self``--the type of the returned value will be the same subclass if called + on a subclass .. autoclass:: ppb_vector.Vector2 @@ -27,11 +23,3 @@ In the following, :py:data:`Vector` is a type variable that denotes either :annotation: : float The Y coordinate of the vector - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` From 14752b1b0360bfd5f667af66d2dca714a22a3325 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 22:25:20 +0100 Subject: [PATCH 47/70] =?UTF-8?q?README:=20Drop=20documentation=20of=20?= =?UTF-8?q?=E2=80=9CMathematical=20operators=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Each operator's docstring refers to `convert()` for describing vector-likes, and provides a code example using a vector-like. --- README.md | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/README.md b/README.md index 8e3f2e28..fabb40cb 100644 --- a/README.md +++ b/README.md @@ -24,18 +24,3 @@ pip install 'ppb-vector' See the [online documentation] for an overview of the functionality. [online documentation]: https://ppb-vector.readthedocs.io/en/latest/ - - -## Mathematical operators - -In addition to `Vector2`s, operators also accept, as second operand, -vector-like objects such as `tuple`, `list`, and `dict`. - - >>> Vector2(1, 1) + [1, 3] - Vector2(2.0, 4.0) - - >>> Vector2(1, 1) - (2, 4) - Vector2(-1.0, -3.0) - - >>> Vector2(1, 1) * {"x": 3, "y": 5} - 8.0 From 941d1b1bf9044c94297201824abbc225c8278a19 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Sat, 23 Mar 2019 17:27:45 -0400 Subject: [PATCH 48/70] docs: Add an annotation to Vector with the actual declaration --- docs/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/index.rst b/docs/index.rst index 2b84666e..a93db438 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -2,6 +2,7 @@ PPB 2D Vector ============= .. py:data:: ppb_vector.vector2.Vector + :annotation: = typing.TypeVar('Vector', bound='Vector2') In the following, :py:data:`Vector` is a type variable that denotes either :py:class:`Vector2` or any of its subclasses. Implicitely, it is the type of From 8a859145e859b2fab364a8359ca76fd345270344 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 22:28:11 +0100 Subject: [PATCH 49/70] Vector2.__eq__: Reference convert()/vector-like in docstring --- ppb_vector/vector2.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index e6e14610..be183937 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -322,6 +322,9 @@ def __repr__(self: Vector) -> str: def __eq__(self: Vector, other: typing.Any) -> bool: """Test wheter two vectors are equal. + :param other: A :py:class:`Vector2` or a vector-like. + For a description of vector-likes, see :py:func:`convert`. + Vectors are equal if their coordinates are equal. >>> Vector2(1, 0) == (0, 1) From ed127db783331f1832cd8731320d0b87e13d29f9 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 22:31:55 +0100 Subject: [PATCH 50/70] Vector2.__eq__: Drop the ambiguous & unhelpful definition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It can easily be misunderstood as “equals if the x and y coordinates are equal”. Moreover, it's not particularly useful: ppb-vector is meant to be easy to use, but it is not meant to be a basic course on 2D geometry. --- ppb_vector/vector2.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index be183937..94841603 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -325,8 +325,6 @@ def __eq__(self: Vector, other: typing.Any) -> bool: :param other: A :py:class:`Vector2` or a vector-like. For a description of vector-likes, see :py:func:`convert`. - Vectors are equal if their coordinates are equal. - >>> Vector2(1, 0) == (0, 1) False """ From 158cf09e219989e9205b075331e87da78b4ba59d Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 22:42:18 +0100 Subject: [PATCH 51/70] docs/Vector: Add a cross-reference to typing.TypeVar --- docs/index.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index a93db438..e2cd5699 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -4,10 +4,11 @@ PPB 2D Vector .. py:data:: ppb_vector.vector2.Vector :annotation: = typing.TypeVar('Vector', bound='Vector2') - In the following, :py:data:`Vector` is a type variable that denotes either + In the following, :py:data:`Vector` is a type variable (an instance of + :py:class:`TypeVar `) that denotes either :py:class:`Vector2` or any of its subclasses. Implicitely, it is the type of - ``self``--the type of the returned value will be the same subclass if called - on a subclass + ``self``-- the type of the returned value will be the same subclass if + called on a subclass .. autoclass:: ppb_vector.Vector2 From af39e54cdefa98cc390db434dab8d4be10665741 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 22:44:13 +0100 Subject: [PATCH 52/70] docs/Vector: Fix minor typo --- docs/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index e2cd5699..401978ea 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -7,7 +7,7 @@ PPB 2D Vector In the following, :py:data:`Vector` is a type variable (an instance of :py:class:`TypeVar `) that denotes either :py:class:`Vector2` or any of its subclasses. Implicitely, it is the type of - ``self``-- the type of the returned value will be the same subclass if + ``self`` -- the type of the returned value will be the same subclass if called on a subclass From cb4c3e8f18ade39089b53351a6ebba57f6de74ba Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 22:45:05 +0100 Subject: [PATCH 53/70] =?UTF-8?q?docs:=20Change=20title=20to=20=E2=80=9CPP?= =?UTF-8?q?B's=202D=20Vector=20class=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 401978ea..2cd37319 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,5 +1,5 @@ -PPB 2D Vector -============= +PPB's 2D Vector class +===================== .. py:data:: ppb_vector.vector2.Vector :annotation: = typing.TypeVar('Vector', bound='Vector2') From f0577953e080f360ae650ecfe18854cab876fdaa Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 23:21:09 +0100 Subject: [PATCH 54/70] Cirrus CI: Add a task for building documentation --- .cirrus.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.cirrus.yml b/.cirrus.yml index 58ebfcea..2bc65a64 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,3 +1,14 @@ +docs_task: + container: + image: python:3.7-slim + + install_script: + - pip install --upgrade-strategy eager -U -r docs-requirements.txt + - pip install -e . + + script: + - make -C docs/ html + lint_task: container: image: python:3.7-slim From 5fc3584aea61e92e2bafd0c3fb1360eae24bfc44 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 23:22:57 +0100 Subject: [PATCH 55/70] fixup! Cirrus CI: Add a task for building documentation --- .cirrus.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.cirrus.yml b/.cirrus.yml index 2bc65a64..aadaf8b6 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -3,6 +3,7 @@ docs_task: image: python:3.7-slim install_script: + - apt install make - pip install --upgrade-strategy eager -U -r docs-requirements.txt - pip install -e . From e815e722d25fea3ba5b1723afd04a9c711b81f2a Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 23:23:56 +0100 Subject: [PATCH 56/70] fixup! Cirrus CI: Add a task for building documentation --- .cirrus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index aadaf8b6..708997fd 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -3,7 +3,7 @@ docs_task: image: python:3.7-slim install_script: - - apt install make + - apt update && apt install make - pip install --upgrade-strategy eager -U -r docs-requirements.txt - pip install -e . From a52160ad7bb6fe9056818184aadf8362cce1eca6 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 23:31:38 +0100 Subject: [PATCH 57/70] Vector2: Add cross-references to the relevant protocols in docstring --- ppb_vector/vector2.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index 94841603..6533cf40 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -63,8 +63,9 @@ class Vector2: :py:class:`Vector2` implements many convenience features, as well as useful mathematical operations for 2D geometry and linear algebra. - :py:class:`Vector2` acts as an iterable and sequence, allowing usage like - unpacking and indexing: + :py:class:`Vector2` implements :py:class:`Sequence + ` (and subsequently :py:class:`Iterable + `), allowing usage like unpacking and indexing: >>> x, y = Vector2(1, 2) >>> x From b09e3fda8c920e9094727166d22ed44157e1c884 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 23:32:43 +0100 Subject: [PATCH 58/70] Vector2: Sort [indexing, unpacking] in class docstring --- ppb_vector/vector2.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index 6533cf40..a5f82011 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -65,7 +65,11 @@ class Vector2: :py:class:`Vector2` implements :py:class:`Sequence ` (and subsequently :py:class:`Iterable - `), allowing usage like unpacking and indexing: + `), allowing usage like indexing, and unpacking: + + >>> v = Vector2(-3, -5) + >>> v[0] + -3.0 >>> x, y = Vector2(1, 2) >>> x @@ -74,10 +78,6 @@ class Vector2: >>> print( *Vector2(1, 2) ) 1.0 2.0 - >>> v = Vector2(-3, -5) - >>> v[0] - -3.0 - It also acts mostly like a mapping, when it does not conflict with being a sequence. In particular, the coordinates may be accessed by subscripting: From 470ee193de90c04733f779e75b084aeecd5b0772 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 23:33:19 +0100 Subject: [PATCH 59/70] Vector2: Add examples of conversions to lists and tuples --- ppb_vector/vector2.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index a5f82011..35601365 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -65,9 +65,14 @@ class Vector2: :py:class:`Vector2` implements :py:class:`Sequence ` (and subsequently :py:class:`Iterable - `), allowing usage like indexing, and unpacking: + `), allowing usage like converting, indexing, and unpacking: >>> v = Vector2(-3, -5) + >>> list(v) + [-3.0, -5.0] + >>> tuple(v) + (-3.0, -5.0) + >>> v[0] -3.0 From c687b20e0cb4c8bf93cb7f37ceaa92bf2e2eb82e Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 23:37:46 +0100 Subject: [PATCH 60/70] Vector2.asdict: Add docstring --- ppb_vector/vector2.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index 35601365..64212e65 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -180,6 +180,16 @@ def length(self) -> float: return hypot(self.x, self.y) def asdict(self) -> typing.Mapping[str, float]: + """Convert a vector to a vector-like dictionary. + + >>> v = Vector2(42, 69) + >>> v.asdict() + {'x': 42.0, 'y': 69.0} + + The conversion can be reversed by :py:meth:`convert`: + + >>> assert v == Vector2.convert(v.asdict()) + """ return {'x': self.x, 'y': self.y} def __len__(self: Vector) -> int: From 8c5e70bf77cf97f7b3d1f6308124a0f1e6fe888b Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 23:46:34 +0100 Subject: [PATCH 61/70] Vector2: Move comparison of scale and normalize to the latter's doc --- ppb_vector/vector2.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index 64212e65..0ad160d2 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -472,7 +472,12 @@ def normalize(self: Vector) -> Vector: >>> Vector2(3, 4).normalize() Vector2(0.6, 0.8) - Note that :py:meth:`normalize()` is equivalent to :py:meth:`scale(1) `. + Note that :py:meth:`normalize()` is equivalent to :py:meth:`scale(1) `: + + >>> Vector2(7, 24).normalize() + Vector2(0.28, 0.96) + >>> Vector2(7, 24).scale_to(1) + Vector2(0.28, 0.96) """ return self.scale(1) @@ -514,11 +519,6 @@ def scale_to(self: Vector, length: typing.SupportsFloat) -> Vector: >>> Vector2(7, 24).scale_to(2) Vector2(0.56, 1.92) - - >>> Vector2(7, 24).normalize() - Vector2(0.28, 0.96) - >>> Vector2(7, 24).scale_to(1) - Vector2(0.28, 0.96) """ length = float(length) if length < 0: From cdc00a7a30721b4dbd555d1fc974c7ca8342b997 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 23:48:12 +0100 Subject: [PATCH 62/70] Vector2.normalize: Replace redundant display with assert in example --- ppb_vector/vector2.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index 0ad160d2..e193b513 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -474,10 +474,7 @@ def normalize(self: Vector) -> Vector: Note that :py:meth:`normalize()` is equivalent to :py:meth:`scale(1) `: - >>> Vector2(7, 24).normalize() - Vector2(0.28, 0.96) - >>> Vector2(7, 24).scale_to(1) - Vector2(0.28, 0.96) + >>> assert Vector2(7, 24).normalize() == Vector2(7, 24).scale_to(1) """ return self.scale(1) From 5d31e92165b0aa2e4cde363818c3c03b21da4e8c Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sat, 23 Mar 2019 23:58:11 +0100 Subject: [PATCH 63/70] Revert "Vector2: Add cross-references to the relevant protocols in docstring" This reverts commit a52160ad7bb6fe9056818184aadf8362cce1eca6. --- ppb_vector/vector2.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index e193b513..344ee791 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -63,9 +63,8 @@ class Vector2: :py:class:`Vector2` implements many convenience features, as well as useful mathematical operations for 2D geometry and linear algebra. - :py:class:`Vector2` implements :py:class:`Sequence - ` (and subsequently :py:class:`Iterable - `), allowing usage like converting, indexing, and unpacking: + :py:class:`Vector2` acts as an iterable and a sequence, allowing usage like + converting, indexing, and unpacking: >>> v = Vector2(-3, -5) >>> list(v) From 83f66125ebb2e6a7dc5640e9e823f2e7e8430881 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sun, 24 Mar 2019 00:00:41 +0100 Subject: [PATCH 64/70] Vector2.isclose: Replace outputting `True` with an assertion --- ppb_vector/vector2.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index 344ee791..6916fb0c 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -399,8 +399,7 @@ def isclose(self: Vector, other: VectorLike, *, :param other: A :py:class:`Vector2` or a vector-like. For a description of vector-likes, see :py:func:`convert`. - >>> Vector2(1, 0).isclose((1, 1e-10)) - True + >>> assert Vector2(1, 0).isclose((1, 1e-10)) :py:meth:`isclose` takes optional, keyword arguments, akin to those of :py:func:`math.isclose`: From 811f6b9adada2e60ed9a2f9352e7ab92b8c827b1 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sun, 24 Mar 2019 00:26:58 +0100 Subject: [PATCH 65/70] Vector2: Fix indentation in class docstring --- ppb_vector/vector2.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ppb_vector/vector2.py b/ppb_vector/vector2.py index 6916fb0c..9228f543 100644 --- a/ppb_vector/vector2.py +++ b/ppb_vector/vector2.py @@ -56,9 +56,9 @@ class Vector2: :py:class:`Vector2` is an immutable 2D Vector, which can be instantiated as expected: - >>> from ppb_vector import Vector2 - >>> Vector2(3, 4) - Vector2(3.0, 4.0) + >>> from ppb_vector import Vector2 + >>> Vector2(3, 4) + Vector2(3.0, 4.0) :py:class:`Vector2` implements many convenience features, as well as useful mathematical operations for 2D geometry and linear algebra. From d51a958c72ff9d5f6bea170842ec9974ec5a508c Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sun, 24 Mar 2019 17:02:16 +0100 Subject: [PATCH 66/70] docs/Vector: Clarify what Vector is used for. --- docs/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 2cd37319..008887b7 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -7,8 +7,8 @@ PPB's 2D Vector class In the following, :py:data:`Vector` is a type variable (an instance of :py:class:`TypeVar `) that denotes either :py:class:`Vector2` or any of its subclasses. Implicitely, it is the type of - ``self`` -- the type of the returned value will be the same subclass if - called on a subclass + ``self``: a method whose return type is :py:data:`Vector` will return a + vector of the same type that it was called on. .. autoclass:: ppb_vector.Vector2 From f6d1e418970ba51d309178bc990ab9390a3395d7 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sun, 24 Mar 2019 21:01:49 +0100 Subject: [PATCH 67/70] Cirrus CI: Do not perform builds for Bors' temporary branches --- .cirrus.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.cirrus.yml b/.cirrus.yml index 4c7702ec..ca15151e 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,4 +1,5 @@ lint_task: + skip: $CIRRUS_BRANCH =~ '.*\.tmp' container: image: python:3.7-slim @@ -15,6 +16,7 @@ lint_task: FreeBSD_task: + skip: $CIRRUS_BRANCH =~ '.*\.tmp' freebsd_instance: image: freebsd-12-0-release-amd64 env: @@ -37,6 +39,7 @@ FreeBSD_task: - ./test.sh Linux_task: + skip: $CIRRUS_BRANCH =~ '.*\.tmp' allow_failures: $CIRRUS_TASK_NAME =~ '.*-rc-.*' container: matrix: @@ -56,6 +59,7 @@ Linux_task: - ./test.sh macOS_task: + skip: $CIRRUS_BRANCH =~ '.*\.tmp' osx_instance: image: mojave-base env: @@ -81,6 +85,7 @@ macOS_task: - ./test.sh Windows_task: + skip: $CIRRUS_BRANCH =~ '.*\.tmp' allow_failures: $CIRRUS_TASK_NAME =~ '.*-rc-.*' windows_container: os_version: 2019 From 554f4c031fcb59eb6fb85cfc7882f9ff757c19e6 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sun, 24 Mar 2019 21:08:36 +0100 Subject: [PATCH 68/70] Bors: Configure required CI checks All tests and lint tasks, except for CPython 3.8-rc. `docs` will need to be added once #130 lands. --- bors.toml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 bors.toml diff --git a/bors.toml b/bors.toml new file mode 100644 index 00000000..06097727 --- /dev/null +++ b/bors.toml @@ -0,0 +1,11 @@ +status = [ + "FreeBSD PYTHON:3.6", + "FreeBSD PYTHON:3.7", + "lint", + "Linux container:python:3.6-slim", + "Linux container:python:3.7-slim", + "Windows container:python:3.6-windowsservercore-1809", + "Windows container:python:3.7-windowsservercore-1809", + "macOS PYTHON:3.6.8", + "macOS PYTHON:3.7.2", +] From 41b34d51a4baf47376389552709e973639db67fd Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sun, 24 Mar 2019 22:32:28 +0100 Subject: [PATCH 69/70] Cirrus CI: Do not build docs on Bors temporary branches --- .cirrus.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.cirrus.yml b/.cirrus.yml index 5bdec8e1..71db21a8 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,4 +1,5 @@ docs_task: + skip: $CIRRUS_BRANCH =~ '.*\.tmp' container: image: python:3.7-slim From 7d562853c8d1ce97c8333bdf9502f123e0f4e622 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sun, 24 Mar 2019 22:33:09 +0100 Subject: [PATCH 70/70] Bors: Require docs to build successfully --- bors.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/bors.toml b/bors.toml index 06097727..da626e82 100644 --- a/bors.toml +++ b/bors.toml @@ -1,4 +1,5 @@ status = [ + "docs", "FreeBSD PYTHON:3.6", "FreeBSD PYTHON:3.7", "lint",