diff --git a/.idea/misc.xml b/.idea/misc.xml
index fcb32da..f9beed9 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -3,5 +3,5 @@
-
+
\ No newline at end of file
diff --git a/.idea/platonic.iml b/.idea/platonic.iml
index 1b7aea9..dd04a93 100644
--- a/.idea/platonic.iml
+++ b/.idea/platonic.iml
@@ -2,19 +2,18 @@
-
+
-
+
-
\ No newline at end of file
diff --git a/README.md b/README.md
index 86e485e..efacde2 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,5 @@
# platonic
-[](https://wemake.services)
[](https://travis-ci.com/python-platonic/platonic)
[](https://coveralls.io/github/python-platonic/platonic?branch=master)
[](https://pypi.org/project/platonic/)
diff --git a/platonic-amazon-s3/Makefile b/platonic-amazon-s3/Makefile
deleted file mode 100644
index 7db08e4..0000000
--- a/platonic-amazon-s3/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-develop:
- ../venv/bin/pip install -e .[dev]
diff --git a/platonic-amazon-s3/README.md b/platonic-amazon-s3/README.md
deleted file mode 100644
index db395be..0000000
--- a/platonic-amazon-s3/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# S3 backed data structures
\ No newline at end of file
diff --git a/platonic-amazon-s3/platonic_amazon_s3/__init__.py b/platonic-amazon-s3/platonic_amazon_s3/__init__.py
deleted file mode 100644
index 81d8b93..0000000
--- a/platonic-amazon-s3/platonic_amazon_s3/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from .iterators import S3RecursiveKeyStream
diff --git a/platonic-amazon-s3/platonic_amazon_s3/iterators.py b/platonic-amazon-s3/platonic_amazon_s3/iterators.py
deleted file mode 100644
index dcc2dee..0000000
--- a/platonic-amazon-s3/platonic_amazon_s3/iterators.py
+++ /dev/null
@@ -1,49 +0,0 @@
-from urllib.parse import urlparse
-
-import boto3
-from boto3_type_annotations import s3
-from botocore.paginate import PageIterator
-from typing import Iterator, Optional
-
-from sorted.sorted import Sorted
-from platonic import Iterable
-
-
-def is_not_a_directory(url: str):
- return not url.endswith('/')
-
-
-class S3RecursiveKeyStream(Sorted, Iterable[str]):
- url: Optional[str] = None
-
- def __init__(self, url: Optional[str] = None):
- if url is not None:
- self.url = url
-
- if self.url is None:
- raise ValueError(f'{self} does not have `url` defined.')
-
- def _recurse(self) -> Iterator[str]:
- """Stream of all file URLs on Data Lake S3 bucket."""
-
- client: s3.Client = boto3.client('s3')
-
- decoded_url = urlparse(self.url)
- bucket_name = decoded_url.netloc
-
- paginator = client.get_paginator('list_objects_v2')
-
- page_iterator: PageIterator = paginator.paginate(
- Bucket=bucket_name,
- Prefix=decoded_url.path.lstrip('/'),
- )
-
- for page in page_iterator:
- records = page.get('Contents', [])
-
- for record in records:
- key = record['Key']
- yield f's3://{bucket_name}/{key}'
-
- def __iter__(self):
- return self._recurse()
diff --git a/platonic-amazon-s3/setup.py b/platonic-amazon-s3/setup.py
deleted file mode 100644
index 5bdcffc..0000000
--- a/platonic-amazon-s3/setup.py
+++ /dev/null
@@ -1,32 +0,0 @@
-import setuptools
-
-with open("README.md", "r") as fh:
- long_description = fh.read()
-
-setuptools.setup(
- name="platonic-amazon-s3",
- version="0.0.1",
- author="Anatoly Scherbakov",
- author_email="altaisoft@gmail.com",
- description=(
- "S3 backend for some of platonic data structures."
- ),
- long_description=long_description,
- long_description_content_type="text/markdown",
- url='https://github.com/anatoly-scherbakov/platonic',
- packages=setuptools.find_packages(),
- install_requires=[
-
- ],
- extras_require={
- 'dev': [
- 'pytest',
- 'boto3'
- ]
- },
- classifiers=[
- "Programming Language :: Python :: 3",
- "License :: OSI Approved :: MIT License",
- "Operating System :: OS Independent",
- ],
-)
diff --git a/platonic-amazon-s3/tests/test_init.py b/platonic-amazon-s3/tests/test_init.py
deleted file mode 100644
index 69b5ac3..0000000
--- a/platonic-amazon-s3/tests/test_init.py
+++ /dev/null
@@ -1,20 +0,0 @@
-import itertools
-
-import pytest
-
-from platonic_amazon_s3 import S3RecursiveKeyStream
-
-
-class TestKeyStream(S3RecursiveKeyStream):
- url = 's3://homo-yetiensis'
-
-
-@pytest.mark.skip('Integration test')
-def test_initialize():
- piece = itertools.islice(
- TestKeyStream(),
- 10
- )
-
- for item in piece:
- print(item)
diff --git a/platonic-redis/Makefile b/platonic-redis/Makefile
deleted file mode 100644
index 7db08e4..0000000
--- a/platonic-redis/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-develop:
- ../venv/bin/pip install -e .[dev]
diff --git a/platonic-redis/README.md b/platonic-redis/README.md
deleted file mode 100644
index d74303d..0000000
--- a/platonic-redis/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# Redis backend for Mapping
\ No newline at end of file
diff --git a/platonic-redis/platonic_redis/__init__.py b/platonic-redis/platonic_redis/__init__.py
deleted file mode 100644
index 22e9abb..0000000
--- a/platonic-redis/platonic_redis/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from .redis_box import RedisBox
-from .redis_mapping import RedisMapping
-from .redis_mutable_mapping import RedisMutableMapping
diff --git a/platonic-redis/platonic_redis/base.py b/platonic-redis/platonic_redis/base.py
deleted file mode 100644
index bb5e3ab..0000000
--- a/platonic-redis/platonic_redis/base.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from redis import Redis
-
-
-class RedisMixin:
- url = 'localhost'
-
- _connection: Redis = None
-
- def create_connection(self):
- return Redis(self.url)
-
- @property
- def redis(self):
- if self._connection is None:
- self._connection = self.create_connection()
-
- return self._connection
diff --git a/platonic-redis/platonic_redis/redis_box.py b/platonic-redis/platonic_redis/redis_box.py
deleted file mode 100644
index fc33ab0..0000000
--- a/platonic-redis/platonic_redis/redis_box.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from typing import TypeVar, Optional
-
-from platonic.box import AbstractBox
-from .base import RedisMixin
-
-T = TypeVar('T')
-
-
-class RedisBox(RedisMixin, AbstractBox[T]):
- name: str
- encoding = 'utf-8'
-
- def deserialize(self, raw_value: Optional[bytes]) -> T:
- if raw_value is None:
- return self.ValueType()
- else:
- return raw_value.decode(self.encoding)
-
- def serialize(self, value: T) -> bytes:
- return bytes(value, encoding=self.encoding)
-
- @property
- def value(self) -> T:
- return self.deserialize(self.redis.get(self.name))
-
- @value.setter
- def value(self, value: T):
- # FIXME str() is not necessarily the best serialization to hardcode
- self.redis.set(self.name, self.serialize(value))
diff --git a/platonic-redis/platonic_redis/redis_mapping.py b/platonic-redis/platonic_redis/redis_mapping.py
deleted file mode 100644
index a0376d8..0000000
--- a/platonic-redis/platonic_redis/redis_mapping.py
+++ /dev/null
@@ -1,22 +0,0 @@
-import typing
-
-from redis import Redis
-from .base import RedisMixin
-
-
-class RedisMapping(RedisMixin, typing.Mapping):
- name = 'test'
-
- def __getitem__(self, k):
- value = self.redis.hget(self.name, k)
- if value is None:
- raise KeyError(k)
-
- else:
- return value
-
- def __iter__(self):
- return self.redis.hscan_iter(self.name)
-
- def __len__(self):
- return self.redis.hlen(self.name)
diff --git a/platonic-redis/platonic_redis/redis_mutable_mapping.py b/platonic-redis/platonic_redis/redis_mutable_mapping.py
deleted file mode 100644
index eeb3d28..0000000
--- a/platonic-redis/platonic_redis/redis_mutable_mapping.py
+++ /dev/null
@@ -1,11 +0,0 @@
-import typing
-
-from .redis_mapping import RedisMapping
-
-
-class RedisMutableMapping(RedisMapping, typing.MutableMapping):
- def __delitem__(self, key) -> None:
- self.redis.hdel(self.name, key)
-
- def __setitem__(self, k, v) -> None:
- self.redis.hset(self.name, k, v)
diff --git a/platonic-redis/setup.py b/platonic-redis/setup.py
deleted file mode 100644
index 84f5054..0000000
--- a/platonic-redis/setup.py
+++ /dev/null
@@ -1,31 +0,0 @@
-import setuptools
-
-with open("README.md", "r") as fh:
- long_description = fh.read()
-
-setuptools.setup(
- name="platonic-redis",
- version="0.0.1",
- author="Anatoly Scherbakov",
- author_email="altaisoft@gmail.com",
- description=(
- "Redis backend for Mapping."
- ),
- long_description=long_description,
- long_description_content_type="text/markdown",
- url='https://github.com/anatoly-scherbakov/platonic',
- packages=setuptools.find_packages(),
- install_requires=[
- 'redis'
- ],
- extras_require={
- 'dev': [
- 'pytest',
- ]
- },
- classifiers=[
- "Programming Language :: Python :: 3",
- "License :: OSI Approved :: MIT License",
- "Operating System :: OS Independent",
- ],
-)
diff --git a/platonic-redis/tests/test_box.py b/platonic-redis/tests/test_box.py
deleted file mode 100644
index d9fd07e..0000000
--- a/platonic-redis/tests/test_box.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from platonic import Box, register
-from platonic_redis import RedisBox
-
-
-class SiteNameBox(Box[str]):
- """Storing our site name"""
-
-
-@register(SiteNameBox)
-class RedisSiteNameBox(RedisBox):
- name = 'site-name'
-
-
-def test_empty():
- assert SiteNameBox().value is ''
-
-
-def test_set():
- box = SiteNameBox()
- box.value = 'John Connor'
-
- assert box.value == 'John Connor'
diff --git a/platonic-redis/tests/test_initialize.py b/platonic-redis/tests/test_initialize.py
deleted file mode 100644
index 7c53173..0000000
--- a/platonic-redis/tests/test_initialize.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from platonic import MutableMapping, register
-from platonic_redis import RedisMutableMapping
-import typing_inspect
-
-
-class Cats(MutableMapping[str, str]):
- pass
-
-
-@register(Cats)
-class RedisCats(RedisMutableMapping):
- pass
-
-
-def test_init():
- Cats()
diff --git a/platonic/Makefile b/platonic/Makefile
deleted file mode 100644
index 7db08e4..0000000
--- a/platonic/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-develop:
- ../venv/bin/pip install -e .[dev]
diff --git a/platonic/README.md b/platonic/README.md
deleted file mode 100644
index a82a1ff..0000000
--- a/platonic/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# platonic
diff --git a/platonic/__init__.py b/platonic/__init__.py
index 40a96af..1f63f31 100644
--- a/platonic/__init__.py
+++ b/platonic/__init__.py
@@ -1 +1,5 @@
-# -*- coding: utf-8 -*-
+from .model import Model
+
+# Data structures
+from .mapping.mapping import Mapping as Mapping
+from .mutable_mapping.mutable_mapping import MutableMapping
diff --git a/platonic/platonic/mapping/__init__.py b/platonic/mapping/__init__.py
similarity index 100%
rename from platonic/platonic/mapping/__init__.py
rename to platonic/mapping/__init__.py
diff --git a/platonic/mapping/mapping.py b/platonic/mapping/mapping.py
new file mode 100644
index 0000000..b137da3
--- /dev/null
+++ b/platonic/mapping/mapping.py
@@ -0,0 +1,53 @@
+import typing
+from abc import ABC
+
+from ..model import Model
+
+
+KeyType = typing.TypeVar('KeyType')
+ValueType = typing.TypeVar('ValueType')
+
+
+class Mapping(Model, typing.Mapping[KeyType, ValueType], ABC):
+ KeyType: type
+ ValueType: type
+
+ def __class_getitem__(cls, args: typing.Tuple[type, type]) -> type:
+ if (
+ # We have to check the types of arguments here to ensure
+ # the structure is used properly. mypy does not condone that.
+ not isinstance(args, tuple) # type: ignore
+ or len(args) != 2
+ ):
+ raise TypeError(
+ f'Class {cls.__name__} requires exactly two type arguments, '
+ f'Key type and Value type. For example:'
+ f'\n'
+ f' {cls.__name__}[str, int]\n'
+ f'\n'
+ f'means a mapping from strings to integers. Instead, the type '
+ f'arguments are: {args}.'
+ )
+
+ key_type, value_type = args
+
+ if not isinstance(key_type, type):
+ raise ValueError(
+ f'Key type {key_type} is a {type(key_type)} value; '
+ f'a type expected.'
+ )
+
+ if not isinstance(value_type, type):
+ raise ValueError(
+ f'Value type {value_type} is a {type(value_type)} value; '
+ f'a type expected.'
+ )
+
+ return type(
+ f'{cls.__name__}[{key_type.__name__}, {value_type.__name__}]',
+ (cls, ),
+ {
+ 'KeyType': key_type,
+ 'ValueType': value_type
+ }
+ )
diff --git a/platonic/model.py b/platonic/model.py
new file mode 100644
index 0000000..c9891bd
--- /dev/null
+++ b/platonic/model.py
@@ -0,0 +1,8 @@
+from abc import ABC
+
+
+PROXY_CLASS_ATTRIBUTE = '__is_proxy_class'
+
+
+class Model(ABC):
+ pass
diff --git a/platonic/platonic/mutable_mapping/__init__.py b/platonic/mutable_mapping/__init__.py
similarity index 53%
rename from platonic/platonic/mutable_mapping/__init__.py
rename to platonic/mutable_mapping/__init__.py
index 3259236..4e78f2b 100644
--- a/platonic/platonic/mutable_mapping/__init__.py
+++ b/platonic/mutable_mapping/__init__.py
@@ -1,2 +1 @@
from .mutable_mapping import MutableMapping
-from .dict_mapping import DictMapping
diff --git a/platonic/platonic/mutable_mapping/mutable_mapping.py b/platonic/mutable_mapping/mutable_mapping.py
similarity index 58%
rename from platonic/platonic/mutable_mapping/mutable_mapping.py
rename to platonic/mutable_mapping/mutable_mapping.py
index a167260..1bf0289 100644
--- a/platonic/platonic/mutable_mapping/mutable_mapping.py
+++ b/platonic/mutable_mapping/mutable_mapping.py
@@ -1,14 +1,16 @@
import typing
from abc import ABC
-from platonic.mapping import Mapping
+from platonic import Mapping
KeyType = typing.TypeVar('KeyType')
ValueType = typing.TypeVar('ValueType')
+# I am not entirely sure how to inherit from a generic type; mypy is very
+# unhappy
class MutableMapping(
- Mapping,
+ Mapping, # type: ignore
typing.MutableMapping[KeyType, ValueType],
ABC
):
diff --git a/platonic/platonic/__init__.py b/platonic/platonic/__init__.py
deleted file mode 100644
index 73fef06..0000000
--- a/platonic/platonic/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from .model import Model
-from .register import register
-
-# Data structures
-from .box import Box
-
-from .mapping import Mapping
-from .mutable_mapping import MutableMapping
-
-from .iterable import Iterable
diff --git a/platonic/platonic/box/__init__.py b/platonic/platonic/box/__init__.py
deleted file mode 100644
index d493a41..0000000
--- a/platonic/platonic/box/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from .abstract import AbstractBox
-from .model import Box
-from .implementation import ValueBox
diff --git a/platonic/platonic/box/abstract.py b/platonic/platonic/box/abstract.py
deleted file mode 100644
index a79ce9f..0000000
--- a/platonic/platonic/box/abstract.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from abc import abstractmethod
-from typing import TypeVar, Generic, Type, Any
-
-T = TypeVar('T')
-
-
-class AbstractBox(Generic[T]):
- ValueType: Type[T] = Any
-
- __marker = object()
-
- def __init__(self, value: T = __marker):
- if not (value is self.__marker):
- self.value = value
-
- @property
- @abstractmethod
- def value(self) -> T:
- raise NotImplementedError()
-
- @value.setter
- @abstractmethod
- def value(self, value: T):
- raise NotImplementedError()
diff --git a/platonic/platonic/box/implementation.py b/platonic/platonic/box/implementation.py
deleted file mode 100644
index 40804fd..0000000
--- a/platonic/platonic/box/implementation.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from typing import TypeVar
-
-from .abstract import AbstractBox
-
-T = TypeVar('T')
-
-
-class ValueBox(AbstractBox[T]):
- _value: T
-
- @property
- def value(self) -> T:
- return self._value
-
- @value.setter
- def value(self, value: T):
- self._value = value
diff --git a/platonic/platonic/box/model.py b/platonic/platonic/box/model.py
deleted file mode 100644
index 82e8ea6..0000000
--- a/platonic/platonic/box/model.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from typing import TypeVar
-
-from platonic import Model
-from .abstract import AbstractBox
-
-
-T = TypeVar('T')
-
-
-class Box(Model, AbstractBox[T]):
- @classmethod
- def __validate_type_args__(cls, args) -> dict:
- value_type, = args
- return {
- 'ValueType': value_type
- }
diff --git a/platonic/platonic/iterable/__init__.py b/platonic/platonic/iterable/__init__.py
deleted file mode 100644
index 4840066..0000000
--- a/platonic/platonic/iterable/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from .iterable import Iterable
diff --git a/platonic/platonic/iterable/iterable.py b/platonic/platonic/iterable/iterable.py
deleted file mode 100644
index 04c6dff..0000000
--- a/platonic/platonic/iterable/iterable.py
+++ /dev/null
@@ -1,9 +0,0 @@
-import typing
-
-from platonic import Model
-
-ValueType = typing.TypeVar('ValueType')
-
-
-class Iterable(typing.Iterable[ValueType], Model):
- pass
diff --git a/platonic/platonic/mapping/mapping.py b/platonic/platonic/mapping/mapping.py
deleted file mode 100644
index 7ef3923..0000000
--- a/platonic/platonic/mapping/mapping.py
+++ /dev/null
@@ -1,35 +0,0 @@
-import typing
-from abc import ABC
-
-from platonic import Model
-
-
-KeyType = typing.TypeVar('KeyType')
-ValueType = typing.TypeVar('ValueType')
-
-
-class Mapping(Model, typing.Mapping[KeyType, ValueType], ABC):
- KeyType: typing.Type = typing.Any
- ValueType: typing.Type = typing.Any
-
- @classmethod
- def __validate_type_args__(cls, args) -> dict:
- if args is None:
- raise TypeError(f'Type args missing for {cls}.')
-
- elif not isinstance(args, tuple):
- raise ValueError(
- f'Type args for {cls} should be a tuple, {args} found instead.'
- )
-
- elif len(args) != 2:
- raise ValueError(
- f'Exactly 2 type args expected for {cls}, {args} found instead.'
- )
-
- key_type, value_type = args
-
- return {
- 'KeyType': key_type,
- 'ValueType': value_type
- }
diff --git a/platonic/platonic/model.py b/platonic/platonic/model.py
deleted file mode 100644
index c5fa21c..0000000
--- a/platonic/platonic/model.py
+++ /dev/null
@@ -1,69 +0,0 @@
-from abc import ABC
-from typing_inspect import is_typevar
-
-
-PROXY_CLASS_ATTRIBUTE = '__is_proxy_class'
-
-
-def create_proxy_class(cls):
- concrete_class = cls.__backend__
- abstract_class = cls
-
- if concrete_class is None:
- raise TypeError(
- f'{abstract_class} does not have a backend defined. Please use '
- f'platonic.register() decorator to assign one.'
- )
-
- bases = (
- concrete_class,
- abstract_class
- )
-
- class_name = f'{abstract_class.__name__} via {concrete_class.__name__}'
-
- # noinspection PyTypeChecker
- return type(class_name, bases, {
- PROXY_CLASS_ATTRIBUTE: True,
- # FIXME this means type argument assignment only happens when an
- # instance is instantiated. That is not necessarily the best course
- # of action and an issue should probably be filed.
- **abstract_class.__validate_type_args__(abstract_class.__type_args__)
- })
-
-
-class Model(ABC):
- proxy_class: type = None
- __backend__: type = None
- __type_args__ = None
-
- @classmethod
- def __validate_type_args__(cls, args) -> dict:
- return {}
-
- # noinspection PyUnresolvedReferences
- def __class_getitem__disabled(cls, params):
- if not isinstance(params, tuple):
- params = (params, )
-
- if all(map(is_typevar, params)):
- pass
-
- return type(
- f'{cls.__name__}[{", ".join(param.__name__ for param in params)}]',
- (cls, ),
- {
- '__type_args__': params,
- }
- )
-
- def __new__disabled(cls, *args, **kwargs):
- if getattr(cls, PROXY_CLASS_ATTRIBUTE, False):
- return super().__new__(cls, *args, **kwargs)
-
- if cls.proxy_class is None:
- cls.proxy_class = create_proxy_class(cls)
-
- concrete_class = cls.__backend__
-
- return concrete_class.__new__(cls.proxy_class, *args, **kwargs)
diff --git a/platonic/platonic/mutable_mapping/dict_mapping.py b/platonic/platonic/mutable_mapping/dict_mapping.py
deleted file mode 100644
index ebb67c3..0000000
--- a/platonic/platonic/mutable_mapping/dict_mapping.py
+++ /dev/null
@@ -1,2 +0,0 @@
-class DictMapping(dict):
- """Implementation of a Mapping based on a standard dict."""
diff --git a/platonic/platonic/register.py b/platonic/platonic/register.py
deleted file mode 100644
index a9dc758..0000000
--- a/platonic/platonic/register.py
+++ /dev/null
@@ -1,14 +0,0 @@
-def register(abstract_class):
- def _registerer(concrete_class):
- if getattr(abstract_class, '__backend__', None):
- raise ValueError(
- f'{abstract_class.__backend__} is already registered '
- f'as a backend for {abstract_class}; cannot register '
- f'{concrete_class} as another one.'
- )
- else:
- abstract_class.__backend__ = concrete_class
-
- return concrete_class
-
- return _registerer
diff --git a/platonic/setup.py b/platonic/setup.py
deleted file mode 100644
index 8293d75..0000000
--- a/platonic/setup.py
+++ /dev/null
@@ -1,33 +0,0 @@
-import setuptools
-
-with open("README.md", "r") as fh:
- long_description = fh.read()
-
-setuptools.setup(
- name="platonic",
- version="2.0.0",
- author="Anatoly Scherbakov",
- author_email="altaisoft@gmail.com",
- description=(
- "A library of common data structures with implementable backends."
- ),
- long_description=long_description,
- long_description_content_type="text/markdown",
- url='https://github.com/anatoly-scherbakov/platonic',
- packages=setuptools.find_packages(),
- install_requires=[
- 'typing_inspect'
- ],
- extras_require={
- 'dev': [
- 'pytest',
- 'boto3',
- 'boto3_type_annotations'
- ]
- },
- classifiers=[
- "Programming Language :: Python :: 3",
- "License :: OSI Approved :: MIT License",
- "Operating System :: OS Independent",
- ],
-)
diff --git a/platonic/tests/__init__.py b/platonic/tests/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/platonic/tests/test_abstract.py b/platonic/tests/test_abstract.py
deleted file mode 100644
index db6559b..0000000
--- a/platonic/tests/test_abstract.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from abc import abstractmethod
-
-from platonic import Model, register
-
-
-class Cat(Model):
- @abstractmethod
- def meow(self):
- raise NotImplementedError()
-
-
-# noinspection PyMethodMayBeStatic
-@register(Cat)
-class CatBackend:
- def meow(self):
- return 'meow'
-
-
-def test_inherit():
- assert Cat().meow() == 'meow'
diff --git a/platonic/tests/test_box/__init__.py b/platonic/tests/test_box/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/platonic/tests/test_box/test_implementation.py b/platonic/tests/test_box/test_implementation.py
deleted file mode 100644
index e74ffb1..0000000
--- a/platonic/tests/test_box/test_implementation.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from platonic import register
-from platonic.box import Box, ValueBox
-
-
-class IntBox(Box[int]):
- pass
-
-
-@register(IntBox)
-class ValueIntBox(ValueBox):
- pass
-
-
-def test_init():
- assert IntBox(5).value == 5
-
-
-def test_assign():
- b = IntBox(5)
- b.value = 8
- assert b.value == 8
diff --git a/platonic/tests/test_dict_mapping.py b/platonic/tests/test_dict_mapping.py
deleted file mode 100644
index 02ae02c..0000000
--- a/platonic/tests/test_dict_mapping.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from abc import ABC
-
-from platonic import register, MutableMapping
-from platonic.mutable_mapping import DictMapping
-
-
-class MyMapping(MutableMapping[str, str]):
- pass
-
-
-@register(MyMapping)
-class MyDictMapping(DictMapping):
- pass
-
-
-def test_dict_mapping():
- m = MyMapping()
-
- assert isinstance(m, MyDictMapping)
- assert m.__class__.__name__ == 'MyMapping via MyDictMapping'
-
- m['a'] = 'b'
-
- assert len(m) == 1
- assert m.pop('a') == 'b'
diff --git a/platonic/tests/test_model/__init__.py b/platonic/tests/test_model/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/platonic/tests/test_model/test_type_args.py b/platonic/tests/test_model/test_type_args.py
deleted file mode 100644
index 4f95657..0000000
--- a/platonic/tests/test_model/test_type_args.py
+++ /dev/null
@@ -1,43 +0,0 @@
-import typing
-
-import pytest
-
-from platonic import Mapping, register, Model
-
-
-class Marks(Mapping[str, int]):
- pass
-
-
-@register(Marks)
-class DictMarks(dict):
- pass
-
-
-class Majors(Mapping):
- pass
-
-
-@register(Majors)
-class DictMajors(dict):
- pass
-
-
-def test_class_getitem():
- subclass = Mapping[str, str]
- assert subclass.__name__ == 'Mapping[str, str]'
-
-
-def test_overlap():
- assert Majors.__type_args__ is None
- assert Marks.__type_args__ == (str, int)
-
- marks = Marks()
- assert marks.KeyType is str
- assert marks.ValueType is int
-
- with pytest.raises(TypeError):
- majors = Majors()
-
- assert Majors.KeyType is typing.Any
- assert Majors.ValueType is typing.Any
diff --git a/platonic/tests/test_new.py b/platonic/tests/test_new.py
deleted file mode 100644
index d064e28..0000000
--- a/platonic/tests/test_new.py
+++ /dev/null
@@ -1,42 +0,0 @@
-import typing
-import platonic
-import dataclasses
-
-
-@dataclasses.dataclass(frozen=True)
-class Cat:
- color: str
- age: int
-
-
-class Cats(platonic.MutableMapping[str, Cat]):
- pass
-
-
-@platonic.register(Cats)
-class CatsBackend(typing.MutableMapping):
- def __delitem__(self, v) -> None:
- pass
-
- def __getitem__(self, k):
- pass
-
- def __len__(self) -> int:
- pass
-
- def __iter__(self):
- pass
-
- def __setitem__(self, k, v) -> None:
- pass
-
-
-def test_initialize():
- cats = Cats()
- assert isinstance(cats, Cats)
- assert isinstance(cats, CatsBackend)
- assert cats.__class__.__name__ == 'Cats via CatsBackend'
- assert cats.__type_args__ == (str, Cat)
-
- cats2 = Cats()
- assert cats.__class__ == cats2.__class__
diff --git a/platonic/tests/test_register.py b/platonic/tests/test_register.py
deleted file mode 100644
index 4c7de13..0000000
--- a/platonic/tests/test_register.py
+++ /dev/null
@@ -1,46 +0,0 @@
-import pytest
-
-from platonic import register, Model
-
-
-class Cat(Model):
- pass
-
-
-@register(Cat)
-class CatBackend:
- pass
-
-
-class Dog(Model):
- pass
-
-
-def test_register_twice():
- try:
- @register(Cat)
- class PussyBackend:
- pass
-
- except ValueError:
- pass
-
- else:
- assert False, "Exception not raised"
-
-
-def test_backend():
- assert Cat.__backend__ == CatBackend
-
-
-def test_isinstance():
- assert isinstance(Cat(), Cat)
-
-
-def test_no_backend():
- with pytest.raises(TypeError):
- Dog()
-
-
-def test_type_equality():
- assert type(Cat()) == type(Cat())
diff --git a/setup.cfg b/setup.cfg
index fb3fcd5..3e23026 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -24,7 +24,7 @@ i-control-code = False
# Disable some pydocstyle checks:
# Exclude some pydoctest checks globally:
-ignore = D100, D104, D106, D401, W504, X100, RST303, RST304, DAR103, DAR203
+ignore = D100, D104, D106, D401, W504, X100, RST303, RST304, DAR103, DAR203, C101
# Excluding some directories:
exclude =
diff --git a/platonic-amazon-s3/tests/__init__.py b/tests/__init__.py
similarity index 100%
rename from platonic-amazon-s3/tests/__init__.py
rename to tests/__init__.py
diff --git a/platonic-redis/tests/__init__.py b/tests/test_model/__init__.py
similarity index 100%
rename from platonic-redis/tests/__init__.py
rename to tests/test_model/__init__.py
diff --git a/tests/test_model/test_type_args.py b/tests/test_model/test_type_args.py
new file mode 100644
index 0000000..b381683
--- /dev/null
+++ b/tests/test_model/test_type_args.py
@@ -0,0 +1,33 @@
+import typing
+
+import pytest
+
+from platonic import Mapping
+
+
+class Marks(Mapping[str, int], typing.Dict[str, int]):
+ pass
+
+
+def test_none_parameters():
+ with pytest.raises(TypeError):
+ Mapping[None] # type: ignore
+
+
+def test_one_parameter():
+ with pytest.raises(TypeError):
+ Mapping[int] # type: ignore
+
+
+def test_key_not_type():
+ with pytest.raises(ValueError):
+ Mapping[5, str] # type: ignore
+
+
+def test_value_not_type():
+ with pytest.raises(ValueError):
+ Mapping[int, 5] # type: ignore
+
+
+def test_name():
+ assert Mapping[str, str].__name__ == 'Mapping[str, str]'