# ArrayDebug
[](https://pypi.python.org/pypi/arraydebug)

[](https://pyup.io/repos/github/liqimai/arraydebug/)
[](https://img.shields.io/pypi/pyversions/arraydebug)
<!-- [](https://arraydebug.readthedocs.io/en/latest/?version=latest) -->
ArrayDebug generates human-friendly debug information for array-like
objects.
- Free software: MIT license
- Support python 3.6+
<!-- - Documentation: <https://arraydebug.readthedocs.io>. -->
## Installation
```shell
$ pip install arraydebug
```
## Get Started
All you need is to `import arraydebug` __after__ numpy, torch, pandas, etc.
```python
import numpy as np
import torch
import pandas as pd
...
import arraydebug # import at last
```
Then you will get information of the array-like object shown in the debugger, like:
```
<Tensor: shape=(6, 4), dtype=float32, device='cpu', requires_grad=True>
```
It works with all debuggers which rely on `repr` function to display variable information.
- VSCode
- IPython
- pdb
- etc.
<!-- TODO: add PyCharm support -->
### VSCode

### IPython
```python
In [1]: import torch
In [2]: import arraydebug
In [3]: torch.ones(6, 4, requires_grad=True)
Out[3]:
<Tensor: shape=(6, 4), dtype=float32, device='cpu', requires_grad=True>
tensor([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]], requires_grad=True)
```
### pdb
```shell
$ python -m pdb examples/example.py
...
...
...
(Pdb) tensor
<Tensor: shape=(6, 4), dtype=float32, device='cpu', requires_grad=True>
tensor([[0.0833, 0.2675, 0.4372, 0.5344],
[0.9977, 0.6844, 0.1404, 0.2646],
[0.7211, 0.7529, 0.1239, 0.2511],
[0.1717, 0.6611, 0.6598, 0.9705],
[0.5230, 0.3439, 0.0459, 0.9937],
[0.8603, 0.6598, 0.0652, 0.1235]], requires_grad=True)
```
<!-- <pre>
<code><span style="color:green">In [1]:</span><span class="pl-k">import</span> torch
<span style="color:green">In [2]:</span><span class="pl-k">import</span> arraydebug
<span style="color:green">In [3]:</span>torch.ones(6, 4, requires_grad=True)
<span style="color:red">Out[3]:</span>
<Tensor: shape=(6, 4), dtype=float32, device='cpu', requires_grad=True>
tensor([[<span class="pl-c1">1.</span>, 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]], requires_grad=True)</code>
</pre> -->
## Usage
Import `arraydebug` __after__ numpy, torch, pandas, etc.
```python
import torch
import arraydebug # import at last
```
Then you will get information of the array-like object shown in the debugger, like:
```
<Tensor: shape=(6, 4), dtype=float32, device='cpu', requires_grad=True>
```
ArrayDebug searches imported packages for array_like objects, and provides debug information for them. So, it important to import `arraydebug` after them.
### How does it work?
Behind the hood, this is achieved by modifying behavior of `repr()`. So, all debuggers that relies on `repr()` will display the debug information.
```python
>>> import torch
>>> import arraydebug
>>> tensor = torch.ones(3, requires_grad=True)
>>> print(repr(tensor))
<Tensor: shape=(3,), dtype=float32, device='cpu', requires_grad=True>
tensor([1., 1., 1.], requires_grad=True)
```
### Enable and disable
To recover the vanilla `repr()`, you may disable ArrayDebug by `disable()`,
```python
>>> arraydebug.disable()
>>> print(repr(tensor))
tensor([1., 1., 1.], requires_grad=True)
```
or enable ArrayDebug again by `enable()`.
```python
>>> arraydebug.enable()
>>> print(repr(tensor))
<Tensor: shape=(3,), dtype=float32, device='cpu', requires_grad=True>
tensor([1., 1., 1.], requires_grad=True)
```
This is also useful when you import some modules after ArrayDebug, and want to enable ArrayDebug for them:
```python
>>> import arraydebug
>>> import torch
>>> print(repr(torch.ones(3, requires_grad=True)))
<Tensor: shape=(3,), dtype=float32, device='cpu', requires_grad=True>
tensor([1., 1., 1.], requires_grad=True)
```
### Customize
You can register your own debug info by `register_repr()`.
```python
>>> class A:
... def __init__(self, x):
... self.x = x
...
>>> info_fn = lambda a: f'<class A object with x={a.x}>'
>>> arraydebug.register_repr(A, info_fn)
>>> print(repr(A(5)))
<class A object with x=5>
```
## Credits
This package was created with
[Cookiecutter](https://github.com/audreyr/cookiecutter) and the
[audreyr/cookiecutter-pypackage](https://github.com/audreyr/cookiecutter-pypackage)
project template.
# History
## 0.1.2 (2022-03-29)
- Allows `array_like.__array__()` to throw exceptions.
- Now, `array_like_info(obj)` degrades to vanilla `repr(obj)` if `obj.__array__()` throws exception. Before, it did nothing, but let caller to handle the exception.
- rename `arraydebug.recover_repr()` to `arraydebug.disable()`.
- rename `arraydebug.inject_repr()` to `arraydebug.enable()`.
- `enable()` also refresh `arraydebug.repr_fn_table` now.
## 0.1.0 (2022-03-27)
* First release on PyPI.
* Support numpy.ndarray, torch.Tensor.
* Support objects with `__array__` method.
* Setup github CI workflow.