Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-gpxpy for openSUSE:Factory 
checked in at 2021-04-29 01:38:20
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-gpxpy (Old)
 and      /work/SRC/openSUSE:Factory/.python-gpxpy.new.12324 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-gpxpy"

Thu Apr 29 01:38:20 2021 rev:4 rq:888985 version:1.4.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-gpxpy/python-gpxpy.changes        
2020-05-28 09:16:44.892882868 +0200
+++ /work/SRC/openSUSE:Factory/.python-gpxpy.new.12324/python-gpxpy.changes     
2021-04-29 01:39:26.322666726 +0200
@@ -1,0 +2,10 @@
+Wed Apr 28 09:01:30 UTC 2021 - Mark??ta Machov?? <[email protected]>
+
+- update to 1.4.2
+  * Consider microseconds when total_seconds o timedelta is requested
+  * Use list instead of getchildren for Python 3.9 compatibility
+  * get_nearest_location(location) has the property that if 'location' 
+    is a point on the track, the point after 'location' on the track 
+    is returned
+
+-------------------------------------------------------------------

Old:
----
  gpxpy-1.4.0.tar.gz

New:
----
  gpxpy-1.4.2.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-gpxpy.spec ++++++
--- /var/tmp/diff_new_pack.V9SwYU/_old  2021-04-29 01:39:26.726667298 +0200
+++ /var/tmp/diff_new_pack.V9SwYU/_new  2021-04-29 01:39:26.730667304 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-gpxpy
 #
-# Copyright (c) 2020 SUSE LLC
+# Copyright (c) 2021 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -19,7 +19,7 @@
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %define skip_python2 1
 Name:           python-gpxpy
-Version:        1.4.0
+Version:        1.4.2
 Release:        0
 Summary:        GPX file parser and GPS track manipulation library
 License:        Apache-2.0
@@ -30,7 +30,7 @@
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
 Requires(post): update-alternatives
-Requires(postun): update-alternatives
+Requires(postun):update-alternatives
 BuildArch:      noarch
 %python_subpackages
 

++++++ gpxpy-1.4.0.tar.gz -> gpxpy-1.4.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gpxpy-1.4.0/PKG-INFO new/gpxpy-1.4.2/PKG-INFO
--- old/gpxpy-1.4.0/PKG-INFO    2020-01-16 20:43:18.000000000 +0100
+++ new/gpxpy-1.4.2/PKG-INFO    2020-06-22 08:57:48.000000000 +0200
@@ -1,8 +1,8 @@
 Metadata-Version: 2.1
 Name: gpxpy
-Version: 1.4.0
+Version: 1.4.2
 Summary: GPX file parser and GPS track manipulation library
-Home-page: http://www.trackprofiler.com/gpxpy/index.html
+Home-page: https://github.com/tkrajina/gpxpy
 Author: Tomo Krajina
 Author-email: [email protected]
 License: Apache License, Version 2.0
@@ -76,7 +76,7 @@
         
         ## GPX version
         
-        gpx.py can parse and generate GPX 1.0 and 1.1 files. Note that the 
generated file will always be a valid XML document, but it may not be (strictly 
speaking) a valid GPX document. For example, if you set gpx.email to "my.email 
AT mail.com" the generated GPX tag won't confirm to the regex pattern. And the 
file won't be valid. Most applications will ignore such errors, but... Be aware 
of this!
+        gpx.py can parse and generate GPX 1.0 and 1.1 files. The generated 
file will always be a valid XML document, but it may not be (strictly speaking) 
a valid GPX document. For example, if you set gpx.email to "my.email AT 
mail.com" the generated GPX tag won't confirm to the regex pattern. And the 
file won't be valid. Most applications will ignore such errors, but... Be aware 
of this!
         
         Be aware that the gpxpy object model *is not 100% equivalent* with the 
underlying GPX XML file schema. That's because the library object model works 
with both GPX 1.0 and 1.1.
         
@@ -88,9 +88,7 @@
         
         ## XML parsing
         
-        If lxml is available, then it will be used for XML parsing.
-        Otherwise minidom is used.
-        Note that lxml is 2-3 times faster so, if you can choose -- use it :)
+        If lxml is available, then it will be used for XML parsing, otherwise 
minidom is used. Lxml is 2-3 times faster so, if you can choose -- use it.
         
         The GPX version is automatically determined when parsing by reading 
the version attribute in the gpx node. If this attribute is not present then 
the version is assumed to be 1.0. A specific version can be forced by setting 
the `version` parameter in the parse function. Possible values for the 
'version' parameter are `1.0`, `1.1` and `None`.
         
@@ -98,7 +96,7 @@
         
         Branches:
         
-        * `branch` contains the code of the latest release
+        * `master` contains the code of the latest release
         * `dev` branch is where code for the next release should go.
         
         Send your pull request against `dev`, not `master`!
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gpxpy-1.4.0/README.md new/gpxpy-1.4.2/README.md
--- old/gpxpy-1.4.0/README.md   2020-01-16 20:41:16.000000000 +0100
+++ new/gpxpy-1.4.2/README.md   2020-05-16 08:46:48.000000000 +0200
@@ -68,7 +68,7 @@
 
 ## GPX version
 
-gpx.py can parse and generate GPX 1.0 and 1.1 files. Note that the generated 
file will always be a valid XML document, but it may not be (strictly speaking) 
a valid GPX document. For example, if you set gpx.email to "my.email AT 
mail.com" the generated GPX tag won't confirm to the regex pattern. And the 
file won't be valid. Most applications will ignore such errors, but... Be aware 
of this!
+gpx.py can parse and generate GPX 1.0 and 1.1 files. The generated file will 
always be a valid XML document, but it may not be (strictly speaking) a valid 
GPX document. For example, if you set gpx.email to "my.email AT mail.com" the 
generated GPX tag won't confirm to the regex pattern. And the file won't be 
valid. Most applications will ignore such errors, but... Be aware of this!
 
 Be aware that the gpxpy object model *is not 100% equivalent* with the 
underlying GPX XML file schema. That's because the library object model works 
with both GPX 1.0 and 1.1.
 
@@ -80,9 +80,7 @@
 
 ## XML parsing
 
-If lxml is available, then it will be used for XML parsing.
-Otherwise minidom is used.
-Note that lxml is 2-3 times faster so, if you can choose -- use it :)
+If lxml is available, then it will be used for XML parsing, otherwise minidom 
is used. Lxml is 2-3 times faster so, if you can choose -- use it.
 
 The GPX version is automatically determined when parsing by reading the 
version attribute in the gpx node. If this attribute is not present then the 
version is assumed to be 1.0. A specific version can be forced by setting the 
`version` parameter in the parse function. Possible values for the 'version' 
parameter are `1.0`, `1.1` and `None`.
 
@@ -90,7 +88,7 @@
 
 Branches:
 
-* `branch` contains the code of the latest release
+* `master` contains the code of the latest release
 * `dev` branch is where code for the next release should go.
 
 Send your pull request against `dev`, not `master`!
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gpxpy-1.4.0/gpxpy/__init__.py 
new/gpxpy-1.4.2/gpxpy/__init__.py
--- old/gpxpy-1.4.0/gpxpy/__init__.py   2020-01-16 20:42:14.000000000 +0100
+++ new/gpxpy-1.4.2/gpxpy/__init__.py   2020-06-22 08:57:11.000000000 +0200
@@ -16,7 +16,7 @@
 
 from . import gpx as mod_gpx
 
-__version__ = '1.4.0'
+__version__ = '1.4.2'
 
 def parse(xml_or_file: Union[AnyStr, IO[str]], version: Optional[str] = None) 
-> mod_gpx.GPX:
     """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gpxpy-1.4.0/gpxpy/gpx.py new/gpxpy-1.4.2/gpxpy/gpx.py
--- old/gpxpy-1.4.0/gpxpy/gpx.py        2020-01-16 20:41:16.000000000 +0100
+++ new/gpxpy-1.4.2/gpxpy/gpx.py        2020-06-22 08:55:50.000000000 +0200
@@ -125,7 +125,7 @@
 class MinimumMaximum(NamedTuple):
     minimum: Optional[float]
     maximum: Optional[float]
-class NearestLocationData(NamedTuple):
+class NearestLocationData(NamedTuple):  # this is also what walk() 
returns/iterates over
     location: "GPXTrackPoint"
     track_no: int
     segment_no: int
@@ -781,7 +781,7 @@
         for track_point in self.points:
             track_point.move(location_delta)
 
-    def walk(self, only_points: bool=False) -> Iterator[Any]: # TODO: find a 
better solution for typing
+    def walk(self, only_points: bool=False) -> Iterator[Any]: # 
Union[GPXTrackPoint, Tuple[GPXTrackPoint, int]]]:
         """
         Generator for iterating over segment points
 
@@ -797,7 +797,7 @@
         point_no: int
             Not included in yield if only_points is true
         """
-        for point_no, point in enumerate(self.points):
+        for point_no, point in enumerate(self.points if self.points else []):
             if only_points:
                 yield point
             else:
@@ -904,18 +904,16 @@
                 speed_kmh: float = 0
                 if seconds > 0 and distance is not None:
                     # TODO: compute threshold in m/s instead this to kmh every 
time:
-                    speed_kmh = (distance / 1000.) / 
(mod_utils.total_seconds(timedelta) / 60. ** 2)
-
-                #print speed, stopped_speed_threshold
-                if distance:
-                    if speed_kmh <= stopped_speed_threshold:
-                        stopped_time += mod_utils.total_seconds(timedelta)
-                        stopped_distance += distance
-                    else:
-                        moving_time += mod_utils.total_seconds(timedelta)
-                        moving_distance += distance
-                    if moving_time:
-                        speeds_and_distances.append((distance / 
mod_utils.total_seconds(timedelta), distance, ))
+                    speed_kmh = (distance / 1000.) / (seconds / 60. ** 2)
+                    if distance:
+                        if speed_kmh <= stopped_speed_threshold:
+                            stopped_time += seconds
+                            stopped_distance += distance
+                        else:
+                            moving_time += seconds
+                            moving_distance += distance
+                        if moving_time:
+                            speeds_and_distances.append((distance / seconds, 
distance, ))
 
         max_speed = None
         if speeds_and_distances:
@@ -1218,27 +1216,9 @@
 
     def get_nearest_location(self, location: mod_geo.Location) -> 
Optional[NearestLocationData]:
         """ Return the (location, track_point_no) on this track segment """
-        if not self.points:
-            return None
-
-        result: Optional[GPXTrackPoint] = None
-        current_distance = None
-        result_track_point_no = None
-        for i in range(len(self.points)):
-            track_point = self.points[i]
-            if not result:
-                result = track_point
-            else:
-                distance = track_point.distance_2d(location)
-                #print current_distance, distance
-                if not current_distance or distance < current_distance:
-                    current_distance = distance
-                    result = track_point
-                    result_track_point_no = i
-
-        if result is not None and result_track_point_no is not None:
-            return NearestLocationData(result, -1, -1, result_track_point_no)
-        return None
+        return min((NearestLocationData(pt, -1, -1, pt_no) for (pt, pt_no) in 
self.walk())
+                   ,key=lambda x: x.location.distance_2d(location) if x is not 
None else float('INF')
+                   ,default=None)
 
     def smooth(self, vertical: bool=True, horizontal: bool=False, 
remove_extremes: bool=False) -> None:
         """ "Smooths" the elevation graph. Can be called multiple times. """
@@ -1565,7 +1545,7 @@
 
         return bounds
 
-    def walk(self, only_points: bool=False) -> Iterator[Union[GPXTrackPoint, 
Tuple[GPXTrackPoint, int, int]]]:
+    def walk(self, only_points: bool=False) -> Iterator[Any]: 
#Union[GPXTrackPoint, Tuple[GPXTrackPoint, int, int]]]:
         """
         Generator used to iterates through track
 
@@ -1584,8 +1564,8 @@
         point_no : integer
             Index of point. This is suppressed if only_points is True.
         """
-        for segment_no, segment in enumerate(self.segments):
-            for point_no, point in enumerate(segment.points):
+        for segment_no, segment in enumerate(self.segments if self.segments 
else []):
+            for point_no, point in enumerate(segment.points if segment.points 
else []):
                 if only_points:
                     yield point
                 else:
@@ -1914,30 +1894,10 @@
 
     def get_nearest_location(self, location: mod_geo.Location) -> 
Optional[NearestLocationData]:
         """ Returns (location, track_segment_no, track_point_no) for nearest 
location on track """
-        if not self.segments:
-            return None
-
-        result: Optional[GPXTrackPoint] = None
-        distance: float = -1
-        result_track_segment_no: int = -1
-        result_track_point_no: int = -1
-
-        for i in range(len(self.segments)):
-            track_segment = self.segments[i]
-            nearest_loc_info = track_segment.get_nearest_location(location)
-            nearest_location_distance = None
-            if nearest_loc_info:
-                nearest_location_distance = 
nearest_loc_info.location.distance_2d(location)
-                if distance is not None and nearest_location_distance is not 
None and (distance < 0 or nearest_location_distance < distance):
-                    distance = nearest_location_distance
-                    result = nearest_loc_info.location
-                    result_track_segment_no = i
-                    result_track_point_no = nearest_loc_info.point_no
-
-        if result:
-            return NearestLocationData(result, -1, result_track_segment_no, 
result_track_point_no)
-        return None
-
+        return min((NearestLocationData(pt, -1, seg, pt_no) for (pt, seg, 
pt_no) in self.walk())
+                   ,key=lambda x: x.location.distance_2d(location) if x is not 
None else float('INF')
+                   ,default=None)
+        
     def clone(self) -> "GPXTrack":
         return mod_copy.deepcopy(self)
 
@@ -2354,9 +2314,9 @@
         point_no : integer
             Index of point. This is suppressed if only_points is True.
         """
-        for track_no, track in enumerate(self.tracks):
-            for segment_no, segment in enumerate(track.segments):
-                for point_no, point in enumerate(segment.points):
+        for track_no, track in enumerate(self.tracks if self.tracks else [] ):
+            for segment_no, segment in enumerate(track.segments if 
track.segments else []):
+                for point_no, point in enumerate(segment.points if 
segment.points else []):
                     if only_points:
                         yield point
                     else:
@@ -2549,32 +2509,13 @@
 
         return result
 
+
     def get_nearest_location(self, location: mod_geo.Location) -> 
Optional[NearestLocationData]:
         """ Returns (location, track_no, track_segment_no, track_point_no) for 
the
         nearest location on map """
-        if not self.tracks:
-            return None
-
-        result: Optional[GPXTrackPoint] = None
-        distance = None
-        result_track_no: int = -1
-        result_segment_no: int = -1
-        result_point_no: int = -1
-        for i in range(len(self.tracks)):
-            track = self.tracks[i]
-            nearest_loc_info = track.get_nearest_location(location)
-            if nearest_loc_info:
-                nearest_location_distance = 
nearest_loc_info.location.distance_2d(location)
-                if not distance or nearest_location_distance < distance:
-                    result = nearest_loc_info.location
-                    distance = nearest_location_distance
-                    result_track_no = i
-                    result_segment_no = nearest_loc_info.segment_no
-                    result_point_no = nearest_loc_info.point_no
-
-        if result:
-            return NearestLocationData(result, result_track_no, 
result_segment_no, result_point_no)
-        return None
+        return min((NearestLocationData(pt, tr, seg, pt_no) for (pt,tr, seg, 
pt_no) in self.walk())
+                   ,key=lambda x: x.location.distance_2d(location) if x is not 
None else float('INF')
+                   ,default=None)
 
     def add_elevation(self, delta: float) -> None:
         """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gpxpy-1.4.0/gpxpy/parser.py 
new/gpxpy-1.4.2/gpxpy/parser.py
--- old/gpxpy-1.4.0/gpxpy/parser.py     2020-01-16 20:41:16.000000000 +0100
+++ new/gpxpy-1.4.2/gpxpy/parser.py     2020-06-22 08:55:50.000000000 +0200
@@ -80,6 +80,8 @@
 
         """
         text = xml_or_file.read() if hasattr(xml_or_file, 'read') else 
xml_or_file # type: ignore
+        if isinstance(text, bytes):
+            text = text.decode()
         self.xml = mod_utils.make_str(cast(str, text))
 
     def parse(self, version: Optional[str]=None) -> mod_gpx.GPX:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gpxpy-1.4.0/gpxpy/utils.py 
new/gpxpy-1.4.2/gpxpy/utils.py
--- old/gpxpy-1.4.0/gpxpy/utils.py      2020-01-16 20:41:16.000000000 +0100
+++ new/gpxpy-1.4.2/gpxpy/utils.py      2020-05-16 08:48:16.000000000 +0200
@@ -17,7 +17,7 @@
 import xml.sax.saxutils as mod_saxutils
 import datetime as mod_datetime
 
-from typing import Any, AnyStr, List, Optional
+from typing import Any, AnyStr, List, Optional, cast
 
 def to_xml(tag: str, attributes: Any=None, content: Any=None, default: 
Any=None, escape: bool=False, prettyprint: bool=True, indent: str='') -> str:
     if not prettyprint:
@@ -71,7 +71,7 @@
     """ Some versions of python don't have the timedelta.total_seconds() 
method. """
     if timedelta is None:
         return None
-    return (timedelta.days * 86400) + timedelta.seconds
+    return timedelta.total_seconds()
 
 
 def make_str(s: AnyStr) -> str:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gpxpy-1.4.0/gpxpy.egg-info/PKG-INFO 
new/gpxpy-1.4.2/gpxpy.egg-info/PKG-INFO
--- old/gpxpy-1.4.0/gpxpy.egg-info/PKG-INFO     2020-01-16 20:43:18.000000000 
+0100
+++ new/gpxpy-1.4.2/gpxpy.egg-info/PKG-INFO     2020-06-22 08:57:48.000000000 
+0200
@@ -1,8 +1,8 @@
 Metadata-Version: 2.1
 Name: gpxpy
-Version: 1.4.0
+Version: 1.4.2
 Summary: GPX file parser and GPS track manipulation library
-Home-page: http://www.trackprofiler.com/gpxpy/index.html
+Home-page: https://github.com/tkrajina/gpxpy
 Author: Tomo Krajina
 Author-email: [email protected]
 License: Apache License, Version 2.0
@@ -76,7 +76,7 @@
         
         ## GPX version
         
-        gpx.py can parse and generate GPX 1.0 and 1.1 files. Note that the 
generated file will always be a valid XML document, but it may not be (strictly 
speaking) a valid GPX document. For example, if you set gpx.email to "my.email 
AT mail.com" the generated GPX tag won't confirm to the regex pattern. And the 
file won't be valid. Most applications will ignore such errors, but... Be aware 
of this!
+        gpx.py can parse and generate GPX 1.0 and 1.1 files. The generated 
file will always be a valid XML document, but it may not be (strictly speaking) 
a valid GPX document. For example, if you set gpx.email to "my.email AT 
mail.com" the generated GPX tag won't confirm to the regex pattern. And the 
file won't be valid. Most applications will ignore such errors, but... Be aware 
of this!
         
         Be aware that the gpxpy object model *is not 100% equivalent* with the 
underlying GPX XML file schema. That's because the library object model works 
with both GPX 1.0 and 1.1.
         
@@ -88,9 +88,7 @@
         
         ## XML parsing
         
-        If lxml is available, then it will be used for XML parsing.
-        Otherwise minidom is used.
-        Note that lxml is 2-3 times faster so, if you can choose -- use it :)
+        If lxml is available, then it will be used for XML parsing, otherwise 
minidom is used. Lxml is 2-3 times faster so, if you can choose -- use it.
         
         The GPX version is automatically determined when parsing by reading 
the version attribute in the gpx node. If this attribute is not present then 
the version is assumed to be 1.0. A specific version can be forced by setting 
the `version` parameter in the parse function. Possible values for the 
'version' parameter are `1.0`, `1.1` and `None`.
         
@@ -98,7 +96,7 @@
         
         Branches:
         
-        * `branch` contains the code of the latest release
+        * `master` contains the code of the latest release
         * `dev` branch is where code for the next release should go.
         
         Send your pull request against `dev`, not `master`!
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gpxpy-1.4.0/gpxpy.egg-info/SOURCES.txt 
new/gpxpy-1.4.2/gpxpy.egg-info/SOURCES.txt
--- old/gpxpy-1.4.0/gpxpy.egg-info/SOURCES.txt  2020-01-16 20:43:18.000000000 
+0100
+++ new/gpxpy-1.4.2/gpxpy.egg-info/SOURCES.txt  2020-06-22 08:57:48.000000000 
+0200
@@ -30,10 +30,12 @@
 test_files/gpx1.1_with_all_fields.gpx
 test_files/gpx1.1_with_extensions.gpx
 test_files/gpx1.1_with_extensions_without_namespaces.gpx
+test_files/gpx_with_garmin_extension.gpx
 test_files/korita-zbevnica.gpx
 test_files/route.gpx
 test_files/track-with-empty-segment.gpx
 test_files/track-with-extremes.gpx
+test_files/track-with-less-sec-time.gpx
 test_files/track-with-small-floats.gpx
 test_files/track_with_dilution_errors.gpx
 test_files/track_with_speed.gpx
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gpxpy-1.4.0/setup.py new/gpxpy-1.4.2/setup.py
--- old/gpxpy-1.4.0/setup.py    2020-01-16 20:41:16.000000000 +0100
+++ new/gpxpy-1.4.2/setup.py    2020-06-17 07:01:30.000000000 +0200
@@ -34,7 +34,7 @@
     license='Apache License, Version 2.0',
     author='Tomo Krajina',
     author_email='[email protected]',
-    url='http://www.trackprofiler.com/gpxpy/index.html',
+    url='https://github.com/tkrajina/gpxpy',
     packages=['gpxpy', ],
     python_requires=">=3.6",
     classifiers=[
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gpxpy-1.4.0/test.py new/gpxpy-1.4.2/test.py
--- old/gpxpy-1.4.0/test.py     2020-01-16 20:41:16.000000000 +0100
+++ new/gpxpy-1.4.2/test.py     2020-06-22 08:55:50.000000000 +0200
@@ -135,7 +135,7 @@
 ##    input()
 
 
-def node_strip(text: AnyStr) -> AnyStr:
+def node_strip(text: str) -> str:
     if text is None:
         return ''
     return text.strip()
@@ -185,6 +185,13 @@
         with open('test_files/korita-zbevnica.gpx', encoding='utf-8') as f:
             mod_gpxpy.parse(f)
 
+    def test_parse_bytes(self) -> None:
+        # Must not throw any exception:
+        with open('test_files/korita-zbevnica.gpx', encoding='utf-8') as f:
+            byts = f.read().encode(encoding='utf-8')
+            print(type(byts))
+            mod_gpxpy.parse(byts)
+
     def test_simple_parse_function_invalid_xml(self) -> None:
         try:
             mod_gpxpy.parse('<gpx></gpx')
@@ -345,6 +352,18 @@
         self.assertTrue(gpx.tracks[2].has_times())
         self.assertTrue(gpx.tracks[3].has_times())
 
+    def test_total_time_support_less_one_sec(self) -> None:
+        start_time = mod_datetime.datetime(2018, 7, 4, 0, 0, 0)
+        end_time = mod_datetime.datetime(2018, 7, 4, 0, 0, 0, 994000)
+        d_time = end_time - start_time
+        moving_time = total_seconds(d_time)
+        self.assertEqual(0.994, moving_time)
+
+
+    def test_total_time_none(self) -> None:
+        moving_time = total_seconds(None) #type: ignore
+        self.assertIsNone(moving_time)
+
     def test_unicode_name(self) -> None:
         gpx = self.parse('unicode.gpx', encoding='utf-8')
         name = gpx.waypoints[0].name
@@ -381,26 +400,38 @@
 ##        self.assertTrue(make_str(security) == 'Open')
 
     def test_nearest_location_1(self) -> None:
+        def test_nearest_gpx(gpx: mod_gpx.GPX) -> None:
+            def test_nearest(gpx: mod_gpx.GPX,loc: mod_geo.Location) -> None:
+                def test_nearest_part(gpx_part: Union[mod_gpx.GPX, 
mod_gpx.GPXTrack, mod_gpx.GPXTrackSegment], loc: mod_geo.Location) -> 
mod_gpx.NearestLocationData:
+                    nearest_loc_info = gpx_part.get_nearest_location(loc)
+                    print(gpx_part,nearest_loc_info)
+                    self.assertTrue(nearest_loc_info is not None)
+                    location = nearest_loc_info.location # type: ignore
+                    nearest_nearest_loc_info = 
gpx_part.get_nearest_location(location)
+                    self.assertTrue(nearest_nearest_loc_info == 
nearest_loc_info)
+                    return nearest_loc_info # type: ignore
+                
+                nearest_loc_info =test_nearest_part( gpx, loc)
+                location=nearest_loc_info.location
+                point = 
gpx.tracks[nearest_loc_info.track_no].segments[nearest_loc_info.segment_no].points[nearest_loc_info.point_no]
+                self.assertTrue(point.distance_2d(location) < 0.001) # type: 
ignore
+                self.assertTrue(point.distance_2d(nearest_loc_info.location) < 
0.001) # type: ignore
+                test_nearest_part( gpx.tracks[nearest_loc_info.track_no], loc)
+                test_nearest_part( 
gpx.tracks[nearest_loc_info.track_no].segments[nearest_loc_info.segment_no], 
loc)
+            
+            test_nearest(gpx,mod_geo.Location(45.451058791, 14.027903696))
+            test_nearest(gpx,mod_geo.Location(1, 1))
+            test_nearest(gpx,mod_geo.Location(50,50))
+                
         gpx = self.parse('korita-zbevnica.gpx')
-
-        location = mod_geo.Location(45.451058791, 14.027903696)
-        nearest_loc_info = gpx.get_nearest_location(location)
-        print(nearest_loc_info)
-        self.assertTrue(nearest_loc_info is not None)
-        point = 
gpx.tracks[nearest_loc_info.track_no].segments[nearest_loc_info.segment_no].points[nearest_loc_info.point_no]
 # type: ignore
-        self.assertTrue(point.distance_2d(location) < 0.001) # type: ignore
-        self.assertTrue(point.distance_2d(nearest_loc_info.location) < 0.001) 
# type: ignore
-
-        location = mod_geo.Location(1, 1)
-        nearest_location, track_no, track_segment_no, track_point_no = 
gpx.get_nearest_location(location) # type: ignore
-        point = 
gpx.tracks[track_no].segments[track_segment_no].points[track_point_no]
-        self.assertTrue(point.distance_2d(nearest_location) < 0.001) # type: 
ignore
-
-        location = mod_geo.Location(50, 50)
-        nearest_location, track_no, track_segment_no, track_point_no = 
gpx.get_nearest_location(location) # type: ignore
-        point = 
gpx.tracks[track_no].segments[track_segment_no].points[track_point_no]
-        self.assertTrue(point.distance_2d(nearest_location) < 0.001) # type: 
ignore
-
+        test_nearest_gpx(gpx)
+        gpx.tracks[0].segments[0].points = None # type: ignore
+        test_nearest_gpx(gpx)
+        gpx.tracks[0].segments = None # type: ignore
+        test_nearest_gpx(gpx)
+        gpx.tracks = None # type: ignore
+        self.assertTrue( gpx.get_nearest_location(mod_geo.Location(1, 1)) is 
None)
+        
     def test_long_timestamps(self) -> None:
         # Check if timestamps in format: 1901-12-13T20:45:52.2073437Z work
         gpx = self.parse('Mojstrovka.gpx')
@@ -879,6 +910,15 @@
             
self.assertTrue(test_gpx.tracks[0].segments[0].points[0].vertical_dilution == 
301.1)
             
self.assertTrue(test_gpx.tracks[0].segments[0].points[0].position_dilution == 
302.1)
 
+    def test_subsecond_speed(self) -> None:
+        t1 = mod_datetime.datetime(2020, 1, 1, 0, 0, 0, 0)
+        pt1 = mod_gpx.GPXTrackPoint(0, 0, time=t1)
+        pt2 = mod_gpx.GPXTrackPoint(1, 1, time=t1 + 
mod_datetime.timedelta(milliseconds=500))
+        print(pt1.time)
+        print(pt2.time)
+        speed = pt1.speed_between(pt2)
+        self.assertTrue(speed > 0) # type: ignore
+
     def test_course_between(self) -> None:
         gpx = mod_gpx.GPX()
         track = mod_gpx.GPXTrack()
@@ -1131,7 +1171,7 @@
         for tmp_point in track.walk():
             self.assertTrue(tmp_point)
 
-        for point, segment_no, point_no in track.walk(): # type: ignore
+        for point, segment_no, point_no in track.walk():
             self.assertTrue(point)
 
         self.assertEqual(segment_no, len(track.segments) - 1)
@@ -3129,7 +3169,15 @@
         gpx = mod_gpxpy.parse(f)
         self.assertEqual(2, len(gpx.waypoints[0].extensions))
         self.assertEqual("bbb", gpx.waypoints[0].extensions[0].text)
-        self.assertEqual("eee", 
gpx.waypoints[0].extensions[1].getchildren()[0].text.strip())
+        self.assertEqual("eee", 
list(gpx.waypoints[0].extensions[1])[0].text.strip())
+
+    def test_garmin_extension(self) -> None:
+        f = open('test_files/gpx_with_garmin_extension.gpx', 'r')
+        gpx = mod_gpxpy.parse(f)
+        xml = gpx.to_xml()
+        self.assertTrue("<gpxtpx:TrackPointExtension>" in xml)
+        self.assertTrue("<gpxtpx:hr>171</gpxtpx:hr>" in xml)
+        print(gpx.to_xml())
 
     def test_with_ns_namespace(self) -> None:
         gpx_with_ns = mod_gpxpy.parse("""<?xml version="1.0" encoding="UTF-8"?>
@@ -3163,8 +3211,8 @@
         for gpx in [gpx_with_ns, reparsed]:
             extensions = gpx.tracks[0].segments[0].points[0].extensions
             self.assertEqual(1, len(extensions))
-            self.assertEqual("125", 
extensions[0].getchildren()[0].text.strip())
-            self.assertEqual("75", extensions[0].getchildren()[1].text.strip())
+            self.assertEqual("125", list(extensions[0])[0].text.strip())
+            self.assertEqual("75", list(extensions[0])[1].text.strip())
 
     def test_join_gpx_xml_files(self) -> None:
         import gpxpy.gpxxml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gpxpy-1.4.0/test_files/gpx_with_garmin_extension.gpx 
new/gpxpy-1.4.2/test_files/gpx_with_garmin_extension.gpx
--- old/gpxpy-1.4.0/test_files/gpx_with_garmin_extension.gpx    1970-01-01 
01:00:00.000000000 +0100
+++ new/gpxpy-1.4.2/test_files/gpx_with_garmin_extension.gpx    2020-06-22 
08:55:50.000000000 +0200
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gpx
+  version="1.1"
+  creator="Runkeeper - http://www.runkeeper.com";
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+  xmlns="http://www.topografix.com/GPX/1/1";
+  xsi:schemaLocation="http://www.topografix.com/GPX/1/1 
http://www.topografix.com/GPX/1/1/gpx.xsd";
+  xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1";>
+<wpt lat="37.778259000" lon="-122.391386000">
+<ele>3.4</ele><time>2016-06-17T23:41:03Z</time><extensions><gpxtpx:TrackPointExtension><gpxtpx:hr>171</gpxtpx:hr></gpxtpx:TrackPointExtension></extensions>
+</wpt>
+</gpx>
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gpxpy-1.4.0/test_files/track-with-less-sec-time.gpx 
new/gpxpy-1.4.2/test_files/track-with-less-sec-time.gpx
--- old/gpxpy-1.4.0/test_files/track-with-less-sec-time.gpx     1970-01-01 
01:00:00.000000000 +0100
+++ new/gpxpy-1.4.2/test_files/track-with-less-sec-time.gpx     2020-05-16 
08:46:48.000000000 +0200
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<gpx xmlns="http://www.topografix.com/GPX/1/1"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"; 
xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"; 
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 
http://www.topografix.com/GPX/1/1/gpx.xsd 
http://www.garmin.com/xmlschemas/GpxExtensions/v3 
http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd 
http://www.garmin.com/xmlschemas/TrackPointExtension/v1 
http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd"; version="1.1" 
creator="NikePlus GPX Bridge">
+  <trk>
+    <type>run</type>
+    <trkseg>
+      <trkpt lon="9.992872" lat="57.011456">
+        <ele>23.5536</ele>
+        <time>2015-12-11T15:43:13.000+01:00</time>
+      </trkpt>
+      <trkpt lon="9.992874" lat="57.01147">
+        <ele>23.551199</ele>
+        <time>2015-12-11T15:43:13.994+01:00</time>
+      </trkpt>
+    </trkseg>
+  </trk>
+</gpx>

Reply via email to