Skip to content
This repository has been archived by the owner on Mar 12, 2020. It is now read-only.

Commit

Permalink
Use decimal arithmetic when parsing coordinates
Browse files Browse the repository at this point in the history
  • Loading branch information
Mike Graves committed Aug 13, 2015
1 parent 09b2d26 commit 6266289
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 24 deletions.
22 changes: 11 additions & 11 deletions kepler/parsers.py
@@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division
from __future__ import absolute_import
from lxml.etree import iterparse
import pymarc
import re
import decimal
from decimal import Decimal, getcontext


class XMLParser(object):
Expand Down Expand Up @@ -106,17 +106,17 @@ def record(self):
return record

@classmethod
def convert_coord(cls, coordinate):
def convert_coord(cls, coordinate, precision=10):
o_precision = getcontext().prec
getcontext().prec = precision
matches = cls.COORD_REGEX.search(coordinate)
if not matches:
return None
parts = matches.groupdict()
dec = float(parts.get('degrees')) + \
float(parts.get('minutes') or 0) / 60 + \
float(parts.get('seconds') or 0) / 3600
dec = Decimal(parts.get('degrees')) + \
Decimal(parts.get('minutes') or 0) / 60 + \
Decimal(parts.get('seconds') or 0) / 3600
if parts.get('hemisphere') and parts.get('hemisphere').lower() in 'ws-':
dec = -dec
try:
return decimal.Decimal(dec)
except TypeError:
return decimal.Decimal("%.7f" % dec)
dec = dec * -1
getcontext().prec = o_precision
return dec
3 changes: 3 additions & 0 deletions tests/fixtures/marc.xml
Expand Up @@ -78,6 +78,9 @@
<datafield tag="500" ind1=" " ind2=" ">
<subfield code="a">Includes text and inset of &quot;Heat flow in the Rio Grande rift and adjacient areas.&quot;</subfield>
</datafield>
<datafield tag="520" ind1=" " ind2=" ">
<subfield code="a">Here's a summary</subfield>
</datafield>
<datafield tag="504" ind1=" " ind2=" ">
<subfield code="a">Bibliography.</subfield>
</datafield>
Expand Down
36 changes: 23 additions & 13 deletions tests/test_parsers.py
@@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division
from __future__ import absolute_import
from io import BytesIO
from xml.etree.ElementTree import Element
import decimal
from decimal import Decimal, getcontext

import pytest
from mock import Mock
Expand All @@ -25,12 +25,12 @@ def start_handler(elem):
return parser


def almost_equal(x, y):
try:
y = decimal.Decimal(y)
except TypeError:
y = decimal.Decimal("%.7f" % y)
return abs(x - y) <= decimal.Decimal("0.0000001")
@pytest.yield_fixture()
def prec_10():
o_prec = getcontext().prec
getcontext().prec = 10
yield
getcontext().prec = o_prec


class TestXMLParser(object):
Expand Down Expand Up @@ -134,12 +134,22 @@ def testCoordRegexExtractsPartsOfCoordinate(self):
assert parts.groupdict().get('minutes') == '45'
assert parts.groupdict().get('seconds') == '67.89'

def testConvertCoordConvertsStringToDecimal(self):
degrees = 12 + 34/60 + 56/3600
assert almost_equal(MarcParser.convert_coord("S0123456"), -degrees)
def testConvertCoordConvertsStringToDecimal(self, prec_10):
degrees = (12 + Decimal(34)/60 + Decimal(56)/3600) * -1
assert MarcParser.convert_coord("S0123456") == degrees

degrees = 123 + 45.6789/60
assert almost_equal(MarcParser.convert_coord("12345.6789"), degrees)
degrees = 123 + Decimal('45.6789')/60
assert MarcParser.convert_coord("12345.6789") == degrees

def testConvertCoordUsesPrecision(self, prec_10):
assert MarcParser.convert_coord("12345.6789", precision=5) == Decimal('123.76')

def testConvertCoordResetsPrecision(self, prec_10):
MarcParser.convert_coord('12345.6789', precision=2)
assert Decimal(2)/3 == Decimal('0.6666666667')

def testConvertCoordReturnsNoneWhenNoMatch(self):
assert MarcParser.convert_coord("asdf") is None

def testParsesMarcXml(self, marc):
parser = MarcParser(marc)
Expand Down

0 comments on commit 6266289

Please sign in to comment.