Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

png writing error with planuml #98

Open
etainardi opened this issue Jan 16, 2025 · 1 comment
Open

png writing error with planuml #98

etainardi opened this issue Jan 16, 2025 · 1 comment

Comments

@etainardi
Copy link

etainardi commented Jan 16, 2025

Automated generation of plantuml structures for every script in the project, integrated into the Sphinx documentation generation process.

PermissionError: [WinError 32] The process cannot access the file because it is being used by another process

See attached logs.

I have deleted the first part of the address locations in the logs for security purposes.
When this error occurs, I simply close VsCode and open the environment again - then re-excute the project. this allows the process to finish without this error.
index.rst and conf.py also attached.
add_pdf_viewer in extensions - its a custom extension that adds an insertion of pdf.js to one of the HTML output pages. no problem with it no relation to this issue, executes perfectly.
The files mentioned are not open in any tool what so ever, not before\during or after the project execution.

How to Reproduce

# Platform:         win32; (Windows-10-10.0.19045-SP0)
# Sphinx version:   8.1.3
# Python version:   3.10.2 (CPython)
# Docutils version: 0.21.2
# Jinja2 version:   3.1.5
# Pygments version: 2.18.0

# Last messages:
#   writing output... [ 59%]
#   VisScripts.Plot_Neural_Network_Architecture_Models
#   
#   
#   ====================== slowest reading durations =======================
#   0.516 PhysicalScripts
#   0.484 SphinxScripts
#   0.344 models
#   0.313 dataset
#   0.297 MirrorScripts

# Loaded extensions:
#   sphinx.ext.mathjax (8.1.3)
#   alabaster (1.0.0)
#   sphinxcontrib.applehelp (2.0.0)
#   sphinxcontrib.devhelp (2.0.0)
#   sphinxcontrib.htmlhelp (2.1.0)
#   sphinxcontrib.serializinghtml (2.0.0)
#   sphinxcontrib.qthelp (2.0.0)
#   sphinx.ext.autodoc.preserve_defaults (8.1.3)
#   sphinx.ext.autodoc.type_comment (8.1.3)
#   sphinx.ext.autodoc.typehints (8.1.3)
#   sphinx.ext.autodoc (8.1.3)
#   sphinx.ext.duration (8.1.3)
#   sphinx.ext.doctest (8.1.3)
#   sphinx.ext.napoleon (8.1.3)
#   sphinx.ext.autosummary (8.1.3)
#   sphinx.ext.viewcode (8.1.3)
#   sphinxcontrib.plantuml (unknown version)
#   add_pdf_viewer (unknown version)
#   sphinxcontrib.jquery (4.1)
#   sphinx_rtd_theme (unknown version)

# Traceback:
Traceback (most recent call last):
  File "Python310\lib\site-packages\sphinx\cmd\build.py", line 514, in build_main
    app.build(args.force_all, args.filenames)
  File "Python310\lib\site-packages\sphinx\application.py", line 381, in build
    self.builder.build_update()
  File "Python310\lib\site-packages\sphinx\builders\__init__.py", line 358, in build_update
    self.build(
  File "Python310\lib\site-packages\sphinx\builders\__init__.py", line 437, in build
    self.write(docnames, list(updated_docnames), method)
  File "Python310\lib\site-packages\sphinx\builders\__init__.py", line 711, in write
    self.write_documents(docnames)
  File "Python310\lib\site-packages\sphinx\builders\__init__.py", line 725, in write_documents
    self._write_serial(sorted_docnames)
  File "Python310\lib\site-packages\sphinx\builders\__init__.py", line 744, in _write_serial
    self.write_doc(docname, doctree)
  File "Python310\lib\site-packages\sphinx\builders\html\__init__.py", line 653, in write_doc
    self.docwriter.write(doctree, destination)
  File "Python310\lib\site-packages\docutils\writers\__init__.py", line 80, in write
    self.translate()
  File "Python310\lib\site-packages\sphinx\writers\html.py", line 35, in translate
    self.document.walkabout(visitor)
  File "Python310\lib\site-packages\docutils\nodes.py", line 186, in walkabout
    if child.walkabout(visitor):
  File "Python310\lib\site-packages\docutils\nodes.py", line 186, in walkabout
    if child.walkabout(visitor):
  File "Python310\lib\site-packages\docutils\nodes.py", line 186, in walkabout
    if child.walkabout(visitor):
  File "Python310\lib\site-packages\docutils\nodes.py", line 178, in walkabout
    visitor.dispatch_visit(self)
  File "Python310\lib\site-packages\sphinx\util\docutils.py", line 723, in dispatch_visit
    method(node)
  File "Python310\lib\site-packages\sphinxcontrib\plantuml.py", line 584, in html_visit_plantuml
    fnames = dict((e, render_plantuml(self, node, e)) for e in fileformats)
  File "Python310\lib\site-packages\sphinxcontrib\plantuml.py", line 584, in <genexpr>
    fnames = dict((e, render_plantuml(self, node, e)) for e in fileformats)
  File "Python310\lib\site-packages\sphinxcontrib\plantuml.py", line 236, in render_plantuml
    cachefname = self.builder.plantuml_builder.render(node, fileformat)
  File "Python310\lib\site-packages\sphinxcontrib\plantuml.py", line 412, in render
    rename(f.name, outfname)
  File "Python310\lib\site-packages\sphinxcontrib\plantuml.py", line 51, in rename
    os.rename(src, dst)
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'MirrorAI\\Documentation_Build\\_plantuml\\42\\42c32892f81bd3b5ceb5ef3960380dd689d2aee8.png.newrozahnne' -> 'MirrorAI\\Documentation_Build\\_plantuml\\42\\42c32892f81bd3b5ceb5ef3960380dd689d2aee8.png'

RST FILE:

.. MirrorAI documentation master file, created by
   sphinx-quickstart on Wed Oct 13 2021.
   You can adapt this file completely to your liking, but it should at least
   contain the root `toctree` directive.

Welcome to MirrorAI's documentation!
====================================

.. toctree::
   :maxdepth: 2
   :caption: Contents:

   project_execution_and_results
   modules

   

Indices and tables
==================

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

CONF.PY FILE:

# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Path setup -----------------------------------------------------
import os
import sys
print(sys.path)        # Debug: Print the sys.path
# Add the path to your project directory to Python's path
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))  # Replace '.' with the path to your project directory
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'SphinxScripts')))

# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information

project = 'MirrorAI'
copyright = '2024, SomeName'
author = 'SomeName'
release = '1.0'

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

extensions = ['sphinx.ext.autodoc',
              'sphinx.ext.duration',
              'sphinx.ext.doctest',
              'sphinx.ext.napoleon',
              'sphinx.ext.autosummary',
              'sphinx.ext.viewcode',
              'sphinx.ext.mathjax',
              'sphinxcontrib.plantuml',
              'add_pdf_viewer']

autodoc_member_order = 'bysource'  # 'alphabetical' or 'groupwise' are other options
autosummary_generate = True              
templates_path = ['_templates']
diagrams_path = ['_diagrams']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
plantuml = 'java -jar Path/MirrorAI/plantuml-1.2024.8.jar'
# extension 'sphinxcontrib.plantuml',

# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output

html_theme = 'sphinx_rtd_theme'        # or 'alabaster'
html_static_path = ['_static']
html_css_files = ['custom.css'] # Link to your custom CSS file
html_js_files = ['https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.5.207/pdf.min.js',
                 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.5.207/pdf.worker.min.js']

Environment Information


Platform:              win32; (Windows-10-10.0.19045-SP0)
Python version:        3.10.2 (tags/v3.10.2:a58ebcc, Jan 17 2022, 14:12:15) [MSC v.1929 64 bit (AMD64)])
Python implementation: CPython
Sphinx version:        8.1.3
Docutils version:      0.21.2
Jinja2 version:        3.1.5
Pygments version:      2.18.0

Sphinx extensions

extensions = ['sphinx.ext.autodoc',
              'sphinx.ext.duration',
              'sphinx.ext.doctest',
              'sphinx.ext.napoleon',
              'sphinx.ext.autosummary',
              'sphinx.ext.viewcode',
              'sphinx.ext.mathjax',
              'sphinxcontrib.plantuml',
              'add_pdf_viewer']
@etainardi
Copy link
Author

etainardi commented Jan 27, 2025

Solved it myself. I figured I'd drop dead if I waited.

Any more subtle solution would be great in case anyone has any suggestions.

for the file:
Python\Python310\Lib\site-packages\sphinxcontrib\plantuml.py

the following function was to blame:

    def rename(src, dst):
        try:
            os.rename(src, dst)
        except OSError as err:
            if err.errno != errno.EEXIST:
                raise
            os.unlink(dst)
            os.rename(src, dst)

Re-written it as follows, with retries to handle transient file access issues:

    def rename(src, dst, retries=5, delay=0.5):
        for attempt in range(retries):
            try:
                os.rename(src, dst)
                return  # Success, exit the function
            except OSError as err:
                if err.errno == errno.EEXIST:
                    # Destination file exists; remove it and retry
                    try:
                        os.unlink(dst)
                    except OSError as unlink_err:
                        raise RuntimeError(f"Failed to remove existing file: {dst}") from unlink_err
                    os.rename(src, dst)
                    return
                elif err.errno == 32:  # Windows-specific: File is being used by another process
                    if attempt < retries - 1:
                        time.sleep(delay)  # Wait before retrying
                    else:
                        raise RuntimeError(f"File rename failed after {retries} attempts: {src} -> {dst}") from err
                else:
                    raise  # Raise any other exceptions immediately

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant