From d41819dd1312c9b453f6d7490df60b0f9648a08e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Piotr=20Ma=C5=9Blanka?= <piotr.maslanka@henrietta.com.pl>
Date: Wed, 30 Jun 2021 15:20:01 +0200
Subject: [PATCH] 2.5

---
 docs/index.rst         |  3 ---
 docs/usage.rst         |  3 +++
 minijson.pyx           | 37 +++++++++++++++++++++++++++----------
 setup.cfg              |  2 +-
 tests/test.sh          |  2 +-
 tests/test_minijson.py | 16 +++++++++++++---
 6 files changed, 45 insertions(+), 18 deletions(-)

diff --git a/docs/index.rst b/docs/index.rst
index c1a16a3..0c4df87 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -20,9 +20,6 @@ whose all keys are strings.
 You should avoid objects with keys different than strings, since they will always use a
 4-byte length field. This is to be improved in a future release.
 
-.. warning:: Take care for your data to be without cycles. Feeding the encoder cycles
-   will probably dump your interpreter's core.
-
 Indices and tables
 ==================
 
diff --git a/docs/usage.rst b/docs/usage.rst
index 3b52e3f..2685b86 100644
--- a/docs/usage.rst
+++ b/docs/usage.rst
@@ -1,6 +1,9 @@
 Usage
 =====
 
+.. warning:: Take care for your data to be without cycles. Feeding the encoder cycles
+   will probably dump your interpreter's core.
+
 MiniJSON implements the same interface as json or yaml, namely:
 
 .. warning:: Cycles are not automatically detected. They might make the application hang
diff --git a/minijson.pyx b/minijson.pyx
index b996151..156d2c6 100644
--- a/minijson.pyx
+++ b/minijson.pyx
@@ -317,27 +317,27 @@ cdef class MiniJSONEncoder:
     """
     cdef:
         object _default
-        bint use_double
+        public bint use_double
 
     def __init__(self, default: tp.Optional[None] = None,
-                 use_double: bool = False):
+                 bint use_double = False):
         self._default = default
         self.use_double = use_double
 
-    cpdef bint should_double_be_used(self, double x):
+    def should_double_be_used(self, y) -> bool:
         """
         A function that you are meant to overload that will decide on a per-case basis
         which representation should be used for given number.
-        
-        :param x: number to check 
+
+        :param y: number to check
         :return: True if double should be used, else False
         """
         return self.use_double
 
-    cpdef default(self, v):
+    def default(self, v):
         """
         Convert an object to a JSON-able representation.
-        
+
         Overload this to provide your default function in other way that giving
         the callable as a parameter.
 
@@ -512,12 +512,19 @@ cdef class MiniJSONEncoder:
                 return offset
         else:
             v = self.default(data)
+            if not is_jsonable(v):
+                raise EncodingError('default returned a non-JSONable value!')
             return self.dump(v, cio)
 
 
-cpdef int dump(object data, cio: io.BytesIO, default: tp.Callable) except -1:
+cpdef int dump(object data, cio: io.BytesIO, default: tp.Optional[tp.Callable] = None) except -1:
     """
-    Write an object to a stream
+    Write an object to a stream.
+    
+    Note that this will load the initial value of current default float encoding mode and remember
+    it throughout the streaming process, so you can't change it mid-value.
+    
+    To do so, please use :class:`~minijson.MiniJSONEncoder`
 
     :param data: object to write
     :param cio: stream to write to
@@ -533,8 +540,13 @@ cpdef int dump(object data, cio: io.BytesIO, default: tp.Callable) except -1:
 
 cpdef bytes dumps(object data, default: tp.Optional[tp.Callable] = None):
     """
-    Serialize given data to a MiniJSON representation
+    Serialize given data to a MiniJSON representation.
 
+    Note that this will load the initial value of current default float encoding mode and remember
+    it throughout the streaming process, so you can't change it mid-value.
+    
+    To do so, please use :class:`~minijson.MiniJSONEncoder`
+        
     :param data: data to serialize
     :param default: a function that should be used to convert non-JSONable objects to JSONable ones.
         Default, None, will raise an EncodingError upon encountering such a value
@@ -552,6 +564,11 @@ cpdef bytes dumps_object(object data, default: tp.Optional[tp.Callable] = None):
     
     Note that subobject's :code:`__dict__` will not be copied. Use default for that.
     
+    Note that this will load the initial value of current default float encoding mode and remember
+    it throughout the streaming process, so you can't change it mid-value.
+    
+    To do so, please use :class:`~minijson.MiniJSONEncoder`
+    
     :param data: object to dump 
     :param default: a function that should be used to convert non-JSONable objects to JSONable ones.
         Default, None, will raise an EncodingError upon encountering such a value
diff --git a/setup.cfg b/setup.cfg
index c840eff..a0f4d85 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,6 +1,6 @@
 # coding: utf-8
 [metadata]
-version = 2.5a1
+version = 2.5
 name = minijson
 long_description = file: README.md
 long_description_content_type = text/markdown; charset=UTF-8
diff --git a/tests/test.sh b/tests/test.sh
index 8b496fd..f62c46f 100644
--- a/tests/test.sh
+++ b/tests/test.sh
@@ -1,4 +1,4 @@
 #!/bin/bash
 
-pytest --cov=./ --cov-report=xml
+pytest --cov=./ --cov-report=xml -vv
 coverage report
diff --git a/tests/test_minijson.py b/tests/test_minijson.py
index 4d3f2a8..a4e10d5 100644
--- a/tests/test_minijson.py
+++ b/tests/test_minijson.py
@@ -58,7 +58,17 @@ class TestMiniJSON(unittest.TestCase):
 
         a = Subclass({1: 2, 3: 4})
         b = dumps(a)
-        self.assertEquals(loads(b), {1: 2, 3: 4})
+        self.assertEqual(loads(b), {1: 2, 3: 4})
+
+    def test_should_double_be_used(self):
+        class Encoder(MiniJSONEncoder):
+            def should_double_be_used(self, y):
+                return y == 0
+
+        e = Encoder()
+
+        self.assertEqual(len(e.encode(0.0)), 9)
+        self.assertEqual(len(e.encode(1.0)), 5)
 
     def test_subclasses_of_lists(self):
         """Assert that you can correctly serialize subclasses of list"""
@@ -67,7 +77,7 @@ class TestMiniJSON(unittest.TestCase):
 
         a = Subclass([1, 2, 3])
         b = dumps(a)
-        self.assertEquals(loads(b), [1, 2, 3])
+        self.assertEqual(loads(b), [1, 2, 3])
 
     def test_subclasses_of_tuples(self):
         """Assert that you can correctly serialize subclasses of tuple"""
@@ -76,7 +86,7 @@ class TestMiniJSON(unittest.TestCase):
 
         a = Subclass((1, 2, 3))
         b = dumps(a)
-        self.assertEquals(loads(b), [1, 2, 3])
+        self.assertEqual(loads(b), [1, 2, 3])
 
     def test_malformed(self):
         """Test unserializing malformed strings yields DecodingError"""
-- 
GitLab