Compare commits

..
6 Commits
22 changed files with 8250 additions and 2016 deletions
@@ -18,12 +18,13 @@ jobs:
python-version: 3.12
- uses: abatilo/actions-poetry@v2
- name: Install
run: |
poetry install
run: poetry install
- name: Install libgl1
run: sudo apt install -y libgl1 libegl1 libglib2.0-0 libxkbcommon0 libdbus-1-3
- name: Copy stubs
run: cp stubs/2.5.2/mobase-stubs/__init__.pyi docs/mobase.py
run: |
mkdir -p docs/src
cp -r stubs/2.5.2/mobase-stubs docs/src/mobase
- name: Build
run: poetry run sphinx-build -b html docs/source docs/build
env:
+2 -2
View File
@@ -34,7 +34,7 @@ jobs:
poetry version ${TAG#v}
poetry build
- name: Store the distribution packages
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v7
with:
name: python-package-distributions
path: stubs/setup/dist/
@@ -49,7 +49,7 @@ jobs:
steps:
- name: Download all the dists
uses: actions/download-artifact@v3
uses: actions/download-artifact@v7
with:
name: python-package-distributions
path: dist/
-1
View File
@@ -109,7 +109,6 @@ import mobase
import mobase.widgets
```
**Note:** Most classes in `mobase` cannot be instantiated, so this is mostly intended
for MO2 developers.
+329 -5
View File
@@ -3,7 +3,7 @@
version: 2
# version of the stubs - this is overridden when publishing
__version__: "2.5.2"
__version__: "2.5.3-beta10"
# This is the root of the mobase module and will contain everything
# related to functions / classes, including their documentation.
@@ -354,6 +354,66 @@ mobase:
The last extension of this entry, or an empty string if the file has no extension
or is directory.
IExecutable:
title:
returns: The title of the executable.
binaryInfo:
returns: The file info of the executable binary.
arguments:
__doc__: |
Retrieve the arguments passed to the executable.
This API might be changed in the future to return a list of strings.
returns: The arguments to be passed to the executable.
steamAppID:
returns: The Steam App ID associated with this executable, or an empty string if there is none.
workingDirectory:
returns: The working directory for the executable.
isShownOnToolbar:
returns: True if the executable is shown on the toolbar.
usesOwnIcon:
returns: True if the executable's application icon is used for desktop shortcuts.
minimizeToSystemTray:
__doc__: |
Check if Mod Organizer should minimize to the system tray while this executable
is running.
returns: True if Mod Organizer should minimize to the system tray while this executable is running.
hide:
returns: True if this executable is hidden in the user interface.
IExecutablesList:
__doc__: Interface to the list of executables configured in Mod Organizer.
executables:
__doc__: Retrieve all configured executables.
returns: A generator yielding all configured executables.
getByTitle:
__doc__: Retrieve an executable by its title.
args:
title: Title of the executable to retrieve.
returns: The executable with the specified title, or `None` if not found.
getByBinary:
__doc__: Retrieve an executable by its binary file info.
args:
info: File info of the executable binary to retrieve.
returns: The executable with the specified binary, or `None` if not found.
contains:
__doc__: Check if an executable with the specified title exists.
args:
title: Title of the executable to check.
returns: True if an executable with the specified title exists, False otherwise.
IGameFeatures:
__doc__: |
Interface for the game features, accessible through IOrganizer.gameFeatures().
@@ -495,6 +555,8 @@ mobase:
returns: True if light plugins are supported, False otherwise.
mediumPluginsAreSupported:
returns: True if medium plugins are supported, False otherwise.
blueprintPluginsAreSupported:
returns: True if blueprint plugins are supported, False otherwise.
readPluginLists:
__doc__:
args:
@@ -595,6 +657,14 @@ mobase:
file_id: ID of the file to download.
returns: An ID identifying the download.
startDownloadNexusFileForGame:
__doc__: Download a file from www.nexusmods.com.
args:
game_name: Short name of the game the mod is for.
mod_id: ID of the mod to download the file from.
file_id: ID of the file to download.
returns: An ID identifying the download.
startDownloadURLs:
__doc__: |
Download a file by url.
@@ -662,6 +732,15 @@ mobase:
root node is destroyed, it will not be possible to go up the tree, even if we still have
a valid shared pointer.
GlobPatternType:
__doc__: |
Enumeration that can defines how the pattern is parsed in IFileTree.glob.
GLOB: Glob pattern, similar to pathlib.Path.glob.
REGEX: |
Regex pattern, i.e., each pattern of the pattern (between / and \) is considered
a regex, except for ** which has the same meaning as GLOB.
InsertPolicy:
__doc__:
FAIL_IF_EXISTS: Operation will fail if the destination already exists.
@@ -803,6 +882,15 @@ mobase:
was not of the correct type.
type: IFileTree | FileTreeEntry | None
glob:
__doc__: Glob entries matching the given pattern in this tree.
args:
pattern: Glob pattern to match.
type: Type of the pattern.
returns:
__doc__: An iterator over entry of this tree matching the given pattern.
type: Iterator[FileTreeEntry]
insert:
__doc__: |
Insert the given entry in this tree, removing it from its
@@ -925,7 +1013,7 @@ mobase:
filter: Predicate that should return true for entries to delete.
returns: The number of deleted entry.
walk:
walk.1:
__doc__: |
Walk this tree, calling the given function for each entry in it.
@@ -936,6 +1024,53 @@ mobase:
callback: Method to call for each entry in the tree.
sep: Type of separator to use to construct the path.
walk.2:
__doc__: |
Walk this tree and return the entries in it.
During the walk, parent tree are guaranteed to be visited before their children.
The current tree is not included in the return generator.
returns:
__doc__: An iterator over entry of this tree.
type: Iterator[FileTreeEntry]
IInstance:
__doc__: Represents a Mod Organizer instance, either global or portable.
displayName:
returns: The instance name; this is the directory name or "Portable" for portable instances.
gameName:
returns: The name of the game managed by this instance, or an empty string if the INI file could not be read.
gameDirectory:
returns: The directory where the game is installed, or an empty string if the INI file could not be read.
isPortable:
returns: True if this is a portable instance, False if it is a global one.
IInstanceManager:
__doc__: Interface to the instance manager of Mod Organizer.
currentInstance:
returns: The current instance.
globalInstancePaths:
__doc__: |
Retrieve the list of absolute paths to all global instances.
This does not include portable instances.
returns: The list of absolute paths to all global instances.
getGlobalInstance:
__doc__: Retrieve the global instance corresponding to the given name.
args:
instanceName: |
Name of the global instance to retrieve. This is the directory
name of the instance.
returns: The global instance corresponding to the given name, or `None` if no such instance exists.
IInstallationManager:
__doc__:
@@ -1001,6 +1136,9 @@ mobase:
absolutePath:
returns: Absolute path to the mod to be used in file system operations.
author:
returns: The author of this mode.
isBackup:
returns: True if this mod represents a backup.
@@ -1074,6 +1212,12 @@ mobase:
color:
returns: The color of the 'Notes' column chosen by the user.
uploader:
returns: The uploader of this mod.
uploaderUrl:
returns: The URL of the uploader of this mod.
url:
returns: |
The URL of this mod, or an empty QString() if no URL is associated
@@ -1554,9 +1698,6 @@ mobase:
getPluginDataPath:
returns: The directory for plugin data, typically plugins/data.
appVersion:
returns: The running version of Mod Organizer.
basePath:
returns: The absolute path to the base directory of Mod Organizer.
@@ -1582,6 +1723,9 @@ mobase:
downloadsPath:
returns: The absolute path to the download directory.
executablesList:
returns: The interface to list of executables.
findFileInfos:
__doc__: Find files in the virtual directory matching the specified filter.
args:
@@ -1629,6 +1773,12 @@ mobase:
name: Name of the game (short name).
returns: The plugin for the given game, or `None` if none was found.
getProfile:
__doc__: Retrieve a profile by name.
args:
name: Name of the profile.
returns: The profile with the specified name or None if no such profile exists.
installMod:
__doc__: Install a mod archive at the specified location.
args:
@@ -1636,6 +1786,17 @@ mobase:
name_suggestion: Suggested name for this mod. This can still be changed by the user.
returns: An interface to the new installed mod, or `None` if no installation took place (canceled or failure).
instanceManager:
returns: The interface to the instance manager.
instanceName:
__doc__: |
Retrieve the name of the current instance.
For global instance, this corresponds to the directory name, for portable
instance this always returns "Portable".
returns: The name of the current instance.
isPluginEnabled.1:
__doc__: Check if a plugin is enabled.
args:
@@ -1851,6 +2012,9 @@ mobase:
profileName:
returns: The name of the current profile, or an empty string if no profile has been loaded (yet).
profileNames:
returns: The names of all existing profiles.
profilePath:
returns: The absolute path to the active profile or an empty string if no profile has been loaded (yet).
@@ -1912,6 +2076,10 @@ mobase:
ignoreCustomOverwrite: Set to true to ignore the profile's configured custom overwrite.
returns: The handle to the started application, or 0 if the application failed to start.
version:
__doc__: Retrieve the running version of MO2.
returns: The running version of MO2.
virtualFileTree:
__doc__: Retrieve a IFileTree object representing the virtual file tree.
returns: An IFileTree representing the virtual file tree.
@@ -1932,6 +2100,8 @@ mobase:
completed successfully, and `exitcode` is the exit code of the application.
# IOrganizer has a bunch of deprecated functions:
appVersion:
deprecated: true
getMod:
deprecated: true
removeMod:
@@ -2129,6 +2299,9 @@ mobase:
binaryName:
returns: The name of the default executable to run (relative to the game folder).
blueprintPrefix:
returns: The blueprint plugin prefix for blueprint auto loading.
dataDirectory:
returns: The path to the directory containing data (absolute path).
@@ -2184,6 +2357,11 @@ mobase:
The name of the launcher executable to run (relative to the game folder), or an
empty string if there is no launcher.
getModMappings:
abstract: false
__doc__: Gets a virtualization mapping for mod directories.
returns:
getSupportURL:
returns: An URL for the support page of this game.
@@ -2230,6 +2408,11 @@ mobase:
returns: |
The game name to use when calling LOOT from MO2, default to gameShortName().
modDataDirectory:
__doc__:
abstract: False
returns:
nexusGameID:
__doc__: |
Retrieve the Nexus game ID for this game.
@@ -2477,6 +2660,42 @@ mobase:
IPluginList:
__doc__: Primary interface to the list of plugins.
author:
__doc__: Retrieve the author of the plugin.
args:
name: Filename of the plugin (without path but with file extension).
returns: The author of the plugin or an empty string if the plugin does not exist.
description:
__doc__: Retrieve the description of the plugin.
args:
name: Filename of the plugin (without path but with file extension).
returns: The description of the plugin or an empty string if the plugin does not exist.
formVersion:
__doc__: Retrieve the form version of the plugin.
args:
name: Filename of the plugin (without path but with file extension).
returns: The form version of the plugin or -1 if the plugin does not exist.
headerVersion:
__doc__: Retrieve the header version of the plugin.
args:
name: Filename of the plugin (without path but with file extension).
returns: The header version of the plugin or -1 if the plugin does not exist.
isBlueprintFlagged:
__doc__: |
Determine if a plugin is flagged as blueprint.
Blueprint plugins were added in Starfield and are plugins that are hidden in
the Creation Kit and removed from plugins.txt on game launch.
args:
name: Filename of the plugin (without path but with file extension).
returns: |
True if the given plugin is a blueprint plugin, False otherwise or if the
file does not exist.
isMaster:
deprecated: True
__doc__: |
@@ -3095,6 +3314,9 @@ mobase:
ModRepositoryFileInfo:
__doc__:
properties[]:
author:
type: str
desc:
categoryID:
type: int
desc:
@@ -3134,6 +3356,12 @@ mobase:
repository:
type: str
desc:
uploader:
type: str
desc:
uploaderUrl:
type: str
desc:
uri:
type: str
desc:
@@ -3281,6 +3509,102 @@ mobase:
mod_name: Internal name of the mod.
returns: The secondary files (absolute paths) for the request mod.
Version:
__doc__: |
Class representing a version objects.
Valid versions are an "extension" of SemVer (see https://semver.org/) with the
following tweaks:
- version can have a sub-patch, i.e., x.y.z.p, which are normally not allowed by
SemVer,
- non-integer pre-release identifiers are limited to dev, alpha (a), beta (b) and rc,
and dev is lower than alpha (according to SemVer, the pre-release should be
ordered alphabetically),
- the '-' between version and pre-release can be made optional, and also the '.'
between pre-releases segment.
The extension from SemVer are only meant to be used by MO2 and USVFS versioning,
plugins and extensions should follow SemVer standard (and not use dev), this is
mainly
- for back-compatibility purposes, because USVFS versioning contains sub-patches and
there are old MO2 releases with sub-patch,
- because MO2 is not going to become MO3, so having an extra level make sense.
Unlike VersionInfo, this class is immutable and only hold valid versions.
ParseMode:
__doc__: Enumeration defining how to parse version from string.
SEMVER: Official semver parsing with pre-release limited to dev, alpha/a, beta/b and rc.
MO2: |
MO2 parsing, e.g., 2.5.1rc1 - this either parse a string with no pre-release
information (e.g. 2.5.1) or with a single pre-release + a version (e.g., 2.5.1a1
or 2.5.2rc1).
This mode can parse sub-patch (SemVer mode cannot).
FormatMode:
__doc__: Enumeration defining how to format version into string.
FORCE_SUBPATCH: Show sub-patch even if sub-patch is 0.
NO_SEPARATOR: |
Do not add separators between version and pre-release (-) or between pre-release
segments (.).
SHORT_ALPHA_BETA: Use short form for alpha and beta (a/b instead of alpha/beta).
NO_METADATA: Do not add metadata even if present.
CONDENSED: Condensed format, combination of NO_SEPARATOR, SHORT_ALPHA_BETA and NO_METADATA.
ReleaseType:
__doc__: Enumeration representing the release type of a version.
DEVELOPMENT:
ALPHA:
BETA:
RELEASE_CANDIDATE:
properties[]:
major:
type: int
desc: The major component of this version.
minor:
type: int
desc: The minor component of this version.
patch:
type: int
desc: The patch component of this version.
subpatch:
type: int
desc: The sub-patch component of this version.
prereleases:
type: list[int | ReleaseType]
desc: The pre-release components of this version.
build_metadata:
type: str
desc: The build-metadata component of this version, or an empty string.
isPreRelease:
__doc__: Check if this version represents a pre-release version.
returns: True if this version is a pre-release version, False otherwise.
parse:
__doc__: |
Parse version from the given string, throw InvalidVersionException if the
string cannot be parsed.
static: True
args:
value: Value to parse.
mode: Mode to use when parsing, see ParseMode for more details.
returns: The parsed version.
string:
__doc__: Convert this version to a string.
args:
mode: Combination of modes to use creating the string, see FormatMode.
returns: A string representing this version according to the given modes.
VersionInfo:
__doc__: Represents the version of a mod or plugin.
-4
View File
@@ -1,4 +0,0 @@
sphinx-rtd-theme
sphinx-autodoc-typehints
sphinx-automodapi
PyQt6
+5 -1
View File
@@ -27,8 +27,9 @@ extensions = [
"sphinx.ext.autodoc",
"sphinx_autodoc_typehints",
"sphinx.ext.napoleon",
"autoapi.extension",
# "sphinx.ext.autosummary",
"sphinx_automodapi.automodapi",
# "sphinx_automodapi.automodapi",
]
# Add any paths that contain templates here, relative to this directory.
@@ -39,6 +40,9 @@ templates_path = ["_templates"]
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []
autoapi_dirs = ["../src"]
autoapi_member_order = "groupwise"
# -- Options for HTML output -------------------------------------------------
-1
View File
@@ -18,7 +18,6 @@ This documentation is dedicated to writting MO2 **Python** plugins.
plugin-types
writing-plugins
faq
mobase
-11
View File
@@ -1,11 +0,0 @@
``mobase`` API
==============
.. currentmodule:: mobase
.. automodapi:: mobase
:no-inheritance-diagram:
:no-heading:
.. toctree::
:maxdepth: 4
-7
View File
@@ -1,7 +0,0 @@
mobase
======
.. toctree::
:maxdepth: 4
mobase
+3 -5
View File
@@ -64,10 +64,8 @@ These plugins (shall eventually) implement all the game specific features and fu
able to add support for further games.
The plugin is also responsible to help MO determine if (and where) the game is installed in the first place.
Since supporting a game properly requires extensions in many places of the UI.
To allow this without creating one huge plugin interface that involves every aspect of MO, game plugins
expose a *feature list*.
The list of possible features can be found in the "game_features" project and each feature can itself be
considered a plugin interface.
To allow this without creating one huge plugin interface that involves every aspect of MO,
game plugins can register only the features they need to MO2 using :meth:`registerFeature<mobase.IGameFeatures.registerFeature>`
As an example for a game feature take BSA invalidation: If the game requires BSA invalidation it will implement
this feature.
@@ -147,4 +145,4 @@ File Mappings
This interface allows plugins to add virtual file (or directory) links to the virtual file system in addition to the
mod files.
Profile-local save games, ini-files and load-orders are all implemented this way in MO2.
Profile-local save games, ini-files and load-orders are all implemented this way in MO2.
Generated
+481 -376
View File
File diff suppressed because it is too large Load Diff
+26 -23
View File
@@ -1,36 +1,39 @@
[tool.poetry]
[project]
name = "mo2-pystubs-generation"
version = "0.1.0"
description = ""
authors = ["Holt59 <capelle.mikael@gmail.com>"]
license = "MIT"
version = "0.1.0"
readme = "README.md"
packages = [{ include = "mo2", from = "src" }]
authors = [{ name = "Holt59", email = "capelle.mikael@gmail.com" }]
requires-python = ">=3.12,<4.0"
dependencies = [
"pyqt6 (==6.11.0)",
"pyyaml (>=6.0.3,<7.0.0)",
"typing-extensions (>=4.15.0,<5.0.0)",
]
[tool.poetry.scripts]
[project.scripts]
mo2-stubs-generator = "mo2.stubs.generator.__main__:main"
[tool.poetry.dependencies]
python = "^3.12"
pyqt6 = "6.7.1"
pyyaml = "^6.0.1"
typing-extensions = "^4.12.2"
[build-system]
requires = ['poetry-core (>=2.0,<3.0)']
build-backend = "poetry.core.masonry.api"
[tool.poetry]
packages = [{ include = "mo2", from = "src" }]
[tool.poetry.group.dev.dependencies]
pyright = "^1.1.374"
ruff = "^0.5.5"
types-pyyaml = "^6.0.12.20240724"
poethepoet = "^0.27.0"
pyright = "^1.1.409"
ruff = "^0.15.12"
types-pyyaml = "^6.0.12.20260508"
poethepoet = "^0.45.0"
[tool.poetry.group.doc.dependencies]
sphinx-rtd-theme = "^2.0.0"
sphinx-autodoc-typehints = "^2.2.3"
sphinx-automodapi = "^0.17.0"
sphinx = "<8"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
sphinx-rtd-theme = "^3.0.2"
sphinx-autodoc-typehints = "^3.2.0"
sphinx-automodapi = "^0.20.0"
sphinx = "^8.2.3"
sphinx-autoapi = "^3.6.0"
[tool.poe.tasks]
format-imports = "ruff check --select I src --fix"
@@ -43,7 +46,7 @@ lint.sequence = ["lint-ruff", "lint-ruff-format", "lint-pyright"]
lint.ignore_fail = "return_non_zero"
[tool.ruff]
target-version = "py310"
target-version = "py312"
[tool.ruff.lint]
extend-select = ["B", "Q", "I"]
+22 -10
View File
@@ -8,19 +8,19 @@ from pathlib import Path
from typing import Callable
from .loader import load_mobase
from .mtypes import Class, Constant, PyTyping
from .mtypes import Class, Constant, Enum, Function, PyTyping
from .parser import is_enum
from .register import MobaseRegister
from .utils import Settings, clean_class
from .writer import Writer, is_list_of_functions
from .writer import Writer, is_list_of
LOGGER = logging.getLogger(__package__)
def extract_objects(
module: object, skips: Sequence[str] = []
) -> list[tuple[str, type]]:
objects: list[tuple[str, type]] = []
) -> list[tuple[str, object]]:
objects: list[tuple[str, object]] = []
assert hasattr(module, "__name__")
module_name: str = module.__name__ # type: ignore
@@ -140,7 +140,7 @@ def main() -> None:
}
# list of objects directly in mobase
module_objects: dict[str, list[tuple[str, type]]] = {
module_objects: dict[str, list[tuple[str, object]]] = {
"mobase": extract_objects(
mobase,
[
@@ -181,7 +181,7 @@ def main() -> None:
elif isinstance(c, (PyTyping, Constant)):
...
elif is_list_of_functions(c):
elif is_list_of(c, Function):
settings.patch_functions(c)
else:
@@ -198,6 +198,21 @@ def main() -> None:
# create directory if required
output_folder.mkdir(parents=True, exist_ok=True)
# sort the stubs
def _key_fn(o: Class | Constant | list[Function] | PyTyping) -> tuple[int, ...]:
# order is PyTyping -> Constant -> Function -> Enum -> Top-Level Class -> Child Level Classes
return (
not isinstance(o, PyTyping),
not isinstance(o, Constant),
not isinstance(o, list),
not isinstance(o, Enum),
isinstance(o, Class) and len(o.all_bases),
)
stub_objects = sorted(
(register.get_object(n) for n, _o in objects), key=_key_fn
)
# write everything
with open(output_folder.joinpath("__init__.pyi"), "w") as output:
writer = Writer(package=name, output=output, settings=settings)
@@ -208,10 +223,7 @@ def main() -> None:
module_headers[name](writer)
for n, _o in objects:
# Get the corresponding object:
c = register.get_object(n)
for c in stub_objects:
writer.print_object(c)
subprocess.run(
+15 -12
View File
@@ -4,7 +4,7 @@ import re
import types
from collections import OrderedDict, defaultdict
from itertools import chain
from typing import Any, Iterable, cast
from typing import Any, Callable, Iterable, cast
from .mtypes import (
Argument,
@@ -118,7 +118,7 @@ def parse_python_signature(s: str, name: str) -> tuple[PyType, list[Argument]]:
return PyType(return_type), arguments
def is_enum(e: type) -> bool:
def is_enum(e: object) -> bool:
"""Check if the given class is an enumeration.
Args:
@@ -144,17 +144,18 @@ class Overload:
self.arguments = arguments
def parse_pybind11_function_docstring(e: type) -> list[Overload]:
def parse_pybind11_function_docstring(name: str, doc: str | None) -> list[Overload]:
"""
Parse the docstring of the given element.
Parse the docstring of a Pybind11 function.
Args:
e: The function to "parse".
name: Name of the function.
doc: The docstring of the function generated by Pybind11.
Returns:
A list of overloads for the given function.
"""
lines = (e.__doc__ or "").strip().split("\n")
lines = (doc or "").strip().split("\n")
signatures: list[str]
if len(lines) == 1:
@@ -162,7 +163,7 @@ def parse_pybind11_function_docstring(e: type) -> list[Overload]:
else:
signatures = []
for line in lines:
m = re.match(rf"^[0-9]+[.]\s+({e.__name__}.*)$", line)
m = re.match(rf"^[0-9]+[.]\s+({name}.*)$", line)
if m:
signatures.append(m.group(1).strip())
@@ -174,16 +175,16 @@ def parse_pybind11_function_docstring(e: type) -> list[Overload]:
signature = signature.replace("MOBase::", "mobase.").replace("::", ".")
try:
return_type, arguments = parse_python_signature(signature, e.__name__)
return_type, arguments = parse_python_signature(signature, name)
except ValueError as err:
raise ValueError(f"invalid signature: {e.__name__}, {e.__doc__}") from err
raise ValueError(f"invalid signature: {name}, {doc}") from err
overloads.append(Overload(return_type=return_type, arguments=arguments))
return overloads
def make_functions(e: type) -> list[Function]:
overloads = parse_pybind11_function_docstring(e)
def make_functions(e: Callable[..., Any]) -> list[Function]:
overloads = parse_pybind11_function_docstring(e.__name__, e.__doc__)
return [
Function(
@@ -295,7 +296,9 @@ def make_class(e: type, register: MobaseRegister) -> Class:
# otherwise we parse the docstring
else:
overloads = parse_pybind11_function_docstring(method)
overloads = parse_pybind11_function_docstring(
method.__name__, method.__doc__
)
for overload in overloads:
args = overload.arguments
+4 -4
View File
@@ -15,14 +15,14 @@ class MobaseRegister:
objects: dict[str, Class | Constant | list[Function] | PyTyping]
def __init__(self) -> None:
self.raw_objects: dict[str, type] = OrderedDict()
self.raw_objects: dict[str, object] = OrderedDict()
self.objects = {}
def add_object(self, name: str, object: type) -> None:
self.raw_objects[name] = object
def add_object(self, n: str, o: object, /) -> None:
self.raw_objects[n] = o
def make_object(
self, name: str, e: type | None = None
self, name: str, e: object | None = None
) -> Class | list[Function] | Constant | PyTyping:
"""
Construct a Function, Class, Constant or Enum for the given object.
+9 -9
View File
@@ -215,7 +215,7 @@ class Settings:
# Check the args:
if function_settings.args is not None:
if len(function_settings.args) != len(fn.args):
LOGGER.warn(
LOGGER.warning(
f"Mismatch number of arguments for function "
f"mobase.{setting_name}."
)
@@ -243,7 +243,7 @@ class Settings:
fn.deprecated = function_settings.deprecated
else:
LOGGER.warn(
LOGGER.warning(
"Missing settings for function mobase.{}.".format(setting_name)
)
@@ -268,7 +268,7 @@ class Settings:
class_settings = self._get_class_settings(cls.canonical_name)
if class_settings is None:
LOGGER.warn("Class {} not found in settings.".format(cls.canonical_name))
LOGGER.warning("Class {} not found in settings.".format(cls.canonical_name))
return
if "__doc__" in class_settings and class_settings["__doc__"] is not None:
@@ -306,7 +306,7 @@ class Settings:
if "type" in settings_property:
prop.type = PyType(settings_property["type"])
else:
LOGGER.warn(
LOGGER.warning(
"Missing type for property {}.{}.".format(
cls.canonical_name, prop.name
)
@@ -320,7 +320,7 @@ class Settings:
prop.doc = settings_property["desc"]
else:
LOGGER.warn(
LOGGER.warning(
"Missing description for property {}.{}.".format(
cls.canonical_name, prop.name
)
@@ -366,7 +366,7 @@ class Settings:
if function_settings.args is not None:
method_arguments = m.args if m.is_static() else m.args[1:]
if len(function_settings.args) != len(method_arguments):
LOGGER.warn(
LOGGER.warning(
"Mismatch number of arguments for method {}.{}.".format(
cls.canonical_name, settings_name
)
@@ -380,7 +380,7 @@ class Settings:
not method_arg.name.startswith("arg")
and method_arg.name != settings_arg.name
):
LOGGER.warn(
LOGGER.warning(
(
"Mismatch argument name for method {}.{}: "
"{} {}, using {}."
@@ -429,7 +429,7 @@ class Settings:
if n_overloads > 0 and missing_settings:
for settings_name in missing_settings:
LOGGER.warn(
LOGGER.warning(
"Missing settings for method {}.{}.".format(
cls.canonical_name, settings_name
)
@@ -447,7 +447,7 @@ class Settings:
# Print items missing in mobase
missing_items = [k for k, v in keys.items() if not v]
if missing_items:
LOGGER.warn(
LOGGER.warning(
"The following members were found in settings but not in the actual"
" class {}: {}.".format(cls.canonical_name, ", ".join(missing_items))
)
+8 -6
View File
@@ -1,5 +1,5 @@
import logging
from typing import Any, Iterable, TextIO
from typing import Any, TextIO
from typing_extensions import TypeIs
@@ -9,10 +9,12 @@ from .utils import Settings
LOGGER = logging.getLogger(__package__)
def is_list_of_functions(e: Any | Iterable[Any]) -> TypeIs[list[Function]]:
if not isinstance(e, list):
return False
return all(isinstance(x, Function) for x in e)
def is_list_of_any(e: Any) -> TypeIs[list[Any]]:
return isinstance(e, list)
def is_list_of[T](e: Any, t: type[T]) -> TypeIs[list[T]]:
return is_list_of_any(e) and all(isinstance(x, t) for x in e)
class Writer:
@@ -270,7 +272,7 @@ class Writer:
if isinstance(e, Class):
self.print_class(e)
elif is_list_of_functions(e):
elif is_list_of(e, Function):
for fn in e:
self.print_function(fn)
File diff suppressed because it is too large Load Diff
+23 -10
View File
@@ -13,7 +13,17 @@ class TaskDialog:
Customizable choice dialog.
"""
def __init__(self: TaskDialog, parent: PyQt6.QtWidgets.QWidget | None = None, title: str = '', main: str = '', content: str = '', details: str = '', icon: PyQt6.QtWidgets.QMessageBox.Icon = PyQt6.QtWidgets.QMessageBox.Icon.NoIcon, buttons: list[TaskDialogButton] = [], remember: Union[str, tuple[str, str]] = '') -> None:
def __init__(
self: TaskDialog,
parent: PyQt6.QtWidgets.QWidget | None = None,
title: str = "",
main: str = "",
content: str = "",
details: str = "",
icon: PyQt6.QtWidgets.QMessageBox.Icon = PyQt6.QtWidgets.QMessageBox.Icon.NoIcon,
buttons: list[TaskDialogButton] = [],
remember: Union[str, tuple[str, str]] = "",
) -> None:
"""
Construct a new TaskDialog.
@@ -91,7 +101,7 @@ class TaskDialog:
main: Main message of the dialog.
"""
...
def setRemember(self: TaskDialog, action: str, file: str = '') -> TaskDialog:
def setRemember(self: TaskDialog, action: str, file: str = "") -> TaskDialog:
"""
Configure the dialog to remember user-choice.
"""
@@ -113,7 +123,6 @@ class TaskDialog:
"""
...
class TaskDialogButton:
"""
Special button to be used inside TaskDialog widgets.
@@ -123,19 +132,21 @@ class TaskDialogButton:
def button(self) -> PyQt6.QtWidgets.QMessageBox.StandardButton: ...
@button.setter
def button(self, arg0: PyQt6.QtWidgets.QMessageBox.StandardButton) -> None: ...
@property
def description(self) -> str: ...
@description.setter
def description(self, arg0: str) -> None: ...
@property
def text(self) -> str: ...
@text.setter
def text(self, arg0: str) -> None: ...
@overload
def __init__(self: TaskDialogButton, text: str, description: str, button: PyQt6.QtWidgets.QMessageBox.StandardButton) -> None:
def __init__(
self: TaskDialogButton,
text: str,
description: str,
button: PyQt6.QtWidgets.QMessageBox.StandardButton,
) -> None:
"""
Create a TaskDialogButton.
@@ -146,7 +157,11 @@ class TaskDialogButton:
"""
...
@overload
def __init__(self: TaskDialogButton, text: str, button: PyQt6.QtWidgets.QMessageBox.StandardButton) -> None:
def __init__(
self: TaskDialogButton,
text: str,
button: PyQt6.QtWidgets.QMessageBox.StandardButton,
) -> None:
"""
Create a TaskDialogButton without description.
@@ -155,5 +170,3 @@ class TaskDialogButton:
button: Value returned by TaskDialog.exec() if this button is clicked.
"""
...
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More