rinohtype icon indicating copy to clipboard operation
rinohtype copied to clipboard

NotImplementedError for desc_sig_keyword node with Sphinx frontend

Open vikrantrathore opened this issue 7 months ago • 6 comments

Is there an existing issue for this?

  • [x] I have searched the existing issues

Sphinx or rinoh output

Traceback
=========

      File ".../.venv/lib/python3.12/site-packages/rinoh/frontend/__init__.py", line 30, in map_node
        raise NotImplementedError("{}:{} the '{}' node is not yet supported "
    NotImplementedError: None:None the 'desc_sig_keyword' node is not yet supported (rinoh.frontend.sphinx.nodes)

Source files

Hello Rinohtype Team,

I am encountering a NotImplementedError when trying to build a PDF from a Sphinx project using the Rinohtype builder. The error indicates that the desc_sig_keyword node is not yet supported by the rinoh.frontend.sphinx.nodes module.

This issue seems to prevent the rendering of API documentation, likely generated by extensions such as autoapi.extension or standard Sphinx autodoc directives, as desc_sig_keyword is commonly used for representing keywords in code signatures.

Environment:

  • Platform: macOS (darwin)
  • Python version: 3.12.9 (CPython)
  • Rinohtype version: rinoh.frontend.sphinx (0.5.5)
  • Sphinx version: 8.2.3
  • Docutils version: 0.21.2
  • Relevant Sphinx Extensions Used: (Please list extensions you suspect are involved, e.g., autoapi.extension, sphinx.ext.autodoc, sphinx_click)

Steps to Reproduce (Conceptual):

  1. Set up a Sphinx project that uses an extension like autoapi.extension to generate API documentation from Python source code, or uses sphinx.ext.autodoc to document code objects with type hints and keywords.
  2. Configure Sphinx's conf.py to use the Rinohtype builder (rinoh.frontend.sphinx).
  3. Attempt to build the PDF output using sphinx-build -b rinoh source_dir output_dir.

Expected Behavior:

The PDF should build successfully, with code signatures (including keywords like def, class, type hints, etc.) rendered appropriately.

Actual Behavior:

The build process fails with the following traceback:

Traceback (most recent call last):
  File ".../.venv/lib/python3.12/site-packages/rinoh/frontend/__init__.py", line 27, in map_node
    return cls._mapping[node_name.replace('-', '_')](node, **context)
           ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
KeyError: 'desc_sig_keyword'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File ".../.venv/lib/python3.12/site-packages/sphinx/cmd/build.py", line 432, in build_main
    app.build(args.force_all, args.filenames)
  # ... (further traceback lines as provided previously, omitting user-specific paths) ...
  # ... culminating in ...
  File ".../.venv/lib/python3.12/site-packages/rinoh/frontend/__init__.py", line 30, in map_node
    raise NotImplementedError("{}:{} the '{}' node is not yet supported "
NotImplementedError: None:None the 'desc_sig_keyword' node is not yet supported (rinoh.frontend.sphinx.nodes)

Last Build Messages (if relevant): (You can include the "Last Messages" section from your Sphinx output here if it provides context, removing any sensitive project names)

   ...
   resolving references...

Loaded Extensions (Relevant Subset): (You can include the "Loaded Extensions" section, perhaps trimmed to the most relevant ones)

* sphinx.ext.autodoc (8.2.3)
* autoapi.extension (unknown version)  # Or version if known
* rinoh.frontend.sphinx (0.5.5)
...

Additional Context:

  • The issue persists with the latest available versions of Rinohtype, Sphinx, and related packages as of [current date].
  • The desc_sig_keyword node is a standard part of Sphinx's description unit nodes, making its support important for comprehensive API documentation rendering.

Could you please look into adding support for the desc_sig_keyword node in the Sphinx frontend? Let me know if a minimal reproducible example project would be helpful.

Thank you for your work on Rinohtype!

Versions

*   **Platform:** macOS (darwin)
*   **Python version:** 3.12.9 (CPython)
*   **Rinohtype version:** `rinoh.frontend.sphinx (0.5.5)`
*   **Sphinx version:** 8.2.3
*   **Docutils version:** 0.21.2

vikrantrathore avatar May 24 '25 07:05 vikrantrathore

I suspect there might be a very straightforward solution for this, but I would need to reproduce the issue to verify whether this properly fixes the issue. It takes far too much time to figure out exactly which reStructuredText input reproduces this crash, so please do provide a minimal reproducible sample project. Thanks!

brechtm avatar May 24 '25 09:05 brechtm

I can give you the rts file which below:

// professional.rts
// This stylesheet defines a complete document template by importing article.rts.
// article.rts is a standard Rinohtype document template.
@import article.rts

// Global styling options
[styling]
// Fallback font for symbols or characters not present in the primary fonts.
// Install a font like Noto Sans Symbols2 for broad Unicode coverage.
font_fallbacks = $(font_fallbacks_var)

[VARIABLES]
// Define main typeface families as variables for easy customization
serif_typeface = EB Garamond
sans_typeface = Source Sans Pro
mono_typeface = Fira Mono
font_fallbacks_var = Noto Sans Symbols2 // Used in [styling] section

// Define some colors (optional, can be directly used in styles)
main_text_color = #333333
heading_text_color = #2c3e50
code_background_color = #F8F9FA
code_border_color = #E0E0E0
admonition_blue = #4A90E2
admonition_blue_bg = #E9F5FC
admonition_orange = #F5A623
admonition_orange_bg = #FFF9E6
admonition_red = #D0021B
admonition_red_bg = #FCEFEE
admonition_green = #7ED321
admonition_green_bg = #E7F5E8

[STYLES]
// Base style for the document
base = typeface: $(serif_typeface)
       font_size: 10pt
       line_spacing: proportional(1.45) // Replaces line_height
       text_color: $(main_text_color)

// Paragraph styles
paragraph = extends: base // Ensure paragraph inherits base text properties
            margin_bottom: 6pt
            indent_first: 1.5em // Replaces first_line_indent
            text_align: justify

// Heading styles (H1-H4)
heading = typeface: $(sans_typeface)
          font_weight: bold
          text_color: $(heading_text_color)
          keep_with_next: true
          // Ensure headings reset paragraph indentation for themselves
          indent_first: 0pt

heading_1 = extends: heading
            font_size: 22pt
            margin_top: 24pt
            margin_bottom: 16pt
            text_align: left

heading_2 = extends: heading
            font_size: 18pt
            margin_top: 20pt
            margin_bottom: 12pt
            text_align: left

heading_3 = extends: heading
            font_size: 15pt
            margin_top: 16pt
            margin_bottom: 8pt
            text_align: left

heading_4 = extends: heading
            font_size: 12pt
            // font_weight: bold_italic // Rinohtype typically uses font_slant for italic
            font_slant: italic
            margin_top: 12pt
            margin_bottom: 6pt
            text_align: left

// Table of Contents styles
toc_title = extends: heading_1
            text_align: left
            margin_bottom: 24pt
            text: Contents // Default, can be overridden by Sphinx language settings

// Base style for all ToC entries
toc_entry = typeface: $(sans_typeface)
            margin_bottom: 5pt
            // Define tab stop for page numbers: right-aligned at 100% width, with dots as leader
            tab_stops: 100% right '.'
            text_align: left // For the entry text part

toc_1 = extends: toc_entry
        font_size: 11pt
        font_weight: normal // Or bold if preferred
        text: '{NUMBER} {TITLE}{TAB}{PAGE}' // {TAB} will use the tab_stops definition
        margin_left: 0em

toc_2 = extends: toc_entry
        font_size: 10pt
        text: '{NUMBER} {TITLE}{TAB}{PAGE}'
        margin_left: 1.5em

toc_3 = extends: toc_entry
        font_size: 10pt
        text: '{NUMBER} {TITLE}{TAB}{PAGE}'
        margin_left: 3em

toc_4 = extends: toc_entry
        font_size: 10pt
        text: '{NUMBER} {TITLE}{TAB}{PAGE}'
        margin_left: 4.5em


// List styles
bullet_list_item_paragraph = margin_bottom: 2pt
bullet_list_item = marker_style: disc // Standard disc marker
                   margin_bottom: 4pt
                   margin_left: 1.5em

enumerated_list_item_paragraph = margin_bottom: 2pt
enumerated_list_item = margin_bottom: 4pt
                       margin_left: 1.5em

// Code and literal text styles
literal = typeface: $(mono_typeface) // Inline code
          font_size: 0.9em
          background_color: #f0f0f0
          padding_left: 0.2em
          padding_right: 0.2em
          border_radius: 2pt

literal_block = typeface: $(mono_typeface) // Code blocks
                font_size: 9pt
                background_color: $(code_background_color)
                padding: 10pt
                border_width: 0.5pt
                border_color: $(code_border_color)
                border_radius: 3pt
                line_spacing: proportional(1.35)
                hyphenate: false // Important for code
                margin_top: 12pt
                margin_bottom: 12pt

// Table styles
table = margin_top: 12pt
        margin_bottom: 12pt
        default_border_width: 0.5pt // This applies to cell borders if not overridden
        default_border_color: #BFBFBF

table_cell = padding: 5pt
             vertical_alignment: top // Default, can be overridden per cell

table_header_cell = extends: table_cell
                    font_weight: bold
                    typeface: $(sans_typeface)
                    background_color: #EAEAEA

// Admonition styles (note, warning, etc.)
admonition = padding: 12pt
             margin_top: 12pt
             margin_bottom: 12pt
             border_width: 1pt
             border_radius: 3pt

admonition_title = typeface: $(sans_typeface)
                   font_weight: bold
                   font_size: 1.1em
                   margin_bottom: 6pt

note = extends: admonition
       border_color: $(admonition_blue)
       background_color: $(admonition_blue_bg)
note_title = extends: admonition_title
             color: $(admonition_blue) // Title color same as border for consistency

warning = extends: admonition
          border_color: $(admonition_orange)
          background_color: $(admonition_orange_bg)
warning_title = extends: admonition_title
                color: $(admonition_orange)

important = extends: admonition // Sphinx 'important' often maps to a red admonition
            border_color: $(admonition_red)
            background_color: $(admonition_red_bg)
important_title = extends: admonition_title
                  color: $(admonition_red)

tip = extends: admonition // Sphinx 'tip' often maps to a green admonition
      border_color: $(admonition_green)
      background_color: $(admonition_green_bg)
tip_title = extends: admonition_title
            color: $(admonition_green)

// Definition List styles
definition_list_term = font_weight: bold
                       typeface: $(sans_typeface)
                       margin_bottom: 2pt
definition_list_classifier = font_slant: italic
                               font_weight: normal
definition = margin_left: 1.5em
             margin_bottom: 8pt

// Style for text in headers and footers (used in PAGE_TEMPLATES)
header_footer_text = typeface: $(sans_typeface)
                     font_size: 8pt
                     color: #555555

[PAGE_TEMPLATES]
// Base page configuration used by other page templates
_base_page = columns: 1
             margin_top: 2.2cm
             margin_bottom: 2.2cm
             margin_left: 2cm
             margin_right: 2cm

// Page template for the main document body (Arabic page numbers)
page = extends: _base_page
       header = [
           Flowable(type: Header, content: [
               Paragraph(DocumentTitle(), style: header_footer_text, alignment: left),
               Paragraph(SectionTitle(depth: 1), style: header_footer_text, alignment: center),
               Paragraph(PageNumber(), style: header_footer_text, alignment: right),
           ], horizontal_alignment: justify, padding_bottom: 0.3cm, border_bottom_width: 0.5pt, border_bottom_color: #AAAAAA)
       ]
       // Footer can be enabled by uncommenting and defining its content
       // footer = [ ... ]
       page_counter = PageCounter(format: arabic, start_value: 1)

// Page template for the title page (no header/footer by default from first_page)
// Roman numeral 'i' will be assigned but typically not displayed on the title page itself.
first_page = extends: _base_page
             header: null
             footer: null
             page_counter = PageCounter(format: roman, start_value: 1)

// Page template for front matter (e.g., Table of Contents - Roman page numbers)
front_matter_page = extends: _base_page
                    header = [
                        Flowable(type: Header, content: [
                            Paragraph(SectionTitle(), style: header_footer_text, alignment: center), // e.g., "Contents"
                        ], horizontal_alignment: justify, padding_bottom: 0.3cm, border_bottom_width: 0.5pt, border_bottom_color: #AAAAAA)
                    ]
                    footer = [
                        Flowable(type: Footer, content: [
                            Paragraph(PageNumber(), style: header_footer_text, alignment: center),
                        ], horizontal_alignment: justify, padding_top: 0.3cm, border_top_width: 0.5pt, border_top_color: #AAAAAA)
                    ]
                    page_counter = PageCounter(format: roman) // Continues Roman numbering from first_page

[DOCUMENT_SETUP]
page_template = page                 // Default template for body pages
first_page_template = first_page     // Template for the first page (title page)
front_matter_page_template = front_matter_page // Template for ToC etc.

[TEMPLATES]
// Custom Title Page Layout (this defines the 'title_page' document part's content)
title_page = [
    VSpace(3cm),
    Paragraph(DocumentTitle(), style: title_page_title),
    VSpace(1cm),
    Paragraph('Version ' + DocumentMetadata(name: version), style: title_page_subtitle),
    VSpace(3cm),
    If(DocumentMetadata(name: logo_file), [
        Image(DocumentMetadata(name: logo_file), width: 6cm, alignment: center), // type: image is implicit
        VSpace(3cm),
    ]),
    Paragraph(DocumentAuthor(), style: title_page_author),
    VFill(),
    Paragraph(DocumentDate(), style: title_page_date),
    VSpace(2cm),
]

// Styles for the custom title page elements
title_page_title = typeface: $(sans_typeface)
                   font_size: 30pt
                   font_weight: bold
                   alignment: center
                   line_spacing: proportional(1.2)
                   text_color: #1a237e

title_page_subtitle = typeface: $(sans_typeface)
                      font_size: 16pt
                      alignment: center
                      margin_top: 0.5cm
                      text_color: #555555

title_page_author = typeface: $(sans_typeface)
                    font_size: 16pt
                    alignment: center
                    margin_top: 1.5cm
                    text_color: #333333

title_page_date = typeface: $(sans_typeface)
                  font_size: 12pt
                  alignment: center
                  margin_top: 1cm
                  text_color: #555555

Sphinx Configuration for it is:

# --- Rinohtype PDF output configuration ------------------------------------

# Determine the directory of conf.py for robust path calculations
_conf_py_dir = os.path.dirname(__file__)

# Date for the title page (Rinohtype template can use DocumentDate())
current_date_formatted = datetime.now().strftime('%B %d, %Y')

# Path to the logo, relative to the conf.py directory.
# This is passed via metadata to the custom .rts template.
logo_filename = 'logo.png' # Just the filename
logo_relative_path_for_rinoh = os.path.join('_static', logo_filename) # 
_full_logo_path_check = os.path.join(_conf_py_dir, logo_relative_path_for_rinoh)
_logo_to_pass_to_template = logo_relative_path_for_rinoh if os.path.exists(_full_logo_path_check) else None

rinoh_documents = [
    dict(
        # Master document (usually 'index' or 'contents')
        doc='index',
        # Output PDF filename (without .pdf extension)
        target=f'{project.lower().replace(" ", "_").replace("/", "_")}',
        # Document title (for PDF metadata and available in templates via DocumentTitle())
        title=f'{project} Documentation',
        # Author (for PDF metadata and available in templates via DocumentAuthor())
        author=author,
        # Date (for PDF metadata and available in templates via DocumentDate())
        # The custom title page template uses DocumentDate()
        date=current_date_formatted,
        # Path to your custom .rts file (acting as stylesheet and template config)
        # Assumes 'professional.rts' is in the same dir as conf.py or in rinoh_stylesheet_path
        template='professional.rts',
        # Maximum depth for the Table of Contents
        toctree_depth=3,
        # Pass additional metadata to the Rinohtype template
        metadata=dict(
            # The .rts template uses 'version' and 'logo_file'
            version=release,
            logo_file=_logo_to_pass_to_template,
            # You can add other custom metadata here if your template needs it
            # project_name=project, # DocumentTitle() field is generally preferred in templates
        )
    )
]

# Optional: If 'professional.rts' is not in the same directory as conf.py,
# add the directory containing it to rinoh_stylesheet_path.
# For example, if it's in 'docs/source/_styles/':
rinoh_stylesheet_path = ['_styles']

vikrantrathore avatar May 24 '25 09:05 vikrantrathore

The .rts stylesheet seems to be made up by an LLM. It doesn't follow the basic .ini syntax, so it's not going to work. Also your conf.py includes fantasy variables such as "rinoh_stylesheet_path".

Please deliver a compressed archive of the Sphinx project that triggers the crash reported. Preferably, that contains the minumum of .rst content to reproduce the issue, but you can also send the entire project if that is too difficult. You can send it to me personally at [email protected] if you cannot share it publicly.

brechtm avatar May 24 '25 10:05 brechtm

@brechtm Thanks for pointing out the errors and I should have gone through in details with manual and reference guid instead of falling prey to LLM output by providing them as context. So created a new one and also removed the fantasy variable but error remains same.

Now will do some more troubleshooting before updating the issue.

vikrantrathore avatar May 24 '25 16:05 vikrantrathore

The .rts stylesheet seems to be made up by an LLM. It doesn't follow the basic .ini syntax, so it's not going to work. Also your conf.py includes fantasy variables such as "rinoh_stylesheet_path".

Please deliver a compressed archive of the Sphinx project that triggers the crash reported. Preferably, that contains the minumum of .rst content to reproduce the issue, but you can also send the entire project if that is too difficult. You can send it to me personally at [email protected] if you cannot share it publicly.

Ok removed the complete stylesheet and every rinoh related variable and try to use it as described in manual.pdf documentation. Following is the conf.py for rinoh.

rinoh_documents = [
    dict(
        doc='index',
        target=f'{project.lower().replace(" ", "_").replace("/", "_")}',
    )
]

It can generate one page index.rst if not linked it any other page as soon as include other pages it gives the same error as I have provided earlier.

../.venv/lib/python3.12/site-packages/rinoh/frontend/__init__.py", line 30, in map_node
        raise NotImplementedError("{}:{} the '{}' node is not yet supported "
    NotImplementedError: None:None the 'desc_sig_keyword' node is not yet supported (rinoh.frontend.sphinx.nodes)

I have a latex configuration and it successfully generated the pdf using latex. Also its able to generate html. I was not sharing the original document yet because I have not decided on the open source license and how to proceed. If you still need my rst files can send you later.

I have tried it on another project with simple file it did work for it.

Below is the index.rst:

###########################
Agentic System Introduction
###########################
	

Welcome to Our Agentic System!
------------------------------

This documentation provides an overview of our simple agentic system, its core concepts, and how it operates.

.. note::
   This documentation is actively being developed. Content and structure may evolve.
   
.. toctree::
   :maxdepth: 2
   :caption: Getting Started
   
   introduction

Introduction.rst:

.. _introduction:

############
Introduction
############
	
	
Introduction to Agentic Systems
-------------------------------

An **agentic system** is a computational system that perceives its environment through sensors and acts upon that environment through actuators to achieve specific goals. Key characteristics include:

*   **Autonomy**: Operates without direct human intervention.
*   **Reactivity**: Responds in a timely fashion to changes in the environment.
*   **Pro-activeness**: Exhibits goal-directed behavior by taking the initiative.
*   **Social ability** (optional for simple systems): Interacts with other agents.

Our System Overview
-------------------

This section describes the specific architecture and purpose of *our* agentic system.
(You would fill this with a brief summary of your particular system).

Core Components
---------------

Our agentic system is composed of the following main components:

Perception Module
~~~~~~~~~~~~~~~~~
The Perception Module is responsible for:

*   Gathering data from the environment (e.g., sensor readings, API responses).
*   Processing raw data into a more usable format for the agent.

Decision-Making Engine
~~~~~~~~~~~~~~~~~~~~~~
This is the "brain" of the agent. It:

*   Evaluates the current state based on perceived information.
*   Utilizes a set of rules, a model, or a policy to decide on the next action.
*   Aims to achieve predefined goals or maximize a utility function.

Action Module
~~~~~~~~~~~~~
The Action Module translates the decisions made by the engine into concrete actions:

*   Interacts with the environment through actuators (e.g., sending commands, API calls).
*   Provides feedback on action execution.

Environment Interface
~~~~~~~~~~~~~~~~~~~~~
Defines how the agent interacts with its specific environment. This could be:

*   A simulated world.
*   A set of APIs.
*   Physical sensors and actuators.

Simple Workflow Example
-----------------------

1.  **Perceive**: The Perception Module gathers data (e.g., "temperature is 25°C").
2.  **Decide**: The Decision-Making Engine processes this. If a goal is "maintain temperature below 24°C", it might decide to "activate cooling".
3.  **Act**: The Action Module executes the "activate cooling" command.
4.  **Environment Changes**: The temperature starts to drop.
5.  The cycle repeats.

Getting Started (Conceptual)
----------------------------

1.  **Define Goals**: What should the agent achieve?
2.  **Design Sensors/Perception**: How will the agent understand its environment?
3.  **Implement Decision Logic**: What rules or models will drive behavior?
4.  **Develop Actuators/Actions**: How will the agent influence its environment?
5.  **Integrate and Test**: Put all components together and observe.

Further Considerations
----------------------

*   **Learning**: Could the agent learn and improve over time?
*   **Error Handling**: What happens when actions fail or perception is noisy?
*   **Scalability**: Can the system handle more complex tasks or environments?

Indices and tables
------------------

vikrantrathore avatar May 26 '25 07:05 vikrantrathore

This NotImplementedError exception is related to the use of Sphinx domains which is used to document APIs. Your original messages states that you're using the autodoc extension, which also produces doctrees featuring domain nodes.

You can try to reduce the part of the API documented in your Sphinx project to where it's just enough to still trigger the NotImplementedError. I hope that will reduce the number of files you would need to share with me, as I can very well understand you're not super excited about sending your code with some random bloke on the internet. 😄 Anyway, if would be a tremendous help if you can do that, as these types of crashes seem to happen quite often. I'll also look into extracting more context when this crash happens to make them easier to debug in the future.

brechtm avatar May 26 '25 19:05 brechtm