mirror of
https://github.com/ModOrganizer2/pystubs-generation.git
synced 2026-07-27 14:07:13 -07:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e9919fb94 | ||
|
|
422e29417c |
@@ -15,16 +15,15 @@ jobs:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.12
|
||||
python-version: 3.11
|
||||
- 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: |
|
||||
mkdir -p docs/src
|
||||
cp -r stubs/2.5.2/mobase-stubs docs/src/mobase
|
||||
run: cp stubs/2.5.0/mobase-stubs/__init__.pyi docs/mobase.py
|
||||
- name: Build
|
||||
run: poetry run sphinx-build -b html docs/source docs/build
|
||||
env:
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.12
|
||||
python-version: 3.11
|
||||
- uses: abatilo/actions-poetry@v2
|
||||
- name: Install
|
||||
run: |
|
||||
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
replace-with: "$1"
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.12
|
||||
python-version: 3.11
|
||||
- uses: abatilo/actions-poetry@v2
|
||||
- name: Build
|
||||
run: |
|
||||
|
||||
@@ -109,6 +109,7 @@ import mobase
|
||||
import mobase.widgets
|
||||
```
|
||||
|
||||
|
||||
**Note:** Most classes in `mobase` cannot be instantiated, so this is mostly intended
|
||||
for MO2 developers.
|
||||
|
||||
|
||||
+24
-22
@@ -3,11 +3,12 @@
|
||||
version: 2
|
||||
|
||||
# version of the stubs - this is overridden when publishing
|
||||
__version__: "2.5.2"
|
||||
__version__: "2.5.0"
|
||||
|
||||
# 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:
|
||||
@@ -301,7 +302,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:
|
||||
@@ -486,6 +487,9 @@ mobase:
|
||||
|
||||
returns: The number of unregistered features.
|
||||
|
||||
|
||||
|
||||
|
||||
GamePlugins:
|
||||
__abstract__: true
|
||||
getLoadOrder:
|
||||
@@ -493,8 +497,8 @@ mobase:
|
||||
returns:
|
||||
lightPluginsAreSupported:
|
||||
returns: True if light plugins are supported, False otherwise.
|
||||
mediumPluginsAreSupported:
|
||||
returns: True if medium plugins are supported, False otherwise.
|
||||
overridePluginsAreSupported:
|
||||
returns: True if override plugins are supported, False otherwise.
|
||||
readPluginLists:
|
||||
__doc__:
|
||||
args:
|
||||
@@ -578,6 +582,7 @@ mobase:
|
||||
returns: The list of variants for this GuessedString.
|
||||
|
||||
IDownloadManager:
|
||||
|
||||
downloadPath:
|
||||
__doc__: Retrieve the (absolute) path of the specified download.
|
||||
args:
|
||||
@@ -735,7 +740,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.
|
||||
@@ -998,6 +1003,7 @@ mobase:
|
||||
returns: The result of the installation.
|
||||
|
||||
IModInterface:
|
||||
|
||||
absolutePath:
|
||||
returns: Absolute path to the mod to be used in file system operations.
|
||||
|
||||
@@ -1333,6 +1339,7 @@ mobase:
|
||||
returns: The state of the given mod.
|
||||
|
||||
IModRepositoryBridge:
|
||||
|
||||
__bases__:
|
||||
- PyQt6.QtCore.QObject
|
||||
|
||||
@@ -2475,6 +2482,7 @@ mobase:
|
||||
installation did not succeed.
|
||||
|
||||
IPluginList:
|
||||
|
||||
__doc__: Primary interface to the list of plugins.
|
||||
|
||||
isMaster:
|
||||
@@ -2519,9 +2527,10 @@ 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.
|
||||
@@ -2531,16 +2540,16 @@ mobase:
|
||||
True if the given plugin is a light plugin, False otherwise or if the
|
||||
file does not exist.
|
||||
|
||||
isMediumFlagged:
|
||||
isOverlayFlagged:
|
||||
__doc__: |
|
||||
Determine if a plugin is flagged as medium.
|
||||
Determine if a plugin is flagged as overlay
|
||||
|
||||
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 a medium plugin, False otherwise or if the
|
||||
True if the given plugin is an overlay plugin, False otherwise or if the
|
||||
file does not exist.
|
||||
|
||||
hasLightExtension:
|
||||
@@ -2653,6 +2662,7 @@ mobase:
|
||||
returns: The state of the plugin.
|
||||
|
||||
IPluginModPage:
|
||||
|
||||
_parentWidget:
|
||||
abstract: false
|
||||
returns: The parent widget.
|
||||
@@ -2698,27 +2708,15 @@ mobase:
|
||||
by qt are implemented (including dds) but no audio files and no 3d mesh formats.
|
||||
|
||||
genFilePreview:
|
||||
__doc__: Generate a preview widget for the specified file.
|
||||
__doc__: Generate a preview 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.
|
||||
|
||||
@@ -2801,6 +2799,7 @@ 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
|
||||
@@ -2928,6 +2927,7 @@ mobase:
|
||||
returns:
|
||||
|
||||
Mapping:
|
||||
|
||||
__init__.1:
|
||||
__doc__: Creates an empty Mapping.
|
||||
|
||||
@@ -3348,6 +3348,7 @@ mobase:
|
||||
returns: The version scheme in effect for this VersionInfo.
|
||||
|
||||
mobase.widgets:
|
||||
|
||||
TaskDialog:
|
||||
__doc__: Customizable choice dialog.
|
||||
|
||||
@@ -3436,6 +3437,7 @@ mobase.widgets:
|
||||
args:
|
||||
width: Width of the dialog.
|
||||
|
||||
|
||||
TaskDialogButton:
|
||||
__doc__: Special button to be used inside TaskDialog widgets.
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
sphinx-rtd-theme
|
||||
sphinx-autodoc-typehints
|
||||
sphinx-automodapi
|
||||
PyQt6
|
||||
+1
-5
@@ -27,9 +27,8 @@ 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.
|
||||
@@ -40,9 +39,6 @@ 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 -------------------------------------------------
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ This documentation is dedicated to writting MO2 **Python** plugins.
|
||||
plugin-types
|
||||
writing-plugins
|
||||
faq
|
||||
mobase
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
``mobase`` API
|
||||
==============
|
||||
|
||||
.. currentmodule:: mobase
|
||||
|
||||
.. automodapi:: mobase
|
||||
:no-inheritance-diagram:
|
||||
:no-heading:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
@@ -0,0 +1,7 @@
|
||||
mobase
|
||||
======
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
mobase
|
||||
@@ -64,8 +64,10 @@ 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 can register only the features they need to MO2 using :meth:`registerFeature<mobase.IGameFeatures.registerFeature>`
|
||||
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.
|
||||
|
||||
As an example for a game feature take BSA invalidation: If the game requires BSA invalidation it will implement
|
||||
this feature.
|
||||
@@ -145,4 +147,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
+172
-221
File diff suppressed because it is too large
Load Diff
+11
-10
@@ -12,22 +12,20 @@ mo2-stubs-generator = "mo2.stubs.generator.__main__:main"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.12"
|
||||
pyqt6 = "6.7.1"
|
||||
pyqt6 = "^6.7.0"
|
||||
pyyaml = "^6.0.1"
|
||||
typing-extensions = "^4.12.2"
|
||||
|
||||
[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.365"
|
||||
ruff = "^0.4.7"
|
||||
types-pyyaml = "^6.0.12.20240311"
|
||||
poethepoet = "^0.26.1"
|
||||
|
||||
[tool.poetry.group.doc.dependencies]
|
||||
sphinx-rtd-theme = "^2.0.0"
|
||||
sphinx-autodoc-typehints = "^2.2.3"
|
||||
sphinx-automodapi = "^0.17.0"
|
||||
sphinx = "<8"
|
||||
sphinx-autoapi = "^3.2.1"
|
||||
sphinx-autodoc-typehints = "^2.1.0"
|
||||
sphinx-automodapi = "^0.16.0"
|
||||
sphinx = "^7.3.7"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
@@ -49,6 +47,9 @@ 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
|
||||
|
||||
@@ -8,7 +8,7 @@ from pathlib import Path
|
||||
from typing import Callable
|
||||
|
||||
from .loader import load_mobase
|
||||
from .mtypes import Class, Constant, Enum, Function, PyTyping
|
||||
from .mtypes import Class, PyTyping
|
||||
from .parser import is_enum
|
||||
from .register import MobaseRegister
|
||||
from .utils import Settings, clean_class
|
||||
@@ -146,9 +146,6 @@ def main() -> None:
|
||||
[
|
||||
# the "real" IPlugin is IPluginBase
|
||||
"IPlugin",
|
||||
|
||||
# this is deprecated
|
||||
"PluginSetting"
|
||||
],
|
||||
),
|
||||
"mobase.widgets": extract_objects(mobase.widgets), # type: ignore
|
||||
@@ -174,10 +171,6 @@ def main() -> None:
|
||||
# Create the corresponding object:
|
||||
c = register.make_object(n, o)
|
||||
|
||||
|
||||
for n, o in objects:
|
||||
c = register.get_object(n)
|
||||
|
||||
if isinstance(c, Class):
|
||||
# Clean the class (e.g., remove duplicates methods due to wrappers):
|
||||
clean_class(c)
|
||||
@@ -185,7 +178,7 @@ def main() -> None:
|
||||
# Path the class using the configuration:
|
||||
settings.patch_class(c)
|
||||
|
||||
elif isinstance(c, (PyTyping, Constant)):
|
||||
elif isinstance(c, PyTyping):
|
||||
...
|
||||
|
||||
elif is_list_of_functions(c):
|
||||
@@ -205,21 +198,6 @@ 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)
|
||||
@@ -230,22 +208,25 @@ def main() -> None:
|
||||
|
||||
module_headers[name](writer)
|
||||
|
||||
for c in stub_objects:
|
||||
for n, _o in objects:
|
||||
# Get the corresponding object:
|
||||
c = register.get_object(n)
|
||||
|
||||
writer.print_object(c)
|
||||
|
||||
subprocess.run(
|
||||
[
|
||||
"ruff",
|
||||
"format",
|
||||
"--silent",
|
||||
"format",
|
||||
output_folder.joinpath("__init__.pyi").as_posix(),
|
||||
]
|
||||
)
|
||||
subprocess.run(
|
||||
[
|
||||
"ruff",
|
||||
"check",
|
||||
"--silent",
|
||||
"check",
|
||||
"--select",
|
||||
"I",
|
||||
"--fix",
|
||||
|
||||
@@ -33,7 +33,7 @@ def load_mobase(path: os.PathLike[Any]) -> Module:
|
||||
os.add_dll_directory(str(path.joinpath("dlls"))) # type: ignore
|
||||
|
||||
# We need to add plugins/data to sys.path, mainly for PyQt6
|
||||
sys.path.insert(1, path.joinpath("proxies", "python", "libs").as_posix())
|
||||
sys.path.insert(1, path.joinpath("plugins", "plugin_python", "libs").as_posix())
|
||||
|
||||
import mobase # type: ignore
|
||||
|
||||
|
||||
@@ -234,8 +234,6 @@ def make_class(e: type, register: MobaseRegister) -> Class:
|
||||
# members to exclude
|
||||
EXCLUDED_MEMBERS = [
|
||||
"__init_subclass__",
|
||||
"__dict__",
|
||||
"__doc__",
|
||||
"__module__",
|
||||
"__subclasshook__",
|
||||
"__hash__",
|
||||
@@ -348,7 +346,7 @@ def make_class(e: type, register: MobaseRegister) -> Class:
|
||||
|
||||
direct_bases: list[Class] = []
|
||||
for c in e.__bases__:
|
||||
if c.__module__ not in ("pybind11_builtins", "builtins"):
|
||||
if c.__module__ != "pybind11_builtins":
|
||||
b = register.get_object(c.__name__)
|
||||
assert isinstance(b, Class)
|
||||
direct_bases.append(b)
|
||||
|
||||
@@ -4,7 +4,7 @@ from __future__ import annotations
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from .mtypes import Class, Constant, Function, PyType, PyTyping
|
||||
from .mtypes import Class, Function, PyTyping
|
||||
|
||||
|
||||
class MobaseRegister:
|
||||
@@ -12,7 +12,7 @@ class MobaseRegister:
|
||||
Class that register classes.
|
||||
"""
|
||||
|
||||
objects: dict[str, Class | Constant | list[Function] | PyTyping]
|
||||
objects: dict[str, Class | 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] | Constant | PyTyping:
|
||||
) -> Class | list[Function] | PyTyping:
|
||||
"""
|
||||
Construct a Function, Class, Constant or Enum for the given object.
|
||||
Construct a Function, Class 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 | Constant | list[Function] | PyTyping:
|
||||
def get_object(self, name: str) -> Class | 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).
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
import logging
|
||||
from typing import Any, Iterable, TextIO
|
||||
from typing import Any, Iterable, TextIO, TypeGuard
|
||||
|
||||
from typing_extensions import TypeIs
|
||||
|
||||
from .mtypes import Class, Constant, Enum, Function, Method, Property, PyTyping
|
||||
from .mtypes import Class, Enum, Function, Method, Property, PyTyping
|
||||
from .utils import Settings
|
||||
|
||||
LOGGER = logging.getLogger(__package__)
|
||||
|
||||
|
||||
def is_list_of_functions(e: Any | Iterable[Any]) -> TypeIs[list[Function]]:
|
||||
def is_list_of_functions(e: Any | Iterable[Any]) -> TypeGuard[list[Function]]:
|
||||
if not isinstance(e, list):
|
||||
return False
|
||||
return all(isinstance(x, Function) for x in e)
|
||||
@@ -258,15 +256,7 @@ class Writer:
|
||||
def print_typing(self, typ: PyTyping):
|
||||
self._print(f"{typ.name} = {typ.typing}")
|
||||
|
||||
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):
|
||||
def print_object(self, e: object):
|
||||
if isinstance(e, Class):
|
||||
self.print_class(e)
|
||||
|
||||
@@ -276,6 +266,3 @@ 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
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user