Skip to content

Commit

Permalink
Add vg.compat forward-compatibilty layer for libraries (#158)
Browse files Browse the repository at this point in the history
Closes #112
  • Loading branch information
paulmelnikow authored Jul 13, 2021
1 parent 636b11d commit 900413e
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 45 deletions.
44 changes: 1 addition & 43 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ A **v**ery **g**ood vector-geometry toolbelt for dealing with 3D points and
vectors. These are simple [NumPy][] operations made readable, built to scale
from prototyping to production.

See the complete API reference: https://vgpy.readthedocs.io/en/latest/
:book: See the complete documentation: https://vgpy.readthedocs.io/en/latest/

[pypi]: https://pypi.org/project/vg/
[coverage]: https://github.com/lace/vg/blob/master/.coveragerc
Expand Down Expand Up @@ -70,14 +70,6 @@ angles = np.arccos(np.clip(cosines, -1.0, 1.0))
angles = vg.angle(v1s, v2s)
```

Features
--------

All functions are optionally vectorized, meaning they accept single inputs and
stacks of inputs interchangeably. They return The Right Thing – a single
result or a stack of results – without the need to reshape inputs or outputs.
With the power of NumPy, the vectorized functions are fast.

Installation
------------

Expand All @@ -100,32 +92,6 @@ projected = vg.scalar_projection(
```


Design principles
-----------------

Linear algebra is useful and it doesn't have to be dificult to use. With the
power of abstractions, simple operations can be made simple, without poring
through lecture slides, textbooks, inscrutable Stack Overflow answers, or
dense NumPy docs. Code that uses linear algebra and geometric transformation
should be readable like English, without compromising efficiency.

These common operations should be abstracted for a few reasons:

1. If a developer is not programming linalg every day, they might forget the
underlying formula. These forms are easier to remember and more easily
referenced.

2. These forms tend to be self-documenting in a way that the NumPy forms are
not. If a developer is not programming linalg every day, this will again
come in handy.

3. These implementations are more robust. They automatically inspect `ndim`
on their arguments, so they work equally well if the argument is a vector
or a stack of vectors. They are more careful about checking edge cases
like a zero norm or zero cross product and returning a correct result
or raising an appropriate error.


Development
-----------

Expand All @@ -139,14 +105,6 @@ Subsequently, run `./dev.py install` to update the dependencies.
[install poetry]: https://python-poetry.org/docs/#installation


Versioning
----------

This library adheres to [Semantic Versioning][semver].

[semver]: https://semver.org/


Acknowledgements
----------------

Expand Down
48 changes: 46 additions & 2 deletions doc/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,57 @@ These common operations should be abstracted for a few reasons:
or raising an appropriate error.


Versioning
----------
Future-proofing your application or library
-------------------------------------------

This library adheres to [Semantic Versioning][semver].

[semver]: https://semver.org/

Since Python can accommodate only one installation of a package, using a
toolbelt like `vg` as a transitive dependency can be a particular challenge, as
various dependencies in the tree may rely on different versions of vg.

One option would be to avoid making breaking changes forevever. However this is
antithetical to one of the goals of the project, which is to make a friendly
interface for doing linear algebra. Experience has shown that over the years,
we get clearer about what does and doesn't belong in this library, and what ways
of exposing this functionality are easiest to learn. We want to continue to
improve the interface over time, even if it means small breaking changes.

As a result, we provide a forward compatibility layer, which all libraries
depending on `vg` are encouraged to use. Replace `import vg` with
`from vg.compat import v1 as vg` and use `>=1.11` as your dependency specifier.
You can also replace 1.11 with a later version which includes a feature you
need. The important thing is not to use `>=1.11,<2`. Since this project
guarantees that `from vg.compat import v1 as vg` will continue to work the same
in 2.0+, the `<2` constraint provides no stability value &ndash; and it makes
things unnecessarily difficult for consumers who use multiple dependencies with
`vg`.

Applications have two options:

1. Follow the recommendation for libraries: specify `>=1.11` and import using
`from vg.compat import v1 as vg`. This option provides better code stability
and makes upgrades seamless.
2. Specify `>=1.11,<2` and use `import vg` directly, and when upgrading to
`>=2,<3`, review the changelog and modify the calling code if necessary.
This option ensures you stay up to date with the recommended, friendliest
interface for calling into `vg`.

### Breaking changes

The project's goal is to limit breaking changes to the API to every one to two
years. This means breaking changes must be batched. Typically such features are
first made available under the `vg.experimental` module, and then moved into
`vg` upon the next major version release. Such experimental features may change
in any subsequent minor release.

### Deprecations

Deprecated features will emit deprecation warnings in a minor version and cause
errors or incorrect behavior in the next major version.


If you like vg you might also like &hellip;
-------------------------------------------
Expand Down
Empty file added vg/compat/__init__.py
Empty file.
21 changes: 21 additions & 0 deletions vg/compat/test_v1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import numpy as np
import pytest
import vg.compat.v1 as vg


def test_v1_has_functions():
np.testing.assert_array_equal(
vg.normalize(np.array([5, 0, 0])), np.array([1, 0, 0])
)


def test_v1_has_constants():
np.testing.assert_array_equal(vg.basis.x, np.array([1, 0, 0]))


def test_v1_orient_is_alias_for_aligned_with():
v1 = np.array([1.0, 2.0, 3.0])
with pytest.deprecated_call():
np.testing.assert_array_equal(
vg.orient(v1, along=vg.basis.z), vg.aligned_with(v1, along=vg.basis.z)
)
1 change: 1 addition & 0 deletions vg/compat/v1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from ..core import * # noqa: F401, F403

0 comments on commit 900413e

Please sign in to comment.