Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
steps:
- uses: actions/setup-python@v5
with:
python-version: "3.12"
python-version: "3.13"

- name: Set environmental variables
shell: bash
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/linters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.12
python-version: 3.13
- uses: abatilo/actions-poetry@v2
- name: Install
run: |
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Download the archive for your MO2 version and extract it directly into your MO2

- Mod Organizer **2.3.2**: [Download](https://github.com/ModOrganizer2/modorganizer-basic_games/releases/download/v0.0.3/basic_games-0.0.3.zip)
and extract in your `plugins/` folder (see below).
- Mod Organizer **2.4**: Basic games is included in Mod Organizer 2.4.
- Mod Organizer **2.4 and later**: Basic games is already included.
- If you want to use new game plugins that have not been included in the
release, [download the latest archive](https://github.com/ModOrganizer2/modorganizer-basic_games/archive/master.zip) and extract the files
in the existing `basic_games` folder, overwriting existing files.
Expand Down Expand Up @@ -217,15 +217,15 @@ Game IDs can be found here:

We recommend using a dedicated Python environment to write a new basic game plugins.

1. Install the required version of Python --- Currently Python 3.11 (MO2 2.5).
1. Install the required version of Python --- Currently Python 3.13 (MO2 2.6).
2. Remove the repository at `${MO2_INSTALL}/plugins/basic_games`.
3. Clone this repository at the location of the old plugin (
`${MO2_INSTALL}/plugins/basic_games`).
4. Place yourself inside the cloned folder and:

```bash
# create a virtual environment (recommended)
py -3.11 -m venv .\venv
py -3.13 -m venv .\venv
.\venv\scripts\Activate.ps1

# "install" poetry and the development package
Expand Down
13 changes: 3 additions & 10 deletions games/stalkeranomaly/XRSave.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
import struct
from datetime import datetime
from pathlib import Path
from typing import BinaryIO, Optional, cast
from typing import BinaryIO, Optional

import lzokay # pyright: ignore[reportMissingTypeStubs]
import lzokay

from .XRIO import XRReader, XRStream
from .XRObject import XRCreatureActor, XRFlag
Expand Down Expand Up @@ -108,14 +108,7 @@ def readFile(self, file: BinaryIO) -> Optional[XRStream]:
if (start == -1) and (version >= 6):
file.seek(12)
data = file.read(size - 12)
return XRStream(
cast(
bytes,
lzokay.decompress( # pyright: ignore[reportUnknownMemberType]
data, source
),
)
)
return XRStream(lzokay.decompress(data, source))

return None

Expand Down
6 changes: 3 additions & 3 deletions plugin-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
psutil==5.8.0
psutil==7.2.2
vdf==3.4
lzokay==1.1.5
pyyaml==6.0.2
lzokay==2.1.0
pyyaml==6.0.3
340 changes: 195 additions & 145 deletions poetry.lock

Large diffs are not rendered by default.

26 changes: 14 additions & 12 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,25 @@ description = ""
authors = []
license = "MIT"
readme = "README.md"
requires-python = ">=3.12,<4.0"
requires-python = ">=3.13,<4.0"
dynamic = ["dependencies"]

[tool.poetry]
package-mode = false

[tool.poetry.dependencies]
psutil = "^5.8.0"
vdf = "3.4"
lzokay = "1.1.5"
pyqt6 = "6.7.0"
pyyaml = "^6.0.2"
psutil = "^7.2.2"
vdf = "^3.4"
lzokay = "^2.1.0"
pyqt6 = "6.11.0"
pyyaml = "^6.0.3"

[tool.poetry.group.dev.dependencies]
mobase-stubs = "^2.5.2"
pyqt6 = "^6.7.0"
pyright = "^1.1.402"
ruff = "^0.12.2"
types-psutil = "<6"
poethepoet = "^0.36.0"
pyright = "^1.1.409"
ruff = "^0.15.14"
types-psutil = "^7.2.2.20260518"
poethepoet = "^0.46.0"

[build-system]
requires = ["poetry-core (>=2.0)"]
Expand All @@ -42,6 +41,9 @@ lint-pyright = "pyright ."
lint.sequence = ["lint-ruff", "lint-ruff-format", "lint-pyright"]
lint.ignore_fail = "return_non_zero"

[tool.ruff]
extend-exclude = ["typings"]

[tool.ruff.lint]
extend-select = ["B", "Q", "I"]

Expand All @@ -52,7 +54,7 @@ extend-immutable-calls = ["PyQt6.QtCore.QModelIndex"]
known-first-party = ["mobase"]

[tool.pyright]
exclude = ["lib", "**/.*", "venv"]
exclude = ["lib", "**/.*", "venv", "typings"]
typeCheckingMode = "strict"
reportMissingTypeStubs = true
reportMissingModuleSource = false
Expand Down
149 changes: 149 additions & 0 deletions typings/PyQt6/QAxContainer.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# The PEP 484 type hints stub file for the QAxContainer module.
#
# Generated by SIP 6.15.3
#
# Copyright (c) 2026 Riverbank Computing Limited <info@riverbankcomputing.com>
#
# This file is part of PyQt6.
#
# This file may be used under the terms of the GNU General Public License
# version 3.0 as published by the Free Software Foundation and appearing in
# the file LICENSE included in the packaging of this file. Please review the
# following information to ensure the GNU General Public License version 3.0
# requirements will be met: http://www.gnu.org/copyleft/gpl.html.
#
# If you do not wish to use this file under the terms of the GPL version 3.0
# then you may purchase a commercial license. For more information contact
# info@riverbankcomputing.com.
#
# This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
# WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.


import collections, re, typing

try:
from warnings import deprecated
except ImportError:
pass

import PyQt6.sip

from PyQt6 import QtCore
from PyQt6 import QtGui
from PyQt6 import QtWidgets

# Support for QDate, QDateTime and QTime.
import datetime

# Convenient type aliases.
PYQT_SIGNAL = typing.Union[QtCore.pyqtSignal, QtCore.pyqtBoundSignal]
PYQT_SLOT = typing.Union[collections.abc.Callable[..., Any], QtCore.pyqtBoundSignal]


class QAxBase(PyQt6.sip.simplewrapper):

@typing.overload
def __init__(self) -> None: ...
@typing.overload
def __init__(self, a0: 'QAxBase') -> None: ...

def setClassContext(self, classContext: int) -> None: ...
def classContext(self) -> int: ...
def disableEventSink(self) -> None: ...
def disableClassInfo(self) -> None: ...
def disableMetaObject(self) -> None: ...
def setControl(self, a0: str|None) -> bool: ...
def clear(self) -> None: ...
def asVariant(self) -> typing.Any: ...
def verbs(self) -> list[str]: ...
def isNull(self) -> bool: ...
def setPropertyWritable(self, a0: str, a1: bool) -> None: ...
def propertyWritable(self, a0: str) -> bool: ...
def generateDocumentation(self) -> str: ...
def setPropertyBag(self, a0: dict[str|None, typing.Any]) -> None: ...
def propertyBag(self) -> dict[str, typing.Any]: ...
@typing.overload
def querySubObject(self, a0: str, a1: collections.abc.Iterable[typing.Any]) -> 'QAxObject|None': ...
@typing.overload
def querySubObject(self, a0: str, value1: typing.Any = ..., value2: typing.Any = ..., value3: typing.Any = ..., value4: typing.Any = ..., value5: typing.Any = ..., value6: typing.Any = ..., value7: typing.Any = ..., value8: typing.Any = ...) -> 'QAxObject|None': ...
@typing.overload
def dynamicCall(self, a0: str, a1: collections.abc.Iterable[typing.Any]) -> typing.Any: ...
@typing.overload
def dynamicCall(self, a0: str, value1: typing.Any = ..., value2: typing.Any = ..., value3: typing.Any = ..., value4: typing.Any = ..., value5: typing.Any = ..., value6: typing.Any = ..., value7: typing.Any = ..., value8: typing.Any = ...) -> typing.Any: ...
def control(self) -> str: ...


class QAxObjectInterface(PyQt6.sip.simplewrapper):

@typing.overload
def __init__(self) -> None: ...
@typing.overload
def __init__(self, a0: 'QAxObjectInterface') -> None: ...

def resetControl(self) -> None: ...
def setControl(self, c: str|None) -> bool: ...
def control(self) -> str: ...
def setClassContext(self, classContext: int) -> None: ...
def classContext(self) -> int: ...


class QAxBaseObject(QtCore.QObject, QAxObjectInterface):

def __init__(self) -> None: ...

signal: typing.ClassVar[QtCore.pyqtSignal]
propertyChanged: typing.ClassVar[QtCore.pyqtSignal]
exception: typing.ClassVar[QtCore.pyqtSignal]


class QAxObject(QAxBaseObject, QAxBase):

@typing.overload
def __init__(self, parent: QtCore.QObject|None = ...) -> None: ...
@typing.overload
def __init__(self, a0: str|None, parent: QtCore.QObject|None = ...) -> None: ...

def connectNotify(self, a0: QtCore.QMetaMethod) -> None: ...
def doVerb(self, a0: str|None) -> bool: ...
def clear(self) -> None: ...
def resetControl(self) -> None: ...
def setControl(self, c: str|None) -> bool: ...
def control(self) -> str: ...
def setClassContext(self, classContext: int) -> None: ...
def classContext(self) -> int: ...


class QAxBaseWidget(QtWidgets.QWidget, QAxObjectInterface):

def __init__(self) -> None: ...

signal: typing.ClassVar[QtCore.pyqtSignal]
propertyChanged: typing.ClassVar[QtCore.pyqtSignal]
exception: typing.ClassVar[QtCore.pyqtSignal]


class QAxWidget(QAxBaseWidget, QAxBase):

@typing.overload
def __init__(self, parent: QtWidgets.QWidget|None = ..., flags: QtCore.Qt.WindowType = ...) -> None: ...
@typing.overload
def __init__(self, a0: str|None, parent: QtWidgets.QWidget|None = ..., flags: QtCore.Qt.WindowType = ...) -> None: ...

def connectNotify(self, a0: QtCore.QMetaMethod) -> None: ...
def translateKeyEvent(self, a0: int, a1: int) -> bool: ...
def resizeEvent(self, a0: QtGui.QResizeEvent|None) -> None: ...
def changeEvent(self, a0: QtCore.QEvent|None) -> None: ...
@typing.overload
def createHostWindow(self, a0: bool) -> bool: ...
@typing.overload
def createHostWindow(self, a0: bool, a1: QtCore.QByteArray|bytes|bytearray|memoryview) -> bool: ...
def minimumSizeHint(self) -> QtCore.QSize: ...
def sizeHint(self) -> QtCore.QSize: ...
def doVerb(self, a0: str|None) -> bool: ...
def clear(self) -> None: ...
def resetControl(self) -> None: ...
def setControl(self, c: str|None) -> bool: ...
def control(self) -> str: ...
def setClassContext(self, classContext: int) -> None: ...
def classContext(self) -> int: ...
Loading
Loading