tkrajina/gpxpy

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

Closed this issue · 5 comments

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.'))

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.

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.

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.

@hyperknot fixed now in 1672f15 (still in dev but I'll merge/release it after more testing)