move proto files into separate py_library in same namespace

Will allow importing the Protobuf without pulling in the rest of
the library. This is not a full PEP420 namespace, and the wheel still
bundles everything - it just makes things easier in a Bazel workspace.
I originally tried with PEP420, but it required more invasive changes,
and I ran into issues with mypy.
This commit is contained in:
Damien Elmes 2021-07-11 14:51:25 +10:00
parent 372a28be29
commit 7ac1fa17e6
22 changed files with 64 additions and 45 deletions

View file

@ -31,6 +31,7 @@ py_test(
main = "tests/run_mypy.py", main = "tests/run_mypy.py",
deps = [ deps = [
"//pylib/anki", "//pylib/anki",
"//pylib/anki:proto",
requirement("mypy"), requirement("mypy"),
], ],
) )

View file

@ -4,6 +4,7 @@ load("@py_deps//:requirements.bzl", "requirement")
load("@rules_python//experimental/python:wheel.bzl", "py_package", "py_wheel") load("@rules_python//experimental/python:wheel.bzl", "py_package", "py_wheel")
load("//:defs.bzl", "anki_version") load("//:defs.bzl", "anki_version")
load("//pylib:orjson.bzl", "orjson_if_available") load("//pylib:orjson.bzl", "orjson_if_available")
load("//pylib:protobuf.bzl", "py_proto")
copy_file( copy_file(
name = "buildinfo", name = "buildinfo",
@ -32,7 +33,6 @@ py_library(
"py.typed", "py.typed",
":buildinfo", ":buildinfo",
":hooks_gen", ":hooks_gen",
":proto_py",
"//pylib/anki/_backend", "//pylib/anki/_backend",
], ],
imports = [ imports = [
@ -40,6 +40,7 @@ py_library(
], ],
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
":proto",
requirement("beautifulsoup4"), requirement("beautifulsoup4"),
requirement("decorator"), requirement("decorator"),
requirement("distro"), requirement("distro"),
@ -107,8 +108,6 @@ filegroup(
], ],
) )
load("//pylib:protobuf.bzl", "py_proto")
py_proto( py_proto(
name = "proto_py", name = "proto_py",
srcs = ["//proto"], srcs = ["//proto"],
@ -117,10 +116,15 @@ py_proto(
], ],
) )
# only used for genbackend.py
py_library( py_library(
name = "proto_lib", name = "proto",
srcs = [":proto_py", "__init__.py"], srcs = [
"__init__.py",
# includes the .py files
":proto_py",
],
# includes the .pyi files
data = [":proto_py", "py.typed"],
imports = [".."], imports = [".."],
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
) )

View file

@ -1,20 +1,2 @@
# Copyright: Ankitects Pty Ltd and contributors # Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import os
import sys
if not os.getenv("PROTOS_ONLY"):
from anki.buildinfo import version
from anki.collection import Collection
if sys.version_info[0] < 3 or sys.version_info[1] < 7:
raise Exception("Anki requires Python 3.7+")
# ensure unicode filenames are supported
try:
"テスト".encode(sys.getfilesystemencoding())
except UnicodeEncodeError as exc:
raise Exception("Anki requires a UTF-8 locale.") from exc
__all__ = ["Collection"]

View file

@ -12,7 +12,7 @@ py_binary(
requirement("black"), requirement("black"),
requirement("stringcase"), requirement("stringcase"),
requirement("protobuf"), requirement("protobuf"),
"//pylib/anki:proto_lib", "//pylib/anki:proto",
], ],
) )

View file

@ -11,6 +11,7 @@ from weakref import ref
from markdown import markdown from markdown import markdown
import anki.buildinfo import anki.buildinfo
import anki.lang
from anki import backend_pb2, i18n_pb2 from anki import backend_pb2, i18n_pb2
from anki._backend.generated import RustBackendGenerated from anki._backend.generated import RustBackendGenerated
from anki.dbproxy import Row as DBRow from anki.dbproxy import Row as DBRow

View file

@ -8,8 +8,6 @@ import sys
import google.protobuf.descriptor import google.protobuf.descriptor
os.environ["PROTOS_ONLY"] = "1"
import anki.backend_pb2 import anki.backend_pb2
import anki.i18n_pb2 import anki.i18n_pb2
import anki.cards_pb2 import anki.cards_pb2
@ -232,6 +230,22 @@ col.decks.all_config()
from typing import * from typing import *
import anki import anki
import anki.backend_pb2
import anki.i18n_pb2
import anki.cards_pb2
import anki.collection_pb2
import anki.decks_pb2
import anki.deckconfig_pb2
import anki.notes_pb2
import anki.notetypes_pb2
import anki.scheduler_pb2
import anki.sync_pb2
import anki.configs_pb2
import anki.search_pb2
import anki.stats_pb2
import anki.card_rendering_pb2
import anki.tags_pb2
import anki.media_pb2
class RustBackendGenerated: class RustBackendGenerated:
def _run_command(self, service: int, method: int, input: Any) -> bytes: def _run_command(self, service: int, method: int, input: Any) -> bytes:

View file

@ -6,8 +6,6 @@ from __future__ import annotations
import sys import sys
from typing import Any, Dict, NewType, Optional from typing import Any, Dict, NewType, Optional
import anki
# whether new cards should be mixed with reviews, or shown first or last # whether new cards should be mixed with reviews, or shown first or last
NEW_CARDS_DISTRIBUTE = 0 NEW_CARDS_DISTRIBUTE = 0
NEW_CARDS_LAST = 1 NEW_CARDS_LAST = 1
@ -93,6 +91,8 @@ REVLOG_RESCHED = 4
# Labels # Labels
########################################################################## ##########################################################################
import anki.collection
def _tr(col: Optional[anki.collection.Collection]) -> Any: def _tr(col: Optional[anki.collection.Collection]) -> Any:
if col: if col:

View file

@ -7,7 +7,7 @@ import re
from re import Match from re import Match
from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple, Union from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple, Union
import anki import anki._backend
# DBValue is actually Union[str, int, float, None], but if defined # DBValue is actually Union[str, int, float, None], but if defined
# that way, every call site needs to do a type check prior to using # that way, every call site needs to do a type check prior to using

View file

@ -76,7 +76,7 @@ class HttpClient:
return buf.getvalue() return buf.getvalue()
def _agentName(self) -> str: def _agentName(self) -> str:
from anki import version from anki.buildinfo import version
return f"Anki {version}" return f"Anki {version}"

View file

@ -3,7 +3,7 @@
from typing import Any, Callable, Sequence, Tuple, Type, Union from typing import Any, Callable, Sequence, Tuple, Type, Union
from anki import Collection from anki.collection import Collection
from anki.importing.anki2 import Anki2Importer from anki.importing.anki2 import Anki2Importer
from anki.importing.apkg import AnkiPackageImporter from anki.importing.apkg import AnkiPackageImporter
from anki.importing.base import Importer from anki.importing.base import Importer

View file

@ -10,7 +10,8 @@ import json
import time import time
from typing import Any, Dict, List, Optional, Sequence, Tuple, Union from typing import Any, Dict, List, Optional, Sequence, Tuple, Union
import anki import anki.cards
import anki.collection
from anki.consts import * from anki.consts import *
from anki.lang import FormatTimeSpan from anki.lang import FormatTimeSpan
from anki.utils import ids2str from anki.utils import ids2str

View file

@ -5,7 +5,8 @@ from __future__ import annotations
from typing import Any, Callable, List, Tuple from typing import Any, Callable, List, Tuple
import anki import anki.collection
import anki.models
from anki import notetypes_pb2 from anki import notetypes_pb2
from anki.utils import from_json_bytes from anki.utils import from_json_bytes

View file

@ -26,7 +26,7 @@ except ImportError as e:
from flask import Response from flask import Response
from anki import Collection from anki.collection import Collection
from anki.sync_pb2 import SyncServerMethodRequest from anki.sync_pb2 import SyncServerMethodRequest
Method = SyncServerMethodRequest.Method # pylint: disable=no-member Method = SyncServerMethodRequest.Method # pylint: disable=no-member

View file

@ -6,7 +6,7 @@ import shutil
import tempfile import tempfile
import time import time
from anki import Collection as aopen from anki.collection import Collection as aopen
# Between 2-4AM, shift the time back so test assumptions hold. # Between 2-4AM, shift the time back so test assumptions hold.
lt = time.localtime() lt = time.localtime()

View file

@ -6,7 +6,7 @@
import os import os
import tempfile import tempfile
from anki import Collection as aopen from anki.collection import Collection as aopen
from anki.dbproxy import emulate_named_args from anki.dbproxy import emulate_named_args
from anki.lang import TR, without_unicode_isolation from anki.lang import TR, without_unicode_isolation
from anki.stdmodels import addBasicModel, get_stock_notetypes from anki.stdmodels import addBasicModel, get_stock_notetypes

View file

@ -6,7 +6,7 @@
import os import os
import tempfile import tempfile
from anki import Collection as aopen from anki.collection import Collection as aopen
from anki.exporting import * from anki.exporting import *
from anki.importing import Anki2Importer from anki.importing import Anki2Importer
from tests.shared import errorsAfterMidnight from tests.shared import errorsAfterMidnight

View file

@ -4,7 +4,7 @@
import copy import copy
import time import time
from anki import Collection from anki.collection import Collection
from anki.consts import * from anki.consts import *
from anki.lang import without_unicode_isolation from anki.lang import without_unicode_isolation
from anki.utils import intTime from anki.utils import intTime

View file

@ -13,13 +13,27 @@ import traceback
from typing import Any, Callable, Dict, List, Optional, Tuple, Union, cast from typing import Any, Callable, Dict, List, Optional, Tuple, Union, cast
import anki.lang import anki.lang
from anki import version as _version
from anki._backend import RustBackend from anki._backend import RustBackend
from anki.buildinfo import version as _version
from anki.collection import Collection
from anki.consts import HELP_SITE from anki.consts import HELP_SITE
from anki.utils import checksum, isLin, isMac from anki.utils import checksum, isLin, isMac
from aqt.qt import * from aqt.qt import *
from aqt.utils import TR, locale_dir, tr from aqt.utils import TR, locale_dir, tr
if sys.version_info[0] < 3 or sys.version_info[1] < 7:
raise Exception("Anki requires Python 3.7+")
# ensure unicode filenames are supported
try:
"テスト".encode(sys.getfilesystemencoding())
except UnicodeEncodeError as exc:
raise Exception("Anki requires a UTF-8 locale.") from exc
# compat aliases
anki.version = _version # type: ignore
anki.Collection = Collection # type: ignore
# we want to be able to print unicode debug info to console without # we want to be able to print unicode debug info to console without
# fear of a traceback on systems with the console set to ASCII # fear of a traceback on systems with the console set to ASCII
try: try:

View file

@ -6,7 +6,8 @@ from operator import itemgetter
from typing import Any, List, Optional, Sequence from typing import Any, List, Optional, Sequence
import aqt.clayout import aqt.clayout
from anki import Collection, stdmodels from anki import stdmodels
from anki.collection import Collection
from anki.lang import without_unicode_isolation from anki.lang import without_unicode_isolation
from anki.models import NotetypeDict, NotetypeId, NotetypeNameIdUseCount from anki.models import NotetypeDict, NotetypeId, NotetypeNameIdUseCount
from anki.notes import Note from anki.notes import Note

View file

@ -17,7 +17,7 @@ from send2trash import send2trash
import anki.lang import anki.lang
import aqt.forms import aqt.forms
import aqt.sound import aqt.sound
from anki import Collection from anki.collection import Collection
from anki.db import DB from anki.db import DB
from anki.lang import without_unicode_isolation from anki.lang import without_unicode_isolation
from anki.sync import SyncAuth from anki.sync import SyncAuth

View file

@ -34,8 +34,8 @@ from PyQt5.QtWidgets import (
) )
import aqt import aqt
from anki import Collection
from anki._legacy import deprecated from anki._legacy import deprecated
from anki.collection import Collection
from anki.lang import TR, tr_legacyglobal # pylint: disable=unused-import from anki.lang import TR, tr_legacyglobal # pylint: disable=unused-import
from anki.utils import invalidFilename, isMac, isWin, noBundledLibs, versionWithBuild from anki.utils import invalidFilename, isMac, isWin, noBundledLibs, versionWithBuild
from aqt.qt import * from aqt.qt import *

View file

@ -30,8 +30,8 @@ if subprocess.run(
"--", "--",
"--config-file", "--config-file",
"qt/mypy.ini", "qt/mypy.ini",
"bazel-bin/qt/dmypy.runfiles/anki/pylib/anki", "bazel-bin/qt/dmypy.runfiles/ankidesktop/pylib/anki",
"bazel-bin/qt/dmypy.runfiles/anki/qt/aqt", "bazel-bin/qt/dmypy.runfiles/ankidesktop/qt/aqt",
"--python-executable", "--python-executable",
os.path.abspath("pip/stubs/extendsitepkgs"), os.path.abspath("pip/stubs/extendsitepkgs"),
], ],