From 8c8fcb05ce1a0579415328dbff28b93eb75b87de Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Mon, 20 Jan 2025 12:42:04 +0100 Subject: [PATCH 01/28] add venv and macos DS_Store to gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 14e46c466a..941f9fdfae 100644 --- a/.gitignore +++ b/.gitignore @@ -5,8 +5,10 @@ .waf-* .waf3-* .lock-waf* +.DS_Store wingdbstub.py* mydbstub.py* +venv*/ .idea .cache From 35c28cae14384e1dd7cfb1bffee9ef86a8b5aa81 Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Tue, 21 Jan 2025 01:05:27 +0100 Subject: [PATCH 02/28] Docs: replaced deprecated getargspec --- sphinxtools/modulehunter.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/sphinxtools/modulehunter.py b/sphinxtools/modulehunter.py index 7626614a20..4a6acfaa12 100644 --- a/sphinxtools/modulehunter.py +++ b/sphinxtools/modulehunter.py @@ -13,7 +13,7 @@ from buildtools.config import phoenixDir -from inspect import getargspec, ismodule, getdoc, getmodule, getcomments, isfunction +from inspect import getfullargspec, ismodule, getdoc, getmodule, getcomments, isfunction from inspect import ismethoddescriptor, getsource, ismemberdescriptor, isgetsetdescriptor from inspect import isbuiltin, isclass, getfile, ismethod @@ -117,23 +117,21 @@ def analyze_params(obj, signature): return signature, param_tuple try: - arginfo = getargspec(obj) - # TODO: Switch to getfullargspec + arginfo = getfullargspec(obj) except (TypeError, ValueError): arginfo = None pevals = {} if arginfo: - args = arginfo[0] - argsvar = arginfo[1] + args = arginfo.args - if arginfo[3]: + if arginfo.defaults: - dl = len(arginfo[3]) + dl = len(arginfo.defaults) al = len(args) defargs = args[al-dl:al] - info = arginfo[3] + info = arginfo.defaults for d, i in zip(defargs, info): pevals[d] = i From 4bdae713a20a14f8ab6a6b6a9ad6b5a3de826b51 Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Tue, 21 Jan 2025 01:08:02 +0100 Subject: [PATCH 03/28] Docs: unpinned sphinx dependencies --- requirements/devel.txt | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/requirements/devel.txt b/requirements/devel.txt index 90bd36928c..05c73bd929 100644 --- a/requirements/devel.txt +++ b/requirements/devel.txt @@ -13,17 +13,16 @@ pytest-xdist pytest-forked pytest-timeout -sphinx==2.2.0 ; python_version >= '3.0' -sphinx==1.8.5 ; python_version < '3.0' -alabaster<0.7.14 -sphinxcontrib-applehelp<1.0.8 -sphinxcontrib-devhelp<1.0.6 -sphinxcontrib-htmlhelp<2.0.5 -sphinxcontrib-jsmath<1.0.2 -sphinxcontrib-qthelp<1.0.7 -sphinxcontrib-serializinghtml<1.1.10 -Jinja2==2.10 -markupsafe==1.1.1 -doc2dash==2.3.0 +sphinx; python_version >= '3.0' +alabaster +sphinxcontrib-applehelp +sphinxcontrib-devhelp +sphinxcontrib-htmlhelp +sphinxcontrib-jsmath +sphinxcontrib-qthelp +sphinxcontrib-serializinghtml +Jinja2 +markupsafe +doc2dash beautifulsoup4 typing-extensions; python_version < '3.11' From 129ac6d783b1a8dee6fdbbb27374ef06ceb6e131 Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Tue, 21 Jan 2025 01:11:06 +0100 Subject: [PATCH 04/28] Docs: test with Doxygen 1.9.1, same version as wxWidgets uses --- build.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.py b/build.py index d82b94b16b..f5113f46f1 100755 --- a/build.py +++ b/build.py @@ -83,9 +83,9 @@ wafCurrentVersion = '2.1.3' wafMD5 = '20d4d78744d728f0d6cd9665e79c087f' -doxygenCurrentVersion = '1.8.8' +doxygenCurrentVersion = '1.9.1' doxygenMD5 = { - 'darwin' : '71c590e6cab47100f23919a2696cc7fd', + 'darwin' : '6912d41cef5971fb07573190849a8a84', 'win32' : 'a3dcff227458e423c132f16f57e26510', 'linux' : '083b3d8f614b538696041c7364e0f334', } From 245888ebf89a33af35e8d2e43bdc1a18bcbf1a94 Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Tue, 21 Jan 2025 01:20:37 +0100 Subject: [PATCH 05/28] Docs: remove alabaster, add jquery as sphinx dependecies --- docs/sphinx/conf.py | 3 ++- requirements/devel.txt | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/sphinx/conf.py b/docs/sphinx/conf.py index 8184a0849d..1a489a2a0e 100644 --- a/docs/sphinx/conf.py +++ b/docs/sphinx/conf.py @@ -25,7 +25,8 @@ # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.todo', +extensions = ["sphinxcontrib.jquery", + 'sphinx.ext.todo', 'sphinx.ext.autodoc', 'sphinx.ext.autosummary', 'sphinx.ext.coverage', diff --git a/requirements/devel.txt b/requirements/devel.txt index 05c73bd929..87597da698 100644 --- a/requirements/devel.txt +++ b/requirements/devel.txt @@ -13,8 +13,8 @@ pytest-xdist pytest-forked pytest-timeout -sphinx; python_version >= '3.0' -alabaster +sphinx +sphinxcontrib-jquery sphinxcontrib-applehelp sphinxcontrib-devhelp sphinxcontrib-htmlhelp From b7b97eaa85e9c5c66d853f7241b02e63344873af Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Wed, 22 Jan 2025 20:26:00 +0100 Subject: [PATCH 06/28] Docs: update method formatting in css --- docs/sphinx/_static/css/phoenix.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sphinx/_static/css/phoenix.css b/docs/sphinx/_static/css/phoenix.css index 152b40148e..bb6e0c6f9d 100644 --- a/docs/sphinx/_static/css/phoenix.css +++ b/docs/sphinx/_static/css/phoenix.css @@ -551,7 +551,7 @@ cite, code, tt { letter-spacing: 0.01em; } -code.descname, code.descclassname { +code.descname, code.descclassname, span.sig-name { font-weight: bold; } a.headerlink { @@ -762,4 +762,4 @@ hr.overloadsep { border: none; width: 50%; float: left; -} \ No newline at end of file +} From 9696ae0637b4ecd546a141070a02ab2d0fabc0ca Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Wed, 22 Jan 2025 20:39:11 +0100 Subject: [PATCH 07/28] Docs: convert sphinx theme.conf to theme.toml --- docs/sphinx/phoenix_theme/theme.conf | 38 ---------------------------- docs/sphinx/phoenix_theme/theme.toml | 35 +++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 38 deletions(-) delete mode 100644 docs/sphinx/phoenix_theme/theme.conf create mode 100644 docs/sphinx/phoenix_theme/theme.toml diff --git a/docs/sphinx/phoenix_theme/theme.conf b/docs/sphinx/phoenix_theme/theme.conf deleted file mode 100644 index 6ae2b09885..0000000000 --- a/docs/sphinx/phoenix_theme/theme.conf +++ /dev/null @@ -1,38 +0,0 @@ -[theme] - -inherit = basic -stylesheet = phoenix.css -pygments_style = sphinx - -[options] - -disqus_comments = false -google_analytics = false - -rightsidebar = false -collapsiblesidebar = true -headerheight = 30px - -externalrefs = false - -footerbgcolor = #11303d -footertextcolor = #ffffff -sidebarbgcolor = #1c4e63 -sidebarbtncolor = #3c6e83 -sidebartextcolor = #ffffff -sidebarlinkcolor = #98dbcc -relbarbgcolor = #133f52 -relbartextcolor = #ffffff -relbarlinkcolor = #ffffff -bgcolor = #ffffff -textcolor = #000000 -headbgcolor = #f2f2f2 -headtextcolor = #20435c -headlinkcolor = #c60f0f -linkcolor = #355f7c -visitedlinkcolor = #355f7c -codebgcolor = #eeffcc -codetextcolor = #333333 - -bodyfont = sans-serif -headfont = 'Trebuchet MS', Verdana, Arial, Helvetica, sans-serif \ No newline at end of file diff --git a/docs/sphinx/phoenix_theme/theme.toml b/docs/sphinx/phoenix_theme/theme.toml new file mode 100644 index 0000000000..71ee4a4a05 --- /dev/null +++ b/docs/sphinx/phoenix_theme/theme.toml @@ -0,0 +1,35 @@ +[theme] +inherit = "basic" +stylesheets = [ + "phoenix.css", +] +pygments_style = { default = "sphinx" } + +[options] +disqus_comments = "false" +google_analytics = "false" +rightsidebar = "false" +collapsiblesidebar = "true" +headerheight = "30px" +externalrefs = "false" +footerbgcolor = "#11303d" +footertextcolor = "#ffffff" +sidebarbgcolor = "#1c4e63" +sidebarbtncolor = "#3c6e83" +sidebartextcolor = "#ffffff" +sidebarlinkcolor = "#98dbcc" +relbarbgcolor = "#133f52" +relbartextcolor = "#ffffff" +relbarlinkcolor = "#ffffff" +bgcolor = "#ffffff" +textcolor = "#000000" +headbgcolor = "#f2f2f2" +headtextcolor = "#20435c" +headlinkcolor = "#c60f0f" +linkcolor = "#355f7c" +visitedlinkcolor = "#355f7c" +codebgcolor = "#eeffcc" +codetextcolor = "#333333" +bodyfont = "sans-serif" +headfont = "'Trebuchet MS', Verdana, Arial, Helvetica, sans-serif" + From 102c88c33b87ae9aa020bd1c43f787f0465716be Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Wed, 22 Jan 2025 20:40:48 +0100 Subject: [PATCH 08/28] Docs: fix python warning about invalid escape sequence --- sphinxtools/postprocess.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinxtools/postprocess.py b/sphinxtools/postprocess.py index 0c66051db7..3b33de6127 100644 --- a/sphinxtools/postprocess.py +++ b/sphinxtools/postprocess.py @@ -339,7 +339,7 @@ def removeUnreferenced(input, class_summary, enum_base, unreferenced_classes, te def addSpacesToLinks(text): - regex = re.findall('\w:ref:`(.*?)`', text) + regex = re.findall(r'\w:ref:`(.*?)`', text) for reg in regex: text = text.replace(':ref:`%s`'%reg, ' :ref:`%s`'%reg) From 43dc209080f93445147d1dabf91391f09f31eb84 Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Wed, 22 Jan 2025 20:43:50 +0100 Subject: [PATCH 09/28] Docs: write sphinx warnings to log file in html directory --- build.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build.py b/build.py index f5113f46f1..b3d776f06f 100755 --- a/build.py +++ b/build.py @@ -1162,7 +1162,10 @@ def cmd_sphinx(options, args): pwd2 = pushDir(sphinxDir) buildDir = os.path.join(sphinxDir, 'build') htmlDir = os.path.join(phoenixDir(), 'docs', 'html') - runcmd('{} -m sphinx -b html -d {}/doctrees . {}'.format(PYTHON, buildDir, htmlDir)) + sphinx_log = os.path.join(htmlDir, 'warnings', 'sphinx_warnings.log') + + runcmd('{} -m sphinx --builder html --color --warning-file {} \ + --doctree-dir {}/doctrees . {}'.format(PYTHON, sphinx_log, buildDir, htmlDir)) del pwd2 msg('Postprocessing sphinx output...') From 2760598f096e318ad1c9237f346a6c5ad2d88a23 Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Wed, 22 Jan 2025 20:45:00 +0100 Subject: [PATCH 10/28] Docs: fixes and updates to sphinx configuration --- docs/sphinx/conf.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/docs/sphinx/conf.py b/docs/sphinx/conf.py index 1a489a2a0e..1ff4f1efb3 100644 --- a/docs/sphinx/conf.py +++ b/docs/sphinx/conf.py @@ -14,6 +14,7 @@ import sys, os from datetime import datetime +from buildtools.config import Config # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -37,7 +38,7 @@ templates_path = ['_templates'] # The suffix(es) of source filenames. -source_suffix = ['.txt'] +source_suffix = {'.txt': 'restructuredtext'} todo_include_todos = True todo_all_todos = True @@ -50,6 +51,7 @@ # The master toctree document. master_doc = 'index' +toc_object_entries = False # General information about the project. project = u'wxPython Phoenix' @@ -59,7 +61,6 @@ # |version| and |release|, also used in various other places throughout the # built documents. -from buildtools.config import Config cfg = Config(noWxConfig=True) # The short X.Y version. @@ -67,7 +68,6 @@ # The full version, including alpha/beta/rc tags. release = cfg.VERSION - # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None @@ -102,11 +102,10 @@ # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - # If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False +keep_warnings = False +show_warning_types = True +supress_warnings = [] # -- Options for HTML output --------------------------------------------------- @@ -166,11 +165,15 @@ # Additional templates that should be rendered to pages, maps page names to # template names. -html_additional_pages = {'gallery': 'gallery.html', 'main': 'main.html'} +html_additional_pages = {'gallery': 'gallery.html', + 'main': 'main.html'} # If false, no module index is generated. html_use_modindex = True +# A list of ignored prefixes for module index sorting. +modindex_common_prefix = ['wx.', 'wx.lib.', 'wx.py.'] + # If false, no index is generated. html_use_index = True @@ -281,3 +284,4 @@ # Enable experimental feature to split table cells. Use it # if you get "DelayedTable too big" errors pdf_splittables = True + From 166f59fd6449671c040c684a4b91d2e01e83c818 Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Thu, 23 Jan 2025 02:51:35 +0100 Subject: [PATCH 11/28] Docs: update postprocessing to account for sphinx v8 --- sphinxtools/constants.py | 8 +++--- sphinxtools/postprocess.py | 52 +++++++++++++++++++++++++------------- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/sphinxtools/constants.py b/sphinxtools/constants.py index 7ee45bfe1d..70debebd77 100644 --- a/sphinxtools/constants.py +++ b/sphinxtools/constants.py @@ -169,15 +169,17 @@ # A list of things used in the post-processing of the HTML files generated by Sphinx # This list is used only to insert a HTML horizontal line (
) after each method/function # description -HTML_REPLACE = ['module', 'function', 'method', 'class', 'classmethod', 'staticmethod', 'attribute'] +HTML_REPLACE = ['module', 'function', 'py function', 'class', 'py class', + 'method', 'py method', 'classmethod', 'staticmethod', + 'attribute', 'py attribute'] # Today's date representation for the Sphinx HTML docs TODAY = datetime.date.today().strftime('%d %B %Y') # Inheritance diagram external hyperlinks -PYTHON_DOCS = 'http://docs.python.org/library/' -NUMPY_DOCS = 'http://docs.scipy.org/doc/numpy/reference/generated/' +PYTHON_DOCS = 'https://docs.python.org/3/library/' +NUMPY_DOCS = 'https://numpy.org/doc/stable/reference/' EXTERN_INHERITANCE = {'UserDict.' : PYTHON_DOCS, 'ctypes.' : PYTHON_DOCS, diff --git a/sphinxtools/postprocess.py b/sphinxtools/postprocess.py index 3b33de6127..43848fcae4 100644 --- a/sphinxtools/postprocess.py +++ b/sphinxtools/postprocess.py @@ -657,22 +657,27 @@ def postProcess(folder, options): for indx, enum in enumerate(enum_base): html_file = os.path.split(enum_files[indx])[1] base = enum.split('.')[-1] - new = '(%s)'%(html_file, base, base) - enum_dict['(%s)'%enum] = new + new = '(%s)' % (html_file, base, base) + enum_dict['(%s)' % enum] = new for filename in fileNames: if "genindex" in filename or "modindex" in filename: continue - methods_done = properties_done = False + methods_done = attr_done = fn_done = False with textfile_open(filename, "rt") as fid: orig_text = text = fid.read() - text = text.replace('Overloaded Implementations:', 'Overloaded Implementations:') + text = text.replace('Overloaded Implementations:', + 'Overloaded Implementations:') + for item in HTML_REPLACE: - if item != 'class': - text = text.replace('
'%item, '\n

\n
'%item) + if item in ('class', 'py class'): + continue + + text = text.replace('
' % item, + '

' % item) newtext = '' splitted_text = text.splitlines() @@ -684,19 +689,32 @@ def postProcess(folder, options): line = line.replace('–

', '– ') line = line.replace('

', '') - if line.strip() == '

' or line.strip() == '


': - next_line = splitted_text[index+1] - stripline = next_line.strip() + if not fn_done and \ + line.strip() in ('

', + '

'): + + line = line[8:] + fn_done = True + + if not methods_done and \ + line.strip() in ('

', + '

', + '

', + '

'): + + line = '\n
\n

Methods

\n' + line[8:] + methods_done = True - # replace the
with a new headline for the first method or first property - if (stripline == '
' or stripline == '
' \ - or stripline == '
') and not methods_done: - line = '\n

Methods

\n' - methods_done = True + if not attr_done and \ + line.strip() in ('

', + '

'): - elif stripline == '
' and not properties_done: - line = '\n

Properties

\n' - properties_done = True + line = '\n
\n

Properties

\n' + line[8:] + attr_done = True newtext += line + '\n' From 5d70577b7e58cb1a6f2d18cd8da5b658a6c9dca5 Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Thu, 23 Jan 2025 03:16:43 +0100 Subject: [PATCH 12/28] Docs: small fixes for css and templates --- docs/sphinx/_static/css/phoenix.css | 16 ++++++++++++---- docs/sphinx/_templates/searchbox.html | 14 +++++++------- docs/sphinx/_templates/sourcelink.html | 10 ++++++---- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/docs/sphinx/_static/css/phoenix.css b/docs/sphinx/_static/css/phoenix.css index bb6e0c6f9d..bc230e93a4 100644 --- a/docs/sphinx/_static/css/phoenix.css +++ b/docs/sphinx/_static/css/phoenix.css @@ -144,9 +144,8 @@ div#searchbox { div#sourcelink { position: absolute; - bottom: 0; - font-style: italic; - font-size: small; + bottom: 0.2rem; + left: 0.5rem; } div.related { @@ -551,9 +550,10 @@ cite, code, tt { letter-spacing: 0.01em; } -code.descname, code.descclassname, span.sig-name { +code.descname, code.descclassname, span.sig-name, span.sig-prename { font-weight: bold; } + a.headerlink { color: #c60f0f; font-size: 0.8em; @@ -755,6 +755,14 @@ table.contentstable p.mybiglink { line-height: 150%; } +hr { + color: #ccc; + background-color: #ccc; + height: 1px; + border: none; + margin-bottom: 0.7rem; +} + hr.overloadsep { color: #0000FF; background-color: #0000FF; diff --git a/docs/sphinx/_templates/searchbox.html b/docs/sphinx/_templates/searchbox.html index e9c860192e..304595366b 100644 --- a/docs/sphinx/_templates/searchbox.html +++ b/docs/sphinx/_templates/searchbox.html @@ -8,14 +8,14 @@ :license: BSD, see LICENSE for details. #} {%- if pagename != "search" and builder != "singlehtml" %} - + + {%- endif %} diff --git a/docs/sphinx/_templates/sourcelink.html b/docs/sphinx/_templates/sourcelink.html index 2692973ecc..25ce54a93b 100644 --- a/docs/sphinx/_templates/sourcelink.html +++ b/docs/sphinx/_templates/sourcelink.html @@ -8,8 +8,10 @@ :license: BSD, see LICENSE for details. #} {%- if show_source and has_source and sourcename %} - + {%- endif %} From ddc7a345a4da3d22361824606419a48ad3d7aaf3 Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Thu, 23 Jan 2025 14:49:39 +0100 Subject: [PATCH 13/28] Docs: doc2dash now needs file-extension added to the --name --- build.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.py b/build.py index b3d776f06f..7d328584fc 100755 --- a/build.py +++ b/build.py @@ -1022,8 +1022,8 @@ def cmd_docset_py(options, args): sys.exit(1) # clear out any old docset build - name = 'wxPython-{}'.format(cfg.VERSION) - docset = posixjoin('dist', '{}.docset'.format(name)) + name = 'wxPython-{}.docset'.format(cfg.VERSION) + docset = posixjoin('dist', name) if os.path.isdir(docset): shutil.rmtree(docset) @@ -1040,7 +1040,7 @@ def cmd_docset_py(options, args): # Remove the sidebar from the pages in the docset msg('Removing sidebar from docset pages...') - _removeSidebar(opj('dist', name+'.docset', 'Contents', 'Resources', 'Documents')) + _removeSidebar(opj('dist', name, 'Contents', 'Resources', 'Documents')) # build the tarball msg('Archiving Phoenix docset...') @@ -1049,7 +1049,7 @@ def cmd_docset_py(options, args): if os.path.exists(tarfilename): os.remove(tarfilename) with tarfile.open(name=tarfilename, mode="w:gz") as tarball: - tarball.add(opj('dist', name+'.docset'), name+'.docset', filter=_setTarItemPerms) + tarball.add(opj('dist', name), name, filter=_setTarItemPerms) if options.upload: uploadPackage(tarfilename, options, keep=5, From f2cc091c56f802a2975fbbad7e84fdc51a31fe73 Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Thu, 23 Jan 2025 14:51:39 +0100 Subject: [PATCH 14/28] Docs: remove explicid install of sphinx dependencies --- requirements/devel.txt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/requirements/devel.txt b/requirements/devel.txt index 87597da698..87f7eb23af 100644 --- a/requirements/devel.txt +++ b/requirements/devel.txt @@ -15,12 +15,6 @@ pytest-timeout sphinx sphinxcontrib-jquery -sphinxcontrib-applehelp -sphinxcontrib-devhelp -sphinxcontrib-htmlhelp -sphinxcontrib-jsmath -sphinxcontrib-qthelp -sphinxcontrib-serializinghtml Jinja2 markupsafe doc2dash From fd2b07e4c60f520f3926a862675dd71dd9950e87 Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Fri, 24 Jan 2025 14:55:31 +0100 Subject: [PATCH 15/28] Docs: remove outdated modindex entry in sphinx conf --- docs/sphinx/conf.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/sphinx/conf.py b/docs/sphinx/conf.py index 1ff4f1efb3..2158acc8c9 100644 --- a/docs/sphinx/conf.py +++ b/docs/sphinx/conf.py @@ -168,9 +168,7 @@ html_additional_pages = {'gallery': 'gallery.html', 'main': 'main.html'} -# If false, no module index is generated. -html_use_modindex = True - +html_domain_indices = {'py-modindex'} # A list of ignored prefixes for module index sorting. modindex_common_prefix = ['wx.', 'wx.lib.', 'wx.py.'] From b4cb78119a35c4e2dfd72ea3f60846998b32277c Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Fri, 24 Jan 2025 14:56:10 +0100 Subject: [PATCH 16/28] Docs: fix external link to numpy documentation --- sphinxtools/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinxtools/constants.py b/sphinxtools/constants.py index 70debebd77..67bb8fc860 100644 --- a/sphinxtools/constants.py +++ b/sphinxtools/constants.py @@ -179,7 +179,7 @@ # Inheritance diagram external hyperlinks PYTHON_DOCS = 'https://docs.python.org/3/library/' -NUMPY_DOCS = 'https://numpy.org/doc/stable/reference/' +NUMPY_DOCS = 'https://numpy.org/doc/stable/reference/generated/' EXTERN_INHERITANCE = {'UserDict.' : PYTHON_DOCS, 'ctypes.' : PYTHON_DOCS, From 9dd6d9d0e06a99505258526958256c14ae222f2d Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Fri, 24 Jan 2025 14:57:42 +0100 Subject: [PATCH 17/28] Docs: fix 2 small errors in sphinx REST files --- docs/sphinx/rest_substitutions/overviews/high_dpi_overview.rst | 2 +- docs/sphinx/rest_substitutions/overviews/index.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sphinx/rest_substitutions/overviews/high_dpi_overview.rst b/docs/sphinx/rest_substitutions/overviews/high_dpi_overview.rst index 210a0bb7ca..4dc0f45156 100644 --- a/docs/sphinx/rest_substitutions/overviews/high_dpi_overview.rst +++ b/docs/sphinx/rest_substitutions/overviews/high_dpi_overview.rst @@ -1,7 +1,7 @@ .. include:: headings.inc -.. _html overview: +.. _high dpi overview: ====================================== |phoenix_title| **High DPI Overview** diff --git a/docs/sphinx/rest_substitutions/overviews/index.rst b/docs/sphinx/rest_substitutions/overviews/index.rst index 190e616f50..5439305b81 100644 --- a/docs/sphinx/rest_substitutions/overviews/index.rst +++ b/docs/sphinx/rest_substitutions/overviews/index.rst @@ -23,7 +23,7 @@ and launch the wxPython demo for you. .. note:: If you wish to help in the documentation effort, the main docstrings guidelines are outlined in the - `Docstring Guidelines `_ + `Docstring Guidelines `_ document. From 5951052d0ee80b10b864f68d8fcc7682ef5081ca Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Sun, 26 Jan 2025 00:33:36 +0100 Subject: [PATCH 18/28] Docs: update template and css for control screenshots in the docs --- docs/sphinx/_static/css/phoenix.css | 30 +++++++++++++++++++++++++++++ sphinxtools/templates.py | 25 ++++++++++++------------ 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/docs/sphinx/_static/css/phoenix.css b/docs/sphinx/_static/css/phoenix.css index bc230e93a4..c628267788 100644 --- a/docs/sphinx/_static/css/phoenix.css +++ b/docs/sphinx/_static/css/phoenix.css @@ -254,6 +254,36 @@ div.footer { color: rgb(0,102,204); } +.control-appearance-figures { + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: end; + column-gap: 1.0em; + justify-content: space-around; +} + +.appearance-figure { + margin: 0; + padding: 0; + max-width: 500px; + flex-shrink: 1; +} + +.appearance-figure img { + max-height: 320px; +} + +figcaption { + text-align: center; + text-align-last: center; +} + +figcaption a.headerlink { + margin: 0; + padding: 0; +} + .floatleft { position: relative; float:left; diff --git a/sphinxtools/templates.py b/sphinxtools/templates.py index 03fbeee89d..97832dd66e 100644 --- a/sphinxtools/templates.py +++ b/sphinxtools/templates.py @@ -60,26 +60,27 @@ | -.. figure:: _static/images/widgets/fullsize/wxmsw/%s - :alt: wxMSW - :figclass: floatleft +.. container:: control-appearance-figures - **wxMSW** + .. figure:: _static/images/widgets/fullsize/wxmsw/%s + :alt: wxMSW + :figclass: appearance-figure + **wxMSW** -.. figure:: _static/images/widgets/fullsize/wxmac/%s - :alt: wxMAC - :figclass: floatright - **wxMAC** + .. figure:: _static/images/widgets/fullsize/wxmac/%s + :alt: wxMAC + :figclass: appearance-figure + **wxMAC** -.. figure:: _static/images/widgets/fullsize/wxgtk/%s - :alt: wxGTK - :figclass: floatcenter - **wxGTK** + .. figure:: _static/images/widgets/fullsize/wxgtk/%s + :alt: wxGTK + :figclass: appearance-figure + **wxGTK** | From d2daf2c31b214d87daa0430f62d53d94381c4fad Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Mon, 27 Jan 2025 21:01:57 +0100 Subject: [PATCH 19/28] Docs: move a layout tweak from postprocessor to generator --- etgtools/sphinx_generator.py | 2 +- sphinxtools/postprocess.py | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/etgtools/sphinx_generator.py b/etgtools/sphinx_generator.py index b64ae2f332..88a2dc9396 100644 --- a/etgtools/sphinx_generator.py +++ b/etgtools/sphinx_generator.py @@ -2893,7 +2893,7 @@ def Reformat(self, stream): pickleItem(desc, self.current_module, self.class_name, 'class') if self.overloads: - docstrings += '\n\n%s|overload| Overloaded Implementations:\n\n'%spacer + docstrings += '\n\n%s|overload| **Overloaded Implementations:**\n\n'%spacer docstrings += '%s:html:`

`\n\n'%spacer for index, over in enumerate(self.overloads): diff --git a/sphinxtools/postprocess.py b/sphinxtools/postprocess.py index 43848fcae4..e61ac73f90 100644 --- a/sphinxtools/postprocess.py +++ b/sphinxtools/postprocess.py @@ -669,9 +669,6 @@ def postProcess(folder, options): with textfile_open(filename, "rt") as fid: orig_text = text = fid.read() - text = text.replace('Overloaded Implementations:', - 'Overloaded Implementations:') - for item in HTML_REPLACE: if item in ('class', 'py class'): continue From 09772adbea7cb6a59ae54e9b6724e888ca05573d Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Mon, 27 Jan 2025 21:03:47 +0100 Subject: [PATCH 20/28] Docs: fix a sphinx warning by stripping trailing whitespace from ref --- etgtools/sphinx_generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etgtools/sphinx_generator.py b/etgtools/sphinx_generator.py index 88a2dc9396..b39e310be3 100644 --- a/etgtools/sphinx_generator.py +++ b/etgtools/sphinx_generator.py @@ -1592,7 +1592,7 @@ def Join(self, with_tail=True): text = '' elif not isNumeric(text): - text = '``%s``'%text + text = '``%s``' % text.strip() elif 'funcmacro' in values: if '(' in stripped: From ed5f392fdba8ddc46a8b32653df7504ad5852b48 Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Wed, 29 Jan 2025 02:15:06 +0100 Subject: [PATCH 21/28] Docs: better flow for sidebar elements --- docs/sphinx/_static/css/phoenix.css | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/docs/sphinx/_static/css/phoenix.css b/docs/sphinx/_static/css/phoenix.css index c628267788..47f46fd781 100644 --- a/docs/sphinx/_static/css/phoenix.css +++ b/docs/sphinx/_static/css/phoenix.css @@ -114,6 +114,10 @@ div.document { div.sphinxsidebarwrapper { padding: 10px 5px 0 10px; + min-height: 98%; + display: flex; + flex-direction: column; + justify-content: space-between; } div.document-no-sidebar { @@ -138,14 +142,14 @@ div.sphinxsidebar { bottom: 0; } -div#searchbox { - margin-top: 30px; +#searchbox { + margin-top: 1.8em; + flex-grow: 1; } -div#sourcelink { - position: absolute; - bottom: 0.2rem; - left: 0.5rem; +#sourcelink { + margin-top: 1.8em; + flex-grow: 0; } div.related { From 5c0752aab167f7b59d0e8fad30b60ef9f51cc80e Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Wed, 29 Jan 2025 02:52:03 +0100 Subject: [PATCH 22/28] Docs: add sticky header and correct z-order of elements --- docs/sphinx/_static/css/phoenix.css | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/sphinx/_static/css/phoenix.css b/docs/sphinx/_static/css/phoenix.css index 47f46fd781..da43c2684c 100644 --- a/docs/sphinx/_static/css/phoenix.css +++ b/docs/sphinx/_static/css/phoenix.css @@ -107,9 +107,10 @@ div.headerimage-noshow { } div.document { - background-color: rgb(230,230,230); - position: relative; - margin-left: 240px; + background-color: rgb(230,230,230); + position: relative; + margin-left: 240px; + z-index: 500; } div.sphinxsidebarwrapper { @@ -140,6 +141,7 @@ div.sphinxsidebar { left: 0; top: 30px; bottom: 0; + z-index: 600; } #searchbox { @@ -159,9 +161,9 @@ div.related { font-size: 90%; line-height: normal; height: auto; - left: 0; - right: 0; + position: sticky; top: 0; + z-index: 999; } div.related ul { From 4baa5871765eff293f7ec7c67b283af4725d22fb Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Wed, 29 Jan 2025 11:43:40 +0100 Subject: [PATCH 23/28] Docs: fix sphinx error which can't find image path on windows --- etgtools/sphinx_generator.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/etgtools/sphinx_generator.py b/etgtools/sphinx_generator.py index b39e310be3..cbdcdf9b4d 100644 --- a/etgtools/sphinx_generator.py +++ b/etgtools/sphinx_generator.py @@ -1163,7 +1163,9 @@ def Join(self, with_tail=True): rel_path = os.path.normpath(static_path[rel_path_index:]) docstrings = '\n\n' - docstrings += '.. figure:: %s\n' % rel_path + # Sphinx (on windows) can't parse windows style paths when reading + # .rst files. Therefore paths are written unix style. + docstrings += '.. figure:: %s\n' % rel_path.replace('\\', '/') docstrings += ' :align: center\n\n\n' docstrings += '|\n\n' From 8c8ff3e8c66d92bb7573ff2071e5da406e3409a2 Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Sat, 1 Feb 2025 15:19:10 +0100 Subject: [PATCH 24/28] Docs: add script that sorts wxStyledTextCtrl into categories --- etg/_stc.py | 2 + sphinxtools/stc_doc_postprocess.py | 247 +++++++++++++++++++++++++++++ 2 files changed, 249 insertions(+) create mode 100644 sphinxtools/stc_doc_postprocess.py diff --git a/etg/_stc.py b/etg/_stc.py index bcf8b55f62..12197e612d 100644 --- a/etg/_stc.py +++ b/etg/_stc.py @@ -9,6 +9,7 @@ import etgtools import etgtools.tweaker_tools as tools +import sphinxtools.stc_doc_postprocess as postprocess PACKAGE = "wx" MODULE = "_stc" @@ -259,6 +260,7 @@ def run(): #----------------------------------------------------------------- tools.doCommonTweaks(module) tools.runGenerators(module) + postprocess.categorise_methods() diff --git a/sphinxtools/stc_doc_postprocess.py b/sphinxtools/stc_doc_postprocess.py new file mode 100644 index 0000000000..8ac6ea0c88 --- /dev/null +++ b/sphinxtools/stc_doc_postprocess.py @@ -0,0 +1,247 @@ +# -*- coding: utf-8 -*- +#--------------------------------------------------------------------------- +# Name: sphinxtools/stc_doc_postprocess.py +# Author: Matthias (neofelis2X) +# +# Created: 27-Jan-2025 +# Copyright: (c) 2010-2025 +# License: wxWindows License +#--------------------------------------------------------------------------- +""" +This script postprocesses the ReST documentation file of the +wx.stc.StyledTextCtrl class. This class has more than 760 methods, +so the 'Method Summary' is sorted into categories. +""" + +import os +import xml.etree.ElementTree as ET + +from sphinxtools.constants import XMLSRC, SPHINXROOT + +STC_CLASS_XML = os.path.join(XMLSRC, "classwx_styled_text_ctrl.xml") +STC_RST = os.path.join(SPHINXROOT, "wx.stc.StyledTextCtrl.txt") +TBL_SEP = "======================================================" + \ + "========================== ===========================" + \ + "=====================================================\n" + +def _parse_method_categories(xml_file: str): + """ + Parses values from an xml file containing categories, method + names and occasional additional category descriptions. + """ + + tree = ET.parse(xml_file) + root = tree.getroot() + + method_mapping = {} + current_category = "empty" + current_pretty = "Empty" + description = '' + new_header = False + + for elem in root.iter(): + if elem.tag == 'listofallmembers': + break + + if elem.tag == "header" and isinstance(elem.text, str): + if "Raw variants" in elem.text: + current_category = "Raw Variants" + current_pretty = "Raw Variants" + else: + current_category = elem.text + current_pretty = _clean_category_title(current_category) + + description = '' + new_header = True + + elif elem.tag == "description" and new_header: + para = elem.findall("para") + description = _parse_description(para) + + new_header = False + + elif elem.tag == "name": + method_mapping[elem.text] = (current_pretty, description) + + return method_mapping + +def _parse_description(para): + """ + Goes through some extra steps to parse method descriptions from references. + """ + description = '' + + if len(para) > 1: + txt = para[1].itertext() + sect = para[1].findall("simplesect") + + if len(sect): + description = "".join(txt).split('(', maxsplit=1)[0].strip() + description = f".. seealso:: :meth:`~wx.stc.StyledTextCtrl.{description}`" + else: + description = "".join(txt).strip() + + return description + +def _parse_stcdoc_segments(file: str): + """ + Read the reStructuredText file and split relevant parts into textblocks. + """ + + m_count = 0 # Count the collected methods + pretext = '' # All text before the 'Method Summary' + parse_pretext = True + links = [] # + index_links_done = False + methods = {} + current_method = '' + parse_methods = False + posttext = '' # All text after the 'Method Summary' + parse_posttext = False + + with open(file, 'r', encoding="utf-8") as f: + for line in f: + + if parse_posttext: + posttext += line + + elif not index_links_done and line.startswith("- `"): + # Rewrite index links + new_link = line.split('<')[0].strip("-_ `") + new_link = _clean_category_title(new_link) + pretext += f"- `{new_link}`_\n" + links.append(new_link) + + if "Constructors" in line: + awm = "Additional wxPython Methods" + pretext += f"- `{awm}`_\n" + links.append(awm) + + elif "Text area methods" in line: + index_links_done = True + + elif line.startswith(":meth:`~wx.stc.StyledTextCtrl."): + # Collect all methods from 'Method Summary' + m_count += 1 + parse_pretext = False + parse_methods = True + + current_method = line[30:].split('`')[0].strip() + + if not current_method: + print("stc_doc_postprocess:: WARNING: Invalid method name") + else: + methods[current_method] = line + + elif parse_methods and line.strip() == '|': + parse_methods = False + parse_posttext = True + posttext = '\n' + line + + elif parse_pretext: + if not TBL_SEP.strip() in line: + pretext += line + + # print(f"Debug: Read {m_count} methods from file.") + return (pretext, methods, posttext, links) + +def _methods_to_categories(methods, mapping): + """ + Find the right category for each method. Around 20 methods are + unique in wxPython and will be put into their own group. + """ + grouped_methods = {} + + for name, text in methods.items(): + + if name in ("__init__", "Create"): + category = "Constructors and Related Methods" + description = '' + text = text.replace("Ctor.", '') + + elif name in mapping: + category = mapping[name][0] + description = mapping[name][1] + + else: + category = "Additional wxPython Methods" + description = "In addition to the standard Scintilla " + \ + "functions, wxPython includes the following " + \ + "methods to better integrate better with other features." + + if category in grouped_methods: + grouped_methods[category][0].append(text) + grouped_methods[category][1] = description + else: + grouped_methods[category] = [[text, ], ''] + + if description: + grouped_methods[category][1] = description + + return grouped_methods + +def _clean_category_title(raw_title): + """ + Applies proper title case to category titles. + """ + category_title = raw_title.strip().title().replace("And", "and") + category_title = category_title.replace("Wxstyledtextctrl", "wxStyledTextCtrl") + category_title = category_title.replace("Wxpython", "wxPython") + + return category_title + +def _assemble_method_category(category, cat_methods, cc): + """ + Assembles all method ReST directives that go into one category. + """ + group = '' + + dashline = '-' * len(category) + group = f"\n{category}\n{dashline}\n\n" + + if cat_methods[1]: + group += '\n' + cat_methods[1] + '\n\n' + + group += TBL_SEP + + for method in cat_methods[0]: + cc += 1 + group += method + + group += TBL_SEP + '\n' + + return group, cc + +def _output_reordered_doc(pretext, posttext, grouped_methods): + """ + Writes the formatted ReST to a file. Overwrites the original file. + """ + m_count = 0 # count the written methods + doc = pretext + + for category, methods in grouped_methods.items(): + cat, m_count = _assemble_method_category(category, methods, m_count) + doc += cat + + doc += posttext + + with open(STC_RST, 'w', encoding="utf-8") as f: + f.write(doc) + + # print(f"Debug: Wrote {m_count} methods to new file.") + +def categorise_methods(): + """ + Loads the ReST file, categorises the method summary and saves a new file. + Thr original file is overwritten. + """ + mapping = _parse_method_categories(STC_CLASS_XML) + pre, methods, post, links = _parse_stcdoc_segments(STC_RST) + grouped_methods = _methods_to_categories(methods, mapping) + sorted_methods = {key: grouped_methods[key] for key in links} + _output_reordered_doc(pre, post, sorted_methods) + + +if __name__ == "__main__": + categorise_methods() + From b373f253a053c5d6eb2c7d3600413ebb64dc870c Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Sat, 1 Feb 2025 15:21:06 +0100 Subject: [PATCH 25/28] Docs: fix various minor sphinx parsing issues --- wx/lib/agw/scrolledthumbnail.py | 2 +- wx/lib/masked/maskededit.py | 116 +++++++++++++------------ wx/lib/masked/numctrl.py | 2 +- wx/lib/plot/examples/demo.py | 8 +- wx/lib/plot/examples/simple_example.py | 4 +- wx/lib/plot/polyobjects.py | 39 ++++----- 6 files changed, 89 insertions(+), 82 deletions(-) diff --git a/wx/lib/agw/scrolledthumbnail.py b/wx/lib/agw/scrolledthumbnail.py index 2215581646..ce8f187e2d 100644 --- a/wx/lib/agw/scrolledthumbnail.py +++ b/wx/lib/agw/scrolledthumbnail.py @@ -71,7 +71,7 @@ class also has methods to perform thumbnail operations such as rotation, notes that :class:`ThumbnailCtrl` wouldn't have been so fast and complete without the suggestions and hints from Peter Damoc. -Usage: +Usage ===== Usage example:: diff --git a/wx/lib/masked/maskededit.py b/wx/lib/masked/maskededit.py index 87335d4273..b99d054342 100644 --- a/wx/lib/masked/maskededit.py +++ b/wx/lib/masked/maskededit.py @@ -117,7 +117,7 @@ X Allow string.letters, string.punctuation, string.digits & Allow string.punctuation only (doesn't include all unicode symbols) \* Allow any visible character - | explicit field boundary (takes no space in the control; allows mix + \| Explicit field boundary (takes no space in the control; allows mix of adjacent mask characters to be treated as separate fields, eg: '&|###' means "field 0 = '&', field 1 = '###'", but there's no fixed characters in between. @@ -189,59 +189,67 @@ formatcodes These other properties can be passed to the class when instantiating it: Formatcodes are specified as a string of single character formatting - codes that modify behavior of the control:: - - _ Allow spaces - ! Force upper - ^ Force lower - R Right-align field(s) - r Right-insert in field(s) (implies R) - < Stay in field until explicit navigation out of it - - > Allow insert/delete within partially filled fields (as - opposed to the default "overwrite" mode for fixed-width - masked edit controls.) This allows single-field controls - or each field within a multi-field control to optionally - behave more like standard text controls. - (See EMAIL or phone number autoformat examples.) - - *Note: This also governs whether backspace/delete operations - shift contents of field to right of cursor, or just blank the - erased section. - - Also, when combined with 'r', this indicates that the field - or control allows right insert anywhere within the current - non-empty value in the field. (Otherwise right-insert behavior - is only performed to when the entire right-insertable field is - selected or the cursor is at the right edge of the field.* - - - , Allow grouping character in integer fields of numeric controls - and auto-group/regroup digits (if the result fits) when leaving - such a field. (If specified, .SetValue() will attempt to - auto-group as well.) - ',' is also the default grouping character. To change the - grouping character and/or decimal character, use the groupChar - and decimalChar parameters, respectively. - Note: typing the "decimal point" character in such fields will - clip the value to that left of the cursor for integer - fields of controls with "integer" or "floating point" masks. - If the ',' format code is specified, this will also cause the - resulting digits to be regrouped properly, using the current - grouping character. - - Prepend and reserve leading space for sign to mask and allow - signed values (negative #s shown in red by default.) Can be - used with argument useParensForNegatives (see below.) - 0 integer fields get leading zeros - D Date[/time] field - T Time field - F Auto-Fit: the control calculates its size from - the length of the template mask - V validate entered chars against validRegex before allowing them - to be entered vs. being allowed by basic mask and then having - the resulting value just colored as invalid. - (See USSTATE autoformat demo for how this can be used.) - S select entire field when navigating to new field + codes that modify behavior of the control: + + ======= ========================================================== + _ Allow spaces + ! Force upper + ^ Force lower + R Right-align field(s) + r Right-insert in field(s) (implies R) + < Stay in field until explicit navigation out of it + + > Allow insert/delete within partially filled fields (as + opposed to the default "overwrite" mode for fixed-width + masked edit controls.) This allows single-field controls + or each field within a multi-field control to optionally + behave more like standard text controls. + (See EMAIL or phone number autoformat examples.) + + .. note:: + + This also governs whether backspace/delete operations + shift contents of field to right of cursor, or just blank + the erased section. + + Also, when combined with 'r', this indicates that the field + or control allows right insert anywhere within the current + non-empty value in the field. (Otherwise right-insert behavior + is only performed to when the entire right-insertable field is + selected or the cursor is at the right edge of the field. + + + , Allow grouping character in integer fields of numeric controls + and auto-group/regroup digits (if the result fits) when leaving + such a field. (If specified, .SetValue() will attempt to + auto-group as well.) + ',' is also the default grouping character. To change the + grouping character and/or decimal character, use the groupChar + and decimalChar parameters, respectively. + + .. note:: + + Typing the "decimal point" character in such fields will + clip the value to that left of the cursor for integer + fields of controls with "integer" or "floating point" masks. + + If the ',' format code is specified, this will also cause the + resulting digits to be regrouped properly, using the current + grouping character. + \- Prepend and reserve leading space for sign to mask and allow + signed values (negative #s shown in red by default.) Can be + used with argument useParensForNegatives (see below.) + 0 Integer fields get leading zeros + D Date[/time] field + T Time field + F Auto-Fit: the control calculates its size from + the length of the template mask + V Validate entered chars against validRegex before allowing them + to be entered vs. being allowed by basic mask and then having + the resulting value just colored as invalid. + (See USSTATE autoformat demo for how this can be used.) + S Select entire field when navigating to new field + ======= ========================================================== fillChar diff --git a/wx/lib/masked/numctrl.py b/wx/lib/masked/numctrl.py index d0177d1903..284f7a5a13 100644 --- a/wx/lib/masked/numctrl.py +++ b/wx/lib/masked/numctrl.py @@ -89,7 +89,7 @@ emptyBackgroundColour = "White", validBackgroundColour = "White", invalidBackgroundColour = "Yellow", - autoSize = True + autoSize = True, ) diff --git a/wx/lib/plot/examples/demo.py b/wx/lib/plot/examples/demo.py index ce1767b190..4bb63437b4 100644 --- a/wx/lib/plot/examples/demo.py +++ b/wx/lib/plot/examples/demo.py @@ -7,10 +7,14 @@ demo.py ======= +.. highlight:: shell + This is a demo showing some of the capabilities of the :mod:`wx.lib.plot` -package. It is intended to be run as a standalone script via:: +package. + +It is intended to be run as a standalone script via:: - user@host:.../site-packages/wx/lib/plot$ python examples/demo.py + user@host:.../site-packages/wx/lib/plot$ python examples/demo.py """ __docformat__ = "restructuredtext en" diff --git a/wx/lib/plot/examples/simple_example.py b/wx/lib/plot/examples/simple_example.py index e8f539c87f..b120bfe077 100644 --- a/wx/lib/plot/examples/simple_example.py +++ b/wx/lib/plot/examples/simple_example.py @@ -1,10 +1,12 @@ # -*- coding: utf-8 -*- """ +.. highlight:: shell + A simple example showing how to use lib.plot from wxPython. It is intended to be run as a standalone script via:: - user@host:.../site-packages/wx/lib/plot$ python examples/simple_example.py + user@host:.../site-packages/wx/lib/plot$ python examples/simple_example.py """ __docformat__ = "restructuredtext en" diff --git a/wx/lib/plot/polyobjects.py b/wx/lib/plot/polyobjects.py index be9ab83124..81f5d27b3e 100644 --- a/wx/lib/plot/polyobjects.py +++ b/wx/lib/plot/polyobjects.py @@ -120,7 +120,7 @@ def symLogScale(self): :type: tuple of bool, length 2 :raises ValueError: when setting an invalid value - .. notes:: + .. note:: This is a simplified example of how SymLog works:: @@ -163,7 +163,7 @@ def symLogThresh(self): :type: tuple of float, length 2 :raises ValueError: when setting an invalid value - .. notes:: + .. note:: This is a simplified example of how SymLog works:: @@ -221,7 +221,7 @@ def points(self): :setter: Sets the value of points. :type: list of `(x, y)` pairs - .. Note:: + .. note:: Only set unscaled points - do not perform the log, abs, or symlog adjustments yourself. @@ -1010,17 +1010,10 @@ def calcBpData(self, data=None): outliers are outside of 1.5 * IQR - Parameters - ---------- - data : array-like - The data to plot - - Returns - ------- - bpdata : collections.namedtuple - Descriptive statistics for data: + :param array-like data: The data to plot + :return bpdata: Descriptive statistics for data: (min_data, low_whisker, q25, median, q75, high_whisker, max_data) - + :rtype: collections.namedtuple """ data = self._clean_data(data) @@ -1066,20 +1059,20 @@ def draw(self, dc, printerScale, coord=None): """ Draws a box plot on the DC. - Notes - ----- - The following draw order is required: + .. note:: + + The following draw order is required: - 1. First the whisker line - 2. Then the IQR box - 3. Lasly the median line. + 1. First the whisker line + 2. Then the IQR box + 3. Lasly the median line. - This is because + This is because - + The whiskers are drawn as single line rather than two lines - + The median line must be visible over the box if the box has a fill. + + The whiskers are drawn as single line rather than two lines + + The median line must be visible over the box if the box has a fill. - Other than that, the draw order can be changed. + Other than that, the draw order can be changed. """ self._draw_whisker(dc, printerScale) self._draw_iqr_box(dc, printerScale) From 98f19f03803a90b105bd216bb200574861bd7c54 Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Mon, 3 Feb 2025 02:40:54 +0100 Subject: [PATCH 26/28] refactor getTool, add support for .tar.bz2 files --- build.py | 175 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 99 insertions(+), 76 deletions(-) diff --git a/build.py b/build.py index 7d328584fc..9b13362713 100755 --- a/build.py +++ b/build.py @@ -22,6 +22,11 @@ import re import shutil import subprocess +import requests +from requests.exceptions import HTTPError +import traceback +from io import BytesIO +import bz2 import tarfile import tempfile import datetime @@ -86,8 +91,8 @@ doxygenCurrentVersion = '1.9.1' doxygenMD5 = { 'darwin' : '6912d41cef5971fb07573190849a8a84', - 'win32' : 'a3dcff227458e423c132f16f57e26510', - 'linux' : '083b3d8f614b538696041c7364e0f334', + 'win32' : '90439896025dc8ddcd5d767ab2c2c489', + 'linux' : '5e869ab2085183f3d297b0156a10d4a1', } # And the location where they can be downloaded from @@ -525,7 +530,6 @@ def deleteIfExists(deldir, verbose=True): shutil.rmtree(deldir) except Exception: if verbose: - import traceback msg("Error: %s" % traceback.format_exc(1)) else: if verbose: @@ -538,6 +542,50 @@ def delFiles(fileList, verbose=True): print("Removing file: %s" % afile) os.remove(afile) +def _error_msg(txt, cmdname, envvar): + msg('ERROR: ' + txt) + msg(' Set %s in the environment to use a local build of %s instead' % (envvar, cmdname)) + +def _download_tool(cmd, cmdname, envvar): + msg('Not found. Attempting to download...') + url = f"{toolsURL}/{os.path.basename(cmd)}.bz2" + + try: + resp = requests.get(url) + resp.raise_for_status() + except HTTPError: + # The files could be packed as a tarball + url = url.replace(".bz2", ".tar.bz2") + try: + resp = requests.get(url) + resp.raise_for_status() + except HTTPError: + _error_msg('Unable to download ' + url, cmdname, envvar) + traceback.print_exc() + sys.exit(1) + + msg('Connection successful...') + data = resp.content + msg('Data downloaded...') + + if ".tar." in url: + with tarfile.open('r:bz2', fileobj=BytesIO(data)) as tar: + # Extraction filters are only available since Python 3.12 + tar.extraction_filter = getattr(tarfile, 'data_filter', + (lambda member, path: member)) + filelist = [] + for file in tar.getmembers(): + if file.name.startswith("doxygen") or \ + file.name.startswith("libclang"): + filelist.append(file) + + tar.extractall(members=filelist, path=os.path.dirname(cmd)) + else: + data = bz2.decompress(data) + with open(cmd, 'wb') as f: + f.write(data) + + os.chmod(cmd, 0o755) def getTool(cmdName, version, MD5, envVar, platformBinary, linuxBits=False): # Check in the bin dir for the specified version of the tool command. If @@ -546,90 +594,68 @@ def getTool(cmdName, version, MD5, envVar, platformBinary, linuxBits=False): if os.environ.get(envVar): # Setting a value in the environment overrides other options return os.environ.get(envVar) - else: - # setup - if platformBinary: - platform = getToolsPlatformName(linuxBits) - ext = '' - if platform == 'win32': - ext = '.exe' - cmd = opj(phoenixDir(), 'bin', '%s-%s-%s%s' % (cmdName, version, platform, ext)) - md5 = MD5[platform] - else: - cmd = opj(phoenixDir(), 'bin', '%s-%s' % (cmdName, version)) - md5 = MD5 - - - def _error_msg(txt): - msg('ERROR: ' + txt) - msg(' Set %s in the environment to use a local build of %s instead' % (envVar, cmdName)) + # setup + if platformBinary: + platform = getToolsPlatformName(linuxBits) + ext = '' + if platform == 'win32': + ext = '.exe' + cmd = opj(phoenixDir(), 'bin', '%s-%s-%s%s' % (cmdName, version, platform, ext)) + md5 = MD5[platform] + else: + cmd = opj(phoenixDir(), 'bin', '%s-%s' % (cmdName, version)) + md5 = MD5 - msg('Checking for %s...' % cmd) - if os.path.exists(cmd): - # if the file exists run some verification checks on it + msg('Checking for %s...' % cmd) + if os.path.exists(cmd): + # if the file exists run some verification checks on it - # first make sure it is a normal file - if not os.path.isfile(cmd): - _error_msg('%s exists but is not a regular file.' % cmd) - sys.exit(1) + # first make sure it is a normal file + if not os.path.isfile(cmd): + _error_msg('%s exists but is not a regular file.' % cmd, + cmdName, envVar) + sys.exit(1) - # now check the MD5 if not in dev mode and it's set to None - if not (devMode and md5 is None): - m = hashlib.md5() - with open(cmd, 'rb') as fid: - m.update(fid.read()) - if m.hexdigest() != md5: - _error_msg('MD5 mismatch, got "%s"\n ' - 'expected "%s"' % (m.hexdigest(), md5)) - sys.exit(1) - - # If the cmd is a script run by some interpreter, or similar, - # then we don't need to check anything else - if not platformBinary: - return cmd - - # Ensure that commands that are platform binaries are executable - if not os.access(cmd, os.R_OK | os.X_OK): - _error_msg('Cannot execute %s due to permissions error' % cmd) + # now check the MD5 if not in dev mode and it's set to None + if not (devMode and md5 is None): + m = hashlib.md5() + with open(cmd, 'rb') as fid: + m.update(fid.read()) + if m.hexdigest() != md5: + _error_msg('MD5 mismatch, got "%s"\n ' + 'expected "%s"' % (m.hexdigest(), md5), + cmdName, envVar) sys.exit(1) - try: - p = subprocess.Popen([cmd, '--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=os.environ) - p.communicate() - except OSError as e: - _error_msg('Could not execute %s, got "%s"' % (cmd, e)) - sys.exit(1) - - # if we get this far then all is well, the cmd is good to go + # If the cmd is a script run by some interpreter, or similar, + # then we don't need to check anything else + if not platformBinary: return cmd + # Ensure that commands that are platform binaries are executable + if not os.access(cmd, os.R_OK | os.X_OK): + _error_msg('Cannot execute %s due to permissions error' % cmd, + cmdName, envVar) + sys.exit(1) - msg('Not found. Attempting to download...') - url = '%s/%s.bz2' % (toolsURL, os.path.basename(cmd)) try: - import requests - resp = requests.get(url) - resp.raise_for_status() - msg('Connection successful...') - data = resp.content - msg('Data downloaded...') - except Exception: - _error_msg('Unable to download ' + url) - import traceback - traceback.print_exc() + p = subprocess.Popen([cmd, '--help'], stdout=subprocess.PIPE, + stderr=subprocess.PIPE, env=os.environ) + p.communicate() + except OSError as e: + _error_msg('Could not execute %s, got "%s"' % (cmd, e), + cmdName, envVar) sys.exit(1) - import bz2 - data = bz2.decompress(data) - with open(cmd, 'wb') as f: - f.write(data) - os.chmod(cmd, 0o755) + # if we get this far then all is well, the cmd is good to go + return cmd - # Recursive call so the MD5 value will be double-checked on what was - # just downloaded - return getTool(cmdName, version, MD5, envVar, platformBinary, linuxBits) + _download_tool(cmd, cmdName, envVar) + # Recursive call so the MD5 value will be double-checked on what was + # just downloaded + return getTool(cmdName, version, MD5, envVar, platformBinary, linuxBits) # The download and MD5 check only needs to happen once per run, cache the sip @@ -660,14 +686,12 @@ def getMSWebView2(): msg('Downloading microsoft.web.webview2 {}...'.format(MS_edge_version)) try: - import requests resp = requests.get(MS_edge_url) resp.raise_for_status() msg('Connection successful...') data = resp.content msg('Data downloaded...') except Exception: - import traceback traceback.print_exc() sys.exit(1) @@ -1585,7 +1609,6 @@ def cmd_build_wx(options, args): except Exception: print("ERROR: failed building wxWidgets") - import traceback traceback.print_exc() sys.exit(1) From 1d555f08d4e179bc4df6189ed7f1635264ac23b2 Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Sat, 8 Feb 2025 14:24:54 +0100 Subject: [PATCH 27/28] Docs: fix sphinx (win) could not handle spaces in path --- build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.py b/build.py index 9b13362713..69ecae7b97 100755 --- a/build.py +++ b/build.py @@ -1188,7 +1188,7 @@ def cmd_sphinx(options, args): htmlDir = os.path.join(phoenixDir(), 'docs', 'html') sphinx_log = os.path.join(htmlDir, 'warnings', 'sphinx_warnings.log') - runcmd('{} -m sphinx --builder html --color --warning-file {} \ + runcmd('"{}" -m sphinx --builder html --color --warning-file {} \ --doctree-dir {}/doctrees . {}'.format(PYTHON, sphinx_log, buildDir, htmlDir)) del pwd2 From 1f1602536bc43a9e7a0a43d95f2ef9b8c1e452dd Mon Sep 17 00:00:00 2001 From: neofelis2X Date: Sat, 8 Feb 2025 14:27:11 +0100 Subject: [PATCH 28/28] Docs: add libclang to gitignore which can come with doxygen 1.9 --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 941f9fdfae..e2acb59c9b 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ venv*/ /bin/waf-* /bin/waf3-* /bin/doxygen-* +/bin/libclang* /demo/version.py