Skip to content

Commit

Permalink
v 2.1.1
Browse files Browse the repository at this point in the history
  • Loading branch information
Andy Landy committed Nov 19, 2024
1 parent 559b943 commit 5e3a561
Show file tree
Hide file tree
Showing 26 changed files with 290 additions and 70 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/dev-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
- name: Test with pytest
run: |
python -m pytest -vv --cov=traceback_with_variables --cov-report=json
python -Xfrozen_modules=off -m pytest -vv --cov=traceback_with_variables --cov-report=json
- name: Upload coverage report
uses: actions/upload-artifact@v4
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/master-test.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Dev-Tests
name: tests
on:
pull_request:
branches:
Expand Down Expand Up @@ -36,7 +36,7 @@ jobs:
- name: Test with pytest
run: |
python -m pytest -vv --cov=traceback_with_variables --cov-report=json
python -Xfrozen_modules=off -m pytest -vv --cov=traceback_with_variables --cov-report=json
- name: Upload coverage report
uses: actions/upload-artifact@v4
Expand Down
16 changes: 13 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
# Changelog

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

## 2.1.0
- Fully compatible with 2.0.4
- Add short names for frequently used things like `a` and `fmt`
- Fixed some bugs
- Add unified `activate_by_import` to be used both for Jupyter and regular Python
- Add relative ellipsis position for strings like `x=['some', ...long', 'list']`
- Add detailed object printout, useful for non-dataclass classes
- Add protection against acidental mistyping in format attributes
- Fixed some bugs, e.g.
- cli not working in Python 3.12+
- `default_format` being sometimes ignored

## 2.0.4
- ...
- ...much, to be filled...

## 2.0.3
- Fixed tests in Windows/Mac
Expand Down
25 changes: 14 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<p align="center">Very simple to use, but versatile when needed. Try for debug and keep for 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>
<a href="https://github.com/andy-landy/traceback_with_variables/blob/master/.github/workflows/dev-test.yml#L59"><img title="code tests coverage is 100%" alt="code tests coverage is 100%" src="https://img.shields.io/badge/coverage-100%25-brightgreen.svg"></a>
<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>
<a href="https://github.com/andy-landy/traceback_with_variables/blob/master/.github/workflows/master-test.yml#L59"><img title="code tests coverage is 100%" alt="code tests coverage is 100%" src="https://img.shields.io/badge/coverage-100%25-brightgreen.svg"></a>
<a href="https://github.com/andy-landy/traceback_with_variables/tree/master/LICENSE"><img alt="License: MIT" src="https://img.shields.io/github/license/andy-landy/traceback_with_variables?color=informational"></a>
<a href="https://pepy.tech/project/traceback-with-variables"><img alt="Downloads" src="https://static.pepy.tech/badge/traceback-with-variables"></a>
<a href="https://pypi.org/project/traceback-with-variables"><img alt="PyPI" src="https://img.shields.io/pypi/v/traceback-with-variables"></a>
Expand Down Expand Up @@ -40,17 +40,22 @@ _Contents:_ **[Installation](#installation)** | **[🚀 Quick Start](#-quick-sta

---

> :warning: **This module is actively updated and has a substantial list of features to add this week**: so any proposal or advice or warning is very welcome and will be taken into account of course. When I started it I wanted to make a tool meeting all standard use cases. I think in this particular domain this is rather achievable, so I'll try. Note `next_version` branch also. Have fun!
> :warning: **I'm open to update this module to meet new use cases and to make using it easier and fun**: so any proposal or advice or warning is very welcome and will be taken into account of course. When I started it I wanted to make a tool meeting all standard use cases. I think in this particular domain this is rather achievable, so I'll try. Note `next_version` branch also. Have fun!
---

### Installation

```
pip install traceback-with-variables==2.1.0
pip install traceback-with-variables==2.1.1
```
```
conda install -c conda-forge traceback-with-variables=2.1.0
conda install -c conda-forge traceback-with-variables
```

to use shorter `tb` alias in interactive mode call this once:
```
python3 -c 'from traceback_with_variables.tb_alias import create_tb_alias as c; c()'
```

### 🚀 Quick Start
Expand All @@ -60,17 +65,15 @@ Using without code editing, <a href="https://github.com/andy-landy/traceback_wit
traceback-with-variables tested_script.py ...srcipt's args...
```

<a href="https://github.com/andy-landy/traceback_with_variables/tree/master/examples/simple.py">Simplest usage in regular Python</a>, for the whole program:
<a href="https://github.com/andy-landy/traceback_with_variables/tree/master/examples/simple.py">Simplest usage</a>, for the whole program:
```python
from traceback_with_variables import activate_by_import
```

<a href="https://github.com/andy-landy/traceback_with_variables/tree/master/examples/simple_jupyter.py">Simplest usage in Jupyter or IPython</a>, for the whole program:
or just (if you added an alias by the above command)
```python
from traceback_with_variables import activate_in_ipython_by_import
import tb.a
```


<a href="https://github.com/andy-landy/traceback_with_variables/tree/master/examples/print_for_function.py">Decorator</a>, for a single function:
```python
@prints_exc
Expand Down Expand Up @@ -238,7 +241,7 @@ Using a logger [<a href="https://github.com/andy-landy/traceback_with_variables/
is_vegan = not (eggs or milk)
is_huge = (sugar + eggs + milk + flour + salt + water > 10000)
if not (is_sweet or is_vegan or is_huge):
raise ValueError('This is unacceptable, guess why!')
raise ValueError('This is unacceptable, look why!')
...
```

Expand Down
23 changes: 13 additions & 10 deletions README.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<p align="center">Very simple to use, but versatile when needed. Try for debug and keep for production.</p>

<p align="center">
<a href="{{ repo_url }}/actions"><img alt="Actions Status" src="{{ repo_url }}/workflows/Tests/badge.svg"></a>
<a href="{{ repo_url }}/blob/master/.github/workflows/dev-test.yml#L59"><img title="code tests coverage is 100%" alt="code tests coverage is 100%" src="https://img.shields.io/badge/coverage-100%25-brightgreen.svg"></a>
<a href="{{ repo_url }}/actions"><img alt="Actions Status" src="{{ repo_url }}/workflows/tests/badge.svg"></a>
<a href="{{ repo_url }}/blob/master/.github/workflows/master-test.yml#L59"><img title="code tests coverage is 100%" alt="code tests coverage is 100%" src="https://img.shields.io/badge/coverage-100%25-brightgreen.svg"></a>
<a href="{{ code_url }}/LICENSE"><img alt="License: MIT" src="https://img.shields.io/github/license/{{ user_repo_name }}?color=informational"></a>
<a href="https://pepy.tech/project/traceback-with-variables"><img alt="Downloads" src="https://static.pepy.tech/badge/traceback-with-variables"></a>
<a href="{{ pypi_url }}"><img alt="PyPI" src="https://img.shields.io/pypi/v/{{ package_name }}"></a>
Expand Down Expand Up @@ -40,7 +40,7 @@ _Contents:_ **[Installation](#installation)** | **[🚀 Quick Start](#-quick-sta

---

> :warning: **This module is actively updated and has a substantial list of features to add this week**: so any proposal or advice or warning is very welcome and will be taken into account of course. When I started it I wanted to make a tool meeting all standard use cases. I think in this particular domain this is rather achievable, so I'll try. Note `next_version` branch also. Have fun!
> :warning: **I'm open to update this module to meet new use cases and to make using it easier and fun**: so any proposal or advice or warning is very welcome and will be taken into account of course. When I started it I wanted to make a tool meeting all standard use cases. I think in this particular domain this is rather achievable, so I'll try. Note `next_version` branch also. Have fun!

---

Expand All @@ -50,7 +50,12 @@ _Contents:_ **[Installation](#installation)** | **[🚀 Quick Start](#-quick-sta
pip install traceback-with-variables=={{ version }}
```
```
conda install -c conda-forge traceback-with-variables={{ version }}
conda install -c conda-forge traceback-with-variables
```

to use shorter `tb` alias in interactive mode call this once:
```
python3 -c 'from traceback_with_variables.tb_alias import create_tb_alias as c; c()'
```

### 🚀 Quick Start
Expand All @@ -60,17 +65,15 @@ Using without code editing, <a href="{{ examples_code_url }}/external_script.sh"
traceback-with-variables tested_script.py ...srcipt's args...
```

<a href="{{ examples_code_url }}/simple.py">Simplest usage in regular Python</a>, for the whole program:
<a href="{{ examples_code_url }}/simple.py">Simplest usage</a>, for the whole program:
```python
from {{ import_name }} import activate_by_import
```

<a href="{{ examples_code_url }}/simple_jupyter.py">Simplest usage in Jupyter or IPython</a>, for the whole program:
or just (if you added an alias by the above command)
```python
from {{ import_name }} import activate_in_ipython_by_import
import tb.a
```


<a href="{{ examples_code_url }}/print_for_function.py">Decorator</a>, for a single function:
```python
@prints_exc
Expand Down Expand Up @@ -238,7 +241,7 @@ Using a logger [<a href="{{ examples_code_url }}/log_for_function.py">with a dec
is_vegan = not (eggs or milk)
is_huge = (sugar + eggs + milk + flour + salt + water > 10000)
if not (is_sweet or is_vegan or is_huge):
raise ValueError('This is unacceptable, guess why!')
raise ValueError('This is unacceptable, look why!')
...
```

Expand Down
2 changes: 2 additions & 0 deletions examples/simple.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from traceback_with_variables import a # , fmt
# or
from traceback_with_variables import activate_by_import # , fmt
# or (if you added the "tb" alias)
import tb.a


# fmt.max_value_str_len = 10000
Expand Down
23 changes: 22 additions & 1 deletion examples/simple_jupyter.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,23 @@
from traceback_with_variables import a

# or just
# import tb.a
# if you created the tb alias

# or
# from traceback_with_variables import activate_by_import
# if you prefer better names

n = 0
1/0





"""How to install in Colab etc."""

!pip install traceback-with-variables
from traceback_with_variables import activate_in_ipython_by_import
# add this to use "tb" alias for the package
from tracaback_with_variables import create_tb_alias
create_tb_alias()
7 changes: 4 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
'rollable. Debug reasons of exceptions by logging or pretty printing color'
'ful variable contexts for each frame in a stacktrace, showing every value'
'. Dump locals environments after errors to console, files, and loggers. W'
'orks with Jupiter and IPython.',
'orks with Jupyter and IPython.',
long_description=long_description,
long_description_content_type="text/markdown",
url='https://github.com/andy-landy/traceback_with_variables',
Expand All @@ -23,7 +23,7 @@
'variables', 'python3', 'stacktrace', 'arguments', 'errors',
'error-handling', 'dump', 'exception-handling', 'exceptions',
'pretty', 'pretty-print', 'frame', 'simple',
'colors', 'jupyer', 'jupyer-notebook', 'ipython', 'customize'],
'colors', 'jupyter', 'jupyter-notebook', 'ipython', 'customize'],
classifiers=[
'Programming Language :: Python :: 3',
'License :: OSI Approved :: MIT License',
Expand All @@ -38,7 +38,8 @@
tests_require=[
'flake8',
'ipython',
'pytest-cov'
'pytest-cov',
'notebook==6.2.0',
],
install_requires=[],
python_requires='>=3.6',
Expand Down
4 changes: 2 additions & 2 deletions tests/dumps/test_core.after_100_.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ Traceback with variables (most recent call last):
. fmt.skip_files_except = []
. fmt.brief_files_except = []
. fmt.custom_var_printers = []
. with pytest.raises(AttributeError):
. with pytest.raises(AttributeError) as e:
. fmt.max_val_str_len = 1
. assert str(e.value) == "'Format' object has no attribute 'max_val_str_len'"
.
.
. def test_default(check):
Expand Down Expand Up @@ -88,7 +89,6 @@ Traceback with variables (most recent call last):
. def test_objects_details(tb_reg, obj, objects_details):
. try:
. 1/0
. except:
kwargs = {'fmt': <traceback_with_variables.core.Format object at 0x...omitted for tests only...>}
tb_reg = <bound method Reg.match_tb_text of <tests.test_utils.Reg object at 0x...omitted for tests only...>>
File "...omitted for tests only.../dummies.py", line...omitted for tests only..., in f
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Traceback (most recent call last):
File "...omitted for tests only.../code.py", line...omitted for tests only..., in <module>
from traceback_with_variables import activate_in_ipython_by_import
File "...omitted for tests only.../activate_in_ipython_by_import.py", line...omitted for tests only..., in <module>
default_global_print_exc_in_ipython()
File "...omitted for tests only.../default_global_hooks.py", line...omitted for tests only..., in default_global_print_exc_in_ipython
global_print_exc_in_ipython()
File "...omitted for tests only.../global_hooks.py", line...omitted for tests only..., in global_print_exc_in_ipython
raise ValueError("IPython not found")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Traceback (most recent call last):
File "...omitted for tests only.../code.py", line...omitted for tests only..., in <module>
import tb.a
ModuleNotFoundError: No module named 'tb'
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Traceback (most recent call last):
File "...omitted for tests only.../code.py", line...omitted for tests only..., in <module>
import tb.a
ModuleNotFoundError: No module named 'tb'
29 changes: 29 additions & 0 deletions tests/dumps/test_tb_alias.create_and_rm_tb_alias.run_with_tb.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
Traceback with variables (most recent call last):
File "...omitted for tests only.../code.py", line...omitted for tests only..., in <module>
f()
...skipped... 13 vars
File "...omitted for tests only.../code.py", line...omitted for tests only..., in f
return f(
n = 10001
s1 = 'short string with n: 10001'
l1 = 'long string with 0..n: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 1...9951, 9952, 9953, 9954, 9955, 9956, 9957, 9958, 9959, 9960, 9961, 9962, 9963, 9964, 9965, 9966, 9967, 9968, 9969, 9970, 9971, 9972, 9973, 9974, 9975, 9976, 9977, 9978, 9979, 9980, 9981, 9982, 9983, 9984, 9985, 9986, 9987, 9988, 9989, 9990, 9991, 9992, 9993, 9994, 9995, 9996, 9997, 9998, 9999, 10000'
us = <exception while printing> Traceback (most recent call last):
File "...omitted for tests only.../core.py", line...omitted for tests only..., in _to_cropped_str
raw = print_(obj)
File "...omitted for tests only.../code.py", line...omitted for tests only..., in __repr__
raise ValueError("please don't print me")
ValueError: please don't print me

File "...omitted for tests only.../code.py", line...omitted for tests only..., in f
return 1 // (n * 0)
n = 10000
s1 = 'short string with n: 10000'
l1 = 'long string with 0..n: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 1... 9950, 9951, 9952, 9953, 9954, 9955, 9956, 9957, 9958, 9959, 9960, 9961, 9962, 9963, 9964, 9965, 9966, 9967, 9968, 9969, 9970, 9971, 9972, 9973, 9974, 9975, 9976, 9977, 9978, 9979, 9980, 9981, 9982, 9983, 9984, 9985, 9986, 9987, 9988, 9989, 9990, 9991, 9992, 9993, 9994, 9995, 9996, 9997, 9998, 9999'
us = <exception while printing> Traceback (most recent call last):
File "...omitted for tests only.../core.py", line...omitted for tests only..., in _to_cropped_str
raw = print_(obj)
File "...omitted for tests only.../code.py", line...omitted for tests only..., in __repr__
raise ValueError("please don't print me")
ValueError: please don't print me

builtins.ZeroDivisionError: integer division or modulo by zero
3 changes: 2 additions & 1 deletion tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,9 @@ def test_setattr():
fmt.skip_files_except = []
fmt.brief_files_except = []
fmt.custom_var_printers = []
with pytest.raises(AttributeError):
with pytest.raises(AttributeError) as e:
fmt.max_val_str_len = 1
assert str(e.value) == "'Format' object has no attribute 'max_val_str_len'"


def test_default(check):
Expand Down
73 changes: 73 additions & 0 deletions tests/test_module_alias.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import os

import pytest

import traceback_with_variables as twv
from traceback_with_variables.module_alias import create_alias, rm_alias, module_name_to_path, Path


ROOT_PATH = Path(twv.__file__).parent.parent
TWV = 'traceback_with_variables'
OS = 'os'
ALIAS = 'alias'


def test_module_name_to_path():
assert module_name_to_path(OS) == Path(os.__file__)
assert module_name_to_path(TWV) == ROOT_PATH / TWV
with pytest.raises(ModuleNotFoundError):
module_name_to_path('nonexistant_module')


def test_create_and_rm_alias():
# problems before we have the alias

with pytest.raises(ValueError) as e:
create_alias('', TWV)
assert str(e.value) == 'the alias must be non-empty'

with pytest.raises(ValueError) as e:
create_alias('bad name', TWV)
assert str(e.value) == 'the alias must have only ascii lowecases, digits and underscores'

with pytest.raises(ModuleNotFoundError):
create_alias(ALIAS, 'nonexistant_module')

with pytest.raises(ValueError) as e:
create_alias(OS, TWV)
assert str(e.value) == 'a module with the alias name already exists'

with pytest.raises(ModuleNotFoundError):
rm_alias(ALIAS)

with pytest.raises(ValueError) as e:
rm_alias(TWV)

assert str(e.value) == 'the module is not an alias'

create_alias(ALIAS, TWV)

# problems once we have the alias

with pytest.raises(ValueError) as e:
create_alias(ALIAS, TWV)
assert str(e.value) == 'a module with the alias name already exists'

with pytest.raises(ValueError) as e:
create_alias(ALIAS, OS)
assert str(e.value) == 'a module with the alias name already exists'

rm_alias(ALIAS)

# problems after we rm the alias

with pytest.raises(ModuleNotFoundError):
rm_alias(ALIAS)

# rare case of garbage in the lib dir

os.symlink(str(ROOT_PATH / 'nonexistant'), str(ROOT_PATH / ALIAS))
with pytest.raises(ValueError) as e:
create_alias(ALIAS, TWV)
assert str(e.value) == 'the needed file system location already occupied'
os.remove(str(ROOT_PATH / ALIAS))
Loading

0 comments on commit 5e3a561

Please sign in to comment.