Skip to content
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

Update mapper to sqlalchemy 1.4 #44

Open
wants to merge 147 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
147 commits
Select commit Hold shift + click to select a range
fff68bd
ORM for _allocations set on Batch
hjwp Mar 11, 2019
8dae126
repository tests
hjwp Mar 11, 2019
b635a15
repository for batches [chapter_02_repository_ends]
hjwp Mar 11, 2019
fda077d
first api tests [first_api_test]
hjwp Mar 11, 2019
15902a6
all the dockerfile gubbins
hjwp Mar 19, 2019
8fc086e
first cut of flask app [first_cut_flask_app]
hjwp Mar 11, 2019
158e760
test persistence by double-allocating. [second_api_test]
hjwp Mar 19, 2019
d0ee7ad
need to commit [flask_commit]
hjwp Mar 19, 2019
f20c479
test some 400 error cases [test_error_cases]
hjwp Mar 19, 2019
80dece9
flask now does error handling [flask_error_handling]
hjwp Mar 19, 2019
a1903fa
first tests for the services layer [first_services_tests]
hjwp Mar 19, 2019
9fe9a3d
FakeRepository [fake_repo]
hjwp Jan 3, 2020
15b9bf7
FakeSession [fake_session]
hjwp Jan 3, 2020
eded7eb
test commmits [second_services_test]
hjwp Apr 23, 2019
d1e2e6e
services layer with valid-sku check [service_function]
hjwp Mar 19, 2019
cf2f52b
modify flask app to use service layer [flask_app_using_service_layer]
hjwp Mar 19, 2019
b537364
strip out unecessary tests from e2e layer [fewer_e2e_tests]
hjwp Mar 19, 2019
952a3d2
fix conftest waits and travis config [chapter_04_service_layer_ends]
hjwp Mar 26, 2019
bdf8fe9
move to a more nested folder structure
hjwp Dec 23, 2019
1bb572a
nest the tests too
hjwp Dec 31, 2019
db89218
get all tests passing
hjwp Dec 31, 2019
c5822aa
rewrite service layer to take primitives [service_takes_primitives]
hjwp Apr 23, 2019
f341bee
services tests partially converted to primitives [tests_call_with_pri…
hjwp Apr 23, 2019
1e1f238
fixture function for batches [services_factory_function]
hjwp Apr 23, 2019
5c953da
new service to add a batch [add_batch_service]
hjwp Apr 23, 2019
262eec0
service-layer test for add batch [test_add_batch]
hjwp Apr 23, 2019
c8fbb60
all service-layer tests now services [services_tests_all_services]
hjwp Apr 23, 2019
96301d2
modify flask app to use new service layer api [api_uses_modified_serv…
hjwp Apr 23, 2019
6b404b5
add api endpoint for add_batch [api_for_add_batch]
hjwp Apr 24, 2019
fd45a6f
api tests no longer need hardcoded sql fixture [chapter_05_high_gear_…
hjwp Apr 24, 2019
d9c340c
start moving files into src folder and add setup.py
hjwp Feb 27, 2019
c843a10
fix all the imports, get it all working
hjwp Feb 27, 2019
12d2bc2
get tests working in docker container
hjwp Feb 27, 2019
28afa9a
make mypy slightly stricter
hjwp May 23, 2019
53ad798
better requirements.txt [appendix_project_structure_ends]
hjwp Mar 11, 2019
833d48b
basic uow test, uow and conftest.py changes
hjwp Mar 11, 2019
658e61a
use uow in services, flask app
hjwp Mar 20, 2019
7526014
two more tests for rollback behaviour [chapter_06_uow_ends]
hjwp Mar 12, 2019
c50ab2c
start on a Product model with an allocate fn [product_aggregate]
hjwp Mar 23, 2019
9d6eed1
first cut of a product with a version number
hjwp Mar 23, 2019
1610943
start adding tests for consistency on version_number [data_integrity_…
hjwp Mar 23, 2019
bdd3d90
select for update is one approach [with_for_update]
hjwp Mar 23, 2019
dfaa46a
alternative: isolation=SERIALIZABLE [chapter_07_aggregate_ends]
hjwp Mar 23, 2019
5d5f194
Mocky test for email [mocky_test_for_send_email]
hjwp Apr 9, 2019
62aff87
email in model [email_in_model]
hjwp Apr 9, 2019
1a3b48d
putting it in the services layer isn't lovely either [email_in_services]
hjwp Apr 9, 2019
05f7256
first cut of out of stock event [domain_event]
hjwp Mar 28, 2019
ab4080c
remove commented-out line from model
hjwp Jun 9, 2019
845286e
Adjust unit tests now we're no longer raising out of stock exception
hjwp Jun 9, 2019
290914b
first cut of message bus [service_talks_to_messagebus]
hjwp Jan 3, 2020
e1faf88
uow now does messagebus magically. breaks tests [uow_has_messagebus]
hjwp Apr 9, 2019
46c62d5
implement .seen on repository [repository_tracks_seen]
hjwp Jun 9, 2019
2c90178
a little hack in the orm so that events work
hjwp Apr 9, 2019
1ba5848
remove now unused out-of-stock exception [chapter_08_events_and_messa…
hjwp Jun 9, 2019
28b6049
allocationrequired and batchcreated events [two_new_events]
hjwp May 26, 2019
3c45aa3
change exception import in flask app
hjwp Jan 3, 2020
6718fb2
move services.py to handlers.py
hjwp May 26, 2019
94c0c0c
Start moving to handlers [services_to_handlers]
hjwp Aug 6, 2019
c0a89dd
use classes in services/handlers test [tests_use_classes]
hjwp Feb 9, 2020
5647d0f
tests change to use bus [handler_tests]
hjwp Feb 9, 2020
ea72d42
messagebus takes a uow [handle_takes_uow]
hjwp Jan 3, 2020
b7c6e7e
messagebus has uow, manages queue [handle_has_uow_and_queue]
hjwp Jan 6, 2020
b40f8ed
Uow no longer puts events directly on the bus [uow_collect_new_events]
hjwp Jan 6, 2020
8f3e8b2
Ugly hack for messagebus to return results [hack_messagebus_results]
hjwp Aug 6, 2019
1f40682
modify flask to use messagebus [flask_uses_messagebus]
hjwp Aug 6, 2019
e4e48bd
new event for new input [batch_quantity_changed_event]
hjwp Aug 6, 2019
d13475b
new test and put them into classes [test_change_batch_quantity_handler]
hjwp May 25, 2019
1c365c7
start on handler for change quantity [change_quantity_handler]
hjwp May 25, 2019
71a6fa3
get_by_batchref in abstract+real repo, and a new integration test for…
hjwp May 28, 2019
8f67133
fake repo get_by_batchref [fakerepo_get_by_batchref]
hjwp May 28, 2019
be5b945
change_batch_quantity on product, needed change to batch, also emit a…
hjwp May 25, 2019
1cad6e8
sort-of fake messagebus on fake-uow. [fake_messagebus]
hjwp Oct 29, 2019
68ce401
isolated test for a handler [test_handler_in_isolation]
hjwp Oct 29, 2019
6e6937c
Revert fake messagebus stuff [chapter_09_all_messagebus_ends]
hjwp Oct 29, 2019
bfbee2e
add commands [commands_dot_py]
hjwp Aug 13, 2019
6157d48
top-level messagebus.handle dispatches events vs comannds [messagebus…
hjwp Jan 7, 2020
c31d765
subhandler for events [handle_event]
hjwp Jan 7, 2020
de1a7b4
subhandler for commands [handle_command]
hjwp Jan 7, 2020
3a18a9d
handlers dicts split in two [two_hander_dicts]
hjwp Jan 7, 2020
8fdf119
remove old events
hjwp Aug 13, 2019
1d2b68c
handlers take commands now, modify tests too
hjwp Aug 13, 2019
7aed316
model method for change batch qty now raise commands hmmm
hjwp Aug 13, 2019
d958887
flask now uses commands [chapter_10_commands_ends]
hjwp Aug 13, 2019
120f598
Add redis to docker-compose and config, conftest
hjwp Jul 26, 2019
f99ab96
refactor e2e tests, move random_refs and api_client out
hjwp Jul 26, 2019
c69661d
redis client for tests [redis_client_for_tests]
hjwp Jul 26, 2019
8ee0a93
Test for our external events [redis_e2e_test]
hjwp Jul 26, 2019
28b8093
use tenacity in conftest
hjwp Nov 15, 2019
42d1dd8
Docker infrastructure for new redis event listener container
hjwp Jul 26, 2019
75b50c5
add Allocated event [allocated_event]
hjwp Aug 14, 2019
b54e10e
redis eventconsumer first cut [redis_eventconsumer_first_cut]
hjwp Jan 3, 2020
c063c27
redis eventpublisher first cut [redis_eventpublisher_first_cut]
hjwp Jan 3, 2020
9bd4a60
sneak in a redis patch so unit test dont need redis
hjwp Jul 18, 2019
7a75df7
test and Product change to emit event [model_emits_allocated_event]
hjwp Aug 14, 2019
070eec6
add handler for Allocated [chapter_11_external_events_ends]
hjwp Aug 14, 2019
bd080f2
modify api tests to try and do a get after a post [get_after_post]
hjwp Jun 10, 2019
9b4bd65
modify allocate handler to no longer return anything
hjwp Jun 10, 2019
94111f5
modify flask to add new view endpoint and return 202s
hjwp Jun 10, 2019
3a55cde
session_factory -> sqlite_session_factory (needs backport)
hjwp Jun 12, 2019
0866c72
integration test for our view
hjwp Jun 10, 2019
f63f7a5
first cut of a view with raw sql [views_dot_py]
hjwp Jun 10, 2019
5e545e1
use repository and go via Product [view_using_repo]
hjwp Nov 6, 2019
074c820
arguably-unnecessary helper property on model. [orderids_property]
hjwp Nov 6, 2019
38f89db
finder method on repo [for_order_method]
hjwp Nov 6, 2019
71091ba
Use the ORM instead [view_using_orm]
hjwp Nov 6, 2019
50905cf
Simpler view based on a new read model table
hjwp Jun 10, 2019
7e58f4b
new table in orm
hjwp Jun 10, 2019
011d640
handler for view model update
hjwp Jun 10, 2019
ac94091
add handler for allocated
hjwp Jun 10, 2019
c015f2a
handle_command no longer returns
hjwp Aug 13, 2019
f98c68d
pylint thing
hjwp Aug 13, 2019
7d6be2c
fix redis e2e test
hjwp Aug 13, 2019
02e6b5d
make sure deallocation fixes view model too [deallocation_to_readmodel]
hjwp Jun 10, 2019
d090fb8
handlers talk to redis [redis_readmodel_handlers]
hjwp Nov 26, 2019
856ec5f
new helpers to update read model [redis_readmodel_client]
hjwp Nov 26, 2019
ec9fb19
view now users redis, tweak tests+app. [redis_readmodel_view]
hjwp Nov 26, 2019
d4f651d
Revert "view now users redis, tweak tests+app. [...]" [chapter_12_cqr…
hjwp Nov 26, 2019
286f106
handlers now have all and only explicit dependencies [handler_with_ex…
hjwp Jul 15, 2019
257f29f
change reallocate handler to avoid cmd/event clash
hjwp Jan 6, 2020
a0c2c47
bring static handlers dicts across from messagebus
hjwp Jan 6, 2020
1da2541
messagebus becomes a class, requires handlers [messagebus_as_class]
hjwp Jan 5, 2020
e9ae6db
use self.handlers for handle_event and handle_command [messagebus_han…
hjwp Jan 7, 2020
82d7908
conftest change to backport, session_factory -> sqlite_session_factory
hjwp Jul 15, 2019
36b2c82
conftest change to backport to ch 5, isolation serializable in all pg…
hjwp Jul 15, 2019
5b05570
uow tests maybe backport, pass explicit uow to threads
hjwp Jul 15, 2019
c3282c9
bootstrap script preps DI'd handlers and start orm [bootstrap_script]
hjwp Oct 7, 2019
f923760
use bootstrap in service layer tests [bootstrap_tests]
hjwp Jul 15, 2019
e883f20
fixture to start mappers explicitly, use in repo and uow tests
hjwp Jan 6, 2020
c6f9429
fix view tests to use bootstrap. [bootstrap_view_tests]
hjwp Jan 6, 2020
d4a8674
use bootstrap in flask [flask_calls_bootstrap]
hjwp Oct 7, 2019
4ca05b0
use bootstrap for redis
hjwp Jan 6, 2020
5f9b143
experiment with nonmagic DI zzzz [nomagic_di]
hjwp Jan 7, 2020
2e5e5de
Revert "experiment with nonmagic DI zzzz"
hjwp Jan 7, 2020
09c0214
switch to a notifications class [notifications_class]
hjwp Jul 14, 2019
0943337
tests for notifcations [notifications_unit_tests]
hjwp Jul 14, 2019
3f1d63d
add a mailhog fake email server to docker-compose
hjwp Jul 14, 2019
c112af9
logging.info needs backport
hjwp Oct 8, 2019
5d8136c
integration test for emails [chapter_13_dependency_injection_ends]
hjwp Jul 14, 2019
2c62b9d
update travis config
hjwp Feb 25, 2021
4157d6d
readme fixes
hjwp Feb 25, 2021
79392e8
attempt docker login
hjwp Feb 25, 2021
3ed6ff0
upgrade travis to focal + 3.9 why the heck not
hjwp Feb 25, 2021
2045cd7
fix requirements installation command in README
GeyseR Apr 2, 2021
9471128
Merge pull request #30 from GeyseR/patch-1
hjwp May 6, 2021
28b984e
Corrected commands of the individual tests make commands
adamculp May 22, 2021
69a88f8
Merge pull request #32 from adamculp/master
hjwp Jul 4, 2021
7e95928
Update mapper to sqlalchemy 1.4
lotusirous Oct 27, 2021
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
18 changes: 9 additions & 9 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
dist: xenial
dist: focal
language: python
python: 3.8

install:
- pip3 install sqlalchemy

python: 3.9
before_install:
- echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
script:
- make test

- make all
branches:
except:
- /.*_exercise$/
- "/.*_exercise$/"
env:
global:
secure: cNctlzVCjUj1oOrRW0aryxhJHB/u0b6vmn532jcgyCRS1aQjMJtT61O7tW6yMk4wOaH4Lr0kAI0J6+1lnRYf5g11H1M+IpEHGMWgJgImsysDpLRWUGmDJTez/ii8psk0SfOP/0ZwQp+QxOB92CHdPeOPOmu2HFa00V82/H7gousXR7ywQRNthLHwso36O8+UoHc4qw8nIbjcHzbfD6ysJNynmaUMlB3mRTU1hkjGKKpA2Xyl4tmkIhp3NCPJc0WR4SgB3y0u3dVOC+RtbRzl/XpEbjsZHHNloBirK+8ERn9ISBBh/mvfo6qTix743e+xvhtBlLJjk3o4H0VMH+wQ3zIpIh4TKbhPCMqWY3gvtKDVRHD+Sywk2TE6zSz0sDPWk248MC2QsL7sgeFwcnFHOWy2iKf4YyuZtoaJuX+2tw23cDCdMS6wbARlT8Kb5QwMlsxuKYN/04kQB+9nXTVsWKJGIwLKdYRzshnlzqB/UEe2vrjZcbBixCp4pbZ2jSzw2881he4KSbVGIJdZYSFetMuaN0P9obtdaJU4V+IhwzFyyapjZhEGCTl+l/m8uGdJ5DOhFlZ7OczHja7DKUuQvB3AbnMGvN518C+fJkJpWxAn5UeIp3d0ZZm32XVKt3k8PJaP7LBYdxnr3JCRit7+kNnlP7Ho0NjvX6GTHQ+r+JM=
13 changes: 13 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM python:3.9-slim-buster

# RUN apt install gcc libpq (no longer needed bc we use psycopg2-binary)

COPY requirements.txt /tmp/
RUN pip install -r /tmp/requirements.txt

RUN mkdir -p /src
COPY src/ /src/
RUN pip install -e /src
COPY tests/ /tests/

WORKDIR /src
32 changes: 28 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,32 @@
test:
pytest --tb=short
# these will speed up builds, for docker-compose >= 1.25
export COMPOSE_DOCKER_CLI_BUILD=1
export DOCKER_BUILDKIT=1

watch-tests:
ls *.py | entr pytest --tb=short
all: down build up test

build:
docker-compose build

up:
docker-compose up -d

down:
docker-compose down --remove-orphans

test: up
docker-compose run --rm --no-deps --entrypoint=pytest api /tests/unit /tests/integration /tests/e2e

unit-tests:
docker-compose run --rm --no-deps --entrypoint=pytest api /tests/unit

integration-tests: up
docker-compose run --rm --no-deps --entrypoint=pytest api /tests/integration

e2e-tests: up
docker-compose run --rm --no-deps --entrypoint=pytest api /tests/e2e

logs:
docker-compose logs --tail=25 api redis_pubsub

black:
black -l 86 $$(find * -name '*.py')
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@
## Chapters

Each chapter has its own branch which contains all the commits for that chapter,
so it has the state that corresponds to the _end_ of that chapter. If you want
to try and code along with a chapter, you'll want to check out the branch for the
previous chapter.
so it has the state that corresponds to the _end_ of that chapter.
If you want to try and code along with a chapter,
you'll want to check out the branch for the previous chapter.

https://github.com/python-leap/code/branches/all
https://github.com/cosmicpython/code/branches/all


## Exercises

Branches for the exercises follow the convention `{chatper_name}_exercise`, eg
https://github.com/python-leap/code/tree/chapter_04_service_layer_exercise
Branches for the exercises follow the convention `{chapter_name}_exercise`,
eg https://github.com/cosmicpython/code/tree/chapter_04_service_layer_exercise


## Requirements

* docker with docker-compose
* for chapters 1 and 2, and optionally for the rest: a local python3.7 virtualenv
* for chapters 1 and 2, and optionally for the rest: a local python3.8 virtualenv


## Building the containers
Expand All @@ -45,10 +45,10 @@ pip install pytest
pip install pytest sqlalchemy

# for chapter 4+5
pip install requirements.txt
pip install -r requirements.txt

# for chapter 6+
pip install requirements.txt
pip install -r requirements.txt
pip install -e src/
```

Expand All @@ -60,9 +60,9 @@ pip install -e src/
```sh
make test
# or, to run individual test types
make unit
make integration
make e2e
make unit-tests
make integration-tests
make e2e-tests
# or, if you have a local virtualenv
make up
pytest tests/unit
Expand Down
19 changes: 0 additions & 19 deletions conftest.py

This file was deleted.

70 changes: 70 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
version: "3"

services:

redis_pubsub:
build:
context: .
dockerfile: Dockerfile
image: allocation-image
depends_on:
- postgres
- redis
- mailhog
environment:
- DB_HOST=postgres
- DB_PASSWORD=abc123
- REDIS_HOST=redis
- EMAIL_HOST=mailhog
- PYTHONDONTWRITEBYTECODE=1
volumes:
- ./src:/src
- ./tests:/tests
entrypoint:
- python
- /src/allocation/entrypoints/redis_eventconsumer.py

api:
image: allocation-image
depends_on:
- redis_pubsub
- mailhog
environment:
- DB_HOST=postgres
- DB_PASSWORD=abc123
- API_HOST=api
- REDIS_HOST=redis
- EMAIL_HOST=mailhog
- PYTHONDONTWRITEBYTECODE=1
- FLASK_APP=allocation/entrypoints/flask_app.py
- FLASK_DEBUG=1
- PYTHONUNBUFFERED=1
volumes:
- ./src:/src
- ./tests:/tests
entrypoint:
- flask
- run
- --host=0.0.0.0
- --port=80
ports:
- "5005:80"

postgres:
image: postgres:9.6
environment:
- POSTGRES_USER=allocation
- POSTGRES_PASSWORD=abc123
ports:
- "54321:5432"

redis:
image: redis:alpine
ports:
- "63791:6379"

mailhog:
image: mailhog/mailhog
ports:
- "11025:1025"
- "18025:8025"
8 changes: 3 additions & 5 deletions mypy.ini
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
[mypy]
ignore_missing_imports = False
mypy_path = ./src
check_untyped_defs = True

[mypy-pytest.*]
[mypy-pytest.*,sqlalchemy.*,redis.*]
ignore_missing_imports = True

[mypy-sqlalchemy.*]
ignore_missing_imports = True

29 changes: 0 additions & 29 deletions orm.py

This file was deleted.

13 changes: 13 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# app
sqlalchemy
flask
psycopg2-binary
redis

# dev/tests
pytest
pytest-icdiff
mypy
pylint
requests
tenacity
Empty file added src/allocation/__init__.py
Empty file.
Empty file.
28 changes: 28 additions & 0 deletions src/allocation/adapters/notifications.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# pylint: disable=too-few-public-methods
import abc
import smtplib
from allocation import config


class AbstractNotifications(abc.ABC):
@abc.abstractmethod
def send(self, destination, message):
raise NotImplementedError


DEFAULT_HOST = config.get_email_host_and_port()["host"]
DEFAULT_PORT = config.get_email_host_and_port()["port"]


class EmailNotifications(AbstractNotifications):
def __init__(self, smtp_host=DEFAULT_HOST, port=DEFAULT_PORT):
self.server = smtplib.SMTP(smtp_host, port=port)
self.server.noop()

def send(self, destination, message):
msg = f"Subject: allocation service notification\n{message}"
self.server.sendmail(
from_addr="[email protected]",
to_addrs=[destination],
msg=msg,
)
80 changes: 80 additions & 0 deletions src/allocation/adapters/orm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import logging

from sqlalchemy import Column, Date, ForeignKey, Integer, String, Table, event
from sqlalchemy.orm import registry, relationship

from allocation.domain import model

logger = logging.getLogger(__name__)


mapper_registry = registry()
metadata = mapper_registry.metadata

order_lines = Table(
"order_lines",
metadata,
Column("id", Integer, primary_key=True, autoincrement=True),
Column("sku", String(255)),
Column("qty", Integer, nullable=False),
Column("orderid", String(255)),
)

products = Table(
"products",
metadata,
Column("sku", String(255), primary_key=True),
Column("version_number", Integer, nullable=False, server_default="0"),
)

batches = Table(
"batches",
metadata,
Column("id", Integer, primary_key=True, autoincrement=True),
Column("reference", String(255)),
Column("sku", ForeignKey("products.sku")),
Column("_purchased_quantity", Integer, nullable=False),
Column("eta", Date, nullable=True),
)

allocations = Table(
"allocations",
metadata,
Column("id", Integer, primary_key=True, autoincrement=True),
Column("orderline_id", ForeignKey("order_lines.id")),
Column("batch_id", ForeignKey("batches.id")),
)

allocations_view = Table(
"allocations_view",
metadata,
Column("orderid", String(255)),
Column("sku", String(255)),
Column("batchref", String(255)),
)


def start_mappers():
logger.info("Starting mappers")
lines_mapper = mapper_registry.map_imperatively(model.OrderLine, order_lines)
batches_mapper = mapper_registry.map_imperatively(
model.Batch,
batches,
properties={
"_allocations": relationship(
lines_mapper,
secondary=allocations,
collection_class=set,
)
},
)
mapper_registry.map_imperatively(
model.Product,
products,
properties={"batches": relationship(batches_mapper)},
)


@event.listens_for(model.Product, "load")
def receive_load(product, _):
product.events = []
Loading