1+ from pathlib import PurePath
2+
13import io
24import json
35import re
@@ -647,7 +649,7 @@ def filter_geom(self, src, val):
647649 plan = self ._find_first_plan_with_supported_file_extension (val , supported_extensions )
648650 geom_file = self ._fetch_geometry_file (plan )
649651
650- ext = plan [ 'traductionFichiers' ][ 0 ][ 'extension' ]
652+ ext = self . _get_plan_extension ( plan )
651653 if ext == 'gpx' :
652654 return ApidaeTrekParser ._get_geom_from_gpx (geom_file )
653655 elif ext == 'kml' :
@@ -694,7 +696,7 @@ def filter_source(self, src, val):
694696 val = [manager ['nom' ]]
695697 )
696698 source = sources [0 ]
697- source .website = manager [ 'siteWeb' ]
699+ source .website = manager . get ( 'siteWeb' )
698700 source .save ()
699701 return sources
700702
@@ -902,14 +904,26 @@ def _find_first_plan_with_supported_file_extension(items, supported_extensions):
902904 plans = [item for item in items if item ['type' ] == 'PLAN' ]
903905 if not plans :
904906 raise RowImportError ('The trek from APIDAE has no attachment with the type "PLAN"' )
905- supported_plans = [plan for plan in plans if plan ['traductionFichiers' ][0 ]['extension' ] in supported_extensions ]
907+ supported_plans = [plan for plan in plans if
908+ ApidaeTrekParser ._get_plan_extension (plan ) in supported_extensions ]
906909 if not supported_plans :
907910 raise RowImportError (
908911 "The trek from APIDAE has no attached \" PLAN\" in a supported format. "
909912 f"Supported formats are : { ', ' .join (supported_extensions )} "
910913 )
911914 return supported_plans [0 ]
912915
916+ @staticmethod
917+ def _get_plan_extension (plan ):
918+ info_fichier = plan ['traductionFichiers' ][0 ]
919+ extension_prop = info_fichier .get ('extension' )
920+ if extension_prop :
921+ return extension_prop
922+ url_suffix = PurePath (info_fichier ['url' ]).suffix
923+ if url_suffix :
924+ return url_suffix .split ('.' )[1 ]
925+ return None
926+
913927 @staticmethod
914928 def _get_geom_from_gpx (data ):
915929 """Given GPX data as bytes it returns a geom."""
@@ -925,6 +939,8 @@ def _get_geom_from_gpx(data):
925939 geos = ApidaeTrekParser ._maybe_get_linestring_from_layer (layer )
926940 if geos :
927941 break
942+ else :
943+ raise RowImportError ("No LineString feature found in GPX layers tracks or routes" )
928944 geos .transform (settings .SRID )
929945 return geos
930946
@@ -998,13 +1014,24 @@ def _convert_to_geos(geom):
9981014 def _maybe_get_linestring_from_layer (layer ):
9991015 if layer .num_feat == 0 :
10001016 return None
1001- first_feature = layer [0 ]
1002- geos = ApidaeTrekParser ._convert_to_geos (first_feature .geom )
1003- if geos .geom_type == 'MultiLineString' :
1004- geos = geos .merged
1017+ geoms = []
1018+ for feat in layer :
1019+ if feat .geom .num_coords == 0 :
1020+ continue
1021+ geos = ApidaeTrekParser ._convert_to_geos (feat .geom )
10051022 if geos .geom_type == 'MultiLineString' :
1006- raise RowImportError (_ ("The geometry cannot be converted to a single continuous LineString feature" ))
1007- return geos
1023+ geos = geos .merged # If possible we merge the MultiLineString into a LineString
1024+ if geos .geom_type == 'MultiLineString' :
1025+ raise RowImportError (_ ("Feature geometry cannot be converted to a single continuous LineString feature" ))
1026+ geoms .append (geos )
1027+
1028+ full_geom = MultiLineString (geoms )
1029+ full_geom .srid = geoms [0 ].srid
1030+ full_geom = full_geom .merged # If possible we merge the MultiLineString into a LineString
1031+ if full_geom .geom_type == 'MultiLineString' :
1032+ raise RowImportError (_ ("Geometries from various features cannot be converted to a single continuous LineString feature" ))
1033+
1034+ return full_geom
10081035
10091036 @staticmethod
10101037 def _find_matching_practice_in_mapping (activities_ids , mapping ):
@@ -1095,12 +1122,19 @@ def est_fermé_temporairement(ouverture):
10951122
10961123 @staticmethod
10971124 def _make_duration (duration_in_minutes = None , duration_in_days = None ):
1098- """Returns the duration in hours. The method expects one argument or the other, not both. If both arguments have
1099- non-zero values the method only considers `duration_in_minutes` and discards `duration_in_days`."""
1100- if duration_in_minutes :
1101- return float ((Decimal (duration_in_minutes ) / Decimal (60 )).quantize (Decimal ('.01' )))
1102- elif duration_in_days :
1125+ """Returns the duration in hours. There are 2 use cases:
1126+
1127+ 1. the parsed trek is a one-day trip: only the duration in minutes is provided from Apiade.
1128+ 2. the parsed trek is a multiple-day trip: the duration_in_days is provided. The duration_in_minutes may be provided
1129+ as a crude indication of how long each step is. That second value does not fit in Geotrek model.
1130+
1131+ So the duration_in_days is used if provided (and duration_in_minutes discarded), it means we are in the use case 2.
1132+ Otherwise the duration_in_minutes is used, it means use case 1.
1133+ """
1134+ if duration_in_days :
11031135 return float (duration_in_days * 24 )
1136+ elif duration_in_minutes :
1137+ return float ((Decimal (duration_in_minutes ) / Decimal (60 )).quantize (Decimal ('.01' )))
11041138 else :
11051139 return None
11061140
0 commit comments