py4web-debug-tools 0.1.1__tar.gz → 0.2.0.dev0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (20) hide show
  1. {py4web-debug-tools-0.1.1 → py4web-debug-tools-0.2.0.dev0}/PKG-INFO +13 -5
  2. {py4web-debug-tools-0.1.1 → py4web-debug-tools-0.2.0.dev0}/README.md +12 -4
  3. py4web-debug-tools-0.2.0.dev0/py4web_debug/core.py +64 -0
  4. {py4web-debug-tools-0.1.1 → py4web-debug-tools-0.2.0.dev0}/py4web_debug/debugbar.py +2 -2
  5. {py4web-debug-tools-0.1.1 → py4web-debug-tools-0.2.0.dev0}/py4web_debug/dumping.py +1 -1
  6. {py4web-debug-tools-0.1.1 → py4web-debug-tools-0.2.0.dev0}/py4web_debug/internals.py +53 -43
  7. {py4web-debug-tools-0.1.1 → py4web-debug-tools-0.2.0.dev0}/py4web_debug_tools.egg-info/PKG-INFO +13 -5
  8. {py4web-debug-tools-0.1.1 → py4web-debug-tools-0.2.0.dev0}/setup.py +1 -1
  9. py4web-debug-tools-0.1.1/py4web_debug/core.py +0 -49
  10. {py4web-debug-tools-0.1.1 → py4web-debug-tools-0.2.0.dev0}/py4web_debug/__init__.py +0 -0
  11. {py4web-debug-tools-0.1.1 → py4web-debug-tools-0.2.0.dev0}/py4web_debug/env.py +0 -0
  12. {py4web-debug-tools-0.1.1 → py4web-debug-tools-0.2.0.dev0}/py4web_debug/templates/debugbar.html +0 -0
  13. {py4web-debug-tools-0.1.1 → py4web-debug-tools-0.2.0.dev0}/py4web_debug/templates/dumpdie.html +0 -0
  14. {py4web-debug-tools-0.1.1 → py4web-debug-tools-0.2.0.dev0}/py4web_debug/templates/error_default.html +0 -0
  15. {py4web-debug-tools-0.1.1 → py4web-debug-tools-0.2.0.dev0}/py4web_debug/templates/fancy_dumpdie.html +0 -0
  16. {py4web-debug-tools-0.1.1 → py4web-debug-tools-0.2.0.dev0}/py4web_debug_tools.egg-info/SOURCES.txt +0 -0
  17. {py4web-debug-tools-0.1.1 → py4web-debug-tools-0.2.0.dev0}/py4web_debug_tools.egg-info/dependency_links.txt +0 -0
  18. {py4web-debug-tools-0.1.1 → py4web-debug-tools-0.2.0.dev0}/py4web_debug_tools.egg-info/requires.txt +0 -0
  19. {py4web-debug-tools-0.1.1 → py4web-debug-tools-0.2.0.dev0}/py4web_debug_tools.egg-info/top_level.txt +0 -0
  20. {py4web-debug-tools-0.1.1 → py4web-debug-tools-0.2.0.dev0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: py4web-debug-tools
3
- Version: 0.1.1
3
+ Version: 0.2.0.dev0
4
4
  Summary: Debug Tools for py4web
5
5
  Home-page: https://github.com/trialandsuccess/py4web-debug-tools
6
6
  Author: Robin van der Noord
@@ -9,7 +9,8 @@ Requires-Python: >3.10.0
9
9
  Description-Content-Type: text/markdown
10
10
 
11
11
  # py4web debug tools
12
- Tooling to improve the developer experience when working with py4web.
12
+
13
+ Tooling to improve the developer experience when working with py4web.
13
14
 
14
15
  There are two main tools and some helpers that this package provides.
15
16
 
@@ -19,9 +20,16 @@ There are two main tools and some helpers that this package provides.
19
20
  ## In this package:
20
21
 
21
22
  - `tools`:
22
- - `enable(db: DAL, enabled: bool)`: activate or disable the debug tools (add the custom error screen and create the Debug Bar
23
- Fixture).
24
- The first argument (DAL) is required for the debug bar to collect queries.
23
+ - `enable(db: DAL, enabled?: bool, fancy_rendering?: bool, bar_style?: "bootstrap", slow_threshold_ms?: int)`:
24
+ activate or disable the debug tools (add the custom error screen and create the Debug Bar Fixture).
25
+ The first argument (DAL) is required for the debug bar to collect queries.
26
+ `enabled` can be used to dynamically turn on/off the debug features.
27
+ `fancy_rendering`: This will render the `data` section of the debug bar using `json-browse`, which
28
+ includes `jQuery`. If this clashes with the other JS on a page, this can be set to False to simply show a `<pre>`
29
+ block with data.
30
+ `bar_style`: only bootstrap is supported at this moment.
31
+ `slow_threshold_ms`: amount of milliseconds an SQL query has to take before it is considered a 'slow query' in the
32
+ debug bar.
25
33
  - `debug_bar`: this Fixture can be used on py4web actions to enable the bar for that page.
26
34
  - `catch(*)`: Data and a stacktrace of where `catch()` is called can be found in the catch tab of the debug bar.
27
35
  - `dump(*)`: convert objects to JSON, with a more capable converter than the default json.dumps (e.g. it works better
@@ -1,5 +1,6 @@
1
1
  # py4web debug tools
2
- Tooling to improve the developer experience when working with py4web.
2
+
3
+ Tooling to improve the developer experience when working with py4web.
3
4
 
4
5
  There are two main tools and some helpers that this package provides.
5
6
 
@@ -9,9 +10,16 @@ There are two main tools and some helpers that this package provides.
9
10
  ## In this package:
10
11
 
11
12
  - `tools`:
12
- - `enable(db: DAL, enabled: bool)`: activate or disable the debug tools (add the custom error screen and create the Debug Bar
13
- Fixture).
14
- The first argument (DAL) is required for the debug bar to collect queries.
13
+ - `enable(db: DAL, enabled?: bool, fancy_rendering?: bool, bar_style?: "bootstrap", slow_threshold_ms?: int)`:
14
+ activate or disable the debug tools (add the custom error screen and create the Debug Bar Fixture).
15
+ The first argument (DAL) is required for the debug bar to collect queries.
16
+ `enabled` can be used to dynamically turn on/off the debug features.
17
+ `fancy_rendering`: This will render the `data` section of the debug bar using `json-browse`, which
18
+ includes `jQuery`. If this clashes with the other JS on a page, this can be set to False to simply show a `<pre>`
19
+ block with data.
20
+ `bar_style`: only bootstrap is supported at this moment.
21
+ `slow_threshold_ms`: amount of milliseconds an SQL query has to take before it is considered a 'slow query' in the
22
+ debug bar.
15
23
  - `debug_bar`: this Fixture can be used on py4web actions to enable the bar for that page.
16
24
  - `catch(*)`: Data and a stacktrace of where `catch()` is called can be found in the catch tab of the debug bar.
17
25
  - `dump(*)`: convert objects to JSON, with a more capable converter than the default json.dumps (e.g. it works better
@@ -0,0 +1,64 @@
1
+ # Transforms janky 'internals' into easy to work with tool
2
+ import os
3
+ import typing
4
+
5
+ from py4web import DAL as P4WDAL
6
+
7
+ from .debugbar import DummyDebugBar, DebugBar
8
+ from .env import is_debug
9
+ from .internals import patch_py4
10
+
11
+
12
+ class DebugTools:
13
+ # by default, it is not enabled! This is so you can still import it on production,
14
+ # but don't actually show any debug info. enable(on_off) can be called with e.g. an ENV variable
15
+ enabled = False
16
+ db: P4WDAL
17
+ debug_bar = DummyDebugBar()
18
+ IS_DEBUG: bool = is_debug()
19
+
20
+ def enable(
21
+ self,
22
+ # general settings:
23
+ db: P4WDAL,
24
+ enabled: bool | None = None, # OVERWRITES errorpage_enabled and debugbar_enabled
25
+ set_env_var: bool = True,
26
+
27
+ # error screen settings:
28
+ errorpage_enabled: bool = None, # value of 'enabled' is used by default
29
+ errorpage_renderer: typing.Callable = None,
30
+
31
+ # debugbar settings:
32
+ debugbar_enabled: bool = None, # value of 'enabled' is used by default
33
+ debugbar_fancy_rendering: bool = True,
34
+ debugbar_style: typing.Literal["bootstrap"] = "bootstrap",
35
+ debugbar_slow_threshold_ms: int = 10,
36
+ ):
37
+ """
38
+ By default, on_off looks at PY4WEB_DEBUG_MODE in the env
39
+
40
+ @todo: debugbar style (bootstrap/default, bulma, ...)
41
+ """
42
+ if enabled is None:
43
+ enabled = is_debug()
44
+
45
+ self.db = db
46
+ self.enabled = enabled
47
+
48
+ self.IS_DEBUG = enabled
49
+ if enabled:
50
+ if errorpage_enabled in (True, None):
51
+ patch_py4(errorpage_renderer)
52
+
53
+ if debugbar_enabled in (True, None):
54
+ self.debug_bar = DebugBar(db, debugbar_fancy_rendering, debugbar_style, debugbar_slow_threshold_ms)
55
+
56
+ if set_env_var:
57
+ # will change the result of is_debug (hopefully)
58
+ os.environ["PY4WEB_DEBUG_MODE"] = "1"
59
+ else:
60
+ self.debug_bar = DummyDebugBar()
61
+
62
+
63
+ tools = DebugTools()
64
+
@@ -133,7 +133,7 @@ def debugbar_template(fixture: Fixture, debug_data: dict, fancy=True):
133
133
  T = typing.TypeVar("T")
134
134
 
135
135
 
136
- def _prune_long_values(value: T) -> T:
136
+ def _prune_long_values(value: T) -> T | str:
137
137
  """
138
138
  Find the end values in nested dicts and lists and prune them if they are too long,
139
139
  Usually (tm) returns the same type as the input (except when the input is long bytes)
@@ -146,7 +146,7 @@ def _prune_long_values(value: T) -> T:
146
146
  for key, item in value.items():
147
147
  value[key] = _prune_long_values(item)
148
148
  elif isinstance(value, str | bytes) and len(value) > 50:
149
- value = "[pruned due to length]"
149
+ return "[pruned due to length]"
150
150
 
151
151
  return value
152
152
 
@@ -104,7 +104,7 @@ class ApiDumpDieError(Exception):
104
104
  pass
105
105
 
106
106
 
107
- def dd(*data, fancy=True, api=False) -> typing.NoReturn:
107
+ def dd(*data, fancy=True, api=False):
108
108
  """
109
109
  Dump and Die:
110
110
  Show args as JSON an halt the rest of the request
@@ -5,6 +5,7 @@ import logging
5
5
  import os
6
6
  import re
7
7
  import traceback
8
+ import typing
8
9
 
9
10
  import ombott as bottle
10
11
  import yatl
@@ -27,12 +28,17 @@ def custom_error_page(
27
28
  color=None,
28
29
  message=None,
29
30
  traceback="",
30
- err_type=None,
31
+ err_type: str | typing.Type | None = None,
31
32
  bare_exception=None,
33
+
34
+ renderer=None
32
35
  ):
33
- if not isinstance(err_type, str):
36
+ if err_type and not isinstance(err_type, str):
34
37
  err_type = err_type.__name__
35
38
 
39
+ # make sure the name is a string (but it probably already is:)
40
+ err_type_name = str(err_type)
41
+
36
42
  if hasattr(Template, "_on_success"):
37
43
  # reset here on error, because on_error might not be called!
38
44
  Template.on_success = Template._on_success
@@ -60,6 +66,9 @@ def custom_error_page(
60
66
  return json.dumps(context)
61
67
  # else - return html error-page
62
68
 
69
+ if renderer:
70
+ return renderer(context)
71
+
63
72
  templates = {
64
73
  "default": "error_default.html",
65
74
  "DumpDieError": "dumpdie.html",
@@ -67,7 +76,7 @@ def custom_error_page(
67
76
  "ApiDumpDieError": None,
68
77
  }
69
78
 
70
- _tmpl = templates.get(err_type, templates["default"])
79
+ _tmpl = templates.get(err_type_name, templates["default"])
71
80
 
72
81
  if _tmpl is None:
73
82
  # just bare exception
@@ -84,44 +93,45 @@ def custom_error_page(
84
93
  )
85
94
 
86
95
 
87
- def custom_catch_errors(app_name, func):
88
- """Catches and logs errors in an action; also sets request.app_name"""
89
-
90
- @functools.wraps(func)
91
- def wrapper(*func_args, **func_kwargs):
92
- try:
93
- request.app_name = app_name
94
- ret = func(*func_args, **func_kwargs)
95
- if isinstance(ret, dict):
96
- response.headers["Content-Type"] = "application/json"
97
- ret = dumps(ret)
98
- return ret
99
- except HTTP as http:
100
- response.status = http.status
101
- response.headers.update(http.headers)
102
- return http.body
103
- except bottle.HTTPResponse:
104
- raise
105
- except Exception as e:
106
- snapshot = get_error_snapshot()
107
- logging.error(snapshot["traceback"])
108
- ticket_uuid = error_logger.log(request.app_name, snapshot) or "unknown"
109
- response.status = 500
110
-
111
- raise bottle.HTTPResponse(
112
- body=custom_error_page(
113
- 500,
114
- button_text=ticket_uuid,
115
- href="/_dashboard/ticket/" + ticket_uuid,
116
- traceback=traceback.format_exc(),
117
- err_type=type(e),
118
- bare_exception=e,
119
- ),
120
- status=500,
121
- )
122
-
123
- return wrapper
124
-
125
-
126
- def patch_py4():
96
+ def patch_py4(renderer=None):
97
+ def custom_catch_errors(app_name, func):
98
+ """Catches and logs errors in an action; also sets request.app_name"""
99
+
100
+ @functools.wraps(func)
101
+ def wrapper(*func_args, **func_kwargs):
102
+ try:
103
+ request.app_name = app_name
104
+ ret = func(*func_args, **func_kwargs)
105
+ if isinstance(ret, dict):
106
+ response.headers["Content-Type"] = "application/json"
107
+ ret = dumps(ret)
108
+ return ret
109
+ except HTTP as http:
110
+ response.status = http.status
111
+ response.headers.update(http.headers)
112
+ return http.body
113
+ except bottle.HTTPResponse:
114
+ raise
115
+ except Exception as e:
116
+ snapshot = get_error_snapshot()
117
+ logging.error(snapshot["traceback"])
118
+ ticket_uuid = error_logger.log(request.app_name, snapshot) or "unknown"
119
+ response.status = 500
120
+
121
+ raise bottle.HTTPResponse(
122
+ body=custom_error_page(
123
+ 500,
124
+ button_text=ticket_uuid,
125
+ href="/_dashboard/ticket/" + ticket_uuid,
126
+ traceback=traceback.format_exc(),
127
+ err_type=type(e),
128
+ bare_exception=e,
129
+
130
+ renderer=renderer
131
+ ),
132
+ status=500,
133
+ )
134
+
135
+ return wrapper
136
+
127
137
  action.catch_errors = custom_catch_errors
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: py4web-debug-tools
3
- Version: 0.1.1
3
+ Version: 0.2.0.dev0
4
4
  Summary: Debug Tools for py4web
5
5
  Home-page: https://github.com/trialandsuccess/py4web-debug-tools
6
6
  Author: Robin van der Noord
@@ -9,7 +9,8 @@ Requires-Python: >3.10.0
9
9
  Description-Content-Type: text/markdown
10
10
 
11
11
  # py4web debug tools
12
- Tooling to improve the developer experience when working with py4web.
12
+
13
+ Tooling to improve the developer experience when working with py4web.
13
14
 
14
15
  There are two main tools and some helpers that this package provides.
15
16
 
@@ -19,9 +20,16 @@ There are two main tools and some helpers that this package provides.
19
20
  ## In this package:
20
21
 
21
22
  - `tools`:
22
- - `enable(db: DAL, enabled: bool)`: activate or disable the debug tools (add the custom error screen and create the Debug Bar
23
- Fixture).
24
- The first argument (DAL) is required for the debug bar to collect queries.
23
+ - `enable(db: DAL, enabled?: bool, fancy_rendering?: bool, bar_style?: "bootstrap", slow_threshold_ms?: int)`:
24
+ activate or disable the debug tools (add the custom error screen and create the Debug Bar Fixture).
25
+ The first argument (DAL) is required for the debug bar to collect queries.
26
+ `enabled` can be used to dynamically turn on/off the debug features.
27
+ `fancy_rendering`: This will render the `data` section of the debug bar using `json-browse`, which
28
+ includes `jQuery`. If this clashes with the other JS on a page, this can be set to False to simply show a `<pre>`
29
+ block with data.
30
+ `bar_style`: only bootstrap is supported at this moment.
31
+ `slow_threshold_ms`: amount of milliseconds an SQL query has to take before it is considered a 'slow query' in the
32
+ debug bar.
25
33
  - `debug_bar`: this Fixture can be used on py4web actions to enable the bar for that page.
26
34
  - `catch(*)`: Data and a stacktrace of where `catch()` is called can be found in the catch tab of the debug bar.
27
35
  - `dump(*)`: convert objects to JSON, with a more capable converter than the default json.dumps (e.g. it works better
@@ -7,7 +7,7 @@ dependencies = ["py4web", "yatl", "pydal", "configurable-json"]
7
7
 
8
8
  setup(
9
9
  name="py4web-debug-tools",
10
- version="0.1.1",
10
+ version="0.2.0-dev",
11
11
  description="Debug Tools for py4web",
12
12
  author="Robin van der Noord",
13
13
  author_email="contact@trialandsuccess.nl",
@@ -1,49 +0,0 @@
1
- # Transforms janky 'internals' into easy to work with tool
2
- import os
3
-
4
- from py4web import DAL as P4WDAL
5
-
6
- from .debugbar import DummyDebugBar, DebugBar
7
- from .env import is_debug
8
- from .internals import patch_py4
9
-
10
-
11
- class DebugTools:
12
- # by default, it is not enabled! This is so you can still import it on production,
13
- # but don't actually show any debug info. enable(on_off) can be called with e.g. an ENV variable
14
- enabled = False
15
- db: P4WDAL
16
- debug_bar = DummyDebugBar()
17
- IS_DEBUG: bool = is_debug()
18
-
19
- def enable(
20
- self,
21
- db: P4WDAL,
22
- enabled: bool = None,
23
- fancy_rendering=True,
24
- bar_style="bootstrap",
25
- slow_threshold_ms=10,
26
- ):
27
- """
28
- By default, on_off looks at PY4WEB_DEBUG_MODE in the env
29
-
30
- @todo: debugbar style (bootstrap/default, bulma, ...)
31
- """
32
- if enabled is None:
33
- enabled = os.getenv("PY4WEB_DEBUG_MODE", False)
34
-
35
- self.db = db
36
- self.enabled = enabled
37
-
38
- self.IS_DEBUG = enabled
39
- if enabled:
40
- patch_py4()
41
- self.debug_bar = DebugBar(db, fancy_rendering, bar_style, slow_threshold_ms)
42
-
43
- # will change the result of is_debug (hopefully)
44
- os.environ["PY4WEB_DEBUG_MODE"] = "1"
45
- else:
46
- self.debug_bar = DummyDebugBar()
47
-
48
-
49
- tools = DebugTools()