Fix: In packages/griffelib/src/griffe/_internal/merger.py,... - #483

Closed
M001N wants to merge 1 commit into
mkdocstrings:mainfrom
M001N:oss-engine/e27b6eec-e96e1653
Closed

Fix: In packages/griffelib/src/griffe/_internal/merger.py,...#483
M001N wants to merge 1 commit into
mkdocstrings:mainfrom
M001N:oss-engine/e27b6eec-e96e1653

Conversation

@M001N

Copy link
Copy Markdown

Summary

  1. Changed _merge_stubs_docstring to overwrite obj.docstring whenever stubs.docstring exists AND (obj has no docstring OR obj.analysis == 'dynamic'), leaving statically-analyzed genuine docstrings untouched. 2) In _merge_overload_annotations, added a docstring fallback: if the base function has no docstring or is dynamically analyzed, take the docstring from the first overload that has one, before merging annotations.

Problem

mkdocstrings/griffe issue reference: #447

Root Cause

In packages/griffelib/src/griffe/_internal/merger.py, _merge_stubs_docstring(obj, stubs) used if not obj.docstring and stubs.docstring -- it treated 'has any docstring' as sufficient reason to keep the runtime object's docstring, without checking whether that docstring was genuinely authored (obj.analysis == 'static'/None) versus an auto-generated placeholder from runtime inspection (obj.analysis == 'dynamic'), even though griffe's Object model already tracks this via the analysis: Literal['static','dynamic'] | None attribute (set by the inspector for dynamically-analyzed members). Separately, _merge_overload_annotations(function, overloads) merged parameter/return type annotations from @overload stub signatures onto the base function but never propagated any overload's docstring onto it.

Testing

PASS - all 9 tests in test_merger.py pass (3 new + 6 existing); full suite (minus unrelated test_api.py which fails to import due to missing optional 'mkdocstrings' dependency in this environment, and test_git.py which fails due to a missing pytest-git plugin fixture, both pre-existing/unrelated to this change) shows 1742 passed, 22 skipped, 0 failures caused by this change.

Related Issue

#447

…ocstrings#447)
_merge_stubs_docstring() only filled in a docstring when the runtime
object had none at all, so an auto-generated placeholder docstring
from dynamic/runtime inspection (e.g. a SWIG/pybind11 C-level
signature string) was never replaced by the real, human-authored
docstring from a .pyi stub. Now it also overwrites when the object's
analysis is 'dynamic', while still leaving genuine statically-analyzed
docstrings untouched.
Also propagate an overload's docstring onto the base function when
merging overload-only stub methods, for the same dynamic/missing
docstring cases.
@pawamoy

Copy link
Copy Markdown
Member

Thanks @M001N but we already have a PR for this: #481. Let me know if I misunderstood the changes here.

@pawamoypawamoy closed this Aug 17, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@M001N@pawamoy
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Fix: In packages/griffelib/src/griffe/_internal/merger.py,... - #483

Closed
M001N wants to merge 1 commit into
mkdocstrings:mainfrom
M001N:oss-engine/e27b6eec-e96e1653
Closed

Fix: In packages/griffelib/src/griffe/_internal/merger.py,...#483
M001N wants to merge 1 commit into
mkdocstrings:mainfrom
M001N:oss-engine/e27b6eec-e96e1653

Conversation

@M001N

Copy link
Copy Markdown

Summary

  1. Changed _merge_stubs_docstring to overwrite obj.docstring whenever stubs.docstring exists AND (obj has no docstring OR obj.analysis == 'dynamic'), leaving statically-analyzed genuine docstrings untouched. 2) In _merge_overload_annotations, added a docstring fallback: if the base function has no docstring or is dynamically analyzed, take the docstring from the first overload that has one, before merging annotations.

Problem

mkdocstrings/griffe issue reference: #447

Root Cause

In packages/griffelib/src/griffe/_internal/merger.py, _merge_stubs_docstring(obj, stubs) used if not obj.docstring and stubs.docstring -- it treated 'has any docstring' as sufficient reason to keep the runtime object's docstring, without checking whether that docstring was genuinely authored (obj.analysis == 'static'/None) versus an auto-generated placeholder from runtime inspection (obj.analysis == 'dynamic'), even though griffe's Object model already tracks this via the analysis: Literal['static','dynamic'] | None attribute (set by the inspector for dynamically-analyzed members). Separately, _merge_overload_annotations(function, overloads) merged parameter/return type annotations from @overload stub signatures onto the base function but never propagated any overload's docstring onto it.

Testing

PASS - all 9 tests in test_merger.py pass (3 new + 6 existing); full suite (minus unrelated test_api.py which fails to import due to missing optional 'mkdocstrings' dependency in this environment, and test_git.py which fails due to a missing pytest-git plugin fixture, both pre-existing/unrelated to this change) shows 1742 passed, 22 skipped, 0 failures caused by this change.

Related Issue

#447

…ocstrings#447)
_merge_stubs_docstring() only filled in a docstring when the runtime
object had none at all, so an auto-generated placeholder docstring
from dynamic/runtime inspection (e.g. a SWIG/pybind11 C-level
signature string) was never replaced by the real, human-authored
docstring from a .pyi stub. Now it also overwrites when the object's
analysis is 'dynamic', while still leaving genuine statically-analyzed
docstrings untouched.
Also propagate an overload's docstring onto the base function when
merging overload-only stub methods, for the same dynamic/missing
docstring cases.
@pawamoy

Copy link
Copy Markdown
Member

Thanks @M001N but we already have a PR for this: #481. Let me know if I misunderstood the changes here.

@pawamoypawamoy closed this Aug 17, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@M001N@pawamoy
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix: In packages/griffelib/src/griffe/_internal/merger.py,... - #483

Closed
M001N wants to merge 1 commit into
mkdocstrings:mainfrom
M001N:oss-engine/e27b6eec-e96e1653
Closed

Fix: In packages/griffelib/src/griffe/_internal/merger.py,...#483
M001N wants to merge 1 commit into
mkdocstrings:mainfrom
M001N:oss-engine/e27b6eec-e96e1653

Conversation

@M001N

Copy link
Copy Markdown

Summary

  1. Changed _merge_stubs_docstring to overwrite obj.docstring whenever stubs.docstring exists AND (obj has no docstring OR obj.analysis == 'dynamic'), leaving statically-analyzed genuine docstrings untouched. 2) In _merge_overload_annotations, added a docstring fallback: if the base function has no docstring or is dynamically analyzed, take the docstring from the first overload that has one, before merging annotations.

Problem

mkdocstrings/griffe issue reference: #447

Root Cause

In packages/griffelib/src/griffe/_internal/merger.py, _merge_stubs_docstring(obj, stubs) used if not obj.docstring and stubs.docstring -- it treated 'has any docstring' as sufficient reason to keep the runtime object's docstring, without checking whether that docstring was genuinely authored (obj.analysis == 'static'/None) versus an auto-generated placeholder from runtime inspection (obj.analysis == 'dynamic'), even though griffe's Object model already tracks this via the analysis: Literal['static','dynamic'] | None attribute (set by the inspector for dynamically-analyzed members). Separately, _merge_overload_annotations(function, overloads) merged parameter/return type annotations from @overload stub signatures onto the base function but never propagated any overload's docstring onto it.

Testing

PASS - all 9 tests in test_merger.py pass (3 new + 6 existing); full suite (minus unrelated test_api.py which fails to import due to missing optional 'mkdocstrings' dependency in this environment, and test_git.py which fails due to a missing pytest-git plugin fixture, both pre-existing/unrelated to this change) shows 1742 passed, 22 skipped, 0 failures caused by this change.

Related Issue

#447

…ocstrings#447)
_merge_stubs_docstring() only filled in a docstring when the runtime
object had none at all, so an auto-generated placeholder docstring
from dynamic/runtime inspection (e.g. a SWIG/pybind11 C-level
signature string) was never replaced by the real, human-authored
docstring from a .pyi stub. Now it also overwrites when the object's
analysis is 'dynamic', while still leaving genuine statically-analyzed
docstrings untouched.
Also propagate an overload's docstring onto the base function when
merging overload-only stub methods, for the same dynamic/missing
docstring cases.
@pawamoy

Copy link
Copy Markdown
Member

Thanks @M001N but we already have a PR for this: #481. Let me know if I misunderstood the changes here.

@pawamoypawamoy closed this Aug 17, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@M001N@pawamoy
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix: In packages/griffelib/src/griffe/_internal/merger.py,... - #483

Closed
M001N wants to merge 1 commit into
mkdocstrings:mainfrom
M001N:oss-engine/e27b6eec-e96e1653
Closed

Fix: In packages/griffelib/src/griffe/_internal/merger.py,...#483
M001N wants to merge 1 commit into
mkdocstrings:mainfrom
M001N:oss-engine/e27b6eec-e96e1653

Conversation

@M001N

Copy link
Copy Markdown

Summary

  1. Changed _merge_stubs_docstring to overwrite obj.docstring whenever stubs.docstring exists AND (obj has no docstring OR obj.analysis == 'dynamic'), leaving statically-analyzed genuine docstrings untouched. 2) In _merge_overload_annotations, added a docstring fallback: if the base function has no docstring or is dynamically analyzed, take the docstring from the first overload that has one, before merging annotations.

Problem

mkdocstrings/griffe issue reference: #447

Root Cause

In packages/griffelib/src/griffe/_internal/merger.py, _merge_stubs_docstring(obj, stubs) used if not obj.docstring and stubs.docstring -- it treated 'has any docstring' as sufficient reason to keep the runtime object's docstring, without checking whether that docstring was genuinely authored (obj.analysis == 'static'/None) versus an auto-generated placeholder from runtime inspection (obj.analysis == 'dynamic'), even though griffe's Object model already tracks this via the analysis: Literal['static','dynamic'] | None attribute (set by the inspector for dynamically-analyzed members). Separately, _merge_overload_annotations(function, overloads) merged parameter/return type annotations from @overload stub signatures onto the base function but never propagated any overload's docstring onto it.

Testing

PASS - all 9 tests in test_merger.py pass (3 new + 6 existing); full suite (minus unrelated test_api.py which fails to import due to missing optional 'mkdocstrings' dependency in this environment, and test_git.py which fails due to a missing pytest-git plugin fixture, both pre-existing/unrelated to this change) shows 1742 passed, 22 skipped, 0 failures caused by this change.

Related Issue

#447

…ocstrings#447)
_merge_stubs_docstring() only filled in a docstring when the runtime
object had none at all, so an auto-generated placeholder docstring
from dynamic/runtime inspection (e.g. a SWIG/pybind11 C-level
signature string) was never replaced by the real, human-authored
docstring from a .pyi stub. Now it also overwrites when the object's
analysis is 'dynamic', while still leaving genuine statically-analyzed
docstrings untouched.
Also propagate an overload's docstring onto the base function when
merging overload-only stub methods, for the same dynamic/missing
docstring cases.
@pawamoy

Copy link
Copy Markdown
Member

Thanks @M001N but we already have a PR for this: #481. Let me know if I misunderstood the changes here.

@pawamoypawamoy closed this Aug 17, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@M001N@pawamoy
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Fix: In packages/griffelib/src/griffe/_internal/merger.py,... - #483

Closed
M001N wants to merge 1 commit into
mkdocstrings:mainfrom
M001N:oss-engine/e27b6eec-e96e1653
Closed

Fix: In packages/griffelib/src/griffe/_internal/merger.py,...#483
M001N wants to merge 1 commit into
mkdocstrings:mainfrom
M001N:oss-engine/e27b6eec-e96e1653

Conversation

@M001N

Copy link
Copy Markdown

Summary

  1. Changed _merge_stubs_docstring to overwrite obj.docstring whenever stubs.docstring exists AND (obj has no docstring OR obj.analysis == 'dynamic'), leaving statically-analyzed genuine docstrings untouched. 2) In _merge_overload_annotations, added a docstring fallback: if the base function has no docstring or is dynamically analyzed, take the docstring from the first overload that has one, before merging annotations.

Problem

mkdocstrings/griffe issue reference: #447

Root Cause

In packages/griffelib/src/griffe/_internal/merger.py, _merge_stubs_docstring(obj, stubs) used if not obj.docstring and stubs.docstring -- it treated 'has any docstring' as sufficient reason to keep the runtime object's docstring, without checking whether that docstring was genuinely authored (obj.analysis == 'static'/None) versus an auto-generated placeholder from runtime inspection (obj.analysis == 'dynamic'), even though griffe's Object model already tracks this via the analysis: Literal['static','dynamic'] | None attribute (set by the inspector for dynamically-analyzed members). Separately, _merge_overload_annotations(function, overloads) merged parameter/return type annotations from @overload stub signatures onto the base function but never propagated any overload's docstring onto it.

Testing

PASS - all 9 tests in test_merger.py pass (3 new + 6 existing); full suite (minus unrelated test_api.py which fails to import due to missing optional 'mkdocstrings' dependency in this environment, and test_git.py which fails due to a missing pytest-git plugin fixture, both pre-existing/unrelated to this change) shows 1742 passed, 22 skipped, 0 failures caused by this change.

Related Issue

#447

…ocstrings#447)
_merge_stubs_docstring() only filled in a docstring when the runtime
object had none at all, so an auto-generated placeholder docstring
from dynamic/runtime inspection (e.g. a SWIG/pybind11 C-level
signature string) was never replaced by the real, human-authored
docstring from a .pyi stub. Now it also overwrites when the object's
analysis is 'dynamic', while still leaving genuine statically-analyzed
docstrings untouched.
Also propagate an overload's docstring onto the base function when
merging overload-only stub methods, for the same dynamic/missing
docstring cases.
@pawamoy

Copy link
Copy Markdown
Member

Thanks @M001N but we already have a PR for this: #481. Let me know if I misunderstood the changes here.

@pawamoypawamoy closed this Aug 17, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@M001N@pawamoy
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix: In packages/griffelib/src/griffe/_internal/merger.py,... - #483

Closed
M001N wants to merge 1 commit into
mkdocstrings:mainfrom
M001N:oss-engine/e27b6eec-e96e1653
Closed

Fix: In packages/griffelib/src/griffe/_internal/merger.py,...#483
M001N wants to merge 1 commit into
mkdocstrings:mainfrom
M001N:oss-engine/e27b6eec-e96e1653

Conversation

@M001N

Copy link
Copy Markdown

Summary

  1. Changed _merge_stubs_docstring to overwrite obj.docstring whenever stubs.docstring exists AND (obj has no docstring OR obj.analysis == 'dynamic'), leaving statically-analyzed genuine docstrings untouched. 2) In _merge_overload_annotations, added a docstring fallback: if the base function has no docstring or is dynamically analyzed, take the docstring from the first overload that has one, before merging annotations.

Problem

mkdocstrings/griffe issue reference: #447

Root Cause

In packages/griffelib/src/griffe/_internal/merger.py, _merge_stubs_docstring(obj, stubs) used if not obj.docstring and stubs.docstring -- it treated 'has any docstring' as sufficient reason to keep the runtime object's docstring, without checking whether that docstring was genuinely authored (obj.analysis == 'static'/None) versus an auto-generated placeholder from runtime inspection (obj.analysis == 'dynamic'), even though griffe's Object model already tracks this via the analysis: Literal['static','dynamic'] | None attribute (set by the inspector for dynamically-analyzed members). Separately, _merge_overload_annotations(function, overloads) merged parameter/return type annotations from @overload stub signatures onto the base function but never propagated any overload's docstring onto it.

Testing

PASS - all 9 tests in test_merger.py pass (3 new + 6 existing); full suite (minus unrelated test_api.py which fails to import due to missing optional 'mkdocstrings' dependency in this environment, and test_git.py which fails due to a missing pytest-git plugin fixture, both pre-existing/unrelated to this change) shows 1742 passed, 22 skipped, 0 failures caused by this change.

Related Issue

#447

…ocstrings#447)
_merge_stubs_docstring() only filled in a docstring when the runtime
object had none at all, so an auto-generated placeholder docstring
from dynamic/runtime inspection (e.g. a SWIG/pybind11 C-level
signature string) was never replaced by the real, human-authored
docstring from a .pyi stub. Now it also overwrites when the object's
analysis is 'dynamic', while still leaving genuine statically-analyzed
docstrings untouched.
Also propagate an overload's docstring onto the base function when
merging overload-only stub methods, for the same dynamic/missing
docstring cases.
@pawamoy

Copy link
Copy Markdown
Member

Thanks @M001N but we already have a PR for this: #481. Let me know if I misunderstood the changes here.

@pawamoypawamoy closed this Aug 17, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@M001N@pawamoy
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix: In packages/griffelib/src/griffe/_internal/merger.py,... - #483

Closed
M001N wants to merge 1 commit into
mkdocstrings:mainfrom
M001N:oss-engine/e27b6eec-e96e1653
Closed

Fix: In packages/griffelib/src/griffe/_internal/merger.py,...#483
M001N wants to merge 1 commit into
mkdocstrings:mainfrom
M001N:oss-engine/e27b6eec-e96e1653

Conversation

@M001N

Copy link
Copy Markdown

Summary

  1. Changed _merge_stubs_docstring to overwrite obj.docstring whenever stubs.docstring exists AND (obj has no docstring OR obj.analysis == 'dynamic'), leaving statically-analyzed genuine docstrings untouched. 2) In _merge_overload_annotations, added a docstring fallback: if the base function has no docstring or is dynamically analyzed, take the docstring from the first overload that has one, before merging annotations.

Problem

mkdocstrings/griffe issue reference: #447

Root Cause

In packages/griffelib/src/griffe/_internal/merger.py, _merge_stubs_docstring(obj, stubs) used if not obj.docstring and stubs.docstring -- it treated 'has any docstring' as sufficient reason to keep the runtime object's docstring, without checking whether that docstring was genuinely authored (obj.analysis == 'static'/None) versus an auto-generated placeholder from runtime inspection (obj.analysis == 'dynamic'), even though griffe's Object model already tracks this via the analysis: Literal['static','dynamic'] | None attribute (set by the inspector for dynamically-analyzed members). Separately, _merge_overload_annotations(function, overloads) merged parameter/return type annotations from @overload stub signatures onto the base function but never propagated any overload's docstring onto it.

Testing

PASS - all 9 tests in test_merger.py pass (3 new + 6 existing); full suite (minus unrelated test_api.py which fails to import due to missing optional 'mkdocstrings' dependency in this environment, and test_git.py which fails due to a missing pytest-git plugin fixture, both pre-existing/unrelated to this change) shows 1742 passed, 22 skipped, 0 failures caused by this change.

Related Issue

#447

…ocstrings#447)
_merge_stubs_docstring() only filled in a docstring when the runtime
object had none at all, so an auto-generated placeholder docstring
from dynamic/runtime inspection (e.g. a SWIG/pybind11 C-level
signature string) was never replaced by the real, human-authored
docstring from a .pyi stub. Now it also overwrites when the object's
analysis is 'dynamic', while still leaving genuine statically-analyzed
docstrings untouched.
Also propagate an overload's docstring onto the base function when
merging overload-only stub methods, for the same dynamic/missing
docstring cases.
@pawamoy

Copy link
Copy Markdown
Member

Thanks @M001N but we already have a PR for this: #481. Let me know if I misunderstood the changes here.

@pawamoypawamoy closed this Aug 17, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@M001N@pawamoy
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Fix: In packages/griffelib/src/griffe/_internal/merger.py,... - #483

Closed
M001N wants to merge 1 commit into
mkdocstrings:mainfrom
M001N:oss-engine/e27b6eec-e96e1653
Closed

Fix: In packages/griffelib/src/griffe/_internal/merger.py,...#483
M001N wants to merge 1 commit into
mkdocstrings:mainfrom
M001N:oss-engine/e27b6eec-e96e1653

Conversation

@M001N

Copy link
Copy Markdown

Summary

  1. Changed _merge_stubs_docstring to overwrite obj.docstring whenever stubs.docstring exists AND (obj has no docstring OR obj.analysis == 'dynamic'), leaving statically-analyzed genuine docstrings untouched. 2) In _merge_overload_annotations, added a docstring fallback: if the base function has no docstring or is dynamically analyzed, take the docstring from the first overload that has one, before merging annotations.

Problem

mkdocstrings/griffe issue reference: #447

Root Cause

In packages/griffelib/src/griffe/_internal/merger.py, _merge_stubs_docstring(obj, stubs) used if not obj.docstring and stubs.docstring -- it treated 'has any docstring' as sufficient reason to keep the runtime object's docstring, without checking whether that docstring was genuinely authored (obj.analysis == 'static'/None) versus an auto-generated placeholder from runtime inspection (obj.analysis == 'dynamic'), even though griffe's Object model already tracks this via the analysis: Literal['static','dynamic'] | None attribute (set by the inspector for dynamically-analyzed members). Separately, _merge_overload_annotations(function, overloads) merged parameter/return type annotations from @overload stub signatures onto the base function but never propagated any overload's docstring onto it.

Testing

PASS - all 9 tests in test_merger.py pass (3 new + 6 existing); full suite (minus unrelated test_api.py which fails to import due to missing optional 'mkdocstrings' dependency in this environment, and test_git.py which fails due to a missing pytest-git plugin fixture, both pre-existing/unrelated to this change) shows 1742 passed, 22 skipped, 0 failures caused by this change.

Related Issue

#447

…ocstrings#447)
_merge_stubs_docstring() only filled in a docstring when the runtime
object had none at all, so an auto-generated placeholder docstring
from dynamic/runtime inspection (e.g. a SWIG/pybind11 C-level
signature string) was never replaced by the real, human-authored
docstring from a .pyi stub. Now it also overwrites when the object's
analysis is 'dynamic', while still leaving genuine statically-analyzed
docstrings untouched.
Also propagate an overload's docstring onto the base function when
merging overload-only stub methods, for the same dynamic/missing
docstring cases.
@pawamoy

Copy link
Copy Markdown
Member

Thanks @M001N but we already have a PR for this: #481. Let me know if I misunderstood the changes here.

@pawamoypawamoy closed this Aug 17, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@M001N@pawamoy