Skip to content

Commit e1ff208

Browse files
committed
Fix #350 separate column for errors
1 parent 7d104ed commit e1ff208

File tree

7 files changed

+185
-47
lines changed

7 files changed

+185
-47
lines changed

Diff for: dotextensions/server/handlers/basic_handlers.py

+61-24
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,20 @@ def run(self, command: Command) -> Result:
5151
except DotHttpException as exc:
5252
logger.error(f"dothttp exception happened {exc}", exc_info=True)
5353
result = Result(
54-
id=command.id, result={"error_message": exc.message, "error": True}
54+
id=command.id, result={
55+
"error_message": exc.message, "error": True}
5556
)
5657
except RequestException as exc:
5758
logger.error(f"exception from requests {exc}", exc_info=True)
5859
result = Result(
59-
id=command.id, result={"error_message": str(exc), "error": True}
60+
id=command.id, result={
61+
"error_message": str(exc), "error": True}
6062
)
6163
except Exception as exc:
6264
logger.error(f"unknown error happened {exc}", exc_info=True)
6365
result = Result(
64-
id=command.id, result={"error_message": str(exc), "error": True}
66+
id=command.id, result={
67+
"error_message": str(exc), "error": True}
6568
)
6669
return result
6770

@@ -71,14 +74,14 @@ def execute(self, command):
7174
req = self.get_curl_comp(config)
7275
result = req.get_curl_output()
7376
result = Result(
74-
id=command.id,
75-
result={
76-
"body": result,
77-
"headers": {
78-
"Content-Type": mimetypes.types_map[".sh"],
79-
},
77+
id=command.id,
78+
result={
79+
"body": result,
80+
"headers": {
81+
"Content-Type": mimetypes.types_map[".sh"],
8082
},
81-
)
83+
},
84+
)
8285
else:
8386
comp = self.get_request_comp(config)
8487
result = self.get_request_result(command, comp)
@@ -94,7 +97,8 @@ def get_config(self, command):
9497
target = params.get("target", "1")
9598
nocookie = params.get("nocookie", False)
9699
curl = params.get("curl", False)
97-
properties = [f"{i}={j}" for i, j in params.get("properties", {}).items()]
100+
properties = [f"{i}={j}" for i,
101+
j in params.get("properties", {}).items()]
98102
content = params.get("content", None)
99103
contexts = params.get("contexts")
100104
property_file = params.get("property-file", None)
@@ -123,6 +127,26 @@ def get_config(self, command):
123127

124128
def get_request_result(self, command, comp: RequestCompiler):
125129
comp.load_def()
130+
if comp.property_util.errors:
131+
return Result(
132+
id=command.id,
133+
result={
134+
"errors": [{"var": list(error.kwargs['var']), "message": str(error)} for error in comp.property_util.errors],
135+
"response": {
136+
"body": "",
137+
"output_file": "",
138+
"status": 0,
139+
"method": "ERROR",
140+
"url": "ERROR",
141+
"headers": {
142+
"Content-Type": "text/plain",
143+
},
144+
"error": True,
145+
"error_message": "errors found",
146+
"contentType": "text/plain",
147+
},
148+
},
149+
)
126150
resp = comp.get_response()
127151
if output := comp.httpdef.output:
128152
# body = f"Output stored in {output}"
@@ -131,7 +155,8 @@ def get_request_result(self, command, comp: RequestCompiler):
131155
except Exception as e:
132156
output = f"Not!. unhandled error happened : {e}"
133157
logger.warning("unable to write because", exc_info=True)
134-
script_result = comp.script_execution.execute_test_script(resp).as_json()
158+
script_result = comp.script_execution.execute_test_script(
159+
resp).as_json()
135160
body = resp.text
136161
response_data = {
137162
"response": {
@@ -140,6 +165,7 @@ def get_request_result(self, command, comp: RequestCompiler):
140165
**self._get_resp_data(resp),
141166
},
142167
"script_result": script_result,
168+
"errors": [error.kwargs for error in comp.property_util.errors],
143169
}
144170
if resp.history:
145171
response_data["history"] = [
@@ -153,9 +179,11 @@ def get_request_result(self, command, comp: RequestCompiler):
153179
# redirects can add cookies
154180
comp.httpdef.headers["cookie"] = resp.request.headers["cookie"]
155181
try:
156-
data.update({"http": self.get_http_from_req(comp.httpdef, comp.property_util)})
182+
data.update({"http": self.get_http_from_req(
183+
comp.httpdef, comp.property_util)})
157184
except Exception as e:
158-
logger.error("ran into error regenerating http def from parsed object")
185+
logger.error(
186+
"ran into error regenerating http def from parsed object")
159187
data.update(
160188
{"http": f"ran into error \n Exception: `{e}` message:{e.args}"}
161189
)
@@ -175,7 +203,8 @@ def get_request_comp(self, config):
175203

176204
@staticmethod
177205
def get_http_from_req(request: HttpDef, property_util: "PropertyProvider"):
178-
http_def = MultidefHttp(import_list=[], allhttps=[request.get_http_from_req()])
206+
http_def = MultidefHttp(import_list=[], allhttps=[
207+
request.get_http_from_req()])
179208
return HttpFileFormatter.format(http_def, property_util=property_util)
180209

181210

@@ -200,7 +229,8 @@ def load_model(self):
200229
##
201230
# context has varibles defined
202231
# for resolving purpose, including them into content
203-
self.content = self.content + CONTEXT_SEP + CONTEXT_SEP.join(self.args.contexts)
232+
self.content = self.content + CONTEXT_SEP + \
233+
CONTEXT_SEP.join(self.args.contexts)
204234

205235
def select_target(self):
206236
for context in self.args.contexts:
@@ -219,7 +249,7 @@ def select_target(self):
219249
self.model.import_list = model.import_list
220250
self.load_imports()
221251
self.content += context + "\n\n" + context
222-
252+
223253
except Exception as e:
224254
# contexts, can not always be correct syntax
225255
# in such scenarios, don't complain, try to resolve with
@@ -277,19 +307,20 @@ def run(self, command: Command) -> Result:
277307
"headers": {
278308
"Content-Type": "text/plain",
279309
},
280-
"output_file":"",
310+
"output_file": "",
281311
"error": True,
282312
"error_message": error_result,
283313
"contentType": "text/plain",
284314
}
285315
result = {
286316
"response": response,
287-
"script_result": {"stdout": "", "error": "", "properties":{}, "tests":[]},
317+
"script_result": {"stdout": "", "error": "", "properties": {}, "tests": []},
288318
"http": "REQUEST_EXECUTION_ERROR",
289319
"filenameExtension": ".txt",
290320
}
291321
result.update(response)
292-
return Result(id=command.id, result=result)
322+
return Result(id=command.id, result=result)
323+
293324

294325
class FormatHttpFileHandler(BaseHandler):
295326
method = "/file/format"
@@ -301,6 +332,7 @@ def run(self, command: Command) -> Result:
301332
result = Result(id=command.id, result=command.params)
302333
return result
303334

335+
304336
class ResolveBase():
305337

306338
def get_resolved(self, command: Command) -> Result:
@@ -320,7 +352,7 @@ def get_resolved(self, command: Command) -> Result:
320352
if match.start() <= pos <= match.end():
321353
property_hovered = match.group()[2:-2].split("=")[0].strip()
322354
break
323-
355+
324356
type_dict = TypeFromPos.figure_n_get(model, pos)
325357
if "target" not in type_dict:
326358
command.params["target"] = 1
@@ -363,12 +395,14 @@ def get_resolved(self, command: Command) -> Result:
363395
return Result(id=command.id, result=type_dict)
364396

365397
# return resolved string instead of model object
398+
399+
366400
class GetHoveredResolvedParamFileHandler(RunHttpFileHandler, ResolveBase):
367401
method = "/file/resolve"
368402

369403
def get_method(self):
370404
return GetHoveredResolvedParamFileHandler.method
371-
405+
372406
def run(self, command):
373407
return self.get_resolved(command)
374408

@@ -382,6 +416,7 @@ def get_method(self):
382416
def run(self, command):
383417
return self.get_resolved(command)
384418

419+
385420
class GetNameReferencesHandler(BaseHandler):
386421
name = "/file/names"
387422

@@ -394,7 +429,8 @@ def run(self, command: Command) -> Result:
394429
result = self.execute(command, filename)
395430
except DotHttpException as ex:
396431
result = Result(
397-
id=command.id, result={"error_message": ex.message, "error": True}
432+
id=command.id, result={
433+
"error_message": ex.message, "error": True}
398434
)
399435
except Exception as e:
400436
result = Result(
@@ -428,7 +464,8 @@ def parse_n_get(self, http_data, filename: str):
428464
for new_model, _content in BaseModelProcessor._get_models_from_import(
429465
model, filename
430466
):
431-
self.get_for_http(new_model.allhttps, imported_names, imported_urls)
467+
self.get_for_http(new_model.allhttps,
468+
imported_names, imported_urls)
432469
return all_names, all_urls, imported_names, imported_urls
433470

434471
def get_for_http(self, allhttps, all_names, all_urls):

Diff for: dothttp/exceptions.py

+13
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ def wrapper(cls):
55
class exc(cls):
66
def __init__(self, **kwargs):
77
self.message = message.format(**kwargs)
8+
self.kwargs = kwargs
89

910
return exc
1011

@@ -17,6 +18,18 @@ def __str__(self) -> str:
1718
return self.message
1819

1920

21+
class DothttpMultiExceptions(DotHttpException):
22+
def __init__(self, exceptions):
23+
self.exceptions = exceptions
24+
25+
@property
26+
def message(self):
27+
return "\n".join([str(exception) for exception in self.exceptions])
28+
29+
def __str__(self) -> str:
30+
return "\n".join([str(exception) for exception in self.exceptions])
31+
32+
2033
@exception_wrapper(
2134
"http def with name `{base}` not defined for http with name `{target}`"
2235
)

Diff for: dothttp/parse/__init__.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ def __init__(self, args: Config):
182182
self.content = ""
183183
self.original_content = self.content = ""
184184
self.property_util = PropertyProvider(self.property_file)
185+
self.errors = []
185186
self.load()
186187

187188
def load(self):
@@ -277,7 +278,11 @@ def load_content(self):
277278
self.original_content = self.content = f.read()
278279

279280
def get_updated_content(self, content) -> str:
280-
return self.property_util.get_updated_content(content)
281+
try:
282+
return self.property_util.get_updated_content(content)
283+
except DotHttpException as e:
284+
self.errors.append(e)
285+
return content
281286

282287
def get_updated_content_object(self, content) -> str:
283288
return self.property_util.get_updated_content(content, "obj")

Diff for: dothttp/parse/request_base.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
from ..utils.property_util import PropertyProvider, Property
2020

21-
from ..exceptions import DothttpUnSignedCertException
21+
from ..exceptions import DothttpMultiExceptions, DothttpUnSignedCertException
2222
from ..models.parse_models import Http, HttpFileType, MultidefHttp, ScriptType
2323
from ..parse import (
2424
APPLICATION_JSON,
@@ -480,6 +480,10 @@ def query_to_http(line):
480480
class RequestCompiler(RequestBase):
481481
def run(self):
482482
self.load_def()
483+
if len(self.property_util.errors) > 0:
484+
for error in self.errors:
485+
eprint(error)
486+
raise DothttpMultiExceptions(self.property_util.errors)
483487
resp = self.get_response()
484488
self.print_req_info(resp.request)
485489
for hist_resp in resp.history:

Diff for: dothttp/utils/property_util.py

+18-13
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ def __init__(self, property_file=""):
157157
self.command_line_properties = {}
158158
self.property_file = property_file
159159
self.is_running_system_command_enabled = False
160+
self.errors = []
160161

161162
def enable_system_command(self):
162163
self.is_running_system_command_enabled = True
@@ -238,19 +239,23 @@ def is_special_keyword(key):
238239
return ret or key.startswith("$expr:")
239240

240241
def get_updated_content(self, content, type="str"):
241-
content_prop_needed, props_needed = self.check_properties_for_content(
242-
content)
243-
for var in props_needed:
244-
if type == "str":
245-
value = self.resolve_property_string(var)
246-
for text_to_replace in content_prop_needed[var].text:
247-
content = content.replace(
248-
"{{" + text_to_replace + "}}", str(value)
249-
)
250-
else:
251-
content = self.resolve_property_object(var)
252-
base_logger.debug(f"using `{content}` for property {var}")
253-
return content
242+
try:
243+
content_prop_needed, props_needed = self.check_properties_for_content(
244+
content)
245+
for var in props_needed:
246+
if type == "str":
247+
value = self.resolve_property_string(var)
248+
for text_to_replace in content_prop_needed[var].text:
249+
content = content.replace(
250+
"{{" + text_to_replace + "}}", str(value)
251+
)
252+
else:
253+
content = self.resolve_property_object(var)
254+
base_logger.debug(f"using `{content}` for property {var}")
255+
return content
256+
except PropertyNotFoundException as e:
257+
self.errors.append(e)
258+
return content
254259

255260
def get_updated_obj_content(self, content):
256261
return self.get_updated_content(content, "obj")

0 commit comments

Comments
 (0)