diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml
index 8701a9ff..98a8551c 100644
--- a/.github/workflows/build_wheels.yml
+++ b/.github/workflows/build_wheels.yml
@@ -4,7 +4,6 @@ on:
push:
pull_request:
paths-ignore:
- - "docs/**"
- "CONTRIBUTING.md"
release:
types:
@@ -212,8 +211,7 @@ jobs:
container:
image: archlinux
- options: --cap-add=SYS_PTRACE
-
+ options: --cap-add=SYS_PTRACE --security-opt seccomp=unconfined
steps:
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css
new file mode 100644
index 00000000..15bb31a9
--- /dev/null
+++ b/docs/_static/css/custom.css
@@ -0,0 +1,462 @@
+/* GLOBAL STYLES
+-------------------------------------------------- */
+/* Padding below the footer and lighter body text */
+
+body {
+ padding-top: 3rem;
+ padding-bottom: 3rem;
+ color: #5a5a5a;
+}
+
+a {
+ color: #e18325;
+}
+
+a:hover {
+ color: #fe6615;
+}
+
+/* NAVAR
+ * ----------------------------------------*/
+
+.navbar {
+ background-color: rgb(245, 245, 245);
+}
+
+.navbar li {
+ transition: 0.3s background-color;
+ text-align: center;
+ background-color: transparent;
+ padding: 0rem 1rem;
+ text-decoration: none;
+ border-radius: 0.3rem;
+}
+
+.navbar li:hover {
+ background-color: #e18325;
+}
+
+.navbar li .nav-link {
+ color: #e18325;
+}
+
+.navbar li:hover .nav-link {
+ color: #31373e;
+}
+
+.dropdown-menu {
+ background-color: rgb(250, 250, 250);
+ /*#000000d0;*/
+}
+
+.dropdown-item {
+ color: #e18325;
+}
+
+.dropdown-item:hover {
+ background-color: #e18325;
+}
+
+/* Buttons
+-------------------------------------------------- */
+
+.outline-pystack {
+ color: #31373e;
+ background-color: transparent;
+ border-color: #00a3e0;
+}
+
+.filled-pystack {
+ color: #fff;
+ background-color: #235d9f;
+ border-color: #235d9f;
+}
+
+.filled-pystack:hover {
+ color: #fff;
+ background-color: #fe6615;
+ border-color: #ff0000;
+}
+
+/* Hero element
+-------------------------------------------------- */
+
+.splash {
+ width: 99vw;
+ height: 99vh;
+ margin: 0;
+ padding: 0;
+ background-color: #fff;
+ background-repeat: no-repeat;
+ background-size: cover;
+ background-position: center;
+ font-family: "Open Sans", sans-serif;
+ font-weight: 300;
+}
+
+.splash-container {
+ z-index: 2;
+}
+
+.splash-image {
+ max-width: 60%;
+ min-width: 25em;
+}
+
+.m-intro {
+ text-align: center;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 97%;
+ margin: 0 auto;
+ overflow: hidden;
+ position: relative;
+}
+
+@keyframes move_wave {
+ 0% {
+ transform: translateX(0) translateZ(0) scaleY(1)
+ }
+ 50% {
+ transform: translateX(-25%) translateZ(0) scaleY(0.55)
+ }
+ 100% {
+ transform: translateX(-50%) translateZ(0) scaleY(1)
+ }
+}
+.waveWrapper {
+ overflow: hidden;
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ top: 0;
+ margin: auto;
+ z-index: 0;
+}
+.waveWrapperInner {
+ position: absolute;
+ width: 100%;
+ overflow: hidden;
+ height: 100%;
+ bottom: -1px;
+ background-image: linear-gradient(to top, #009dff 20%, rgb(245, 245, 245));
+}
+.bgTop {
+ z-index: 15;
+ opacity: 0.5;
+}
+.bgMiddle {
+ z-index: 10;
+ opacity: 0.75;
+}
+.bgBottom {
+ z-index: 5;
+}
+.wave {
+ position: absolute;
+ left: 0;
+ width: 200%;
+ height: 100%;
+ background-repeat: repeat no-repeat;
+ background-position: 0 bottom;
+ transform-origin: center bottom;
+}
+.waveTop {
+ background-size: 50% 100px;
+}
+.waveAnimation .waveTop {
+animation: move-wave 3s;
+ -webkit-animation: move-wave 3s;
+ -webkit-animation-delay: 1s;
+ animation-delay: 1s;
+}
+.waveMiddle {
+ background-size: 50% 120px;
+}
+.waveAnimation .waveMiddle {
+ animation: move_wave 10s linear infinite;
+}
+.waveBottom {
+ background-size: 50% 100px;
+}
+.waveAnimation .waveBottom {
+ animation: move_wave 15s linear infinite;
+}
+
+/* Animation for the hero element
+-------------------------------------------------- */
+
+@-webkit-keyframes rotate {
+ 0% {
+ transform: rotate(0);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+@-moz-keyframes rotate {
+ 0% {
+ transform: rotate(0);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+@-o-keyframes rotate {
+ 0% {
+ transform: rotate(0);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+@keyframes rotate {
+ 0% {
+ transform: rotate(0);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+/* Text typing animation
+-------------------------------------------------- */
+
+.typewriter_container {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ font-size: clamp(2rem, 2.8vw, 5rem);
+}
+
+.typewriter {
+ overflow: hidden;
+ border-right: 0.15em solid #31373e;
+ white-space: nowrap;
+ margin: 0 auto;
+ animation: typing 2.5s steps(40, end), blink-caret 0.75s step-end infinite;
+}
+
+@keyframes typing {
+ from {
+ width: 0;
+ }
+
+ to {
+ width: 32ch;
+ }
+}
+
+@keyframes blink-caret {
+ from,
+ to {
+ border-color: transparent;
+ }
+
+ 50% {
+ border-color: #31373e;
+ }
+}
+
+/* Scrolling Indicator (mouse wheel)
+-------------------------------------------------- */
+
+.mouse {
+ display: block;
+ margin: 0 auto;
+ width: 43px;
+ height: 80px;
+ border-radius: 53px;
+ border: 2px solid #235d9f;
+ position: absolute;
+ top: 85%;
+ position: absolute;
+ left: 50%;
+ margin-left: -14px;
+}
+
+.mouse span {
+ display: block;
+ margin: 6px auto;
+ width: 3px;
+ height: 7px;
+ border-radius: 100%;
+ background: #235d9f;
+ -webkit-animation-duration: 1s;
+ animation-duration: 1s;
+ -webkit-animation-fill-mode: both;
+ animation-fill-mode: both;
+ -webkit-animation-iteration-count: infinite;
+ animation-iteration-count: infinite;
+ -webkit-animation-name: scroll;
+ animation-name: scroll;
+}
+
+@-webkit-keyframes scroll {
+ 0% {
+ opacity: 1;
+ -webkit-transform: translateY(0);
+ transform: translateY(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateY(52px);
+ transform: translateY(52px);
+ }
+}
+
+@keyframes scroll {
+ 0% {
+ opacity: 1;
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ transform: translateY(0);
+ }
+
+ 100% {
+ opacity: 0;
+ -webkit-transform: translateY(52px);
+ -ms-transform: translateY(52px);
+ transform: translateY(52px);
+ }
+}
+
+/* Image animations on scroll
+-------------------------------------------------- */
+
+.reveal_l {
+ position: relative;
+ transform: translateY(150px);
+ opacity: 0;
+ transition: 2s all ease;
+}
+
+.reveal_l.active {
+ transform: translateY(0);
+ opacity: 1;
+}
+
+.reveal_r {
+ position: relative;
+ transform: translateY(-150px);
+ opacity: 0;
+ transition: 2s all ease;
+}
+
+.reveal_r.active {
+ transform: translateY(0);
+ opacity: 1;
+}
+
+/* MARKETING CONTENT
+-------------------------------------------------- */
+
+/* Border for the rounded images */
+
+.rounded-header-image {
+ border-radius: 50%;
+ border: 5px solid rgb(245, 245, 245);
+ box-shadow: 0 2px 2px rgba(0, 0, 0, 0.3);
+}
+
+.rounded-header-image:hover {
+ -webkit-transform: scale(1.1);
+ transform: scale(1.1);
+ transition: all 0.3s ease-in-out;
+}
+
+/* Center align the text within the three columns below the carousel */
+.marketing .col-lg-4 {
+ margin-bottom: 1.5rem;
+ text-align: center;
+}
+
+.marketing h2 {
+ font-weight: 400;
+}
+
+.marketing .col-lg-4 p {
+ margin-right: 0.75rem;
+ margin-left: 0.75rem;
+}
+
+/* Featurettes
+------------------------- */
+
+.featurette-divider {
+ margin: 5rem 0;
+ /* Space out the Bootstrap
more */
+}
+
+/* Thin out the marketing headings */
+.featurette-heading {
+ font-weight: 300;
+ line-height: 1;
+ letter-spacing: -0.05rem;
+}
+
+/* Cards and card columns
+----------------------------- */
+
+.card-container {
+ margin: 0 50px;
+}
+
+.card-columns {
+ flex-wrap: wrap;
+}
+
+.card:hover {
+ background: linear-gradient(90deg, #cc9add 8.06%, #ebad98 106.93%);
+ text-decoration: none;
+ transform: scale(1.05);
+ transition: all 0.3s ease-in-out;
+}
+
+.card:hover .card-title,
+.card:hover .card-subtitle,
+.card:hover .card-text {
+ color: white;
+}
+
+.card:hover .card-link {
+ color: rgb(231, 231, 231);
+}
+
+@media (min-width: 768px) {
+ .card {
+ flex-basis: calc(33.33% - 30px);
+ }
+}
+
+/* RESPONSIVE CSS
+-------------------------------------------------- */
+
+@media (min-width: 40em) {
+ /* Bump up size of carousel content */
+ .carousel-caption p {
+ margin-bottom: 1.25rem;
+ font-size: 1.25rem;
+ line-height: 1.4;
+ }
+
+ .featurette-heading {
+ font-size: 50px;
+ }
+}
+
+@media (min-width: 62em) {
+ .featurette-heading {
+ margin-top: 7rem;
+ }
+}
diff --git a/docs/_static/images/box.png b/docs/_static/images/box.png
new file mode 100644
index 00000000..4157fe8f
Binary files /dev/null and b/docs/_static/images/box.png differ
diff --git a/docs/_static/images/locals.png b/docs/_static/images/locals.png
new file mode 100644
index 00000000..324b6ee5
Binary files /dev/null and b/docs/_static/images/locals.png differ
diff --git a/docs/_static/images/native.png b/docs/_static/images/native.png
new file mode 100644
index 00000000..984bbd7e
Binary files /dev/null and b/docs/_static/images/native.png differ
diff --git a/docs/_static/images/python.png b/docs/_static/images/python.png
new file mode 100644
index 00000000..c65bebaf
Binary files /dev/null and b/docs/_static/images/python.png differ
diff --git a/docs/_static/images/stack.png b/docs/_static/images/stack.png
new file mode 100644
index 00000000..a8b7145c
Binary files /dev/null and b/docs/_static/images/stack.png differ
diff --git a/docs/_static/js/custom.js b/docs/_static/js/custom.js
new file mode 100644
index 00000000..baf67f69
--- /dev/null
+++ b/docs/_static/js/custom.js
@@ -0,0 +1,19 @@
+function reveal() {
+ var classes = [".reveal_l", ".reveal_r"];
+ classes.map(function (c) {
+ var reveals = document.querySelectorAll(c);
+ for (var i = 0; i < reveals.length; i++) {
+ var windowHeight = window.innerHeight;
+ var elementTop = reveals[i].getBoundingClientRect().top;
+ var elementVisible = 150;
+ if (elementTop < windowHeight - elementVisible) {
+ reveals[i].classList.add("active");
+ } else {
+ reveals[i].classList.remove("active");
+ }
+ }
+ });
+}
+window.addEventListener("scroll", reveal);
+// To check the scroll position on page load
+reveal();
diff --git a/docs/_templates/index.html b/docs/_templates/index.html
new file mode 100644
index 00000000..8313759f
--- /dev/null
+++ b/docs/_templates/index.html
@@ -0,0 +1,302 @@
+
+
+
+
+
+
+
+
+
+ PyStack: the endgame Python stack debugger
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
The endgame Python stack debugger
+
+
+ PyStack reports the stack frames of a running Python process or a Python core dump
+
+
+ Documentation
+ Community
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Processes and core files
+
+ No matter the situation, PyStack is your reliable
+ companion for program analysis. If a process is running
+ more slowly than you expected, PyStack can tell you what
+ it's doing. If it's hanging, PyStack can tell you where
+ it got stuck. If it crashed, PyStack can even tell you
+ what it was doing from the core dump it left behind.
+
+
Get started »
+
+
+
+
Ready for anything
+
+ PyStack thrives in extreme conditions, always ensuring
+ accurate insights. It can handle deep call stacks like
+ a breeze. It can get you a comprehensive report even if
+ your Python interpreter is heavily optimized and shipped
+ without debug information. Even if memory corruption has
+ trashed some of the interpreter's internal data
+ structures, PyStack can handle it!
+
+
See for yourself »
+
+
+
+
Prevent regressions
+
+ You can easily integrate PyStack into your
+ pytest
test suite. If a test gets stuck,
+ our plugin can automatically report each thread's stack
+ and help you figure out what went wrong.
+
+
Discover the plugin »
+
+
+
+
+
+
+
+
+
+ Uncover your program's secrets.
+ No more deadlocks or mysterious crashes.
+
+
+ PyStack provides a powerful tool for inspecting the
+ stack frames of a running Python process or a Python
+ core dump. It allows developers to quickly and easily
+ understand what's happening in their Python programs
+ without delving into the intricate details of CPython
+ internals. When you ask PyStack to analyze a running
+ process or core file, it prints a stack trace for each
+ thread, which shows the sequence of function calls and
+ their corresponding line numbers in the Python code.
+ This feature is invaluable for debugging and
+ understanding the runtime behavior of an application,
+ especially when encountering unexpected hangs or
+ crashes.
+
+
+
+
+
+
+
+
+
+
+
+
+ No more hidden code!
+ Peer inside native extensions.
+
+
+ PyStack's native mode offers an additional layer of
+ insight by including native function calls in the stack
+ trace. When your Python code calls into some code that
+ isn't written in Python, PyStack shows you what native
+ functions are executed. If one of those functions calls
+ a function written in Python, the reported stack will
+ switch right back to displaying Python frames.
+
+
+ This mode lets developers see the full stack trace,
+ including calls to C/C++/Rust functions, while still
+ providing context about the Python code being executed
+ at each level. PyStack automatically demangles symbols
+ in the native stack, and it can even include calls to
+ inlined functions whenever there is sufficient debug
+ information available! Native mode is particularly
+ useful when analyzing the interactions between Python
+ and native code in a mixed-language application — which
+ of course is exactly where many crashes and deadlocks
+ occur.
+
+
+
+
+
+
+
+
+
+
+
+
+ Deep Dive into Program State.
+ See inside your functions!
+
+
+ You can ask PyStack to go beyond providing a stack
+ trace, and to also print the values of local variables
+ and function arguments within Python stack frames. This
+ lets developers obtain a more detailed understanding of
+ what the program is currently doing inside each call.
+ This feature is especially helpful when trying to
+ understand why a particular function was called, or to
+ see what work was being performed when a process
+ crashed. By examining the local variables and arguments,
+ developers can gain crucial insights into the runtime
+ behavior of their Python. This is one of the best ways
+ to leverage PyStack's debugging capabilities to analyze
+ your application and identify potential errors or
+ unexpected behaviors.
+
+
+
+
+
+
+
+
+
PyStack in the media
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/conf.py b/docs/conf.py
index 4512735c..7ffc1b69 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -36,6 +36,12 @@
"sidebar_hide_name": True,
}
+templates_path = ["_templates"]
+html_additional_pages = {
+ "index": "index.html",
+}
+root_doc = "overview"
+
# -- Options for smartquotes ----------------------------------------------------------
# Disable the conversion of dashes so that long options like "--find-links" won't
diff --git a/docs/index.rst b/docs/overview.rst
similarity index 100%
rename from docs/index.rst
rename to docs/overview.rst
diff --git a/tests/integration/test_core_analyzer.py b/tests/integration/test_core_analyzer.py
index 34157476..6e77e51e 100644
--- a/tests/integration/test_core_analyzer.py
+++ b/tests/integration/test_core_analyzer.py
@@ -395,7 +395,7 @@ def test_thread_registered_with_python_with_other_threads(tmpdir):
assert lines == [13, 10]
native_frames = list(non_python_thread.native_frames)
- assert len(native_frames) >= 5
+ assert len(native_frames) >= 4
symbols = {frame.symbol for frame in native_frames}
assert any(
[
diff --git a/tests/integration/test_gather_stacks.py b/tests/integration/test_gather_stacks.py
index bcae32c8..183c630c 100644
--- a/tests/integration/test_gather_stacks.py
+++ b/tests/integration/test_gather_stacks.py
@@ -553,7 +553,7 @@ def test_thread_registered_with_python_with_other_threads(tmpdir):
assert lines == [13, 10]
native_frames = list(non_python_thread.native_frames)
- assert len(native_frames) >= 5
+ assert len(native_frames) >= 4
symbols = {frame.symbol for frame in native_frames}
assert any(
[