Repository: debrief/pepys-import

Issue:
Bug in writing to PostGres
It _looks like_ we're trying to write a Typed Quantity to PostGres:
```
'PLATFORM-1' added to Platform!
'PLATFORM-1' added to Platform!
Traceback (most recent call last):
  File "/home/ian/git/pepys-import/venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1249, in _execute_context
    cursor, statement, parameters, context
  File "/home/ian/git/pepys-import/venv/lib/python3.6/site-packages/sqlalchemy/engine/default.py", line 580, in do_execute
    cursor.execute(statement, parameters)
psycopg2.ProgrammingError: can't adapt type 'Quantity'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/lib/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/home/ian/git/pepys-import/pepys_import/import.py", line 44, in <module>
    main(path=args.path, db=args.db)
  File "/home/ian/git/pepys-import/pepys_import/import.py", line 31, in main
    processor.process(path, data_store, True)
  File "/home/ian/git/pepys-import/pepys_import/file/file_processor.py", line 85, in process
    file, current_path, data_store, processed_ctr
  File "/home/ian/git/pepys-import/pepys_import/file/file_processor.py", line 156, in process_file
    datafile.commit(data_store.session)
  File "/home/ian/git/pepys-import/pepys_import/core/store/postgres_db.py", line 269, in commit
    file.submit(session)
  File "/home/ian/git/pepys-import/pepys_import/core/store/postgres_db.py", line 556, in submit
    session.flush()
  File "/home/ian/git/pepys-import/venv/lib/python3.6/site-packages/sqlalchemy/orm/session.py", line 2470, in flush
    self._flush(objects)
  File "/home/ian/git/pepys-import/venv/lib/python3.6/site-packages/sqlalchemy/orm/session.py", line 2608, in _flush
    transaction.rollback(_capture_exception=True)
  File "/home/ian/git/pepys-import/venv/lib/python3.6/site-packages/sqlalchemy/util/langhelpers.py", line 68, in __exit__
    compat.reraise(exc_type, exc_value, exc_tb)
  File "/home/ian/git/pepys-import/venv/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 153, in reraise
    raise value
  File "/home/ian/git/pepys-import/venv/lib/python3.6/site-packages/sqlalchemy/orm/session.py", line 2568, in _flush
    flush_context.execute()
  File "/home/ian/git/pepys-import/venv/lib/python3.6/site-packages/sqlalchemy/orm/unitofwork.py", line 422, in execute
    rec.execute(self)
  File "/home/ian/git/pepys-import/venv/lib/python3.6/site-packages/sqlalchemy/orm/unitofwork.py", line 589, in execute
    uow,
  File "/home/ian/git/pepys-import/venv/lib/python3.6/site-packages/sqlalchemy/orm/persistence.py", line 245, in save_obj
    insert,
  File "/home/ian/git/pepys-import/venv/lib/python3.6/site-packages/sqlalchemy/orm/persistence.py", line 1137, in _emit_insert_statements
    statement, params
  File "/home/ian/git/pepys-import/venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 988, in execute
    return meth(self, multiparams, params)
  File "/home/ian/git/pepys-import/venv/lib/python3.6/site-packages/sqlalchemy/sql/elements.py", line 287, in _execute_on_connection
    return connection._execute_clauseelement(self, multiparams, params)
  File "/home/ian/git/pepys-import/venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1107, in _execute_clauseelement
    distilled_params,
  File "/home/ian/git/pepys-import/venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1253, in _execute_context
    e, statement, parameters, cursor, context
  File "/home/ian/git/pepys-import/venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1473, in _handle_dbapi_exception
    util.raise_from_cause(sqlalchemy_exception, exc_info)
  File "/home/ian/git/pepys-import/venv/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 398, in raise_from_cause
    reraise(type(exception), exception, tb=exc_tb, cause=cause)
  File "/home/ian/git/pepys-import/venv/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 152, in reraise
    raise value.with_traceback(tb)
  File "/home/ian/git/pepys-import/venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1249, in _execute_context
    cursor, statement, parameters, context
  File "/home/ian/git/pepys-import/venv/lib/python3.6/site-packages/sqlalchemy/engine/default.py", line 580, in do_execute
    cursor.execute(statement, parameters)
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) can't adapt type 'Quantity'
[SQL: INSERT INTO pepys."States" (state_id, time, sensor_id, location, elevation, heading, course, speed, source_id, privacy_id, created_date) VALUES (%(state_id)s, %(time)s, %(sensor_id)s, ST_GeomFromEWKT(%(location)s), %(elevation)s, %(heading)s, %(course)s, %(speed)s, %(source_id)s, %(privacy_id)s, %(created_date)s)]
[parameters: {'state_id': UUID('5a3d74a5-6114-4474-9031-cb93ae133a58'), 'time': datetime.datetime(2016, 11, 5, 15, 0, 2), 'sensor_id': UUID('db45dabf-f8ea-4d84-b426-306f315586f5'), 'location': '(10.483609138888887 10.483610388888888)', 'elevation': None, 'heading': <Quantity(200.0, 'degree')>, 'course': None, 'speed': 2.057777777777778, 'source_id': UUID('f8ace693-1e48-4056-a73d-a5cdfc60579b'), 'privacy_id': None, 'created_date': datetime.datetime(2020, 3, 4, 14, 22, 57, 201049)}]
(Background on this error at: http://sqlalche.me/e/f405)

```

Discussion:

Patch:
diff --git a/pepys_import/file/nmea_importer.py b/pepys_import/file/nmea_importer.py
index 4291bdee..37cf181a 100644
--- a/pepys_import/file/nmea_importer.py
+++ b/pepys_import/file/nmea_importer.py
@@ -126,7 +126,7 @@ class NMEAImporter(Importer):
 
                     heading = convert_absolute_angle(self.heading, line_number)
                     if heading:
-                        state.heading = heading
+                        state.heading = heading.magnitude
 
                     speed = convert_speed(self.speed, line_number)
                     if speed:
@@ -154,14 +154,12 @@ class NMEAImporter(Importer):
     @staticmethod
     def parse_location(lat, lat_hem, lon, long_hem):
         lat_degrees = float(lat[0:2])
-        lat_minutes = float(lat[2:4])
-        lat_seconds = float(lat[4:])
-        lat_degrees = lat_degrees + lat_minutes / 60 + lat_seconds / 60 / 60
+        lat_minutes = float(lat[2:])
+        lat_degrees = lat_degrees + lat_minutes / 60
 
         lon_degrees = float(lon[0:3])
-        lon_minutes = float(lon[3:5])
-        lon_seconds = float(lon[5:])
-        lon_degrees = lon_degrees + lon_minutes / 60 + lon_seconds / 60 / 60
+        lon_minutes = float(lon[3:])
+        lon_degrees = lon_degrees + lon_minutes / 60
 
         if lat_hem == "S":
             lat_degrees = -1 * lat_degrees
@@ -169,7 +167,7 @@ class NMEAImporter(Importer):
         if long_hem == "W":
             lon_degrees = -1 * lon_degrees
 
-        return f"({lat_degrees} {lon_degrees})"
+        return f"POINT({lon_degrees} {lat_degrees})"
 
     @staticmethod
     def parse_timestamp(date, time):


Test patch:
diff --git a/tests/test_importers.py b/tests/test_importers.py
index 8a38b8a5..ccb21b83 100644
--- a/tests/test_importers.py
+++ b/tests/test_importers.py
@@ -259,8 +259,10 @@ class NMEAImporterTestCase(unittest.TestCase):
 
     def test_parse_location(self):
         """Test whether the method correctly converts the given string location"""
-        location = self.nmea_importer.parse_location("01603600", "S", "001603600", "W")
-        self.assertEqual("(-3.0 -3.0)", location)
+        location = self.nmea_importer.parse_location(
+            "3030.3000", "S", "00154.5400", "W"
+        )
+        self.assertEqual("POINT(-1.909 -30.505)", location)
 
     def test_tokens(self):
         """Test whether the method correctly tokenize the given string"""