Compare commits

..
6 Commits
Author SHA1 Message Date
Mikaël Capelle 6ca51655aa Fix version in config. 2022-04-21 21:19:37 +02:00
Mikaël Capelle 0ec04f4e9e Fix setup.py 2022-04-21 21:10:14 +02:00
Mikaël Capelle d43d067c84 Update for Qt6. 2022-04-21 21:03:48 +02:00
Mikaël Capelle 06e0fe1cca Update documentation. 2021-02-26 19:25:23 +01:00
Mikaël Capelle c57280578d Update PyQt5-stubs version. 2021-02-26 19:25:15 +01:00
Mikaël Capelle 178b1d111d Fix some argument names in the configuration file. 2021-02-07 20:20:02 +01:00
16 changed files with 7606 additions and 132 deletions
+2 -2
View File
@@ -24,7 +24,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.8'
python-version: '3.10'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
@@ -37,4 +37,4 @@ jobs:
cd stubs/setup
cp ../${{ steps.version.outputs.replaced }}/mobase.pyi mobase-stubs/__init__.pyi
python setup.py sdist bdist_wheel
twine upload dist/*
twine upload dist/*
+3 -3
View File
@@ -642,7 +642,7 @@ mobase:
The path to copy the entry to. If the path ends with / or \\, the entry will
be copied in the corresponding directory instead of replacing it. If the
given path is empty (`""`), the entry is copied directly under this tree.
policy: Policy to use to resolve conflicts.
insert_policy: Policy to use to resolve conflicts.
returns: The new entry (copy of the specified entry).
raises:
RuntimeError: If the entry could not be copied.
@@ -2947,7 +2947,7 @@ mobase:
getMissingAssets:
__doc__: Retrieve missing assets from the save.
args:
filepath: The save to find missing assets for.
save: The save to find missing assets for.
returns: |
A collection of missing assets and the modules that can supply those assets.
@@ -3095,7 +3095,7 @@ mobase:
args:
value: String to parse.
scheme: Scheme to use to parse the string.
manual_input: True if the given string should be treated as user input.
is_manual: True if the given string should be treated as user input.
scheme:
returns: The version scheme in effect for this VersionInfo.
File diff suppressed because it is too large Load Diff
+22 -23
View File
@@ -15,7 +15,7 @@ This guide assumes that:
`Python extension <https://marketplace.visualstudio.com/items?itemName=ms-python.python>`_.
- You have Python installed: https://www.python.org/downloads/.
- It is recommended but not mandatory to use the Python version that is used by MO2.
- You must use the Python version that used by MO2.
You can check the ``pythonXX.dll`` in the MO2 installation folder to find the Python version used by MO2 (``python38.dll`` means Python 3.8).
- You obviously need a valid MO2 installation: https://github.com/modorganizer2/modorganizer/releases
@@ -28,8 +28,8 @@ Preparation
-----------
**Note:** This part is optional but highly recommended if you want a proper environment to work with.
Everything here is written to be as simple as possible but you can of course adapt it to your preferences: use a python virtual
environment, use workspace settings instead of global ones, etc.
Everything here is written to be as simple as possible but you can of course adapt it to your preferences:
use a python virtual environment, use workspace settings instead of global ones, etc.
1. Get the ``mobase`` stubs
...........................
@@ -39,11 +39,14 @@ as ``flake8`` or ``mypy``.
Instead, we provide `stubs <https://stackoverflow.com/questions/59051631/what-is-the-use-of-stub-files-pyi-in-python>`_
which can be used for auto-completion or type-checking.
The stubs for ``mobase`` are available at https://github.com/ModOrganizer2/pystubs-generation/tree/master/stubs.
You want to download the ``mobase.pyi`` file in the folder corresponding to your MO2 version and put it under ``$MO2DIR/plugins/data``.
You can install the stubs for ``mobase`` using ``pip``:
.. code::
pip install mobase-stubs
This will install the stubs for ``mobase`` but also for PyQt5, which is heavily used by MO2.
**Note:** It is possible to put the stubs in a different location, but we are going to use ``$MO2DIR/plugins/data`` for PyQt5,
so we might as well use it for the stubs.
2. Configure Visual Studio Code for ``mobase``
..............................................
@@ -57,32 +60,28 @@ Open ``settings.json`` (Ctrl+Shift+P, then "Open Settings (JSON)"), and add the
"python.linting.enabled": true,
"python.linting.mypyEnabled": true,
"python.linting.flake8Enabled": true,
"python.autoComplete.extraPaths": [
"$MO2DIR\\plugins\\data",
]
3. Configure ``mypy`` to find the ``mobase`` stubs
..................................................
3. [Optional] Configure ``black`` to auto-format your source files
..................................................................
There are multiply way to configure ``mypy``:
This step is optional for your own plugin but recent MO2 plugins use ``black``
to get consistent formatting.
1. You can create a ``mypy.ini`` file somewhere containing:
You can install ``black`` with ``pip``:
.. code-block:: ini
.. code::
[mypy]
mypy_path = $MO2DIR\plugins\data
pip install black flake8-black
And then add the following to ``settings.json`` (with the correct path):
To configure Visual Studio Code to auto-format your code with ``black`` when saving, open ``settings.json``
(Ctrl+Shift+P, then "Open Settings (JSON)"), and add the following entries:
.. code-block:: json-object
"python.linting.mypyArgs": [
"--config-file=path-to-mypy.ini",
]
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"python.formatting.provider": "black",
2. You can set the ``MYPYPATH`` environment variable to ``$MO2DIR\plugins\data`` (this requires
restarting VS code).
4. [Optional] Automatically reload plugins during development
.............................................................
-1
View File
@@ -3,7 +3,6 @@
import logging
import sys
logging.basicConfig(stream=sys.stderr, format="%(levelname)s: %(message)s")
logger = logging.getLogger(__name__)
logger.setLevel(logging.WARNING)
-1
View File
@@ -4,7 +4,6 @@ import importlib.machinery
import importlib.util
import os
import sys
from pathlib import Path
+4 -5
View File
@@ -1,9 +1,8 @@
# -*- encoding: utf-8 -*-
from typing import Optional, List, Any, Dict, Union
from typing import Any, Dict, List, Optional, Union
from . import logger
from . import utils
from . import logger, utils
class Type:
@@ -20,7 +19,7 @@ class Type:
def __init__(self, name: Union[str, type]):
# Import only here since we change the path to find them:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt6 import QtCore, QtGui, QtWidgets
if isinstance(name, type):
name = name.__name__
@@ -141,7 +140,7 @@ class CType(Type):
def _try_fix(self, name, settings: utils.Settings):
from .parser import parse_ctype, magic_split, parse_csig
from .parser import magic_split, parse_csig, parse_ctype
from .register import MOBASE_REGISTER
pname = name
+6 -19
View File
@@ -2,26 +2,13 @@
import inspect
import re
from collections import OrderedDict, defaultdict
from typing import Dict, List, Optional, Tuple, Union
from collections import defaultdict, OrderedDict
from typing import List, Tuple, Optional, Dict, Union
from .register import MobaseRegister
from .mtypes import (
Type,
CType,
Class,
PyClass,
Enum,
Arg,
Ret,
Method,
Constant,
Property,
Function,
)
from . import logger
from .mtypes import (Arg, Class, Constant, CType, Enum, Function, Method,
Property, PyClass, Ret, Type)
from .register import MobaseRegister
def magic_split(value: str, sep=",", open="(<", close=")>"):
@@ -320,7 +307,7 @@ def make_enum(fullname: str, e: type) -> Enum:
class Overload:
""" Small class to avoid mypy issues... """
"""Small class to avoid mypy issues..."""
rtype: Type
args: List[Arg]
+3 -3
View File
@@ -1,10 +1,10 @@
# -*- encoding: utf-8 -*-
from collections import OrderedDict
from typing import Optional, Dict, Union, List
from typing import Dict, List, Optional, Union
from . import logger
from .mtypes import Class, Type, CType, Function
from .mtypes import Class, CType, Function, Type
class MobaseRegister:
@@ -37,7 +37,7 @@ class MobaseRegister:
Returns:
A Class object for the given type, or a list of function overloads.
"""
from .parser import make_enum, make_class, is_enum, make_functions
from .parser import is_enum, make_class, make_enum, make_functions
if e is None:
e = self.raw_objects[name]
+18 -15
View File
@@ -1,24 +1,13 @@
# -*- encoding: utf-8 -*-
from collections import OrderedDict, defaultdict
from typing import (
Any,
Dict,
List,
NamedTuple,
Optional,
Set,
TextIO,
Tuple,
Union,
TYPE_CHECKING,
)
from . import logger
from . import mtypes
from typing import (TYPE_CHECKING, Any, Dict, List, NamedTuple, Optional, Set,
TextIO, Tuple, Union)
import yaml
from . import logger, mtypes
if TYPE_CHECKING:
from .register import MobaseRegister
@@ -339,6 +328,20 @@ class Settings:
for sarg, marg in zip(fsettings.args, margs):
marg.doc = sarg.doc
if (
not marg.name.startswith("arg")
and marg.name != sarg.name
):
logger.warn(
"Mismatch argument name for method {}.{}: {} {}, using {}.".format( # noqa: E501
cls.canonical_name,
sname,
marg.name,
sarg.name,
sarg.name,
)
)
marg.name = sarg.name
if not sarg.type.is_none():
marg.type = sarg.type
+2 -2
View File
@@ -1,9 +1,9 @@
# -*- encoding: utf-8 -*-
from typing import TextIO, List, Union, Tuple
from typing import List, TextIO, Tuple, Union
from . import logger
from .mtypes import Function, Class, Method, Property, Enum
from .mtypes import Class, Enum, Function, Method, Property
from .utils import Settings
+2 -4
View File
@@ -2,20 +2,18 @@
import argparse
import logging
from pathlib import Path
import black
from generator import logger
from generator.loader import load_mobase
from generator.register import MOBASE_REGISTER
from generator.mtypes import Class, Function, Type
from generator.parser import is_enum
from generator.mtypes import Type, Class, Function
from generator.register import MOBASE_REGISTER
from generator.utils import Settings, clean_class
from generator.writer import Writer
parser = argparse.ArgumentParser("Stubs generator for the MO2 python interface")
parser.add_argument(
"install_dir",
+6 -6
View File
@@ -795,7 +795,7 @@ class IFileTree(FileTreeEntry):
self,
entry: "FileTreeEntry",
path: str = "",
policy: "IFileTree.InsertPolicy" = InsertPolicy.FAIL_IF_EXISTS,
insert_policy: "IFileTree.InsertPolicy" = InsertPolicy.FAIL_IF_EXISTS,
) -> "FileTreeEntry":
"""
Move the given entry to the given path under this tree.
@@ -816,7 +816,7 @@ class IFileTree(FileTreeEntry):
path: The path to copy the entry to. If the path ends with / or \\, the entry will
be copied in the corresponding directory instead of replacing it. If the
given path is empty (`""`), the entry is copied directly under this tree.
policy: Policy to use to resolve conflicts.
insert_policy: Policy to use to resolve conflicts.
Returns:
The new entry (copy of the specified entry).
@@ -3900,12 +3900,12 @@ class SaveGameInfo(abc.ABC):
def __init__(self): ...
@abc.abstractmethod
def getMissingAssets(self, filepath: "ISaveGame") -> Dict[str, List[str]]:
def getMissingAssets(self, save: "ISaveGame") -> Dict[str, List[str]]:
"""
Retrieve missing assets from the save.
Args:
filepath: The save to find missing assets for.
save: The save to find missing assets for.
Returns:
A collection of missing assets and the modules that can supply those assets.
@@ -4155,7 +4155,7 @@ class VersionInfo:
self,
value: str,
scheme: "VersionScheme" = VersionScheme.DISCOVER,
manual_input: bool = False,
is_manual: bool = False,
):
"""
Update this VersionInfo by parsing the given string using the given scheme.
@@ -4163,7 +4163,7 @@ class VersionInfo:
Args:
value: String to parse.
scheme: Scheme to use to parse the string.
manual_input: True if the given string should be treated as user input.
is_manual: True if the given string should be treated as user input.
"""
...
def scheme(self) -> "VersionScheme":
File diff suppressed because it is too large Load Diff
+127 -46
View File
@@ -1,4 +1,4 @@
__version__ = "2.4.0"
__version__ = "2.5.0.dev0"
import abc
from enum import Enum
@@ -36,7 +36,7 @@ def getFileVersion(filepath: str) -> str:
"""
...
def getIconForExecutable(executable: str) -> PyQt5.QtGui.QIcon:
def getIconForExecutable(executable: str) -> PyQt6.QtGui.QIcon:
"""
Retrieve the icon of an executable. Currently this always extracts the biggest icon.
@@ -65,6 +65,7 @@ class EndorsedState(Enum):
ENDORSED_TRUE = ...
ENDORSED_UNKNOWN = ...
ENDORSED_NEVER = ...
def __and__(self, other: int) -> bool: ...
def __or__(self, other: int) -> bool: ...
def __rand__(self, other: int) -> bool: ...
@@ -82,6 +83,7 @@ class GuessQuality(Enum):
META = ...
PRESET = ...
USER = ...
def __and__(self, other: int) -> bool: ...
def __or__(self, other: int) -> bool: ...
def __rand__(self, other: int) -> bool: ...
@@ -93,6 +95,7 @@ class InstallResult(Enum):
CANCELED = ...
MANUAL_REQUESTED = ...
NOT_ATTEMPTED = ...
def __and__(self, other: int) -> bool: ...
def __or__(self, other: int) -> bool: ...
def __rand__(self, other: int) -> bool: ...
@@ -101,6 +104,7 @@ class InstallResult(Enum):
class LoadOrderMechanism(Enum):
FILE_TIME = ...
PLUGINS_TXT = ...
def __and__(self, other: int) -> bool: ...
def __or__(self, other: int) -> bool: ...
def __rand__(self, other: int) -> bool: ...
@@ -114,6 +118,7 @@ class ModState(Enum):
ENDORSED = ...
VALID = ...
ALTERNATE = ...
def __and__(self, other: int) -> bool: ...
def __or__(self, other: int) -> bool: ...
def __rand__(self, other: int) -> bool: ...
@@ -123,6 +128,7 @@ class PluginState(Enum):
MISSING = ...
INACTIVE = ...
ACTIVE = ...
def __and__(self, other: int) -> bool: ...
def __or__(self, other: int) -> bool: ...
def __rand__(self, other: int) -> bool: ...
@@ -133,6 +139,7 @@ class ProfileSetting(Enum):
CONFIGURATION = ...
SAVEGAMES = ...
PREFER_DEFAULTS = ...
def __and__(self, other: int) -> bool: ...
def __or__(self, other: int) -> bool: ...
def __rand__(self, other: int) -> bool: ...
@@ -144,6 +151,7 @@ class ReleaseType(Enum):
BETA = ...
CANDIDATE = ...
FINAL = ...
def __and__(self, other: int) -> bool: ...
def __or__(self, other: int) -> bool: ...
def __rand__(self, other: int) -> bool: ...
@@ -154,6 +162,7 @@ class SortMechanism(Enum):
MLOX = ...
BOSS = ...
LOOT = ...
def __and__(self, other: int) -> bool: ...
def __or__(self, other: int) -> bool: ...
def __rand__(self, other: int) -> bool: ...
@@ -163,6 +172,7 @@ class TrackedState(Enum):
TRACKED_FALSE = ...
TRACKED_TRUE = ...
TRACKED_UNKNOWN = ...
def __and__(self, other: int) -> bool: ...
def __or__(self, other: int) -> bool: ...
def __rand__(self, other: int) -> bool: ...
@@ -175,6 +185,7 @@ class VersionScheme(Enum):
NUMBERS_AND_LETTERS = ...
DATE = ...
LITERAL = ...
def __and__(self, other: int) -> bool: ...
def __or__(self, other: int) -> bool: ...
def __rand__(self, other: int) -> bool: ...
@@ -248,10 +259,10 @@ class ExecutableForcedLoadSetting:
def withForced(self, forced: bool) -> "ExecutableForcedLoadSetting": ...
class ExecutableInfo:
def __init__(self, title: str, binary: PyQt5.QtCore.QFileInfo): ...
def __init__(self, title: str, binary: PyQt6.QtCore.QFileInfo): ...
def arguments(self) -> List[str]: ...
def asCustom(self) -> "ExecutableInfo": ...
def binary(self) -> PyQt5.QtCore.QFileInfo: ...
def binary(self) -> PyQt6.QtCore.QFileInfo: ...
def isCustom(self) -> bool: ...
def isValid(self) -> bool: ...
def steamAppID(self) -> str: ...
@@ -259,9 +270,9 @@ class ExecutableInfo:
def withArgument(self, argument: str) -> "ExecutableInfo": ...
def withSteamAppId(self, app_id: str) -> "ExecutableInfo": ...
def withWorkingDirectory(
self, directory: PyQt5.QtCore.QDir
self, directory: PyQt6.QtCore.QDir
) -> "ExecutableInfo": ...
def workingDirectory(self) -> PyQt5.QtCore.QDir: ...
def workingDirectory(self) -> PyQt6.QtCore.QDir: ...
class FileInfo:
"""
@@ -306,13 +317,16 @@ class FileTreeEntry:
DIRECTORY = ...
FILE = ...
FILE_OR_DIRECTORY = ...
def __and__(self, other: int) -> bool: ...
def __or__(self, other: int) -> bool: ...
def __rand__(self, other: int) -> bool: ...
def __ro__(self, other: int) -> bool: ...
DIRECTORY: "FileTreeEntry.FileTypes" = ...
FILE: "FileTreeEntry.FileTypes" = ...
FILE_OR_DIRECTORY: "FileTreeEntry.FileTypes" = ...
@overload
def __eq__(self, arg2: str) -> bool: ...
@overload
@@ -681,10 +695,12 @@ class IFileTree(FileTreeEntry):
FAIL_IF_EXISTS = ...
REPLACE = ...
MERGE = ...
def __and__(self, other: int) -> bool: ...
def __or__(self, other: int) -> bool: ...
def __rand__(self, other: int) -> bool: ...
def __ro__(self, other: int) -> bool: ...
class WalkReturn(Enum):
"""
Enumeration that can be returned by the callback for the `walk()` method to stop the
@@ -694,16 +710,19 @@ class IFileTree(FileTreeEntry):
CONTINUE = ...
STOP = ...
SKIP = ...
def __and__(self, other: int) -> bool: ...
def __or__(self, other: int) -> bool: ...
def __rand__(self, other: int) -> bool: ...
def __ro__(self, other: int) -> bool: ...
CONTINUE: "IFileTree.WalkReturn" = ...
FAIL_IF_EXISTS: "IFileTree.InsertPolicy" = ...
MERGE: "IFileTree.InsertPolicy" = ...
REPLACE: "IFileTree.InsertPolicy" = ...
SKIP: "IFileTree.WalkReturn" = ...
STOP: "IFileTree.WalkReturn" = ...
def __bool__(self) -> bool:
"""
Returns:
@@ -795,7 +814,7 @@ class IFileTree(FileTreeEntry):
self,
entry: "FileTreeEntry",
path: str = "",
policy: "IFileTree.InsertPolicy" = InsertPolicy.FAIL_IF_EXISTS,
insert_policy: "IFileTree.InsertPolicy" = InsertPolicy.FAIL_IF_EXISTS,
) -> "FileTreeEntry":
"""
Move the given entry to the given path under this tree.
@@ -816,7 +835,7 @@ class IFileTree(FileTreeEntry):
path: The path to copy the entry to. If the path ends with / or \\, the entry will
be copied in the corresponding directory instead of replacing it. If the
given path is empty (`""`), the entry is copied directly under this tree.
policy: Policy to use to resolve conflicts.
insert_policy: Policy to use to resolve conflicts.
Returns:
The new entry (copy of the specified entry).
@@ -1183,7 +1202,7 @@ class IModInterface:
The old settings from the given plugin, as returned by `pluginSettings()`.
"""
...
def color(self) -> PyQt5.QtGui.QColor:
def color(self) -> PyQt6.QtGui.QColor:
"""
Returns:
The color of the 'Notes' column chosen by the user.
@@ -1634,15 +1653,16 @@ class IModList:
...
class IModRepositoryBridge(PyQt5.QtCore.QObject):
descriptionAvailable: PyQt5.QtCore.pyqtSignal = ...
filesAvailable: PyQt5.QtCore.pyqtSignal = ...
fileInfoAvailable: PyQt5.QtCore.pyqtSignal = ...
downloadURLsAvailable: PyQt5.QtCore.pyqtSignal = ...
endorsementsAvailable: PyQt5.QtCore.pyqtSignal = ...
endorsementToggled: PyQt5.QtCore.pyqtSignal = ...
trackedModsAvailable: PyQt5.QtCore.pyqtSignal = ...
trackingToggled: PyQt5.QtCore.pyqtSignal = ...
requestFailed: PyQt5.QtCore.pyqtSignal = ...
descriptionAvailable: PyQt6.QtCore.pyqtSignal = ...
filesAvailable: PyQt6.QtCore.pyqtSignal = ...
fileInfoAvailable: PyQt6.QtCore.pyqtSignal = ...
downloadURLsAvailable: PyQt6.QtCore.pyqtSignal = ...
endorsementsAvailable: PyQt6.QtCore.pyqtSignal = ...
endorsementToggled: PyQt6.QtCore.pyqtSignal = ...
trackedModsAvailable: PyQt6.QtCore.pyqtSignal = ...
trackingToggled: PyQt6.QtCore.pyqtSignal = ...
requestFailed: PyQt6.QtCore.pyqtSignal = ...
def _object(self) -> PyQt5.QtCore.QObject:
"""
Returns:
@@ -2227,6 +2247,14 @@ class IOrganizer:
The handle to the started application, or 0 if the application failed to start.
"""
...
def virtualFileTree(self) -> "IFileTree":
"""
Retrieve a IFileTree object representing the virtual file tree.
Returns:
An IFileTree representing the virtual file tree.
"""
...
def waitForApplication(self, handle: int, refresh: bool = True) -> Tuple[bool, int]:
"""
Wait for the application corresponding to the given handle to finish.
@@ -2267,6 +2295,15 @@ class IPlugin(abc.ABC):
"""
...
@abc.abstractmethod
def enabledByDefault(self) -> bool:
"""
Check whether this plugin should be enabled by default.
Returns:
True if this plugin should be enabled by default, False otherwise.
"""
...
@abc.abstractmethod
def init(self, organizer: "IOrganizer") -> bool:
"""
Initialize this plugin.
@@ -2490,7 +2527,7 @@ class IPluginGame(IPlugin):
"""
...
@abc.abstractmethod
def dataDirectory(self) -> PyQt5.QtCore.QDir:
def dataDirectory(self) -> PyQt6.QtCore.QDir:
"""
Returns:
The path to the directory containing data (absolute path).
@@ -2516,7 +2553,7 @@ class IPluginGame(IPlugin):
"""
...
@abc.abstractmethod
def documentsDirectory(self) -> PyQt5.QtCore.QDir:
def documentsDirectory(self) -> PyQt6.QtCore.QDir:
"""
Returns:
The directory of the documents folder where configuration files and such for this game reside.
@@ -2559,14 +2596,14 @@ class IPluginGame(IPlugin):
"""
...
@abc.abstractmethod
def gameDirectory(self) -> PyQt5.QtCore.QDir:
def gameDirectory(self) -> PyQt6.QtCore.QDir:
"""
Returns:
The directory containing the game installation.
"""
...
@abc.abstractmethod
def gameIcon(self) -> PyQt5.QtGui.QIcon:
def gameIcon(self) -> PyQt6.QtGui.QIcon:
"""
Returns:
The icon representing the game.
@@ -2630,7 +2667,7 @@ class IPluginGame(IPlugin):
"""
...
@abc.abstractmethod
def initializeProfile(self, directory: PyQt5.QtCore.QDir, settings: int):
def initializeProfile(self, directory: PyQt6.QtCore.QDir, settings: int):
"""
Initialize a profile for this game.
@@ -2653,7 +2690,7 @@ class IPluginGame(IPlugin):
"""
...
@abc.abstractmethod
def listSaves(self, folder: PyQt5.QtCore.QDir) -> List["ISaveGame"]:
def listSaves(self, folder: PyQt6.QtCore.QDir) -> List["ISaveGame"]:
"""
List saves in the given directory.
@@ -2672,7 +2709,7 @@ class IPluginGame(IPlugin):
"""
...
@abc.abstractmethod
def looksValid(self, directory: PyQt5.QtCore.QDir) -> bool:
def looksValid(self, directory: PyQt6.QtCore.QDir) -> bool:
"""
Check if the given directory looks like a valid game installation.
@@ -2726,7 +2763,7 @@ class IPluginGame(IPlugin):
"""
...
@abc.abstractmethod
def savesDirectory(self) -> PyQt5.QtCore.QDir:
def savesDirectory(self) -> PyQt6.QtCore.QDir:
"""
Returns:
The directory where save games are stored.
@@ -3019,18 +3056,59 @@ class IPluginList:
Primary interface to the list of plugins.
"""
def isMaster(self, name: str) -> bool:
def hasLightExtension(self, name: str) -> bool:
"""
Check if a plugin is a master file (basically a library, referenced by other plugins).
In gamebryo games, a master file will usually have a .esm file extension but technically
an esp can be flagged as master and an esm might not be.
Determine if a plugin has a .esl extension.
Args:
name: Filename of the plugin (without path but with file extension).
Returns:
True if the given plugin is a master plugin, False otherwise or if the file does not exist.
True if the given file has a .esl extension, False otherwise or if the
file does not exist.
"""
...
def hasMasterExtension(self, name: str) -> bool:
"""
Determine if a plugin has a .esm extension.
Args:
name: Filename of the plugin (without path but with file extension).
Returns:
True if the given file has a .esm extension, False otherwise or if the
file does not exist.
"""
...
def isLightFlagged(self, name: str) -> bool:
"""
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.
Args:
name: Filename of the plugin (without path but with file extension).
Returns:
True if the given plugin is a light plugin, False otherwise or if the
file does not exist.
"""
...
def isMasterFlagged(self, name: str) -> bool:
"""
Determine if a plugin is flagged as mater, i.e., a library, reference by
other plugins.
In gamebryo games, a master file will usually have a .esm file extension but
technically an esp can be flagged as master and an esm might not be.
Args:
name: Filename of the plugin (without path but with file extension).
Returns:
True if the given plugin is a master plugin, False otherwise or if the
file does not exist.
"""
...
def loadOrder(self, name: str) -> int:
@@ -3069,7 +3147,7 @@ class IPluginList:
True if the handler was installed properly (there are currently no reasons for this to fail).
"""
...
def onPluginStateChanged(self, callback: Callable[[Dict[str, int]], None]) -> bool:
def onPluginStateChanged(self, callback: Callable[[str, int], None]) -> bool:
"""
Install a new handler to be called when plugin states change.
@@ -3188,8 +3266,8 @@ class IPluginModPage(IPlugin):
@abc.abstractmethod
def handlesDownload(
self,
page_url: PyQt5.QtCore.QUrl,
download_url: PyQt5.QtCore.QUrl,
page_url: PyQt6.QtCore.QUrl,
download_url: PyQt6.QtCore.QUrl,
fileinfo: "ModRepositoryFileInfo",
) -> bool:
"""
@@ -3205,14 +3283,14 @@ class IPluginModPage(IPlugin):
"""
...
@abc.abstractmethod
def icon(self) -> PyQt5.QtGui.QIcon:
def icon(self) -> PyQt6.QtGui.QIcon:
"""
Returns:
The icon to display with the page.
"""
...
@abc.abstractmethod
def pageURL(self) -> PyQt5.QtCore.QUrl:
def pageURL(self) -> PyQt6.QtCore.QUrl:
"""
Returns:
The URL to open when the user wants to visit this mod page.
@@ -3251,7 +3329,7 @@ class IPluginPreview(IPlugin):
def __init__(self): ...
@abc.abstractmethod
def genFilePreview(
self, filename: str, max_size: PyQt5.QtCore.QSize
self, filename: str, max_size: PyQt6.QtCore.QSize
) -> PyQt5.QtWidgets.QWidget:
"""
Generate a preview for the specified file.
@@ -3345,7 +3423,7 @@ class IPluginTool(IPlugin):
"""
...
@abc.abstractmethod
def icon(self) -> PyQt5.QtGui.QIcon:
def icon(self) -> PyQt6.QtGui.QIcon:
"""
Returns:
The icon for this tool, or a default-constructed QICon().
@@ -3435,7 +3513,7 @@ class ISaveGame:
The list of all files related to this save.
"""
...
def getCreationTime(self) -> PyQt5.QtCore.QDateTime:
def getCreationTime(self) -> PyQt6.QtCore.QDateTime:
"""
Retrieve the creation time of the save.
@@ -3500,7 +3578,7 @@ class ISaveGameInfoWidget(PyQt5.QtWidgets.QWidget):
class LocalSavegames(abc.ABC):
def __init__(self): ...
@abc.abstractmethod
def mappings(self, profile_save_dir: PyQt5.QtCore.QDir) -> List["Mapping"]: ...
def mappings(self, profile_save_dir: PyQt6.QtCore.QDir) -> List["Mapping"]: ...
@abc.abstractmethod
def prepareProfile(self, profile: "IProfile") -> bool: ...
@@ -3556,13 +3634,16 @@ class ModDataChecker(abc.ABC):
INVALID = ...
FIXABLE = ...
VALID = ...
def __and__(self, other: int) -> bool: ...
def __or__(self, other: int) -> bool: ...
def __rand__(self, other: int) -> bool: ...
def __ro__(self, other: int) -> bool: ...
FIXABLE: "ModDataChecker.CheckReturn" = ...
INVALID: "ModDataChecker.CheckReturn" = ...
VALID: "ModDataChecker.CheckReturn" = ...
def __init__(self): ...
@abc.abstractmethod
def dataLooksValid(self, filetree: "IFileTree") -> "ModDataChecker.CheckReturn":
@@ -3900,12 +3981,12 @@ class SaveGameInfo(abc.ABC):
def __init__(self): ...
@abc.abstractmethod
def getMissingAssets(self, filepath: "ISaveGame") -> Dict[str, List[str]]:
def getMissingAssets(self, save: "ISaveGame") -> Dict[str, List[str]]:
"""
Retrieve missing assets from the save.
Args:
filepath: The save to find missing assets for.
save: The save to find missing assets for.
Returns:
A collection of missing assets and the modules that can supply those assets.
@@ -4016,7 +4097,7 @@ class UnmanagedMods(abc.ABC):
"""
...
@abc.abstractmethod
def referenceFile(self, mod_name: str) -> PyQt5.QtCore.QFileInfo:
def referenceFile(self, mod_name: str) -> PyQt6.QtCore.QFileInfo:
"""
Retrieve the reference file for the requested mod.
@@ -4155,7 +4236,7 @@ class VersionInfo:
self,
value: str,
scheme: "VersionScheme" = VersionScheme.DISCOVER,
manual_input: bool = False,
is_manual: bool = False,
):
"""
Update this VersionInfo by parsing the given string using the given scheme.
@@ -4163,7 +4244,7 @@ class VersionInfo:
Args:
value: String to parse.
scheme: Scheme to use to parse the string.
manual_input: True if the given string should be treated as user input.
is_manual: True if the given string should be treated as user input.
"""
...
def scheme(self) -> "VersionScheme":
+3 -2
View File
@@ -11,6 +11,7 @@
import io
import os
import re
from setuptools import setup
@@ -46,8 +47,8 @@ setup(
version=find_version("mobase-stubs", "__init__.pyi"),
package_data={"mobase-stubs": ["*.pyi"]},
packages=["mobase-stubs"],
install_requires=["PyQt5-stubs==5.14.2"],
python_requires="==3.8.*",
install_requires=[],
python_requires="==3.10.*",
classifiers=[
"Intended Audience :: Developers",
"Programming Language :: Python :: 3.8",