Skip to content

Commit

Permalink
the 2.4 near perfection
Browse files Browse the repository at this point in the history
  • Loading branch information
manatlan committed Apr 23, 2020
1 parent f82c836 commit 0df9e65
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 39 deletions.
File renamed without changes.
5 changes: 5 additions & 0 deletions REALTESTS/_auto_command_shebang/test.rml
@@ -0,0 +1,5 @@
#! --b

- GET: /get_txt # same as "auto_rmr_cant_save_rmr_on_dual.yml" but with a reqman.conf
tests:
- status: 200
8 changes: 8 additions & 0 deletions REALTESTS/_auto_command_shebang/test.yml
@@ -0,0 +1,8 @@
#!python3 fakereqman.py
#:valid:1 --i test.rml
# -*- coding: utf-8 -*-
#--------------------------------------------------------------
# ^^^^^ REAL SHEBANG ^^^^^ (real test with real reqman sources)
# (works in vs code, press F5)
#--------------------------------------------------------------

7 changes: 3 additions & 4 deletions REALTESTS/auto_new_features.yml
@@ -1,5 +1,5 @@
#!python3 fakereqman.py
#:valid:111111,111111111 THIS --b
#:valid:111111,11111111 THIS --b
# -*- coding: utf-8 -*-
#--------------------------------------------------------------
# ^^^^^ REAL SHEBANG ^^^^^ (real test with real reqman sources)
Expand All @@ -26,9 +26,8 @@
- status|testInt: ok #new
- json.info.n|testInt: ok #new
- json.msg|testStr: ok #new
- header.X-MyHeader: hello #new
- header.x-myheader: hel #new (contains)
- header.x-myHEADer|upper|decor: XHELLOX #new
- headers.x-myheader: hello #new (lowercased!)
- headers.x-myheader|upper|decor: XHELLOX #new (lowercased!)

- mybool: true # can test real var too !
- kiki: null # unknown var is None/null
Expand Down
46 changes: 46 additions & 0 deletions REALTESTS/auto_new_response_request.yml
@@ -0,0 +1,46 @@
#!python3 fakereqman.py
#:valid:11111111111111111111111 THIS --b
# -*- coding: utf-8 -*-
#--------------------------------------------------------------
# ^^^^^ REAL SHEBANG ^^^^^ (real test with real reqman sources)
# (works in vs code, press F5)
#--------------------------------------------------------------

- POST: http://localhost:11111/ping
headers:
X-Test: test
body: hello
tests:
- status: 201

# old
- content: hello
- content: hel # old can contains !

- x-test: es # old can contains ! and mixed case header
- X-TesT: es # old can contains ! and mixed case header

# newest
- headers.x-test: test # header lowercased!
- headers.x-test: . ? es
- headers.X-Test: null

- header.X-Test: null # old way (2.3.10 < 2.4)
- header.x-test: null # old way (2.3.10 < 2.4)

# ultra newest
- response.status: 201
- response.content: hello
- response.content: .? hel
- response.headers.X-Test: null
- response.headers.x-test: test # header lowercased!
- response.headers.x-test: .? es

- request.path: http://localhost:11111/ping
- request.method: POST
- request.content: hello
- request.content: .? hel
- request.headers.X-Test: null
- request.headers.x-test: test # header lowercased!
- request.headers.x-test: .? es # header lowercased!

5 changes: 3 additions & 2 deletions REALTESTS/auto_selfconf_global_headers.yml
@@ -1,5 +1,5 @@
#!python3 fakereqman.py
#:valid:111 THIS --b
#:valid:1111 THIS --b
# -*- coding: utf-8 -*-
#--------------------------------------------------------------
# ^^^^^ REAL SHEBANG ^^^^^ (real test with real reqman sources)
Expand All @@ -16,5 +16,6 @@
tests:
- status: 201
- content: hello
- headers.X-My: Hello
- headers.X-My: null # in headers, its lowercased !
- headers.x-my: Hello

1 change: 1 addition & 0 deletions changelog
@@ -1,4 +1,5 @@
THE FUTURE 2.4.0
- EVOL: new compare operator ".?" (??????????????????????)
- EVOL: simple "if statement" !
- remove old shebang system
- FIX: jpath can now resolve python methods too !!! (in a good way)
Expand Down
37 changes: 20 additions & 17 deletions fakereqman.py
Expand Up @@ -181,6 +181,7 @@ def checkSign(sign1,sign2,args):
if t1!=t2:
diffs=[i+1 for i,(a1,a2) in enumerate(zip(t1,t2)) if a1!=a2]
return "Req %s fail on its %s test, for %s" % (idx+1,diffs[0],args)

def main( file, avoidBrowser=True ):
"""
yield "" : si valid est ok
Expand Down Expand Up @@ -208,26 +209,28 @@ class RR:
sys.argv = ["reqman"] + args

rc=reqman.main(hookResults=o)
o.rr=None
if rc>=0:
if o.rr:
if hasattr(o,"rr"):
details=[]
details2=[]
for i in o.rr.results:
for j in i.exchanges:
if type(j)==tuple:
if j[0]: details.append("".join([str(int(t)) for t in j[0].tests]))
if j[1]: details2.append("".join([str(int(t)) for t in j[1].tests]))
else:
details.append("".join([str(int(t)) for t in j.tests]))
toValid=",".join(details)
if details2: toValid+=":"+",".join(details2)

if valid:
err=checkSign(valid,toValid,args)
print("> Check valid:",valid,"?==",toValid,"-->","!!! ERROR: %s !!!"%err if err else "OK")
if o.rr and o.rr.results:
for i in o.rr.results:
for j in i.exchanges:
if type(j)==tuple:
if j[0]: details.append("".join([str(int(t)) for t in j[0].tests]))
if j[1]: details2.append("".join([str(int(t)) for t in j[1].tests]))
else:
details.append("".join([str(int(t)) for t in j.tests]))
toValid=",".join(details)
if details2: toValid+=":"+",".join(details2)

if valid:
err=checkSign(valid,toValid,args)
print("> Check valid:",valid,"?==",toValid,"-->","!!! ERROR: %s !!!"%err if err else "OK")
else:
print("> No validation check! (valid:%s)" % toValid)
err=None
else:
print("> No validation check! (valid:%s)" % toValid)
err=None
else:
err="" #TODO: do something here (see test "new url")
Expand All @@ -249,7 +252,7 @@ class RR:

if __name__=="__main__":

# sys.argv=["","REALTESTS/rmr_self_conf.yml"] # *** FOR running in DEDUG MODE ***
# sys.argv=["","REALTESTS/auto_new_response_request.yml"] # *** FOR running in DEDUG MODE ***

try:
ws=FakeWebServer(11111)
Expand Down
95 changes: 79 additions & 16 deletions reqman.py
Expand Up @@ -34,7 +34,13 @@
import xpath # see "pip install py-dom-xpath-six"

#95%: python3 -m pytest --cov-report html --cov=reqman .
__version__="2.4.0.0" #only SemVer (the last ".0" is win only)
__version__="PRE2.4.0.0" #only SemVer (the last ".0" is win only)

"""
- verifier que les tests continuent pas passer, suite a l'ajout request/response
- harmoniser .header -> .headers
- s'assurer des noms request/response ou objet rm.request / rm.response ?!
"""


try: # colorama is optionnal
Expand Down Expand Up @@ -82,8 +88,11 @@ def isPython(x):

def jdumps(o,*a,**k):
k["ensure_ascii"]=False
#~ k["default"]=serialize
return json.dumps(o,*a,**k)

#~ def serialize(obj):
#~ return str(obj)

def izip(ex1,ex2):
pop= lambda ex: len(ex)>0 and ex.pop(0) or None
Expand Down Expand Up @@ -206,9 +215,14 @@ def toJson(self):
return json.loads( self.__b.decode() )
def toXml(self):
return Xml( repr(self) )
def bytes(self):
def __bytes__(self):
return self.__b

class RmDict(dict):
def __init__(self,**kargs):
self.__dict__.update(kargs)
dict.__init__(self,**kargs)


"""
AHTTP = httpcore.AsyncClient(verify=False)
Expand Down Expand Up @@ -321,7 +335,7 @@ def jpath(elem, path: str) -> T.Union[int, T.Type[NotFound], str]:
return len(elem)
else:
elem = elem[int(i)]
elif type(elem) in [dict,Env]:
elif isinstance(elem,dict):
if i == "size":
return len(list(elem.keys()))
else:
Expand Down Expand Up @@ -503,7 +517,7 @@ def replaceObj(self, v: T.Any) -> T.Any: # same as txtReplace() but for "object
if type(v) is bytes:
return v
elif type(v) is Content: # (when save to var)
return v.bytes()
return bytes(v)
elif type(v) is not str:
v=jdumps(v)

Expand Down Expand Up @@ -544,7 +558,35 @@ def getVar(var:str):
content = None

for m in method.split("|"):
content = self.replaceObj( content ) ## important, resolv inner method first .... see tests 044, 045, 046
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
if type(content) != RmDict: # !!!!!!!!!!!!!!!!!!!!!!
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
#!!!!!!!!!!!!!!!!!!!!!!!!!!!! A TESTER CA
content = self.replaceObj( content ) ## important, resolv inner method first .... see tests 044, 045, 046

content = self.transform(content, m)
return content
Expand Down Expand Up @@ -1135,7 +1177,7 @@ def resolvHeaders(headers):
envResponse = scope.clone()
envResponse["content"] = ex.content
envResponse["status"] = ex.status
envResponse["header"] = {k.lower():v for k,v in ex.outHeaders.items()} # NEW !!!!
envResponse["headers"] = {k.lower():v for k,v in ex.outHeaders.items()} # NEW !!!! (2.3.10)
#TODO: expose time ?
try:
envResponse["json"] = ex.content.toJson()
Expand All @@ -1145,9 +1187,22 @@ def resolvHeaders(headers):
envResponse["xml"] = ex.content.toXml()
except:
pass

envResponse["request"]=RmDict( # new
path = ex.url,
method = ex.method,
content = ex.bodyContent,
headers = {k.lower():v for k,v in ex.inHeaders.items()}
)
envResponse["response"]=RmDict( # new
status= envResponse["status"],
content= envResponse["content"],
headers= envResponse["headers"], ## headers != header !!!!!!!!!!!!! harmoniser !!!
json= envResponse.get("json",None),
xml= envResponse.get("xml",None),
)
#+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-


try:
for s in saves:
for saveKey, saveWhat in s.items():
Expand Down Expand Up @@ -1280,7 +1335,7 @@ def guessValue(txt):
def getValOpe(v):
try:
if type(v) == str and v.startswith("."):
g = re.match(r"^\. *([!=<>]{1,2}) *(.+)$", v)
g = re.match(r"^\. *([\?!=<>]{1,2}) *(.+)$", v)
if g:
op, v = g.groups()
if op == "==": # not needed really, but just for compatibility
Expand Down Expand Up @@ -1317,6 +1372,13 @@ def getValOpe(v):
"<",
">=",
)
elif op == "?":
return (
v,
lambda a, b: str(a) in str(b),
"contains",
"doesn't contain",
)
except (
yaml.scanner.ScannerError,
yaml.constructor.ConstructorError,
Expand All @@ -1342,7 +1404,8 @@ def __init__(self, tests, env, status) -> None:


firstWord = re.split(r"[\.|]",what)[0]
testContains = False # true pour contant & headers !!!!!
testContains = False # true pour content & "old headers" !!!!!
# to ensure compatibility with < 2.3.8
if firstWord=="content":
testContains=True
elif firstWord=="status":
Expand All @@ -1351,14 +1414,14 @@ def __init__(self, tests, env, status) -> None:
testContains=False
elif firstWord=="xml":
testContains=False
elif firstWord=="header":
testContains=True
elif firstWord=="headers":
testContains=False
else: # header
if "header" in env:
if "headers" in env:
header=what.lower()
if header in env["header"]:
print( cy("**DEPRECATED**"), "use new header syntax in tests (- header.%s: ...)"%what )
tvalue = env["header"][header]
if header in env["headers"]:
print( cy("**DEPRECATED**"), "use new header syntax in tests (- headers.%s: ...)"%what )
tvalue = env["headers"][header]
testContains=True

# test if all match as json (list, dict, str ...)
Expand Down Expand Up @@ -2175,4 +2238,4 @@ class RMCommandException(Exception): pass

if __name__=="__main__":
sys.exit(main())

0 comments on commit 0df9e65

Please sign in to comment.