tkrajina / gpxpy

gpx-py is a python GPX parser. GPX (GPS eXchange Format) is an XML based file format for GPS tracks.
Apache License 2.0
1.01k stars 223 forks source link

Can no longer feed a file to gpxpy.parse() in Python 3 / Django 2.2 #175

Closed ramonakira closed 4 years ago

ramonakira commented 5 years ago

Hi,

In a site we built using Django 1.11 and Python 2.7 the following would work:

    try:
        gpx_data = gpxpy.parse(gpx_file)
    except GPXException:
        raise ValidationError(_('Invalid GPX file.'))

(where gpx_file is from a django FileField)

After upgrading to Python 3 and Django 2 the above does not work anymore, resulting in a gpxpy.gpx.GPXXMLSyntaxException: Error parsing XML: Start tag expected, '<' not found, line 1, column 1

A workaround is:

    try:
        gpx_string = str(gpx_file.read().decode())
        gpx_data = gpxpy.parse(gpx_string)
    except GPXException:
        raise ValidationError(_('Invalid GPX file.'))
tkrajina commented 5 years ago

That's an error from an underlying XML parses. Can you provide the GPX file, and is it possible that(as the error says) < isn't found on line 1 column 1?

Update: Ignore ^. Somehow I overlooked your workaround. Anyway, yes, that workaround should probably be part of the parse() function. If somebody is willing to implement it I'll merge the PR.

tkrajina commented 4 years ago

I thought a bit more about this, and I think I'll close this issue for now. Because, from inside gpxpy it's totally not clear why (and when) should I call .decode() if it's available after .read(). I understand it fixes a problem for FileFields from Django. But it works for normal file IO objects.

I agree with you that it's an issue, but I'm not 100% sure it should be fixed inside gpxpy. The argument in parse() must be a string or a file (the arg is named xml_or_file). If there is a way to reproduce it with GPX files and normal file-like objects, I'll add this fix.

hyperknot commented 4 years ago

This bug bit me on Pyramid's file upload. The fix is very simple though, run decode() if the type is bytes, but not when it is string.

I don't know how to make it compatible with 2.7, but in py3 this would be a straightforward fix.

tkrajina commented 4 years ago

@hyperknot fixed now in https://github.com/tkrajina/gpxpy/commit/1672f15d3871694eb324b0e3d39d4d69b1791dcf (still in dev but I'll merge/release it after more testing)

hyperknot commented 4 years ago

Looks good!

On 2020. Jun 17., Wed at 7:29, Tomo Krajina notifications@github.com wrote:

@hyperknot https://github.com/hyperknot fixed now in 1672f15d3871694eb324b0e3d39d4d69b1791dcf (still in dev but I'll merge/release it after more testing)

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/tkrajina/gpxpy/issues/175#issuecomment-645159971, or unsubscribe https://github.com/notifications/unsubscribe-auth/AADYVDZGAZVOEHKMELICSJTRXBIBZANCNFSM4HYFV7DQ .