<s> from copy import copy <EOL> import io <EOL> import re <EOL> import inspect <EOL> from sondra . document import Document <EOL> from sondra . collection import Collection <EOL> from sondra . ref import Reference <EOL> from sondra import help <EOL> class ParseError ( Exception ) : <EOL> pass <EOL> def _schema ( method ) : <EOL> return { <EOL> "<STR_LIT:id>" : method . __self__ . url + '<STR_LIT:.>' + method . slug + '<STR_LIT>' if hasattr ( method , '<STR_LIT>' ) else method . slug + '<STR_LIT>' , <EOL> "<STR_LIT:title>" : method . slug , <EOL> "<STR_LIT:description>" : method . __doc__ or "<STR_LIT>" , <EOL> "<STR_LIT:type>" : "<STR_LIT:object>" , <EOL> "<STR_LIT>" : [ { "<STR_LIT>" : "<STR_LIT>" + method . slug + "<STR_LIT>" } , { "<STR_LIT>" : "<STR_LIT>" + method . slug + "<STR_LIT>" } ] , <EOL> "<STR_LIT>" : { <EOL> method . slug + "<STR_LIT>" : method . request_schema ( method ) , <EOL> method . slug + "<STR_LIT>" : method . response_schema ( method ) <EOL> } <EOL> } <EOL> def _response_schema ( method ) : <EOL> metadata = inspect . signature ( method ) <EOL> instance = method . __self__ if hasattr ( method , '<STR_LIT>' ) else None <EOL> if metadata . return_annotation is not metadata . empty : <EOL> argtype = _parse_arg ( instance , metadata . return_annotation ) <EOL> if '<STR_LIT:type>' in argtype : <EOL> if argtype [ '<STR_LIT:type>' ] in { '<STR_LIT:list>' , '<STR_LIT:object>' } : <EOL> return argtype <EOL> else : <EOL> return { <EOL> "<STR_LIT:type>" : "<STR_LIT:object>" , <EOL> "<STR_LIT>" : { <EOL> "<STR_LIT:_>" : argtype <EOL> } <EOL> } <EOL> elif "<STR_LIT>" in argtype : <EOL> coll = Reference ( argtype [ '<STR_LIT>' ] ) <EOL> return coll . get_collection ( ) . schema <EOL> else : <EOL> return { <EOL> "<STR_LIT:type>" : "<STR_LIT:object>" , <EOL> "<STR_LIT>" : { <EOL> "<STR_LIT:_>" : argtype <EOL> } <EOL> } <EOL> else : <EOL> return { "<STR_LIT:type>" : "<STR_LIT:object>" , "<STR_LIT:description>" : "<STR_LIT>" } <EOL> def _request_schema ( method ) : <EOL> required_args = [ ] <EOL> metadata = inspect . signature ( method ) <EOL> instance = method . __self__ if hasattr ( method , '<STR_LIT>' ) else None <EOL> properties = { } <EOL> for i , ( name , param ) in enumerate ( metadata . parameters . items ( ) ) : <EOL> if i == <NUM_LIT:0> : <EOL> continue <EOL> schema = _parse_arg ( instance , param . annotation ) <EOL> if param . default is not metadata . empty : <EOL> schema [ '<STR_LIT:default>' ] = param . default <EOL> else : <EOL> required_args . append ( name ) <EOL> properties [ name ] = schema <EOL> ret = { <EOL> "<STR_LIT:type>" : "<STR_LIT:object>" , <EOL> "<STR_LIT>" : properties <EOL> } <EOL> if required_args : <EOL> ret [ '<STR_LIT>' ] = required_args <EOL> return ret <EOL> def _parse_arg ( instance , arg ) : <EOL> if isinstance ( arg , tuple ) : <EOL> arg , description = arg <EOL> else : <EOL> description = None <EOL> if arg is None : <EOL> return { "<STR_LIT:type>" : "<STR_LIT:null>" } <EOL> if isinstance ( arg , str ) : <EOL> arg = { "<STR_LIT:type>" : "<STR_LIT:string>" , "<STR_LIT>" : arg } <EOL> elif arg is str : <EOL> arg = { "<STR_LIT:type>" : "<STR_LIT:string>" } <EOL> elif arg is bytes : <EOL> arg = { "<STR_LIT:type>" : "<STR_LIT:string>" , "<STR_LIT>" : "<STR_LIT>" } <EOL> elif arg is int : <EOL> arg = { "<STR_LIT:type>" : "<STR_LIT>" } <EOL> elif arg is float : <EOL> arg = { "<STR_LIT:type>" : "<STR_LIT>" } <EOL> elif arg is bool : <EOL> arg = { "<STR_LIT:type>" : "<STR_LIT>" } <EOL> elif arg is list : <EOL> arg = { "<STR_LIT:type>" : "<STR_LIT>" } <EOL> elif arg is dict : <EOL> arg = { "<STR_LIT:type>" : "<STR_LIT:object>" } <EOL> elif isinstance ( arg , re . _pattern_type ) : <EOL> arg = { "<STR_LIT:type>" : "<STR_LIT:string>" , "<STR_LIT>" : arg . pattern } <EOL> elif isinstance ( arg , list ) : <EOL> arg = { "<STR_LIT:type>" : "<STR_LIT>" , "<STR_LIT>" : _parse_arg ( instance , arg [ <NUM_LIT:0> ] ) } <EOL> elif isinstance ( arg , dict ) : <EOL> arg = { "<STR_LIT:type>" : "<STR_LIT:object>" , "<STR_LIT>" : { k : _parse_arg ( instance , v ) for k , v in arg . items ( ) } } <EOL> elif issubclass ( arg , Collection ) : <EOL> arg = { "<STR_LIT>" : ( instance . application [ arg . slug ] . url if instance else "<STR_LIT>" ) + "<STR_LIT>" } <EOL> elif issubclass ( arg , Document ) : <EOL> arg = copy ( arg . schema ) <EOL> arg [ '<STR_LIT:id>' ] = arg . __module__ + "<STR_LIT:.>" + arg . __class__ . __name__ <EOL> else : <EOL> raise ParseError ( "<STR_LIT>" ) <EOL> if description : <EOL> arg [ '<STR_LIT:description>' ] = description <EOL> return arg <EOL> def _help ( method , out = None , initial_heading_level = <NUM_LIT:0> ) : <EOL> out = out or io . StringIO ( ) <EOL> builder = help . SchemaHelpBuilder ( method . schema ( method ) , out = out , initial_heading_level = <NUM_LIT:0> ) <EOL> builder . build ( ) <EOL> builder . line ( ) <EOL> return out . getvalue ( ) <EOL> class expose ( object ) : <EOL> exposed = True <EOL> def __init__ ( self , method ) : <EOL> self . method = method <EOL> self . slug = method . __name__ . replace ( '<STR_LIT:_>' , '<STR_LIT:->' ) <EOL> self . _instance = None <EOL> self . __name__ = method . __name__ <EOL> def __get__ ( self , instance , owner ) : <EOL> self . _owner = owner <EOL> self . _instance = instance <EOL> print ( self . _owner ) <EOL> print ( self . _instance ) <EOL> return self <EOL> def __call__ ( self , * args , ** kwargs ) : <EOL> return self . method . __call__ ( self . _instance , * args , ** kwargs ) <EOL> @ property <EOL> def url ( self ) : <EOL> return self . _instance . url + '<STR_LIT:.>' + self . slug if self . _instance else self . slug <EOL> def schema ( self ) : <EOL> return { <EOL> "<STR_LIT:id>" : self . url + '<STR_LIT>' , <EOL> "<STR_LIT:title>" : self . slug , <EOL> "<STR_LIT:description>" : self . method . __doc__ or "<STR_LIT>" , <EOL> "<STR_LIT:type>" : "<STR_LIT:object>" , <EOL> "<STR_LIT>" : [ { "<STR_LIT>" : "<STR_LIT>" + self . slug + "<STR_LIT>" } , { "<STR_LIT>" : "<STR_LIT>" + self . slug + "<STR_LIT>" } ] , <EOL> "<STR_LIT>" : { <EOL> self . slug + "<STR_LIT>" : self . request_schema ( ) , <EOL> self . slug + "<STR_LIT>" : self . response_schema ( ) <EOL> } <EOL> } <EOL> def response_schema ( self ) : <EOL> instance = self . _instance <EOL> metadata = inspect . signature ( self . method ) <EOL> if metadata . return_annotation is not metadata . empty : <EOL> argtype = _parse_arg ( instance , metadata . return_annotation ) <EOL> if '<STR_LIT:type>' in argtype : <EOL> if argtype [ '<STR_LIT:type>' ] in { '<STR_LIT:list>' , '<STR_LIT:object>' } : <EOL> return argtype <EOL> else : <EOL> return { <EOL> "<STR_LIT:type>" : "<STR_LIT:object>" , <EOL> "<STR_LIT>" : { <EOL> "<STR_LIT:_>" : argtype <EOL> } <EOL> } <EOL> elif "<STR_LIT>" in argtype : <EOL> coll = Reference ( argtype [ '<STR_LIT>' ] ) <EOL> return coll . get_collection ( ) . schema <EOL> else : <EOL> return { <EOL> "<STR_LIT:type>" : "<STR_LIT:object>" , <EOL> "<STR_LIT>" : { <EOL> "<STR_LIT:_>" : argtype <EOL> } <EOL> } <EOL> else : <EOL> return { "<STR_LIT:type>" : "<STR_LIT:object>" , "<STR_LIT:description>" : "<STR_LIT>" } <EOL> def request_schema ( self ) : <EOL> required_args = [ ] <EOL> metadata = inspect . signature ( self . method ) <EOL> instance = self . _instance <EOL> properties = { } <EOL> for i , ( name , param ) in enumerate ( metadata . parameters . items ( ) ) : <EOL> if i == <NUM_LIT:0> : <EOL> continue <EOL> schema = _parse_arg ( instance , param . annotation ) <EOL> if param . default is not metadata . empty : <EOL> schema [ '<STR_LIT:default>' ] = param . default <EOL> else : <EOL> required_args . append ( name ) <EOL> properties [ name ] = schema <EOL> ret = { <EOL> "<STR_LIT:type>" : "<STR_LIT:object>" , <EOL> "<STR_LIT>" : properties <EOL> } <EOL> if required_args : <EOL> ret [ '<STR_LIT>' ] = required_args <EOL> return ret <EOL> def parse_arg ( self , instance , arg ) : <EOL> if isinstance ( arg , tuple ) : <EOL> arg , description = arg <EOL> else : <EOL> description = None <EOL> if arg is None : <EOL> return { "<STR_LIT:type>" : "<STR_LIT:null>" } <EOL> if isinstance ( arg , str ) : <EOL> arg = { "<STR_LIT:type>" : "<STR_LIT:string>" , "<STR_LIT>" : arg } <EOL> elif arg is str : <EOL> arg = { "<STR_LIT:type>" : "<STR_LIT:string>" } <EOL> elif arg is bytes : <EOL> arg = { "<STR_LIT:type>" : "<STR_LIT:string>" , "<STR_LIT>" : "<STR_LIT>" } <EOL> elif arg is int : <EOL> arg = { "<STR_LIT:type>" : "<STR_LIT>" } <EOL> elif arg is float : <EOL> arg = { "<STR_LIT:type>" : "<STR_LIT>" } <EOL> elif arg is bool : <EOL> arg = { "<STR_LIT:type>" : "<STR_LIT>" } <EOL> elif arg is list : <EOL> arg = { "<STR_LIT:type>" : "<STR_LIT>" } <EOL> elif arg is dict : <EOL> arg = { "<STR_LIT:type>" : "<STR_LIT:object>" } <EOL> elif isinstance ( arg , re . _pattern_type ) : <EOL> arg = { "<STR_LIT:type>" : "<STR_LIT:string>" , "<STR_LIT>" : arg . pattern } <EOL> elif isinstance ( arg , list ) : <EOL> arg = { "<STR_LIT:type>" : "<STR_LIT>" , "<STR_LIT>" : _parse_arg ( instance , arg [ <NUM_LIT:0> ] ) } <EOL> elif isinstance ( arg , dict ) : <EOL> arg = { "<STR_LIT:type>" : "<STR_LIT:object>" , "<STR_LIT>" : { k : _parse_arg ( instance , v ) for k , v in arg . items ( ) } } <EOL> elif issubclass ( arg , Collection ) : <EOL> arg = { "<STR_LIT>" : ( instance . application [ arg . slug ] . url if instance else "<STR_LIT>" ) + "<STR_LIT>" } <EOL> elif issubclass ( arg , Document ) : <EOL> arg = copy ( arg . schema ) <EOL> arg [ '<STR_LIT:id>' ] = arg . __module__ + "<STR_LIT:.>" + arg . __class__ . __name__ <EOL> else : <EOL> raise ParseError ( "<STR_LIT>" ) <EOL> if description : <EOL> arg [ '<STR_LIT:description>' ] = description <EOL> return arg <EOL> def help ( self , out = None , initial_heading_level = <NUM_LIT:0> ) : <EOL> out = out or io . StringIO ( ) <EOL> builder = help . SchemaHelpBuilder ( self . schema ( ) , out = out , initial_heading_level = <NUM_LIT:0> ) <EOL> builder . build ( ) <EOL> builder . line ( ) <EOL> return out . getvalue ( ) </s>
