83 Commits

Author SHA1 Message Date
Campbell Barton
50f3240abd Cleanup: spelling & duplicate terms (check_spelling.py) 2025-05-30 11:03:56 +10:00
Hans Goudey
91803e130f Cleanup: Grammar: Fix uses of "for e.g."
e.g. stands for "exempli gratia" in Latin which means "for example".
The best way to make sure it makes sense when writing is to just expand
it to "for example". In these cases where the text was "for e.g.", that
leaves us with "for for example" which makes no sense. This commit fixes
all 110 cases, mostly just just replacing the words with "for example",
but also restructuring the text a bit more in a few cases, mostly by
moving "e.g." to the beginning of a list in parentheses.

Pull Request: https://projects.blender.org/blender/blender/pulls/139596
2025-05-29 21:21:18 +02:00
YimingWu
68a0e68bcd Fix #135999: Extensions: Remove emails in bl_info['author']
Previously when an addon is expanded on the UI, the "Maintainer" string
would be cut short until a `<` character, to prevent showing e-mail on the
UI, however there could be more than one person/email entries in there
so to prevent cutting short the string, now we use regex to take out the
email part only, so full maintainer string is displayed.

Pull Request: https://projects.blender.org/blender/blender/pulls/136031
2025-03-24 07:35:44 +01:00
Campbell Barton
fb3fe458bf Extensions: forward any errors setting up wheels to reports
When actions on extensions failed setup extensions, errors weren't
forwarded to the user and were only visible in the terminal.
2025-02-07 20:30:02 +11:00
Campbell Barton
6ca1417103 Cleanup: suppress unused Python warnings
Suppress unused warnings using the "vulture" utility.

- Include public definitions in the modules `__all__`.
- Mark arguments & variables as unused with a "_" prefix.
2024-12-03 12:54:13 +11:00
Campbell Barton
db62ddd57c Merge branch 'blender-v4.3-release' 2024-11-09 13:20:40 +11:00
Campbell Barton
325c8c0190 PyDoc: add doc-string for addon_utils.extensions_refresh 2024-11-09 13:19:27 +11:00
Campbell Barton
9ee8e00fbc Merge branch 'blender-v4.3-release' 2024-11-09 11:46:44 +11:00
Campbell Barton
cd07e729a2 Fix #130024: addon_utils.enable(..) doesn't setup extensions wheels
addon_utils.enable/disable now handle wheels so that the functions can
be used with extension add-ons.

A new argument `refresh_handled` supports scripts handing refresh
themselves which is needed to avoid refreshing many times in cases
when there are multiple calls to enable/disable.

This is mostly useful for internal operations.
2024-11-09 11:44:34 +11:00
Jonas Holzman
263212c4fa Merge branch 'blender-v4.3-release' 2024-11-09 01:35:36 +01:00
Campbell Barton
eb390425f3 Fix missing extensions refresh after the repository config changed
Enabling/disabling a repository was not refreshing its wheels or
compatibility data.
2024-11-09 11:10:26 +11:00
Campbell Barton
e97e2e4b6d Merge branch 'blender-v4.3-release' 2024-11-03 22:04:42 +11:00
Campbell Barton
901359abf7 Cleanup: replace doc-strings with comments for internal logic
There is no need to store text in memory for comments on functions
that aren't exposed publicly and are only of used when reading
the code.
2024-11-03 21:50:33 +11:00
Campbell Barton
f17379a5d0 Merge branch 'blender-v4.3-release' 2024-11-03 16:07:40 +11:00
Campbell Barton
3bcfb151c1 PyDoc: use Python's type annotation syntax for doc-strings
Replace plain-text type information with the type syntax used
for Python's type annotations as it's more concise, especially for
callbacks which often didn't include useful type information.

Note that this change only applies to inline doc-strings,
generated doc-strings from RNA need to be updated separately.

Details:

- Many minor corrections were made when "list" was incorrectly used
  instead of "sequence".
- Some type information wasn't defined in the doc-strings and has been
  added.
- Verbose type info would benefit from support for type aliases.
2024-11-03 15:44:35 +11:00
Campbell Barton
1cf7781596 Cleanup: quiet Python warnings from ruff 2024-10-27 22:35:58 +11:00
Campbell Barton
a0453ab87a Cleanup: update use of typing in for Python scripts 2024-10-23 12:48:09 +11:00
Campbell Barton
6d1e235f15 Cleanup: remove use of deprecated typing from scripts/modules/
Also use comments for typing that can't be checked.
2024-10-18 10:43:14 +11:00
Campbell Barton
1a1e75c253 Cleanup: replace implicit BaseException with Exception
Exception is more appropriate as a general exception in these cases.
2024-10-08 09:41:51 +11:00
Campbell Barton
1563ba7e6c Fix #128175: Updating extension can remove the extension on WIN32
On Windows an entire directory may be locked when any files inside it
are opened by another process. This can cause operations that
recursively remove a directory (uninstalling & updating) to fail
with a partially removed extension.

The case of uninstalling was already handled, where failure to remove
a directory would stage the extension for later removal.
In the case of updating however, the user could be left with a broken
(partially removed) extension where some files were removed, as the
directory was locked, the update would fail to extract new files.

Address this issue by renaming the directory before recursive removal.

The following logic has been implemented:

- If any files in the directory are locked, renaming will fail.
  So even though the operation fails the extension is left intact.

- If renaming succeeds, it's possible to apply the update.

  While it's possible (albeit unlikely) recursive removal fails,
  which could be caused by file-system permissions issues corruption or
  a process could open a file between rename & removal.

  In this case the renamed directory is staged for later removal.

Other changes:

- Resolve a related problem where the user could install an
  extension previously staged for removal, now installing an extension
  ensured it's not removed later.

  This would occur if uninstalling failed, the user resolves
  directory-lock, uninstalls again, then re-installs the extension.

- When an extension fails to be removed, don't attempt to remove
  user configuration for that extension.

  Prefer to keep the extension & it's settings in their "current state"
  if it can't be removed.
2024-10-03 12:15:27 +10:00
Campbell Barton
a7ab81d927 PyAPI: remove use of BaseException
BaseException was used as a catch-all in situations where it
didn't make sense and where "Exception" is more appropriate
based on Python's documentation & error checking tools,
`pylint` warns `broad-exception-caught` for e.g.

BaseException includes SystemExit, KeyboardInterrupt & GeneratorExit,
so unless the intention is to catch calls to `sys.exit(..)`,
breaking a out of a loop using Ctrl-C or generator-exit,
then it shouldn't be used.

Even then, it's preferable to catch those exceptions explicitly.
2024-10-01 13:18:46 +10:00
Campbell Barton
9f072ecefb Cleanup: remove unused exception values 2024-10-01 10:30:04 +10:00
Campbell Barton
5cb29528e6 Cleanup: spelling in comments 2024-08-26 11:50:15 +10:00
Campbell Barton
58c7237bbf Fix #125958: Disabling/uninstalling extensions doesn't remove wheels
Cleaning up wheels was skipped when there were no enabled extensions.

Now this is only skipped when there are no extensions on startup.
2024-08-16 18:12:57 +10:00
Campbell Barton
fc6a99e0d2 Fix #77837: Error removing addons/extension/wheels on WIN32
When deleting files on WIN32, open files cannot be removed.
This is especially a problem for compiled Python modules which
remain open once imported.

Previously it was not as common for add-ons to include compiled Python
modules however with extensions supporting Python-wheels,
it's increasingly likely users run into this.

Workaround the problem by:
- Scheduling the files for removal next time Blender starts.
- Rename paths that cannot be removed to avoid collisions when
  the paths is reused (re-installing for example).

This is supported for:
- Extensions.
- Python wheels.
- Legacy user add-ons.
- App-templates.

Details:
- On startup, a file exists that indicates cleanup is needed.
  In the common case the file doesn't exist.
  Otherwise module paths are scanned for files to remove.
- Since errors resolving paths to remove could result in user data loss,
  ensure the paths are always within the (extension/addon/app-template)
  directory.
- File locking isn't used, if multiple Blender instances start at the
  same time and try to remove the same files, this won't cause errors.
  Even so, remove the checking file immediately avoid unnecessary
  file-system access overhead for other Blender instances.

Also resolves #125049.
2024-08-05 09:49:14 +10:00
Campbell Barton
319684d8f6 Extensions: warn when extensions violate module policies
As each extension has it's own package, any modules it includes must be
imported as sub-modules. Warn if extensions are including themselves
in the sys.path as this breaks name-spacing of extensions.

Show these warnings in the add-on & extensions UI.
2024-07-11 17:50:30 +10:00
Campbell Barton
9ffc973918 Fix missing check for debug print 2024-07-11 14:22:49 +10:00
Campbell Barton
d13da71db4 Fix the extension add-on reloading when caching the extensions state
When the extensions add-on module was loaded before the add-on was
enabled, the module was detected as having changed since it had no
`__time__` member. Loading the add-on would then reload the module.

Resolve by setting the __time__ when first importing.
2024-07-11 14:12:36 +10:00
Campbell Barton
c29d8326e0 UI: sort add-ons by name
Previously add-ons were sorted by category & name, remove the category
only sorting by name since the category is no longer displayed and
isn't part of extension meta-data. Now the add-ons are sorted by name
(case insensitive).

Details:

- Store add-ons modules sorted to avoid having to sort on every redraw.
- addon_utils.modules() now returns an iterator.
2024-07-02 15:06:14 +10:00
Campbell Barton
67ddb0e1a5 Extensions: detect external changes on startup & loading preferences
Changes to an extensions manifest weren't accounted for.
This was particularly a problem for "System" extensions which aren't
intended to be managed inside Blender however the problem existed for
any changes made outside of Blender.

Now enabled extensions are checked on startup to ensure:

- They are compatible with Blender.
- The Python wheels are synchronized.

Resolves #123645.

Details:

- Any extension incompatibilities prevent the add-on being enabled
  with a message printing the reason for it being disabled.

- Incompatible add-ons are kept enabled in the preferences to avoid
  loosing their own preferences and allow for an upgrade to restore
  compatibility.

- To avoid slowing down Blender's startup:

  - Checks are skipped when no extensions are enabled
    (as is the case for `--factory-startup` & running tests).
  - Compatibility data is cached so in common case,
    the cache is loaded and all enabled extensions `stat` their
    manifests to detect changes without having to parse them.
  - The cache is re-generated if any extensions change or the
    Blender/Python version changes.

- Compatibility data is updated:

  - On startup (when needed).
  - On an explicit "Refresh Local"
    (mainly for developers who may edit the manifest).
  - When refreshing extensions after install/uninstall etc.
    since an incompatible extensions may become compatible
    after an update.
  - When reloading preferences.

- Additional info is shown when the `--debug-python` is enabled,
  if there are ever issues with the extension compatibility cache
  generation not working as expected.

- The behavior for Python wheels has changed so they are only setup
  when the extension is enabled. This was done to simplify startup
  checks and has the benefit that an installed but disabled extension
  never runs code - as the ability to install wheels means it could
  have been imported from other scripts. It also means users can disable
  an extension to avoid wheel version conflicts.

  This does add the complication however that enabling add-on which is
  an extension must first ensure it's wheels are setup.
  See `addon_utils.extensions_refresh(..)`.

See code-comments for further details.
2024-07-01 15:08:14 +10:00
Campbell Barton
350b8047c6 Extensions: move the wheel_manager out of the extensions add-on
Move wheel management to a generic private module, prepare addon_utils
to handle changes to repositories on load (needed to resolve #123645).
2024-07-01 10:07:16 +10:00
Campbell Barton
ac8da6c72e Extensions: move junction_module to a private location
bpy_extras is part of the public API where as the junction_module
is part of the internal implementation of extensions.
Move to "_bpy_internal".
2024-06-28 14:30:11 +10:00
Campbell Barton
96906536db Extensions: add a Python API for user editable extension directories
Provide a convenient way to access a writable directory for extensions.
This will typically be accessed via:

  bpy.utils.extension_path_user(__package__, create=True)

This API is provided as some extensions on extensions.blender.org
are writing into the extensions own directory which is error prone:

- The extensions own directory is removed when upgrading.
- Users may not have write access to the extensions directory,
  especially with "System" repositories which may be on shared network
  drives for example.

These directories are only removed when:

- Uninstalling the extension.
- Removing the repository and its files.
2024-06-26 14:23:17 +10:00
Campbell Barton
b4ea8583ed WM: correct logic for resetting add-ons & caching meta-data
All add-ons were being scanned at startup, while this didn't cause
errors it was noticeable with extensions where any errors in the
manifest were being reported at startup, even when running with
factory-startup (including blender's own tests).

Address two issues:

- The logic to "reset" add-ons, so as to match the preferences when
  reverting or resetting preferences always ran on startup.
  This occurred because a check for Python being initialized was
  incorrectly used to detect that this wasn't the first time preferences
  were being loaded (regression in [0]).

- Resetting add-ons scanned all add-ons (including disabled add-ons) to
  ensure their module cache is up to date. Since this the cache is
  lazily initialized, it's simpler to set it as uninitialized as
  resetting the add-ons doesn't require the cached meta-data.

[0]: 497bc4d19977abc7b9e2c0f5024a23057e680954
2024-06-10 00:22:56 +10:00
Campbell Barton
949dfbfaa8 Cleanup: Python script formatting
- Double quotes for strings.
- Trailing commas when wrapped lines.
2024-06-06 11:26:28 +10:00
Brecht Van Lommel
5ce58d63b7 Fix: bl_info version from extension is string instead of int tuple
The extensions spec says this should use semantic version,
so it should always start with X.Y.Z numbers.

Co-authored-by: Campbell Barton <campbell@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/122687
2024-06-04 16:21:25 +02:00
Damien Picard
f5c4372531 Extensions: expose extension tagline to bl_info
An extension's optional "tagline" field is equivalent to a legacy
add-on's "description". This allows exposing the tagline as a
description in `bl_info`.

The main goal of this change is to expose extension taglines to the
translations, since the legacy description was already extracted.

Pull Request: https://projects.blender.org/blender/blender/pulls/122327
2024-05-27 19:30:14 +02:00
Campbell Barton
744819cf9b Addons: only ever check "addons_core" for bundled add-ons
Avoid checking every scripts directory for add-ons core,
as creating this directory would cause "addons" to be ignored.
2024-05-16 15:06:10 +10:00
Campbell Barton
ecec9de4e6 Cleanup: remove internal argument to override the support level
This was only ever used for addons_contrib which has been removed.
2024-05-16 09:03:16 +10:00
Campbell Barton
c4a0bbb1f4 Extensions: Support online extensions and move add-ons outside Blender
The extensions system allows to extend Blender with connectivity to the internet. Right now it means Blender can
discover and install add-ons and themes directly from the internet, and notify users about their updates.

By default this is disabled (opt-in), and users can enable it the first time they try to install an extension or visit
the Prefences > Extensions tab. If this is enabled, Blender will automatically check for updates for
extensions.blender.org upon startup.

When will Blender access the remote repositories:

* Every time you open the Preferences → Extensions: ALL the enabled repositories get checked for the latest info (json)
* Every time you try to install by dragging: ALL the enabled repositories get checked for the latest info (json).
* Every time you start Blender: selected repositories get checked for the latest info (json).

------------------

From the Blender code point of view, this means that most of the add-ons and themes originally bundled with Blender
will now be available from the online platform, instead of bundled with Blender. The exception are add-ons which are
deemed core functionality which just happened to be written as Python add-ons.

Links:
* Original Extenesions Platform Announcement: https://code.blender.org/2022/10/blender-extensions-platform/
* Extensions website: https://extensions.blender.org/
* User Manual: https://docs.blender.org/manual/en/4.2/extensions/index.html#extensions-index
* Technical specifications: https://developer.blender.org/docs/features/extensions/
* Changes on add-ons bundling: https://devtalk.blender.org/t/changes-to-add-on-bundling-4-2-onwards/34593

------------------

This PR does the following:

* Move extensions out of experimental.
* No longer install `scripts/addons` & `scripts/addons_contrib`.
* Add `scripts/addons_core` to blender's repository.

These add-ons will still be bundled with Blender and will be always enabled in the future, with their preferences
moved to be more closely integrated with the rest of Blender. This will happen during the remaining bcon2 period.
For more details, see #121830

From scripts/addons:

* copy_global_transform.py
* hydra_storm
* io_anim_bvh
* io_curve_svg
* io_mesh_uv_layout
* io_scene_fbx
* io_scene_gltf2
* pose_library
* ui_translate
* viewport_vr_preview

Extra: bl_pkg (scripts/addons_contrib)

Note: The STL (legacy) add-on is going to be moved to the extensions platform. There is already a C++ version on core
which is enabled by default.

All the other add-ons are already available at extensions.blender.org. To use them you need to:

* Go to User Preferences > Extensions
* You will be greated with an "Online Extensions" message, click on "Enable Repository".
* Search the add-on you are looking for (e.g, Import Images as Planes).
* Click on Install

Over time their maintaince will be transferred over to the community so their development can carry on. If you used to
help maintain a bundled add-on please read: https://devtalk.blender.org/t/changes-to-add-on-bundling-4-2-onwards/34593

Ref: !121825
2024-05-15 19:26:29 +02:00
Campbell Barton
2c47937a96 Extensions: add Preferences.extensions
Accessing extensions options in preferences.filepaths didn't make so
much sense.
2024-05-15 00:52:23 +10:00
YimingWu
c324c19765 Fix #121021: Avoid size change of addon_modules during iteration
Copy modules before filtering `addon_modules` to avoid
change of dictionnary size during iterations. Otherwise errors
can be triggerd when running `python -m pytest test.py` since
it may modify the module dict.

Co-authored-by: Alexis-19 <alexis-19@noreply.localhost>
Pull Request: https://projects.blender.org/blender/blender/pulls/121100
2024-05-11 08:58:20 +02:00
Campbell Barton
3d84a1170f Extensions: ensure extensions "site-packages" precede Python's
Ensure extensions modules aren't overridden to the systems modules.
Without this, installing a system module could break an extension.
2024-05-08 21:32:16 +10:00
Campbell Barton
95fcffed4a Cleanup: remove debug print 2024-05-03 23:23:35 +10:00
Campbell Barton
0a17f4a711 Extensions: add an extensions-local site-packages
This will be used as the destination location for wheels.
Currently this is only added to the `sys.path` if it already exists.
2024-05-02 12:49:02 +10:00
Campbell Barton
5088b0154d Cleanup: replace %-formatting with str.format in scripts/modules/
The "bl_i18n_utils" module has been excluded I'm not sure how best
to run it with reasonable code coverage.
2024-04-27 16:06:51 +10:00
Campbell Barton
429959e268 UI: always report to the user when an add-ons fail to load
Failure to import the module would print a message but not show
any feedback to the user - failing silently.
2024-03-21 16:57:31 +11:00
Campbell Barton
3cb687c32c addon_utils: show a useful error when loading a module without a file
When loading an add-on without a __file__ set the "cause" was empty.

Now the modules __path__ is included (when available) which points
to the path that failed to load to help with troubleshooting.
2024-03-21 16:54:15 +11:00
Campbell Barton
16919ea5f2 Fix addon_utils.enable() error when the module has no __file__
Although this error isn't specific to extensions, extensions containing
a blender_manifest.toml but no __init__.py would import a module
with the __file__ set to None.
While there is logic to handle this case, it didn't account for modules
already in sys.modules with __file__ set to None.

From a user perspective enabling the extension silently failed raising
an error on the second attempt to enable.
2024-03-21 16:54:15 +11:00
Campbell Barton
0b13d1f31a Extensions: suppress noisy "bl_info" prints unless --debug-python is set
Ref !119521
2024-03-20 15:43:40 +11:00