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

Feature/mobility data importers tests use mock fixtures #298

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
f5bf3ac
Add info of importing exclude rules
juuso-j Jul 20, 2023
12fa6fd
Add initial exclusion rules
juuso-j Jul 20, 2023
5fe6137
Add model ExclusionRule
juuso-j Jul 20, 2023
bf044ac
Import ExclusionRule
juuso-j Jul 20, 2023
848d52f
Add model ExclusionRule
juuso-j Jul 20, 2023
a40e0e7
Add websearch and exclusion rules
juuso-j Jul 20, 2023
bf98d3d
Add information about use_websearch param
juuso-j Jul 20, 2023
dcd3f38
Add get_search_exclusions function
juuso-j Jul 20, 2023
94dd7a2
Add fixtures for testing exclusion rules
juuso-j Jul 20, 2023
be19bb7
Add exclusion rules tests
juuso-j Jul 20, 2023
ecb26b8
Add function for getting data sources
juuso-j Jul 25, 2023
5bc1b3f
Add function for getting the data layer
juuso-j Jul 25, 2023
0c0f965
Move geojson file name retrieving to a function
juuso-j Jul 25, 2023
6e0d5c3
Move geojson file name retrieving to a function
juuso-j Jul 25, 2023
ec75be2
Fix typo
juuso-j Jul 25, 2023
f1a2dc6
Move geojson file name retrieving to a function
juuso-j Jul 25, 2023
e9a7169
Catch GDAL exception, add function to get the data source
juuso-j Jul 25, 2023
14d7078
Remove empty file, functionality moved
juuso-j Jul 25, 2023
36bb0a8
Remove obsolete 'the'
juuso-j Jul 25, 2023
04d6774
Fix typo
juuso-j Jul 25, 2023
44b3570
Replace inheritance from BaseImportCommand with BaseCommand
juuso-j Jul 25, 2023
b06c198
Replace inheritance from BaseImportCommand with BaseCommand
juuso-j Jul 25, 2023
f9f5216
Replace inheritance from BaseImportCommand with BaseCommand
juuso-j Jul 25, 2023
31d3553
Fix typo
juuso-j Jul 25, 2023
36a95ee
Fix typo
juuso-j Jul 25, 2023
f760b9c
Replace BaseImportCommand with BaseCommand and remove obsolete code
juuso-j Jul 26, 2023
8acd0c8
Send max_features as arg to get_data_source function
juuso-j Jul 26, 2023
9d2faec
Add get_data_source and get_test_fixture_data_layer functions
juuso-j Jul 26, 2023
42a728f
Mock fixture data
juuso-j Jul 26, 2023
9736d50
Remove json_data param
juuso-j Jul 26, 2023
1b086b0
Remove test_data param
juuso-j Jul 26, 2023
b88f317
Use mock objects for fixture data
juuso-j Jul 26, 2023
231f8ab
Add function to get JSON data
juuso-j Jul 27, 2023
8f25608
Patch get_json_data
juuso-j Jul 27, 2023
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
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,12 @@ For Turku specific imports see smbackend_turku/README.md.
./manage.py geo_import helsinki --divisions
./manage.py index_search_columns
```

Import exclude rules fixtures used by the search:
```
./manage.py loaddata services/fixtures/exclusion_rules.json
```
7. Redis

Redis is used for caching and as a message broker for Celery.
Install Redis. Ubuntu: `sudo apt-get install redis-server`

Expand Down Expand Up @@ -198,3 +202,6 @@ psql template1 -c 'CREATE EXTENSION IF NOT EXISTS pg_trgm;'
Mobility platform
-----------------
The mobility data platform of the service map is being developed as part of European Union Horizon 2020 programme funded SCALE-UP project (grant agreement no. 955332).

For more information see: mobility_data/README.mk

30 changes: 15 additions & 15 deletions mobility_data/importers/bicycle_stands.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,24 +198,24 @@
self.prefix_name = {k: f"{NAME_PREFIX[k]} {v}" for k, v in self.name.items()}


def get_bicycle_stand_objects(data_source=None):
def get_data_sources():
data_sources = []

Check warning on line 202 in mobility_data/importers/bicycle_stands.py

View check run for this annotation

Codecov / codecov/patch

mobility_data/importers/bicycle_stands.py#L202

Added line #L202 was not covered by tests
# Add the WFS datasource that is in GML format
ds = DataSource(BICYCLE_STANDS_URL)
data_sources.append(("gml", ds))

Check warning on line 205 in mobility_data/importers/bicycle_stands.py

View check run for this annotation

Codecov / codecov/patch

mobility_data/importers/bicycle_stands.py#L204-L205

Added lines #L204 - L205 were not covered by tests
# Add the GEOJSON datasource which is a file
data_path = os.path.join(get_root_dir(), "mobility_data/data")
file_path = os.path.join(data_path, GEOJSON_FILENAME)
ds = DataSource(file_path)
data_sources.append(("geojson", ds))
return data_sources

Check warning on line 211 in mobility_data/importers/bicycle_stands.py

View check run for this annotation

Codecov / codecov/patch

mobility_data/importers/bicycle_stands.py#L207-L211

Added lines #L207 - L211 were not covered by tests


def get_bicycle_stand_objects():
"""
Returns a list containg instances of BicycleStand class.
"""
data_sources = []

if data_source:
data_sources.append(data_source)
else:
# Add the WFS datasource that is in GML format
ds = DataSource(BICYCLE_STANDS_URL)
data_sources.append(("gml", ds))
# Add the GEOJSON datasource which is a file
data_path = os.path.join(get_root_dir(), "mobility_data/data")
file_path = os.path.join(data_path, GEOJSON_FILENAME)
ds = DataSource(file_path)
data_sources.append(("geojson", ds))

data_sources = get_data_sources()
bicycle_stands = []
"""
external_stands dict is used to keep track of the names of imported external stands
Expand Down
24 changes: 11 additions & 13 deletions mobility_data/importers/bike_service_stations.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,18 @@
self.extra["in_terrain"] = feature["Maastossa"].as_string()


def get_bike_service_station_objects(geojson_file=None):
bicycle_repair_points = []
file_name = None
if not geojson_file:
file_name = get_file_name_from_data_source(CONTENT_TYPE_NAME)
if not file_name:
file_name = f"{get_root_dir()}/mobility_data/data/{GEOJSON_FILENAME}"
else:
file_name = f"{get_root_dir()}/mobility_data/data/{GEOJSON_FILENAME}"
def get_data_layer():
file_name = get_file_name_from_data_source(CONTENT_TYPE_NAME)

Check warning on line 68 in mobility_data/importers/bike_service_stations.py

View check run for this annotation

Codecov / codecov/patch

mobility_data/importers/bike_service_stations.py#L68

Added line #L68 was not covered by tests
if not file_name:
file_name = f"{get_root_dir()}/mobility_data/data/{GEOJSON_FILENAME}"

Check warning on line 70 in mobility_data/importers/bike_service_stations.py

View check run for this annotation

Codecov / codecov/patch

mobility_data/importers/bike_service_stations.py#L70

Added line #L70 was not covered by tests
else:
# Use the test data file
file_name = f"{get_root_dir()}/mobility_data/tests/data/{geojson_file}"

file_name = f"{get_root_dir()}/mobility_data/data/{GEOJSON_FILENAME}"

Check warning on line 72 in mobility_data/importers/bike_service_stations.py

View check run for this annotation

Codecov / codecov/patch

mobility_data/importers/bike_service_stations.py#L72

Added line #L72 was not covered by tests
data_layer = GDALDataSource(file_name)[0]
for feature in data_layer:
return data_layer

Check warning on line 74 in mobility_data/importers/bike_service_stations.py

View check run for this annotation

Codecov / codecov/patch

mobility_data/importers/bike_service_stations.py#L74

Added line #L74 was not covered by tests


def get_bike_service_station_objects():
bicycle_repair_points = []
for feature in get_data_layer():
bicycle_repair_points.append(BikeServiceStation(feature))
return bicycle_repair_points
18 changes: 9 additions & 9 deletions mobility_data/importers/charging_stations.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,18 +111,18 @@
return number_of_rows


def get_charging_station_objects(csv_file=None):
def get_csv_file_name():
file_name = get_file_name_from_data_source(CONTENT_TYPE_NAME)

Check warning on line 115 in mobility_data/importers/charging_stations.py

View check run for this annotation

Codecov / codecov/patch

mobility_data/importers/charging_stations.py#L115

Added line #L115 was not covered by tests
if file_name:
return file_name
return f"{get_root_dir()}/mobility_data/data/{SOURCE_DATA_FILE_NAME}"

Check warning on line 118 in mobility_data/importers/charging_stations.py

View check run for this annotation

Codecov / codecov/patch

mobility_data/importers/charging_stations.py#L117-L118

Added lines #L117 - L118 were not covered by tests


def get_charging_station_objects():
# Store the imported stations to dict, the index is the key.
file_name = get_csv_file_name()
charging_stations = {}
column_mappings = {}
if not csv_file:
file_name = get_file_name_from_data_source(CONTENT_TYPE_NAME)
if not file_name:
file_name = f"{get_root_dir()}/mobility_data/data/{SOURCE_DATA_FILE_NAME}"
else:
# Use the test data file
file_name = f"{get_root_dir()}/mobility_data/tests/data/{csv_file}"

number_of_rows = get_number_of_rows(file_name)
with open(file_name, encoding="utf-8-sig") as csv_file:
csv_reader = csv.reader(csv_file, delimiter=";")
Expand Down
20 changes: 9 additions & 11 deletions mobility_data/importers/disabled_and_no_staff_parking.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,19 +135,17 @@
self.extra[field_name] = feature[field].as_double()


def get_no_staff_parking_objects(geojson_file=None):
no_staff_parkings = []
disabled_parkings = []
file_name = None
def get_geojson_file_name():
file_name = get_file_name_from_data_source(NO_STAFF_PARKING_CONTENT_TYPE_NAME)

Check warning on line 139 in mobility_data/importers/disabled_and_no_staff_parking.py

View check run for this annotation

Codecov / codecov/patch

mobility_data/importers/disabled_and_no_staff_parking.py#L139

Added line #L139 was not covered by tests
if file_name:
return file_name
return f"{get_root_dir()}/mobility_data/data/{GEOJSON_FILENAME}"

Check warning on line 142 in mobility_data/importers/disabled_and_no_staff_parking.py

View check run for this annotation

Codecov / codecov/patch

mobility_data/importers/disabled_and_no_staff_parking.py#L141-L142

Added lines #L141 - L142 were not covered by tests

if not geojson_file:
file_name = get_file_name_from_data_source(NO_STAFF_PARKING_CONTENT_TYPE_NAME)
if not file_name:
file_name = f"{get_root_dir()}/mobility_data/data/{GEOJSON_FILENAME}"
else:
# Use the test data file
file_name = f"{get_root_dir()}/mobility_data/tests/data/{geojson_file}"

def get_no_staff_parking_objects():
no_staff_parkings = []
disabled_parkings = []
file_name = get_geojson_file_name()
data_layer = GDALDataSource(file_name)[0]

for feature in data_layer:
Expand Down
16 changes: 11 additions & 5 deletions mobility_data/importers/gas_filling_station.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import logging

import requests
from django.conf import settings
from django.contrib.gis.geos import Point, Polygon
from munigeo.models import Municipality

from .constants import SOUTHWEST_FINLAND_BOUNDARY, SOUTHWEST_FINLAND_BOUNDARY_SRID
from .utils import (
fetch_json,
get_street_name_and_number,
get_street_name_translations,
LANGUAGES,
Expand Down Expand Up @@ -54,15 +54,21 @@
self.extra["lng_cng"] = self.lng_cng


def get_filtered_gas_filling_station_objects(json_data=None):
def get_json_data(url):
response = requests.get(url)
assert response.status_code == 200, "Fetching {} status code: {}".format(

Check warning on line 59 in mobility_data/importers/gas_filling_station.py

View check run for this annotation

Codecov / codecov/patch

mobility_data/importers/gas_filling_station.py#L58-L59

Added lines #L58 - L59 were not covered by tests
url, response.status_code
)
return response.json()

Check warning on line 62 in mobility_data/importers/gas_filling_station.py

View check run for this annotation

Codecov / codecov/patch

mobility_data/importers/gas_filling_station.py#L62

Added line #L62 was not covered by tests


def get_filtered_gas_filling_station_objects():
"""
Returns a list of GasFillingStation objects that are filtered by location.
Stations inside boundarys of Southwest Finland are included, the rest
are discarded.
"""

if not json_data:
json_data = fetch_json(GAS_FILLING_STATIONS_URL)
json_data = get_json_data(GAS_FILLING_STATIONS_URL)
# srid = json_data["spatialReference"]["wkid"]
# NOTE, hack to fix srid 102100 in source data causes "crs not found"
srid = 4326
Expand Down
18 changes: 8 additions & 10 deletions mobility_data/importers/loading_unloading_places.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,18 +104,16 @@
self.extra[field_name] = feature[field].as_int()


def get_loading_and_unloading_objects(geojson_file=None):
objects = []
file_name = None
def get_geojson_file_name():
file_name = get_file_name_from_data_source(CONTENT_TYPE_NAME)

Check warning on line 108 in mobility_data/importers/loading_unloading_places.py

View check run for this annotation

Codecov / codecov/patch

mobility_data/importers/loading_unloading_places.py#L108

Added line #L108 was not covered by tests
if file_name:
return file_name
return f"{get_root_dir()}/mobility_data/data/{GEOJSON_FILENAME}"

Check warning on line 111 in mobility_data/importers/loading_unloading_places.py

View check run for this annotation

Codecov / codecov/patch

mobility_data/importers/loading_unloading_places.py#L110-L111

Added lines #L110 - L111 were not covered by tests

if not geojson_file:
file_name = get_file_name_from_data_source(CONTENT_TYPE_NAME)
if not file_name:
file_name = f"{get_root_dir()}/mobility_data/data/{GEOJSON_FILENAME}"
else:
# Use the test data file
file_name = f"{get_root_dir()}/mobility_data/tests/data/{geojson_file}"

def get_loading_and_unloading_objects():
objects = []
file_name = get_geojson_file_name()
data_layer = GDALDataSource(file_name)[0]
for feature in data_layer:
objects.append(LoadingPlace(feature))
Expand Down
4 changes: 2 additions & 2 deletions mobility_data/importers/lounaistieto_shapefiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,5 +123,5 @@
if obj.add_feature(feature, config, srid):
objects.append(obj)
content_type = get_or_create_content_type_from_config(config["content_type_name"])
num_ceated, num_deleted = save_to_database(objects, content_type)
log_imported_message(logger, content_type, num_ceated, num_deleted)
num_created, num_deleted = save_to_database(objects, content_type)
log_imported_message(logger, content_type, num_created, num_deleted)

Check warning on line 127 in mobility_data/importers/lounaistieto_shapefiles.py

View check run for this annotation

Codecov / codecov/patch

mobility_data/importers/lounaistieto_shapefiles.py#L126-L127

Added lines #L126 - L127 were not covered by tests
16 changes: 8 additions & 8 deletions mobility_data/importers/share_car_parking_places.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,16 @@
self.extra[self.RESTRICTION_FIELD][language] = restrictions[i].strip()


def get_geojson_file_name():
file_name = get_file_name_from_data_source(CONTENT_TYPE_NAME)

Check warning on line 58 in mobility_data/importers/share_car_parking_places.py

View check run for this annotation

Codecov / codecov/patch

mobility_data/importers/share_car_parking_places.py#L58

Added line #L58 was not covered by tests
if file_name:
return file_name
return f"{get_root_dir()}/mobility_data/data/{GEOJSON_FILENAME}"

Check warning on line 61 in mobility_data/importers/share_car_parking_places.py

View check run for this annotation

Codecov / codecov/patch

mobility_data/importers/share_car_parking_places.py#L60-L61

Added lines #L60 - L61 were not covered by tests


def get_car_share_parking_place_objects(geojson_file=None):
car_share_parking_places = []
file_name = None
if not geojson_file:
file_name = get_file_name_from_data_source(CONTENT_TYPE_NAME)
if not file_name:
file_name = f"{get_root_dir()}/mobility_data/data/{GEOJSON_FILENAME}"
else:
# Use the test data file
file_name = f"{get_root_dir()}/mobility_data/tests/data/{geojson_file}"
file_name = get_geojson_file_name()

data_layer = GDALDataSource(file_name)[0]
for feature in data_layer:
Expand Down
55 changes: 31 additions & 24 deletions mobility_data/importers/wfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from django import db
from django.conf import settings
from django.contrib.gis.gdal import DataSource
from django.contrib.gis.gdal.error import GDALException
from django.contrib.gis.geos import GEOSGeometry, MultiPolygon, Polygon
from munigeo.models import Municipality

Expand Down Expand Up @@ -67,22 +68,24 @@
if config.get("locates_in_turku", False):
if not locates_in_turku(feature, source_srid):
return False

# If geometry contains multiple polygons and create_multipolygon attribute is True
# create one multipolygon from the polygons.
if (
len(feature.geom.coords) > 1
and create_multipolygon
and isinstance(feature.geom, gdalgeometries.Polygon)
):
polygons = []
for coords in feature.geom.coords:
polygons.append(Polygon(coords, srid=source_srid))
self.geometry = MultiPolygon(polygons, srid=source_srid)
else:
self.geometry = GEOSGeometry(feature.geom.wkt, srid=source_srid)
self.geometry.transform(settings.DEFAULT_SRID)

try:
if (
len(feature.geom.coords) > 1
and create_multipolygon
and isinstance(feature.geom, gdalgeometries.Polygon)
):
polygons = []
for coords in feature.geom.coords:
polygons.append(Polygon(coords, srid=source_srid))
self.geometry = MultiPolygon(polygons, srid=source_srid)
else:
self.geometry = GEOSGeometry(feature.geom.wkt, srid=source_srid)
self.geometry.transform(settings.DEFAULT_SRID)
except GDALException as ex:
logger.error(ex)
return False

Check warning on line 88 in mobility_data/importers/wfs.py

View check run for this annotation

Codecov / codecov/patch

mobility_data/importers/wfs.py#L86-L88

Added lines #L86 - L88 were not covered by tests
if "municipality" in config:
municipality = feature[config["municipality"]].as_string()
if municipality:
Expand Down Expand Up @@ -129,8 +132,16 @@
return True


def get_data_source(config, max_features):
wfs_url = config.get("wfs_url", settings.TURKU_WFS_URL)
url = WFS_URL.format(

Check warning on line 137 in mobility_data/importers/wfs.py

View check run for this annotation

Codecov / codecov/patch

mobility_data/importers/wfs.py#L136-L137

Added lines #L136 - L137 were not covered by tests
wfs_url=wfs_url, wfs_layer=config["wfs_layer"], max_features=max_features
)
ds = DataSource(url)
return ds

Check warning on line 141 in mobility_data/importers/wfs.py

View check run for this annotation

Codecov / codecov/patch

mobility_data/importers/wfs.py#L140-L141

Added lines #L140 - L141 were not covered by tests


def import_wfs_feature(config, data_file=None):
max_features = DEFAULT_MAX_FEATURES
if "content_type_name" not in config:
logger.warning(f"Skipping feature {config}, 'content_type_name' is required.")
return False
Expand All @@ -139,23 +150,19 @@
return False
if "max_features" in config:
max_features = config["max_features"]
wfs_layer = config["wfs_layer"]
else:
max_features = DEFAULT_MAX_FEATURES
objects = []
if data_file:
ds = DataSource(data_file)
else:
wfs_url = config.get("wfs_url", settings.TURKU_WFS_URL)

url = WFS_URL.format(
wfs_url=wfs_url, wfs_layer=wfs_layer, max_features=max_features
)
ds = DataSource(url)
ds = get_data_source(config, max_features)
assert len(ds) == 1
layer = ds[0]
for feature in layer:
object = MobilityData()
if object.add_feature(feature, config):
objects.append(object)
content_type = get_or_create_content_type_from_config(config["content_type_name"])
num_ceated, num_deleted = save_to_database(objects, content_type)
log_imported_message(logger, content_type, num_ceated, num_deleted)
num_created, num_deleted = save_to_database(objects, content_type)
log_imported_message(logger, content_type, num_created, num_deleted)
13 changes: 0 additions & 13 deletions mobility_data/management/commands/_utils.py

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"""
This command removes all units that have a ContentType or
GroupType where type_name is not Null. This data is deprecated
as the only the name will be used in future.
as only the name will be used in future.
"""


Expand Down
Loading
Loading