├── .gitignore ├── README.md ├── example.py ├── poetry.lock ├── pyproject.toml └── superdebug ├── __init__.py └── __pycache__ └── __init__.cpython-38.pyc /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | .history/ 3 | tmp/ 4 | tmp.py 5 | */__pycache__ 6 | superdebug/__pycache__ 7 | super_debug -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SuperDebug 2 | 3 | ## 使用方法: 4 | 5 | `pip install superdebug` 6 | 7 | `from superdebug import debug, mail` 8 | 9 | ### 功能1: `debug(var)` 10 | 11 | 用黄色字体打印出(与普通的打印区分): 12 | 13 | - `var`所在具体行数(command / ctrl + 单击 即可跳转到文件相应位置) 14 | - 数组形状(限list、numpy的array、torch的tensor) 15 | - `var`的具体值 16 | 17 | 进阶功能: 18 | 19 | 1. 一次性打印多个变量:`debug(var1, var2, var3, ...)` 20 | 2. 同步输出在终端(`PRINT = True`)和同目录下的debug.log文件中(`TO_FILE = True`) 21 | 3. 对于一些循环程序,你或许只想打印有限次,只需设置 `MAX_LOG = 想打印的次数` 即可 22 | 4. 如果你希望只打印变量的形状,而不打印变量的内容,可以使用 `debug(False, var)` 23 | 5. 打印完整矩阵内容,禁止pytorch、numpy自动省略:`FULL = True` 24 | 6. 对于一些套娃list / dict,可以控制详细打印至第几层,标准为0,建议用3: `PEEK_LAYER = 0` 25 | 26 | ### 功能2: `debug()` 27 | 28 | 简单标记程序已经运行到了某一位置,可用于判断程序在哪一处卡在、程序进入了哪一个if分支等,也可以查看程序运行到这一位置的时间。 29 | 30 | ### 功能3: 在出错时跳至ipdb调试界面,便捷debug 31 | 32 | 自动停在出错的那一步(需设置 `BUGGY = True`):当出现Exception,程序不会退出,而是会暂停在出现Exception的那一步。 33 | 34 | 这时你可以使用 `var`(输出var的值), `up`(上一步), `down`(下一步)等控制命令进行调试。更多命令同ipdb 35 | 36 | ### 功能4: 在指定位置停下(设置断点) 37 | 38 | 在想设置断点处写 `raise Exception()`,与功能3同理,程序将会停在exception处。 39 | 40 | ### 功能5: 邮件提醒 41 | 42 | 用于在某一任务完成后发送邮件通知。 43 | 44 | 需配置环境变量 `MY_QQ_EMAIL`(QQ邮箱地址)与 `MY_QQ_EMAIL_PWD`(QQ邮箱授权码)。 45 | 46 | 使用 `mail("邮件主题", "邮件内容")`即可便捷地向你自己的邮箱发送通知,可用于提醒模型已训练完毕、某项耗时的任务已处理完成等。 47 | -------------------------------------------------------------------------------- /example.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict, defaultdict 2 | from superdebug import debug 3 | import time 4 | 5 | debug("程序开始运行了,记得看时间哦") 6 | 7 | story = ["从前有座山", "山里有座庙", "庙里有个老和尚", "老和尚在给小和尚讲故事", "讲什么呢"] * 10000 # 重复10000遍 8 | 9 | config = OrderedDict({"标题": "和尚的故事", "内容": story, "更多信息": {"作者": ("老和尚", "小和尚", "小小和尚"), "时间": {"创作时间": "很久很久以前", "timestamp": time.time()}}}) 10 | debug("你可以同时debug多个变量,没有被设置名字的变量会显示为'?'", story, 提示 = "这个故事实在太长了,我们只打印其中的一段", config = config, 另一个提示 = "我们可以清晰地看出变量的嵌套结构") 11 | 12 | from superdebug import mail 13 | debug("让我们模拟一段耗时的任务,任务结束后我会向你发送邮件") 14 | time.sleep(10) 15 | mail("任务已处理完成") 16 | debug("你收到邮件了吗?") 17 | 18 | raise Exception("哎呀,程序出错了... 去在ipdb界面中调试程序吧") -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "appnope" 3 | version = "0.1.2" 4 | description = "Disable App Nap on macOS >= 10.9" 5 | category = "main" 6 | optional = false 7 | python-versions = "*" 8 | 9 | [[package]] 10 | name = "asttokens" 11 | version = "2.0.5" 12 | description = "Annotate AST trees with source code positions" 13 | category = "main" 14 | optional = false 15 | python-versions = "*" 16 | 17 | [package.dependencies] 18 | six = "*" 19 | 20 | [package.extras] 21 | test = ["astroid", "pytest"] 22 | 23 | [[package]] 24 | name = "backcall" 25 | version = "0.2.0" 26 | description = "Specifications for callback functions passed in to an API" 27 | category = "main" 28 | optional = false 29 | python-versions = "*" 30 | 31 | [[package]] 32 | name = "certifi" 33 | version = "2021.10.8" 34 | description = "Python package for providing Mozilla's CA Bundle." 35 | category = "main" 36 | optional = false 37 | python-versions = "*" 38 | 39 | [[package]] 40 | name = "charset-normalizer" 41 | version = "2.0.12" 42 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 43 | category = "main" 44 | optional = false 45 | python-versions = ">=3.5.0" 46 | 47 | [package.extras] 48 | unicode_backport = ["unicodedata2"] 49 | 50 | [[package]] 51 | name = "colorama" 52 | version = "0.4.4" 53 | description = "Cross-platform colored terminal text." 54 | category = "main" 55 | optional = false 56 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 57 | 58 | [[package]] 59 | name = "decorator" 60 | version = "5.1.1" 61 | description = "Decorators for Humans" 62 | category = "main" 63 | optional = false 64 | python-versions = ">=3.5" 65 | 66 | [[package]] 67 | name = "executing" 68 | version = "0.8.3" 69 | description = "Get the currently executing AST node of a frame, and other information" 70 | category = "main" 71 | optional = false 72 | python-versions = "*" 73 | 74 | [[package]] 75 | name = "idna" 76 | version = "3.3" 77 | description = "Internationalized Domain Names in Applications (IDNA)" 78 | category = "main" 79 | optional = false 80 | python-versions = ">=3.5" 81 | 82 | [[package]] 83 | name = "ipython" 84 | version = "8.1.1" 85 | description = "IPython: Productive Interactive Computing" 86 | category = "main" 87 | optional = false 88 | python-versions = ">=3.8" 89 | 90 | [package.dependencies] 91 | appnope = {version = "*", markers = "sys_platform == \"darwin\""} 92 | backcall = "*" 93 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 94 | decorator = "*" 95 | jedi = ">=0.16" 96 | matplotlib-inline = "*" 97 | pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} 98 | pickleshare = "*" 99 | prompt-toolkit = ">=2.0.0,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.1.0" 100 | pygments = ">=2.4.0" 101 | stack-data = "*" 102 | traitlets = ">=5" 103 | 104 | [package.extras] 105 | all = ["black", "Sphinx (>=1.3)", "ipykernel", "nbconvert", "nbformat", "ipywidgets", "notebook", "ipyparallel", "qtconsole", "curio", "matplotlib (!=3.2.0)", "numpy (>=1.19)", "pandas", "pytest", "testpath", "trio", "pytest-asyncio"] 106 | black = ["black"] 107 | doc = ["Sphinx (>=1.3)"] 108 | kernel = ["ipykernel"] 109 | nbconvert = ["nbconvert"] 110 | nbformat = ["nbformat"] 111 | notebook = ["ipywidgets", "notebook"] 112 | parallel = ["ipyparallel"] 113 | qtconsole = ["qtconsole"] 114 | test = ["pytest", "pytest-asyncio", "testpath"] 115 | test_extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.19)", "pandas", "pytest", "testpath", "trio"] 116 | 117 | [[package]] 118 | name = "jedi" 119 | version = "0.18.1" 120 | description = "An autocompletion tool for Python that can be used for text editors." 121 | category = "main" 122 | optional = false 123 | python-versions = ">=3.6" 124 | 125 | [package.dependencies] 126 | parso = ">=0.8.0,<0.9.0" 127 | 128 | [package.extras] 129 | qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] 130 | testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<7.0.0)"] 131 | 132 | [[package]] 133 | name = "matplotlib-inline" 134 | version = "0.1.3" 135 | description = "Inline Matplotlib backend for Jupyter" 136 | category = "main" 137 | optional = false 138 | python-versions = ">=3.5" 139 | 140 | [package.dependencies] 141 | traitlets = "*" 142 | 143 | [[package]] 144 | name = "mypy" 145 | version = "0.941" 146 | description = "Optional static typing for Python" 147 | category = "main" 148 | optional = false 149 | python-versions = ">=3.6" 150 | 151 | [package.dependencies] 152 | mypy-extensions = ">=0.4.3" 153 | tomli = ">=1.1.0" 154 | typing-extensions = ">=3.10" 155 | 156 | [package.extras] 157 | dmypy = ["psutil (>=4.0)"] 158 | python2 = ["typed-ast (>=1.4.0,<2)"] 159 | reports = ["lxml"] 160 | 161 | [[package]] 162 | name = "mypy-extensions" 163 | version = "0.4.3" 164 | description = "Experimental type system extensions for programs checked with the mypy typechecker." 165 | category = "main" 166 | optional = false 167 | python-versions = "*" 168 | 169 | [[package]] 170 | name = "mypyc-ipython" 171 | version = "0.0.2" 172 | description = "IPython magic command interface for interactive work with mypyc." 173 | category = "main" 174 | optional = false 175 | python-versions = ">=3.6" 176 | 177 | [package.dependencies] 178 | ipython = "*" 179 | mypy = ">=0.800" 180 | 181 | [[package]] 182 | name = "numpy" 183 | version = "1.22.3" 184 | description = "NumPy is the fundamental package for array computing with Python." 185 | category = "main" 186 | optional = false 187 | python-versions = ">=3.8" 188 | 189 | [[package]] 190 | name = "parso" 191 | version = "0.8.3" 192 | description = "A Python Parser" 193 | category = "main" 194 | optional = false 195 | python-versions = ">=3.6" 196 | 197 | [package.extras] 198 | qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] 199 | testing = ["docopt", "pytest (<6.0.0)"] 200 | 201 | [[package]] 202 | name = "pexpect" 203 | version = "4.8.0" 204 | description = "Pexpect allows easy control of interactive console applications." 205 | category = "main" 206 | optional = false 207 | python-versions = "*" 208 | 209 | [package.dependencies] 210 | ptyprocess = ">=0.5" 211 | 212 | [[package]] 213 | name = "pickleshare" 214 | version = "0.7.5" 215 | description = "Tiny 'shelve'-like database with concurrency support" 216 | category = "main" 217 | optional = false 218 | python-versions = "*" 219 | 220 | [[package]] 221 | name = "pillow" 222 | version = "9.0.1" 223 | description = "Python Imaging Library (Fork)" 224 | category = "main" 225 | optional = false 226 | python-versions = ">=3.7" 227 | 228 | [[package]] 229 | name = "prompt-toolkit" 230 | version = "3.0.28" 231 | description = "Library for building powerful interactive command lines in Python" 232 | category = "main" 233 | optional = false 234 | python-versions = ">=3.6.2" 235 | 236 | [package.dependencies] 237 | wcwidth = "*" 238 | 239 | [[package]] 240 | name = "ptyprocess" 241 | version = "0.7.0" 242 | description = "Run a subprocess in a pseudo terminal" 243 | category = "main" 244 | optional = false 245 | python-versions = "*" 246 | 247 | [[package]] 248 | name = "pure-eval" 249 | version = "0.2.2" 250 | description = "Safely evaluate AST nodes without side effects" 251 | category = "main" 252 | optional = false 253 | python-versions = "*" 254 | 255 | [package.extras] 256 | tests = ["pytest"] 257 | 258 | [[package]] 259 | name = "pygments" 260 | version = "2.11.2" 261 | description = "Pygments is a syntax highlighting package written in Python." 262 | category = "main" 263 | optional = false 264 | python-versions = ">=3.5" 265 | 266 | [[package]] 267 | name = "requests" 268 | version = "2.27.1" 269 | description = "Python HTTP for Humans." 270 | category = "main" 271 | optional = false 272 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" 273 | 274 | [package.dependencies] 275 | certifi = ">=2017.4.17" 276 | charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""} 277 | idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""} 278 | urllib3 = ">=1.21.1,<1.27" 279 | 280 | [package.extras] 281 | socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] 282 | use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] 283 | 284 | [[package]] 285 | name = "six" 286 | version = "1.16.0" 287 | description = "Python 2 and 3 compatibility utilities" 288 | category = "main" 289 | optional = false 290 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 291 | 292 | [[package]] 293 | name = "stack-data" 294 | version = "0.2.0" 295 | description = "Extract data from python stack frames and tracebacks for informative displays" 296 | category = "main" 297 | optional = false 298 | python-versions = "*" 299 | 300 | [package.dependencies] 301 | asttokens = "*" 302 | executing = "*" 303 | pure-eval = "*" 304 | 305 | [package.extras] 306 | tests = ["pytest", "typeguard", "pygments", "littleutils", "cython"] 307 | 308 | [[package]] 309 | name = "tomli" 310 | version = "2.0.1" 311 | description = "A lil' TOML parser" 312 | category = "main" 313 | optional = false 314 | python-versions = ">=3.7" 315 | 316 | [[package]] 317 | name = "torch" 318 | version = "1.11.0" 319 | description = "Tensors and Dynamic neural networks in Python with strong GPU acceleration" 320 | category = "main" 321 | optional = false 322 | python-versions = ">=3.7.0" 323 | 324 | [package.dependencies] 325 | typing-extensions = "*" 326 | 327 | [[package]] 328 | name = "torchvision" 329 | version = "0.12.0" 330 | description = "image and video datasets and models for torch deep learning" 331 | category = "main" 332 | optional = false 333 | python-versions = ">=3.7" 334 | 335 | [package.dependencies] 336 | numpy = "*" 337 | pillow = ">=5.3.0,<8.3.0 || >=8.4.0" 338 | requests = "*" 339 | torch = "*" 340 | typing-extensions = "*" 341 | 342 | [package.extras] 343 | scipy = ["scipy"] 344 | 345 | [[package]] 346 | name = "traitlets" 347 | version = "5.1.1" 348 | description = "Traitlets Python configuration system" 349 | category = "main" 350 | optional = false 351 | python-versions = ">=3.7" 352 | 353 | [package.extras] 354 | test = ["pytest"] 355 | 356 | [[package]] 357 | name = "typing-extensions" 358 | version = "4.1.1" 359 | description = "Backported and Experimental Type Hints for Python 3.6+" 360 | category = "main" 361 | optional = false 362 | python-versions = ">=3.6" 363 | 364 | [[package]] 365 | name = "urllib3" 366 | version = "1.26.9" 367 | description = "HTTP library with thread-safe connection pooling, file post, and more." 368 | category = "main" 369 | optional = false 370 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" 371 | 372 | [package.extras] 373 | brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] 374 | secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] 375 | socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] 376 | 377 | [[package]] 378 | name = "wcwidth" 379 | version = "0.2.5" 380 | description = "Measures the displayed width of unicode strings in a terminal" 381 | category = "main" 382 | optional = false 383 | python-versions = "*" 384 | 385 | [metadata] 386 | lock-version = "1.1" 387 | python-versions = "^3.8" 388 | content-hash = "39bfe3bb169593a337fd9c39341db4e055c7a1ff67ee91c63f7748c2837b1e02" 389 | 390 | [metadata.files] 391 | appnope = [ 392 | {file = "appnope-0.1.2-py2.py3-none-any.whl", hash = "sha256:93aa393e9d6c54c5cd570ccadd8edad61ea0c4b9ea7a01409020c9aa019eb442"}, 393 | {file = "appnope-0.1.2.tar.gz", hash = "sha256:dd83cd4b5b460958838f6eb3000c660b1f9caf2a5b1de4264e941512f603258a"}, 394 | ] 395 | asttokens = [ 396 | {file = "asttokens-2.0.5-py2.py3-none-any.whl", hash = "sha256:0844691e88552595a6f4a4281a9f7f79b8dd45ca4ccea82e5e05b4bbdb76705c"}, 397 | {file = "asttokens-2.0.5.tar.gz", hash = "sha256:9a54c114f02c7a9480d56550932546a3f1fe71d8a02f1bc7ccd0ee3ee35cf4d5"}, 398 | ] 399 | backcall = [ 400 | {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, 401 | {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, 402 | ] 403 | certifi = [ 404 | {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, 405 | {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, 406 | ] 407 | charset-normalizer = [ 408 | {file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"}, 409 | {file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"}, 410 | ] 411 | colorama = [ 412 | {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, 413 | {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, 414 | ] 415 | decorator = [ 416 | {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, 417 | {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, 418 | ] 419 | executing = [ 420 | {file = "executing-0.8.3-py2.py3-none-any.whl", hash = "sha256:d1eef132db1b83649a3905ca6dd8897f71ac6f8cac79a7e58a1a09cf137546c9"}, 421 | {file = "executing-0.8.3.tar.gz", hash = "sha256:c6554e21c6b060590a6d3be4b82fb78f8f0194d809de5ea7df1c093763311501"}, 422 | ] 423 | idna = [ 424 | {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, 425 | {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, 426 | ] 427 | ipython = [ 428 | {file = "ipython-8.1.1-py3-none-any.whl", hash = "sha256:6f56bfaeaa3247aa3b9cd3b8cbab3a9c0abf7428392f97b21902d12b2f42a381"}, 429 | {file = "ipython-8.1.1.tar.gz", hash = "sha256:8138762243c9b3a3ffcf70b37151a2a35c23d3a29f9743878c33624f4207be3d"}, 430 | ] 431 | jedi = [ 432 | {file = "jedi-0.18.1-py2.py3-none-any.whl", hash = "sha256:637c9635fcf47945ceb91cd7f320234a7be540ded6f3e99a50cb6febdfd1ba8d"}, 433 | {file = "jedi-0.18.1.tar.gz", hash = "sha256:74137626a64a99c8eb6ae5832d99b3bdd7d29a3850fe2aa80a4126b2a7d949ab"}, 434 | ] 435 | matplotlib-inline = [ 436 | {file = "matplotlib-inline-0.1.3.tar.gz", hash = "sha256:a04bfba22e0d1395479f866853ec1ee28eea1485c1d69a6faf00dc3e24ff34ee"}, 437 | {file = "matplotlib_inline-0.1.3-py3-none-any.whl", hash = "sha256:aed605ba3b72462d64d475a21a9296f400a19c4f74a31b59103d2a99ffd5aa5c"}, 438 | ] 439 | mypy = [ 440 | {file = "mypy-0.941-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:98f61aad0bb54f797b17da5b82f419e6ce214de0aa7e92211ebee9e40eb04276"}, 441 | {file = "mypy-0.941-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6a8e1f63357851444940351e98fb3252956a15f2cabe3d698316d7a2d1f1f896"}, 442 | {file = "mypy-0.941-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b30d29251dff4c59b2e5a1fa1bab91ff3e117b4658cb90f76d97702b7a2ae699"}, 443 | {file = "mypy-0.941-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8eaf55fdf99242a1c8c792247c455565447353914023878beadb79600aac4a2a"}, 444 | {file = "mypy-0.941-cp310-cp310-win_amd64.whl", hash = "sha256:080097eee5393fd740f32c63f9343580aaa0fb1cda0128fd859dfcf081321c3d"}, 445 | {file = "mypy-0.941-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f79137d012ff3227866222049af534f25354c07a0d6b9a171dba9f1d6a1fdef4"}, 446 | {file = "mypy-0.941-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8e5974583a77d630a5868eee18f85ac3093caf76e018c510aeb802b9973304ce"}, 447 | {file = "mypy-0.941-cp36-cp36m-win_amd64.whl", hash = "sha256:0dd441fbacf48e19dc0c5c42fafa72b8e1a0ba0a39309c1af9c84b9397d9b15a"}, 448 | {file = "mypy-0.941-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0d3bcbe146247997e03bf030122000998b076b3ac6925b0b6563f46d1ce39b50"}, 449 | {file = "mypy-0.941-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3bada0cf7b6965627954b3a128903a87cac79a79ccd83b6104912e723ef16c7b"}, 450 | {file = "mypy-0.941-cp37-cp37m-win_amd64.whl", hash = "sha256:eea10982b798ff0ccc3b9e7e42628f932f552c5845066970e67cd6858655d52c"}, 451 | {file = "mypy-0.941-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:108f3c7e14a038cf097d2444fa0155462362c6316e3ecb2d70f6dd99cd36084d"}, 452 | {file = "mypy-0.941-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d61b73c01fc1de799226963f2639af831307fe1556b04b7c25e2b6c267a3bc76"}, 453 | {file = "mypy-0.941-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:42c216a33d2bdba08098acaf5bae65b0c8196afeb535ef4b870919a788a27259"}, 454 | {file = "mypy-0.941-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fc5ecff5a3bbfbe20091b1cad82815507f5ae9c380a3a9bf40f740c70ce30a9b"}, 455 | {file = "mypy-0.941-cp38-cp38-win_amd64.whl", hash = "sha256:bf446223b2e0e4f0a4792938e8d885e8a896834aded5f51be5c3c69566495540"}, 456 | {file = "mypy-0.941-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:745071762f32f65e77de6df699366d707fad6c132a660d1342077cbf671ef589"}, 457 | {file = "mypy-0.941-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:465a6ce9ca6268cadfbc27a2a94ddf0412568a6b27640ced229270be4f5d394d"}, 458 | {file = "mypy-0.941-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d051ce0946521eba48e19b25f27f98e5ce4dbc91fff296de76240c46b4464df0"}, 459 | {file = "mypy-0.941-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:818cfc51c25a5dbfd0705f3ac1919fff6971eb0c02e6f1a1f6a017a42405a7c0"}, 460 | {file = "mypy-0.941-cp39-cp39-win_amd64.whl", hash = "sha256:b2ce2788df0c066c2ff4ba7190fa84f18937527c477247e926abeb9b1168b8cc"}, 461 | {file = "mypy-0.941-py3-none-any.whl", hash = "sha256:3cf77f138efb31727ee7197bc824c9d6d7039204ed96756cc0f9ca7d8e8fc2a4"}, 462 | {file = "mypy-0.941.tar.gz", hash = "sha256:cbcc691d8b507d54cb2b8521f0a2a3d4daa477f62fe77f0abba41e5febb377b7"}, 463 | ] 464 | mypy-extensions = [ 465 | {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, 466 | {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, 467 | ] 468 | mypyc-ipython = [ 469 | {file = "mypyc_ipython-0.0.2-py3-none-any.whl", hash = "sha256:eb8057908781a01cebf564b753be56cec17247d6f10a5ed0cba5d93636de6a00"}, 470 | {file = "mypyc_ipython-0.0.2.tar.gz", hash = "sha256:e265704ac98c3c42df404d7066f8c122a6fcb4ef6d88410ed84d60979d1b6bea"}, 471 | ] 472 | numpy = [ 473 | {file = "numpy-1.22.3-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:92bfa69cfbdf7dfc3040978ad09a48091143cffb778ec3b03fa170c494118d75"}, 474 | {file = "numpy-1.22.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8251ed96f38b47b4295b1ae51631de7ffa8260b5b087808ef09a39a9d66c97ab"}, 475 | {file = "numpy-1.22.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48a3aecd3b997bf452a2dedb11f4e79bc5bfd21a1d4cc760e703c31d57c84b3e"}, 476 | {file = "numpy-1.22.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3bae1a2ed00e90b3ba5f7bd0a7c7999b55d609e0c54ceb2b076a25e345fa9f4"}, 477 | {file = "numpy-1.22.3-cp310-cp310-win32.whl", hash = "sha256:f950f8845b480cffe522913d35567e29dd381b0dc7e4ce6a4a9f9156417d2430"}, 478 | {file = "numpy-1.22.3-cp310-cp310-win_amd64.whl", hash = "sha256:08d9b008d0156c70dc392bb3ab3abb6e7a711383c3247b410b39962263576cd4"}, 479 | {file = "numpy-1.22.3-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:201b4d0552831f7250a08d3b38de0d989d6f6e4658b709a02a73c524ccc6ffce"}, 480 | {file = "numpy-1.22.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f8c1f39caad2c896bc0018f699882b345b2a63708008be29b1f355ebf6f933fe"}, 481 | {file = "numpy-1.22.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:568dfd16224abddafb1cbcce2ff14f522abe037268514dd7e42c6776a1c3f8e5"}, 482 | {file = "numpy-1.22.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ca688e1b9b95d80250bca34b11a05e389b1420d00e87a0d12dc45f131f704a1"}, 483 | {file = "numpy-1.22.3-cp38-cp38-win32.whl", hash = "sha256:e7927a589df200c5e23c57970bafbd0cd322459aa7b1ff73b7c2e84d6e3eae62"}, 484 | {file = "numpy-1.22.3-cp38-cp38-win_amd64.whl", hash = "sha256:07a8c89a04997625236c5ecb7afe35a02af3896c8aa01890a849913a2309c676"}, 485 | {file = "numpy-1.22.3-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:2c10a93606e0b4b95c9b04b77dc349b398fdfbda382d2a39ba5a822f669a0123"}, 486 | {file = "numpy-1.22.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fade0d4f4d292b6f39951b6836d7a3c7ef5b2347f3c420cd9820a1d90d794802"}, 487 | {file = "numpy-1.22.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bfb1bb598e8229c2d5d48db1860bcf4311337864ea3efdbe1171fb0c5da515d"}, 488 | {file = "numpy-1.22.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97098b95aa4e418529099c26558eeb8486e66bd1e53a6b606d684d0c3616b168"}, 489 | {file = "numpy-1.22.3-cp39-cp39-win32.whl", hash = "sha256:fdf3c08bce27132395d3c3ba1503cac12e17282358cb4bddc25cc46b0aca07aa"}, 490 | {file = "numpy-1.22.3-cp39-cp39-win_amd64.whl", hash = "sha256:639b54cdf6aa4f82fe37ebf70401bbb74b8508fddcf4797f9fe59615b8c5813a"}, 491 | {file = "numpy-1.22.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c34ea7e9d13a70bf2ab64a2532fe149a9aced424cd05a2c4ba662fd989e3e45f"}, 492 | {file = "numpy-1.22.3.zip", hash = "sha256:dbc7601a3b7472d559dc7b933b18b4b66f9aa7452c120e87dfb33d02008c8a18"}, 493 | ] 494 | parso = [ 495 | {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"}, 496 | {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"}, 497 | ] 498 | pexpect = [ 499 | {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, 500 | {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, 501 | ] 502 | pickleshare = [ 503 | {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, 504 | {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, 505 | ] 506 | pillow = [ 507 | {file = "Pillow-9.0.1-1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a5d24e1d674dd9d72c66ad3ea9131322819ff86250b30dc5821cbafcfa0b96b4"}, 508 | {file = "Pillow-9.0.1-1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2632d0f846b7c7600edf53c48f8f9f1e13e62f66a6dbc15191029d950bfed976"}, 509 | {file = "Pillow-9.0.1-1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b9618823bd237c0d2575283f2939655f54d51b4527ec3972907a927acbcc5bfc"}, 510 | {file = "Pillow-9.0.1-cp310-cp310-macosx_10_10_universal2.whl", hash = "sha256:9bfdb82cdfeccec50aad441afc332faf8606dfa5e8efd18a6692b5d6e79f00fd"}, 511 | {file = "Pillow-9.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5100b45a4638e3c00e4d2320d3193bdabb2d75e79793af7c3eb139e4f569f16f"}, 512 | {file = "Pillow-9.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:528a2a692c65dd5cafc130de286030af251d2ee0483a5bf50c9348aefe834e8a"}, 513 | {file = "Pillow-9.0.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f29d831e2151e0b7b39981756d201f7108d3d215896212ffe2e992d06bfe049"}, 514 | {file = "Pillow-9.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:855c583f268edde09474b081e3ddcd5cf3b20c12f26e0d434e1386cc5d318e7a"}, 515 | {file = "Pillow-9.0.1-cp310-cp310-win32.whl", hash = "sha256:d9d7942b624b04b895cb95af03a23407f17646815495ce4547f0e60e0b06f58e"}, 516 | {file = "Pillow-9.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:81c4b81611e3a3cb30e59b0cf05b888c675f97e3adb2c8672c3154047980726b"}, 517 | {file = "Pillow-9.0.1-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:413ce0bbf9fc6278b2d63309dfeefe452835e1c78398efb431bab0672fe9274e"}, 518 | {file = "Pillow-9.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80fe64a6deb6fcfdf7b8386f2cf216d329be6f2781f7d90304351811fb591360"}, 519 | {file = "Pillow-9.0.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cef9c85ccbe9bee00909758936ea841ef12035296c748aaceee535969e27d31b"}, 520 | {file = "Pillow-9.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d19397351f73a88904ad1aee421e800fe4bbcd1aeee6435fb62d0a05ccd1030"}, 521 | {file = "Pillow-9.0.1-cp37-cp37m-win32.whl", hash = "sha256:d21237d0cd37acded35154e29aec853e945950321dd2ffd1a7d86fe686814669"}, 522 | {file = "Pillow-9.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:ede5af4a2702444a832a800b8eb7f0a7a1c0eed55b644642e049c98d589e5092"}, 523 | {file = "Pillow-9.0.1-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:b5b3f092fe345c03bca1e0b687dfbb39364b21ebb8ba90e3fa707374b7915204"}, 524 | {file = "Pillow-9.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:335ace1a22325395c4ea88e00ba3dc89ca029bd66bd5a3c382d53e44f0ccd77e"}, 525 | {file = "Pillow-9.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db6d9fac65bd08cea7f3540b899977c6dee9edad959fa4eaf305940d9cbd861c"}, 526 | {file = "Pillow-9.0.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f154d173286a5d1863637a7dcd8c3437bb557520b01bddb0be0258dcb72696b5"}, 527 | {file = "Pillow-9.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14d4b1341ac07ae07eb2cc682f459bec932a380c3b122f5540432d8977e64eae"}, 528 | {file = "Pillow-9.0.1-cp38-cp38-win32.whl", hash = "sha256:effb7749713d5317478bb3acb3f81d9d7c7f86726d41c1facca068a04cf5bb4c"}, 529 | {file = "Pillow-9.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:7f7609a718b177bf171ac93cea9fd2ddc0e03e84d8fa4e887bdfc39671d46b00"}, 530 | {file = "Pillow-9.0.1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:80ca33961ced9c63358056bd08403ff866512038883e74f3a4bf88ad3eb66838"}, 531 | {file = "Pillow-9.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1c3c33ac69cf059bbb9d1a71eeaba76781b450bc307e2291f8a4764d779a6b28"}, 532 | {file = "Pillow-9.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12875d118f21cf35604176872447cdb57b07126750a33748bac15e77f90f1f9c"}, 533 | {file = "Pillow-9.0.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:514ceac913076feefbeaf89771fd6febde78b0c4c1b23aaeab082c41c694e81b"}, 534 | {file = "Pillow-9.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3c5c79ab7dfce6d88f1ba639b77e77a17ea33a01b07b99840d6ed08031cb2a7"}, 535 | {file = "Pillow-9.0.1-cp39-cp39-win32.whl", hash = "sha256:718856856ba31f14f13ba885ff13874be7fefc53984d2832458f12c38205f7f7"}, 536 | {file = "Pillow-9.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:f25ed6e28ddf50de7e7ea99d7a976d6a9c415f03adcaac9c41ff6ff41b6d86ac"}, 537 | {file = "Pillow-9.0.1-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:011233e0c42a4a7836498e98c1acf5e744c96a67dd5032a6f666cc1fb97eab97"}, 538 | {file = "Pillow-9.0.1-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:253e8a302a96df6927310a9d44e6103055e8fb96a6822f8b7f514bb7ef77de56"}, 539 | {file = "Pillow-9.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6295f6763749b89c994fcb6d8a7f7ce03c3992e695f89f00b741b4580b199b7e"}, 540 | {file = "Pillow-9.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:a9f44cd7e162ac6191491d7249cceb02b8116b0f7e847ee33f739d7cb1ea1f70"}, 541 | {file = "Pillow-9.0.1.tar.gz", hash = "sha256:6c8bc8238a7dfdaf7a75f5ec5a663f4173f8c367e5a39f87e720495e1eed75fa"}, 542 | ] 543 | prompt-toolkit = [ 544 | {file = "prompt_toolkit-3.0.28-py3-none-any.whl", hash = "sha256:30129d870dcb0b3b6a53efdc9d0a83ea96162ffd28ffe077e94215b233dc670c"}, 545 | {file = "prompt_toolkit-3.0.28.tar.gz", hash = "sha256:9f1cd16b1e86c2968f2519d7fb31dd9d669916f515612c269d14e9ed52b51650"}, 546 | ] 547 | ptyprocess = [ 548 | {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, 549 | {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, 550 | ] 551 | pure-eval = [ 552 | {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, 553 | {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, 554 | ] 555 | pygments = [ 556 | {file = "Pygments-2.11.2-py3-none-any.whl", hash = "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65"}, 557 | {file = "Pygments-2.11.2.tar.gz", hash = "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a"}, 558 | ] 559 | requests = [ 560 | {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"}, 561 | {file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"}, 562 | ] 563 | six = [ 564 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, 565 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, 566 | ] 567 | stack-data = [ 568 | {file = "stack_data-0.2.0-py3-none-any.whl", hash = "sha256:999762f9c3132308789affa03e9271bbbe947bf78311851f4d485d8402ed858e"}, 569 | {file = "stack_data-0.2.0.tar.gz", hash = "sha256:45692d41bd633a9503a5195552df22b583caf16f0b27c4e58c98d88c8b648e12"}, 570 | ] 571 | tomli = [ 572 | {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, 573 | {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, 574 | ] 575 | torch = [ 576 | {file = "torch-1.11.0-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:62052b50fffc29ca7afc0c04ef8206b6f1ca9d10629cb543077e12967e8d0398"}, 577 | {file = "torch-1.11.0-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:866bfba29ac98dec35d893d8e17eaec149d0ac7a53be7baae5c98069897db667"}, 578 | {file = "torch-1.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:951640fb8db308a59d9b510e7d1ad910aff92913323bbe4bc75435347ddd346d"}, 579 | {file = "torch-1.11.0-cp310-none-macosx_10_9_x86_64.whl", hash = "sha256:5d77b5ece78fdafa5c7f42995ff9474399d22571cd6b2de21a5d666306a2ff8c"}, 580 | {file = "torch-1.11.0-cp310-none-macosx_11_0_arm64.whl", hash = "sha256:b5a38682769b544c875ecc34bcb81fbad5c922139b61319aacffcfd8a32f528c"}, 581 | {file = "torch-1.11.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:f82d77695a60626f2b7382d85bc566de8a6b3e50d32080755abc040db802e419"}, 582 | {file = "torch-1.11.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b96654d42566080a134e784705f33f8536b3b95b5dcde357ed7879b1692a5f78"}, 583 | {file = "torch-1.11.0-cp37-cp37m-win_amd64.whl", hash = "sha256:8ee7c2e8d7f7020d5bfbc1bb91b9591044c26bbd0cee5e4f694cfd7ed8649260"}, 584 | {file = "torch-1.11.0-cp37-none-macosx_10_9_x86_64.whl", hash = "sha256:6860b1d1bf0bb0b67a6bd47f85a0e4c825b518eea13b5d6101999dbbcbd5bc0c"}, 585 | {file = "torch-1.11.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:4322aa29f50da7f404db06cdf30896ea67b09f673af4a985afc7162bc897864d"}, 586 | {file = "torch-1.11.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:e4d2e0ddd652f30e94cff750220324ec45705d4ecc69658f773b3cb1c7a28dd0"}, 587 | {file = "torch-1.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:34ce5ea4d8d85da32cdbadb50d4585106901e9f8a3527991daa70c13a09de1f7"}, 588 | {file = "torch-1.11.0-cp38-none-macosx_10_9_x86_64.whl", hash = "sha256:0ccc85cd06227a3edf809e2c795fd5762c3d4e8a38b5c9f744c6e7cf841361bb"}, 589 | {file = "torch-1.11.0-cp38-none-macosx_11_0_arm64.whl", hash = "sha256:c1554e49d74f1b2c3e7202d77056ba2dd7465437585bac64062b580f714a44e9"}, 590 | {file = "torch-1.11.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:58c7814502b1c129a650d7092033bbb0bbd64faf1a7941631aaa1aeaddc37570"}, 591 | {file = "torch-1.11.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:831cf588f01dda9409e75576741d2823453990dee2983d670f2584b37a01adf7"}, 592 | {file = "torch-1.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:44a1d02fd20f827f0f36dc26fdcfc45e793806a6ad52769a22260655a77a4369"}, 593 | {file = "torch-1.11.0-cp39-none-macosx_10_9_x86_64.whl", hash = "sha256:50fd9bf85c578c871c28f1cb0ace9dfc6024401c7f399b174fb0f370899f4454"}, 594 | {file = "torch-1.11.0-cp39-none-macosx_11_0_arm64.whl", hash = "sha256:0e48af66ad755f0f9c5f2664028a414f57c49d6adc37e77e06fe0004da4edb61"}, 595 | ] 596 | torchvision = [ 597 | {file = "torchvision-0.12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:693656e6790b6ab21e4a6e87e81c2982bad9e455b5eb24e14bb672382ec6130f"}, 598 | {file = "torchvision-0.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0be4501ca0ba1b195644c9243f49a1c49a26e52a7f37924c4239d0bf5ecbd8d"}, 599 | {file = "torchvision-0.12.0-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:ebfb47adf65bf3926b990b2c4767e291f135e259e03232e0e1a30ecdb05eb087"}, 600 | {file = "torchvision-0.12.0-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:9771231639afb5973cdaea1d449b451e2982e1ef5410ca67bbdc2b465565573a"}, 601 | {file = "torchvision-0.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:894dacdc64b6e35e3f330722db51c76f4de016c7bf7bd79cf02ed2f4c106e625"}, 602 | {file = "torchvision-0.12.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:36dfdf6451fe3072ab15118982853b848896c0fd3b26cb8135e1e7981dbb0916"}, 603 | {file = "torchvision-0.12.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:aac76d52c5ce4229cb0eaebb762f3391fa736565eb35a4184fa0f7be30b705cd"}, 604 | {file = "torchvision-0.12.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:926666f0b893dce6619759c19b0dd3884af7a9d7022b10395653659d28e43c48"}, 605 | {file = "torchvision-0.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c225f55c1bfce027a03f4ca46ddb9559c83f8087c2880bed3261a76c49bb7996"}, 606 | {file = "torchvision-0.12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d1ccb53836ba886320dcda12d00ee8b5f8f38b6c36d7906f141d25778cf74104"}, 607 | {file = "torchvision-0.12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9f42420f7f0b29cd3d61776df3157827257a0cf16b2c02776dc16c96abb1256d"}, 608 | {file = "torchvision-0.12.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:9017248c7e526c8cdcaaab8cf41d904a520a409d707398189a06d0757901d235"}, 609 | {file = "torchvision-0.12.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:0744902f2265d4c3e83c44a06b567df312e4a9faf8c92620016c7bed7056b5a7"}, 610 | {file = "torchvision-0.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:a91db01496932350bf9c0ee8607ac8ef31c3ebfdaedefe5c5cda0515317f8b8e"}, 611 | {file = "torchvision-0.12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:24d03fcaa28004c64a24124ac4a894c50f5948c8eb290e398d6c76fff2bc678f"}, 612 | {file = "torchvision-0.12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:69d82f47b67bad6ddcbb87833ba5950a6c271ba97baae4c0955610071bf034f5"}, 613 | {file = "torchvision-0.12.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:49ed7886b93b80c9733462edd06a07f8d4c6ea4d5bd2894e7268f7a3774f4f7d"}, 614 | {file = "torchvision-0.12.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b93a767f44e3933cb3b01a6fe9727db54590f57b7dac09d5aaf15966c6c151dd"}, 615 | {file = "torchvision-0.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:edab05f7ba9f648c00435b384ffdbd7bde79a3b8ea893813fb50f6ccf28b1e76"}, 616 | ] 617 | traitlets = [ 618 | {file = "traitlets-5.1.1-py3-none-any.whl", hash = "sha256:2d313cc50a42cd6c277e7d7dc8d4d7fedd06a2c215f78766ae7b1a66277e0033"}, 619 | {file = "traitlets-5.1.1.tar.gz", hash = "sha256:059f456c5a7c1c82b98c2e8c799f39c9b8128f6d0d46941ee118daace9eb70c7"}, 620 | ] 621 | typing-extensions = [ 622 | {file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"}, 623 | {file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"}, 624 | ] 625 | urllib3 = [ 626 | {file = "urllib3-1.26.9-py2.py3-none-any.whl", hash = "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14"}, 627 | {file = "urllib3-1.26.9.tar.gz", hash = "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e"}, 628 | ] 629 | wcwidth = [ 630 | {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, 631 | {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, 632 | ] 633 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "superdebug" 3 | version = "0.4.4" 4 | description = "Convenient debugging for machine learning projects" 5 | authors = ["Azure-Vision "] 6 | license = "MIT" 7 | 8 | [tool.poetry.dependencies] 9 | mypyc-ipython = "^0.0.2" 10 | numpy = "^1.0.0" 11 | 12 | [tool.poetry.dev-dependencies] 13 | 14 | [build-system] 15 | requires = ["poetry-core>=1.0.0"] 16 | build-backend = "poetry.core.masonry.api" 17 | -------------------------------------------------------------------------------- /superdebug/__init__.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | # from superdebug import debug, mail 3 | import torch 4 | try: 5 | from torchvision.utils import save_image 6 | except: 7 | save_image is None 8 | tf = None 9 | if False: 10 | try: 11 | import tensorflow as tf 12 | except: 13 | pass 14 | import numpy as np 15 | import sys 16 | import os 17 | import time 18 | import re 19 | from collections import OrderedDict, defaultdict 20 | try: 21 | from PIL import Image 22 | except: 23 | Image = None 24 | 25 | # 开关 ################################# 26 | ON_DEBUG = True # debug总开关 27 | PLAIN = False # 开启则仅普通的打印(至终端或debug.log) 28 | MAX_LOG = -1 # 0: 不debug, -1: 无限输出 NOTE: 无输出?可能这里设成了0,或者数量不够高、没到需要输出的变量! 29 | FULL = False # 是否输出完整的tensor、string内容,而不用...进行省略 30 | TO_FILE = False # 是否写入debug.log 31 | PRINT = True # 是否打印至终端 32 | BUGGY = True # 便捷地debug(出现bug则进入自动进入调试模式) 33 | PEEK_LAYER = 3 # 详细打印至第几层,不详细打印可使用0,详细打印建议用3 34 | MAX_PEEK_ITEM = 3 # 详细打印几项,标准为2 35 | MAX_STR_LEN = 540 # 最长打印的字符串长度,推荐: 540 ,无限大: 9999999999999999 36 | SAVE_IMAGE_NORM = False # 把tensor保存成图片时是否normalize 37 | # 控制是否打印细节:debug(True/False, xxx, xxx),False则只打印形状 38 | 39 | # 教程 ################################# 40 | # 功能1: debug(xxx) : 用黄色字体打印出xxx的形状及具体值,debug(False, xxx)则只打印形状,不打印具体值。更多控制开关见上方。 41 | # 功能2: mark(xxx) : 标记运行到了某个位置,若有输入,则用黄色字体打印出xxx值,若仅用mark()无输入,则打印mark()所在的位置 42 | # 功能3: 在出错时跳至ipdb界面,便捷debug 43 | 44 | # 实现 ################################# 45 | try: 46 | MY_QQ_EMAIL = os.environ["MY_QQ_EMAIL"] # Email address 47 | MY_QQ_EMAIL_PWD = os.environ["MY_QQ_EMAIL_PWD"] # Password 48 | except: 49 | print("为了使用邮件提醒功能,请设置环境变量MY_QQ_EMAIL(QQ邮箱地址)与MY_QQ_EMAIL_PWD(QQ邮箱授权码)") 50 | 51 | debug_count = 1 52 | debug_file = None 53 | debug_path = "super_debug" 54 | if os.path.exists(debug_path): 55 | os.system("rm -r " + debug_path) 56 | os.makedirs(debug_path, exist_ok=True) 57 | log_path = os.path.join(debug_path, "debug.log") 58 | os.system("touch " + log_path) 59 | image_count = {} 60 | simple_types = [str, int, float, bool] 61 | 62 | 63 | class ExceptionHook: 64 | instance = None 65 | 66 | def __call__(self, *args, **kwargs): 67 | if not BUGGY: 68 | return 69 | if self.instance is None: 70 | from IPython.core import ultratb 71 | self.instance = ultratb.FormattedTB(mode='Plain', 72 | color_scheme='Linux', call_pdb=1) 73 | return self.instance(*args, **kwargs) 74 | 75 | 76 | sys.excepthook = ExceptionHook() 77 | 78 | 79 | def get_pos(level=1, end="\n"): 80 | position = """{}:{} {}""".format( 81 | # position = """"{}", line {}, in {}""".format( 82 | sys._getframe(level).f_code.co_filename, # 当前文件名 83 | sys._getframe(level).f_lineno, # 当前行号 84 | sys._getframe(level).f_code.co_name, # 当前函数/module名 85 | ) 86 | return position 87 | 88 | def get_time(): 89 | return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) 90 | 91 | def print_yellow(text, end="\n"): 92 | print(f"\033[1;33m{text}\033[0m", end=end) 93 | 94 | 95 | def normalize(tensor): 96 | max_value = torch.max(tensor) 97 | min_value = torch.min(tensor) 98 | tensor = (tensor - min_value) / (max_value - min_value) 99 | return tensor 100 | 101 | def print_image(tensor, name, is_np = False): 102 | if name not in image_count: 103 | image_count[name] = 0 104 | file_path = os.path.join(debug_path, f"tensor_{debug_count}_{name}_{image_count[name]}.jpg") 105 | normallized_file_path = os.path.join(debug_path, f"tensor_{debug_count}_{name}_{image_count[name]}_norm.jpg") 106 | image_count[name] += 1 107 | if Image is not None and type(tensor) == Image.Image: 108 | tensor.save(file_path) 109 | else: 110 | if is_np: 111 | tensor = torch.Tensor(tensor) 112 | normalized_tensor = normalize(tensor) 113 | try: 114 | if save_image is not None: 115 | if SAVE_IMAGE_NORM: 116 | save_image(normalized_tensor, normallized_file_path) 117 | else: 118 | save_image(tensor, file_path) 119 | except Exception: 120 | pass 121 | def mark(marker=None): 122 | print("Mark is deprecated. Use debug() instead.") 123 | 124 | 125 | def logging(*message, end="\n"): 126 | """同时输出到终端和debug.log""" 127 | message = " ".join([str(_) for _ in message]) 128 | if PRINT: 129 | print_yellow(message, end=end) 130 | if debug_file and not debug_file.closed: 131 | message = re.sub("\033\[.*?m", "", message) 132 | debug_file.write(message + end) 133 | logging("------------------\033[0m\033[1;31m", get_time(), "\033[0m\033[1;33m------------------") 134 | 135 | 136 | def info(var, name="?", detail=True, layer=0): 137 | """递归打印变量""" 138 | space = " " 139 | if type(var) == int or type(var) == float: 140 | logging(space * layer, f"\033[0m\033[1;36m{name}\033[0m\033[1;33m", "num val:", var) 141 | else: 142 | if var is None: 143 | logging(space * layer, f"\033[0m\033[1;36m{name}\033[0m\033[1;33m", "None") 144 | elif type(var) == str: 145 | length = len(var) 146 | if not FULL and len(var) >= MAX_STR_LEN: 147 | var = var[:MAX_STR_LEN - 20] + " ... " + var[-20:] 148 | logging(space * layer, f"\033[0m\033[1;36m{name}\033[0m\033[1;33m", "str len", str(length)+":", var) 149 | elif type(var) == bool: 150 | logging(space * layer, f"\033[0m\033[1;36m{name}\033[0m\033[1;33m", "bool:", var) 151 | elif type(var) == list: 152 | logging(space * layer, f"\033[0m\033[1;36m{name}\033[0m\033[1;33m", "list size:", len(var), end="") 153 | if layer < PEEK_LAYER and len(var) > 0 and type(var[0]) not in simple_types: # a list of complex variables 154 | logging(f" [{min(len(var), 3)*'.'}]") 155 | for no, item in enumerate(var[:MAX_PEEK_ITEM]): 156 | info(item, "item " + str(no) + ": ", detail, layer + 1) 157 | if len(var) > MAX_PEEK_ITEM: 158 | logging(space * (layer + 1), len(var) - MAX_PEEK_ITEM, "extra items") 159 | else: 160 | var_str = str(var) 161 | if len(var) > 0 and type(var[0]) in simple_types and all([type(var[i]) == type(var[0]) for i in range(len(var))]): # a list of variables of the same simple type 162 | if len(var_str) >= MAX_STR_LEN + 3: # too long 163 | # show_num = len(var_str[:MAX_STR_LEN].split(",")) 164 | logging(" val:", f"{var_str[:MAX_STR_LEN]} ... and extra items]" if detail else "*") 165 | else: 166 | logging(" val:", var_str if detail else "*") 167 | elif layer < PEEK_LAYER: # variables of different simple types 168 | logging(f" [{min(len(var), 3)*'.'}]") 169 | for no, item in enumerate(var): 170 | info(item, "item " + str(no) + ": ", detail, layer + 1) 171 | else: 172 | logging(" val:", var_str if detail else "*") 173 | elif type(var) == tuple: 174 | logging(space * layer, f"\033[0m\033[1;36m{name}\033[0m\033[1;33m", "tuple size:", len(var), end="") 175 | if layer < PEEK_LAYER and len(var) > 0: 176 | logging(f" ({min(len(var), 3)*'.'})") 177 | for no, item in enumerate(var): 178 | info(item, "item " + str(no) + ": ", detail, layer + 1) 179 | else: 180 | logging(" val:", var if detail else "*") 181 | elif type(var) == set: 182 | logging(space * layer, f"\033[0m\033[1;36m{name}\033[0m\033[1;33m", "set size:", len(var), end="") 183 | if layer < PEEK_LAYER and len(var) > 0: 184 | logging(" {" + min(len(var), 3)*'.' + "}") 185 | for no, item in enumerate(var): 186 | info(item, "item " + str(no) + ": ", detail, layer + 1) 187 | else: 188 | logging(" val:", var if detail else "*") 189 | elif type(var) == dict: 190 | dict_keys = sorted(list(var.keys())) 191 | dict_end = "" 192 | if len(dict_keys) >= 100: 193 | dict_keys = dict_keys[:100] 194 | dict_end = "... and extra items]" 195 | logging(space * layer, f"\033[0m\033[1;36m{name}\033[0m\033[1;33m", "dict {" + min(len(var), 3)*'.' + "} " + f"with {len(dict_keys)} keys", dict_keys, end=dict_end) 196 | if layer < PEEK_LAYER and len(var) > 0: 197 | logging("") 198 | for key in dict_keys: 199 | info(var[key], key, detail, layer + 1) 200 | else: 201 | logging(" val:", var if detail else "*") 202 | elif type(var) == OrderedDict: 203 | dict_keys = sorted(list(var.keys())) 204 | dict_end = "" 205 | if len(dict_keys) >= 100: 206 | dict_keys = dict_keys[:100] 207 | dict_end = "... and extra items]" 208 | logging(space * layer, f"\033[0m\033[1;36m{name}\033[0m\033[1;33m", "OrderedDict {" + min(len(var), 3)*'.' + "} " + f"with {len(dict_keys)} keys", dict_keys, end=dict_end) 209 | if layer < PEEK_LAYER and len(var) > 0: 210 | logging("") 211 | for key in dict_keys: 212 | info(var[key], key, detail, layer + 1) 213 | else: 214 | logging(" val:", var if detail else "*") 215 | elif type(var) == defaultdict: 216 | tmp_val = 12341231354124 217 | assert tmp_val not in var 218 | default_val = var[tmp_val] 219 | del var[tmp_val] 220 | 221 | dict_keys = sorted(list(var.keys())) 222 | dict_end = "" 223 | if len(dict_keys) >= 100: 224 | dict_keys = dict_keys[:100] 225 | dict_end = "... and extra items]" 226 | 227 | logging(space * layer, f"\033[0m\033[1;36m{name}\033[0m\033[1;33m", "defaultdict {" + min(len(var), 3)*'.' + "} with default", default_val, f"{len(dict_keys)} keys", dict_keys, end=dict_end) 228 | if layer < PEEK_LAYER and len(var) > 0: 229 | logging("") 230 | for key in dict_keys: 231 | info(var[key], key, detail, layer + 1) 232 | else: 233 | logging(" val:", var if detail else "*") 234 | elif type(var) == torch.Tensor: 235 | logging(space * layer, f"\033[0m\033[1;36m{name}\033[0m\033[1;33m", "Tensor size:", var.shape, "val:", var if detail else "*") 236 | print_image(var, name) 237 | elif type(var) == np.ndarray: 238 | logging(space * layer, f"\033[0m\033[1;36m{name}\033[0m\033[1;33m", "ndarray size:", var.shape, 239 | "val:", var if detail else "*") 240 | print_image(var, name, True) 241 | elif tf is not None and type(var) == tf.Tensor: 242 | logging(space * layer, f"\033[0m\033[1;36m{name}\033[0m\033[1;33m", "Tensor size:", var.shape, "val:", var if detail else "*") 243 | elif Image is not None and type(var) == Image.Image: 244 | print_image(var, name) 245 | else: 246 | var_type = str(type(var)).split("'")[1] 247 | try: 248 | if layer >= PEEK_LAYER: 249 | raise Exception("Too many layers") 250 | props = var.__dict__ 251 | logging(space * layer, f"\033[0m\033[1;36m{name}\033[0m\033[1;33m", var_type, "with props", list(props.keys()), end="") 252 | prop_valid = False 253 | for key in props: 254 | if not key.startswith("_"): 255 | if not prop_valid: 256 | prop_valid = True 257 | logging("") 258 | info(props[key], key, detail, layer + 1) 259 | if not prop_valid: 260 | logging(" val:", var) 261 | except Exception: 262 | var_type = str(type(var))[8:-2] 263 | logging(space * layer, f"\033[0m\033[1;36m{name}\033[0m\033[1;33m", var_type, "with val: ", var) 264 | 265 | 266 | def debug(*args, **kwargs): 267 | """debug打印主入口""" 268 | global ON_DEBUG 269 | global debug_count 270 | global debug_file 271 | global TO_FILE 272 | global PLAIN 273 | if not ON_DEBUG: 274 | return 275 | if TO_FILE: 276 | try: 277 | debug_file = open(log_path, "a", encoding='utf-8') 278 | except: 279 | debug_file = None 280 | logging("------------------\033[0m\033[1;31m", get_time(), "\033[0m\033[1;33m------------------") 281 | if PLAIN: 282 | logging(*args, **kwargs, end="\n") 283 | if TO_FILE and debug_file is not None: 284 | debug_file.close() 285 | return 286 | global FULL 287 | if FULL: 288 | torch.set_printoptions(profile="full") 289 | np.set_printoptions(threshold=sys.maxsize) 290 | count = 0 291 | if MAX_LOG != -1 and debug_count >= MAX_LOG: 292 | if debug_file: 293 | debug_file.close() 294 | return 295 | detail = True 296 | if args and type(args[0]) is bool: 297 | detail = args[0] 298 | args = args[1:] 299 | keys = list(kwargs.keys()) 300 | if len(args) + len(kwargs) == 0: 301 | logging(f"\033[0m\033[1;32mMARK:\033[0m\033[1;33m at \033[0m\033[1;32m{get_pos(level=2)}\033[0m\033[1;33m") 302 | elif len(args) == 1 and len(kwargs) == 0 and type(args[0]) == str: 303 | logging(f"\033[0m\033[1;32mDEBUG:\033[0m\033[1;33m at \033[0m\033[1;32m{get_pos(level=2)}\033[0m\033[1;33m") 304 | logging(f"\033[0m\033[1;36m{args[0]}\033[0m\033[1;33m") 305 | else: 306 | logging(f"\033[0m\033[1;32mDEBUG:\033[0m\033[1;33m {len(args) + len(kwargs)} vars: {['?' for _ in args] + keys}, at \033[0m\033[1;32m{get_pos(level=2)}\033[0m\033[1;33m") 307 | for var in args: 308 | logging(f"{count} / {debug_count}.", end=" ") 309 | info(var, detail=detail) 310 | debug_count += 1 311 | count += 1 312 | for key in keys: 313 | logging(f"{count} / {debug_count}.", end=" ") 314 | info(kwargs[key], key, detail=detail) 315 | count += 1 316 | debug_count += 1 317 | logging("------------------\033[0m\033[1;31m", get_time(), "\033[0m\033[1;33m------------------") 318 | if TO_FILE and debug_file is not None: 319 | debug_file.close() 320 | 321 | def mail(subject = "Progress Notification", message = ""): 322 | from email.mime.text import MIMEText 323 | subject = f"[SUPERDEBUG] {subject}" 324 | message = f"{message}\nThis email is sent at {get_pos(level=2)}" 325 | mail = MIMEText(message) 326 | mail['Subject'] = subject 327 | mail['From'] = MY_QQ_EMAIL 328 | mail['To'] = MY_QQ_EMAIL 329 | 330 | import smtplib 331 | smtp=smtplib.SMTP() 332 | smtp.connect('smtp.qq.com', 25) 333 | smtp.login(MY_QQ_EMAIL, MY_QQ_EMAIL_PWD) 334 | 335 | smtp.sendmail(MY_QQ_EMAIL, MY_QQ_EMAIL, mail.as_string()) # To是接收邮箱 336 | -------------------------------------------------------------------------------- /superdebug/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Vision/SuperDebug/e8e705eaea27c0cf7e69eaaf283cf6bab142387e/superdebug/__pycache__/__init__.cpython-38.pyc --------------------------------------------------------------------------------