Compare commits

..
10 Commits
Author SHA1 Message Date
Mikaël Capelle c5ee7f8a43 Pypi-publish on tag. 2022-04-22 13:17:01 +02:00
Mikaël Capelle 33b7222b13 Fix enabledByDefault(). 2022-04-22 12:19:47 +02:00
Mikaël Capelle e083e0832e Linting. 2022-04-21 22:03:21 +02:00
Mikaël Capelle 478af17c58 Fix PyQt5 -> PyQt6. 2022-04-21 21:40:18 +02:00
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 3404 additions and 155 deletions
+6 -5
View File
@@ -4,8 +4,8 @@
name: Upload Python Package
on:
release:
types: [published]
push:
tags: ["*.dev[0-9]+"]
jobs:
deploy:
@@ -18,13 +18,13 @@ jobs:
uses: frabert/replace-string-action@v1.1
id: version
with:
string: ${{ github.event.release.tag_name }}
string: ${{ github.ref_name }}
pattern: "v?([0-9][.][0-9][.][0-9]).*"
replace-with: "$1"
- 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
@@ -36,5 +36,6 @@ jobs:
run: |
cd stubs/setup
cp ../${{ steps.version.outputs.replaced }}/mobase.pyi mobase-stubs/__init__.pyi
sed -i 's/__version__ = ".*"/__version__ = "${{ github.ref_name }}"/' 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)
+2 -2
View File
@@ -4,7 +4,6 @@ import importlib.machinery
import importlib.util
import os
import sys
from pathlib import Path
@@ -16,6 +15,7 @@ def load_module(name: str, path: Path):
# Extract the spec:
spec = importlib.util.spec_from_loader(name, loader)
assert spec is not None
# Create the module and execute it?
module = importlib.util.module_from_spec(spec)
@@ -54,7 +54,7 @@ def load_mobase(path: Path, moprivate: bool = False):
os.add_dll_directory(str(path)) # type: ignore[attr-defined]
os.add_dll_directory(str(path.joinpath("dlls"))) # type: ignore[attr-defined]
# We need to add plugins/data to sys.path, mainly for PyQt5
# We need to add plugins/data to sys.path, mainly for PyQt6
sys.path.insert(1, path.joinpath("plugins", "data").as_posix())
mobase = load_module("mobase", path.joinpath("plugins", "data", "pythonrunner.dll"))
+7 -8
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__
@@ -120,9 +119,9 @@ class CType(Type):
REPLACEMENTS = {
"QString": "str",
"QStringList": "List[str]",
"QWidget *": "PyQt5.QtWidgets.QWidget",
"QMainWindow *": "PyQt5.QtWidgets.QMainWindow",
"QObject *": "PyQt5.QtCore.QObject",
"QWidget *": "PyQt6.QtWidgets.QWidget",
"QMainWindow *": "PyQt6.QtWidgets.QMainWindow",
"QObject *": "PyQt6.QtCore.QObject",
"void *": "object",
"api::object": "object",
}
@@ -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
+21 -23
View File
@@ -2,26 +2,24 @@
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=")>"):
@@ -206,9 +204,9 @@ def parse_psig(s: str, name: str) -> Tuple[Type, List[Arg]]:
n: str = pa.strip()
d: Optional[str] = None
if pa.find("=") != -1:
n, d = pa.split("=")
n, ds = pa.split("=")
n = n.strip()
d = d.strip()
d = ds.strip()
elif i > len(args) - c - 1:
d = Arg.DEFAULT_NONE
pargs.append(Arg(n, Type(t), d))
@@ -320,7 +318,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]
@@ -585,10 +583,10 @@ def make_class(fullname: str, e: type, register: MobaseRegister) -> Class:
if e.__name__.endswith("Widget"):
logger.info(
"Forcing base {} for class {}.".format(
"PyQt5.QtWidgets.QWidget", e.__name__
"PyQt6.QtWidgets.QWidget", e.__name__
)
)
direct_bases.append(PyClass("PyQt5.QtWidgets.QWidget"))
direct_bases.append(PyClass("PyQt6.QtWidgets.QWidget"))
return Class(
e.__name__,
+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]
+17 -4
View File
@@ -2,6 +2,7 @@
from collections import OrderedDict, defaultdict
from typing import (
TYPE_CHECKING,
Any,
Dict,
List,
@@ -11,14 +12,12 @@ from typing import (
TextIO,
Tuple,
Union,
TYPE_CHECKING,
)
from . import logger
from . import mtypes
import yaml
from . import logger, mtypes
if TYPE_CHECKING:
from .register import MobaseRegister
@@ -339,6 +338,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
+5 -7
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",
@@ -136,9 +134,9 @@ with open(args.output, "w") as output:
"Type",
],
),
"PyQt5.QtCore",
"PyQt5.QtGui",
"PyQt5.QtWidgets",
"PyQt6.QtCore",
"PyQt6.QtGui",
"PyQt6.QtWidgets",
]
)
+10 -3
View File
@@ -15,19 +15,26 @@ warn_return_any = True
warn_unused_configs = True
namespace_packages = True
[isort]
profile = black
multi_line_output = 3
[tox:tox]
skipsdist = true
envlist = py38-lint
envlist = py310-lint
[testenv:py38-lint]
[testenv:py310-lint]
skip_install = true
deps =
black
mypy
flake8
flake8-black
PyQt5-stubs
git+https://github.com/TilmanK/PyQt6-stubs.git
types-PyYAML
isort
commands =
black generator main.py --check --diff
flake8 generator main.py
mypy generator main.py
isort -c generator main.py
+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
+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",