diff --git a/python/spider-py/pyproject.toml b/python/spider-py/pyproject.toml index 47bac154d..44e05eeba 100644 --- a/python/spider-py/pyproject.toml +++ b/python/spider-py/pyproject.toml @@ -9,6 +9,7 @@ authors = [ { name = "Zhihao Lin", email = "lin.zhihao@yscope.com" }, ] dependencies = [ + "lark>=1.2.2", "mariadb>=1.1.13", "msgpack-types>=0.5.0", ] diff --git a/python/spider-py/src/spider_py/type/__init__.py b/python/spider-py/src/spider_py/type/__init__.py index c943af9d4..a21fd2272 100644 --- a/python/spider-py/src/spider_py/type/__init__.py +++ b/python/spider-py/src/spider_py/type/__init__.py @@ -1,6 +1,16 @@ """Spider type package.""" from spider_py.type.tdl_convert import to_tdl_type_str +from spider_py.type.tdl_parse import parse_tdl_type from spider_py.type.type import Double, Float, Int8, Int16, Int32, Int64 -__all__ = ["Double", "Float", "Int8", "Int16", "Int32", "Int64", "to_tdl_type_str"] +__all__ = [ + "Double", + "Float", + "Int8", + "Int16", + "Int32", + "Int64", + "parse_tdl_type", + "to_tdl_type_str", +] diff --git a/python/spider-py/src/spider_py/type/tdl_parse.py b/python/spider-py/src/spider_py/type/tdl_parse.py new file mode 100644 index 000000000..95376a73c --- /dev/null +++ b/python/spider-py/src/spider_py/type/tdl_parse.py @@ -0,0 +1,102 @@ +"""Parse TDL type string.""" + +from lark import Lark, LarkError, Token, Transformer, v_args + +from spider_py.type.tdl_type import ( + BoolType, + ClassType, + DoubleType, + FloatType, + Int8Type, + Int16Type, + Int32Type, + Int64Type, + ListType, + MapType, + TdlType, +) + +grammar = r""" +type: map_type | list_type | base_type + +map_type: "Map" "<" type "," type ">" +list_type: "List" "<" type ">" +base_type: ID + +ID: /[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)*/ + +%import common.WS +%ignore WS +""" + +PrimitiveTypeDict = { + "bool": BoolType(), + "double": DoubleType(), + "float": FloatType(), + "int8": Int8Type(), + "int16": Int16Type(), + "int32": Int32Type(), + "int64": Int64Type(), +} + + +class TypeTransformer(Transformer[Token, TdlType]): + """Transforms Lark parse tree into TDL type.""" + + @v_args(inline=True) + def type(self, value_type: TdlType) -> TdlType: + """ + Unwraps the type node to return the TdlType. + :param value_type: The type node to unwrap. + :return: The unwrapped TdlType. + """ + return value_type + + @v_args(inline=True) + def map_type(self, key_type: TdlType, value_type: TdlType) -> TdlType: + """ + Transforms map node into Map type. + :param key_type: The key type of the map. + :param value_type: The value type of the map. + :return: The MapType with the given `key_type` and `value_type`. + """ + return MapType(key_type, value_type) + + @v_args(inline=True) + def list_type(self, element_type: TdlType) -> TdlType: + """ + Transforms list node into List type. + :param element_type: The element type of the list. + :return: The ListType with the given `element_type`. + """ + return ListType(element_type) + + @v_args(inline=True) + def base_type(self, token_id: str) -> TdlType: + """ + Transforms primitive node into primitive type. + :param token_id: The token id of the primitive type. + :return: The corresponding TdlType of the `token_id`. + """ + if token_id in PrimitiveTypeDict: + return PrimitiveTypeDict[token_id] + return ClassType(token_id) + + +_parser = Lark(grammar, start="type", parser="lalr") +_transformer = TypeTransformer(visit_tokens=False) + + +def parse_tdl_type(type_string: str) -> TdlType: + """ + Parses TDL type string into TDL type. + :param type_string: TDL type string. + :return: Parsed TDL type. + :raises TypeError: If string is not a valid TDL type. + """ + try: + tree = _parser.parse(type_string) + return _transformer.transform(tree) + except LarkError as e: + msg = f"Cannot parse TDL type `{type_string}`" + raise TypeError(msg) from e diff --git a/python/spider-py/src/spider_py/type/tdl_type.py b/python/spider-py/src/spider_py/type/tdl_type.py index f5c4e15b3..ac6118a26 100644 --- a/python/spider-py/src/spider_py/type/tdl_type.py +++ b/python/spider-py/src/spider_py/type/tdl_type.py @@ -1,9 +1,13 @@ """Spider TDL types.""" from abc import ABC, abstractmethod +from types import GenericAlias from typing_extensions import override +from spider_py.type.type import Double, Float, Int8, Int16, Int32, Int64 +from spider_py.type.utils import get_class_by_name + class TdlType(ABC): """Abstract base class for all TDL types.""" @@ -12,6 +16,10 @@ class TdlType(ABC): def type_str(self) -> str: """:return: String representation of the TDL type.""" + @abstractmethod + def native_type(self) -> type | GenericAlias: + """:return: Native Python type of the TDL type.""" + class DoubleType(TdlType): """TDL double type.""" @@ -20,6 +28,10 @@ class DoubleType(TdlType): def type_str(self) -> str: return "double" + @override + def native_type(self) -> type | GenericAlias: + return Double + class FloatType(TdlType): """TDL float type.""" @@ -28,6 +40,10 @@ class FloatType(TdlType): def type_str(self) -> str: return "float" + @override + def native_type(self) -> type | GenericAlias: + return Float + class Int8Type(TdlType): """TDL int8 type.""" @@ -36,6 +52,10 @@ class Int8Type(TdlType): def type_str(self) -> str: return "int8" + @override + def native_type(self) -> type | GenericAlias: + return Int8 + class Int16Type(TdlType): """TDL int16 type.""" @@ -44,6 +64,10 @@ class Int16Type(TdlType): def type_str(self) -> str: return "int16" + @override + def native_type(self) -> type | GenericAlias: + return Int16 + class Int32Type(TdlType): """TDL int32 type.""" @@ -52,6 +76,10 @@ class Int32Type(TdlType): def type_str(self) -> str: return "int32" + @override + def native_type(self) -> type | GenericAlias: + return Int32 + class Int64Type(TdlType): """TDL int64 type.""" @@ -60,6 +88,10 @@ class Int64Type(TdlType): def type_str(self) -> str: return "int64" + @override + def native_type(self) -> type | GenericAlias: + return Int64 + class BoolType(TdlType): """TDL bool type.""" @@ -68,6 +100,10 @@ class BoolType(TdlType): def type_str(self) -> str: return "bool" + @override + def native_type(self) -> type | GenericAlias: + return bool + class ClassType(TdlType): """TDL Custom class type.""" @@ -83,6 +119,14 @@ def __init__(self, name: str) -> None: def type_str(self) -> str: return self._name + @override + def native_type(self) -> type | GenericAlias: + """ + :return: Native Python type of the class. + :raise: TypeError if `class_name` is not a valid class. + """ + return get_class_by_name(self._name) + class ListType(TdlType): """TDL List type.""" @@ -98,6 +142,10 @@ def __init__(self, element_type: TdlType) -> None: def type_str(self) -> str: return f"List<{self.element_type.type_str()}>" + @override + def native_type(self) -> type | GenericAlias: + return list[self.element_type.native_type()] # type: ignore[misc] + def is_integral(tdl_type: TdlType) -> bool: """ @@ -142,3 +190,7 @@ def __init__(self, key_type: TdlType, value_type: TdlType) -> None: @override def type_str(self) -> str: return f"Map<{self.key_type.type_str()},{self.value_type.type_str()}>" + + @override + def native_type(self) -> type | GenericAlias: + return dict[self.key_type.native_type(), self.value_type.native_type()] # type: ignore[misc] diff --git a/python/spider-py/src/spider_py/type/utils.py b/python/spider-py/src/spider_py/type/utils.py index f1d3ae113..e48fd389f 100644 --- a/python/spider-py/src/spider_py/type/utils.py +++ b/python/spider-py/src/spider_py/type/utils.py @@ -1,5 +1,8 @@ """Utility for TDL types.""" +from importlib import import_module +from typing import cast + def get_class_name(cls: type) -> str: """ @@ -7,3 +10,22 @@ def get_class_name(cls: type) -> str: :return: Full name of `cls`. """ return f"{cls.__module__}.{cls.__qualname__}" + + +def get_class_by_name(name: str) -> type: + """ + Gets class by name. + :param name: + :return: The type object identified by `name`. + :raise: TypeError if `class_name` is not a valid class. + """ + module_name, _, class_name = name.rpartition(".") + if module_name == "": + msg = f"{name} does not contain a valid Python module." + raise TypeError(msg) + try: + module = import_module(module_name) + return cast("type", getattr(module, class_name)) + except (ValueError, ModuleNotFoundError, AttributeError) as e: + msg = f"{name} is not a valid TDL type." + raise TypeError(msg) from e diff --git a/python/spider-py/tests/type/test_to_native.py b/python/spider-py/tests/type/test_to_native.py new file mode 100644 index 000000000..4f7e4281e --- /dev/null +++ b/python/spider-py/tests/type/test_to_native.py @@ -0,0 +1,53 @@ +"""Test converting TDL type to native type.""" + +from types import GenericAlias + +import pytest + +import spider_py +from spider_py.type.tdl_parse import parse_tdl_type +from spider_py.type.utils import get_class_name + + +def _string_to_native(s: str) -> type | GenericAlias: + """ + Converts a TDL type string to a native type object. + :param s: The TDL type string to convert. + :return: The converted native type. + """ + return parse_tdl_type(s).native_type() + + +class TestToNativeType: + """Test converting TDL type to native type.""" + + def test_to_primitive_native_type(self) -> None: + """Test converting primitive TDL type to native type.""" + assert _string_to_native("bool") is bool + assert _string_to_native("double") is spider_py.Double + assert _string_to_native("float") is spider_py.Float + assert _string_to_native("int8") is spider_py.Int8 + assert _string_to_native("int16") is spider_py.Int16 + assert _string_to_native("int32") is spider_py.Int32 + assert _string_to_native("int64") is spider_py.Int64 + + def test_to_class_type(self) -> None: + """Test converting class TDL type to native type.""" + assert _string_to_native(get_class_name(TestToNativeType)) == TestToNativeType + with pytest.raises(TypeError): + _string_to_native("NonExistType") + with pytest.raises(TypeError): + _string_to_native("NonExistModule.NonExistType") + + def test_to_list_type(self) -> None: + """Test converting list TDL type to native type.""" + assert _string_to_native("List") == list[spider_py.Int8] + assert _string_to_native("List>") == list[list[spider_py.Int8]] + + def test_to_map_type(self) -> None: + """Test converting map TDL type to native type.""" + assert _string_to_native("Map") == dict[spider_py.Int8, spider_py.Int8] + assert ( + _string_to_native("Map,Map>") + == dict[list[spider_py.Int8], dict[spider_py.Int8, spider_py.Double]] + ) diff --git a/python/spider-py/uv.lock b/python/spider-py/uv.lock index 66d65e004..6982e6698 100644 --- a/python/spider-py/uv.lock +++ b/python/spider-py/uv.lock @@ -32,6 +32,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, ] +[[package]] +name = "lark" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/af/60/bc7622aefb2aee1c0b4ba23c1446d3e30225c8770b38d7aedbfb65ca9d5a/lark-1.2.2.tar.gz", hash = "sha256:ca807d0162cd16cef15a8feecb862d7319e7a09bdb13aef927968e45040fed80", size = 252132, upload-time = "2024-08-13T19:49:00.652Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2d/00/d90b10b962b4277f5e64a78b6609968859ff86889f5b898c1a778c06ec00/lark-1.2.2-py3-none-any.whl", hash = "sha256:c2276486b02f0f1b90be155f2c8ba4a8e194d42775786db622faccd652d8e80c", size = 111036, upload-time = "2024-08-13T19:48:58.603Z" }, +] + [[package]] name = "mariadb" version = "1.1.13" @@ -222,28 +231,28 @@ wheels = [ [[package]] name = "ruff" -version = "0.12.9" +version = "0.12.10" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4a/45/2e403fa7007816b5fbb324cb4f8ed3c7402a927a0a0cb2b6279879a8bfdc/ruff-0.12.9.tar.gz", hash = "sha256:fbd94b2e3c623f659962934e52c2bea6fc6da11f667a427a368adaf3af2c866a", size = 5254702, upload-time = "2025-08-14T16:08:55.2Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/eb/8c073deb376e46ae767f4961390d17545e8535921d2f65101720ed8bd434/ruff-0.12.10.tar.gz", hash = "sha256:189ab65149d11ea69a2d775343adf5f49bb2426fc4780f65ee33b423ad2e47f9", size = 5310076, upload-time = "2025-08-21T18:23:22.595Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ad/20/53bf098537adb7b6a97d98fcdebf6e916fcd11b2e21d15f8c171507909cc/ruff-0.12.9-py3-none-linux_armv6l.whl", hash = "sha256:fcebc6c79fcae3f220d05585229463621f5dbf24d79fdc4936d9302e177cfa3e", size = 11759705, upload-time = "2025-08-14T16:08:12.968Z" }, - { url = "https://files.pythonhosted.org/packages/20/4d/c764ee423002aac1ec66b9d541285dd29d2c0640a8086c87de59ebbe80d5/ruff-0.12.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:aed9d15f8c5755c0e74467731a007fcad41f19bcce41cd75f768bbd687f8535f", size = 12527042, upload-time = "2025-08-14T16:08:16.54Z" }, - { url = "https://files.pythonhosted.org/packages/8b/45/cfcdf6d3eb5fc78a5b419e7e616d6ccba0013dc5b180522920af2897e1be/ruff-0.12.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5b15ea354c6ff0d7423814ba6d44be2807644d0c05e9ed60caca87e963e93f70", size = 11724457, upload-time = "2025-08-14T16:08:18.686Z" }, - { url = "https://files.pythonhosted.org/packages/72/e6/44615c754b55662200c48bebb02196dbb14111b6e266ab071b7e7297b4ec/ruff-0.12.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d596c2d0393c2502eaabfef723bd74ca35348a8dac4267d18a94910087807c53", size = 11949446, upload-time = "2025-08-14T16:08:21.059Z" }, - { url = "https://files.pythonhosted.org/packages/fd/d1/9b7d46625d617c7df520d40d5ac6cdcdf20cbccb88fad4b5ecd476a6bb8d/ruff-0.12.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1b15599931a1a7a03c388b9c5df1bfa62be7ede6eb7ef753b272381f39c3d0ff", size = 11566350, upload-time = "2025-08-14T16:08:23.433Z" }, - { url = "https://files.pythonhosted.org/packages/59/20/b73132f66f2856bc29d2d263c6ca457f8476b0bbbe064dac3ac3337a270f/ruff-0.12.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3d02faa2977fb6f3f32ddb7828e212b7dd499c59eb896ae6c03ea5c303575756", size = 13270430, upload-time = "2025-08-14T16:08:25.837Z" }, - { url = "https://files.pythonhosted.org/packages/a2/21/eaf3806f0a3d4c6be0a69d435646fba775b65f3f2097d54898b0fd4bb12e/ruff-0.12.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:17d5b6b0b3a25259b69ebcba87908496e6830e03acfb929ef9fd4c58675fa2ea", size = 14264717, upload-time = "2025-08-14T16:08:27.907Z" }, - { url = "https://files.pythonhosted.org/packages/d2/82/1d0c53bd37dcb582b2c521d352fbf4876b1e28bc0d8894344198f6c9950d/ruff-0.12.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:72db7521860e246adbb43f6ef464dd2a532ef2ef1f5dd0d470455b8d9f1773e0", size = 13684331, upload-time = "2025-08-14T16:08:30.352Z" }, - { url = "https://files.pythonhosted.org/packages/3b/2f/1c5cf6d8f656306d42a686f1e207f71d7cebdcbe7b2aa18e4e8a0cb74da3/ruff-0.12.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a03242c1522b4e0885af63320ad754d53983c9599157ee33e77d748363c561ce", size = 12739151, upload-time = "2025-08-14T16:08:32.55Z" }, - { url = "https://files.pythonhosted.org/packages/47/09/25033198bff89b24d734e6479e39b1968e4c992e82262d61cdccaf11afb9/ruff-0.12.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fc83e4e9751e6c13b5046d7162f205d0a7bac5840183c5beebf824b08a27340", size = 12954992, upload-time = "2025-08-14T16:08:34.816Z" }, - { url = "https://files.pythonhosted.org/packages/52/8e/d0dbf2f9dca66c2d7131feefc386523404014968cd6d22f057763935ab32/ruff-0.12.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:881465ed56ba4dd26a691954650de6ad389a2d1fdb130fe51ff18a25639fe4bb", size = 12899569, upload-time = "2025-08-14T16:08:36.852Z" }, - { url = "https://files.pythonhosted.org/packages/a0/bd/b614d7c08515b1428ed4d3f1d4e3d687deffb2479703b90237682586fa66/ruff-0.12.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:43f07a3ccfc62cdb4d3a3348bf0588358a66da756aa113e071b8ca8c3b9826af", size = 11751983, upload-time = "2025-08-14T16:08:39.314Z" }, - { url = "https://files.pythonhosted.org/packages/58/d6/383e9f818a2441b1a0ed898d7875f11273f10882f997388b2b51cb2ae8b5/ruff-0.12.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:07adb221c54b6bba24387911e5734357f042e5669fa5718920ee728aba3cbadc", size = 11538635, upload-time = "2025-08-14T16:08:41.297Z" }, - { url = "https://files.pythonhosted.org/packages/20/9c/56f869d314edaa9fc1f491706d1d8a47747b9d714130368fbd69ce9024e9/ruff-0.12.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f5cd34fabfdea3933ab85d72359f118035882a01bff15bd1d2b15261d85d5f66", size = 12534346, upload-time = "2025-08-14T16:08:43.39Z" }, - { url = "https://files.pythonhosted.org/packages/bd/4b/d8b95c6795a6c93b439bc913ee7a94fda42bb30a79285d47b80074003ee7/ruff-0.12.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:f6be1d2ca0686c54564da8e7ee9e25f93bdd6868263805f8c0b8fc6a449db6d7", size = 13017021, upload-time = "2025-08-14T16:08:45.889Z" }, - { url = "https://files.pythonhosted.org/packages/c7/c1/5f9a839a697ce1acd7af44836f7c2181cdae5accd17a5cb85fcbd694075e/ruff-0.12.9-py3-none-win32.whl", hash = "sha256:cc7a37bd2509974379d0115cc5608a1a4a6c4bff1b452ea69db83c8855d53f93", size = 11734785, upload-time = "2025-08-14T16:08:48.062Z" }, - { url = "https://files.pythonhosted.org/packages/fa/66/cdddc2d1d9a9f677520b7cfc490d234336f523d4b429c1298de359a3be08/ruff-0.12.9-py3-none-win_amd64.whl", hash = "sha256:6fb15b1977309741d7d098c8a3cb7a30bc112760a00fb6efb7abc85f00ba5908", size = 12840654, upload-time = "2025-08-14T16:08:50.158Z" }, - { url = "https://files.pythonhosted.org/packages/ac/fd/669816bc6b5b93b9586f3c1d87cd6bc05028470b3ecfebb5938252c47a35/ruff-0.12.9-py3-none-win_arm64.whl", hash = "sha256:63c8c819739d86b96d500cce885956a1a48ab056bbcbc61b747ad494b2485089", size = 11949623, upload-time = "2025-08-14T16:08:52.233Z" }, + { url = "https://files.pythonhosted.org/packages/24/e7/560d049d15585d6c201f9eeacd2fd130def3741323e5ccf123786e0e3c95/ruff-0.12.10-py3-none-linux_armv6l.whl", hash = "sha256:8b593cb0fb55cc8692dac7b06deb29afda78c721c7ccfed22db941201b7b8f7b", size = 11935161, upload-time = "2025-08-21T18:22:26.965Z" }, + { url = "https://files.pythonhosted.org/packages/d1/b0/ad2464922a1113c365d12b8f80ed70fcfb39764288ac77c995156080488d/ruff-0.12.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ebb7333a45d56efc7c110a46a69a1b32365d5c5161e7244aaf3aa20ce62399c1", size = 12660884, upload-time = "2025-08-21T18:22:30.925Z" }, + { url = "https://files.pythonhosted.org/packages/d7/f1/97f509b4108d7bae16c48389f54f005b62ce86712120fd8b2d8e88a7cb49/ruff-0.12.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d59e58586829f8e4a9920788f6efba97a13d1fa320b047814e8afede381c6839", size = 11872754, upload-time = "2025-08-21T18:22:34.035Z" }, + { url = "https://files.pythonhosted.org/packages/12/ad/44f606d243f744a75adc432275217296095101f83f966842063d78eee2d3/ruff-0.12.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:822d9677b560f1fdeab69b89d1f444bf5459da4aa04e06e766cf0121771ab844", size = 12092276, upload-time = "2025-08-21T18:22:36.764Z" }, + { url = "https://files.pythonhosted.org/packages/06/1f/ed6c265e199568010197909b25c896d66e4ef2c5e1c3808caf461f6f3579/ruff-0.12.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:37b4a64f4062a50c75019c61c7017ff598cb444984b638511f48539d3a1c98db", size = 11734700, upload-time = "2025-08-21T18:22:39.822Z" }, + { url = "https://files.pythonhosted.org/packages/63/c5/b21cde720f54a1d1db71538c0bc9b73dee4b563a7dd7d2e404914904d7f5/ruff-0.12.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c6f4064c69d2542029b2a61d39920c85240c39837599d7f2e32e80d36401d6e", size = 13468783, upload-time = "2025-08-21T18:22:42.559Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/39369e6ac7f2a1848f22fb0b00b690492f20811a1ac5c1fd1d2798329263/ruff-0.12.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:059e863ea3a9ade41407ad71c1de2badfbe01539117f38f763ba42a1206f7559", size = 14436642, upload-time = "2025-08-21T18:22:45.612Z" }, + { url = "https://files.pythonhosted.org/packages/e3/03/5da8cad4b0d5242a936eb203b58318016db44f5c5d351b07e3f5e211bb89/ruff-0.12.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1bef6161e297c68908b7218fa6e0e93e99a286e5ed9653d4be71e687dff101cf", size = 13859107, upload-time = "2025-08-21T18:22:48.886Z" }, + { url = "https://files.pythonhosted.org/packages/19/19/dd7273b69bf7f93a070c9cec9494a94048325ad18fdcf50114f07e6bf417/ruff-0.12.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4f1345fbf8fb0531cd722285b5f15af49b2932742fc96b633e883da8d841896b", size = 12886521, upload-time = "2025-08-21T18:22:51.567Z" }, + { url = "https://files.pythonhosted.org/packages/c0/1d/b4207ec35e7babaee62c462769e77457e26eb853fbdc877af29417033333/ruff-0.12.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f68433c4fbc63efbfa3ba5db31727db229fa4e61000f452c540474b03de52a9", size = 13097528, upload-time = "2025-08-21T18:22:54.609Z" }, + { url = "https://files.pythonhosted.org/packages/ff/00/58f7b873b21114456e880b75176af3490d7a2836033779ca42f50de3b47a/ruff-0.12.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:141ce3d88803c625257b8a6debf4a0473eb6eed9643a6189b68838b43e78165a", size = 13080443, upload-time = "2025-08-21T18:22:57.413Z" }, + { url = "https://files.pythonhosted.org/packages/12/8c/9e6660007fb10189ccb78a02b41691288038e51e4788bf49b0a60f740604/ruff-0.12.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f3fc21178cd44c98142ae7590f42ddcb587b8e09a3b849cbc84edb62ee95de60", size = 11896759, upload-time = "2025-08-21T18:23:00.473Z" }, + { url = "https://files.pythonhosted.org/packages/67/4c/6d092bb99ea9ea6ebda817a0e7ad886f42a58b4501a7e27cd97371d0ba54/ruff-0.12.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7d1a4e0bdfafcd2e3e235ecf50bf0176f74dd37902f241588ae1f6c827a36c56", size = 11701463, upload-time = "2025-08-21T18:23:03.211Z" }, + { url = "https://files.pythonhosted.org/packages/59/80/d982c55e91df981f3ab62559371380616c57ffd0172d96850280c2b04fa8/ruff-0.12.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:e67d96827854f50b9e3e8327b031647e7bcc090dbe7bb11101a81a3a2cbf1cc9", size = 12691603, upload-time = "2025-08-21T18:23:06.935Z" }, + { url = "https://files.pythonhosted.org/packages/ad/37/63a9c788bbe0b0850611669ec6b8589838faf2f4f959647f2d3e320383ae/ruff-0.12.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ae479e1a18b439c59138f066ae79cc0f3ee250712a873d00dbafadaad9481e5b", size = 13164356, upload-time = "2025-08-21T18:23:10.225Z" }, + { url = "https://files.pythonhosted.org/packages/47/d4/1aaa7fb201a74181989970ebccd12f88c0fc074777027e2a21de5a90657e/ruff-0.12.10-py3-none-win32.whl", hash = "sha256:9de785e95dc2f09846c5e6e1d3a3d32ecd0b283a979898ad427a9be7be22b266", size = 11896089, upload-time = "2025-08-21T18:23:14.232Z" }, + { url = "https://files.pythonhosted.org/packages/ad/14/2ad38fd4037daab9e023456a4a40ed0154e9971f8d6aed41bdea390aabd9/ruff-0.12.10-py3-none-win_amd64.whl", hash = "sha256:7837eca8787f076f67aba2ca559cefd9c5cbc3a9852fd66186f4201b87c1563e", size = 13004616, upload-time = "2025-08-21T18:23:17.422Z" }, + { url = "https://files.pythonhosted.org/packages/24/3c/21cf283d67af33a8e6ed242396863af195a8a6134ec581524fd22b9811b6/ruff-0.12.10-py3-none-win_arm64.whl", hash = "sha256:cc138cc06ed9d4bfa9d667a65af7172b47840e1a98b02ce7011c391e54635ffc", size = 12074225, upload-time = "2025-08-21T18:23:20.137Z" }, ] [[package]] @@ -251,6 +260,7 @@ name = "spider-py" version = "0.0.1" source = { editable = "." } dependencies = [ + { name = "lark" }, { name = "mariadb" }, { name = "msgpack-types" }, ] @@ -264,6 +274,7 @@ dev = [ [package.metadata] requires-dist = [ + { name = "lark", specifier = ">=1.2.2" }, { name = "mariadb", specifier = ">=1.1.13" }, { name = "msgpack-types", specifier = ">=0.5.0" }, ]