Skip to content

Commit

Permalink
black in csv and django appendices
Browse files Browse the repository at this point in the history
  • Loading branch information
hjwp committed Feb 24, 2021
1 parent 520d63a commit 57040ff
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 94 deletions.
136 changes: 62 additions & 74 deletions appendix_csvs.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -26,36 +26,32 @@ Here's an E2E test to show you how the CSVs flow in and out:
====
[source,python]
----
def test_cli_app_reads_csvs_with_batches_and_orders_and_outputs_allocations(
make_csv
):
sku1, sku2 = random_ref('s1'), random_ref('s2')
batch1, batch2, batch3 = random_ref('b1'), random_ref('b2'), random_ref('b3')
order_ref = random_ref('o')
make_csv('batches.csv', [
['ref', 'sku', 'qty', 'eta'],
[batch1, sku1, 100, ''],
[batch2, sku2, 100, '2011-01-01'],
[batch3, sku2, 100, '2011-01-02'],
def test_cli_app_reads_csvs_with_batches_and_orders_and_outputs_allocations(make_csv):
sku1, sku2 = random_ref("s1"), random_ref("s2")
batch1, batch2, batch3 = random_ref("b1"), random_ref("b2"), random_ref("b3")
order_ref = random_ref("o")
make_csv("batches.csv", [
["ref", "sku", "qty", "eta"],
[batch1, sku1, 100, ""],
[batch2, sku2, 100, "2011-01-01"],
[batch3, sku2, 100, "2011-01-02"],
])
orders_csv = make_csv('orders.csv', [
['orderid', 'sku', 'qty'],
orders_csv = make_csv("orders.csv", [
["orderid", "sku", "qty"],
[order_ref, sku1, 3],
[order_ref, sku2, 12],
])
run_cli_script(orders_csv.parent)
expected_output_csv = orders_csv.parent / 'allocations.csv'
expected_output_csv = orders_csv.parent / "allocations.csv"
with open(expected_output_csv) as f:
rows = list(csv.reader(f))
assert rows == [
['orderid', 'sku', 'qty', 'batchref'],
[order_ref, sku1, '3', batch1],
[order_ref, sku2, '12', batch2],
["orderid", "sku", "qty", "batchref"],
[order_ref, sku1, "3", batch1],
[order_ref, sku2, "12", batch2],
]
----
====

Expand All @@ -75,48 +71,46 @@ import sys
from datetime import datetime
from pathlib import Path
from allocation import model
from allocation.domain import model
def load_batches(batches_path):
batches = []
with batches_path.open() as inf:
reader = csv.DictReader(inf)
for row in reader:
if row['eta']:
eta = datetime.strptime(row['eta'], '%Y-%m-%d').date()
if row["eta"]:
eta = datetime.strptime(row["eta"], "%Y-%m-%d").date()
else:
eta = None
batches.append(model.Batch(
ref=row['ref'],
sku=row['sku'],
qty=int(row['qty']),
eta=eta
))
batches.append(
model.Batch(
ref=row["ref"], sku=row["sku"], qty=int(row["qty"]), eta=eta
)
)
return batches
def main(folder):
batches_path = Path(folder) / 'batches.csv'
orders_path = Path(folder) / 'orders.csv'
allocations_path = Path(folder) / 'allocations.csv'
batches_path = Path(folder) / "batches.csv"
orders_path = Path(folder) / "orders.csv"
allocations_path = Path(folder) / "allocations.csv"
batches = load_batches(batches_path)
with orders_path.open() as inf, allocations_path.open('w') as outf:
with orders_path.open() as inf, allocations_path.open("w") as outf:
reader = csv.DictReader(inf)
writer = csv.writer(outf)
writer.writerow(['orderid', 'sku', 'batchref'])
writer.writerow(["orderid", "sku", "batchref"])
for row in reader:
orderid, sku = row['orderid'], row['sku']
qty = int(row['qty'])
orderid, sku = row["orderid"], row["sku"]
qty = int(row["qty"])
line = model.OrderLine(orderid, sku, qty)
batchref = model.allocate(line, batches)
writer.writerow([line.orderid, line.sku, batchref])
if __name__ == '__main__':
if __name__ == "__main__":
main(sys.argv[1])
----
====
Expand All @@ -135,35 +129,33 @@ things:
====
[source,python]
----
def test_cli_app_also_reads_existing_allocations_and_can_append_to_them(
make_csv
):
sku = random_ref('s')
batch1, batch2 = random_ref('b1'), random_ref('b2')
old_order, new_order = random_ref('o1'), random_ref('o2')
make_csv('batches.csv', [
['ref', 'sku', 'qty', 'eta'],
[batch1, sku, 10, '2011-01-01'],
[batch2, sku, 10, '2011-01-02'],
def test_cli_app_also_reads_existing_allocations_and_can_append_to_them(make_csv):
sku = random_ref("s")
batch1, batch2 = random_ref("b1"), random_ref("b2")
old_order, new_order = random_ref("o1"), random_ref("o2")
make_csv("batches.csv", [
["ref", "sku", "qty", "eta"],
[batch1, sku, 10, "2011-01-01"],
[batch2, sku, 10, "2011-01-02"],
])
make_csv('allocations.csv', [
['orderid', 'sku', 'qty', 'batchref'],
make_csv("allocations.csv", [
["orderid", "sku", "qty", "batchref"],
[old_order, sku, 10, batch1],
])
orders_csv = make_csv('orders.csv', [
['orderid', 'sku', 'qty'],
orders_csv = make_csv("orders.csv", [
["orderid", "sku", "qty"],
[new_order, sku, 7],
])
run_cli_script(orders_csv.parent)
expected_output_csv = orders_csv.parent / 'allocations.csv'
expected_output_csv = orders_csv.parent / "allocations.csv"
with open(expected_output_csv) as f:
rows = list(csv.reader(f))
assert rows == [
['orderid', 'sku', 'qty', 'batchref'],
[old_order, sku, '10', batch1],
[new_order, sku, '7', batch2],
["orderid", "sku", "qty", "batchref"],
[old_order, sku, "10", batch1],
[new_order, sku, "7", batch2],
]
----
====
Expand Down Expand Up @@ -192,10 +184,9 @@ collection of domain objects:
[source,python]
----
class CsvRepository(repository.AbstractRepository):
def __init__(self, folder):
self._batches_path = Path(folder) / 'batches.csv'
self._allocations_path = Path(folder) / 'allocations.csv'
self._batches_path = Path(folder) / "batches.csv"
self._allocations_path = Path(folder) / "allocations.csv"
self._batches = {} # type: Dict[str, model.Batch]
self._load()
Expand All @@ -209,22 +200,20 @@ class CsvRepository(repository.AbstractRepository):
with self._batches_path.open() as f:
reader = csv.DictReader(f)
for row in reader:
ref, sku = row['ref'], row['sku']
qty = int(row['qty'])
if row['eta']:
eta = datetime.strptime(row['eta'], '%Y-%m-%d').date()
ref, sku = row["ref"], row["sku"]
qty = int(row["qty"])
if row["eta"]:
eta = datetime.strptime(row["eta"], "%Y-%m-%d").date()
else:
eta = None
self._batches[ref] = model.Batch(
ref=ref, sku=sku, qty=qty, eta=eta
)
self._batches[ref] = model.Batch(ref=ref, sku=sku, qty=qty, eta=eta)
if self._allocations_path.exists() is False:
return
with self._allocations_path.open() as f:
reader = csv.DictReader(f)
for row in reader:
batchref, orderid, sku = row['batchref'], row['orderid'], row['sku']
qty = int(row['qty'])
batchref, orderid, sku = row["batchref"], row["orderid"], row["sku"]
qty = int(row["qty"])
line = model.OrderLine(orderid, sku, qty)
batch = self._batches[batchref]
batch._allocations.add(line)
Expand All @@ -248,14 +237,13 @@ And here's what a UoW for CSVs would look like:
[source,python]
----
class CsvUnitOfWork(unit_of_work.AbstractUnitOfWork):
def __init__(self, folder):
self.batches = CsvRepository(folder)
def commit(self):
with self.batches._allocations_path.open('w') as f:
with self.batches._allocations_path.open("w") as f:
writer = csv.writer(f)
writer.writerow(['orderid', 'sku', 'qty', 'batchref'])
writer.writerow(["orderid", "sku", "qty", "batchref"])
for batch in self.batches.list():
for line in batch._allocations:
writer.writerow(
Expand All @@ -280,13 +268,13 @@ _existing_ service layer:
[source,python]
----
def main(folder):
orders_path = Path(folder) / 'orders.csv'
orders_path = Path(folder) / "orders.csv"
uow = csv_uow.CsvUnitOfWork(folder)
with orders_path.open() as f:
reader = csv.DictReader(f)
for row in reader:
orderid, sku = row['orderid'], row['sku']
qty = int(row['qty'])
orderid, sku = row["orderid"], row["sku"]
qty = int(row["qty"])
services.allocate(orderid, sku, qty, uow)
----
====
Expand Down
42 changes: 23 additions & 19 deletions appendix_django.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ Here's how the actual repository ends up looking:
[source,python]
----
class DjangoRepository(AbstractRepository):
def add(self, batch):
super().add(batch)
self.update(batch)
Expand All @@ -148,9 +147,11 @@ class DjangoRepository(AbstractRepository):
django_models.Batch.update_from_domain(batch)
def _get(self, reference):
return django_models.Batch.objects.filter(
reference=reference
).first().to_domain()
return (
django_models.Batch.objects.filter(reference=reference)
.first()
.to_domain()
)
def list(self):
return [b.to_domain() for b in django_models.Batch.objects.all()]
Expand Down Expand Up @@ -179,6 +180,7 @@ Those custom methods look something like this:
from django.db import models
from allocation.domain import model as domain_model
class Batch(models.Model):
reference = models.CharField(max_length=255)
sku = models.CharField(max_length=255)
Expand Down Expand Up @@ -250,6 +252,7 @@ The tests don't change too much:
def insert_batch(ref, sku, qty, eta): #<1>
django_models.Batch.objects.create(reference=ref, sku=sku, qty=qty, eta=eta)
def get_allocated_batch_ref(orderid, sku): #<1>
return django_models.Allocation.objects.get(
line__orderid=orderid, line__sku=sku
Expand All @@ -258,17 +261,17 @@ def get_allocated_batch_ref(orderid, sku): #<1>
@pytest.mark.django_db(transaction=True)
def test_uow_can_retrieve_a_batch_and_allocate_to_it():
insert_batch('batch1', 'HIPSTER-WORKBENCH', 100, None)
insert_batch("batch1", "HIPSTER-WORKBENCH", 100, None)
uow = unit_of_work.DjangoUnitOfWork()
with uow:
batch = uow.batches.get(reference='batch1')
line = model.OrderLine('o1', 'HIPSTER-WORKBENCH', 10)
batch = uow.batches.get(reference="batch1")
line = model.OrderLine("o1", "HIPSTER-WORKBENCH", 10)
batch.allocate(line)
uow.commit()
batchref = get_allocated_batch_ref('o1', 'HIPSTER-WORKBENCH')
assert batchref == 'batch1'
batchref = get_allocated_batch_ref("o1", "HIPSTER-WORKBENCH")
assert batchref == "batch1"
@pytest.mark.django_db(transaction=True) #<2>
Expand Down Expand Up @@ -301,7 +304,6 @@ would work:
[source,python]
----
class DjangoUnitOfWork(AbstractUnitOfWork):
def __enter__(self):
self.batches = repository.DjangoRepository()
transaction.set_autocommit(False) #<1>
Expand Down Expand Up @@ -353,35 +355,37 @@ thin wrapper around our service layer (which didn't change at all, by the way):
====
[source,python]
----
os.environ['DJANGO_SETTINGS_MODULE'] = 'djangoproject.django_project.settings'
os.environ["DJANGO_SETTINGS_MODULE"] = "djangoproject.django_project.settings"
django.setup()
@csrf_exempt
def add_batch(request):
data = json.loads(request.body)
eta = data['eta']
eta = data["eta"]
if eta is not None:
eta = datetime.fromisoformat(eta).date()
services.add_batch(
data['ref'], data['sku'], data['qty'], eta,
data["ref"], data["sku"], data["qty"], eta,
unit_of_work.DjangoUnitOfWork(),
)
return HttpResponse('OK', status=201)
return HttpResponse("OK", status=201)
@csrf_exempt
def allocate(request):
data = json.loads(request.body)
try:
batchref = services.allocate(
data['orderid'],
data['sku'],
data['qty'],
data["orderid"],
data["sku"],
data["qty"],
unit_of_work.DjangoUnitOfWork(),
)
except (model.OutOfStock, services.InvalidSku) as e:
return JsonResponse({'message': str(e)}, status=400)
return JsonResponse({"message": str(e)}, status=400)
return JsonResponse({'batchref': batchref}, status=201)
return JsonResponse({"batchref": batchref}, status=201)
----
====

Expand Down
2 changes: 1 addition & 1 deletion code
Submodule code updated 52 files
+1 −0 .gitignore
+4 −0 .travis.yml
+4 −0 Dockerfile
+6 −6 Makefile
+3 −44 docker-compose.yml
+1 −1 mypy.ini
+4 −6 requirements.txt
+0 −28 src/allocation/adapters/notifications.py
+0 −86 src/allocation/adapters/orm.py
+0 −16 src/allocation/adapters/redis_eventpublisher.py
+24 −41 src/allocation/adapters/repository.py
+0 −51 src/allocation/bootstrap.py
+0 −13 src/allocation/config.py
+0 −29 src/allocation/domain/commands.py
+0 −26 src/allocation/domain/events.py
+14 −34 src/allocation/domain/model.py
+0 −41 src/allocation/entrypoints/flask_app.py
+0 −31 src/allocation/entrypoints/redis_eventconsumer.py
+0 −120 src/allocation/service_layer/handlers.py
+0 −55 src/allocation/service_layer/messagebus.py
+43 −0 src/allocation/service_layer/services.py
+12 −34 src/allocation/service_layer/unit_of_work.py
+0 −12 src/allocation/views.py
+0 −0 src/djangoproject/alloc/__init__.py
+5 −0 src/djangoproject/alloc/apps.py
+76 −0 src/djangoproject/alloc/migrations/0001_initial.py
+0 −0 src/djangoproject/alloc/migrations/__init__.py
+65 −0 src/djangoproject/alloc/models.py
+42 −0 src/djangoproject/alloc/views.py
+0 −0 src/djangoproject/django_project/__init__.py
+116 −0 src/djangoproject/django_project/settings.py
+22 −0 src/djangoproject/django_project/urls.py
+16 −0 src/djangoproject/django_project/wsgi.py
+21 −0 src/djangoproject/manage.py
+1 −1 src/setup.py
+15 −70 tests/conftest.py
+0 −30 tests/e2e/api_client.py
+0 −18 tests/e2e/redis_client.py
+40 −22 tests/e2e/test_api.py
+0 −40 tests/e2e/test_external_events.py
+0 −37 tests/integration/test_email.py
+41 −16 tests/integration/test_repository.py
+27 −104 tests/integration/test_uow.py
+0 −49 tests/integration/test_views.py
+1 −2 tests/pytest.ini
+0 −17 tests/random_refs.py
+47 −0 tests/unit/test_allocate.py
+13 −0 tests/unit/test_batches.py
+0 −142 tests/unit/test_handlers.py
+0 −74 tests/unit/test_product.py
+62 −0 tests/unit/test_services.py
+17 −0 tests/wait_for_postgres.py

0 comments on commit 57040ff

Please sign in to comment.