diff --git a/.gitignore b/.gitignore index 14cd250..1ca20df 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ test.py dist/ .pdm-python + +# Sphinx documentation +docs/build/ \ No newline at end of file diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..d8b8660 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,15 @@ +# Required +version: 2 + +# Set the OS, Python version and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.11" + + +python: + install: + - requirements: docs/requirements.txt +sphinx: + configuration: docs/source/conf.py \ No newline at end of file diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..061f32f --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..911069d --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,45 @@ +# This file is @generated by PDM. +# Please do not edit it manually. + +alabaster==0.7.13 +babel==2.14.0 +certifi==2024.2.2 +charset-normalizer==3.3.2 +colorama==0.4.6; sys_platform == "win32" +dill==0.3.7 +docutils==0.17.1 +exceptiongroup==1.2.0; python_version < "3.11" +flake8==5.0.4 +idna==3.6 +imagesize==1.4.1 +importlib-metadata==4.2.0; python_version < "3.8" +iniconfig==2.0.0 +jinja2==3.1.3 +markupsafe==2.1.5 +mccabe==0.7.0 +packaging==23.2 +pluggy==1.2.0 +pycodestyle==2.9.1 +pyflakes==2.5.0 +pygments==2.17.2 +pytest==7.4.4 +pytest-order==1.2.0 +pytz==2024.1; python_version < "3.9" +requests==2.31.0 +setuptools==68.0.0 +snowballstemmer==2.2.0 +sphinx==4.3.2 +sphinx-copybutton==0.5.2 +sphinx-rtd-theme==1.3.0 +sphinx-tabs==3.4.5 +sphinxcontrib-applehelp==1.0.2 +sphinxcontrib-devhelp==1.0.2 +sphinxcontrib-htmlhelp==2.0.0 +sphinxcontrib-jquery==4.1 +sphinxcontrib-jsmath==1.0.1 +sphinxcontrib-qthelp==1.0.3 +sphinxcontrib-serializinghtml==1.1.5 +tomli==2.0.1; python_version < "3.11" +typing-extensions==4.7.1; python_version < "3.8" +urllib3==2.0.7 +zipp==3.15.0; python_version < "3.8" diff --git a/docs/source/_static/favicon.png b/docs/source/_static/favicon.png new file mode 100644 index 0000000..f2115fd Binary files /dev/null and b/docs/source/_static/favicon.png differ diff --git a/docs/source/_static/header_photo_1.png b/docs/source/_static/header_photo_1.png new file mode 100644 index 0000000..0e588fe Binary files /dev/null and b/docs/source/_static/header_photo_1.png differ diff --git a/docs/source/_static/logo.png b/docs/source/_static/logo.png new file mode 100644 index 0000000..c0ba1f3 Binary files /dev/null and b/docs/source/_static/logo.png differ diff --git a/docs/source/_static/rpdb.png b/docs/source/_static/rpdb.png new file mode 100644 index 0000000..00bf061 Binary files /dev/null and b/docs/source/_static/rpdb.png differ diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..d370497 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,40 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = 'pydumpling' +copyright = '2024, cocolato' +author = 'cocolato' +release = '0.1.4' + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration +html_context = { + "display_github": True, # Integrate GitHub + "github_user": "cocolato", # Username + "github_repo": "pydumpling", # Repo name + "github_version": "main", # Version + "conf_py_path": "/source/", # Path in the checkout to the docs root +} + +extensions = [ + "sphinx_rtd_theme", + "sphinx_tabs.tabs", + "sphinx_copybutton" +] + +templates_path = ['_templates'] +exclude_patterns = [] + + +html_theme = "sphinx_rtd_theme" + +html_static_path = ['_static'] +html_logo = "_static/logo.png" +html_favicon = "_static/favicon.png" +html_title = "Pydumpling Documentation" +html_show_sourcelink = False diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..0816e37 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,55 @@ +Welcome to Pydumpling +======================= + +.. image:: https://img.shields.io/pypi/dm/pydumpling + :alt: PyPI - Downloads + :target: https://pypi.org/project/pydumpling/ + +.. image:: https://img.shields.io/pypi/v/pydumpling + :alt: PyPI - Version + :target: https://pypi.org/project/pydumpling/ + +.. image:: https://img.shields.io/github/stars/cocolato/pydumpling + :alt: GitHub Repo stars + :target: https://github.com/cocolato/pydumpling/ + + + +It's a fork/optimized version from `elifiner/pydump`_ .The main optimization points are: + +* Save the ``Python traceback`` anywhere, not just when it's an exception. +* Optimize code structure && remove redundant code +* fix bug in python2.7 && support python3.10+ +* supported more pdb command +* provides command line tools + +.. _elifiner/pydump: https://github.com/elifiner/pydump + +Pydumpling writes the ``python current traceback`` into a file and +can later load it in a Python debugger. It works with the built-in +pdb and with other popular debuggers (`pudb`_, `ipdb`_ and `pdbpp`_). + +.. _pudb: https://github.com/inducer/pudb +.. _ipdb: https://github.com/gotcha/ipdb +.. _pdbpp: https://github.com/pdbpp/pdbpp + +Why use Pydumpling? +------------------- + +* We usually use ``try... except ... `` to catch exceptions that occur in our programs, but do we really know why they occur? +* When your project is running online, you suddenly get an unexpected exception that causes the process to exit. How do you reproduce this problem? +* Not enough information in the logs to help us pinpoint online issues? +* If we were able to save the exception error and then use the debugger to recover the traceback at that time, we could see the entire stack variables along the traceback as if you had caught the exception at the local breakpoint. + + +User's Guide +------------ + +Get started with :doc:`installation` +and then get an overview with the :doc:`tutorial` that shows how to use. + +.. toctree:: + :maxdepth: 4 + + installation + tutorial \ No newline at end of file diff --git a/docs/source/installation.rst b/docs/source/installation.rst new file mode 100644 index 0000000..e3a5e4f --- /dev/null +++ b/docs/source/installation.rst @@ -0,0 +1,27 @@ +Installation +============= + +Python Version +--------------- + +Python version: >=3.7 + + +Install +------- + +Not published in pypi yet, so use the `.whl` file install pydumpling in the dist path. + +.. tabs:: + + .. group-tab:: Linux/macOS + + .. code-block:: text + + $ pip3 install pydumpling + + .. group-tab:: Windows + + .. code-block:: text + + > pip install pydumpling \ No newline at end of file diff --git a/docs/source/tutorial.rst b/docs/source/tutorial.rst new file mode 100644 index 0000000..5298069 --- /dev/null +++ b/docs/source/tutorial.rst @@ -0,0 +1,167 @@ +Tutorial +========= + +Save the python traceback anywhere +----------------------------------- + +.. code-block:: python + + from pydumpling import dump_current_traceback + + + def inner(): + a = 1 + b = "2" + dump_current_traceback("test.dump") + c = str(a) + b + + + def outer(): + d = 4 + inner() + + outer() + + + +Save the exception traceback +---------------------------- +.. code-block:: python + + from pydumpling import save_dumping + + def inner(): + a = 1 + b = "2" + c = a + b + + + def outer(): + inner() + + + if __name__ == "__main__": + try: + outer() + except Exception: + save_dumping("test.dump") + + +Use ``debug_dumpling`` to do pdb debug +-------------------------------------- + +.. code-block:: console + + Python 3.10.6 (main, Aug 1 2022, 20:38:21) [GCC 5.4.0 20160609] on linux + Type "help", "copyright", "credits" or "license" for more information. + >>> from pydumpling import debug_dumpling + >>> debug_dumpling("test.dump") + > /home/loyd/vscodeFiles/pydumpling/test.py(6)inner() + -> c = a + b + (Pdb) list 1,17 + 1 from pydumpling import save_dumping + 2 + 3 def inner(): + 4 >> a = 1 + 5 b = "2" + 6 -> c = a + b + 7 + 8 + 9 def outer(): + 10 inner() + 11 + 12 + 13 if __name__ == "__main__": + 14 try: + 15 outer() + 16 except Exception: + 17 save_dumping("test.dump") + (Pdb) ll + 3 def inner(): + 4 >> a = 1 + 5 b = "2" + 6 -> c = a + b + (Pdb) bt + /home/loyd/vscodeFiles/pydumpling/test.py(15)() + -> outer() + /home/loyd/vscodeFiles/pydumpling/test.py(10)outer() + -> inner() + > /home/loyd/vscodeFiles/pydumpling/test.py(6)inner() + -> c = a + b + (Pdb) pp a + 1 + (Pdb) pp b + '2' + (Pdb) u + > /home/loyd/vscodeFiles/pydumpling/test.py(10)outer() + -> inner() + (Pdb) ll + 9 def outer(): + 10 -> inner() + (Pdb) + +Use command line +---------------- + +help message + +.. code-block:: console + + python -m pydumpling --help + +.. code-block:: text + + usage: pydumpling [options] filename + + pydumpling cli tools + + positional arguments: + filename the .dump file + + options: + -h, --help show this help message and exit + --print print traceback information + --debug enter pdb debugging interface + +Print the traceback +################### + +Use ``pydumpling --print test.dump`` to print the traceback information. + +It will print the following information: + +.. code-block:: text + + Traceback (most recent call last): + File "/workspaces/pydumpling/tests/test_dump.py", line 20, in test_dumpling + outer() + File "/workspaces/pydumpling/tests/test_dump.py", line 14, in outer + inner() + File "/workspaces/pydumpling/tests/test_dump.py", line 10, in inner + c = a + b # noqa: F841 + TypeError: unsupported operand type(s) for +: 'int' and 'str' + + +Do pdb debug with dump file +############################ + +Use ``pydumpling --debug test.deump`` to do pdb debugging with dump file. + +It will open the pdb window: + +.. code-block:: text + + -> c = a + b + (Pdb) + + +Do remote debug with dump file +############################## +Use ``python -m pydumpling --rdebug test.dump`` to do remote debug. +It will open the debugger on port 4444, then we can access pdb using `telnet`_, `netcat`_ . + +.. _telnet: https://en.wikipedia.org/wiki/Telnet#Modern_day_uses +.. _netcat: https://netcat.sourceforge.net/ + + +.. image:: _static/rpdb.png \ No newline at end of file diff --git a/pdm.lock b/pdm.lock index fc02541..3504eee 100644 --- a/pdm.lock +++ b/pdm.lock @@ -5,7 +5,7 @@ groups = ["default", "test", "dev"] strategy = ["cross_platform", "inherit_metadata"] lock_version = "4.4.1" -content_hash = "sha256:4283861c949ce20be843e3267675005fa327480b382557f40a49bd039e28719f" +content_hash = "sha256:dcbed90c2662bf8fb637d492c47e923ff19a43a1c2a1f2b47cbd7d20e671a822" [[package]] name = "colorama" @@ -230,7 +230,7 @@ name = "six" version = "1.16.0" requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" summary = "Python 2 and 3 compatibility utilities" -groups = ["default", "dev", "test"] +groups = ["dev"] files = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, diff --git a/pyproject.toml b/pyproject.toml index 81131d5..57b0ffb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,6 +3,9 @@ distribution = true [tool.pdm.scripts] test = {composite = ["pdm install", "flake8 ./pydumpling ./tests", "pytest tests/"]} +docs = {shell = "cd docs && make html"} # build sphinx docs +docs_export = { shell = "pdm export -G doc -o docs/requirements.txt --without-hashes" } # export requirements for docs +docs_preview = {shell = 'python -m http.server -d docs\build\html'} [tool.pdm.build] includes = ["pydumpling/*.py"] @@ -29,7 +32,6 @@ authors = [ ] dependencies = [ "dill<1.0.0,>=0.3.2", - "six<2.0.0,>=1.16.0", "packaging>=24.0", ] requires-python = ">=3.7" @@ -39,3 +41,11 @@ license = {text = "MIT"} [project.urls] homepage = "https://github.com/cocolato/pydumpling" + +[project.optional-dependencies] +doc = [ + "sphinx>=4.3.2", + "sphinx-rtd-theme>=1.3.0", + "sphinx-tabs>=3.4.5", + "sphinx-copybutton>=0.5.2", +]