Skip to content

Commit 6b84411

Browse files
committed
Tests and style
1 parent b39d89b commit 6b84411

File tree

15 files changed

+571
-129
lines changed

15 files changed

+571
-129
lines changed

.github/FUNDING.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
# These are supported funding model platforms
3+
4+
patreon: sobolevn

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ install: poetry install
1414

1515
script:
1616
- poetry run flake8 .
17-
- poetry run mypy safe_assert
17+
- poetry run mypy classes tests/**/*.py
1818
- poetry run pytest
1919
- poetry check
2020
- poetry run pip check

CONTRIBUTING.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# How to contribute
2+
3+
## Tutorials
4+
5+
If you want to start working on this project,
6+
you will need to get familiar with these concepts:
7+
8+
- <http://learnyouahaskell.com/types-and-typeclasses>
9+
- <https://en.wikipedia.org/wiki/Type_class>
10+
11+
Similar projects:
12+
13+
- <https://github.com/thejohnfreeman/python-typeclasses>
14+
- <https://docs.python.org/3/library/functools.html#functools.singledispatch>
15+
16+
## Dependencies
17+
18+
We use [`poetry`](https://github.com/sdispater/poetry) to manage the dependencies.
19+
20+
To install them you would need to run `install` command:
21+
22+
```bash
23+
poetry install
24+
```
25+
26+
To activate your `virtualenv` run `poetry shell`.
27+
28+
29+
## Tests
30+
31+
We use `pytest` and `flake8` for quality control.
32+
We also use `wemake_python_styleguide` to enforce the code quality.
33+
34+
To run all tests:
35+
36+
```bash
37+
pytest
38+
```
39+
40+
To run linting:
41+
42+
```bash
43+
flake8 .
44+
```
45+
46+
These steps are mandatory during the CI.
47+
48+
## Type checks
49+
50+
We use `mypy` to run type checks on our code.
51+
To use it:
52+
53+
```bash
54+
mypy returns tests/**/*.py
55+
```
56+
57+
This step is mandatory during the CI.
58+
59+
60+
## Submitting your code
61+
62+
We use [trunk based](https://trunkbaseddevelopment.com/)
63+
development (we also sometimes call it `wemake-git-flow`).
64+
65+
What the point of this method?
66+
67+
1. We use protected `master` branch,
68+
so the only way to push your code is via pull request
69+
2. We use issue branches: to implement a new feature or to fix a bug
70+
create a new branch named `issue-$TASKNUMBER`
71+
3. Then create a pull request to `master` branch
72+
4. We use `git tag`s to make releases, so we can track what has changed
73+
since the latest release
74+
75+
So, this way we achieve an easy and scalable development process
76+
which frees us from merging hell and long-living branches.
77+
78+
In this method, the latest version of the app is always in the `master` branch.
79+
80+
### Before submitting
81+
82+
Before submitting your code please do the following steps:
83+
84+
1. Run `pytest` to make sure everything was working before
85+
2. Add any changes you want
86+
3. Add tests for the new changes
87+
4. Edit documentation if you have changed something significant
88+
5. Update `CHANGELOG.md` with a quick summary of your changes
89+
6. Run `pytest` again to make sure it is still working
90+
7. Run `mypy` to ensure that types are correct
91+
8. Run `flake8` to ensure that style is correct
92+
9. Run `doc8` to ensure that docs are correct
93+
94+
95+
## Other help
96+
97+
You can contribute by spreading a word about this library.
98+
It would also be a huge contribution to write
99+
a short article on how you are using this project.
100+
You can also share your best practices with us.

README.md

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,37 @@
1313

1414
-----
1515

16-
Use smart, ad-hoc, typed polymorphism for your data types.
16+
Smart, pythonic, ad-hoc, typed polymorphism for Python.
1717

1818

1919
## Features
2020

21-
- WIP
21+
- Provides a bunch of primitives to write declarative business logic
22+
- Enforces better architecture
23+
- Fully typed with annotations and checked with `mypy`, [PEP561 compatible](https://www.python.org/dev/peps/pep-0561/)
24+
- Allows to write a lot of simple code without inheritance or interfaces
25+
- Pythonic and pleasant to write and to read (!)
26+
- Easy to start: has lots of docs, tests, and tutorials
27+
28+
29+
## Installation
30+
31+
```bash
32+
pip install classes
33+
```
34+
35+
You might also want to [configure](https://classes.readthedocs.io/en/latest/pages/container.html#type-safety)
36+
`mypy` correctly and install our plugin
37+
to fix [this existing issue](https://github.com/python/mypy/issues/3157):
38+
39+
```ini
40+
# In setup.cfg or mypy.ini:
41+
[mypy]
42+
plugins =
43+
classes.contrib.mypy.typeclass_plugin
44+
```
45+
46+
We also recommend to use the same `mypy` settings [we use](https://github.com/wemake-services/wemake-python-styleguide/blob/master/styles/mypy.toml).
47+
48+
Make sure you know how to get started, [check out our docs](https://classes.readthedocs.io/en/latest/)!
49+

classes/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@
77
so mypy's ``implicit_reexport`` rule will be happy.
88
"""
99

10+
from classes.typeclass import TypeClass as TypeClass
1011
from classes.typeclass import typeclass as typeclass

classes/contrib/mypy/typeclass_plugin.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
66
Features:
77
8-
- We return a valid ``typeclass`` generic instance from `@typeclass` contructor
8+
- We return a valid ``typeclass`` generic instance
9+
from ``@typeclass`` contructor
910
- We force ``.instance()`` calls to extend the union of allowed types
1011
- We ensure that when calling the typeclass'es function
1112
we know what values can be used as inputs
@@ -15,12 +16,13 @@
1516
1617
We use ``pytest-mypy-plugins`` to test that it works correctly, see:
1718
https://github.com/TypedDjango/pytest-mypy-plugins
19+
1820
"""
1921

2022
from typing import Type
2123

2224
from mypy.plugin import Plugin
23-
from mypy.types import AnyType, UnionType, TypeOfAny, CallableType
25+
from mypy.types import AnyType, CallableType, TypeOfAny, TypeVarType, UnionType
2426

2527

2628
def _adjust_arguments(ctx):
@@ -79,28 +81,28 @@ def _adjust_typeclass_type(self, ctx, instance_type):
7981
# It means that function was defined without annotation
8082
# or with explicit `Any`, we prevent our Union from polution.
8183
# Because `Union[Any, int]` is just `Any`.
82-
lambda type_: not isinstance(type_, AnyType),
84+
# We also clear accidential type vars.
85+
self._filter_out_unified_types,
8386
[instance_type, ctx.type.args[0]],
8487
))
8588

86-
if len(unified) == 1:
87-
# We don't want to mix `Union[A]` into the types,
88-
# which sometimes works just like an alias for `Optional[A]`:
89-
ctx.type.args[0] = instance_type
90-
else:
91-
ctx.type.args[0] = UnionType(unified)
89+
if not isinstance(instance_type, TypeVarType):
90+
ctx.type.args[0] = UnionType.make_union(unified)
91+
92+
def _filter_out_unified_types(self, type_) -> bool:
93+
return not isinstance(type_, (AnyType, TypeVarType))
9294

9395

9496
class _TypedDecoratorPlugin(Plugin):
9597
def get_method_signature_hook(self, fullname: str):
9698
"""Here we fix the calling method types to accept only valid types."""
97-
if fullname == 'classes.typeclass._TypeClassMethod.__call__':
99+
if fullname == 'classes.typeclass.TypeClass.__call__':
98100
return _adjust_call_signature
99101
return None
100102

101103
def get_method_hook(self, fullname: str):
102104
"""Here we adjust the typeclass with new allowed types."""
103-
if fullname == 'classes.typeclass._TypeClassMethod.instance':
105+
if fullname == 'classes.typeclass.TypeClass.instance':
104106
return _AdjustInstanceSignature().instance
105107
return None
106108

classes/functions.py

Lines changed: 0 additions & 59 deletions
This file was deleted.

0 commit comments

Comments
 (0)