diff --git a/setup.cfg b/setup.cfg index 22f792d4b..6d8134e91 100644 --- a/setup.cfg +++ b/setup.cfg @@ -74,7 +74,7 @@ install_requires = ujson==5.1.0 # required by aiocache urllib3==1.26.11 uvloop==0.17.0 - web3==6.0.0b9 + web3==6.2.0 dependency_links = https://github.com/aleph-im/py-libp2p/tarball/0.1.4-1-use-set#egg=libp2p @@ -99,7 +99,7 @@ exclude = testing = ipfshttpclient==0.8.0a2 # eth/web3 test dependency, for some reason more-itertools==8.14.0 - mypy==0.950 + mypy==1.2.0 pytest pytest-cov pytest-aiohttp diff --git a/src/aleph/chains/chaindata.py b/src/aleph/chains/chaindata.py index 367045a9b..1af14a4f6 100644 --- a/src/aleph/chains/chaindata.py +++ b/src/aleph/chains/chaindata.py @@ -1,6 +1,6 @@ import asyncio import json -from typing import Dict, Optional, List, Any, Mapping, Set, cast +from typing import Dict, Optional, List, Any, Mapping, Set, cast, Type, Union from aleph_message.models import StoreContent, ItemType, Chain, MessageType from pydantic import ValidationError @@ -177,7 +177,7 @@ def _get_tx_messages_smart_contract_protocol(tx: ChainTxDb) -> List[Dict[str, An Message validation should be left to the message processing pipeline. """ - payload_model = ( + payload_model: Union[Type[TezosMessageEventPayload], Type[MessageEvent]] = ( TezosMessageEventPayload if tx.chain == Chain.TEZOS else MessageEvent ) diff --git a/src/aleph/chains/ethereum.py b/src/aleph/chains/ethereum.py index 6f8b8a10d..1f9e69fc8 100644 --- a/src/aleph/chains/ethereum.py +++ b/src/aleph/chains/ethereum.py @@ -63,7 +63,7 @@ async def get_contract(config, web3: Web3): def get_logs_query(web3: Web3, contract, start_height, end_height): return web3.eth.get_logs( - {"address": contract.address, "fromBlock": start_height, "toBlock": end_height} # type: ignore[arg-type] + {"address": contract.address, "fromBlock": start_height, "toBlock": end_height} ) diff --git a/src/aleph/commands.py b/src/aleph/commands.py index f64e8170e..99ccdd4fd 100644 --- a/src/aleph/commands.py +++ b/src/aleph/commands.py @@ -66,7 +66,7 @@ async def init_node_cache(config: Config) -> NodeCache: return node_cache -async def main(args): +async def main(args: List[str]) -> None: """Main entry point allowing external calls Args: @@ -82,7 +82,7 @@ async def main(args): key_pair = generate_keypair(args.print_key) save_keys(key_pair, args.key_dir) if args.print_key: - print(key_pair.private_key.impl.export_key().decode("utf-8")) + print(key_pair.private_key.impl.export_key().decode("utf-8")) # type: ignore[attr-defined] return diff --git a/src/aleph/schemas/api/messages.py b/src/aleph/schemas/api/messages.py index dbf53bd03..5bba74961 100644 --- a/src/aleph/schemas/api/messages.py +++ b/src/aleph/schemas/api/messages.py @@ -1,5 +1,5 @@ import datetime as dt -from typing import Optional, Generic, TypeVar, Literal, List, Any, Union, Dict +from typing import Optional, Generic, TypeVar, Literal, List, Any, Union, Dict, Mapping from aleph_message.models import ( AggregateContent, @@ -8,7 +8,7 @@ ForgetContent, PostContent, ProgramContent, - StoreContent, + StoreContent, AlephMessage, ) from aleph_message.models import MessageType, ItemType from pydantic import BaseModel @@ -91,7 +91,7 @@ class StoreMessage( } -def format_message(message: Any) -> BaseMessage: +def format_message(message: Any) -> AlephMessage: message_cls = MESSAGE_CLS_DICT[message.type] return message_cls.from_orm(message) @@ -164,7 +164,7 @@ class ForgottenMessageStatus(BaseMessageStatus): class RejectedMessageStatus(BaseMessageStatus): status: MessageStatus = MessageStatus.REJECTED - message: Dict[str, Any] + message: Mapping[str, Any] error_code: ErrorCode details: Any diff --git a/src/aleph/schemas/base_messages.py b/src/aleph/schemas/base_messages.py index c1cf693a9..b8edd3dbb 100644 --- a/src/aleph/schemas/base_messages.py +++ b/src/aleph/schemas/base_messages.py @@ -4,7 +4,7 @@ import datetime as dt from hashlib import sha256 -from typing import Optional, Generic, TypeVar +from typing import Optional, Generic, TypeVar, Any, Mapping, cast from aleph_message.models import BaseContent, Chain from aleph_message.models import MessageType, ItemType @@ -62,7 +62,7 @@ def check_item_type(cls, values): return values @validator("item_hash") - def check_item_hash(cls, v, values): + def check_item_hash(cls, v: Any, values: Mapping[str, Any]): """ For inline item types, check that the item hash is equal to the hash of the item content. @@ -73,7 +73,7 @@ def check_item_hash(cls, v, values): raise ValueError("Could not determine item type") if item_type == ItemType.inline: - item_content: str = values.get("item_content") + item_content = cast(Optional[str], values.get("item_content")) if item_content is None: raise ValueError("Could not find inline item content") diff --git a/src/aleph/web/controllers/accounts.py b/src/aleph/web/controllers/accounts.py index 12f05595c..7e037a00b 100644 --- a/src/aleph/web/controllers/accounts.py +++ b/src/aleph/web/controllers/accounts.py @@ -4,7 +4,7 @@ from aiohttp import web from aleph_message.models import MessageType -from pydantic import ValidationError +from pydantic import ValidationError, parse_obj_as from aleph.db.accessors.balances import get_total_balance from aleph.db.accessors.files import ( @@ -15,7 +15,7 @@ from aleph.schemas.api.accounts import ( GetAccountBalanceResponse, GetAccountFilesResponse, - GetAccountFilesQueryParams, + GetAccountFilesQueryParams, GetAccountFilesResponseItem, ) from aleph.types.db_session import DbSessionFactory from aleph.web.controllers.app_state_getters import get_session_factory_from_request @@ -105,7 +105,7 @@ async def get_account_files(request: web.Request) -> web.Response: response = GetAccountFilesResponse( address=address, total_size=total_size, - files=file_pins, + files=parse_obj_as(List[GetAccountFilesResponseItem], file_pins), pagination_page=query_params.page, pagination_total=nb_files, pagination_per_page=query_params.pagination, diff --git a/src/aleph/web/controllers/aggregates.py b/src/aleph/web/controllers/aggregates.py index 9d38d19dc..223d6c9fd 100644 --- a/src/aleph/web/controllers/aggregates.py +++ b/src/aleph/web/controllers/aggregates.py @@ -28,7 +28,7 @@ def split_str(cls, v): return v -async def address_aggregate(request): +async def address_aggregate(request: web.Request) -> web.Response: """Returns the aggregate of an address. TODO: handle filter on a single key, or even subkey. """ diff --git a/src/aleph/web/controllers/channels.py b/src/aleph/web/controllers/channels.py index 6ae1a3cff..b7c4b7c09 100644 --- a/src/aleph/web/controllers/channels.py +++ b/src/aleph/web/controllers/channels.py @@ -5,7 +5,8 @@ from aleph.db.accessors.messages import get_distinct_channels from aleph.types.channel import Channel -from aleph.types.db_session import DbSessionFactory, DbSession +from aleph.types.db_session import DbSession +from aleph.web.controllers.app_state_getters import get_session_factory_from_request @cached(ttl=60 * 120, cache=SimpleMemoryCache, timeout=120) @@ -14,13 +15,13 @@ async def get_channels(session: DbSession) -> List[Channel]: return list(channels) -async def used_channels(request): +async def used_channels(request: web.Request) -> web.Response: """All used channels list TODO: do we need pagination? """ - session_factory: DbSessionFactory = request.app["session_factory"] + session_factory = get_session_factory_from_request(request) with session_factory() as session: channels = await get_channels(session) diff --git a/src/aleph/web/controllers/main.py b/src/aleph/web/controllers/main.py index 07a441aca..8088926d9 100644 --- a/src/aleph/web/controllers/main.py +++ b/src/aleph/web/controllers/main.py @@ -14,7 +14,7 @@ @aiohttp_jinja2.template("index.html") -async def index(request) -> Dict: +async def index(request: web.Request) -> Dict: """Index of aleph.""" session_factory: DbSessionFactory = get_session_factory_from_request(request) @@ -23,7 +23,7 @@ async def index(request) -> Dict: return asdict(await get_metrics(session=session, node_cache=node_cache)) -async def status_ws(request): +async def status_ws(request: web.Request) -> web.WebSocketResponse: ws = web.WebSocketResponse() await ws.prepare(request) @@ -47,13 +47,13 @@ async def status_ws(request): await asyncio.sleep(2) -async def metrics(request): +async def metrics(request: web.Request) -> web.Response: """Prometheus compatible metrics. Naming convention: https://prometheus.io/docs/practices/naming/ """ - session_factory: DbSessionFactory = get_session_factory_from_request(request) + session_factory = get_session_factory_from_request(request) node_cache = get_node_cache_from_request(request) with session_factory() as session: @@ -64,7 +64,7 @@ async def metrics(request): ) -async def metrics_json(request): +async def metrics_json(request: web.Request) -> web.Response: """JSON version of the Prometheus metrics.""" session_factory: DbSessionFactory = get_session_factory_from_request(request) node_cache = get_node_cache_from_request(request) diff --git a/src/aleph/web/controllers/messages.py b/src/aleph/web/controllers/messages.py index 4c8d5465a..10d1b145b 100644 --- a/src/aleph/web/controllers/messages.py +++ b/src/aleph/web/controllers/messages.py @@ -31,6 +31,7 @@ from aleph.types.db_session import DbSessionFactory, DbSession from aleph.types.message_status import MessageStatus from aleph.types.sort_order import SortOrder, SortBy +from aleph.web.controllers.app_state_getters import get_session_factory_from_request from aleph.web.controllers.utils import ( DEFAULT_MESSAGES_PER_PAGE, DEFAULT_PAGE, @@ -195,7 +196,7 @@ def format_response( return web.json_response(text=aleph_json.dumps(response).decode("utf-8")) -async def view_messages_list(request): +async def view_messages_list(request: web.Request) -> web.Response: """Messages list view with filters""" try: @@ -213,7 +214,7 @@ async def view_messages_list(request): pagination_page = query_params.page pagination_per_page = query_params.pagination - session_factory: DbSessionFactory = request.app["session_factory"] + session_factory = get_session_factory_from_request(request) with session_factory() as session: messages = get_matching_messages( session, include_confirmations=True, **find_filters diff --git a/src/aleph/web/controllers/storage.py b/src/aleph/web/controllers/storage.py index f261df896..8075ba2da 100644 --- a/src/aleph/web/controllers/storage.py +++ b/src/aleph/web/controllers/storage.py @@ -168,9 +168,13 @@ async def get_raw_hash(request): return response -async def get_file_pins_count(request): +async def get_file_pins_count(request: web.Request) -> web.Response: item_hash = request.match_info.get("hash", None) - session_factory: DbSessionFactory = request.app["session_factory"] + + if item_hash is None: + raise web.HTTPBadRequest(text="No hash provided") + + session_factory = get_session_factory_from_request(request) with session_factory() as session: count = count_file_pins(session=session, file_hash=item_hash) return web.json_response(data=count) diff --git a/tests/chains/test_tezos.py b/tests/chains/test_tezos.py index 6bd926d8c..11508fa8f 100644 --- a/tests/chains/test_tezos.py +++ b/tests/chains/test_tezos.py @@ -129,7 +129,7 @@ def test_datetime_to_iso_8601(): def test_indexer_event_to_aleph_message(message_type: str, message_content: str): indexer_event = IndexerMessageEvent( source="KT1BfL57oZfptdtMFZ9LNakEPvuPPA2urdSW", - timestamp="2022-11-16T00:00:00Z", + timestamp=dt.datetime(2022, 11, 16, tzinfo=dt.timezone.utc), type="MessageEvent", operationHash="oorMNgusX6RxZ4NhzYriVDN8HDeMBNkjD3E8kx9a7j7dRRDGkzz", blockLevel=584664, diff --git a/tests/web/controllers/test_metrics.py b/tests/web/controllers/test_metrics.py index 17506fefe..6ec4ea3a2 100644 --- a/tests/web/controllers/test_metrics.py +++ b/tests/web/controllers/test_metrics.py @@ -14,7 +14,7 @@ def test_format_dict_for_prometheus(): ) == '{a=1,b=2.2,c="3"}' -def test_format_dataclass_for_prometheus(): +def test_format_dataclass_for_prometheus() -> None: @dataclass class Simple: