├── .appveyor.yml ├── .gitattributes ├── .gitignore ├── .travis.yml ├── 1-prepare-env.sh ├── 2-install-pkgs.sh ├── 3-apply-patches.sh ├── 4-build.sh ├── README.md ├── hooks └── hook-sphinx.py ├── os_classifier.sh ├── patches ├── alabaster.diff ├── docutils.diff ├── sphinx.diff ├── sphinx_bootstrap_theme.diff ├── sphinx_rtd_theme.diff ├── sphinxcontrib-applehelp.diff ├── sphinxcontrib-plantuml.diff └── sphinxcontrib-redoc.diff ├── run_sphinx.py └── test_site ├── _static └── overrides.css ├── _templates ├── layout.html └── versions.html ├── conf.py ├── graphviz.rst ├── index.rst ├── openapi.yaml ├── plantuml-1.2023.1.jar ├── recommonmark.md ├── sphinxcontrib-httpdomain.rst ├── sphinxcontrib-imagesvg.rst ├── sphinxcontrib-openapi.rst ├── sphinxcontrib-plantuml.rst ├── sphinxcontrib-youtube.rst ├── sphinxemoji.rst └── test.yaml /.appveyor.yml: -------------------------------------------------------------------------------- 1 | version: "{branch}.{build}" 2 | image: 3 | - "Visual Studio 2015" 4 | environment: 5 | PATH: "C:\\msys64\\usr\\bin;%PATH%" 6 | matrix: 7 | - APPVEYOR_BITS: 32 8 | - APPVEYOR_BITS: 64 9 | cache: 10 | - '%LOCALAPPDATA%\pip\Cache' 11 | init: 12 | - git config --global core.autocrlf true 13 | install: 14 | - bash -e 1-prepare-env.sh 15 | build: 16 | verbosity: detailed 17 | build_script: 18 | - bash -e 2-install-pkgs.sh 19 | - bash -e 3-apply-patches.sh 20 | - bash -e 4-build.sh 21 | test: off 22 | matrix: 23 | fast_finish: true 24 | artifacts: 25 | - path: build\dist\sphinx.* 26 | name: Releases 27 | deploy: 28 | provider: GitHub 29 | auth_token: 30 | secure: "NFYPLE7fXMSzXHZGA9EEXaGwvgct/x4tnWYIPsvKOK0FmNvYeUT6wxf/pwy/NMc5" 31 | artifact: /sphinx\..*/ 32 | draft: false 33 | prerelease: false 34 | on: 35 | appveyor_repo_tag: true 36 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.bat text eol=crlf 2 | /gradlew text eol=lf 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build output 2 | /build 3 | __pycache__ 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: generic 2 | sudo: required 3 | dist: trusty 4 | os: 5 | - linux 6 | - osx 7 | cache: 8 | directories: 9 | - "$HOME/.cache/pip" 10 | - "$HOME/Library/Caches/pip" 11 | - "$HOME/Library/Caches/Homebrew" 12 | - "/usr/local/Homebrew/Library/Taps/homebrew/homebrew-core" 13 | install: 14 | - ./1-prepare-env.sh 15 | script: 16 | - ./2-install-pkgs.sh 17 | - ./3-apply-patches.sh 18 | - ./4-build.sh 19 | notifications: 20 | email: false 21 | deploy: 22 | provider: releases 23 | api_key: 24 | - secure: "bgcPpVScW3Pd5ShFWJqbVnCd3qf75zwPYi6sTBMnU9NvYsWjixtdITVnXaCACX/jBAbbmiWCXmwlVYxZ6kAQuu/jqBI+EVEQHBtt6HseskQeOEh8YepJGTkEXyPQdMFOcriuJQ4H38OQnp6MOs/uwXvSOXLqtOg8BwQXgOGadpr0KLhBdX5nJuFVTtCILWz2Qzt8znT0ItjeNqEjMA8rM/S2OC7IzWBdGyYU8z2FajjbHnaROzRBuD/RWo6ljnHyKLRmx8PW8fKbchXCgmMahI+hBmtMuk1LjikSdKbqeblScMEcRexAkj4zsJ5twC2lX302bukilvYj8IG9BuO2g7GmDSka0a3AuSPTraPb8ciYa+0v8QNkCJCu4cSkjIyFTr4K+J7vFlYeNcQH+Xe5XzMXvMCWO6LVEsJMxVJ+gUxXUDkiY8/oXZIk5RUVeEIgB73iJlbKRWgIDSFPpKRtBRHMw5J18c+OwbWoNYBXGpzRMn6KbxMNFI9eOjzbQy42drq6v2ySzJqNLF9CLFcqs8zoad3+dFE3BmRo55QAor0leFV1iPm0K0PBKRC095pI2QHEr9j5plF1WZb2Htl2YzuuO1C6lgRuCUcjmjZaKPQx+9f1R1ufQvl1n5X+klq4YTRxII6kML5fOkpoikUVN3BiinYvcZ++vue7fRoVlSU=" 25 | file_glob: true 26 | file: "build/dist/sphinx.*" 27 | skip_cleanup: true 28 | on: 29 | tags: true 30 | -------------------------------------------------------------------------------- /1-prepare-env.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | EXPECTED_PYTHON_VERSION='3.10' 3 | 4 | set -Eeuo pipefail 5 | cd "$(dirname "$0")" 6 | rm -fr build 7 | 8 | # Ensure we're using the desired Python version. 9 | PYTHON="$(which python)" 10 | ACTUAL_PYTHON_VERSION="$("$PYTHON" --version)" 11 | echo "$PYTHON --version: $ACTUAL_PYTHON_VERSION" 12 | if [[ ! "$ACTUAL_PYTHON_VERSION" =~ (^Python 3\.10\.) ]]; then 13 | echo "Python $EXPECTED_PYTHON_VERSION is required." 14 | exit 1 15 | fi 16 | 17 | # Create and activate a virtualenv. 18 | VENV_HOME="$PWD/build/venv.orig" 19 | echo "Creating a new virtualenv with $PYTHON .." 20 | "$PYTHON" -m venv "$VENV_HOME" 21 | 22 | # Use the new Python and pip path after updating PATH. 23 | export PATH="$VENV_HOME/bin:$VENV_HOME/Scripts:$PATH" 24 | PYTHON="$(which python)" 25 | PIP="$(which pip)" 26 | if [[ ! "$PYTHON" =~ (^.*/build/venv\.orig/.*$) ]]; then 27 | echo "Unexpected python location: $PYTHON" 28 | fi 29 | if [[ ! "$PIP" =~ (^.*/build/venv\.orig/.*$) ]]; then 30 | echo "Unexpected pip location: $PIP" 31 | fi 32 | 33 | echo "Created a new virtualenv at $VENV_HOME" 34 | echo "- Python: $PYTHON" 35 | echo "- pip: $PIP" 36 | 37 | # Upgrade pip and setuptools. 38 | UNAME="$(uname)" 39 | if [[ "${UNAME,,}" =~ (^(msys|cygwin)) ]]; then 40 | # Windows 41 | "$PYTHON" -m pip install --upgrade pip setuptools 42 | else 43 | "$PIP" install --upgrade pip setuptools 44 | fi 45 | 46 | # Make sure we use Python 3.10. 47 | ACTUAL_PYTHON_VERSION="$("$PYTHON" --version)" 48 | ACTUAL_PIP_VERSION="$("$PIP" --version)" 49 | echo "$PYTHON --version: $ACTUAL_PYTHON_VERSION" 50 | echo "$PIP --version: $ACTUAL_PIP_VERSION" 51 | echo "os.classifier: $(./os_classifier.sh)" 52 | if [[ ! "$ACTUAL_PYTHON_VERSION" =~ (^Python 3\.10\.) ]] || \ 53 | [[ ! "$ACTUAL_PIP_VERSION" =~ (^.*pip [1-9][0-9]+\..*[\\/]build[\\/]venv\.orig[\\/].*3\.10[^0-9].*$) ]]; then 54 | echo 'Must run on Python 3.10 virtualenv with pip 10+' 55 | exit 1 56 | fi 57 | -------------------------------------------------------------------------------- /2-install-pkgs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | VENV_HOME="$PWD/build/venv.orig" 3 | export PATH="$VENV_HOME/bin:$VENV_HOME/Scripts:$PATH" 4 | if [[ ! -d "$VENV_HOME" ]]; then 5 | echo "virtualenv not ready" 6 | exit 1 7 | fi 8 | 9 | # Install the core packages. 10 | pip install \ 11 | 'PyInstaller==5.8.0' \ 12 | 'PyYAML==6.0' \ 13 | 'Sphinx==6.1.3' 14 | 15 | # Install the extensions. 16 | pip install \ 17 | 'git+https://github.com/executablebooks/MyST-Parser.git@f02d40f77c0b8a628b38e6c914b5684b42cc75aa#egg=myst-parser' \ 18 | 'recommonmark==0.7.1' \ 19 | 'sphinxcontrib-httpdomain==1.8.1' \ 20 | 'sphinxcontrib-imagesvg==0.1' \ 21 | 'sphinxcontrib-openapi==0.8.1' \ 22 | 'sphinxcontrib-plantuml==0.24.1' 'Pillow==9.4.0' \ 23 | 'sphinxcontrib-redoc==1.6.0' \ 24 | 'sphinxcontrib-websupport==1.2.4' \ 25 | 'git+https://github.com/sphinx-contrib/youtube.git@6ac4730bae06fe34a2c3098653326e3d47bb045a#egg=sphinxcontrib.youtube' \ 26 | 'sphinxemoji==0.2.0' \ 27 | 'sphinx-markdown-tables==0.0.17' 28 | 29 | # Install the themes. 30 | pip install \ 31 | 'sphinx-bootstrap-theme==0.8.1' \ 32 | 'sphinx-rtd-theme==1.2.0' 33 | 34 | # Delete compilation cache so it's easier to diff. 35 | find "$VENV_HOME" -type d -name '__pycache__' -exec rm -fr {} ';' >/dev/null 2>&1 || true 36 | -------------------------------------------------------------------------------- /3-apply-patches.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | ORIG_VENV_HOME="$PWD/build/venv.orig" 3 | NEW_VENV_HOME="$PWD/build/venv.new" 4 | 5 | if [[ ! -d "$ORIG_VENV_HOME" ]]; then 6 | echo "virtualenv not ready" 7 | exit 1 8 | fi 9 | 10 | # Revert the new venv so that we can patch from scratch. 11 | rsync -aiP --delete "$ORIG_VENV_HOME/" "$NEW_VENV_HOME/" 12 | 13 | # Make sure we don't refer to the old venv. 14 | if grep -rFl "venv.orig" "$NEW_VENV_HOME"/[Ll]ib; then 15 | echo "The new virtualenv contains a reference to the old one." 16 | exit 1 17 | fi 18 | 19 | # Apply some patches. 20 | export PATH="$NEW_VENV_HOME/bin:$NEW_VENV_HOME/Scripts:$PATH" 21 | PATCH_DIR="$PWD/patches" 22 | if [[ -d "$NEW_VENV_HOME/Lib/site-packages" ]]; then 23 | SITEPKG_DIR="$NEW_VENV_HOME/Lib/site-packages" 24 | elif [[ -d "$NEW_VENV_HOME/lib/python3.10/site-packages" ]]; then 25 | SITEPKG_DIR="$NEW_VENV_HOME/lib/python3.10/site-packages" 26 | fi 27 | pushd "$SITEPKG_DIR" 28 | if [[ ! -a sphinxcontrib/__init__.py ]]; then 29 | echo "__import__('pkg_resources').declare_namespace(__name__)" > sphinxcontrib/__init__.py 30 | fi 31 | find "$PATCH_DIR" -name '*.diff' -print | while read -r PATCH; do 32 | patch -p1 -i "$PATCH" 33 | done 34 | find . -type f -name '*.orig' -delete || true 35 | 36 | # Pre-compile everything unless 'nocompile' option is specified. 37 | if [[ "$1" != 'nocompile' ]]; then 38 | find . -type d -name '__pycache__' -exec rm -fr {} ';' >/dev/null 2>&1 || true 39 | python -m compileall . >/dev/null 2>&1 40 | fi 41 | popd 42 | -------------------------------------------------------------------------------- /4-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | VENV_HOME="$PWD/build/venv.new" 3 | export PATH="$VENV_HOME/bin:$VENV_HOME/Scripts:$PATH" 4 | if [[ ! -d "$VENV_HOME" ]]; then 5 | echo "virtualenv not ready" 6 | exit 1 7 | fi 8 | 9 | # Build the binary. 10 | python -OO -m PyInstaller \ 11 | --noconfirm \ 12 | --console \ 13 | --onefile \ 14 | --distpath build/dist \ 15 | --specpath build \ 16 | --additional-hooks-dir=hooks \ 17 | run_sphinx.py 18 | 19 | # Rename the binary. 20 | OS_CLASSIFIER="$(./os_classifier.sh)" 21 | if [[ -f build/dist/run_sphinx.exe ]]; then 22 | SPHINX_BIN="build/dist/sphinx.$OS_CLASSIFIER.exe" 23 | mv -v build/dist/run_sphinx.exe "$SPHINX_BIN" 24 | else 25 | SPHINX_BIN="build/dist/sphinx.$OS_CLASSIFIER" 26 | mv -v build/dist/run_sphinx "$SPHINX_BIN" 27 | fi 28 | 29 | # Generate the SHA256 checksum. 30 | if [[ -x /usr/local/bin/gsha256sum ]]; then 31 | SHA256SUM_BIN=/usr/local/bin/gsha256sum 32 | else 33 | SHA256SUM_BIN=sha256sum 34 | fi 35 | "$SHA256SUM_BIN" -b "$SPHINX_BIN" | sed 's/ .*//g' > "$SPHINX_BIN.sha256" 36 | echo "sha256sum: $(cat "$SPHINX_BIN.sha256") ($SPHINX_BIN.sha256)" 37 | 38 | # Build a test site with the binary to make sure it really works. 39 | "build/dist/sphinx.$OS_CLASSIFIER" -T test_site build/test_site 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Standalone Sphinx binary 2 | 3 | Run [Sphinx](http://www.sphinx-doc.org/) on Windows, Linux and OS X with a 4 | single-file standalone binary. Built with [PyInstaller](https://www.pyinstaller.org/), 5 | a user can run Sphinx without installing a Python interpreter or any dependencies. 6 | 7 | ## Downloads 8 | 9 | Download the binaries at [Releases](https://github.com/trustin/sphinx-binary/releases). 10 | 11 | ## Additional modules 12 | 13 | As well as vanilla Sphinx, the following modules are provided out of the box 14 | for your convenience: 15 | 16 | - PyYAML 17 | - recommonmark 18 | - sphinxcontrib-httpdomain 19 | - sphinxcontrib-imagesvg 20 | - sphinxcontrib-openapi 21 | - sphinxcontrib-plantuml 22 | - sphinxcontrib-redoc 23 | - sphinxcontrib-websupport 24 | - sphinxcontrib-youtube 25 | - sphinxemoji 26 | - sphinx_bootstrap_theme 27 | - sphinx-markdown-tables 28 | - sphinx_rtd_theme 29 | -------------------------------------------------------------------------------- /hooks/hook-sphinx.py: -------------------------------------------------------------------------------- 1 | from PyInstaller.utils.hooks import collect_submodules, collect_data_files, copy_metadata, is_module_satisfies 2 | hiddenimports = ( 3 | collect_submodules('pkg_resources') + 4 | collect_submodules('sphinx.builders') + 5 | collect_submodules('sphinx.directives') + 6 | collect_submodules('sphinx.environment.collectors') + 7 | collect_submodules('sphinx.ext') + 8 | collect_submodules('sphinx.parsers') + 9 | collect_submodules('sphinx.search') + 10 | collect_submodules('sphinx.transforms') + 11 | collect_submodules('sphinx.websupport.search') + 12 | collect_submodules('sphinx.domains') + 13 | collect_submodules('sphinx.util') + 14 | ['inspect', 'locale'] + 15 | collect_submodules('lib2to3') + 16 | collect_submodules('babel') + 17 | collect_submodules('yaml') + 18 | collect_submodules('javasphinx') + 19 | collect_submodules('myst_parser') + 20 | collect_submodules('recommonmark') + 21 | collect_submodules('sphinx_markdown_tables') + 22 | collect_submodules('sphinxcontrib') + 23 | collect_submodules('sphinxemoji') + 24 | # Themes 25 | collect_submodules('alabaster') + 26 | collect_submodules('sphinx_bootstrap_theme') + 27 | collect_submodules('sphinx_rtd_theme')) 28 | 29 | datas = collect_data_files('sphinx') 30 | datas.extend(collect_data_files('alabaster')) 31 | datas.extend(collect_data_files('sphinx_bootstrap_theme')) 32 | datas.extend(collect_data_files('sphinx_rtd_theme')) 33 | datas.extend(collect_data_files('sphinxcontrib')) 34 | datas.extend(collect_data_files('sphinxemoji')) 35 | datas.extend(copy_metadata('sphinxcontrib-redoc')) 36 | -------------------------------------------------------------------------------- /os_classifier.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | if [[ "$(uname)" =~ ([Ll]inux) ]]; then 3 | echo linux-x86_64 4 | elif [[ "$(uname)" =~ ([Dd]arwin) ]]; then 5 | echo osx-x86_64 6 | elif [[ -n "$APPVEYOR" ]]; then 7 | if [[ "$APPVEYOR_BITS" == '32' ]]; then 8 | echo windows-x86_32 9 | else 10 | echo windows-x86_64 11 | fi 12 | else 13 | echo unknown 14 | fi 15 | -------------------------------------------------------------------------------- /patches/alabaster.diff: -------------------------------------------------------------------------------- 1 | diff -urN dist.orig/alabaster/__init__.py dist/alabaster/__init__.py 2 | --- dist.orig/alabaster/__init__.py 2018-04-24 10:00:27.146537303 +0900 3 | +++ dist/alabaster/__init__.py 2018-04-24 10:10:19.466361886 +0900 4 | @@ -1,4 +1,5 @@ 5 | import os 6 | +import sys 7 | 8 | from alabaster import _version as version 9 | 10 | @@ -8,7 +9,10 @@ 11 | Shortcut for users whose theme is next to their conf.py. 12 | """ 13 | # Theme directory is defined as our parent directory 14 | - return os.path.abspath(os.path.dirname(os.path.dirname(__file__))) 15 | + if getattr(sys, 'frozen', False): 16 | + return sys._MEIPASS 17 | + else: 18 | + return os.path.abspath(os.path.dirname(os.path.dirname(__file__))) 19 | 20 | 21 | def update_context(app, pagename, templatename, context, doctree): 22 | -------------------------------------------------------------------------------- /patches/docutils.diff: -------------------------------------------------------------------------------- 1 | diff -urN dist.orig/docutils/utils/math/tex2mathml_extern.py dist/docutils/utils/math/tex2mathml_extern.py 2 | --- dist.orig/docutils/utils/math/tex2mathml_extern.py 2020-03-29 10:12:49.731642961 +0900 3 | +++ dist/docutils/utils/math/tex2mathml_extern.py 2020-03-29 10:16:39.405250125 +0900 4 | @@ -16,6 +16,7 @@ 5 | # ===================================================== 6 | 7 | from __future__ import print_function 8 | +import os 9 | import subprocess 10 | 11 | document_template = r"""\documentclass{article} 12 | @@ -38,7 +39,8 @@ 13 | stdin=subprocess.PIPE, 14 | stdout=subprocess.PIPE, 15 | stderr=subprocess.PIPE, 16 | - close_fds=True) 17 | + close_fds=True, 18 | + env=_new_env()) 19 | p.stdin.write((document_template % math_code).encode('utf8')) 20 | p.stdin.close() 21 | latexml_code = p.stdout.read() 22 | @@ -56,7 +58,8 @@ 23 | stdin=subprocess.PIPE, 24 | stdout=subprocess.PIPE, 25 | stderr=subprocess.PIPE, 26 | - close_fds=True) 27 | + close_fds=True, 28 | + env=_new_env()) 29 | post_p.stdin.write(latexml_code) 30 | post_p.stdin.close() 31 | result = post_p.stdout.read().decode('utf8') 32 | @@ -84,7 +87,8 @@ 33 | stdin=subprocess.PIPE, 34 | stdout=subprocess.PIPE, 35 | stderr=subprocess.PIPE, 36 | - close_fds=True) 37 | + close_fds=True, 38 | + env=_new_env()) 39 | p.stdin.write((document_template % math_code).encode('utf8')) 40 | p.stdin.close() 41 | result = p.stdout.read() 42 | @@ -122,7 +126,8 @@ 43 | stdin=subprocess.PIPE, 44 | stdout=subprocess.PIPE, 45 | stderr=subprocess.PIPE, 46 | - close_fds=True) 47 | + close_fds=True, 48 | + env=_new_env()) 49 | p.stdin.write(math_code.encode('utf8')) 50 | p.stdin.close() 51 | result = p.stdout.read().decode('utf8') 52 | @@ -138,6 +143,18 @@ 53 | '%s\n') % (mathmode_arg, result[start:end]) 54 | return result 55 | 56 | + 57 | +def _new_env(): 58 | + env = dict(os.environ) # make a copy of the environment 59 | + lp_key = 'LD_LIBRARY_PATH' # for Linux and *BSD. 60 | + lp_orig = env.get(lp_key + '_ORIG') # pyinstaller >= 20160820 has this 61 | + if lp_orig is not None: 62 | + env[lp_key] = lp_orig # restore the original, unmodified value 63 | + else: 64 | + env.pop(lp_key, None) # last resort: remove the env var 65 | + return env 66 | + 67 | + 68 | # self-test 69 | 70 | if __name__ == "__main__": 71 | -------------------------------------------------------------------------------- /patches/sphinx.diff: -------------------------------------------------------------------------------- 1 | diff -urN dist.orig/sphinx/cmd/make_mode.py dist/sphinx/cmd/make_mode.py 2 | --- dist.orig/sphinx/cmd/make_mode.py 2020-03-29 10:12:50.011647462 +0900 3 | +++ dist/sphinx/cmd/make_mode.py 2020-03-29 10:23:41.121770929 +0900 4 | @@ -102,7 +102,7 @@ 5 | makecmd = self.makecmd 6 | try: 7 | with cd(self.builddir_join('latex')): 8 | - return subprocess.call([makecmd, 'all-pdf']) 9 | + return subprocess.run([makecmd, 'all-pdf'], env=_new_env()) 10 | except OSError: 11 | print('Error: Failed to run: %s' % makecmd) 12 | return 1 13 | @@ -117,7 +117,7 @@ 14 | makecmd = self.makecmd 15 | try: 16 | with cd(self.builddir_join('latex')): 17 | - return subprocess.call([makecmd, 'all-pdf']) 18 | + return subprocess.run([makecmd, 'all-pdf'], env=_new_env()) 19 | except OSError: 20 | print('Error: Failed to run: %s' % makecmd) 21 | return 1 22 | @@ -127,7 +127,7 @@ 23 | return 1 24 | try: 25 | with cd(self.builddir_join('texinfo')): 26 | - return subprocess.call([self.makecmd, 'info']) 27 | + return subprocess.run([self.makecmd, 'info'], env=_new_env()) 28 | except OSError: 29 | print('Error: Failed to run: %s' % self.makecmd) 30 | return 1 31 | @@ -164,3 +164,14 @@ 32 | if hasattr(make, run_method): 33 | return getattr(make, run_method)() 34 | return make.run_generic_build(args[0]) 35 | + 36 | + 37 | +def _new_env(): 38 | + env = dict(os.environ) # make a copy of the environment 39 | + lp_key = 'LD_LIBRARY_PATH' # for Linux and *BSD. 40 | + lp_orig = env.get(lp_key + '_ORIG') # pyinstaller >= 20160820 has this 41 | + if lp_orig is not None: 42 | + env[lp_key] = lp_orig # restore the original, unmodified value 43 | + else: 44 | + env.pop(lp_key, None) # last resort: remove the env var 45 | + return env 46 | diff -urN dist.orig/sphinx/ext/graphviz.py dist/sphinx/ext/graphviz.py 47 | --- dist.orig/sphinx/ext/graphviz.py 2020-03-29 10:12:50.021647691 +0900 48 | +++ dist/sphinx/ext/graphviz.py 2020-03-29 10:25:23.613343558 +0900 49 | @@ -9,6 +9,7 @@ 50 | :license: BSD, see LICENSE for details. 51 | """ 52 | 53 | +import os 54 | import posixpath 55 | import re 56 | import subprocess 57 | @@ -245,7 +246,7 @@ 58 | 59 | try: 60 | ret = subprocess.run(dot_args, input=code.encode(), capture_output=True, 61 | - cwd=cwd, check=True) 62 | + cwd=cwd, env=_new_env(), check=True) 63 | if not path.isfile(outfn): 64 | raise GraphvizError(__('dot did not produce an output file:\n[stderr]\n%r\n' 65 | '[stdout]\n%r') % (ret.stderr, ret.stdout)) 66 | @@ -394,6 +395,17 @@ 67 | copy_asset(src, dst) 68 | 69 | 70 | +def _new_env(): 71 | + env = dict(os.environ) # make a copy of the environment 72 | + lp_key = 'LD_LIBRARY_PATH' # for Linux and *BSD. 73 | + lp_orig = env.get(lp_key + '_ORIG') # pyinstaller >= 20160820 has this 74 | + if lp_orig is not None: 75 | + env[lp_key] = lp_orig # restore the original, unmodified value 76 | + else: 77 | + env.pop(lp_key, None) # last resort: remove the env var 78 | + return env 79 | + 80 | + 81 | def setup(app: Sphinx) -> dict[str, Any]: 82 | app.add_node(graphviz, 83 | html=(html_visit_graphviz, None), 84 | diff -urN dist.orig/sphinx/ext/imgconverter.py dist/sphinx/ext/imgconverter.py 85 | --- dist.orig/sphinx/ext/imgconverter.py 2020-03-29 10:12:50.021647691 +0900 86 | +++ dist/sphinx/ext/imgconverter.py 2020-03-29 10:26:54.524735899 +0900 87 | @@ -8,6 +8,7 @@ 88 | :license: BSD, see LICENSE for details. 89 | """ 90 | 91 | +import os 92 | import subprocess 93 | import sys 94 | from subprocess import PIPE, CalledProcessError 95 | @@ -35,7 +36,7 @@ 96 | try: 97 | args = [self.config.image_converter, '-version'] 98 | logger.debug('Invoking %r ...', args) 99 | - subprocess.run(args, capture_output=True, check=True) 100 | + subprocess.run(args, capture_output=True, env=_new_env(), check=True) 101 | return True 102 | except OSError: 103 | logger.warning(__('convert command %r cannot be run, ' 104 | @@ -59,7 +60,7 @@ 105 | self.config.image_converter_args + 106 | [_from, _to]) 107 | logger.debug('Invoking %r ...', args) 108 | - subprocess.run(args, capture_output=True, check=True) 109 | + subprocess.run(args, capture_output=True, env=_new_env(), check=True) 110 | return True 111 | except OSError: 112 | logger.warning(__('convert command %r cannot be run, ' 113 | @@ -72,6 +73,17 @@ 114 | (exc.stderr, exc.stdout)) from exc 115 | 116 | 117 | +def _new_env(): 118 | + env = dict(os.environ) # make a copy of the environment 119 | + lp_key = 'LD_LIBRARY_PATH' # for Linux and *BSD. 120 | + lp_orig = env.get(lp_key + '_ORIG') # pyinstaller >= 20160820 has this 121 | + if lp_orig is not None: 122 | + env[lp_key] = lp_orig # restore the original, unmodified value 123 | + else: 124 | + env.pop(lp_key, None) # last resort: remove the env var 125 | + return env 126 | + 127 | + 128 | def setup(app: Sphinx) -> dict[str, Any]: 129 | app.add_post_transform(ImagemagickConverter) 130 | if sys.platform == 'win32': 131 | diff -urN dist.orig/sphinx/ext/imgmath.py dist/sphinx/ext/imgmath.py 132 | --- dist.orig/sphinx/ext/imgmath.py 2020-03-29 10:12:50.021647691 +0900 133 | +++ dist/sphinx/ext/imgmath.py 2020-03-29 10:28:09.475882256 +0900 134 | @@ -9,6 +9,7 @@ 135 | from __future__ import annotations 136 | 137 | import base64 138 | +import os 139 | import re 140 | import shutil 141 | import subprocess 142 | @@ -163,7 +164,7 @@ 143 | 144 | try: 145 | subprocess.run(command, capture_output=True, cwd=tempdir, check=True, 146 | - encoding='ascii') 147 | + encoding='ascii', env=_new_env()) 148 | return path.join(tempdir, 'math.dvi') 149 | except OSError as exc: 150 | logger.warning(__('LaTeX command %r cannot be run (needed for math ' 151 | @@ -177,7 +178,7 @@ 152 | def convert_dvi_to_image(command: List[str], name: str) -> Tuple[bytes, bytes]: 153 | """Convert DVI file to specific image format.""" 154 | try: 155 | - ret = subprocess.run(command, capture_output=True, check=True, encoding='ascii') 156 | + ret = subprocess.run(command, capture_output=True, check=True, encoding='ascii', env=_new_env()) 157 | return ret.stdout, ret.stderr 158 | except OSError as exc: 159 | logger.warning(__('%s command %r cannot be run (needed for math ' 160 | @@ -379,6 +380,17 @@ 161 | RemovedInSphinx40Warning) 162 | 163 | 164 | +def _new_env(): 165 | + env = dict(os.environ) # make a copy of the environment 166 | + lp_key = 'LD_LIBRARY_PATH' # for Linux and *BSD. 167 | + lp_orig = env.get(lp_key + '_ORIG') # pyinstaller >= 20160820 has this 168 | + if lp_orig is not None: 169 | + env[lp_key] = lp_orig # restore the original, unmodified value 170 | + else: 171 | + env.pop(lp_key, None) # last resort: remove the env var 172 | + return env 173 | + 174 | + 175 | def setup(app: Sphinx) -> dict[str, Any]: 176 | app.add_html_math_renderer('imgmath', 177 | (html_visit_math, None), 178 | -------------------------------------------------------------------------------- /patches/sphinx_bootstrap_theme.diff: -------------------------------------------------------------------------------- 1 | diff -urN dist.orig/sphinx_bootstrap_theme/__init__.py dist/sphinx_bootstrap_theme/__init__.py 2 | --- dist.orig/sphinx_bootstrap_theme/__init__.py 2019-03-30 02:56:20.000000000 +0900 3 | +++ dist/sphinx_bootstrap_theme/__init__.py 2019-04-28 11:08:00.001426140 +0900 4 | @@ -1,5 +1,6 @@ 5 | """Sphinx bootstrap theme.""" 6 | import os 7 | +import sys 8 | 9 | VERSION = (0, 8, 0) 10 | 11 | @@ -8,7 +9,10 @@ 12 | 13 | def get_html_theme_path(): 14 | """Return list of HTML theme paths.""" 15 | - theme_path = os.path.abspath(os.path.dirname(__file__)) 16 | + if getattr(sys, 'frozen', False): 17 | + theme_path = os.path.join(sys._MEIPASS, 'sphinx_bootstrap_theme') 18 | + else: 19 | + theme_path = os.path.abspath(os.path.dirname(__file__)) 20 | return [theme_path] 21 | 22 | def setup(app): 23 | -------------------------------------------------------------------------------- /patches/sphinx_rtd_theme.diff: -------------------------------------------------------------------------------- 1 | diff -urN dist.orig/sphinx_rtd_theme/__init__.py dist/sphinx_rtd_theme/__init__.py 2 | --- dist.orig/sphinx_rtd_theme/__init__.py 2023-02-20 21:42:42.078480089 +0900 3 | +++ dist/sphinx_rtd_theme/__init__.py 2023-02-20 21:46:46.426078882 +0900 4 | @@ -6,6 +6,7 @@ 5 | 6 | from os import path 7 | from sys import version_info as python_version 8 | +import sys 9 | 10 | from sphinx import version_info as sphinx_version 11 | from sphinx.locale import _ 12 | @@ -20,7 +21,10 @@ 13 | 14 | def get_html_theme_path(): 15 | """Return list of HTML theme paths.""" 16 | - cur_dir = path.abspath(path.dirname(path.dirname(__file__))) 17 | + if getattr(sys, 'frozen', False): 18 | + cur_dir = sys._MEIPASS 19 | + else: 20 | + cur_dir = path.abspath(path.dirname(path.dirname(__file__))) 21 | return cur_dir 22 | 23 | 24 | -------------------------------------------------------------------------------- /patches/sphinxcontrib-applehelp.diff: -------------------------------------------------------------------------------- 1 | diff -urN dist.orig/sphinxcontrib/applehelp/__init__.py dist/sphinxcontrib/applehelp/__init__.py 2 | --- dist.orig/sphinxcontrib/applehelp/__init__.py 2019-06-30 13:10:54.368728747 +0900 3 | +++ dist/sphinxcontrib/applehelp/__init__.py 2019-06-30 13:14:28.947028771 +0900 4 | @@ -194,7 +194,7 @@ 5 | ' '.join([shlex.quote(arg) for arg in args])) 6 | else: 7 | try: 8 | - subprocess.run(args, stdout=PIPE, stderr=STDOUT, check=True) 9 | + subprocess.run(args, stdout=PIPE, stderr=STDOUT, env=_new_env(), check=True) 10 | except OSError: 11 | raise AppleHelpIndexerFailed(__('Command not found: %s') % args[0]) 12 | except CalledProcessError as exc: 13 | @@ -218,13 +218,24 @@ 14 | ' '.join([shlex.quote(arg) for arg in args])) 15 | else: 16 | try: 17 | - subprocess.run(args, stdout=PIPE, stderr=STDOUT, check=True) 18 | + subprocess.run(args, stdout=PIPE, stderr=STDOUT, env=_new_env(), check=True) 19 | except OSError: 20 | raise AppleHelpCodeSigningFailed(__('Command not found: %s') % args[0]) 21 | except CalledProcessError as exc: 22 | raise AppleHelpCodeSigningFailed(exc.stdout) 23 | 24 | 25 | +def _new_env(): 26 | + env = dict(environ) # make a copy of the environment 27 | + lp_key = 'LD_LIBRARY_PATH' # for Linux and *BSD. 28 | + lp_orig = env.get(lp_key + '_ORIG') # pyinstaller >= 20160820 has this 29 | + if lp_orig is not None: 30 | + env[lp_key] = lp_orig # restore the original, unmodified value 31 | + else: 32 | + env.pop(lp_key, None) # last resort: remove the env var 33 | + return env 34 | + 35 | + 36 | def setup(app: Sphinx) -> Dict[str, Any]: 37 | app.setup_extension('sphinx.builders.html') 38 | app.add_builder(AppleHelpBuilder) 39 | -------------------------------------------------------------------------------- /patches/sphinxcontrib-plantuml.diff: -------------------------------------------------------------------------------- 1 | --- dist.orig/sphinxcontrib/plantuml.py 2020-01-01 10:30:59.000000000 +0900 2 | +++ dist/sphinxcontrib/plantuml.py 2020-03-29 10:31:53.879307941 +0900 3 | @@ -230,7 +230,8 @@ 4 | stdin=subprocess.PIPE, 5 | stdout=subprocess.PIPE, 6 | stderr=subprocess.PIPE, 7 | - cwd=absincdir) 8 | + cwd=absincdir, 9 | + env=_new_env()) 10 | except OSError as err: 11 | if err.errno != ENOENT: 12 | raise 13 | @@ -321,7 +322,8 @@ 14 | cmdargs.extend(os.path.join(k[:2], '%s.puml' % k) for k in keys) 15 | try: 16 | p = subprocess.Popen(cmdargs, stderr=subprocess.PIPE, 17 | - cwd=self.cache_dir) 18 | + cwd=self.cache_dir, 19 | + env=_new_env()) 20 | except OSError as err: 21 | if err.errno != ENOENT: 22 | raise 23 | @@ -349,7 +351,8 @@ 24 | fileformat), 25 | stdout=f, stdin=subprocess.PIPE, 26 | stderr=subprocess.PIPE, 27 | - cwd=absincdir) 28 | + cwd=absincdir, 29 | + env=_new_env()) 30 | except OSError as err: 31 | if err.errno != ENOENT: 32 | raise 33 | @@ -520,13 +523,15 @@ 34 | try: 35 | try: 36 | p = subprocess.Popen(args, stdout=subprocess.PIPE, 37 | - stderr=subprocess.PIPE) 38 | + stderr=subprocess.PIPE, 39 | + env=_new_env()) 40 | except OSError as err: 41 | # workaround for missing shebang of epstopdf script 42 | if err.errno != getattr(errno, 'ENOEXEC', 0): 43 | raise 44 | p = subprocess.Popen(['bash'] + args, stdout=subprocess.PIPE, 45 | - stderr=subprocess.PIPE) 46 | + stderr=subprocess.PIPE, 47 | + env=_new_env()) 48 | except OSError as err: 49 | if err.errno != ENOENT: 50 | raise 51 | @@ -667,6 +672,17 @@ 52 | app.builder.plantuml_builder.collect_nodes(doctree) 53 | 54 | 55 | +def _new_env(): 56 | + env = dict(os.environ) # make a copy of the environment 57 | + lp_key = 'LD_LIBRARY_PATH' # for Linux and *BSD. 58 | + lp_orig = env.get(lp_key + '_ORIG') # pyinstaller >= 20160820 has this 59 | + if lp_orig is not None: 60 | + env[lp_key] = lp_orig # restore the original, unmodified value 61 | + else: 62 | + env.pop(lp_key, None) # last resort: remove the env var 63 | + return env 64 | + 65 | + 66 | def setup(app): 67 | app.add_node(plantuml, **_NODE_VISITORS) 68 | app.add_directive('uml', UmlDirective) 69 | -------------------------------------------------------------------------------- /patches/sphinxcontrib-redoc.diff: -------------------------------------------------------------------------------- 1 | diff -urN dist.orig/sphinxcontrib/redoc.py dist/sphinxcontrib/redoc.py 2 | --- dist.orig/sphinxcontrib/redoc.py 2018-08-05 20:40:27.000000000 +0900 3 | +++ dist/sphinxcontrib/redoc.py 2018-08-12 17:18:46.438160442 +0900 4 | @@ -11,6 +11,7 @@ 5 | 6 | import io 7 | import os 8 | +import sys 9 | import json 10 | 11 | import jinja2 12 | @@ -23,7 +24,10 @@ 13 | from sphinx.util.osutil import copyfile, ensuredir 14 | 15 | 16 | -_HERE = os.path.abspath(os.path.dirname(__file__)) 17 | +if getattr(sys, 'frozen', False): 18 | + _HERE = os.path.join(sys._MEIPASS, 'sphinxcontrib') 19 | +else: 20 | + _HERE = os.path.abspath(os.path.dirname(__file__)) 21 | _REDOC_CONF_SCHEMA = { 22 | 'type': 'array', 23 | 'items': { 24 | -------------------------------------------------------------------------------- /run_sphinx.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | from sphinx.cmd.build import main 4 | 5 | # Set some environment variables for consistency. 6 | os.putenv("LANG", "en_US.UTF-8") 7 | os.putenv("LC_ALL", "en_US.UTF-8") 8 | os.putenv("TZ", "UTC") 9 | 10 | # Launch Sphinx 11 | sys.exit(main()) 12 | -------------------------------------------------------------------------------- /test_site/_static/overrides.css: -------------------------------------------------------------------------------- 1 | @import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400italic,700,700italic); 2 | @import url(https://fonts.googleapis.com/css?family=Source+Code+Pro:500,700); 3 | @import url(https://cdnjs.cloudflare.com/ajax/libs/github-fork-ribbon-css/0.1.1/gh-fork-ribbon.min.css); 4 | 5 | body { 6 | font-family: 'Source Sans Pro', 'Helvetica', 'Arial', sans-serif; 7 | font-weight: normal; 8 | font-size: 15px; 9 | line-height: 1.42857143; 10 | background-color: white; 11 | margin: 0; 12 | } 13 | 14 | .wy-nav-side { 15 | font-size: 17px; 16 | } 17 | 18 | .wy-nav-top { 19 | line-height: 30px; 20 | } 21 | 22 | .wy-nav-content { 23 | max-width: 100%; 24 | } 25 | 26 | .wy-nav-content p { 27 | font-size: inherit; 28 | } 29 | 30 | .wy-side-nav-search > a, .wy-side-nav-search .wy-dropdown > a, 31 | .wy-nav-top > a { 32 | font-weight: inherit; 33 | } 34 | 35 | .wy-side-nav-search > a { 36 | margin: 0; 37 | display: block; 38 | } 39 | 40 | .wy-side-nav-search > a img.logo { 41 | max-width: 75%; 42 | height: auto; 43 | margin: 0 auto; 44 | padding: 0; 45 | } 46 | 47 | h1, h2, h3, h4, h5, h6 { 48 | font-weight: inherit; 49 | } 50 | 51 | pre, code, kbd, var, samp, tt, 52 | .rst-content div[class^='highlight'] pre, 53 | .rst-content pre.literal-block, 54 | .rst-content tt.literal { 55 | font-family: 'Source Code Pro', 'Consolas', 'Menlo', 'Monaco', 'Lucida Console', 'Liberation Mono', 56 | 'DejaVu Sans Mono', monospace; 57 | font-weight: 500; 58 | } 59 | 60 | pre, 61 | .rst-content div[class^='highlight'] pre, 62 | .rst-content pre.literal-block { 63 | padding: 12px; 64 | font-size: 13px; 65 | overflow: auto; 66 | color: inherit; 67 | } 68 | 69 | code, kbd, var, samp, tt, 70 | .rst-content tt.literal, 71 | .rst-content code.literal { 72 | padding-left: 0; 73 | padding-right: 0; 74 | background: inherit; 75 | font-size: inherit; 76 | border: none; 77 | } 78 | 79 | p { 80 | text-align: justify; 81 | word-wrap: break-word; 82 | overflow-wrap: break-word; 83 | hyphens: auto; 84 | } 85 | 86 | h1, h2, h3, h4, h5, h6 { 87 | font-family: 'Source Sans Pro', 'Helvetica', 'Arial', sans-serif; 88 | } 89 | 90 | .rst-content tt.download { 91 | font-family: inherit; 92 | } 93 | -------------------------------------------------------------------------------- /test_site/_templates/layout.html: -------------------------------------------------------------------------------- 1 | {% extends "!layout.html" %} 2 | {% set sticky_navigation = True %} 3 | {% set extra_css_files = ['_static/overrides.css'] %} 4 | -------------------------------------------------------------------------------- /test_site/_templates/versions.html: -------------------------------------------------------------------------------- 1 |