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: |
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
poetry version ${TAG#v}
|
||||
poetry build
|
||||
- name: Store the distribution packages
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: python-package-distributions
|
||||
path: stubs/setup/dist/
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Download all the dists
|
||||
uses: actions/download-artifact@v7
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: python-package-distributions
|
||||
path: dist/
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
+28
-350
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
+408
-531
File diff suppressed because it is too large
Load Diff
+30
-31
@@ -1,39 +1,35 @@
|
||||
[project]
|
||||
name = "mo2-pystubs-generation"
|
||||
description = ""
|
||||
license = "MIT"
|
||||
version = "0.1.0"
|
||||
readme = "README.md"
|
||||
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)",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
mo2-stubs-generator = "mo2.stubs.generator.__main__:main"
|
||||
|
||||
[build-system]
|
||||
requires = ['poetry-core (>=2.0,<3.0)']
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
||||
[tool.poetry]
|
||||
name = "mo2-pystubs-generation"
|
||||
version = "0.1.0"
|
||||
description = ""
|
||||
authors = ["Holt59 <capelle.mikael@gmail.com>"]
|
||||
license = "MIT"
|
||||
readme = "README.md"
|
||||
packages = [{ include = "mo2", from = "src" }]
|
||||
|
||||
[tool.poetry.scripts]
|
||||
mo2-stubs-generator = "mo2.stubs.generator.__main__:main"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.12"
|
||||
pyqt6 = "^6.7.0"
|
||||
pyyaml = "^6.0.1"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
pyright = "^1.1.409"
|
||||
ruff = "^0.15.12"
|
||||
types-pyyaml = "^6.0.12.20260508"
|
||||
poethepoet = "^0.45.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 = "^3.0.2"
|
||||
sphinx-autodoc-typehints = "^3.2.0"
|
||||
sphinx-automodapi = "^0.20.0"
|
||||
sphinx = "^8.2.3"
|
||||
sphinx-autoapi = "^3.6.0"
|
||||
sphinx-rtd-theme = "^2.0.0"
|
||||
sphinx-autodoc-typehints = "^2.1.0"
|
||||
sphinx-automodapi = "^0.16.0"
|
||||
sphinx = "^7.3.7"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
||||
[tool.poe.tasks]
|
||||
format-imports = "ruff check --select I src --fix"
|
||||
@@ -46,11 +42,14 @@ lint.sequence = ["lint-ruff", "lint-ruff-format", "lint-pyright"]
|
||||
lint.ignore_fail = "return_non_zero"
|
||||
|
||||
[tool.ruff]
|
||||
target-version = "py312"
|
||||
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,19 +8,19 @@ 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
|
||||
from .writer import Writer, is_list_of
|
||||
from .writer import Writer, is_list_of_functions
|
||||
|
||||
LOGGER = logging.getLogger(__package__)
|
||||
|
||||
|
||||
def extract_objects(
|
||||
module: object, skips: Sequence[str] = []
|
||||
) -> list[tuple[str, object]]:
|
||||
objects: list[tuple[str, object]] = []
|
||||
) -> list[tuple[str, type]]:
|
||||
objects: list[tuple[str, type]] = []
|
||||
|
||||
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, object]]] = {
|
||||
module_objects: dict[str, list[tuple[str, type]]] = {
|
||||
"mobase": extract_objects(
|
||||
mobase,
|
||||
[
|
||||
@@ -178,10 +178,10 @@ 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(c, Function):
|
||||
elif is_list_of_functions(c):
|
||||
settings.patch_functions(c)
|
||||
|
||||
else:
|
||||
@@ -198,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)
|
||||
@@ -223,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",
|
||||
|
||||
@@ -4,7 +4,7 @@ import re
|
||||
import types
|
||||
from collections import OrderedDict, defaultdict
|
||||
from itertools import chain
|
||||
from typing import Any, Callable, Iterable, cast
|
||||
from typing import Any, 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: object) -> bool:
|
||||
def is_enum(e: type) -> bool:
|
||||
"""Check if the given class is an enumeration.
|
||||
|
||||
Args:
|
||||
@@ -144,18 +144,17 @@ class Overload:
|
||||
self.arguments = arguments
|
||||
|
||||
|
||||
def parse_pybind11_function_docstring(name: str, doc: str | None) -> list[Overload]:
|
||||
def parse_pybind11_function_docstring(e: type) -> list[Overload]:
|
||||
"""
|
||||
Parse the docstring of a Pybind11 function.
|
||||
Parse the docstring of the given element.
|
||||
|
||||
Args:
|
||||
name: Name of the function.
|
||||
doc: The docstring of the function generated by Pybind11.
|
||||
e: The function to "parse".
|
||||
|
||||
Returns:
|
||||
A list of overloads for the given function.
|
||||
"""
|
||||
lines = (doc or "").strip().split("\n")
|
||||
lines = (e.__doc__ or "").strip().split("\n")
|
||||
|
||||
signatures: list[str]
|
||||
if len(lines) == 1:
|
||||
@@ -163,7 +162,7 @@ def parse_pybind11_function_docstring(name: str, doc: str | None) -> list[Overlo
|
||||
else:
|
||||
signatures = []
|
||||
for line in lines:
|
||||
m = re.match(rf"^[0-9]+[.]\s+({name}.*)$", line)
|
||||
m = re.match(rf"^[0-9]+[.]\s+({e.__name__}.*)$", line)
|
||||
if m:
|
||||
signatures.append(m.group(1).strip())
|
||||
|
||||
@@ -175,16 +174,16 @@ def parse_pybind11_function_docstring(name: str, doc: str | None) -> list[Overlo
|
||||
signature = signature.replace("MOBase::", "mobase.").replace("::", ".")
|
||||
|
||||
try:
|
||||
return_type, arguments = parse_python_signature(signature, name)
|
||||
return_type, arguments = parse_python_signature(signature, e.__name__)
|
||||
except ValueError as err:
|
||||
raise ValueError(f"invalid signature: {name}, {doc}") from err
|
||||
raise ValueError(f"invalid signature: {e.__name__}, {e.__doc__}") from err
|
||||
overloads.append(Overload(return_type=return_type, arguments=arguments))
|
||||
|
||||
return overloads
|
||||
|
||||
|
||||
def make_functions(e: Callable[..., Any]) -> list[Function]:
|
||||
overloads = parse_pybind11_function_docstring(e.__name__, e.__doc__)
|
||||
def make_functions(e: type) -> list[Function]:
|
||||
overloads = parse_pybind11_function_docstring(e)
|
||||
|
||||
return [
|
||||
Function(
|
||||
@@ -296,9 +295,7 @@ def make_class(e: type, register: MobaseRegister) -> Class:
|
||||
|
||||
# otherwise we parse the docstring
|
||||
else:
|
||||
overloads = parse_pybind11_function_docstring(
|
||||
method.__name__, method.__doc__
|
||||
)
|
||||
overloads = parse_pybind11_function_docstring(method)
|
||||
|
||||
for overload in overloads:
|
||||
args = overload.arguments
|
||||
|
||||
@@ -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,20 +12,20 @@ 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, object] = OrderedDict()
|
||||
self.raw_objects: dict[str, type] = OrderedDict()
|
||||
self.objects = {}
|
||||
|
||||
def add_object(self, n: str, o: object, /) -> None:
|
||||
self.raw_objects[n] = o
|
||||
def add_object(self, name: str, object: type) -> None:
|
||||
self.raw_objects[name] = object
|
||||
|
||||
def make_object(
|
||||
self, name: str, e: object | None = None
|
||||
) -> Class | list[Function] | Constant | PyTyping:
|
||||
self, name: str, e: type | None = None
|
||||
) -> 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).
|
||||
|
||||
@@ -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.warning(
|
||||
LOGGER.warn(
|
||||
f"Mismatch number of arguments for function "
|
||||
f"mobase.{setting_name}."
|
||||
)
|
||||
@@ -243,7 +243,7 @@ class Settings:
|
||||
fn.deprecated = function_settings.deprecated
|
||||
|
||||
else:
|
||||
LOGGER.warning(
|
||||
LOGGER.warn(
|
||||
"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.warning("Class {} not found in settings.".format(cls.canonical_name))
|
||||
LOGGER.warn("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.warning(
|
||||
LOGGER.warn(
|
||||
"Missing type for property {}.{}.".format(
|
||||
cls.canonical_name, prop.name
|
||||
)
|
||||
@@ -320,7 +320,7 @@ class Settings:
|
||||
prop.doc = settings_property["desc"]
|
||||
|
||||
else:
|
||||
LOGGER.warning(
|
||||
LOGGER.warn(
|
||||
"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.warning(
|
||||
LOGGER.warn(
|
||||
"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.warning(
|
||||
LOGGER.warn(
|
||||
(
|
||||
"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.warning(
|
||||
LOGGER.warn(
|
||||
"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.warning(
|
||||
LOGGER.warn(
|
||||
"The following members were found in settings but not in the actual"
|
||||
" class {}: {}.".format(cls.canonical_name, ", ".join(missing_items))
|
||||
)
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
import logging
|
||||
from typing import Any, 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_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)
|
||||
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)
|
||||
|
||||
|
||||
class Writer:
|
||||
@@ -260,24 +256,13 @@ 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)
|
||||
|
||||
elif is_list_of(e, Function):
|
||||
elif is_list_of_functions(e):
|
||||
for fn in e:
|
||||
self.print_function(fn)
|
||||
|
||||
elif isinstance(e, PyTyping):
|
||||
self.print_typing(e)
|
||||
|
||||
else:
|
||||
self.print_constent(e)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,159 +0,0 @@
|
||||
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.
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user