From ce1ad582c160191b966bbf5aeab28f270c2a47fc Mon Sep 17 00:00:00 2001 From: repokit Date: Fri, 19 Jun 2026 20:30:46 +0700 Subject: [PATCH 01/19] chore: [repokit] add pyproject.toml --- pyproject.toml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 pyproject.toml diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..b6668a6 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,30 @@ +[build-system] +requires = ["setuptools>=77.0.3"] +build-backend = "setuptools.build_meta" + +[project] +name = "pyvko" +version = "0.1.0" +description = "" +readme = "README.md" +license = "MIT" +authors = [{ name = "Igor Djachenko" }] +requires-python = ">=3.10" + +[project.optional-dependencies] +test = ["pytest"] +release = ["build", "python-semantic-release"] + +[project.urls] +Homepage = "https://github.com/djachenko/pyvko" +Repository = "https://github.com/djachenko/pyvko" +Issues = "https://github.com/djachenko/pyvko/issues" + +[tool.semantic_release] +version_toml = ["pyproject.toml:project.version"] +branch = "master" +build_command = "pip install build && python -m build" +changelog_file = "CHANGELOG.md" +commit_message = "chore(release): v{version} [no ci]" +major_on_zero = false +allow_zero_version = true From c795b9e2b92bd6f0df68632029d1330166b3abc8 Mon Sep 17 00:00:00 2001 From: repokit Date: Fri, 19 Jun 2026 20:30:49 +0700 Subject: [PATCH 02/19] chore: [repokit] save language config --- .repokit | 1 + 1 file changed, 1 insertion(+) create mode 100644 .repokit diff --git a/.repokit b/.repokit new file mode 100644 index 0000000..416bc8d --- /dev/null +++ b/.repokit @@ -0,0 +1 @@ +language=python From 0aa7ff99222c69f98d61adefdaabf1ab91b88f77 Mon Sep 17 00:00:00 2001 From: repokit Date: Sat, 20 Jun 2026 02:36:14 +0700 Subject: [PATCH 03/19] chore: [repokit] update ci workflows --- .github/workflows/integration.yml | 40 +++++++++++++++++++++++++++++++ .github/workflows/release.yml | 40 +++++++++++++++++++++++++++++++ .github/workflows/tests.yml | 11 +++++++++ 3 files changed, 91 insertions(+) create mode 100644 .github/workflows/integration.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/tests.yml diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml new file mode 100644 index 0000000..5145d22 --- /dev/null +++ b/.github/workflows/integration.yml @@ -0,0 +1,40 @@ +name: Integration + +on: + pull_request: + branches: + - master + +jobs: + integration: + uses: djachenko/repokit/.github/workflows/python-integration.yml@0.4 + secrets: inherit + + publish: + needs: integration + runs-on: ubuntu-latest + permissions: + id-token: write + + steps: + - uses: actions/download-artifact@v8 + with: + name: dist + path: dist/ + + - name: Publish to TestPyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: https://test.pypi.org/legacy/ + skip-existing: true + + - name: Smoke test + run: | + PACKAGE=$(ls dist/*.whl | head -1 | xargs basename | sed 's/-[0-9].*//') + VERSION=$(ls dist/*.tar.gz | sed 's/.*-\(.*\)\.tar\.gz/\1/') + for i in {1..5}; do + pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ $PACKAGE==$VERSION && break + echo "Attempt $i failed, retrying in 10s..." + sleep 10 + done + $PACKAGE --help diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..b2fe47b --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,40 @@ +name: Release + +on: + push: + branches: + - master + +jobs: + release: + uses: djachenko/repokit/.github/workflows/python-release.yml@0.4 + secrets: inherit + permissions: + contents: write + + publish: + needs: release + if: needs.release.outputs.released == 'true' + runs-on: ubuntu-latest + permissions: + id-token: write + + steps: + - uses: actions/download-artifact@v8 + with: + name: dist + path: dist/ + + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + + - name: Smoke test + run: | + PACKAGE=$(ls dist/*.whl | head -1 | xargs basename | sed 's/-[0-9].*//') + VERSION=$(ls dist/*.tar.gz | sed 's/.*-\(.*\)\.tar\.gz/\1/') + for i in {1..5}; do + pip install $PACKAGE==$VERSION && break + echo "Attempt $i failed, retrying in 10s..." + sleep 10 + done + $PACKAGE --help diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..97d6abf --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,11 @@ +name: Tests + +on: + push: + branches: + - '**' + +jobs: + tests: + uses: djachenko/repokit/.github/workflows/python-tests.yml@0.4 + secrets: inherit From 3a57a9f8cce872d30f8ae0844d8f82bb59382453 Mon Sep 17 00:00:00 2001 From: repokit Date: Sun, 21 Jun 2026 16:23:33 +0700 Subject: [PATCH 04/19] chore: [repokit] update ci workflows --- .github/workflows/integration.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/tests.yml | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 5145d22..17e5849 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -7,7 +7,7 @@ on: jobs: integration: - uses: djachenko/repokit/.github/workflows/python-integration.yml@0.4 + uses: djachenko/repokit/.github/workflows/python-integration.yml@0.5 secrets: inherit publish: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b2fe47b..2cac989 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,7 +7,7 @@ on: jobs: release: - uses: djachenko/repokit/.github/workflows/python-release.yml@0.4 + uses: djachenko/repokit/.github/workflows/python-release.yml@0.5 secrets: inherit permissions: contents: write diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 97d6abf..85d3924 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -4,8 +4,10 @@ on: push: branches: - '**' + tags-ignore: + - '**' jobs: tests: - uses: djachenko/repokit/.github/workflows/python-tests.yml@0.4 + uses: djachenko/repokit/.github/workflows/python-tests.yml@0.5 secrets: inherit From a57c1a35be16b6b707edccf316de0c108fd63648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=B3=D0=BE=D1=80=D1=8C=20=D0=94=D1=8C=D1=8F=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=BA=D0=BE?= Date: Sun, 21 Jun 2026 16:30:26 +0700 Subject: [PATCH 05/19] fix: Fixed repokit dependencies --- .gitignore | 1 + .repokit | 1 - pyproject.toml | 11 +++++++++-- 3 files changed, 10 insertions(+), 3 deletions(-) delete mode 100644 .repokit diff --git a/.gitignore b/.gitignore index b8e48de..4a0419f 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ pyvko\.egg-info/ test_photos/ build/ +.repokit diff --git a/.repokit b/.repokit deleted file mode 100644 index 416bc8d..0000000 --- a/.repokit +++ /dev/null @@ -1 +0,0 @@ -language=python diff --git a/pyproject.toml b/pyproject.toml index b6668a6..970f936 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,8 +12,15 @@ authors = [{ name = "Igor Djachenko" }] requires-python = ">=3.10" [project.optional-dependencies] -test = ["pytest"] -release = ["build", "python-semantic-release"] +test = [ + "pytest", + "ruff", + "mypy", +] +release = [ + "build", + "python-semantic-release", +] [project.urls] Homepage = "https://github.com/djachenko/pyvko" From c7d91703b0d0afab095177cbc1acb85c05a64c2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=B3=D0=BE=D1=80=D1=8C=20=D0=94=D1=8C=D1=8F=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=BA=D0=BE?= Date: Sun, 21 Jun 2026 16:36:24 +0700 Subject: [PATCH 06/19] fix: Fixed ruff errors --- pyvko/aspects/groups.py | 4 +--- pyvko/aspects/reposts.py | 2 -- pyvko/entities/user.py | 4 +++- pyvko/pyvko_runner.py | 24 +++++++++++------------- 4 files changed, 15 insertions(+), 19 deletions(-) diff --git a/pyvko/aspects/groups.py b/pyvko/aspects/groups.py index c319d06..ad99984 100644 --- a/pyvko/aspects/groups.py +++ b/pyvko/aspects/groups.py @@ -1,5 +1,4 @@ from abc import ABC -from tokenize import group from typing import Dict, List from vk import API @@ -8,6 +7,7 @@ from pyvko.aspects.albums import Albums from pyvko.aspects.events import Events, Event from pyvko.aspects.posts import Posts +from pyvko.entities.user import User from pyvko.shared.utils import get_all @@ -43,8 +43,6 @@ def url(self) -> str: return self.__url def get_members(self) -> List['User']: - from pyvko.entities.user import User - parameters = { "group_id": self.id, "sort": "time_desc", diff --git a/pyvko/aspects/reposts.py b/pyvko/aspects/reposts.py index 8ba483c..cb0ae52 100644 --- a/pyvko/aspects/reposts.py +++ b/pyvko/aspects/reposts.py @@ -39,8 +39,6 @@ def get_reposters(self): groups = response["groups"] groups = [group for group in groups if group["id"] not in self.__ignore_groups] - a = 7 - def get_request(self, parameters: Dict = None) -> Dict: return super().get_request() | { "owner_id": self.owner_id, diff --git a/pyvko/entities/user.py b/pyvko/entities/user.py index fc92233..9484ccb 100644 --- a/pyvko/entities/user.py +++ b/pyvko/entities/user.py @@ -68,4 +68,6 @@ def events(self) -> List[Event]: response = list(get_all(request, self.api.groups.get)) - events = [Event(self.api, event, None) for event in response] \ No newline at end of file + events = [Event(self.api, event, None) for event in response] + + return events \ No newline at end of file diff --git a/pyvko/pyvko_runner.py b/pyvko/pyvko_runner.py index 23dd1ac..adfdda4 100644 --- a/pyvko/pyvko_runner.py +++ b/pyvko/pyvko_runner.py @@ -1,4 +1,3 @@ -import json import random from datetime import timedelta, datetime, date, time from pathlib import Path @@ -6,8 +5,8 @@ from pyvko.aspects.albums import Album from pyvko.aspects.events import Event -from pyvko.config.config import Config from pyvko.aspects.posts import Post +from pyvko.config.config import Config from pyvko.pyvko_main import Pyvko @@ -44,6 +43,8 @@ def create_scheduled_posts(): date=post_datetime ) + print(post) + # test_group.add_post(post) @@ -81,12 +82,12 @@ def test_posting_album(pyvko: Pyvko): photoset_path = Path("C:/Users/justin/photos/stages/stage2.develop/20.12.05.miss_stc/progress/") - post_config_path = photoset_path / "post_config.json" + # post_config_path = photoset_path / "post_config.json" - with post_config_path.open() as post_config_file: - post_config = json.load(post_config_file) + # with post_config_path.open() as post_config_file: + # post_config = json.load(post_config_file) - cover_name = post_config["cover"] + # cover_name = post_config["cover"] photos_folder = photoset_path / "justin" photo_paths = list(photos_folder.iterdir())[:10] @@ -114,12 +115,11 @@ def test_posting_album(pyvko: Pyvko): def get_all_members(pyvko: Pyvko): - group = pyvko.get_by_url("test") + pass + # group = pyvko.get_by_url("test") - members = group.get_members() - posts = group.get_posts() - - a = 7 + # members = group.get_members() + # posts = group.get_posts() def create_event(pyvko: Pyvko): @@ -159,8 +159,6 @@ def main(): append_album(pyvko) - a = 7 - if __name__ == '__main__': main() From b9f4da045e4c026794a467d9099b665cb7cfa7f1 Mon Sep 17 00:00:00 2001 From: Igor Djachenko Date: Mon, 22 Jun 2026 01:52:40 +0700 Subject: [PATCH 07/19] =?UTF-8?q?fix:=20groups=20imports=20=E2=80=94=20rem?= =?UTF-8?q?ove=20tokenize=20shim,=20add=20Any/TYPE=5FCHECKING?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyvko/aspects/groups.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pyvko/aspects/groups.py b/pyvko/aspects/groups.py index dd991b6..d2bcf3a 100644 --- a/pyvko/aspects/groups.py +++ b/pyvko/aspects/groups.py @@ -1,6 +1,5 @@ from abc import ABC -from tokenize import group -from typing import Dict, List +from typing import Any, Dict, List, TYPE_CHECKING if TYPE_CHECKING: from pyvko.entities.user import User @@ -55,9 +54,9 @@ def get_members(self) -> List['User']: parameters = self.get_request(parameters) - users_descriptions = get_all(parameters, self.api.groups.getMembers) + users_descriptions = get_all(parameters, self.new_api.groups.getMembers) - users = [User(api=self.api, user_object=description) for description in users_descriptions] + users = [User(api=self.new_api, user_object=description) for description in users_descriptions] return users From 19374cac033132744652691f2f561989e7b6c35b Mon Sep 17 00:00:00 2001 From: Igor Djachenko Date: Mon, 22 Jun 2026 01:52:46 +0700 Subject: [PATCH 08/19] refactor: add api fail-fast property to ApiMixin and ApiBased --- pyvko/api_based.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pyvko/api_based.py b/pyvko/api_based.py index 745633e..857e1d5 100644 --- a/pyvko/api_based.py +++ b/pyvko/api_based.py @@ -15,6 +15,10 @@ class ApiMixin(RequestRoot, ABC): def new_api(self) -> VkApi: pass + @property + def api(self) -> Any: + assert False, f"{type(self).__name__} still uses unmigrated api — switch to new_api" + @abstractmethod def get_request(self, parameters: Dict = None) -> Dict: return super().get_request(parameters) @@ -32,6 +36,10 @@ def __init__(self, api: Any) -> None: def new_api(self) -> Any: return self.__api + @property + def api(self) -> Any: + assert False, f"{type(self).__name__} still uses unmigrated api — switch to new_api" + @staticmethod def __get_default_object(): return { From c5f8054d57e57ad003f5cd40d7f7af96653d59b7 Mon Sep 17 00:00:00 2001 From: Igor Djachenko Date: Mon, 22 Jun 2026 01:52:49 +0700 Subject: [PATCH 09/19] fix: remove API=Any shims, replace api: API type hints with Any --- pyvko/aspects/albums.py | 1 - pyvko/aspects/comments.py | 6 ++---- pyvko/aspects/likes.py | 2 +- pyvko/aspects/posts.py | 4 +--- pyvko/attachment/attachment_parser.py | 8 +++----- pyvko/attachment/photo.py | 2 +- pyvko/entities/user.py | 12 +++++------- 7 files changed, 13 insertions(+), 22 deletions(-) diff --git a/pyvko/aspects/albums.py b/pyvko/aspects/albums.py index d0eb1ef..cac784c 100644 --- a/pyvko/aspects/albums.py +++ b/pyvko/aspects/albums.py @@ -2,7 +2,6 @@ from pathlib import Path from typing import Any, Dict, List -from vk_api import VkApi from pyvko.api_based import ApiMixin, ApiBased from pyvko.attachment.attachment import Attachment diff --git a/pyvko/aspects/comments.py b/pyvko/aspects/comments.py index 764c2e7..76cb463 100644 --- a/pyvko/aspects/comments.py +++ b/pyvko/aspects/comments.py @@ -3,8 +3,6 @@ from datetime import datetime from typing import List, Dict, Any -API = Any - from pyvko.api_based import ApiMixin, ApiBased from pyvko.attachment.attachment import Attachment from pyvko.attachment.attachment_parser import AttachmentParser @@ -61,7 +59,7 @@ def date(self) -> datetime: def __init__( self, - api: API, + api: Any, comment_id: int, owner_id: int, date: datetime, @@ -77,7 +75,7 @@ def __init__( self.__attachments = attachments @classmethod - def from_api_object(cls, api_object: Dict, api: API) -> 'Comment': + def from_api_object(cls, api_object: Dict, api: Any) -> 'Comment': if "attachments" in api_object: parser = AttachmentParser.shared() diff --git a/pyvko/aspects/likes.py b/pyvko/aspects/likes.py index 5c84ef4..124bb2a 100644 --- a/pyvko/aspects/likes.py +++ b/pyvko/aspects/likes.py @@ -56,7 +56,7 @@ def like(self) -> None: self.api.likes.add(**request) - def get_request(self, parameters: Dict = None) -> Dict: + def get_request(self, parameters: Dict | None = None) -> Dict: return super().get_request() | { "type": self.like_object_type, "owner_id": self.owner_id, diff --git a/pyvko/aspects/posts.py b/pyvko/aspects/posts.py index e6faec5..fd80813 100644 --- a/pyvko/aspects/posts.py +++ b/pyvko/aspects/posts.py @@ -5,8 +5,6 @@ from pathlib import Path from typing import List, Dict, Any -API = Any - from pyvko.api_based import ApiBased, ApiMixin from pyvko.aspects.comments import Comments from pyvko.aspects.likes import Likes @@ -213,7 +211,7 @@ def __get_post_request(self, post: PostModel | Post): return request - def __get_owned_request(self, parameters: Dict = None) -> dict: + def __get_owned_request(self, parameters: Dict | None = None) -> dict: if parameters is None: parameters = {} else: diff --git a/pyvko/attachment/attachment_parser.py b/pyvko/attachment/attachment_parser.py index 19fa24b..a0ac2fd 100644 --- a/pyvko/attachment/attachment_parser.py +++ b/pyvko/attachment/attachment_parser.py @@ -1,8 +1,6 @@ from functools import cache from typing import Any -API = Any - from pyvko.aspects.albums import Album from pyvko.attachment.attachment import Attachment from pyvko.attachment.photo import Photo @@ -55,13 +53,13 @@ class AttachmentParser: def shared(cls): return cls() - def parse_photo(self, api_object: dict, api: API) -> Photo: + def parse_photo(self, api_object: dict, api: Any) -> Photo: return Photo.from_photo_object(api, api_object) - def parse_album(self, api_object: dict, api: API) -> Album: + def parse_album(self, api_object: dict, api: Any) -> Album: return Album(api, api_object) - def parse_object(self, api_object: dict, api: API) -> Attachment | None: + def parse_object(self, api_object: dict, api: Any) -> Attachment | None: if "photo" in api_object: return self.parse_photo(api_object["photo"], api) elif "album" in api_object: diff --git a/pyvko/attachment/photo.py b/pyvko/attachment/photo.py index d7b56eb..2131afa 100644 --- a/pyvko/attachment/photo.py +++ b/pyvko/attachment/photo.py @@ -62,7 +62,7 @@ def item_id(self) -> int: return self.__id @classmethod - def from_photo_object(cls, api: API, photo_object: Json): + def from_photo_object(cls, api: Any, photo_object: Json): id_ = photo_object["id"] owner_id = photo_object["owner_id"] diff --git a/pyvko/entities/user.py b/pyvko/entities/user.py index c2cc712..fd53cb8 100644 --- a/pyvko/entities/user.py +++ b/pyvko/entities/user.py @@ -1,7 +1,5 @@ from typing import List, Dict, Any -API = Any - from pyvko.api_based import ApiBased from pyvko.aspects.events import Event from pyvko.aspects.groups import Group @@ -34,7 +32,7 @@ def url(self) -> str: else: return f"https://vk.com/id{self.__id}" - def __init__(self, api: API, user_object: Dict) -> None: + def __init__(self, api: Any, user_object: Dict) -> None: super().__init__(api) self.__id = user_object["id"] @@ -49,11 +47,11 @@ def groups(self) -> List[Group]: "extended": 1, }) - groups_response = self.api.groups.get(**request) + groups_response = self.new_api.groups.get(**request) groups_objects = groups_response["items"] - groups = [Group(api=self.api, group_object=group_object) for group_object in groups_objects] + groups = [Group(api=self.new_api, group_object=group_object) for group_object in groups_objects] return groups @@ -66,8 +64,8 @@ def events(self) -> List[Event]: ]), } - response = list(get_all(request, self.api.groups.get)) + response = list(get_all(request, self.new_api.groups.get)) - events = [Event(self.api, event, None) for event in response] + events = [Event(self.new_api, event, None) for event in response] return events \ No newline at end of file From d0da0ca6adbe86e16c7ff8373425e51896d4f1cf Mon Sep 17 00:00:00 2001 From: Igor Djachenko Date: Mon, 22 Jun 2026 01:52:52 +0700 Subject: [PATCH 10/19] =?UTF-8?q?fix:=20migrate=20pyvko=5Fmain=20and=20eve?= =?UTF-8?q?nts=20self.api=20=E2=86=92=20self.new=5Fapi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyvko/aspects/events.py | 24 +++++++++++------------- pyvko/pyvko_main.py | 13 ++++++------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/pyvko/aspects/events.py b/pyvko/aspects/events.py index b0a29ec..194d3bd 100644 --- a/pyvko/aspects/events.py +++ b/pyvko/aspects/events.py @@ -79,29 +79,25 @@ def __init__(self, api: Any, event_object: Dict, settings_object: Dict | None) - self.is_closed = bool(event_object["is_closed"]) self.url = event_object["screen_name"] - self.event_category: Event.Category | None - - if settings_object is None: - self.event_category = None - self.__sections: Dict[Event.Section, Event.SectionState] = {} - self.main_section = None - self.secondary_section = None - self.organiser = None - else: + self.event_category: Event.Category | None = None + self.__sections: Dict[Event.Section, Event.SectionState] = {} + self.main_section: Event.Section | None = None + self.secondary_section: Event.Section | None = None + self.organiser: int | None = None + + if settings_object is not None: category_value = settings_object["public_category"] if category_value != 0: self.event_category = Event.Category(category_value) - else: - self.event_category = None - self.__sections: Dict[Event.Section, Event.SectionState] = { + self.__sections = { s: Event.SectionState(settings_object[s.value]) for s in Event.Section } self.main_section = Event.Section.from_index(settings_object["main_section"]) self.secondary_section = Event.Section.from_index(settings_object["secondary_section"]) - self.organiser: int | None = settings_object.get("event_object_id") + self.organiser = settings_object.get("event_object_id") @property def id(self) -> int: @@ -165,6 +161,8 @@ def create_event(self, title: str) -> Event: event = self.get_event(response["id"]) + assert event is not None + return event def get_event(self, url: str | int) -> Event | None: diff --git a/pyvko/pyvko_main.py b/pyvko/pyvko_main.py index 51d4513..f957a76 100644 --- a/pyvko/pyvko_main.py +++ b/pyvko/pyvko_main.py @@ -10,7 +10,6 @@ from pyvko.aspects.utils import Utils from pyvko.config.config import Config from pyvko.entities.user import User -from pyvko.shared.utils import Throttler class Pyvko(ApiBased, Utils, Events, Groups): @@ -35,11 +34,11 @@ def captcha_handler(captcha: Captcha): def current_user(self) -> User: request = self.get_request() - user_response = self.api.users.get(**request) + user_response = self.new_api.users.get(**request) user_id = user_response[0] - user = User(api=self.api, user_object=user_id) + user = User(api=self.new_api, user_object=user_id) return user @@ -54,13 +53,13 @@ def get_user(self, url: str) -> User: ], }) - user_response = self.api.users.get(**user_request) + user_response = self.new_api.users.get(**user_request) - user = User(api=self.api, user_object=user_response[0]) + user = User(api=self.new_api, user_object=user_response[0]) return user - def get_by_url(self, url: str) -> Group | User | None: + def get_by_url(self, url: str) -> Group | User | Event | None: name_type = self.resolve_name(url) if name_type == "group": @@ -103,7 +102,7 @@ def execute(self, code: str): "code": code, } - response = self.api.execute(**request) + response = self.new_api.execute(**request) return response From 4b836622854d7617b1b68ef5b69498c1ad014483 Mon Sep 17 00:00:00 2001 From: Igor Djachenko Date: Mon, 22 Jun 2026 01:52:56 +0700 Subject: [PATCH 11/19] chore: exclude pyvko_runner from mypy, add BACKLOG --- BACKLOG.md | 5 +++++ pyproject.toml | 4 ++++ 2 files changed, 9 insertions(+) create mode 100644 BACKLOG.md diff --git a/BACKLOG.md b/BACKLOG.md new file mode 100644 index 0000000..42e3e5e --- /dev/null +++ b/BACKLOG.md @@ -0,0 +1,5 @@ +# Backlog + +## mypy exclusions (нужно вернуть) + +- `pyvko/pyvko_runner.py` — исключён через `[[tool.mypy.overrides]] ignore_errors = true` в pyproject.toml. Файл содержит старый демо-код с ~20 реальными ошибками (устаревший API, неверные типы). Нужно либо выпилить файл, либо привести в соответствие с текущим API. diff --git a/pyproject.toml b/pyproject.toml index 29c7b27..b6b608a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,6 +27,10 @@ Homepage = "https://github.com/djachenko/pyvko" Repository = "https://github.com/djachenko/pyvko" Issues = "https://github.com/djachenko/pyvko/issues" +[[tool.mypy.overrides]] +module = "pyvko.pyvko_runner" +ignore_errors = true + [tool.semantic_release] version_toml = ["pyproject.toml:project.version"] branch = "master" From 1ca52143341b97f6c974c8cc0e7c550b11335e82 Mon Sep 17 00:00:00 2001 From: Igor Djachenko Date: Mon, 22 Jun 2026 01:57:50 +0700 Subject: [PATCH 12/19] =?UTF-8?q?fix:=20Dict=20=3D=20None=20=E2=86=92=20Di?= =?UTF-8?q?ct=20|=20None=20across=20api=5Fbased,=20albums,=20reposts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyvko/api_based.py | 6 +++--- pyvko/aspects/albums.py | 6 +++--- pyvko/aspects/reposts.py | 6 ++---- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/pyvko/api_based.py b/pyvko/api_based.py index 857e1d5..ba818eb 100644 --- a/pyvko/api_based.py +++ b/pyvko/api_based.py @@ -5,7 +5,7 @@ class RequestRoot: - def get_request(self, parameters: Dict = None): + def get_request(self, parameters: Dict | None = None): return parameters or {} @@ -20,7 +20,7 @@ def api(self) -> Any: assert False, f"{type(self).__name__} still uses unmigrated api — switch to new_api" @abstractmethod - def get_request(self, parameters: Dict = None) -> Dict: + def get_request(self, parameters: Dict | None = None) -> Dict: return super().get_request(parameters) @@ -46,7 +46,7 @@ def __get_default_object(): # "v": ApiBased.__VERSION, } - def get_request(self, parameters: Dict = None) -> Dict: + def get_request(self, parameters: Dict | None = None) -> Dict: if parameters is None: parameters = {} diff --git a/pyvko/aspects/albums.py b/pyvko/aspects/albums.py index cac784c..3bcb20e 100644 --- a/pyvko/aspects/albums.py +++ b/pyvko/aspects/albums.py @@ -39,7 +39,7 @@ def get_photos(self) -> List[Photo]: return photos - def get_request(self, parameters: Dict = None) -> dict: + def get_request(self, parameters: Dict | None = None) -> dict: if parameters is None: parameters = {} @@ -85,7 +85,7 @@ class Albums(ApiMixin, ABC): def id(self) -> int: pass - def __get_albums(self, parameters: Dict = None) -> List[Album]: + def __get_albums(self, parameters: Dict | None = None) -> List[Album]: request = self.__get_owned_request(parameters) result = self.api.photos.getAlbums(**request) @@ -124,7 +124,7 @@ def create_album(self, name: str) -> Album: return created_album - def __get_owned_request(self, parameters: Dict = None) -> dict: + def __get_owned_request(self, parameters: Dict | None = None) -> dict: if parameters is None: parameters = {} else: diff --git a/pyvko/aspects/reposts.py b/pyvko/aspects/reposts.py index cb0ae52..fa5883c 100644 --- a/pyvko/aspects/reposts.py +++ b/pyvko/aspects/reposts.py @@ -9,9 +9,7 @@ class Reposts(ApiMixin, ABC): 100, ] - __IGNORE_GROUPS = [ - - ] + __IGNORE_GROUPS: List[int] = [] @property def __ignore_groups(self) -> List[int]: @@ -39,7 +37,7 @@ def get_reposters(self): groups = response["groups"] groups = [group for group in groups if group["id"] not in self.__ignore_groups] - def get_request(self, parameters: Dict = None) -> Dict: + def get_request(self, parameters: Dict | None = None) -> Dict: return super().get_request() | { "owner_id": self.owner_id, "post_id": self.post_id, From 2409ec19f66b83b1fd1de3b55b64428df76cec28 Mon Sep 17 00:00:00 2001 From: Igor Djachenko Date: Mon, 22 Jun 2026 01:57:54 +0700 Subject: [PATCH 13/19] fix: nullable fields in PostModel, Post, CommentModel --- pyvko/aspects/comments.py | 4 ++-- pyvko/aspects/posts.py | 28 ++++++++++++++++------------ 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/pyvko/aspects/comments.py b/pyvko/aspects/comments.py index 76cb463..1bb6b51 100644 --- a/pyvko/aspects/comments.py +++ b/pyvko/aspects/comments.py @@ -15,7 +15,7 @@ class CommentModel: text: str from_group: int = 0 - attachments: List[Attachment] = None + attachments: List[Attachment] | None = None def to_request(self): request = {} @@ -64,7 +64,7 @@ def __init__( owner_id: int, date: datetime, text: str, - attachments: List[Attachment] + attachments: List[Attachment] | None ) -> None: super().__init__(api) diff --git a/pyvko/aspects/posts.py b/pyvko/aspects/posts.py index fd80813..2736dbf 100644 --- a/pyvko/aspects/posts.py +++ b/pyvko/aspects/posts.py @@ -18,12 +18,12 @@ @dataclass class PostModel: - text: str = None - attachments: List[Attachment] = None - date: datetime = None + text: str | None = None + attachments: List[Attachment] | None = None + date: datetime | None = None def to_request(self) -> dict: - request = { + request: dict[str, Any] = { "primary_attachments_mode": "grid", } @@ -46,18 +46,20 @@ def like_object_type(self) -> str: @property def item_id(self) -> int: + assert self.id is not None return self.id @property def post_id(self) -> int: + assert self.id is not None return self.id @property def owner_id(self) -> int: return self.__owner_id - def __init__(self, api: Any, owner_id: int, text: str = None, attachments: List[Attachment] = None, - date: datetime = None) -> None: + def __init__(self, api: Any, owner_id: int, text: str | None = None, attachments: List[Attachment] | None = None, + date: datetime | None = None) -> None: super().__init__(api) if attachments is None: @@ -66,11 +68,11 @@ def __init__(self, api: Any, owner_id: int, text: str = None, attachments: List[ if not text: text = None - self.date = date - self.attachments = attachments - self.id = None - self.text = text - self.timer_id = None + self.date: datetime | None = date + self.attachments: List[Attachment] = attachments + self.id: int | None = None + self.text: str | None = text + self.timer_id: int | None = None self.__owner_id = owner_id def __str__(self) -> str: @@ -101,7 +103,7 @@ def from_post_object(post_object: Dict, api: Any) -> 'Post': return post def to_request(self) -> dict: - request = { + request: dict[str, Any] = { "primary_attachments_mode": "grid", } @@ -176,6 +178,8 @@ def add_post(self, post: PostModel) -> Post: created_post = self.get_post(post_id) + assert created_post is not None + return created_post def update_post(self, post: Post): From d9f844519116f53a05b083263326400707d1e1ad Mon Sep 17 00:00:00 2001 From: Igor Djachenko Date: Mon, 22 Jun 2026 01:57:59 +0700 Subject: [PATCH 14/19] fix: Link stub properties raise NotImplementedError, photo_object typed as Any --- pyvko/attachment/attachment_parser.py | 6 +++--- pyvko/attachment/photo.py | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/pyvko/attachment/attachment_parser.py b/pyvko/attachment/attachment_parser.py index a0ac2fd..5e8df6e 100644 --- a/pyvko/attachment/attachment_parser.py +++ b/pyvko/attachment/attachment_parser.py @@ -33,15 +33,15 @@ def __init__(self, url: str) -> None: @property def type(self) -> str: - pass + raise NotImplementedError @property def owner_id(self) -> int: - pass + raise NotImplementedError @property def media_id(self) -> int: - pass + raise NotImplementedError def to_attach(self) -> str: return self.__url diff --git a/pyvko/attachment/photo.py b/pyvko/attachment/photo.py index 2131afa..5ae3b6d 100644 --- a/pyvko/attachment/photo.py +++ b/pyvko/attachment/photo.py @@ -4,7 +4,6 @@ from pyvko.api_based import ApiBased from pyvko.aspects.likes import Likes from pyvko.attachment.attachment import Attachment -from pyvko.shared.utils import Json class Photo(ApiBased, Attachment, Likes): @@ -62,7 +61,7 @@ def item_id(self) -> int: return self.__id @classmethod - def from_photo_object(cls, api: Any, photo_object: Json): + def from_photo_object(cls, api: Any, photo_object: Any): id_ = photo_object["id"] owner_id = photo_object["owner_id"] From 71912f8cb77ef7af7c9d2049bc23fa0c402b14d6 Mon Sep 17 00:00:00 2001 From: Igor Djachenko Date: Mon, 22 Jun 2026 01:58:08 +0700 Subject: [PATCH 15/19] fix: get_all and PhotoUploader type signatures --- pyvko/shared/photos_uploader.py | 14 +++++++------- pyvko/shared/utils.py | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pyvko/shared/photos_uploader.py b/pyvko/shared/photos_uploader.py index 1c465a1..0ccd4ea 100644 --- a/pyvko/shared/photos_uploader.py +++ b/pyvko/shared/photos_uploader.py @@ -2,7 +2,7 @@ from abc import abstractmethod from functools import cache from pathlib import Path -from typing import Callable, Dict, List, Iterable, Any +from typing import Callable, Dict, Iterable, Any import requests as requests from vk_api import VkUpload @@ -14,12 +14,12 @@ class PhotoUploader(ApiBased): @property @abstractmethod - def server_provider(self) -> Callable[[Dict], Dict[str, str]]: + def server_provider(self) -> Callable[..., Any]: pass @property @abstractmethod - def saver(self) -> Callable[[Dict], List[Dict]]: + def saver(self) -> Callable[..., Any]: pass @property @@ -94,11 +94,11 @@ def __init__(self, api: Any, group_id: int) -> None: self.__group_id = group_id @property - def server_provider(self) -> Callable[[Dict], str]: + def server_provider(self) -> Callable[..., Any]: return self.new_api.photos.getWallUploadServer @property - def saver(self) -> Callable[[Dict], str]: + def saver(self) -> Callable[..., Any]: return self.new_api.photos.saveWallPhoto @property @@ -123,11 +123,11 @@ def __init__(self, api: Any, album_id: int, group_id: int) -> None: self.__group_id = group_id @property - def server_provider(self) -> Callable[[Dict], str]: + def server_provider(self) -> Callable[..., Any]: return self.new_api.photos.getUploadServer @property - def saver(self) -> Callable[[Dict], List[Dict]]: + def saver(self) -> Callable[..., Any]: return self.new_api.photos.save @property diff --git a/pyvko/shared/utils.py b/pyvko/shared/utils.py index 84e2009..06b682f 100644 --- a/pyvko/shared/utils.py +++ b/pyvko/shared/utils.py @@ -4,8 +4,8 @@ Json = Dict[str, 'Json'] | List['Json'] | str | int -def get_all(parameters: Dict, get_response: Callable[[Json], Json], count_key: str = "count") -> \ - Iterable[Dict]: +def get_all(parameters: Dict, get_response: Callable[..., Any], count_key: str = "count") -> \ + Iterable[Any]: parameters = parameters.copy() total = 0 @@ -13,7 +13,7 @@ def get_all(parameters: Dict, get_response: Callable[[Json], Json], count_key: s parameters["offset"] = total # noinspection PyArgumentList - response = get_response(**parameters) + response: Any = get_response(**parameters) assert "items" in response assert "count" in response From dcb16e415ccd1160addd14296d26f2a9c0557048 Mon Sep 17 00:00:00 2001 From: Igor Djachenko Date: Mon, 22 Jun 2026 02:00:43 +0700 Subject: [PATCH 16/19] refactor: migrate to src layout --- pyproject.toml | 3 +++ {pyvko => src/pyvko}/__init__.py | 0 {pyvko => src/pyvko}/api_based.py | 0 {pyvko => src/pyvko}/aspects/__init__.py | 0 {pyvko => src/pyvko}/aspects/albums.py | 0 {pyvko => src/pyvko}/aspects/comments.py | 0 {pyvko => src/pyvko}/aspects/events.py | 0 {pyvko => src/pyvko}/aspects/groups.py | 0 {pyvko => src/pyvko}/aspects/likes.py | 0 {pyvko => src/pyvko}/aspects/posts.py | 0 {pyvko => src/pyvko}/aspects/reposts.py | 0 {pyvko => src/pyvko}/aspects/utils.py | 0 {pyvko => src/pyvko}/attachment/__init__.py | 0 {pyvko => src/pyvko}/attachment/attachment.py | 0 {pyvko => src/pyvko}/attachment/attachment_parser.py | 0 {pyvko => src/pyvko}/attachment/photo.py | 0 {pyvko => src/pyvko}/config/__init__.py | 0 {pyvko => src/pyvko}/config/config.py | 0 {pyvko => src/pyvko}/entities/__init__.py | 0 {pyvko => src/pyvko}/entities/user.py | 0 {pyvko => src/pyvko}/pyvko_main.py | 0 {pyvko => src/pyvko}/pyvko_runner.py | 0 {pyvko => src/pyvko}/shared/__init__.py | 0 {pyvko => src/pyvko}/shared/photos_uploader.py | 0 {pyvko => src/pyvko}/shared/utils.py | 0 25 files changed, 3 insertions(+) rename {pyvko => src/pyvko}/__init__.py (100%) rename {pyvko => src/pyvko}/api_based.py (100%) rename {pyvko => src/pyvko}/aspects/__init__.py (100%) rename {pyvko => src/pyvko}/aspects/albums.py (100%) rename {pyvko => src/pyvko}/aspects/comments.py (100%) rename {pyvko => src/pyvko}/aspects/events.py (100%) rename {pyvko => src/pyvko}/aspects/groups.py (100%) rename {pyvko => src/pyvko}/aspects/likes.py (100%) rename {pyvko => src/pyvko}/aspects/posts.py (100%) rename {pyvko => src/pyvko}/aspects/reposts.py (100%) rename {pyvko => src/pyvko}/aspects/utils.py (100%) rename {pyvko => src/pyvko}/attachment/__init__.py (100%) rename {pyvko => src/pyvko}/attachment/attachment.py (100%) rename {pyvko => src/pyvko}/attachment/attachment_parser.py (100%) rename {pyvko => src/pyvko}/attachment/photo.py (100%) rename {pyvko => src/pyvko}/config/__init__.py (100%) rename {pyvko => src/pyvko}/config/config.py (100%) rename {pyvko => src/pyvko}/entities/__init__.py (100%) rename {pyvko => src/pyvko}/entities/user.py (100%) rename {pyvko => src/pyvko}/pyvko_main.py (100%) rename {pyvko => src/pyvko}/pyvko_runner.py (100%) rename {pyvko => src/pyvko}/shared/__init__.py (100%) rename {pyvko => src/pyvko}/shared/photos_uploader.py (100%) rename {pyvko => src/pyvko}/shared/utils.py (100%) diff --git a/pyproject.toml b/pyproject.toml index b6b608a..2a6dff9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,6 +27,9 @@ Homepage = "https://github.com/djachenko/pyvko" Repository = "https://github.com/djachenko/pyvko" Issues = "https://github.com/djachenko/pyvko/issues" +[tool.setuptools.packages.find] +where = ["src"] + [[tool.mypy.overrides]] module = "pyvko.pyvko_runner" ignore_errors = true diff --git a/pyvko/__init__.py b/src/pyvko/__init__.py similarity index 100% rename from pyvko/__init__.py rename to src/pyvko/__init__.py diff --git a/pyvko/api_based.py b/src/pyvko/api_based.py similarity index 100% rename from pyvko/api_based.py rename to src/pyvko/api_based.py diff --git a/pyvko/aspects/__init__.py b/src/pyvko/aspects/__init__.py similarity index 100% rename from pyvko/aspects/__init__.py rename to src/pyvko/aspects/__init__.py diff --git a/pyvko/aspects/albums.py b/src/pyvko/aspects/albums.py similarity index 100% rename from pyvko/aspects/albums.py rename to src/pyvko/aspects/albums.py diff --git a/pyvko/aspects/comments.py b/src/pyvko/aspects/comments.py similarity index 100% rename from pyvko/aspects/comments.py rename to src/pyvko/aspects/comments.py diff --git a/pyvko/aspects/events.py b/src/pyvko/aspects/events.py similarity index 100% rename from pyvko/aspects/events.py rename to src/pyvko/aspects/events.py diff --git a/pyvko/aspects/groups.py b/src/pyvko/aspects/groups.py similarity index 100% rename from pyvko/aspects/groups.py rename to src/pyvko/aspects/groups.py diff --git a/pyvko/aspects/likes.py b/src/pyvko/aspects/likes.py similarity index 100% rename from pyvko/aspects/likes.py rename to src/pyvko/aspects/likes.py diff --git a/pyvko/aspects/posts.py b/src/pyvko/aspects/posts.py similarity index 100% rename from pyvko/aspects/posts.py rename to src/pyvko/aspects/posts.py diff --git a/pyvko/aspects/reposts.py b/src/pyvko/aspects/reposts.py similarity index 100% rename from pyvko/aspects/reposts.py rename to src/pyvko/aspects/reposts.py diff --git a/pyvko/aspects/utils.py b/src/pyvko/aspects/utils.py similarity index 100% rename from pyvko/aspects/utils.py rename to src/pyvko/aspects/utils.py diff --git a/pyvko/attachment/__init__.py b/src/pyvko/attachment/__init__.py similarity index 100% rename from pyvko/attachment/__init__.py rename to src/pyvko/attachment/__init__.py diff --git a/pyvko/attachment/attachment.py b/src/pyvko/attachment/attachment.py similarity index 100% rename from pyvko/attachment/attachment.py rename to src/pyvko/attachment/attachment.py diff --git a/pyvko/attachment/attachment_parser.py b/src/pyvko/attachment/attachment_parser.py similarity index 100% rename from pyvko/attachment/attachment_parser.py rename to src/pyvko/attachment/attachment_parser.py diff --git a/pyvko/attachment/photo.py b/src/pyvko/attachment/photo.py similarity index 100% rename from pyvko/attachment/photo.py rename to src/pyvko/attachment/photo.py diff --git a/pyvko/config/__init__.py b/src/pyvko/config/__init__.py similarity index 100% rename from pyvko/config/__init__.py rename to src/pyvko/config/__init__.py diff --git a/pyvko/config/config.py b/src/pyvko/config/config.py similarity index 100% rename from pyvko/config/config.py rename to src/pyvko/config/config.py diff --git a/pyvko/entities/__init__.py b/src/pyvko/entities/__init__.py similarity index 100% rename from pyvko/entities/__init__.py rename to src/pyvko/entities/__init__.py diff --git a/pyvko/entities/user.py b/src/pyvko/entities/user.py similarity index 100% rename from pyvko/entities/user.py rename to src/pyvko/entities/user.py diff --git a/pyvko/pyvko_main.py b/src/pyvko/pyvko_main.py similarity index 100% rename from pyvko/pyvko_main.py rename to src/pyvko/pyvko_main.py diff --git a/pyvko/pyvko_runner.py b/src/pyvko/pyvko_runner.py similarity index 100% rename from pyvko/pyvko_runner.py rename to src/pyvko/pyvko_runner.py diff --git a/pyvko/shared/__init__.py b/src/pyvko/shared/__init__.py similarity index 100% rename from pyvko/shared/__init__.py rename to src/pyvko/shared/__init__.py diff --git a/pyvko/shared/photos_uploader.py b/src/pyvko/shared/photos_uploader.py similarity index 100% rename from pyvko/shared/photos_uploader.py rename to src/pyvko/shared/photos_uploader.py diff --git a/pyvko/shared/utils.py b/src/pyvko/shared/utils.py similarity index 100% rename from pyvko/shared/utils.py rename to src/pyvko/shared/utils.py From c9c21f89226346906d72b78f1c4a5072ab85693f Mon Sep 17 00:00:00 2001 From: Igor Djachenko Date: Mon, 22 Jun 2026 02:05:09 +0700 Subject: [PATCH 17/19] chore: ignore missing stubs globally, document in BACKLOG --- BACKLOG.md | 9 +++++++++ pyproject.toml | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/BACKLOG.md b/BACKLOG.md index 42e3e5e..7cca3b8 100644 --- a/BACKLOG.md +++ b/BACKLOG.md @@ -1,5 +1,14 @@ # Backlog +## mypy third-party stubs + +`[tool.mypy] ignore_missing_imports = true` — временное решение. `vk_api` не имеет type stubs на PyPI. `requests` имеет (`types-requests`). Нужно: +1. Добавить `types-requests` в test-зависимости +2. Для `vk_api` — написать минимальные inline stubs или добавить точечный override +3. Проработать на уровне repokit CI: `mypy --install-types --non-interactive && mypy src/` + + + ## mypy exclusions (нужно вернуть) - `pyvko/pyvko_runner.py` — исключён через `[[tool.mypy.overrides]] ignore_errors = true` в pyproject.toml. Файл содержит старый демо-код с ~20 реальными ошибками (устаревший API, неверные типы). Нужно либо выпилить файл, либо привести в соответствие с текущим API. diff --git a/pyproject.toml b/pyproject.toml index 2a6dff9..6b20c97 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,6 +16,7 @@ test = [ "pytest", "ruff", "mypy", + "types-requests", ] release = [ "build", @@ -30,6 +31,9 @@ Issues = "https://github.com/djachenko/pyvko/issues" [tool.setuptools.packages.find] where = ["src"] +[tool.mypy] +ignore_missing_imports = true + [[tool.mypy.overrides]] module = "pyvko.pyvko_runner" ignore_errors = true From 86a4a5e2500a02494cf84d2b51bd04c8ee861d08 Mon Sep 17 00:00:00 2001 From: repokit Date: Wed, 24 Jun 2026 18:34:37 +0700 Subject: [PATCH 18/19] chore: [repokit] update ci workflows --- .github/workflows/integration.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 17e5849..8492389 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -37,4 +37,4 @@ jobs: echo "Attempt $i failed, retrying in 10s..." sleep 10 done - $PACKAGE --help + python -c "import $PACKAGE" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2cac989..ba13376 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -37,4 +37,4 @@ jobs: echo "Attempt $i failed, retrying in 10s..." sleep 10 done - $PACKAGE --help + python -c "import $PACKAGE" From 47d47b39be635154fb52c4f4c42fa5aba66dac2e Mon Sep 17 00:00:00 2001 From: Igor Djachenko Date: Wed, 24 Jun 2026 19:03:32 +0700 Subject: [PATCH 19/19] fix: precise mypy override for vk_api, remove types-requests from deps --- BACKLOG.md | 7 ------- pyproject.toml | 4 ++-- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/BACKLOG.md b/BACKLOG.md index 7cca3b8..1dfc085 100644 --- a/BACKLOG.md +++ b/BACKLOG.md @@ -1,12 +1,5 @@ # Backlog -## mypy third-party stubs - -`[tool.mypy] ignore_missing_imports = true` — временное решение. `vk_api` не имеет type stubs на PyPI. `requests` имеет (`types-requests`). Нужно: -1. Добавить `types-requests` в test-зависимости -2. Для `vk_api` — написать минимальные inline stubs или добавить точечный override -3. Проработать на уровне repokit CI: `mypy --install-types --non-interactive && mypy src/` - ## mypy exclusions (нужно вернуть) diff --git a/pyproject.toml b/pyproject.toml index 6b20c97..f555595 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,6 @@ test = [ "pytest", "ruff", "mypy", - "types-requests", ] release = [ "build", @@ -31,7 +30,8 @@ Issues = "https://github.com/djachenko/pyvko/issues" [tool.setuptools.packages.find] where = ["src"] -[tool.mypy] +[[tool.mypy.overrides]] +module = "vk_api.*" ignore_missing_imports = true [[tool.mypy.overrides]]