Compare commits

..
8 Commits
15 changed files with 9786 additions and 231 deletions
+2 -2
View File
@@ -15,7 +15,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.11
python-version: 3.12
- uses: abatilo/actions-poetry@v2
- name: Install
run: |
@@ -23,7 +23,7 @@ jobs:
- 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.0/mobase-stubs/__init__.pyi docs/mobase.py
run: cp stubs/2.5.2/mobase-stubs/__init__.pyi docs/mobase.py
- name: Build
run: poetry run sphinx-build -b html docs/source docs/build
env:
+1 -1
View File
@@ -10,7 +10,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.11
python-version: 3.12
- uses: abatilo/actions-poetry@v2
- name: Install
run: |
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
replace-with: "$1"
- uses: actions/setup-python@v2
with:
python-version: 3.11
python-version: 3.12
- uses: abatilo/actions-poetry@v2
- name: Build
run: |
+22 -24
View File
@@ -3,12 +3,11 @@
version: 2
# version of the stubs - this is overridden when publishing
__version__: "2.5.0"
__version__: "2.5.2"
# This is the root of the mobase module and will contain everything
# related to functions / classes, including their documentation.
mobase:
getFileVersion:
__doc__: Retrieve the file version of the given executable.
args:
@@ -302,7 +301,7 @@ mobase:
hasSuffix.2:
__doc__: Check if this entry has the given suffix.
args:
suffix: Suffix to check.
suffix: Suffix to check.
returns: True if this entry is a file and has the given suffix.
isDir:
@@ -487,9 +486,6 @@ mobase:
returns: The number of unregistered features.
GamePlugins:
__abstract__: true
getLoadOrder:
@@ -497,8 +493,8 @@ mobase:
returns:
lightPluginsAreSupported:
returns: True if light plugins are supported, False otherwise.
overridePluginsAreSupported:
returns: True if override plugins are supported, False otherwise.
mediumPluginsAreSupported:
returns: True if medium plugins are supported, False otherwise.
readPluginLists:
__doc__:
args:
@@ -582,7 +578,6 @@ mobase:
returns: The list of variants for this GuessedString.
IDownloadManager:
downloadPath:
__doc__: Retrieve the (absolute) path of the specified download.
args:
@@ -740,7 +735,7 @@ mobase:
given path.
args:
path: Path to the file to create.
replace_if_exists: |
replace_if_exists: |
If True and an entry already exists at the given location, it will be replaced by
a new entry. This will replace both files and directories.
returns: A FileTreeEntry corresponding to the created file.
@@ -1003,7 +998,6 @@ mobase:
returns: The result of the installation.
IModInterface:
absolutePath:
returns: Absolute path to the mod to be used in file system operations.
@@ -1339,7 +1333,6 @@ mobase:
returns: The state of the given mod.
IModRepositoryBridge:
__bases__:
- PyQt6.QtCore.QObject
@@ -2482,7 +2475,6 @@ mobase:
installation did not succeed.
IPluginList:
__doc__: Primary interface to the list of plugins.
isMaster:
@@ -2527,10 +2519,9 @@ mobase:
True if the given file plugin contains no records, False if it does OR if the
file does not exist.
isLightFlagged:
__doc__: |
Determine if a plugin is flagged as light
Determine if a plugin is flagged as light.
In gamebryo games, a master file will usually have a .esl file extension but
technically an esp can be flagged as light.
@@ -2540,16 +2531,16 @@ mobase:
True if the given plugin is a light plugin, False otherwise or if the
file does not exist.
isOverlayFlagged:
isMediumFlagged:
__doc__: |
Determine if a plugin is flagged as overlay
Determine if a plugin is flagged as medium.
This plugin flag was added in Starfield and signifies plugin records that
update existing records
args:
name: Filename of the plugin (without path but with file extension).
returns: |
True if the given plugin is an overlay plugin, False otherwise or if the
True if the given plugin is a medium plugin, False otherwise or if the
file does not exist.
hasLightExtension:
@@ -2662,7 +2653,6 @@ mobase:
returns: The state of the plugin.
IPluginModPage:
_parentWidget:
abstract: false
returns: The parent widget.
@@ -2708,15 +2698,27 @@ mobase:
by qt are implemented (including dds) but no audio files and no 3d mesh formats.
genFilePreview:
__doc__: Generate a preview for the specified file.
__doc__: Generate a preview widget for the specified file.
args:
filename: Path to the file to preview.
max_size: Maximum size of the generated widget.
returns: The widget showing a preview of the file.
genDataPreview:
__doc__: Generate a preview widget from in-memory data.
args:
file_data: In-memory data to preview.
filename: Name of the file the data comes from.
max_size: Maximum size of the generated widget.
returns: The widget showing a preview of the in-memory data.
supportedExtensions:
returns: The list of file extensions that are supported by this preview plugin.
supportsArchives:
__doc__: Check if this preview plugin supports preview from in-memory data.
returns: True if the plugin supports preview from raw data, False otherwise.
IPluginRequirement:
__doc__: Class representing requirements for plugins.
@@ -2799,7 +2801,6 @@ mobase:
plugin: The name of the plugin that must be enabled.
returns: The constructed requirement.
IPluginTool:
__doc__: |
This is the simplest of plugin interfaces. Such plugins simply place an icon inside the tools sub-menu
@@ -2927,7 +2928,6 @@ mobase:
returns:
Mapping:
__init__.1:
__doc__: Creates an empty Mapping.
@@ -3348,7 +3348,6 @@ mobase:
returns: The version scheme in effect for this VersionInfo.
mobase.widgets:
TaskDialog:
__doc__: Customizable choice dialog.
@@ -3437,7 +3436,6 @@ mobase.widgets:
args:
width: Width of the dialog.
TaskDialogButton:
__doc__: Special button to be used inside TaskDialog widgets.
Generated
+190 -172
View File
File diff suppressed because it is too large Load Diff
+9 -11
View File
@@ -12,20 +12,21 @@ mo2-stubs-generator = "mo2.stubs.generator.__main__:main"
[tool.poetry.dependencies]
python = "^3.12"
pyqt6 = "^6.7.0"
pyqt6 = "6.7.1"
pyyaml = "^6.0.1"
typing-extensions = "^4.12.2"
[tool.poetry.group.dev.dependencies]
pyright = "^1.1.365"
ruff = "^0.4.7"
types-pyyaml = "^6.0.12.20240311"
poethepoet = "^0.26.1"
pyright = "^1.1.374"
ruff = "^0.5.5"
types-pyyaml = "^6.0.12.20240724"
poethepoet = "^0.27.0"
[tool.poetry.group.doc.dependencies]
sphinx-rtd-theme = "^2.0.0"
sphinx-autodoc-typehints = "^2.1.0"
sphinx-automodapi = "^0.16.0"
sphinx = "^7.3.7"
sphinx-autodoc-typehints = "^2.2.3"
sphinx-automodapi = "^0.17.0"
sphinx = "<8"
[build-system]
requires = ["poetry-core"]
@@ -47,9 +48,6 @@ target-version = "py310"
[tool.ruff.lint]
extend-select = ["B", "Q", "I"]
[tool.ruff.lint.isort]
known-first-party = ['tas']
[tool.pyright]
typeCheckingMode = "strict"
reportMissingTypeStubs = true
+4 -4
View File
@@ -8,7 +8,7 @@ from pathlib import Path
from typing import Callable
from .loader import load_mobase
from .mtypes import Class, PyTyping
from .mtypes import Class, Constant, PyTyping
from .parser import is_enum
from .register import MobaseRegister
from .utils import Settings, clean_class
@@ -178,7 +178,7 @@ def main() -> None:
# Path the class using the configuration:
settings.patch_class(c)
elif isinstance(c, PyTyping):
elif isinstance(c, (PyTyping, Constant)):
...
elif is_list_of_functions(c):
@@ -217,16 +217,16 @@ def main() -> None:
subprocess.run(
[
"ruff",
"--silent",
"format",
"--silent",
output_folder.joinpath("__init__.pyi").as_posix(),
]
)
subprocess.run(
[
"ruff",
"--silent",
"check",
"--silent",
"--select",
"I",
"--fix",
+7 -7
View File
@@ -4,7 +4,7 @@ from __future__ import annotations
from collections import OrderedDict
from .mtypes import Class, Function, PyTyping
from .mtypes import Class, Constant, Function, PyType, PyTyping
class MobaseRegister:
@@ -12,7 +12,7 @@ class MobaseRegister:
Class that register classes.
"""
objects: dict[str, Class | list[Function] | PyTyping]
objects: dict[str, Class | Constant | list[Function] | PyTyping]
def __init__(self) -> None:
self.raw_objects: dict[str, type] = OrderedDict()
@@ -23,9 +23,9 @@ class MobaseRegister:
def make_object(
self, name: str, e: type | None = None
) -> Class | list[Function] | PyTyping:
) -> Class | list[Function] | Constant | PyTyping:
"""
Construct a Function, Class or Enum for the given object.
Construct a Function, Class, Constant or Enum for the given object.
Args:
name: The name of the object to inspect.
@@ -47,14 +47,14 @@ class MobaseRegister:
self.objects[name] = make_class(e, self)
elif callable(e):
self.objects[name] = make_functions(e)
# typing stuff
elif type(e).__module__ == "types" or type(e).__module__ == "typing":
self.objects[name] = PyTyping(name, e)
else:
self.objects[name] = Constant(name, type=PyType(type(e)), value=e)
return self.objects[name]
def get_object(self, name: str) -> Class | list[Function] | PyTyping:
def get_object(self, name: str) -> Class | Constant | list[Function] | PyTyping:
"""
Retrieve the object if the given name. Fails if no object with this
name exists (if `make_object(name, ...)` has never been called).
+17 -4
View File
@@ -1,13 +1,15 @@
import logging
from typing import Any, Iterable, TextIO, TypeGuard
from typing import Any, Iterable, TextIO
from .mtypes import Class, Enum, Function, Method, Property, PyTyping
from typing_extensions import TypeIs
from .mtypes import Class, Constant, Enum, Function, Method, Property, PyTyping
from .utils import Settings
LOGGER = logging.getLogger(__package__)
def is_list_of_functions(e: Any | Iterable[Any]) -> TypeGuard[list[Function]]:
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)
@@ -256,7 +258,15 @@ class Writer:
def print_typing(self, typ: PyTyping):
self._print(f"{typ.name} = {typ.typing}")
def print_object(self, e: object):
def print_constent(self, constant: Constant):
assert constant.type is not None
self._print(
"{}: {} = ...".format(
constant.name, self._fix_typing(constant.type.typing())
)
)
def print_object(self, e: Class | Constant | list[Function] | PyTyping):
if isinstance(e, Class):
self.print_class(e)
@@ -266,3 +276,6 @@ class Writer:
elif isinstance(e, PyTyping):
self.print_typing(e)
else:
self.print_constent(e)
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,159 @@
from __future__ import annotations
__version__ = "2.5.1"
from typing import List, Tuple, Union, overload
import PyQt6.QtCore
import PyQt6.QtGui
import PyQt6.QtWidgets
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:
"""
Construct a new TaskDialog.
Args:
parent: Parent widget of the dialog.
title: Title of the dialog.
main: Header of the dialog (big text at the top).
content: Main message of the dialog (text below main).
details: Details for the dialog, initially collapsed (bottom of the dialog).
icon: Icon for the dialog.
buttons: List of buttons for the dialog.
remember: Remember the choice for this dialog.
"""
...
def addButton(self: TaskDialog, button: TaskDialogButton) -> TaskDialog:
"""
Add a custom button to this TaskDialog.
Args:
button: Button to add to the dialog.
"""
...
def addContent(self: TaskDialog, widget: PyQt6.QtWidgets.QWidget) -> None:
"""
Add a custom widget content to this TaskDialog. Widget content are put between
content and buttons (above buttons).
Args:
widget: Widget to add.
"""
...
def exec(self: TaskDialog) -> PyQt6.QtWidgets.QMessageBox.StandardButton:
"""
Display this dialog and wait for user-interaction to return. This is a blocking
function.
Returns:
The button clicked by the user. Without custom buttons, this return Ok,
otherwise it returns the button set in the TaskDialogButton.
"""
...
def setContent(self: TaskDialog, content: str) -> TaskDialog:
"""
Set the top-level message of this dialog.
Args:
content: Top-level message to set.
"""
...
def setDetails(self: TaskDialog, details: str) -> TaskDialog:
"""
Set the details for this TaskDialog.
The details are hidden by default and the user can display them by clicking
the "Details" button at the bottom of the TaskDialog.
Args:
details: Details content to display. Can be a multi-line string.
"""
...
def setIcon(self: TaskDialog, icon: PyQt6.QtWidgets.QMessageBox.Icon) -> TaskDialog:
"""
Set the icon of the dialog.
Args:
icon: Icon of the dialog.
"""
...
def setMain(self: TaskDialog, main: str) -> TaskDialog:
"""
Set the main message of the dialog. The main message is displayed at the top of
the dialog in large font.
Args:
main: Main message of the dialog.
"""
...
def setRemember(self: TaskDialog, action: str, file: str = '') -> TaskDialog:
"""
Configure the dialog to remember user-choice.
"""
...
def setTitle(self: TaskDialog, title: str) -> TaskDialog:
"""
Set the title of the dialog.
Args:
title: Title of the dialog.
"""
...
def setWidth(self: TaskDialog, width: int) -> None:
"""
Set the width of the dialog.
Args:
width: Width of the dialog.
"""
...
class TaskDialogButton:
"""
Special button to be used inside TaskDialog widgets.
"""
@property
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:
"""
Create a TaskDialogButton.
Args:
text: Label of the button.
description: Description of the button.
button: Value returned by TaskDialog.exec() if this button is clicked.
"""
...
@overload
def __init__(self: TaskDialogButton, text: str, button: PyQt6.QtWidgets.QMessageBox.StandardButton) -> None:
"""
Create a TaskDialogButton without description.
Args:
text: Label of the button.
button: Value returned by TaskDialog.exec() if this button is clicked.
"""
...
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,159 @@
from __future__ import annotations
__version__ = "2.5.2"
from typing import List, Tuple, Union, overload
import PyQt6.QtCore
import PyQt6.QtGui
import PyQt6.QtWidgets
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:
"""
Construct a new TaskDialog.
Args:
parent: Parent widget of the dialog.
title: Title of the dialog.
main: Header of the dialog (big text at the top).
content: Main message of the dialog (text below main).
details: Details for the dialog, initially collapsed (bottom of the dialog).
icon: Icon for the dialog.
buttons: List of buttons for the dialog.
remember: Remember the choice for this dialog.
"""
...
def addButton(self: TaskDialog, button: TaskDialogButton) -> TaskDialog:
"""
Add a custom button to this TaskDialog.
Args:
button: Button to add to the dialog.
"""
...
def addContent(self: TaskDialog, widget: PyQt6.QtWidgets.QWidget) -> None:
"""
Add a custom widget content to this TaskDialog. Widget content are put between
content and buttons (above buttons).
Args:
widget: Widget to add.
"""
...
def exec(self: TaskDialog) -> PyQt6.QtWidgets.QMessageBox.StandardButton:
"""
Display this dialog and wait for user-interaction to return. This is a blocking
function.
Returns:
The button clicked by the user. Without custom buttons, this return Ok,
otherwise it returns the button set in the TaskDialogButton.
"""
...
def setContent(self: TaskDialog, content: str) -> TaskDialog:
"""
Set the top-level message of this dialog.
Args:
content: Top-level message to set.
"""
...
def setDetails(self: TaskDialog, details: str) -> TaskDialog:
"""
Set the details for this TaskDialog.
The details are hidden by default and the user can display them by clicking
the "Details" button at the bottom of the TaskDialog.
Args:
details: Details content to display. Can be a multi-line string.
"""
...
def setIcon(self: TaskDialog, icon: PyQt6.QtWidgets.QMessageBox.Icon) -> TaskDialog:
"""
Set the icon of the dialog.
Args:
icon: Icon of the dialog.
"""
...
def setMain(self: TaskDialog, main: str) -> TaskDialog:
"""
Set the main message of the dialog. The main message is displayed at the top of
the dialog in large font.
Args:
main: Main message of the dialog.
"""
...
def setRemember(self: TaskDialog, action: str, file: str = '') -> TaskDialog:
"""
Configure the dialog to remember user-choice.
"""
...
def setTitle(self: TaskDialog, title: str) -> TaskDialog:
"""
Set the title of the dialog.
Args:
title: Title of the dialog.
"""
...
def setWidth(self: TaskDialog, width: int) -> None:
"""
Set the width of the dialog.
Args:
width: Width of the dialog.
"""
...
class TaskDialogButton:
"""
Special button to be used inside TaskDialog widgets.
"""
@property
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:
"""
Create a TaskDialogButton.
Args:
text: Label of the button.
description: Description of the button.
button: Value returned by TaskDialog.exec() if this button is clicked.
"""
...
@overload
def __init__(self: TaskDialogButton, text: str, button: PyQt6.QtWidgets.QMessageBox.StandardButton) -> None:
"""
Create a TaskDialogButton without description.
Args:
text: Label of the button.
button: Value returned by TaskDialog.exec() if this button is clicked.
"""
...
+3 -3
View File
@@ -1,7 +1,7 @@
# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
package = []
[metadata]
lock-version = "2.0"
python-versions = "^3.11"
content-hash = "81b2fa642d7f2d1219cf80112ace12d689d053d81be7f7addb98144d56fc0fb2"
python-versions = "^3.12"
content-hash = "34e39677d8527182346093002688d17a5d2fc204b9eb3e094b2e6ac519028228"
+2 -2
View File
@@ -1,6 +1,6 @@
[tool.poetry]
name = "mobase-stubs"
version = "v2.5.0.dev16"
version = "v2.5.0.dev17"
description = "PEP561 stub files for the mobase Python API."
authors = ["Holt59 <capelle.mikael@gmail.com>"]
license = "MIT"
@@ -11,7 +11,7 @@ documentation = "https://www.modorganizer.org/python-plugins-doc/"
repository = "https://github.com/ModOrganizer2/mo2-pystubs-generation"
[tool.poetry.dependencies]
python = "^3.11"
python = "^3.12"
[build-system]
requires = ["poetry-core"]