From 4966fe211132f870037c06db619610157cf4615e Mon Sep 17 00:00:00 2001 From: "Phyks (Lucas Verney)" Date: Thu, 13 Apr 2017 23:22:11 +0200 Subject: [PATCH] Styling update, fix some Pylint errors Also update the stations fetching code to handle the warn the user when fetched stations differ from the one fetched at previous pass. --- .ci/pylintrc | 2 +- flatisfy/database/types.py | 6 ++++-- flatisfy/filters/metadata.py | 20 ++++++++++++++++++-- flatisfy/tools.py | 8 +++++--- flatisfy/web/app.py | 2 +- flatisfy/web/dbplugin.py | 21 ++++++++++++++++++++- flatisfy/web/routes/api.py | 6 +++--- 7 files changed, 52 insertions(+), 13 deletions(-) diff --git a/.ci/pylintrc b/.ci/pylintrc index 71f650e..790b882 100644 --- a/.ci/pylintrc +++ b/.ci/pylintrc @@ -99,7 +99,7 @@ evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / stateme [BASIC] # Good variable names which should always be accepted, separated by a comma -good-names=i,j,k,ex,Run,_,fh +good-names=i,j,k,ex,Run,_,fh,db # Bad variable names which should always be refused, separated by a comma bad-names=foo,bar,baz,toto,tutu,tata diff --git a/flatisfy/database/types.py b/flatisfy/database/types.py index 79f3c49..d55d7bb 100644 --- a/flatisfy/database/types.py +++ b/flatisfy/database/types.py @@ -27,7 +27,8 @@ class StringyJSON(types.TypeDecorator): def process_bind_param(self, value, dialect): """ - TODO + Process the bound param, serialize the object to JSON before saving + into database. """ if value is not None: value = json.dumps(value) @@ -35,7 +36,8 @@ class StringyJSON(types.TypeDecorator): def process_result_value(self, value, dialect): """ - TODO + Process the value fetched from the database, deserialize the JSON + string before returning the object. """ if value is not None: value = json.loads(value) diff --git a/flatisfy/filters/metadata.py b/flatisfy/filters/metadata.py index c050f0a..002934d 100644 --- a/flatisfy/filters/metadata.py +++ b/flatisfy/filters/metadata.py @@ -149,7 +149,7 @@ def guess_postal_code(flats_list, config, distance_threshold=20000): "Found postal code in location field for flat %s: %s.", flat["id"], postal_code ) - except AssertionError as e: + except AssertionError: postal_code = None # If not found, try to find a city @@ -294,7 +294,23 @@ def guess_stations(flats_list, config, distance_threshold=1500): flat["id"], ", ".join(x["name"] for x in good_matched_stations) ) - # TODO: Handle update (second pass) + + # If some stations were already filled in and the result is different, + # display some warning to the user + if ( + "matched_stations" in flat["flatisfy"]["matched_stations"] and + ( + # Do a set comparison, as ordering is not important + set(flat["flatisfy"]["matched_stations"]) != + set(good_matched_stations) + ) + ): + LOGGER.warning( + "Replacing previously fetched stations for flat %s. Found " + "stations differ from the previously found ones.", + flat["id"] + ) + flat["flatisfy"]["matched_stations"] = good_matched_stations return flats_list diff --git a/flatisfy/tools.py b/flatisfy/tools.py index f575011..f714286 100644 --- a/flatisfy/tools.py +++ b/flatisfy/tools.py @@ -19,6 +19,9 @@ import unidecode LOGGER = logging.getLogger(__name__) +# Constants +NAVITIA_ENDPOINT = "https://api.navitia.io/v1/coverage/fr-idf/journeys" + def pretty_json(data): """ @@ -204,7 +207,6 @@ def get_travel_time_between(latlng_from, latlng_to, config): .. note :: Uses the Navitia API. Requires a ``navitia_api_key`` field to be filled-in in the ``config``. """ - NAVITIA_ENDPOINT = "https://api.navitia.io/v1/coverage/fr-idf/journeys" time = None # Check that Navitia API key is available @@ -224,12 +226,12 @@ def get_travel_time_between(latlng_from, latlng_to, config): req.raise_for_status() time = req.json()["journeys"][0]["durations"]["total"] except (requests.exceptions.RequestException, - ValueError, IndexError, KeyError) as e: + ValueError, IndexError, KeyError) as exc: # Ignore any possible exception LOGGER.warning( "An exception occurred during travel time lookup on " "Navitia: %s.", - str(e) + str(exc) ) else: LOGGER.warning( diff --git a/flatisfy/web/app.py b/flatisfy/web/app.py index c5543e8..347bfb4 100644 --- a/flatisfy/web/app.py +++ b/flatisfy/web/app.py @@ -42,7 +42,7 @@ def get_app(config): # API v1 routes app.route("/api/v1/", "GET", api_routes.index_v1) app.route("/api/v1/flats", "GET", api_routes.flats_v1) - app.route("/api/v1/flat/:id", "GET", api_routes.flat_v1) + app.route("/api/v1/flat/:flat_id", "GET", api_routes.flat_v1) # Index app.route("/", "GET", lambda: _serve_static_file("index.html")) diff --git a/flatisfy/web/dbplugin.py b/flatisfy/web/dbplugin.py index 1d5e0b6..6b5e0b8 100644 --- a/flatisfy/web/dbplugin.py +++ b/flatisfy/web/dbplugin.py @@ -2,6 +2,10 @@ """ This module contains a Bottle plugin to pass the database argument to any route which needs it. + +This module is heavily based on code from +[Bottle-SQLAlchemy](https://github.com/iurisilvio/bottle-sqlalchemy) which is +licensed under MIT license. """ from __future__ import ( absolute_import, division, print_function, unicode_literals @@ -14,6 +18,10 @@ import bottle class DatabasePlugin(object): + """ + A Bottle plugin to automatically pass an SQLAlchemy database session object + to the routes specifying they need it. + """ name = 'database' api = 2 KEYWORD = "db" @@ -26,7 +34,7 @@ class DatabasePlugin(object): """ self.get_session = get_session - def setup(self, app): + def setup(self, app): # pylint: disable-no-self-use """ Make sure that other installed plugins don't affect the same keyword argument and check if metadata is available. @@ -40,6 +48,15 @@ class DatabasePlugin(object): ) def apply(self, callback, route): + """ + Method called on route invocation. Should apply some transformations to + the route prior to returing it. + + We check the presence of ``self.KEYWORD`` in the route signature and + replace the route callback by a partial invocation where we replaced + this argument by a valid SQLAlchemy session. + """ + # Check whether the route needs a valid db session or not. try: callback_args = inspect.signature(route.callback).parameters except AttributeError: @@ -47,8 +64,10 @@ class DatabasePlugin(object): callback_args = inspect.getargspec(route.callback).args if self.KEYWORD not in callback_args: + # If no need for a db session, call the route callback return callback else: + # Otherwise, we get a db session and pass it to the callback with self.get_session() as session: kwargs = {} kwargs[self.KEYWORD] = session diff --git a/flatisfy/web/routes/api.py b/flatisfy/web/routes/api.py index a4c88f2..8306740 100644 --- a/flatisfy/web/routes/api.py +++ b/flatisfy/web/routes/api.py @@ -35,13 +35,13 @@ def flats_v1(db): } -def flat_v1(id, db): +def flat_v1(flat_id, db): """ API v1 flat route: - GET /api/v1/flat/:id + GET /api/v1/flat/:flat_id """ - flat = db.query(flat_model.Flat).filter_by(id=id).first() + flat = db.query(flat_model.Flat).filter_by(id=flat_id).first() return { "data": flat.json_api_repr() }