Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

support #inst notation

  • Loading branch information...
commit 1a5a00255b31de716db241d931e52ecd18296939 1 parent cad2021
@sunng87 authored
Showing with 50 additions and 7 deletions.
  1. +42 −4 clj.py
  2. +2 −1  setup.py
  3. +6 −2 tests/clj-test.py
View
46 clj.py
@@ -36,6 +36,8 @@
# clojure boolean true => python boolean true
# clojure nil => python None
#
+# clojure datetime => python datetime
+#
__all__ = ["dump", "dumps", "load", "loads"]
@@ -43,6 +45,10 @@
import os
from cStringIO import StringIO
+from datetime import datetime
+import pyrfc3339
+import pytz
+
def number(v):
if '.' in v:
return float(v)
@@ -67,6 +73,14 @@ def decode(self):
v = self.__read_token()
if len(self.value_stack) == 0:
return v
+
+ def __seek_back(self, size):
+ self.fd.seek(self.fd.tell()-size, 0)
+
+ def __read_and_back(self, size):
+ s = self.fd.read(size)
+ self.__seek_back(size)
+ return s
def __get_type_from_char(self, c):
"""return a tuple of type information
@@ -86,15 +100,18 @@ def __get_type_from_char(self, c):
elif c == '"':
return ("string", False, None)
elif c == '#':
- return ("set", True, "}")
+ if self.__read_and_back(1) == '{':
+ return ("set", True, "}")
+ if self.__read_and_back(4) == 'inst':
+ return ("datetime", False, None)
elif c == '{':
return ("dict", True, "}")
elif c == '(':
return ("list", True, ")")
elif c == '[':
return ('list', True, "]")
- else:
- return (None, False, None)
+
+ return (None, False, None)
def __read_fd(self, size):
if size == 1:
@@ -178,7 +195,7 @@ def __read_token(self):
## [23[12]]
## this is a valid clojure form
if e in _COLL_OPEN_CHARS:
- self.fd.seek(-1, os.SEEK_CUR)
+ self.__seek_back(1)
elif t == "keyword":
buf = [] ##skip the leading ":"
@@ -200,6 +217,18 @@ def __read_token(self):
e = c
#v = u''.join(buf).decode('unicode-escape')
v = ''.join(buf).decode('string-escape')
+
+ elif t == "datetime":
+ ## skip "inst"
+ self.__read_fd(4)
+
+ ## read next value as string
+ s = self.__read_token()
+ if not isinstance(s, str):
+ raise ValueError('Str expected, but got %s' % str(s))
+ e = '"'
+ v = pyrfc3339.parse(s)
+
else:
if c not in _COLL_CLOSE_CHARS:
raise ValueError('Unexpected char: "%s" at line %d, col %d' % (c, self.cur_line, self.cur_pos))
@@ -253,6 +282,8 @@ def get_type(self,t):
return ("list", True)
elif isinstance(t, set):
return ("set", True)
+ elif isinstance(t, datetime):
+ return ("datetime", False)
else:
return ("unknown", False)
@@ -306,6 +337,13 @@ def __do_encode(self, d):
fd.write('false')
elif t == 'None':
fd.write('nil')
+ elif t == 'datetime':
+ s = d.strftime("%Y-%m-%dT%H:%M:%S%z")
+ if not d.tzinfo:
+ ## replace naive datetime
+ d = d.replace(tzinfo=pytz.utc)
+ s = pyrfc3339.generate(d)
+ fd.write("#inst \"%s\"" % s)
else:
fd.write('"'+str(d)+'"')
View
3  setup.py
@@ -6,12 +6,13 @@
long_desc=open('README.rst','r').read()
setup(name="pyclj",
- version="0.1.9.1",
+ version="0.2.0",
author="Sun Ning",
author_email="sunng@about.me",
description="clojure literal reader and writer for python",
long_description=long_desc,
url="http://github.com/sunng87/pyclj",
+ install_requires=["pyRFC3339"],
license='mit',
py_modules=['clj'],
classifiers=['Development Status :: 4 - Beta',
View
8 tests/clj-test.py
@@ -1,6 +1,8 @@
# -*- coding: utf-8 -*-
import unittest
import clj
+import pytz
+from datetime import datetime
class CljLoadTest(unittest.TestCase):
def setUp(self):
@@ -24,7 +26,8 @@ def setUp(self):
"{:a [1 2 3] :b #{23.1 43.1 33.1}}": {"a":[1,2,3], "b":set([23.1,43.1,33.1])},
"{:a 1 :b [32 32 43] :c 4}": {"a":1,"b":[32,32,43],"c":4},
"\\": "",
- "[23[34][32][4]]": [23,[34],[32],[4]]}
+ "[23[34][32][4]]": [23,[34],[32],[4]],
+ "#inst \"2012-10-19T22:19:03.000-00:00\"": datetime(2012, 10, 19, 22, 19, 3, tzinfo=pytz.utc)}
def test_all_data(self):
for k,v in self.data.items():
@@ -53,7 +56,8 @@ def setUp(self):
"{}": {},
'{"a" 1 "b" 2}':{"a":1, "b":2},
'#{1}': set([1]),
- '["h" nil [1 2 3] {"w" true}]':["h",None,[1,2,3],{"w":True}]
+ '["h" nil [1 2 3] {"w" true}]':["h",None,[1,2,3],{"w":True}],
+ '#inst "2012-10-19T14:16:54Z"':datetime(2012,10,19,14,16,54,907)
}
def test_all_data(self):
Please sign in to comment.
Something went wrong with that request. Please try again.