Package: qstion
qstionA querystring parsing and stringifying library with some added security.
Library was based onthisjs library.Usageimportqstionasqsx=qs.parse('a=c')assertx=={'a':'c'}x_str=qs.stringify(x)assertx_str=='a=c'Parsing stringsqstion(as well asqsin js) allows you to parse string into nested objects.importqstionasqsassertqs.parse('a[b][c]=1')=={'a':{'b':{'c':'1'}}}There is no support for plain object options or prototype pollution.Uri encoded strings are supportedimportqstionasqsassertqs.parse('a%5Bb%5D=c')=={'a':{'b':'c'}}Following options are supported:from_url:bool- ifTruethenparsewill parse querystring from url usingurlparsefromurllib.parsemodule, default:Falseimportqstionasqsassertqs.parse('http://localhost:8080/?a=c',from_url=True)=={'a':'c'}assertqs.parse('a=c',from_url=False)=={'a':'c'}delimiter:str|re.Pattern- delimiter for parsing, default:&importqstionasqsassertqs.parse('a=c&b=d',delimiter='&')=={'a':'c','b':'d'}assertqs.parse('a=c;b=d,c=d',delimiter='[;,]')=={'a':'c','b':'d','c':'d'}depth:int- maximum depth for parsing, default:5importqstionasqsassertqs.parse('a[b][c][d][e][f][g][h][i]=j',depth=5)=={'a':{'b':{'c':{'d':{'e':{'f':{'[g][h][i]':'j'}}}}}}}assertqs.parse('a[b][c][d][e][f][g][h][i]=j',depth=1)=={'a':{'b':{'[c][d][e][f][g][h][i]':'j'}}}parameter_limit:int- maximum number of parameters to parse, default:1000importqstionasqsassertqs.parse('a=b&c=d&e=f&g=h&i=j&k=l&m=n&o=p&q=r&s=t&u=v&w=x&y=z',parameter_limit=5)=={'a':'b','c':'d','e':'f','g':'h','i':'j'}allow_dots:bool- ifTruethen dots in keys will be parsed as nested objects, default:Falseimportqstionasqsassertqs.parse('a.b=c',allow_dots=True)=={'a':{'b':'c'}}parse_arrays:bool- ifTruethen arrays will be parsed, default:Falseimportqstionasqsassertqs.parse('a[]=b&a[]=c',parse_arrays=True)=={'a':{0:'b',1:'c'}}assertqs.parse('a[0]=b&a[1]=c',parse_arrays=False)=={'a':{'0':'b','1':'c'}}array_limit:int- maximum number of elements in array to keep array notation (only used with combination of argumentparse_arrays), default:20importqstionasqsassertqs.parse('a[]=b&a[]=c&',parse_arrays=True)=={'a':{0:'b',1:'c'}}assertqs.parse('a[0]=b&a[1]=c&',array_limit=1,parse_arrays=True)=={'a':{'0':'b','1':'c'}}allow_empty:bool- ifTruethen empty values and keys are accepted, default:Falseimportqstionasqsassertqs.parse('a=&b=',allow_empty=True)=={'a':'','b':''}assertqs.parse('a[]=&b[]=',allow_empty=True)=={'a':{'':''},'b':{'':''}}charset:str- charset to use when decoding uri encoded strings, default:utf-8importqstionasqsassertqs.parse('a=%A7',charset='iso-8859-1')=={'a':'§'}assertqs.parse('a=%C2%A7',charset='utf-8')=={'a':'§'}charset_sentinel:bool- ifTruethen, ifutf8=✓arg is included in querystring, then charset will be deduced based on encoding of '✓' character (recognizes onlyutf8andiso-8859-1), default:Falseimportqstionasqsassertqs.parse('a=%C2%A7&utf8=%E2%9C%93',charset='iso-8859-1',charset_sentinel=True)=={'a':'§'}assertqs.parse('a=%A7&utf8=%26%2310003',charset='utf-8',charset_sentinel=True)=={'a':'§'}interpret_numeric_entities:bool- ifTruethen numeric entities will be interpreted as unicode characters, default:Falseimportqstionasqsassertqs.parse('a=%26%2310003',charset='iso-8859-1',interpret_numeric_entities=True)=={'a':'✓'}parse_primitive:bool- ifTruethen primitive values will be parsed in their appearing types, default:Falseimportqstionasqsassertqs.parse('a=1&b=2&c=3',parse_primitive=True)=={'a':1,'b':2,'c':3}assertqs.parse('a=true&b=false&c=null',parse_primitive=True)=={'a':True,'b':False,'c':None}primitive_strict:bool- ifTruethen primitive values ofboolandNoneTypewill be parsed to reserved strict keywords (used only ifparse_primitiveisTrue), default:Trueimportqstionasqsassertqs.parse('a=true&b=false&c=null&d=None',parse_primitive=True,primitive_strict=True)=={'a':True,'b':False,'c':None,'d':'None'}assertqs.parse('a=True&b=False&c=NULL',parse_primitive=True,primitive_strict=True)=={'a':'True','b':'False','c':'NULL'}assertqs.parse('a=True&b=False&c=NULL',parse_primitive=True,primitive_strict=False)=={'a':True,'b':False,'c':None}comma:bool- ifTrue, then coma separated values will be parsed as multiple separate values instead of string, default:Falseimportqstionasqsassertqs.parse('a=1,2,3',comma=True,parse_primitive=True)=={'a':[1,2,3]}Stringifying objectsqstion(as well asqsin js) allows you to stringify objects into querystring.importqstionasqsassertqs.stringify({'a':'b'})=='a=b'Following options are supported:allow_dots:bool- ifTruethen nested keys will be stringified using dot notation instead of brackets, default:Falseimportqstionasqsassertqs.stringify({'a':{'b':'c'}},allow_dots=True)=='a.b=c'encode:bool- ifTruethen keys and values will be uri encoded (with defaultcharset), default:Trueimportqstionasqsassertqs.stringify({'a[b]':'b'},encode=False)=='a[b]=b'assertqs.stringify({'a[b]':'b'},encode=True)=='a%5Bb%5D=b'charset:str- charset to use when encoding uri strings, default:utf-8(ifencodeisTrue), note that un-encodable characters will be encoded using their xml numeric entitiesimportqstionasqsassertqs.stringify({'a':'§'},charset='iso-8859-1')=='a=%A7'assertqs.stringify({'a':'☺'},charset='iso-8859-1')=='a=%26%2312850'charset_sentinel:bool- ifTruethen,utf8=✓will be added to querystring to indicate that charset based on encoding of '✓' character (recognizes onlyutf8andiso-8859-1), default:Falseimportqstionasqsassertqs.stringify({'a':'§'},charset='iso-8859-1',charset_sentinel=True)=='a=%A7&utf8=%E2%9C%93'delimiter:str- delimiter for stringifying, default:&importqstionasqsassertqs.stringify({'a':'b','c':'d'},delimiter='&')=='a=b&c=d'assertqs.stringify({'a':'b','c':'d'},delimiter=';')=='a=b;c=d'encode_values_only:bool- ifTruethen only values will be encoded, default:False(this option is overridden whenencodeisTrue)importqstionasqsassertqs.stringify({'a':{'b':'☺'}},encode_values_only=True,charset='iso-8859-1')=='a[b]=%26%2312850'array_format:str- format for array notation, options: 'brackets','indices', 'repeat', 'comma', default: 'indices'importqstionasqsassertqs.stringify({'a':{1:'b',2:'c'}},array_format='brackets')=='a[]=b&a[]=c'assertqs.stringify({'a':{1:'b',2:'c'}},array_format='indices')=='a[1]=b&a[2]=c'assertqs.stringify({'a':{1:'b',2:'c'}},array_format='repeat')=='a=b&a=c'assertqs.stringify({'a':{1:'b',2:'c'}},array_format='comma')=='a=b,c'sort:bool- ifTruethen keys will be sorted alphabetically, default:Falseimportqstionasqsassertqs.stringify({'x':'y','a':'b'},sort=True)=='a=b&x=y'sort_reverse:bool- ifTruethen keys will be sorted (ifsortisTrue) in reverse order, default:Falseimportqstionasqsassertqs.stringify({'x':'y','a':'b'},sort=True,sort_reverse=True)=='x=y&a=b'filter:list[str]- list of keys to filter, default:Noneimportqstionasqsassertqs.stringify({'a':'b','c':'d'},filter=['a'])=='a=b'