Repository: bayatim/cleanarc

Issue:
ch3_project_setup

Discussion:

Patch:
diff --git a/.flake8 b/.flake8
index e67b6ab..9e0d294 100644
--- a/.flake8
+++ b/.flake8
@@ -2,4 +2,4 @@
 # Recommend matching the black line length (default 88),
 # rather than using the flake8 default of 79:
 max-line-length = 75
-ignore = E231, E203, W503
+ignore = E231, E203, W503
\ No newline at end of file
diff --git a/cli.py b/cli.py
new file mode 100644
index 0000000..6b95ba5
--- /dev/null
+++ b/cli.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+
+from rentomatic.repository.memrepo import MemRepo
+from rentomatic.use_cases.room_list import room_list_use_case
+
+rooms = [
+    {
+        "code": "f853578c-fc0f-4e65-81b8-566c5dffa35a",
+        "size": 215,
+        "price": 39,
+        "longitude": -0.09998975,
+        "latitude": 51.75436293,
+    },
+    {
+        "code": "fe2c3195-aeff-487a-a08f-e0bdc0ec6e9a",
+        "size": 405,
+        "price": 66,
+        "longitude": 0.18228006,
+        "latitude": 51.74640997,
+    },
+    {
+        "code": "913694c6-435a-4366-ba0d-da5334a611b2",
+        "size": 56,
+        "price": 60,
+        "longitude": 0.27891577,
+        "latitude": 51.45994069,
+    },
+    {
+        "code": "eed76e77-55c1-41ce-985d-ca49bf6c0585",
+        "size": 93,
+        "price": 48,
+        "longitude": 0.33894476,
+        "latitude": 51.39916678,
+    },
+]
+
+
+
+
+repo = MemRepo(rooms)
+result = room_list_use_case(repo)
+
+print([room.to_dict() for room in result])
\ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
index cf739ff..17b246c 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,3 +1,3 @@
 [tool.black]
 line-length = 75
-target-version = ['py37']
+target-version = ['py37']
\ No newline at end of file
diff --git a/rentomatic/domain/__init__.py b/rentomatic/domain/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/rentomatic/domain/room.py b/rentomatic/domain/room.py
new file mode 100644
index 0000000..5fbe26c
--- /dev/null
+++ b/rentomatic/domain/room.py
@@ -0,0 +1,21 @@
+import uuid
+import dataclasses
+
+
+@dataclasses.dataclass
+class Room:
+    code: uuid.UUID
+    size: int
+    price: int
+    longitude: float
+    latitude: float
+
+    @classmethod
+    def from_dict(cls, d):
+        return cls(**d)
+    
+    def to_dict(self):
+        return dataclasses.asdict(self)
+
+if __name__ == '__main__':
+    pass
\ No newline at end of file
diff --git a/rentomatic/repository/__init__.py b/rentomatic/repository/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/rentomatic/repository/memrepo.py b/rentomatic/repository/memrepo.py
new file mode 100644
index 0000000..c43b8cc
--- /dev/null
+++ b/rentomatic/repository/memrepo.py
@@ -0,0 +1,8 @@
+from rentomatic.domain.room import Room
+
+class MemRepo:
+    def __init__(self, data):
+        self.data = data
+    
+    def list(self):
+        return [Room.from_dict(i) for i in self.data]
\ No newline at end of file
diff --git a/rentomatic/serializers/__init__.py b/rentomatic/serializers/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/rentomatic/serializers/room.py b/rentomatic/serializers/room.py
new file mode 100644
index 0000000..ee9328a
--- /dev/null
+++ b/rentomatic/serializers/room.py
@@ -0,0 +1,16 @@
+import json
+
+
+class RoomJsonEncoder(json.JSONEncoder):
+    def default(self, o):
+        try:
+            to_serialize = {
+                "code": str(o.code),
+                "size": o.size,
+                "price": o.price,
+                "longitude": o.longitude,
+                "latitude": o.latitude,
+            }
+            return to_serialize
+        except AttributeError: # pragma: no cover
+            return super().default(o)
\ No newline at end of file
diff --git a/rentomatic/use_cases/__init__.py b/rentomatic/use_cases/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/rentomatic/use_cases/room_list.py b/rentomatic/use_cases/room_list.py
new file mode 100644
index 0000000..c331a16
--- /dev/null
+++ b/rentomatic/use_cases/room_list.py
@@ -0,0 +1,2 @@
+def room_list_use_case(repo):
+    return repo.list()
\ No newline at end of file
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..83282a9
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,25 @@
+# This file is used to configure your project.
+# Read more about the various options under:
+# http://setuptools.readthedocs.io/en/latest/setuptools.html#configuring-setup-using-setup-cfg-files
+
+[metadata]
+name = rentomatic
+description = A demo implementation of a clean architecture in Python.
+author = Leonardo Giordani
+author-email = giordani.leonardo@gmail.com
+version = 1.0.0
+license = mit
+long-description = file: README.md
+long_description_content_type = text/markdown
+url = https://github.com/pycabook/rentomatic
+# Change if running only on Windows, Mac or Linux (comma-separated)
+platforms = any
+# Add here all kinds of additional classifiers as defined under
+# https://pypi.python.org/pypi?%3Aaction=list_classifiers
+classifiers =
+    Development Status :: 5 - Production/Stable
+    Programming Language :: Python
+    License :: OSI Approved :: MIT License
+    Operating System :: OS Independent
+    Programming Language :: Python :: 3
+    Programming Language :: Python :: 3 :: Only
\ No newline at end of file
diff --git a/tox.ini b/tox.ini
index ffcd53e..48f3a52 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
 [tox]
-envlist = py33, py34, py35, py36, py37, pypy, flake8
+envlist = py37, py38, py39, flake8
 
 [testenv:flake8]
 basepython=python
@@ -10,7 +10,7 @@ commands=flake8 rentomatic
 setenv =
     PYTHONPATH = {toxinidir}:{toxinidir}/rentomatic
 deps =
-    -r{toxinidir}/requirements_dev.txt
+    -r{toxinidir}/requirements/dev.txt
 commands =
     pip install -U pip
     py.test --basetemp={envtmpdir}
@@ -19,4 +19,4 @@ commands =
 ; If you want to make tox run the tests with the same versions, create a
 ; requirements.txt with the pinned versions and uncomment the following lines:
 ; deps =
-;     -r{toxinidir}/requirements.txt
+;     -r{toxinidir}/requirements.txt
\ No newline at end of file


Test patch:
diff --git a/tests/domain/__init__.py b/tests/domain/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/domain/test_room.py b/tests/domain/test_room.py
new file mode 100644
index 0000000..275dea1
--- /dev/null
+++ b/tests/domain/test_room.py
@@ -0,0 +1,67 @@
+import uuid
+from rentomatic.domain.room import Room
+
+def test_room_model_init():
+    code = uuid.uuid4()
+    room = Room(
+        code,
+        size=200,
+        price=10,
+        longitude=-0.09998975,
+        latitude=51.75436293,
+    )
+
+    assert room.code == code
+    assert room.size == 200
+    assert room.price == 10
+    assert room.longitude == -0.09998975
+    assert room.latitude == 51.75436293
+
+
+def test_room_model_from_dict():
+    code = uuid.uuid4()
+    init_dict = {
+        "code": code,
+        "size": 200,
+        "price": 10,
+        "longitude": -0.09998975,
+        "latitude": 51.75436293,
+    }
+
+    room = Room.from_dict(init_dict)
+
+    assert room.code == code
+    assert room.size == 200
+    assert room.price == 10
+    assert room.longitude == -0.09998975
+    assert room.latitude == 51.75436293
+
+
+def test_room_model_to_dict():
+    code = uuid.uuid4()
+    init_dict = {
+        "code": code,
+        "size": 200,
+        "price": 10,
+        "longitude": -0.09998975,
+        "latitude": 51.75436293,
+    }
+
+    room = Room.from_dict(init_dict)
+    assert room.to_dict() == init_dict
+
+
+def test_room_modl_comparison():
+    code = uuid.uuid4()
+    init_dict = {
+        "code": code,
+        "size": 200,
+        "price": 10,
+        "longitude": -0.09998975,
+        "latitude": 51.75436293,
+    }
+
+    room1 = Room.from_dict(init_dict)
+    room2 = Room.from_dict(init_dict)
+
+    assert room1 == room2
\ No newline at end of file
diff --git a/tests/repository/__init__.py b/tests/repository/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/repository/test_memrepo.py b/tests/repository/test_memrepo.py
new file mode 100644
index 0000000..5a4c75c
--- /dev/null
+++ b/tests/repository/test_memrepo.py
@@ -0,0 +1,46 @@
+import pytest
+
+from rentomatic.domain.room import Room
+from rentomatic.repository.memrepo import MemRepo
+
+
+@pytest.fixture
+def room_dicts():
+    return [
+        {
+            "code": "f853578c-fc0f-4e65-81b8-566c5dffa35a",
+            "size": 215,
+            "price": 39,
+            "longitude": -0.09998975,
+            "latitude": 51.75436293,
+        },
+        {
+            "code": "fe2c3195-aeff-487a-a08f-e0bdc0ec6e9a",
+            "size": 405,
+            "price": 66,
+            "longitude": 0.18228006,
+            "latitude": 51.74640997,
+        },
+        {
+            "code": "913694c6-435a-4366-ba0d-da5334a611b2",
+            "size": 56,
+            "price": 60,
+            "longitude": 0.27891577,
+            "latitude": 51.45994069,
+        },
+        {
+            "code": "eed76e77-55c1-41ce-985d-ca49bf6c0585",
+            "size": 93,
+            "price": 48,
+            "longitude": 0.33894476,
+            "latitude": 51.39916678,
+        },
+    ]
+
+
+def test_repository_list_without_parameters(room_dicts):
+    repo = MemRepo(room_dicts)
+
+    rooms = [Room.from_dict(i) for i in room_dicts]
+
+    assert repo.list() == rooms
\ No newline at end of file
diff --git a/tests/serializers/__init__.py b/tests/serializers/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/serializers/test_room.py b/tests/serializers/test_room.py
new file mode 100644
index 0000000..ab8e630
--- /dev/null
+++ b/tests/serializers/test_room.py
@@ -0,0 +1,33 @@
+import json
+import uuid
+
+from rentomatic.serializers.room import RoomJsonEncoder
+from rentomatic.domain.room import Room
+
+
+def test_serialize_domain_room():
+    code = uuid.uuid4()
+    room = Room(
+        code,
+        size=200,
+        price=10,
+        longitude=-0.09998975,
+        latitude=51.75436293,
+    )
+
+    expected_json = f"""
+        {{
+            "code": "{code}",
+            "size": 200,
+            "price": 10,
+            "longitude": -0.09998975,
+            "latitude": 51.75436293
+        }}
+    """
+
+    json_room = json.dumps(room, cls=RoomJsonEncoder)
+
+    assert json.loads(json_room) == json.loads(expected_json)
+
+if __name__ == '__main__':
+    pass
\ No newline at end of file
diff --git a/tests/use_cases/__init__.py b/tests/use_cases/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/use_cases/test_room_list.py b/tests/use_cases/test_room_list.py
new file mode 100644
index 0000000..134ed93
--- /dev/null
+++ b/tests/use_cases/test_room_list.py
@@ -0,0 +1,56 @@
+import pytest
+import uuid
+from unittest import mock
+
+from rentomatic.domain.room import Room
+from rentomatic.use_cases.room_list import room_list_use_case
+
+
+@pytest.fixture
+def domain_rooms():
+    room_1 = Room(
+        code=uuid.uuid4(),
+        size=215,
+        price=39,
+        longitude=-0.09998975,
+        latitude=51.75436293,
+    )
+
+    room_2 = Room(
+        code=uuid.uuid4(),
+        size=405,
+        price=66,
+        longitude=0.18228006,
+        latitude=51.74640997,
+    )
+
+    room_3 = Room(
+        code=uuid.uuid4(),
+        size=56,
+        price=60,
+        longitude=0.27891577,
+        latitude=51.45994069,
+    )
+
+    room_4 = Room(
+        code=uuid.uuid4(),
+        size=93,
+        price=48,
+        longitude=0.33894476,
+        latitude=51.39916678,
+    )
+
+    return [room_1, room_2, room_3, room_4]
+
+
+def test_room_list_without_parameters(domain_rooms):
+    repo = mock.Mock()
+    repo.list.return_value = domain_rooms
+
+    result = room_list_use_case(repo)
+
+    repo.list.assert_called_with()
+    assert result == domain_rooms
+
+if __name__ == '__main__':
+    pass
\ No newline at end of file