Skip to content

Writing Scripts

KaiUR edited this page May 12, 2026 · 4 revisions

Writing Scripts

Scripts in this collection are run through CatiaMenuWin32, which verifies each script's integrity before running it. Never ask users to edit a script directly — the app checks the SHA hash of every downloaded script against GitHub before launching it. A script that has been locally modified will fail the integrity check and the app will refuse to run it. User-configurable settings must be stored outside the script file using the persistent data pattern described below.


Folder Structure

Scripts must be placed in a subfolder — the subfolder name becomes the tab name in the app:

Any_Document_Scripts\
Part_Document_Scripts\
Process_Document_Scripts\
Product_Document_Scripts\
Shape_Generation_Scripts\

The setup\ folder is reserved for requirements.txt and is never shown as a tab.


Required Header

Every script must begin with a structured metadata header. CatiaMenuWin32 reads this to display the script name, purpose, and description on the button and in the Script Details panel:

'''
    -----------------------------------------------------------------------------------------------------------------------
    Script name:    Your_Script_Name.py
    Version:        1.0
    Code:           Python3.10.4, Pycatia 0.8.3
    Release:        V5R32
    Purpose:        One line summary shown on the script button.
    Author:         Your Name
    Date:           DD.MM.YY
    Description:    Full description of what the script does, what inputs it
                    needs, and what outputs it produces. Continuation lines
                    must be indented.
    dependencies = [
                    "pycatia",
                    ]
    requirements:   Python >= 3.10
                    pycatia
                    Catia V5 running with an open part document.
    -----------------------------------------------------------------------------------------------------------------------
'''

Header Rules

  • Must be inside a triple-quoted string at the very top of the file
  • Purpose — one line only; shown as the subtitle on the script button
  • Description — full detail; continuation lines must be indented
  • dependencies — list all pip packages the script requires
  • requirements — describe the CATIA state needed (document type, open document, etc.)

Naming

Use Snake_Case_Descriptive_Name.py. The app converts underscores to spaces automatically — Export_Points_To_CSV.py becomes Export Points To CSV on the button.


Dependencies

Add any pip packages your script requires to setup/requirements.txt. The app's ↧ Deps button installs them automatically.


Persistent Data

Never ask users to edit a script to change settings or parameters. CatiaMenuWin32 verifies the SHA hash of every downloaded script against GitHub before running it. A script edited locally will fail the integrity check and the app will refuse to run it. All user-configurable data must be stored outside the script file.

Where to Save Data

Store settings in a per-script folder under %APPDATA%\pycatia_scripts\:

%APPDATA%\pycatia_scripts\<Your_Script_Name>\user_settings.json

Use the script filename (without .py) as the folder name. This keeps each script's data isolated and easy to locate or clean up.

Implementation Pattern

Define your hardcoded defaults at the top of the if __name__ == "__main__": block, load the saved file over them, then save after the user confirms:

import os
import json

SETTINGS_DIR  = os.path.join(os.environ['APPDATA'], 'pycatia_scripts', 'Your_Script_Name')
SETTINGS_FILE = os.path.join(SETTINGS_DIR, 'user_settings.json')

# --- In your dialog __init__ ---
hardcoded_defaults = {
    "my_param":     "10.0",
    "another_param": "5.0",
}
settings = hardcoded_defaults.copy()

if os.path.exists(SETTINGS_FILE):
    try:
        with open(SETTINGS_FILE, 'r') as f:
            settings.update(json.load(f))
    except:
        pass  # Fall back to hardcoded defaults on corrupt or missing file

# Pre-fill dialog fields from settings ...

# --- After user clicks OK ---
if not os.path.exists(SETTINGS_DIR):
    os.makedirs(SETTINGS_DIR)

current_data = {
    "my_param":     dlg.my_field.GetValue(),
    "another_param": dlg.other_field.GetValue(),
}
with open(SETTINGS_FILE, 'w') as f:
    json.dump(current_data, f, indent=4)

Rules

  • Always define hardcoded_defaults in the script — these are the factory defaults used when no saved file exists
  • Wrap the file read in try/except and fall back to defaults if the file is corrupt or unreadable
  • Create the directory before writing: use os.makedirs(SETTINGS_DIR) after checking it does not exist
  • Save only on successful completion (when the user clicks OK), not on cancel or error

Provide a Clear Saved Button

Any script that saves settings should include a Clear Saved button in its dialog. This lets users delete the settings file and return to factory defaults without needing to edit or touch any files:

def on_clear_saved(self, event):
    if os.path.exists(SETTINGS_FILE):
        os.remove(SETTINGS_FILE)
        # Reset all dialog fields back to hardcoded_defaults values
    else:
        wx.MessageBox("No saved settings file found.", "Information", wx.OK | wx.ICON_INFORMATION)

See Involute Gear Generator and Check Operation Parameters Against Limits for complete working examples.


Raising Dialogs Above CATIA

CATIA holds the Windows foreground lock, so a plain wx.Dialog will appear behind the CATIA window. Every script that shows a dialog must include the _bring_to_front helper and call it via wx.CallAfter before ShowModal():

import ctypes

def _bring_to_front(window):
    u32 = ctypes.windll.user32
    hwnd = window.GetHandle()
    fg_hwnd = u32.GetForegroundWindow()
    fg_tid = u32.GetWindowThreadProcessId(fg_hwnd, None)
    our_tid = ctypes.windll.kernel32.GetCurrentThreadId()
    if fg_tid != our_tid:
        u32.AttachThreadInput(fg_tid, our_tid, True)
    u32.BringWindowToTop(hwnd)
    u32.SetForegroundWindow(hwnd)
    if fg_tid != our_tid:
        u32.AttachThreadInput(fg_tid, our_tid, False)

Call it at the show site — not before ShowModal:

dlg = ScriptDialog(None)
wx.CallAfter(_bring_to_front, dlg)   # scheduled into ShowModal's event loop
result = dlg.ShowModal()

wx.CallAfter schedules the call to run during ShowModal's event loop, at which point the dialog is already visible and has a valid window handle. Calling _bring_to_front before ShowModal does nothing — the window does not exist yet.

wx.STAY_ON_TOP alone is not sufficient because it cannot override the foreground lock that CATIA holds. It can still be added to the dialog style as a secondary layer to prevent CATIA from covering the dialog after it has been raised, but _bring_to_front is the primary mechanism.

All dialog templates in setup/templates/ already include this helper.


Templates

Ready-to-use starting points are in setup/templates/ in the repository. See Script Templates for the full table and step-by-step guide.


Common Functions

setup/templates/common_functions.py is a reference file of helper functions that appear across many scripts in the collection. Copy the functions you need directly into your own script — do not import the file.

Included functions:

Function Category Used in
searchHybridBody Geometric set navigation Most Part Document scripts
searchHybridBodyWithPath Geometric set navigation Scripts that report set paths
create_datum Geometry operations Isolate / datum-ise hybrid shapes
collect_all_names Geometry operations Recursive name audits
normalize_vector, dot_product, cross_product, are_collinear Coordinate maths Geometry measurement scripts
coords_relative_to_axis Coordinate maths Axis-relative measurement
get_path File input Scripts with a file-picker dialog

All Part Document templates already include searchHybridBody and create_datum. See Common Functions for the full reference with signatures and usage examples.


Contributing Scripts

See CONTRIBUTING.md for full contribution guidelines including pull request process and code style.

Home


Getting Started


Contributing


Any Document Scripts


Part Document Scripts


Shape Generation Scripts


Process Document Scripts


Product Document Scripts


Legal

Clone this wiki locally