Skip to content

Commit

Permalink
Handle fractions
Browse files Browse the repository at this point in the history
  • Loading branch information
bfontaine committed Aug 26, 2018
1 parent 7a3865c commit a6e974d
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 1 deletion.
3 changes: 3 additions & 0 deletions edn_format/edn_dump.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import datetime
import decimal
import fractions
import itertools
import re
import sys
Expand Down Expand Up @@ -105,6 +106,8 @@ def udump(obj,
pairs = ((Keyword(k) if isinstance(k, (bytes, basestring)) else k, v) for k, v in pairs)

return '{{{}}}'.format(seq(itertools.chain.from_iterable(pairs), **kwargs))
elif isinstance(obj, fractions.Fraction):
return '{}/{}'.format(obj.numerator, obj.denominator)
elif isinstance(obj, datetime.datetime):
return '#inst "{}"'.format(pyrfc3339.generate(obj, microseconds=True))
elif isinstance(obj, datetime.date):
Expand Down
9 changes: 9 additions & 0 deletions edn_format/edn_lex.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# see http://stackoverflow.com/a/24519338
import codecs
import decimal
import fractions
import logging
import re
import sys
Expand Down Expand Up @@ -93,6 +94,7 @@ def __str__(self):
'BOOLEAN',
'INTEGER',
'FLOAT',
'RATIO',
'SYMBOL',
'KEYWORD',
'VECTOR_START',
Expand Down Expand Up @@ -215,6 +217,13 @@ def t_FLOAT(t):
return t


def t_RATIO(t):
r"""-?\d+/\d+"""
numerator, denominator = t.value.split("/", 1)
t.value = fractions.Fraction(int(numerator), int(denominator))
return t


def t_INTEGER(t):
r"""[+-]?\d+N?"""
if t.value.endswith('N'):
Expand Down
1 change: 1 addition & 0 deletions edn_format/edn_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def p_term_leaf(p):
| NIL
| KEYWORD
| SYMBOL
| RATIO
| WHITESPACE"""
p[0] = p[1]

Expand Down
22 changes: 21 additions & 1 deletion tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from uuid import uuid4
import random
import datetime
import fractions
import unittest

import pytz
Expand Down Expand Up @@ -74,6 +75,9 @@ def test_lexer(self):
"LexToken(MAP_OR_SET_END,'}',1,21)]",
"{ :a false, :b false }")

self.check_lex("[LexToken(RATIO,Fraction(2, 3),1,0)]",
"2/3")

def check_parse(self, expected_output, actual_input):
self.assertEqual(expected_output, edn_parse.parse(actual_input))

Expand Down Expand Up @@ -129,6 +133,8 @@ def test_parser(self):
self.check_parse(frozenset({ImmutableList([u"ab", u"cd"]),
ImmutableList([u"ef"])}),
'#{["ab", "cd"], ["ef"]}')
self.check_parse(fractions.Fraction(2, 3), "2/3")
self.check_parse((2, Symbol('/'), 3), "(2 / 3)")

def check_roundtrip(self, data_input, **kw):
self.assertEqual(data_input, loads(dumps(data_input, **kw)))
Expand Down Expand Up @@ -234,7 +240,10 @@ def test_round_trip_same(self):
'#date "19/07/1984"',
'#{{"a" 1}}',
'#{{"a" #{{:b 2}}}}',
'"|"'
'"|"',
"/",
"1/3",
'"1/3"',
)

class TagDate(TaggedElement):
Expand Down Expand Up @@ -269,6 +278,17 @@ def test_exceptions(self):
with self.assertRaises(EDNDecodeError):
loads("{")

def test_fractions(self):
for edn_data in (
'0/1',
'1/1',
'1/2',
'1/3',
'-5/3',
'99999999999999999999999999999999999/999999999999999999999999991',
):
self.assertEqual(edn_data, dumps(loads(edn_data)), edn_data)

def test_keyword_keys(self):
unchanged = (
None,
Expand Down

0 comments on commit a6e974d

Please sign in to comment.