mirror of
https://github.com/ModOrganizer2/pystubs-generation.git
synced 2026-07-27 14:07:13 -07:00
Compare commits
14
Commits
v2.5.0.dev16
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
886a50770f | ||
|
|
2ee1505336 | ||
|
|
92dec5b19a | ||
|
|
b33b8bceb1 | ||
|
|
dd80b67a0a | ||
|
|
8789b59f23 | ||
|
|
72c652daaa | ||
|
|
80a365f19a | ||
|
|
1b8d6840e2 | ||
|
|
d7c1ecd6f2 | ||
|
|
6a76dda9d7 | ||
|
|
0c807ad974 | ||
|
|
a3542ca1c4 | ||
|
|
d6760273a2 |
@@ -15,15 +15,16 @@ 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: |
|
||||
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: cp stubs/2.5.0/mobase-stubs/__init__.pyi docs/mobase.py
|
||||
run: |
|
||||
mkdir -p docs/src
|
||||
cp -r stubs/2.5.2/mobase-stubs docs/src/mobase
|
||||
- name: Build
|
||||
run: poetry run sphinx-build -b html docs/source docs/build
|
||||
env:
|
||||
@@ -10,15 +10,11 @@ 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: |
|
||||
poetry install
|
||||
- name: Lint
|
||||
run: |
|
||||
poetry run black src --check --diff
|
||||
poetry run isort -c src
|
||||
poetry run mypy src
|
||||
poetry run ruff src
|
||||
poetry run pyright src
|
||||
poetry run poe lint
|
||||
|
||||
@@ -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: |
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
poetry version ${TAG#v}
|
||||
poetry build
|
||||
- name: Store the distribution packages
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: python-package-distributions
|
||||
path: stubs/setup/dist/
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Download all the dists
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: python-package-distributions
|
||||
path: dist/
|
||||
|
||||
@@ -109,7 +109,6 @@ import mobase
|
||||
import mobase.widgets
|
||||
```
|
||||
|
||||
|
||||
**Note:** Most classes in `mobase` cannot be instantiated, so this is mostly intended
|
||||
for MO2 developers.
|
||||
|
||||
|
||||
+519
-45
File diff suppressed because it is too large
Load Diff
@@ -1,4 +0,0 @@
|
||||
sphinx-rtd-theme
|
||||
sphinx-autodoc-typehints
|
||||
sphinx-automodapi
|
||||
PyQt6
|
||||
+5
-1
@@ -27,8 +27,9 @@ 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.
|
||||
@@ -39,6 +40,9 @@ 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,7 +18,6 @@ This documentation is dedicated to writting MO2 **Python** plugins.
|
||||
plugin-types
|
||||
writing-plugins
|
||||
faq
|
||||
mobase
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
``mobase`` API
|
||||
==============
|
||||
|
||||
.. currentmodule:: mobase
|
||||
|
||||
.. automodapi:: mobase
|
||||
:no-inheritance-diagram:
|
||||
:no-heading:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
@@ -1,7 +0,0 @@
|
||||
mobase
|
||||
======
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
mobase
|
||||
@@ -64,10 +64,8 @@ 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
|
||||
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.
|
||||
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>`
|
||||
|
||||
As an example for a game feature take BSA invalidation: If the game requires BSA invalidation it will implement
|
||||
this feature.
|
||||
@@ -147,4 +145,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
+892
File diff suppressed because it is too large
Load Diff
+39
-44
@@ -1,61 +1,56 @@
|
||||
[tool.poetry]
|
||||
[project]
|
||||
name = "mo2-pystubs-generation"
|
||||
version = "0.1.0"
|
||||
description = ""
|
||||
authors = ["Holt59 <capelle.mikael@gmail.com>"]
|
||||
license = "MIT"
|
||||
version = "0.1.0"
|
||||
readme = "README.md"
|
||||
packages = [{ include = "mo2", from = "src" }]
|
||||
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)",
|
||||
]
|
||||
|
||||
[tool.poetry.scripts]
|
||||
[project.scripts]
|
||||
mo2-stubs-generator = "mo2.stubs.generator.__main__:main"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.11"
|
||||
pyqt6 = "^6.5.2"
|
||||
pyyaml = "^6.0.1"
|
||||
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
black = "^23.9.1"
|
||||
mypy = "^1.5.1"
|
||||
pyright = "^1.1.327"
|
||||
isort = "^5.12.0"
|
||||
ruff = "^0.0.290"
|
||||
flake8 = "^6.1.0"
|
||||
flake8-black = "^0.3.6"
|
||||
flake8-pyproject = "^1.2.3"
|
||||
types-pyyaml = "^6.0.12.11"
|
||||
|
||||
|
||||
[tool.poetry.group.doc.dependencies]
|
||||
sphinx-rtd-theme = "^1.3.0"
|
||||
sphinx-autodoc-typehints = "^1.24.0"
|
||||
sphinx-automodapi = "^0.16.0"
|
||||
sphinx = "^7.2.6"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
requires = ['poetry-core (>=2.0,<3.0)']
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
||||
[tool.flake8]
|
||||
max-line-length = 88
|
||||
extend-ignore = ["E203"]
|
||||
[tool.poetry]
|
||||
packages = [{ include = "mo2", from = "src" }]
|
||||
|
||||
[tool.isort]
|
||||
profile = "black"
|
||||
multi_line_output = 3
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
pyright = "^1.1.409"
|
||||
ruff = "^0.15.12"
|
||||
types-pyyaml = "^6.0.12.20260508"
|
||||
poethepoet = "^0.45.0"
|
||||
|
||||
[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"
|
||||
|
||||
[tool.poe.tasks]
|
||||
format-imports = "ruff check --select I src --fix"
|
||||
format-ruff = "ruff format src"
|
||||
format.sequence = ["format-imports", "format-ruff"]
|
||||
lint-ruff = "ruff check src"
|
||||
lint-ruff-format = "ruff format --check src"
|
||||
lint-pyright = "pyright src"
|
||||
lint.sequence = ["lint-ruff", "lint-ruff-format", "lint-pyright"]
|
||||
lint.ignore_fail = "return_non_zero"
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 88
|
||||
target-version = "py311"
|
||||
target-version = "py312"
|
||||
|
||||
[tool.mypy]
|
||||
warn_return_any = true
|
||||
warn_unused_configs = true
|
||||
namespace_packages = true
|
||||
[tool.ruff.lint]
|
||||
extend-select = ["B", "Q", "I"]
|
||||
|
||||
[tool.pyright]
|
||||
# reportMissingTypeStubs = true
|
||||
# reportUntypedBaseClass = false
|
||||
typeCheckingMode = "strict"
|
||||
reportMissingTypeStubs = true
|
||||
|
||||
@@ -1,25 +1,26 @@
|
||||
import argparse
|
||||
import inspect
|
||||
import logging
|
||||
import subprocess
|
||||
import types
|
||||
from collections.abc import Sequence
|
||||
from pathlib import Path
|
||||
from typing import Callable
|
||||
|
||||
import black
|
||||
import isort
|
||||
|
||||
from .loader import load_mobase
|
||||
from .mtypes import Class, PyTyping
|
||||
from .mtypes import Class, Constant, Enum, Function, PyTyping
|
||||
from .parser import is_enum
|
||||
from .register import MobaseRegister
|
||||
from .utils import Settings, clean_class
|
||||
from .writer import Writer, is_list_of_functions
|
||||
from .writer import Writer, is_list_of
|
||||
|
||||
LOGGER = logging.getLogger(__package__)
|
||||
|
||||
|
||||
def extract_objects(module: object, skips: list[str] = []) -> list[tuple[str, type]]:
|
||||
objects: list[tuple[str, type]] = []
|
||||
def extract_objects(
|
||||
module: object, skips: Sequence[str] = []
|
||||
) -> list[tuple[str, object]]:
|
||||
objects: list[tuple[str, object]] = []
|
||||
|
||||
assert hasattr(module, "__name__")
|
||||
module_name: str = module.__name__ # type: ignore
|
||||
@@ -56,12 +57,9 @@ def add_mobase_header(writer: Writer):
|
||||
"Callable",
|
||||
"Dict",
|
||||
"Iterator",
|
||||
"List",
|
||||
"Optional",
|
||||
"overload",
|
||||
"Sequence",
|
||||
"Set",
|
||||
"Tuple",
|
||||
"Type",
|
||||
"TypeVar",
|
||||
"Union",
|
||||
@@ -142,7 +140,7 @@ def main() -> None:
|
||||
}
|
||||
|
||||
# list of objects directly in mobase
|
||||
module_objects: dict[str, list[tuple[str, type]]] = {
|
||||
module_objects: dict[str, list[tuple[str, object]]] = {
|
||||
"mobase": extract_objects(
|
||||
mobase,
|
||||
[
|
||||
@@ -150,7 +148,7 @@ def main() -> None:
|
||||
"IPlugin",
|
||||
],
|
||||
),
|
||||
"mobase.widgets": extract_objects(getattr(mobase, "widgets")),
|
||||
"mobase.widgets": extract_objects(mobase.widgets), # type: ignore
|
||||
}
|
||||
|
||||
for name, objects in module_objects.items():
|
||||
@@ -180,10 +178,10 @@ 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):
|
||||
elif is_list_of(c, Function):
|
||||
settings.patch_functions(c)
|
||||
|
||||
else:
|
||||
@@ -200,6 +198,21 @@ 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)
|
||||
@@ -210,19 +223,28 @@ def main() -> None:
|
||||
|
||||
module_headers[name](writer)
|
||||
|
||||
for n, o in objects:
|
||||
# Get the corresponding object:
|
||||
c = register.get_object(n)
|
||||
|
||||
for c in stub_objects:
|
||||
writer.print_object(c)
|
||||
|
||||
black.format_file_in_place(
|
||||
output_folder.joinpath("__init__.pyi"),
|
||||
fast=False,
|
||||
mode=black.Mode(is_pyi=True),
|
||||
write_back=black.WriteBack.YES,
|
||||
subprocess.run(
|
||||
[
|
||||
"ruff",
|
||||
"format",
|
||||
"--silent",
|
||||
output_folder.joinpath("__init__.pyi").as_posix(),
|
||||
]
|
||||
)
|
||||
subprocess.run(
|
||||
[
|
||||
"ruff",
|
||||
"check",
|
||||
"--silent",
|
||||
"--select",
|
||||
"I",
|
||||
"--fix",
|
||||
output_folder.joinpath("__init__.pyi").as_posix(),
|
||||
]
|
||||
)
|
||||
isort.api.sort_file(output_folder.joinpath("__init__.pyi"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from collections.abc import Sequence
|
||||
from typing import Final, TypeVar
|
||||
|
||||
|
||||
@@ -164,7 +165,6 @@ class Argument:
|
||||
|
||||
|
||||
class Exception:
|
||||
|
||||
"""
|
||||
Small class representing exception that can be raised from functions.
|
||||
"""
|
||||
@@ -313,20 +313,20 @@ class Class:
|
||||
self,
|
||||
package: str,
|
||||
name: str,
|
||||
bases: list[Class],
|
||||
methods: list[Method],
|
||||
constants: list[Constant] = [],
|
||||
properties: list[Property] = [],
|
||||
inner_classes: list[Class] = [],
|
||||
bases: Sequence[Class],
|
||||
methods: Sequence[Method],
|
||||
constants: Sequence[Constant] = [],
|
||||
properties: Sequence[Property] = [],
|
||||
inner_classes: Sequence[Class] = [],
|
||||
doc: str = "",
|
||||
):
|
||||
self.package = package
|
||||
self.name = name
|
||||
self.bases = bases
|
||||
self.methods = methods
|
||||
self.properties = properties
|
||||
self.constants = constants
|
||||
self.inner_classes = inner_classes
|
||||
self.bases = list(bases)
|
||||
self.methods = list(methods)
|
||||
self.properties = list(properties)
|
||||
self.constants = list(constants)
|
||||
self.inner_classes = list(inner_classes)
|
||||
self.doc = ""
|
||||
self.abstract = False
|
||||
self.outer_class = None
|
||||
@@ -385,7 +385,6 @@ class Class:
|
||||
|
||||
|
||||
class PyClass(Class):
|
||||
|
||||
"""
|
||||
Class use to wrap Python class to be used as parent class for some classes
|
||||
in mobase.
|
||||
@@ -401,7 +400,6 @@ class PyClass(Class):
|
||||
|
||||
|
||||
class Enum(Class):
|
||||
|
||||
"""
|
||||
Class representing an enum.
|
||||
"""
|
||||
|
||||
@@ -4,7 +4,7 @@ import re
|
||||
import types
|
||||
from collections import OrderedDict, defaultdict
|
||||
from itertools import chain
|
||||
from typing import Any, Iterable, cast
|
||||
from typing import Any, Callable, 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: type) -> bool:
|
||||
def is_enum(e: object) -> bool:
|
||||
"""Check if the given class is an enumeration.
|
||||
|
||||
Args:
|
||||
@@ -134,7 +134,6 @@ def is_enum(e: type) -> bool:
|
||||
|
||||
|
||||
class Overload:
|
||||
|
||||
"""Small class to avoid mypy issues..."""
|
||||
|
||||
return_type: PyType
|
||||
@@ -145,17 +144,18 @@ class Overload:
|
||||
self.arguments = arguments
|
||||
|
||||
|
||||
def parse_pybind11_function_docstring(e: type) -> list[Overload]:
|
||||
def parse_pybind11_function_docstring(name: str, doc: str | None) -> list[Overload]:
|
||||
"""
|
||||
Parse the docstring of the given element.
|
||||
Parse the docstring of a Pybind11 function.
|
||||
|
||||
Args:
|
||||
e: The function to "parse".
|
||||
name: Name of the function.
|
||||
doc: The docstring of the function generated by Pybind11.
|
||||
|
||||
Returns:
|
||||
A list of overloads for the given function.
|
||||
"""
|
||||
lines = (e.__doc__ or "").strip().split("\n")
|
||||
lines = (doc or "").strip().split("\n")
|
||||
|
||||
signatures: list[str]
|
||||
if len(lines) == 1:
|
||||
@@ -163,7 +163,7 @@ def parse_pybind11_function_docstring(e: type) -> list[Overload]:
|
||||
else:
|
||||
signatures = []
|
||||
for line in lines:
|
||||
m = re.match(rf"^[0-9]+[.]\s+({e.__name__}.*)$", line)
|
||||
m = re.match(rf"^[0-9]+[.]\s+({name}.*)$", line)
|
||||
if m:
|
||||
signatures.append(m.group(1).strip())
|
||||
|
||||
@@ -175,16 +175,16 @@ def parse_pybind11_function_docstring(e: type) -> list[Overload]:
|
||||
signature = signature.replace("MOBase::", "mobase.").replace("::", ".")
|
||||
|
||||
try:
|
||||
return_type, arguments = parse_python_signature(signature, e.__name__)
|
||||
except ValueError:
|
||||
raise ValueError(f"invalid signature: {e.__name__}, {e.__doc__}")
|
||||
return_type, arguments = parse_python_signature(signature, name)
|
||||
except ValueError as err:
|
||||
raise ValueError(f"invalid signature: {name}, {doc}") from err
|
||||
overloads.append(Overload(return_type=return_type, arguments=arguments))
|
||||
|
||||
return overloads
|
||||
|
||||
|
||||
def make_functions(e: type) -> list[Function]:
|
||||
overloads = parse_pybind11_function_docstring(e)
|
||||
def make_functions(e: Callable[..., Any]) -> list[Function]:
|
||||
overloads = parse_pybind11_function_docstring(e.__name__, e.__doc__)
|
||||
|
||||
return [
|
||||
Function(
|
||||
@@ -221,7 +221,8 @@ def make_class(e: type, register: MobaseRegister) -> Class:
|
||||
|
||||
# This contains ALL the parent classes, not the direct ones:
|
||||
base_classes: list[Class] = [
|
||||
register.make_object(name) for name in base_classes_s # type: ignore
|
||||
register.make_object(name)
|
||||
for name in base_classes_s # type: ignore
|
||||
]
|
||||
|
||||
# retrieve all the attributes that are not in a base class
|
||||
@@ -295,7 +296,9 @@ def make_class(e: type, register: MobaseRegister) -> Class:
|
||||
|
||||
# otherwise we parse the docstring
|
||||
else:
|
||||
overloads = parse_pybind11_function_docstring(method)
|
||||
overloads = parse_pybind11_function_docstring(
|
||||
method.__name__, method.__doc__
|
||||
)
|
||||
|
||||
for overload in overloads:
|
||||
args = overload.arguments
|
||||
|
||||
@@ -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,20 +12,20 @@ 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()
|
||||
self.raw_objects: dict[str, object] = OrderedDict()
|
||||
self.objects = {}
|
||||
|
||||
def add_object(self, name: str, object: type) -> None:
|
||||
self.raw_objects[name] = object
|
||||
def add_object(self, n: str, o: object, /) -> None:
|
||||
self.raw_objects[n] = o
|
||||
|
||||
def make_object(
|
||||
self, name: str, e: type | None = None
|
||||
) -> Class | list[Function] | PyTyping:
|
||||
self, name: str, e: object | None = None
|
||||
) -> 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).
|
||||
|
||||
@@ -215,12 +215,14 @@ class Settings:
|
||||
# Check the args:
|
||||
if function_settings.args is not None:
|
||||
if len(function_settings.args) != len(fn.args):
|
||||
LOGGER.warn(
|
||||
LOGGER.warning(
|
||||
f"Mismatch number of arguments for function "
|
||||
f"mobase.{setting_name}."
|
||||
)
|
||||
|
||||
for setting_arg, method_arg in zip(function_settings.args, fn.args):
|
||||
for setting_arg, method_arg in zip(
|
||||
function_settings.args, fn.args, strict=True
|
||||
):
|
||||
method_arg.doc = setting_arg.doc
|
||||
if not setting_arg.type.is_none():
|
||||
method_arg.type = setting_arg.type
|
||||
@@ -241,7 +243,7 @@ class Settings:
|
||||
fn.deprecated = function_settings.deprecated
|
||||
|
||||
else:
|
||||
LOGGER.warn(
|
||||
LOGGER.warning(
|
||||
"Missing settings for function mobase.{}.".format(setting_name)
|
||||
)
|
||||
|
||||
@@ -266,7 +268,7 @@ class Settings:
|
||||
class_settings = self._get_class_settings(cls.canonical_name)
|
||||
|
||||
if class_settings is None:
|
||||
LOGGER.warn("Class {} not found in settings.".format(cls.canonical_name))
|
||||
LOGGER.warning("Class {} not found in settings.".format(cls.canonical_name))
|
||||
return
|
||||
|
||||
if "__doc__" in class_settings and class_settings["__doc__"] is not None:
|
||||
@@ -304,7 +306,7 @@ class Settings:
|
||||
if "type" in settings_property:
|
||||
prop.type = PyType(settings_property["type"])
|
||||
else:
|
||||
LOGGER.warn(
|
||||
LOGGER.warning(
|
||||
"Missing type for property {}.{}.".format(
|
||||
cls.canonical_name, prop.name
|
||||
)
|
||||
@@ -318,7 +320,7 @@ class Settings:
|
||||
prop.doc = settings_property["desc"]
|
||||
|
||||
else:
|
||||
LOGGER.warn(
|
||||
LOGGER.warning(
|
||||
"Missing description for property {}.{}.".format(
|
||||
cls.canonical_name, prop.name
|
||||
)
|
||||
@@ -364,21 +366,21 @@ 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.warn(
|
||||
LOGGER.warning(
|
||||
"Mismatch number of arguments for method {}.{}.".format(
|
||||
cls.canonical_name, settings_name
|
||||
)
|
||||
)
|
||||
|
||||
for settings_arg, method_arg in zip(
|
||||
function_settings.args, method_arguments
|
||||
function_settings.args, method_arguments, strict=True
|
||||
):
|
||||
method_arg.doc = settings_arg.doc
|
||||
if (
|
||||
not method_arg.name.startswith("arg")
|
||||
and method_arg.name != settings_arg.name
|
||||
):
|
||||
LOGGER.warn(
|
||||
LOGGER.warning(
|
||||
(
|
||||
"Mismatch argument name for method {}.{}: "
|
||||
"{} {}, using {}."
|
||||
@@ -427,7 +429,7 @@ class Settings:
|
||||
|
||||
if n_overloads > 0 and missing_settings:
|
||||
for settings_name in missing_settings:
|
||||
LOGGER.warn(
|
||||
LOGGER.warning(
|
||||
"Missing settings for method {}.{}.".format(
|
||||
cls.canonical_name, settings_name
|
||||
)
|
||||
@@ -445,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.warn(
|
||||
LOGGER.warning(
|
||||
"The following members were found in settings but not in the actual"
|
||||
" class {}: {}.".format(cls.canonical_name, ", ".join(missing_items))
|
||||
)
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
import logging
|
||||
from typing import Any, Iterable, TextIO, TypeGuard
|
||||
from typing import Any, 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]]:
|
||||
if not isinstance(e, list):
|
||||
return False
|
||||
return all(isinstance(x, Function) for x in e)
|
||||
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)
|
||||
|
||||
|
||||
class Writer:
|
||||
@@ -163,7 +167,7 @@ class Writer:
|
||||
if not prop.is_read_only():
|
||||
self._print("{}@{}.setter".format(indent, prop.name))
|
||||
self._print(
|
||||
"{}def {}(self, arg0: {}): ...".format(
|
||||
"{}def {}(self, arg0: {}) -> None: ...".format(
|
||||
indent, prop.name, self._fix_typing(prop.type.typing())
|
||||
)
|
||||
)
|
||||
@@ -256,13 +260,24 @@ 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)
|
||||
|
||||
elif is_list_of_functions(e):
|
||||
elif is_list_of(e, Function):
|
||||
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
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user