Skip to content

feat: add updateAddon.py automated tool to complement existing#41

Open
abdel792 wants to merge 8 commits into
nvaccess:masterfrom
abdel792:updateAddon
Open

feat: add updateAddon.py automated tool to complement existing#41
abdel792 wants to merge 8 commits into
nvaccess:masterfrom
abdel792:updateAddon

Conversation

@abdel792

@abdel792 abdel792 commented Jul 9, 2026

Copy link
Copy Markdown

Link to issue number:

Close #37.

Summary of the issue:

Upgrading an existing add-on to follow the modern addonTemplate structure manually is a repetitive and error-prone process. Developers frequently encounter syntax issues or merge conflicts when manually porting old metadata into the new pyproject.toml structure.

Description of developer facing changes:

Introduces an automated update workflow. Developers can now run a single command (uv run updateAddon.py) from any directory on their PC to automatically migrate metadata, clean template placeholder data (like removing nvaccess from third-party authors lists), and merge project configurations while preserving custom formatting.

Description of development approach

  • Script implementation: Added updateAddon.py at the repository root. The script leverages an AST-aware (Abstract Syntax Tree) approach to perform safe, robust parsing and merging of TOML structures.
  • Dependency Update: Added tomlkit==0.13.0 under the # Update machinery section in pyproject.toml to support programmatic, comment-preserving TOML modifications.
  • Linter Exclusion: Added updateAddon.py to the exclude lists of both [tool.ruff] and [tool.pyright] within pyproject.toml to avoid unnecessary environmental or strict typing alerts during standard repository validation.
  • Documentation: Updated updatingExistingAddons.md to cleanly integrate prerequisites (Python 3.11+, Git available in PATH) and step-by-step instructions on how to use this new companion tool alongside the existing manual instructions.

Testing strategy:

The script and documentation workflow have been tested locally:

  1. Initialized a legacy NVDA add-on workspace using old metadata configurations.
  2. Ran git fetch template to ensure local tracking branches were up to date.
  3. Executed uv run updateAddon.py from the repository root, and verified that a _bak_ backup directory was safely generated.
  4. Checked the newly mutated pyproject.toml to ensure old custom metadata was correctly merged, template placeholder defaults were stripped, and file formatting/comments remained completely intact.
  5. Ran uv sync followed by uv run scons to ensure the final environment synchronized properly and the .nvda-addon bundle compiled successfully with zero errors.
  6. Repeated the execution from a completely different working directory outside the repository to confirm path flexibility.

Known issues with pull request:

None.


Code Review Checklist

  • Testing: Manually tested across diverse repository paths to confirm robustness. Steps to reproduce are detailed in the testing strategy.
  • API is compatible with existing add-ons: This is an infrastructure update tool for developers; it does not introduce any breaking API changes or modifications to the NVDA core ecosystem.
  • Documentation: Technical developer documentation (updatingExistingAddons.md) has been explicitly updated to reflect these changes.
  • UX of all users considered: N/A (Developer-facing infrastructure tool only).
  • Security precautions taken: N/A (The script executes locally during development and does not interact with secure screens or lock screen states).

…ration merges for legacy add-ons.

- Add tomlkit to project dependencies in pyproject.toml to support robust AST-aware TOML parsing.
- Update updatingExistingAddons.md to provide clear instructions and prerequisites for the new automated tool.
- Exclude the update script from ruff and pyright configurations to prevent strict environment linting conflicts.
@abdel792

abdel792 commented Jul 9, 2026

Copy link
Copy Markdown
Author

Hi @nvdaes,

I have just added you as a collaborator to this repository.

If you have some time and interest, feel free to directly review and update the docstrings in updateAddon.py to ensure they perfectly align with the project's official documentation conventions.

Thank you so much for your help and guidance on this!

@nvdaes

nvdaes commented Jul 9, 2026

Copy link
Copy Markdown

Thanks @abdel792 . I've accepted your invitation as a collaborator, and I'll try to update the docstrings.

@nvdaes

nvdaes commented Jul 9, 2026

Copy link
Copy Markdown

@abdel792 , can we add a way to ignore files which shouldn't be merged?
I think that @CyrilleB79 may be interested, and i'd like to have this possibility. For example, I don't want to use the build_addon.yml workflow since it's failing for me, and I prefer to remove it.
Also, I think that instructions for the script should be placed at the start of the file, and manual instructions maybe removed or placed at the end. BTW, they contain an error of a typo. With your permission, I'll fix it.

@abdel792

abdel792 commented Jul 9, 2026

Copy link
Copy Markdown
Author

Thanks a lot @nvdaes for your quick commits and for improving the docstrings and file headers!

Regarding your suggestions:

  1. Ignoring files: That's a great idea. Having a way to skip specific files (like workflows or custom configs) during the merge would make the tool much more flexible. I'll think about the best way to implement this (maybe via an ignore list/parameter) and update the script.
  2. Documentation structure: Completely agree. The automated tool should definitely be the primary option at the top of the file, with the manual steps as a fallback at the end. Please feel free to reorganize the file and fix the typo you found, you have my full permission!

I'll let you know once I've drafted the file-ignoring feature so we can test it. Thanks again for your amazing collaboration!

@nvdaes

nvdaes commented Jul 9, 2026

Copy link
Copy Markdown

@abdel792 , I've reorganized the documentation so that info about the script is at the start. Perhaps the information about merge should be removed=
Looking forward to see a way to ignore files/folders.
Thanks for all your amazing work.

abdel792 and others added 2 commits July 9, 2026 21:25
- Remove trailing "Press Enter to exit..." prompt at successful script completion to allow seamless execution in automated environments.
- Implement specific file/folder exclusion handling during synchronization, with full architecture setup requested by @CyrilleB79.
@abdel792

abdel792 commented Jul 9, 2026

Copy link
Copy Markdown
Author

Hi @nvdaes,

Thank you so much for updating the documentation! It looks great and makes using the automated tool very clear.

Could you please do me a favor and also integrate the new feature requested by @CyrilleB79 that I just implemented in my latest commit? It allows developers to exclude specific template files during synchronization.

Here is the markdown section that needs to be added to the documentation (you can place it right before the build verification step):

### Excluding specific template files

By default, the script synchronizes every infrastructure file provided by AddonTemplate.

If you want to preserve specific files from your repository (for example, a customized GitHub workflow), you can exclude them from synchronization.

Open `updateAddon.py` and locate the `IGNORED_FILES` set near the beginning of the `main()` function:

```python
IGNORED_FILES = {
    os.path.join(".github", "workflows", "build_addon.yml").lower(),
}

Add any relative path from the template root to this set to prevent that file from being synchronized.


@abdel792

abdel792 commented Jul 9, 2026

Copy link
Copy Markdown
Author

Hi @nvdaes,

While looking closely at our documentation, I am considering a complete overhaul and restructuring of the documentation files to make everything cleaner, more cohesive, and easier to navigate for developers.

Before diving into this, I wanted to open a discussion here to get your thoughts, ideas, or any suggestions you might have regarding how we should reorganize the content.

Let me know what you think!

- Completely restructure the guide to separate the recommended automated tool method from the manual Git merge workflow.
- Integrate detailed instructions for the automated companion script (`updateAddon.py`).
- Document the new template synchronization exclusions feature (`IGNORED_FILES`).
- Improve overall clarity, formatting, and prerequisites for initial repository setup.
@abdel792

abdel792 commented Jul 9, 2026

Copy link
Copy Markdown
Author

I have just committed a complete overhaul and reorganization of the update documentation (updatingExistingAddons.md).

In this update, I have:

  • Restructured the document to separate the recommended automated method from the manual workflow.
  • Added the full comprehensive guide for the automated update script (updateAddon.py).
  • Added a dedicated section explaining how to exclude specific template files using the IGNORED_FILES set, as requested by @CyrilleB79.

Please let me know if you have any feedback or further suggestions.

@nvdaes, please feel free to add, modify, or correct anything you see fit—you have the green light, of course!

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a developer-facing automation tool (updateAddon.py) intended to help migrate/update existing NVDA add-ons to the modern AddonTemplate structure, alongside documentation and dependency updates to support that workflow.

Changes:

  • Added updateAddon.py to clone the latest AddonTemplate, sync infrastructure files, and merge buildVars.py / pyproject.toml.
  • Updated pyproject.toml dependencies (pyright bump + new tomlkit dependency) and excluded updateAddon.py from ruff/pyright checks.
  • Expanded docs/managementFromGit/updatingExistingAddons.md with an “automated update” path plus revised manual instructions.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 11 comments.

File Description
updateAddon.py New CLI tool that syncs template infrastructure and performs AST/TOML-based merges.
pyproject.toml Adds tomlkit dependency and excludes the new script from lint/type-checking; bumps pyright.
docs/managementFromGit/updatingExistingAddons.md Documents the new automated update workflow and revises the manual update steps.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread updateAddon.py
Comment on lines +23 to +42
def deepMergeDicts(dictProj: dict[str, Any], dictTpl: dict[str, Any]) -> dict[str, Any]:
"""Recursively merges dictTpl into dictProj. Supports both dict and tomlkit container types.

:param dictProj: The original dictionary to be updated.
:param dictTpl: The template dictionary whose values will be merged into dictProj.
:return: The updated dictProj with merged values from dictTpl.
"""
for key, value in dictTpl.items():
if key in dictProj:
if isinstance(dictProj[key], dict) and isinstance(value, dict):
deepMergeDicts(dictProj[key], value)
elif isinstance(dictProj[key], list) and isinstance(value, list):
for item in value:
if item not in dictProj[key]:
dictProj[key].append(item)
else:
pass
else:
dictProj[key] = value
return dictProj
Comment thread updateAddon.py
Comment on lines +182 to +185
# Extract base package name (e.g. 'pyright' from 'pyright[nodejs]==1.1.407')
def get_base(s: str) -> str:
return s.split("[")[0].split("=")[0].split(">")[0].strip().lower()

Comment thread updateAddon.py
Comment on lines +241 to +247
if val is None:
formattedVal = "None"
elif isinstance(val, str):
is_multiline = key in ["addon_summary", "addon_description", "addon_changelog"]
formattedVal = f'_("""{val}""")' if is_multiline else f'"{val}"'
else:
formattedVal = str(val)
Comment thread updateAddon.py
Comment on lines +315 to +327
addonDirInput = args.addonDir if args.addonDir else os.getcwd()
addonDir = os.path.abspath(addonDirInput)

print("=== NVDA ADD-ON UPDATE TOOL ===")
print(f"[*] Target Directory: {addonDir}")

oldBuildvars = os.path.join(addonDir, "buildVars.py")
oldPyproject = os.path.join(addonDir, "pyproject.toml")

if not os.path.exists(oldBuildvars):
print(f"[-] Error: '{addonDir}' does not appear to be a valid NVDA Add-on (missing buildVars.py).")
input("\nPress Enter to exit...")
sys.exit(1)
Comment thread updateAddon.py
print("[+] Backup created successfully.")
except Exception as e:
print(f"[-] Critical: Backup failed ({e}). Aborting update.")
input("\nPress Enter to exit...")
Comment thread pyproject.toml
"pyright[nodejs]==1.1.407",
"pyright[nodejs]==1.1.411",
# Repository synchronization machinery
"tomlkit>=0.12.0",
Comment on lines +9 to +12
```sh
cd {repoFolder}
git clone https://github.com/{repoName}.git
```

Before running the tool, ensure your system meets the following requirements:

- **Python**: Version **3.11** or newer must be installed.
Comment on lines +102 to +103
> [!NOTE]
> Before modifying any infrastructure files, the script creates an untracked `_bak_` directory containing backups of every file it updates. If necessary, you can restore these files manually.
Comment on lines +90 to +100
Fetch the latest version of AddonTemplate:

```sh
git fetch template
```

Run the update script:

```sh
uv run updateAddon.py
```
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

Successfully merging this pull request may close these issues.

Add documentation for updating the template

3 participants