# Copyright (c) 2013 Michal Vyskocil
#
# pyckle module for python, released under MIT license
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.


"""module pyckle: native serialization format for python

   pyckle aims to be for Python, what is JSON for Javascript
   native serialization format. 
   
   As Python is much fancier than JS, pyckle does support
   more than JSON. And is batterry-included so all
   interesting classes from Python standard library, like
   collections.dequeue or decimal.Decimal are supported by
   default via ``PyckleVisitor`` instances.

Classes:

   Pyckler

Functions:

   dump(object, file)
   dumps(object) -> string
   load(file) -> object
   loads(string) -> object

Misc variables:

    __version__
    __author__

"""

__author__ = 'Michal Vyskocil'
__version__ = '1.0'

__all__ = [
    'dump', 'dumps', 'load', 'loads',
    'Pyckler'
    ]

from pprint import _safe_repr

from .cache import CacheMismatchError, read_cache, write_cache
from .pyckler import Pyckler
from .utils import _split_lines

#json-like API

def loads(string, cls=Pyckler, globals=dict()):
    """Deserialize and evaluate string with a valid
    pyckle document to Python object
    
    Arguments:
    ``string`` - the (unicode) string or string list with a document
    
    Keywords:
    ``cls`` - the visitor class used for evaluation,
    defaults to ``Pyckler``
    
    ``globals`` - an aditional namespace concatenated with a
    ``cls``'s default list """

    if isinstance(string, str):
        slist = _split_lines(string)
    elif isinstance(string, (list, tuple)):
        slist = string
    else:
        raise TypeError("str, list, tuple expected for `string', `{}' found".format(type(string)))
    
    return cls(slist, "<string>", globals).eval()

def load(fp, cls=Pyckler, globals=dict(), use_cache=False, cfilename=None):
    """Deserialize and evaluate file-like object
    containing a valid pyckle document to Python object
    
    Arguments:
    ``fp`` - file-like object with ``.readlines()`` method
    
    Keywords:
    ``cls`` - the visitor class used for evaluation,
    defaults to ``Pyckler``
    
    ``globals`` - an aditional namespace concatenated with a
    ``cls``'s default list. """

    if use_cache and hasattr(fp, "name"):
        try:
            return read_cache(fp.name, cfilename)
        except CacheMismatchError:
            pass

    return cls(
        fp.readlines(),
        fp.name if hasattr(fp, "name") else "<unknown>",
        globals).eval()

def dumps(obj):
    """Return serialized python object as a string

    Arguments:
    ``obj`` - python object to be serialized
    
    WARNING/TODO: ``dumps`` just checks the object is not
    recursive via ``pprint.isreadable``, but does not
    impose any other limits"""

    repr_string, isreadable, isrecursive = \
        _safe_repr(obj, {}, None, 0)

    if not isreadable:
        raise TypeError("'{}' is not readable".format(obj))

    return repr_string

def dump(obj, fp, use_cache=False, cfilename=None):
    """Serialize python object to a file stream
    
    Arguments:
    ``obj`` - python object to be serialized
    ``fp`` - file-like object with ``.write()`` method
    
    """
    ret = fp.write(dumps(obj))
    fp.flush()
    if use_cache and hasattr(fp, "name"):
        write_cache(obj, fp.name, cfilename)
    return ret

@@ -976,14 +976,8 @@
 ckle
-Visito
 r%60%60 
@@ -1622,37 +1622,24 @@
     
-Arguments:%0A    %60%60string%60%60 - t
+:param string: T
 he (
@@ -1693,38 +1693,21 @@
     
-%0A    Keywords:%0A    %60%60cls%60%60 - t
+:param cls: T
 he v
@@ -1731,36 +1731,32 @@
  for evaluation,
-%0A   
  defaults to %60%60P
@@ -1756,44 +1756,38 @@
  to 
-%60%60
 Pyckler
-%60%60
+_
 %0A    
-%0A    %60%60
+:param 
 globals
-%60%60 - a
+: A
 n ad
@@ -1816,32 +1816,36 @@
 atenated with a%0A
+    
     %60%60cls%60%60's de
@@ -1854,16 +1854,20 @@
 ult list
+%0A   
  %22%22%22%0A%0A  
@@ -2359,31 +2359,22 @@
     
-Arguments:%0A    %60%60fp%60%60 -
+:param fp: The
  fil
@@ -2424,38 +2424,21 @@
     
-%0A    Keywords:%0A    %60%60cls%60%60 - t
+:param cls: T
 he v
@@ -2470,20 +2470,16 @@
 luation,
-%0A   
  default
@@ -2503,28 +2503,25 @@
     
-%0A    %60%60
+:param 
 globals
-%60%60 - a
+: A
 n ad
@@ -2554,24 +2554,28 @@
 ated with a%0A
+    
     %60%60cls%60%60'
@@ -2588,17 +2588,20 @@
 ult list
-.
+%0A   
  %22%22%22%0A%0A  
@@ -2954,32 +2954,23 @@
     
-Arguments:%0A    %60%60obj%60%60 -
+:param obj: The
  pyt
@@ -2992,24 +2992,68 @@
 e serialized
+%0A%0A    :return: serialized object as a string
 %0A    %0A    WA
@@ -3494,32 +3494,23 @@
     
-Arguments:%0A    %60%60obj%60%60 -
+:param obj: The
  pyt
@@ -3545,16 +3545,22 @@
     
-%60%60fp%60%60 -
+:param fp: The
  fil
@@ -3603,24 +3603,117 @@
 od%0A    %0A
+    :return: what underlying %60%60.write()%60%60 method returns,%0A    mostly number of written bytes%0A
     %22%22%22%0A
     ret 
@@ -3704,16 +3704,17 @@
     %22%22%22%0A
+%0A
     ret 

fix doc strings of main functions