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.
This commit is contained in:
Lucas Verney 2017-04-13 23:22:11 +02:00
parent d7012e3834
commit 4966fe2111
No known key found for this signature in database
GPG Key ID: 75B45CF41F334690
7 changed files with 52 additions and 13 deletions

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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(

View File

@ -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"))

View File

@ -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

View File

@ -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()
}