- the main purpose of this class is to manage querying the order totals
from the database and slice various kinds of time series out of the
data
- the class holds the former `aggregate_orders()` function as a method
- modularize the corresponding tests
- add `tests.config` with globals used when testing to provide a
single source of truth for various settings
- the function queries the database and aggregates the ad-hoc orders
by pixel and time steps into a demand time series
- implement "heavy" integration tests for `aggregate_orders()`
- make `pandas` a package dependency
- streamline the `Config`
- reorganize `urban_meal_delivery.console` into a sub-package
- move `tests.db.conftest` fixtures into `tests.conftest`
=> some integration tests regarding CLI scripts need a database
- add `urban_meal_delivery.console.decorators.db_revision` decorator
to ensure the database is at a certain state before a CLI script runs
- refactor the `urban_meal_delivery.db.grids.Grid.gridify()` constructor:
- bug fix: even empty `Pixel`s end up in the database temporarily
=> create `Pixel` objects only if an `Address` is to be assigned
to it
- streamline code and docstring
- add further test cases
- the purpose of this constructor method is to generate all `Pixel`s
for a `Grid` that have at least one `Address` assigned to them
- fix missing `UniqueConstraint` in `Grid` class => it was not possible
to create two `Grid`s with the same `.side_length` in different cities
- change the `City.viewport` property into two separate `City.southwest`
and `City.northeast` properties; also add `City.total_x` and
`City.total_y` properties for convenience
- the old `UTMCoordinate` class becomes the new `Location` class
- its main purpose is to represent locations in both lat-long
coordinates as well as in the UTM system
- remove `Address.__init__()` and `City.__init__()` methods as they
are not executed for entries retrieved from the database
- simplfiy the `Location.__init__()` => remove `relative_to` argument
- remove the factory functions for creating engines and sessions
- define global engine, connection, and session objects to be used
everywhere in the urban_meal_delivery package
- add Grid, Pixel, and AddressPixelAssociation ORM models
- each Grid belongs to a City an is characterized by the side_length
of all the square Pixels contained in it
- Pixels aggregate Addresses => many-to-many relationship (that is
modeled with SQLAlchemy's Association Pattern to implement a couple
of constraints)
- the Address.x and Address.y properties use the UTMCoordinate class
behind the scenes
- x and y are simple coordinates in an x-y plane
- the (0, 0) origin is the southwest corner of Address.city.viewport
- the class is a utility to abstract working with latitude-longitude
coordinates in their UTM representation (~ "cartesian plane")
- the class's .x and .y properties enable working with simple x-y
coordinates where the (0, 0) origin is the lower-left of a city's
viewport
- create `*Factory` classes with fakerboy and faker that generate
randomized instances of the ORM models
- add new pytest marker: "db" are the integration tests involving the
database whereas "e2e" will be all other integration tests
- streamline the docstrings in the ORM models
- use Alembic to migrate the PostgreSQL database
+ create initial migration script to set up the database,
as an alternative to db.Base.metadata.create_all()
+ integrate Alembic into the test suite; the db_engine fixture
now has two modes:
* create the latest version of tables all at once
* invoke `alembic upgrade head`
=> the "e2e" tests are all run twice, once in each mode; this
ensures that the migration scripts re-create the same database
schema as db.Base.metadata.create_all() would
* in both modes, a temporary PostgreSQL schema is used to create the
tables in
=> could now run "e2e" tests against production database and still
have isolation
- make the configuration module public (to be used by Alembic)
- adjust linting rules for Alembic
- use SQLAlchemy (and PostgreSQL) to model the ORM layer
- add the following models:
+ Address => modelling all kinds of addresses
+ City => model the three target cities
+ Courier => model the UDP's couriers
+ Customer => model the UDP's customers
+ Order => model the orders received by the UDP
+ Restaurant => model the restaurants active on the UDP
- so far, the emphasis lies on expression the Foreign Key
and Check Constraints that are used to validate the assumptions
inherent to the cleanded data
- provide database-independent unit tests with 100% coverage
- provide additional integration tests ("e2e") that commit data to
a PostgreSQL instance to validate that the constraints work
- adapt linting rules a bit
- add the following file:
+ src/urban_meal_delivery/_config.py
- a config module is created holding two sets of configurations:
+ production => against the real database
+ testing => against a database with test data
- the module is "protected" (i.e., underscore) and imported at the
top level via a proxy-like object `config` that detects in which of
the two environments the package is being run
- for tests/ and the noxfile.py, type annotations are not strictly
enforced any more
+ this simplifies the way test cases and nox sessions are written
+ for many pytest fixtures, no types are available via a public API
- put fixtures inside the classes the corresponding test cases are
grouped in
- add the following file:
+ src/urban_meal_delivery/console.py => click-based CLI tools
+ tests/test_console.py => tests for the module above
- add a CLI entry point `umd`:
+ implement the --version / -V option
to show the installed package's version
+ rework to package's top-level:
* add a __pkg_name__ variable to parameterize the package name
+ add unit and integration tests
- fix that pylint cannot know the proper order of imports in the
isolated nox session
- use pytest as the base, measure coverage with pytest-cov
+ configure coverage to include branches and specify source locations
+ configure pytest to enforce explicit markers
- add a package for the test suite under tests/
- add a `__version__` identifier at the package's root
+ it is dynamically assigned the version of the installed package
+ the version is PEP440 compliant and follows a strict subset of
semantic versioning: x.y.z[.devN] where x, y, z, and N are all
non-negative integers
+ add module with tests for the __version__
- add a nox session "test" that runs the test suite
- use flake8 to lint pytest for consistent style