Skip to content

Pro's solution #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: students-code
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions lottery/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import random
from dataclasses import asdict

from flask import Flask

from .logic import TicketGenerator, TicketSaver
from .ports import APIPort, FilePort, RandomPort

APP = Flask(__name__)
HOSTNAME = "https://httpbin.org/post"
LOG_FILENAME = "ticket.log"
MAX_TICKET_NUMBER = 1000


@APP.route("/")
def lottery():
ticket_generator = TicketGenerator(
random_port=RandomPort(random, MAX_TICKET_NUMBER)
)
ticket_saver = TicketSaver(
api_port=APIPort(host=HOSTNAME), file_port=FilePort(LOG_FILENAME)
)
ticket = ticket_generator.generate_ticket()
ticket_saver.save_ticket(ticket)
return asdict(ticket)
8 changes: 8 additions & 0 deletions lottery/entities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from dataclasses import dataclass, field
from datetime import datetime


@dataclass
class Ticket:
ticket_id: int
creation_time: datetime = field(default_factory=datetime.now)
19 changes: 19 additions & 0 deletions lottery/logic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from .entities import Ticket


class TicketGenerator:
def __init__(self, random_port):
self._random_port = random_port

def generate_ticket(self):
return Ticket(ticket_id=self._random_port.generate())


class TicketSaver:
def __init__(self, api_port, file_port):
self._api_port = api_port
self._file_port = file_port

def save_ticket(self, ticket):
self._file_port.save(ticket)
self._api_port.send(ticket)
16 changes: 0 additions & 16 deletions lottery/lottery.py

This file was deleted.

30 changes: 30 additions & 0 deletions lottery/ports.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from dataclasses import asdict, astuple

import requests


class RandomPort:
def __init__(self, random, max_number):
self._random = random
self._max_number = max_number

def generate(self):
return self._random.randint(1, self._max_number)


class FilePort:
def __init__(self, filename):
self._filename = filename

def save(self, ticket):
with open(self._filename, "a") as file_desc:
file_desc.write("{0},{1}\n".format(*astuple(ticket)))


class APIPort:
def __init__(self, host):
self._host = host
self.last_response = None

def send(self, ticket):
self.last_response = requests.post(self._host, data=asdict(ticket))
2 changes: 1 addition & 1 deletion run.sh
Original file line number Diff line number Diff line change
@@ -1 +1 @@
env FLASK_APP=lottery.lottery flask run
env FLASK_APP=lottery.api flask run
36 changes: 36 additions & 0 deletions tests/test_logic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from unittest.mock import Mock

from pytest import fixture

from lottery.logic import TicketGenerator, TicketSaver
from lottery.ports import APIPort, FilePort, RandomPort


@fixture
def dummy_random():
return Mock(RandomPort, generate=Mock(return_value=527))


@fixture
def dummy_api():
return Mock(APIPort)


@fixture
def dummy_file():
return Mock(FilePort)


def test_generate_ticket(dummy_random):
logic = TicketGenerator(random_port=dummy_random)

assert logic.generate_ticket().ticket_id == 527


def test_send(dummy_api, dummy_file):
logic = TicketSaver(api_port=dummy_api, file_port=dummy_file)

logic.save_ticket(527)

dummy_api.send.assert_called_with(527)
dummy_file.save.assert_called_with(527)
35 changes: 0 additions & 35 deletions tests/test_lottery.py

This file was deleted.

39 changes: 39 additions & 0 deletions tests/test_ports.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from datetime import datetime
from random import Random
from tempfile import mkstemp

from pytest import mark

from lottery.entities import Ticket
from lottery.ports import APIPort, FilePort, RandomPort


def test_random_port():
port = RandomPort(Random(10000), 1000)

assert port.generate() == 592


@mark.integration
def test_file_port():
__, path = mkstemp()
port = FilePort(path)

port.save(Ticket(ticket_id=123, creation_time=datetime(2020, 10, 11, 10, 22, 1)))
port.save(Ticket(ticket_id=987, creation_time=datetime(2020, 10, 11, 11, 22, 1)))

with open(path, "r") as desc:
assert desc.read() == "123,2020-10-11 10:22:01\n987,2020-10-11 11:22:01\n"


@mark.integration
def test_api_port():
port = APIPort("https://httpbin.org/post")

port.send(Ticket(ticket_id=123, creation_time=datetime(2020, 10, 11, 10, 22, 1)))

assert port.last_response.status_code == 200
assert port.last_response.json()["form"] == {
"creation_time": "2020-10-11 10:22:01",
"ticket_id": "123",
}