Skip to content

Commit

Permalink
chore: complete mypy coverage and the build is greenwip
Browse files Browse the repository at this point in the history
  • Loading branch information
Guibod committed Mar 7, 2023
1 parent e932078 commit 06bb7ab
Show file tree
Hide file tree
Showing 19 changed files with 564 additions and 204 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install poetry
poetry install
poetry install --with=types
- name: Lint
run: |
make lint
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ lint: ## Runs black, isort, bandit, flake8 in check mode
poetry run isort --check .
poetry run bandit -r src
poetry run flake8 src tests
poetry run mypy src tests

doc:
poetry run sphinx-build -M html "docs/source" "docs/build"
Expand Down
90 changes: 89 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ httpx = "^0.23.3"
httpx-cache = "^0.7.0"
asgiref = "^3.6.0"

[tool.poetry.group.types]
optional = true

[tool.poetry.group.types.dependencies]
types-aiofiles = "^22.1.0.9"
types-pillow = "^9.4.0.17"
types-pyyaml = "^6.0.12.8"
types-pygments = "^2.14.0.5"
types-python-slugify = "^8.0.0.1"

[tool.poetry.group.docs]
optional = true

Expand Down Expand Up @@ -116,3 +126,16 @@ branch = "main"
build_command = "pip install poetry && make build"
upload_to_pypi = true
upload_to_release = true

[tool.mypy]
python_version = "3.9"

[[tool.mypy.overrides]]
module = [
"httpx_cache",
"ijson",
"appdirs",
"cairosvg"
]
ignore_missing_imports = true

8 changes: 6 additions & 2 deletions src/mightstone/ass/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import logging
from functools import wraps
from typing import Any, AsyncGenerator, Callable, List, TypeVar
from typing import Any, AsyncGenerator, Callable, Coroutine, List, TypeVar, Union

import asyncstdlib
from asgiref.sync import async_to_sync
Expand All @@ -25,7 +25,11 @@ async def aiterator_to_list(ait: AsyncGenerator[T, Any], limit=100) -> List[T]:
R = TypeVar("R")


def synchronize(f: Callable[..., R], docstring: str = None) -> Callable[..., R]:
# TODO: probably bad type returned for AsyncGenerator input
def synchronize(
f: Callable[..., Union[Coroutine[Any, Any, R], AsyncGenerator[R, None]]],
docstring: str = None,
) -> Callable[..., R]:
qname = f"{f.__module__}.{f.__qualname__}"

@wraps(f)
Expand Down
12 changes: 8 additions & 4 deletions src/mightstone/ass/compressor/async_file_obj.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from typing import AsyncIterable, Optional, Union
from typing import AsyncIterable, List, Optional, Union

import aiofiles.threadpool.binary

from mightstone.ass.compressor.codecs import error_import_usage

Expand All @@ -10,7 +12,9 @@ class AsyncFileObj(object):

def __init__(
self,
afd: Union[AsyncIterable[bytes]],
afd: Union[
AsyncIterable[bytes], aiofiles.threadpool.binary.AsyncBufferedReader
],
mode,
compressor,
decompressor,
Expand All @@ -26,7 +30,7 @@ def __init__(
self._buffer = b""
self._buffer_size = buffer_size
self._eof = False
self._lines = []
self._lines: List[bytes] = []
self._index = 0
self._filename = None
self._has_flushed = True
Expand Down Expand Up @@ -98,7 +102,7 @@ async def _write(self, buffer: bytes):
self._has_flushed = False
compressed_data = self._compressor.compress(buffer)
if compressed_data:
return await self._afd.write(compressed_data)
return await self._afd.write(compressed_data) # type: ignore
else:
return 0

Expand Down
13 changes: 7 additions & 6 deletions src/mightstone/containers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import httpx_cache
from appdirs import user_cache_dir
from dependency_injector import containers, providers
from dependency_injector.providers import Factory

from .services.cardconjurer import CardConjurer
from .services.edhrec import EdhRecApi, EdhRecStatic
Expand All @@ -10,33 +11,33 @@

class Container(containers.DeclarativeContainer):
# Gateways
httpx_cache_transport = providers.Factory(
httpx_cache_transport: httpx_cache.AsyncCacheControlTransport = providers.Factory(
httpx_cache.AsyncCacheControlTransport,
cache=httpx_cache.FileCache(cache_dir=user_cache_dir("mightstone")),
)

# Services
scryfall = providers.Factory(
scryfall: Factory[Scryfall] = providers.Factory(
Scryfall,
transport=httpx_cache_transport,
)

edhrec_static = providers.Factory(
edhrec_static: Factory[EdhRecStatic] = providers.Factory(
EdhRecStatic,
transport=httpx_cache_transport,
)

edhrec_api = providers.Factory(
edhrec_api: Factory[EdhRecApi] = providers.Factory(
EdhRecApi,
transport=httpx_cache_transport,
)

card_conjurer = providers.Factory(
card_conjurer: Factory[CardConjurer] = providers.Factory(
CardConjurer,
transport=httpx_cache_transport,
)

mtg_json = providers.Factory(
mtg_json: Factory[MtgJson] = providers.Factory(
MtgJson,
transport=httpx_cache_transport,
)
56 changes: 34 additions & 22 deletions src/mightstone/rule/color.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
import itertools
import logging
from collections import Counter
from typing import Iterable, Iterator, List, Mapping, Sequence, Union
from typing import Dict, Iterable, Iterator, List, Mapping, Sequence, Union, overload

from ordered_set import OrderedSet
from pydantic import constr, validator
from pydantic.types import ConstrainedStr

from mightstone.core import MightstoneModel

logger = logging.getLogger(__name__)


class ColorGlyph(ConstrainedStr):
min_length = 1
max_length = 1
to_lower = True


class Color(MightstoneModel):
symbol: constr(to_lower=True, min_length=1, max_length=1)
symbol: ColorGlyph

def __str__(self):
return f"{{{self.symbol.upper()}}}"
Expand All @@ -21,11 +27,8 @@ def __repr__(self):
return f"Color({self.symbol})"


class ColorPie(MightstoneModel, Sequence[Color]):
colors: List[Color]

@validator("colors")
def sanitize(cls, colors: Iterable[Color]) -> [Color]:
class ColorPie(Sequence[Color]):
def __init__(self, colors: Iterable[Color]):
if not all(isinstance(x, Color) for x in colors):
raise ValueError("Please provide a Color object iterable")

Expand All @@ -37,9 +40,9 @@ def sanitize(cls, colors: Iterable[Color]) -> [Color]:
)

# TODO: search duplicates color values
return list(colors)
self.colors = list(colors)

def __getitem__(self, i: Union[int, str]):
def __getitem__(self, i: Union[int, slice, Union[int, str]]):
if isinstance(i, int):
return self.colors[i]

Expand All @@ -52,7 +55,8 @@ def __len__(self) -> int:
return len(self.colors)

def __iter__(self) -> Iterator[Color]:
return iter(self.colors)
for color in self.colors:
yield color

def shift(self, color: Color, step: int = 1) -> Color:
return self.colors[(step + self.index(color)) % len(self.colors)]
Expand All @@ -66,7 +70,7 @@ def parse(self, identity_as_string: str) -> "Identity":
colors.append(self[letter])
return Identity(self, colors)

def combinations(self) -> ["Identity"]:
def combinations(self) -> List["Identity"]:
"""
A mathematical computation of all possible combinations of colors
This will not provide a proper color pie centric combination though
Expand Down Expand Up @@ -120,10 +124,10 @@ class Identity(Sequence[Color]):
def __init__(self, pie: ColorPie, colors: Iterable[Color]):
self.pie = pie
self.colors = OrderedSet(colors)
self._name = None
self.aliases = []
self._name = ""
self.aliases: List[str] = []

def describe(self, name: str = None, aliases: [str] = None):
def describe(self, name: str = None, aliases: List[str] = None):
if name:
self._name = name
if aliases:
Expand Down Expand Up @@ -159,22 +163,30 @@ def __str__(self):
def __repr__(self):
return f"Identity({self.canonical})"

@overload
def __getitem__(self, i: int) -> Color:
...

@overload
def __getitem__(self, i: slice) -> OrderedSet[Color]:
...

def __getitem__(self, i: Union[int, slice]) -> Union[Color, OrderedSet[Color]]:
return self.colors.__getitem__(i)

def __len__(self):
return len(self.colors)

def __eq__(self, other: "Identity"):
try:
return other.checksum() == self.checksum()
except TypeError:
return False
def __eq__(self, other: object):
if not isinstance(other, Identity):
return NotImplemented

return other.checksum() == self.checksum()


class IdentityMap(Mapping[int, Identity]):
def __init__(self, pie: ColorPie):
self.map = {}
self.map: Dict[int, Identity] = {}
self.pie = pie

def add(self, ident: Identity):
Expand Down Expand Up @@ -208,7 +220,7 @@ def __getitem__(self, k: Union[int, str, Identity]) -> Identity:
def __len__(self) -> int:
return self.map.__len__()

def __iter__(self) -> Iterator[str]:
def __iter__(self) -> Iterator[int]:
return self.map.__iter__()


Expand Down

0 comments on commit 06bb7ab

Please sign in to comment.