Skip to content

Commit

Permalink
v 2.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Andy Landy committed Feb 19, 2025
1 parent 5e3a561 commit a6b0149
Show file tree
Hide file tree
Showing 572 changed files with 1,923 additions and 454 deletions.
35 changes: 25 additions & 10 deletions .github/workflows/dev-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,32 @@ on:
- '*'
jobs:
tests:
runs-on: ${{ matrix.os }}
runs-on: ${{ matrix.arrays.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
# 3.13 not available yet somehow
# 3.7 has issues with multiline expressions
# 3.6- not found for ubuntu-latest
python-version: [3.8, 3.9, '3.10', 3.11, 3.12]
arrays: [
# {os: ubuntu-22.04, python-version: '3.7.17'}, # multiline code is depicted differently
{os: ubuntu-22.04, python-version: '3.8'},
{os: ubuntu-22.04, python-version: '3.9'},
{os: ubuntu-22.04, python-version: '3.10'},
{os: ubuntu-22.04, python-version: '3.11'},
{os: ubuntu-22.04, python-version: '3.12'},
{os: ubuntu-22.04, python-version: '3.13'},
# {os: ubuntu-22.04, python-version: '3.14.0-alpha.5'}, # too early
# {os: windows-latest, python-version: '3.7.9'}, # multiline code is depicted differently
{os: windows-latest, python-version: '3.8'},
{os: windows-latest, python-version: '3.9'},
{os: windows-latest, python-version: '3.10'},
{os: windows-latest, python-version: '3.11'},
{os: windows-latest, python-version: '3.12'},
{os: windows-latest, python-version: '3.13'}
# {os: windows-latest, python-version: '3.14.0-alpha.5'} # too early
]
steps:
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
- name: Set up Python ${{ matrix.arrays.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
python-version: ${{ matrix.arrays.python-version }}

- name: Install dependencies
run: |
Expand All @@ -35,13 +48,15 @@ jobs:
flake8 traceback_with_variables --count --show-source --statistics --max-line-length=127
- name: Test with pytest
env:
PYTHONHASHSEED: 1
run: |
python -Xfrozen_modules=off -m pytest -vv --cov=traceback_with_variables --cov-report=json
- name: Upload coverage report
uses: actions/upload-artifact@v4
with:
name: coverage-${{ matrix.os }}-${{ matrix.python-version }}
name: coverage-${{ matrix.arrays.os }}-${{ matrix.arrays.python-version }}
path: coverage.json

coverage:
Expand Down
35 changes: 25 additions & 10 deletions .github/workflows/master-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,32 @@ on:
- 'master'
jobs:
tests:
runs-on: ${{ matrix.os }}
runs-on: ${{ matrix.arrays.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
# 3.13 not available yet somehow
# 3.7 has issues with multiline expressions
# 3.6- not found for ubuntu-latest
python-version: [3.8, 3.9, '3.10', 3.11, 3.12]
arrays: [
# {os: ubuntu-22.04, python-version: '3.7.17'}, # multiline code is depicted differently
{os: ubuntu-22.04, python-version: '3.8'},
{os: ubuntu-22.04, python-version: '3.9'},
{os: ubuntu-22.04, python-version: '3.10'},
{os: ubuntu-22.04, python-version: '3.11'},
{os: ubuntu-22.04, python-version: '3.12'},
{os: ubuntu-22.04, python-version: '3.13'},
# {os: ubuntu-22.04, python-version: '3.14.0-alpha.5'}, # too early
# {os: windows-latest, python-version: '3.7.9'}, # multiline code is depicted differently
{os: windows-latest, python-version: '3.8'},
{os: windows-latest, python-version: '3.9'},
{os: windows-latest, python-version: '3.10'},
{os: windows-latest, python-version: '3.11'},
{os: windows-latest, python-version: '3.12'},
{os: windows-latest, python-version: '3.13'}
# {os: windows-latest, python-version: '3.14.0-alpha.5'} # too early
]
steps:
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
- name: Set up Python ${{ matrix.arrays.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
python-version: ${{ matrix.arrays.python-version }}

- name: Install dependencies
run: |
Expand All @@ -35,13 +48,15 @@ jobs:
flake8 traceback_with_variables --count --show-source --statistics --max-line-length=127
- name: Test with pytest
env:
PYTHONHASHSEED: 1
run: |
python -Xfrozen_modules=off -m pytest -vv --cov=traceback_with_variables --cov-report=json
- name: Upload coverage report
uses: actions/upload-artifact@v4
with:
name: coverage-${{ matrix.os }}-${{ matrix.python-version }}
name: coverage-${{ matrix.arrays.os }}-${{ matrix.arrays.python-version }}
path: coverage.json

coverage:
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## 2.2.0
- Fully compatible with 2.1.1
- (BIG) Huge collections are printed faster, time depends only on `max_value_str_len`
- Add `hide`, `skip`, `show` as standard prints
- Variables like `password` and `token` are now hidden by default
- Added warning about secrets to readme, an example code to deal with it and a short essay
- Tested in python 3.13 and python 3.7
- More test cases and data types
- All objects without custom `__str__` are printed with all attrs
- Standard backup tracebacks have this library stacks collapsed

## 2.1.1
- Add "tb" alias creation for lines like `import tb.a`

Expand Down
25 changes: 18 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
![Example](https://raw.githubusercontent.com/andy-landy/traceback_with_variables/master/header.png)

<h2 align="center">Python Traceback (Error Message) Printing Variables</h2>
<p align="center">Very simple to use, but versatile when needed. Try for debug and keep for production.</p>
<p align="center">Very simple to use and fast, but versatile when needed. Try for debug and keep for small-scale production.</p>

<p align="center">
<a href="https://github.com/andy-landy/traceback_with_variables/actions"><img alt="Actions Status" src="https://github.com/andy-landy/traceback_with_variables/workflows/tests/badge.svg"></a>
Expand Down Expand Up @@ -47,7 +47,7 @@ _Contents:_ **[Installation](#installation)** | **[🚀 Quick Start](#-quick-sta
### Installation

```
pip install traceback-with-variables==2.1.1
pip install traceback-with-variables==2.2.0
```
```
conda install -c conda-forge traceback-with-variables
Expand Down Expand Up @@ -109,11 +109,12 @@ Using a logger [<a href="https://github.com/andy-landy/traceback_with_variables/

<a href="https://github.com/andy-landy/traceback_with_variables/tree/master/examples/format_customized.py">Customize</a> any of the previous examples:
```python
from traceback_with_variables import fmt
fmt.max_value_str_len = 10000
fmt.skip_files_except = 'my_project'
fmt.custom_var_printers = [] # show all variables, no skips, no hides
```


### Colors

![Example](https://raw.githubusercontent.com/andy-landy/traceback_with_variables/master/color_schemes.png)
Expand Down Expand Up @@ -247,8 +248,8 @@ Using a logger [<a href="https://github.com/andy-landy/traceback_with_variables/

* — Should I use it after debugging is over, i.e. *in production*?

Yes, of course! That way it might save you even more time (watch out for sensitive data
like passwords and tokens in you logs, use skip_files_except to hide code from libs AND custom_var_printers to hide own locals). Note: you can deploy more serious frameworks, e.g. `Sentry`
Yes, of course! That way it might save you even more time (<a href="https://github.com/andy-landy/traceback_with_variables/tree/master/examples/secret_data.py">watch out</a> for sensitive data
like 🔴**passwords** and **tokens** in you logs). Note: you can deploy more serious monitoring frameworks, e.g. `Sentry`

<br/>

Expand All @@ -261,7 +262,16 @@ Using a logger [<a href="https://github.com/andy-landy/traceback_with_variables/
step 5: Examine the printouts and possibly add some more info (then go back to step 2). \
step 6: Erase all recently added printouts, logging and exception messages. \
step 7: Go back to step 1 once bugs appear.



* — Is it slow? I have huge lists and dicts and data objects!

Data size doesn't matter! Printing is smart, so only the resulting suffix and prefix are generated, e.g.

`list(range(100000000))` becomes just `"[0, 1, 2, ...9998, 99999999]"` in 0.00012s

Use `fmt`'s `.max_value_str_len`, and `.ellipsis_rel_pos` (0.0 to 1.0) to tweak the output.


### Examples and recipes

Expand All @@ -279,6 +289,7 @@ Using a logger [<a href="https://github.com/andy-landy/traceback_with_variables/
* <a href="https://github.com/andy-landy/traceback_with_variables/tree/master/examples/work_with_traceback_lines.py">get traceback lines for custom things</a>
* <a href="https://github.com/andy-landy/traceback_with_variables/tree/master/examples/flask.py">using with `flask`</a>
* <a href="https://github.com/andy-landy/traceback_with_variables/tree/master/examples/format_customized.py">customize the output</a>
* <a href="https://github.com/andy-landy/traceback_with_variables/tree/master/examples/secret_data.py">passwords and tokens in logs</a>

### Reference

Expand All @@ -292,7 +303,7 @@ Using a logger [<a href="https://github.com/andy-landy/traceback_with_variables/
* `ellipsis_` string to denote long strings truncation, default=`...`
* `skip_files_except` use to print only certain files; list of regexes, ignored if empty, default=None
* `brief_files_except` use to print variables only in certain files; list of regexes, ignored if empty, default=None
* `custom_var_printers` list of pairs of (filter, printer); filter is a name fragment, a type or a function or a list thereof; printer returns `None` to skip a var
* `custom_var_printers` list of pairs of (filter, printer); filter is a name fragment, a type or a function or a list thereof; printer returns `None` to skip a var, standard ones are `hide`, `skip`, `show`
* `color_scheme` is `None` or one of <a href="https://github.com/andy-landy/traceback_with_variables/tree/master/traceback_with_variables/color.py">`ColorSchemes`</a>: `.none` , `.common`, `.nice`, `.synthwave`. `None` is for auto-detect

---
Expand Down
23 changes: 17 additions & 6 deletions README.tmpl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
![Example]({{ content_url }}/header.png)

<h2 align="center">Python Traceback (Error Message) Printing Variables</h2>
<p align="center">Very simple to use, but versatile when needed. Try for debug and keep for production.</p>
<p align="center">Very simple to use and fast, but versatile when needed. Try for debug and keep for small-scale production.</p>

<p align="center">
<a href="{{ repo_url }}/actions"><img alt="Actions Status" src="{{ repo_url }}/workflows/tests/badge.svg"></a>
Expand Down Expand Up @@ -109,11 +109,12 @@ Using a logger [<a href="{{ examples_code_url }}/log_for_function.py">with a dec

<a href="{{ examples_code_url }}/format_customized.py">Customize</a> any of the previous examples:
```python
from traceback_with_variables import fmt
fmt.max_value_str_len = 10000
fmt.skip_files_except = 'my_project'
fmt.custom_var_printers = [] # show all variables, no skips, no hides
```


### Colors

![Example]({{ content_url }}/color_schemes.png)
Expand Down Expand Up @@ -247,8 +248,8 @@ Using a logger [<a href="{{ examples_code_url }}/log_for_function.py">with a dec

* — Should I use it after debugging is over, i.e. *in production*?

Yes, of course! That way it might save you even more time (watch out for sensitive data
like passwords and tokens in you logs, use skip_files_except to hide code from libs AND custom_var_printers to hide own locals). Note: you can deploy more serious frameworks, e.g. `Sentry`
Yes, of course! That way it might save you even more time (<a href="{{ examples_code_url }}/secret_data.py">watch out</a> for sensitive data
like 🔴**passwords** and **tokens** in you logs). Note: you can deploy more serious monitoring frameworks, e.g. `Sentry`

<br/>

Expand All @@ -261,7 +262,16 @@ Using a logger [<a href="{{ examples_code_url }}/log_for_function.py">with a dec
step 5: Examine the printouts and possibly add some more info (then go back to step 2). \
step 6: Erase all recently added printouts, logging and exception messages. \
step 7: Go back to step 1 once bugs appear.



* — Is it slow? I have huge lists and dicts and data objects!

Data size doesn't matter! Printing is smart, so only the resulting suffix and prefix are generated, e.g.

`list(range(100000000))` becomes just `"[0, 1, 2, ...9998, 99999999]"` in 0.00012s

Use `fmt`'s `.max_value_str_len`, and `.ellipsis_rel_pos` (0.0 to 1.0) to tweak the output.


### Examples and recipes

Expand All @@ -279,6 +289,7 @@ Using a logger [<a href="{{ examples_code_url }}/log_for_function.py">with a dec
* <a href="{{ examples_code_url }}/work_with_traceback_lines.py">get traceback lines for custom things</a>
* <a href="{{ examples_code_url }}/flask.py">using with `flask`</a>
* <a href="{{ examples_code_url }}/format_customized.py">customize the output</a>
* <a href="{{ examples_code_url }}/secret_data.py">passwords and tokens in logs</a>

### Reference

Expand All @@ -292,7 +303,7 @@ Using a logger [<a href="{{ examples_code_url }}/log_for_function.py">with a dec
* `ellipsis_` string to denote long strings truncation, default=`...`
* `skip_files_except` use to print only certain files; list of regexes, ignored if empty, default=None
* `brief_files_except` use to print variables only in certain files; list of regexes, ignored if empty, default=None
* `custom_var_printers` list of pairs of (filter, printer); filter is a name fragment, a type or a function or a list thereof; printer returns `None` to skip a var
* `custom_var_printers` list of pairs of (filter, printer); filter is a name fragment, a type or a function or a list thereof; printer returns `None` to skip a var, standard ones are `hide`, `skip`, `show`
* `color_scheme` is `None` or one of <a href="{{ lib_code_url }}/color.py">`ColorSchemes`</a>: `.none` , `.common`, `.nice`, `.synthwave`. `None` is for auto-detect

---
Expand Down
20 changes: 12 additions & 8 deletions examples/format_customized.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
from traceback_with_variables import Format, ColorSchemes, is_ipython_global, fmt
from traceback_with_variables import Format, ColorSchemes, is_ipython_global, fmt, hide, skip


# approach 1
# approach 1 for simples usage

fmt.max_value_str_len = 10000

# show all vars, no hides, no skips:

# approach 2
fmt.custom_var_printers = []


# approach 2 for explicit format passing

fmt2 = Format(
before=3,
Expand All @@ -20,17 +24,17 @@
skip_files_except=['my_project', 'site-packages'],
brief_files_except='my_project',
custom_var_printers=[ # first matching is used
('password', lambda v: '...hidden...'), # by name, print const str
('password', hide), # by name, print const str
(list, lambda v: f'list{v}'), # by type, print fancy str
(lambda name, type_, filename, is_global: is_global, lambda v: None), # custom filter, skip printing
(lambda name, type_, filename, is_global: is_global, skip), # custom filter, skip printing
(is_ipython_global, lambda v: None), # same, handy for Jupyter
(['secret', dict, (lambda name, *_: 'asd' in name)], lambda v: '???'), # by different things, print const str
]
)
# print_exc(fmt=fmt2)
print_exc(fmt=fmt2)


# approach 3
# approach 3 for explicit format passing, less code

fmt3 = defaults.replace(max_value_str_len=10000)
# print_exc(fmt=fmt3)
print_exc(fmt=fmt3)
50 changes: 50 additions & 0 deletions examples/secret_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""
When you deal with secrets like passwords or tokens any debug report system
puts you at risk of exposing those secrets.
Why? Some secrets are stored securely in databases and are kept decrypted only
for short time in memory while being used in code. So any traceback printout
will save them explicitly for you to read later.
Its not a huge problem if the secret is stored unencrypted, i.e. its your
(not users') secret and the machine is secure. User passwords are a problem.
How to prevent secret vars from being printed? You might
* correctly guess how the secret variables in your code are called
* hide the 3rd party well-established library code totally
It will look like this: some of variables in your code will have
"...hidden..." values, and all library files (where secret variables might go
with unrelated names like "s", "part", "msg" etc.) will be skipped totally.
Default settings include all frequent patterns for your variables:
PATTERN_TO_HIDE = '.*(?i:pass|secret|token|key|api_key|cred|pwd).*'
Which will hide a bit too much, names like "keyword" or "compassion". Address
examples below to fit the hiding.
To hide libraries address examples below, note that you can only allow code,
not deny it, so all 3rd party libraries will be hidden if you use this
setting.
"""

# simple tools usage, for more manual approach address format_customized.py

from traceback_with_variables import fmt, hide


# hide all libraries except couple

fmt.brief_files_except = ['.*my_project.*', '.*some_library_1.*', '.*some_library_2.*']


# show all variables

fmt.custom_var_printers = []


# hide variables differently

fmt.custom_var_printers = [
('.*(precious|ring).*', hide), # by name
(MySecret, hide), # by class
]
Loading

0 comments on commit a6b0149

Please sign in to comment.