mirror of
https://github.com/chatmail/core.git
synced 2026-05-17 05:46:30 +03:00
Refine Python CI
Add lint environment to `deltachat-rpc-client/` and set line length to 120, same as in `python/`. Switch from flake8 to ruff. Fix ruff warnings.
This commit is contained in:
@@ -8,3 +8,18 @@ from .contact import Contact
|
||||
from .deltachat import DeltaChat
|
||||
from .message import Message
|
||||
from .rpc import Rpc
|
||||
|
||||
__all__ = [
|
||||
"Account",
|
||||
"AttrDict",
|
||||
"Bot",
|
||||
"Chat",
|
||||
"Client",
|
||||
"Contact",
|
||||
"DeltaChat",
|
||||
"EventType",
|
||||
"Message",
|
||||
"Rpc",
|
||||
"run_bot_cli",
|
||||
"run_client_cli",
|
||||
]
|
||||
|
||||
@@ -30,12 +30,7 @@ class AttrDict(dict):
|
||||
"""Dictionary that allows accessing values usin the "dot notation" as attributes."""
|
||||
|
||||
def __init__(self, *args, **kwargs) -> None:
|
||||
super().__init__(
|
||||
{
|
||||
_camel_to_snake(key): _to_attrdict(value)
|
||||
for key, value in dict(*args, **kwargs).items()
|
||||
}
|
||||
)
|
||||
super().__init__({_camel_to_snake(key): _to_attrdict(value) for key, value in dict(*args, **kwargs).items()})
|
||||
|
||||
def __getattr__(self, attr):
|
||||
if attr in self:
|
||||
@@ -51,7 +46,7 @@ class AttrDict(dict):
|
||||
async def run_client_cli(
|
||||
hooks: Optional[Iterable[Tuple[Callable, Union[type, "EventFilter"]]]] = None,
|
||||
argv: Optional[list] = None,
|
||||
**kwargs
|
||||
**kwargs,
|
||||
) -> None:
|
||||
"""Run a simple command line app, using the given hooks.
|
||||
|
||||
@@ -65,7 +60,7 @@ async def run_client_cli(
|
||||
async def run_bot_cli(
|
||||
hooks: Optional[Iterable[Tuple[Callable, Union[type, "EventFilter"]]]] = None,
|
||||
argv: Optional[list] = None,
|
||||
**kwargs
|
||||
**kwargs,
|
||||
) -> None:
|
||||
"""Run a simple bot command line using the given hooks.
|
||||
|
||||
@@ -80,7 +75,7 @@ async def _run_cli(
|
||||
client_type: Type["Client"],
|
||||
hooks: Optional[Iterable[Tuple[Callable, Union[type, "EventFilter"]]]] = None,
|
||||
argv: Optional[list] = None,
|
||||
**kwargs
|
||||
**kwargs,
|
||||
) -> None:
|
||||
from .deltachat import DeltaChat
|
||||
from .rpc import Rpc
|
||||
@@ -107,12 +102,9 @@ async def _run_cli(
|
||||
client = client_type(account, hooks)
|
||||
client.logger.debug("Running deltachat core %s", core_version)
|
||||
if not await client.is_configured():
|
||||
assert (
|
||||
args.email and args.password
|
||||
), "Account is not configured and email and password must be provided"
|
||||
asyncio.create_task(
|
||||
client.configure(email=args.email, password=args.password)
|
||||
)
|
||||
assert args.email, "Account is not configured and email must be provided"
|
||||
assert args.password, "Account is not configured and password must be provided"
|
||||
asyncio.create_task(client.configure(email=args.email, password=args.password))
|
||||
await client.run_forever()
|
||||
|
||||
|
||||
|
||||
@@ -89,9 +89,7 @@ class Account:
|
||||
"""Configure an account."""
|
||||
await self._rpc.configure(self.id)
|
||||
|
||||
async def create_contact(
|
||||
self, obj: Union[int, str, Contact], name: Optional[str] = None
|
||||
) -> Contact:
|
||||
async def create_contact(self, obj: Union[int, str, Contact], name: Optional[str] = None) -> Contact:
|
||||
"""Create a new Contact or return an existing one.
|
||||
|
||||
Calling this method will always result in the same
|
||||
@@ -120,10 +118,7 @@ class Account:
|
||||
async def get_blocked_contacts(self) -> List[AttrDict]:
|
||||
"""Return a list with snapshots of all blocked contacts."""
|
||||
contacts = await self._rpc.get_blocked_contacts(self.id)
|
||||
return [
|
||||
AttrDict(contact=Contact(self, contact["id"]), **contact)
|
||||
for contact in contacts
|
||||
]
|
||||
return [AttrDict(contact=Contact(self, contact["id"]), **contact) for contact in contacts]
|
||||
|
||||
async def get_contacts(
|
||||
self,
|
||||
@@ -148,10 +143,7 @@ class Account:
|
||||
|
||||
if snapshot:
|
||||
contacts = await self._rpc.get_contacts(self.id, flags, query)
|
||||
return [
|
||||
AttrDict(contact=Contact(self, contact["id"]), **contact)
|
||||
for contact in contacts
|
||||
]
|
||||
return [AttrDict(contact=Contact(self, contact["id"]), **contact) for contact in contacts]
|
||||
contacts = await self._rpc.get_contact_ids(self.id, flags, query)
|
||||
return [Contact(self, contact_id) for contact_id in contacts]
|
||||
|
||||
@@ -192,9 +184,7 @@ class Account:
|
||||
if alldone_hint:
|
||||
flags |= ChatlistFlag.ADD_ALLDONE_HINT
|
||||
|
||||
entries = await self._rpc.get_chatlist_entries(
|
||||
self.id, flags, query, contact and contact.id
|
||||
)
|
||||
entries = await self._rpc.get_chatlist_entries(self.id, flags, query, contact and contact.id)
|
||||
if not snapshot:
|
||||
return [Chat(self, entry[0]) for entry in entries]
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ class Chat:
|
||||
"""
|
||||
if duration is not None:
|
||||
assert duration > 0, "Invalid duration"
|
||||
dur: Union[str, dict] = dict(Until=duration)
|
||||
dur: Union[str, dict] = {"Until": duration}
|
||||
else:
|
||||
dur = "Forever"
|
||||
await self._rpc.set_chat_mute_duration(self.account.id, self.id, dur)
|
||||
@@ -74,27 +74,19 @@ class Chat:
|
||||
|
||||
async def pin(self) -> None:
|
||||
"""Pin this chat."""
|
||||
await self._rpc.set_chat_visibility(
|
||||
self.account.id, self.id, ChatVisibility.PINNED
|
||||
)
|
||||
await self._rpc.set_chat_visibility(self.account.id, self.id, ChatVisibility.PINNED)
|
||||
|
||||
async def unpin(self) -> None:
|
||||
"""Unpin this chat."""
|
||||
await self._rpc.set_chat_visibility(
|
||||
self.account.id, self.id, ChatVisibility.NORMAL
|
||||
)
|
||||
await self._rpc.set_chat_visibility(self.account.id, self.id, ChatVisibility.NORMAL)
|
||||
|
||||
async def archive(self) -> None:
|
||||
"""Archive this chat."""
|
||||
await self._rpc.set_chat_visibility(
|
||||
self.account.id, self.id, ChatVisibility.ARCHIVED
|
||||
)
|
||||
await self._rpc.set_chat_visibility(self.account.id, self.id, ChatVisibility.ARCHIVED)
|
||||
|
||||
async def unarchive(self) -> None:
|
||||
"""Unarchive this chat."""
|
||||
await self._rpc.set_chat_visibility(
|
||||
self.account.id, self.id, ChatVisibility.NORMAL
|
||||
)
|
||||
await self._rpc.set_chat_visibility(self.account.id, self.id, ChatVisibility.NORMAL)
|
||||
|
||||
async def set_name(self, name: str) -> None:
|
||||
"""Set name of this chat."""
|
||||
@@ -133,9 +125,7 @@ class Chat:
|
||||
if isinstance(quoted_msg, Message):
|
||||
quoted_msg = quoted_msg.id
|
||||
|
||||
msg_id, _ = await self._rpc.misc_send_msg(
|
||||
self.account.id, self.id, text, file, location, quoted_msg
|
||||
)
|
||||
msg_id, _ = await self._rpc.misc_send_msg(self.account.id, self.id, text, file, location, quoted_msg)
|
||||
return Message(self.account, msg_id)
|
||||
|
||||
async def send_text(self, text: str) -> Message:
|
||||
@@ -241,23 +231,17 @@ class Chat:
|
||||
timestamp_to: Optional[datetime] = None,
|
||||
) -> List[AttrDict]:
|
||||
"""Get list of location snapshots for the given contact in the given timespan."""
|
||||
time_from = (
|
||||
calendar.timegm(timestamp_from.utctimetuple()) if timestamp_from else 0
|
||||
)
|
||||
time_from = calendar.timegm(timestamp_from.utctimetuple()) if timestamp_from else 0
|
||||
time_to = calendar.timegm(timestamp_to.utctimetuple()) if timestamp_to else 0
|
||||
contact_id = contact.id if contact else 0
|
||||
|
||||
result = await self._rpc.get_locations(
|
||||
self.account.id, self.id, contact_id, time_from, time_to
|
||||
)
|
||||
result = await self._rpc.get_locations(self.account.id, self.id, contact_id, time_from, time_to)
|
||||
locations = []
|
||||
contacts: Dict[int, Contact] = {}
|
||||
for loc in result:
|
||||
loc = AttrDict(loc)
|
||||
loc["chat"] = self
|
||||
loc["contact"] = contacts.setdefault(
|
||||
loc.contact_id, Contact(self.account, loc.contact_id)
|
||||
)
|
||||
loc["contact"] = contacts.setdefault(loc.contact_id, Contact(self.account, loc.contact_id))
|
||||
loc["message"] = Message(self.account, loc.msg_id)
|
||||
locations.append(loc)
|
||||
return locations
|
||||
|
||||
@@ -47,15 +47,11 @@ class Client:
|
||||
self._should_process_messages = 0
|
||||
self.add_hooks(hooks or [])
|
||||
|
||||
def add_hooks(
|
||||
self, hooks: Iterable[Tuple[Callable, Union[type, EventFilter]]]
|
||||
) -> None:
|
||||
def add_hooks(self, hooks: Iterable[Tuple[Callable, Union[type, EventFilter]]]) -> None:
|
||||
for hook, event in hooks:
|
||||
self.add_hook(hook, event)
|
||||
|
||||
def add_hook(
|
||||
self, hook: Callable, event: Union[type, EventFilter] = RawEvent
|
||||
) -> None:
|
||||
def add_hook(self, hook: Callable, event: Union[type, EventFilter] = RawEvent) -> None:
|
||||
"""Register hook for the given event filter."""
|
||||
if isinstance(event, type):
|
||||
event = event()
|
||||
@@ -64,7 +60,7 @@ class Client:
|
||||
isinstance(
|
||||
event,
|
||||
(NewMessage, MemberListChanged, GroupImageChanged, GroupNameChanged),
|
||||
)
|
||||
),
|
||||
)
|
||||
self._hooks.setdefault(type(event), set()).add((hook, event))
|
||||
|
||||
@@ -76,7 +72,7 @@ class Client:
|
||||
isinstance(
|
||||
event,
|
||||
(NewMessage, MemberListChanged, GroupImageChanged, GroupNameChanged),
|
||||
)
|
||||
),
|
||||
)
|
||||
self._hooks.get(type(event), set()).remove((hook, event))
|
||||
|
||||
@@ -95,9 +91,7 @@ class Client:
|
||||
"""Process events forever."""
|
||||
await self.run_until(lambda _: False)
|
||||
|
||||
async def run_until(
|
||||
self, func: Callable[[AttrDict], Union[bool, Coroutine]]
|
||||
) -> AttrDict:
|
||||
async def run_until(self, func: Callable[[AttrDict], Union[bool, Coroutine]]) -> AttrDict:
|
||||
"""Process events until the given callable evaluates to True.
|
||||
|
||||
The callable should accept an AttrDict object representing the
|
||||
@@ -122,9 +116,7 @@ class Client:
|
||||
if stop:
|
||||
return event
|
||||
|
||||
async def _on_event(
|
||||
self, event: AttrDict, filter_type: Type[EventFilter] = RawEvent
|
||||
) -> None:
|
||||
async def _on_event(self, event: AttrDict, filter_type: Type[EventFilter] = RawEvent) -> None:
|
||||
for hook, evfilter in self._hooks.get(filter_type, []):
|
||||
if await evfilter.filter(event):
|
||||
try:
|
||||
@@ -133,11 +125,7 @@ class Client:
|
||||
self.logger.exception(ex)
|
||||
|
||||
async def _parse_command(self, event: AttrDict) -> None:
|
||||
cmds = [
|
||||
hook[1].command
|
||||
for hook in self._hooks.get(NewMessage, [])
|
||||
if hook[1].command
|
||||
]
|
||||
cmds = [hook[1].command for hook in self._hooks.get(NewMessage, []) if hook[1].command]
|
||||
parts = event.message_snapshot.text.split(maxsplit=1)
|
||||
payload = parts[1] if len(parts) > 1 else ""
|
||||
cmd = parts.pop(0)
|
||||
@@ -202,11 +190,7 @@ class Client:
|
||||
for message in await self.account.get_fresh_messages_in_arrival_order():
|
||||
snapshot = await message.get_snapshot()
|
||||
await self._on_new_msg(snapshot)
|
||||
if (
|
||||
snapshot.is_info
|
||||
and snapshot.system_message_type
|
||||
!= SystemMessageType.WEBXDC_INFO_MESSAGE
|
||||
):
|
||||
if snapshot.is_info and snapshot.system_message_type != SystemMessageType.WEBXDC_INFO_MESSAGE:
|
||||
await self._handle_info_msg(snapshot)
|
||||
await snapshot.message.mark_seen()
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ from .const import EventType
|
||||
|
||||
def _tuple_of(obj, type_: type) -> tuple:
|
||||
if not obj:
|
||||
return tuple()
|
||||
return ()
|
||||
if isinstance(obj, type_):
|
||||
obj = (obj,)
|
||||
|
||||
@@ -39,7 +39,7 @@ class EventFilter(ABC):
|
||||
"""Return True if two event filters are equal."""
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self.__eq__(other)
|
||||
return not self == other
|
||||
|
||||
async def _call_func(self, event) -> bool:
|
||||
if not self.func:
|
||||
@@ -65,9 +65,7 @@ class RawEvent(EventFilter):
|
||||
should be dispatched or not.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, types: Union[None, EventType, Iterable[EventType]] = None, **kwargs
|
||||
):
|
||||
def __init__(self, types: Union[None, EventType, Iterable[EventType]] = None, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
try:
|
||||
self.types = _tuple_of(types, EventType)
|
||||
|
||||
@@ -49,22 +49,14 @@ class Message:
|
||||
"""Mark the message as seen."""
|
||||
await self._rpc.markseen_msgs(self.account.id, [self.id])
|
||||
|
||||
async def send_webxdc_status_update(
|
||||
self, update: Union[dict, str], description: str
|
||||
) -> None:
|
||||
async def send_webxdc_status_update(self, update: Union[dict, str], description: str) -> None:
|
||||
"""Send a webxdc status update. This message must be a webxdc."""
|
||||
if not isinstance(update, str):
|
||||
update = json.dumps(update)
|
||||
await self._rpc.send_webxdc_status_update(
|
||||
self.account.id, self.id, update, description
|
||||
)
|
||||
await self._rpc.send_webxdc_status_update(self.account.id, self.id, update, description)
|
||||
|
||||
async def get_webxdc_status_updates(self, last_known_serial: int = 0) -> list:
|
||||
return json.loads(
|
||||
await self._rpc.get_webxdc_status_updates(
|
||||
self.account.id, self.id, last_known_serial
|
||||
)
|
||||
)
|
||||
return json.loads(await self._rpc.get_webxdc_status_updates(self.account.id, self.id, last_known_serial))
|
||||
|
||||
async def get_webxdc_info(self) -> dict:
|
||||
return await self._rpc.get_webxdc_info(self.account.id, self.id)
|
||||
|
||||
@@ -67,9 +67,7 @@ class ACFactory:
|
||||
) -> Message:
|
||||
if not from_account:
|
||||
from_account = (await self.get_online_accounts(1))[0]
|
||||
to_contact = await from_account.create_contact(
|
||||
await to_account.get_config("addr")
|
||||
)
|
||||
to_contact = await from_account.create_contact(await to_account.get_config("addr"))
|
||||
if group:
|
||||
to_chat = await from_account.create_group(group)
|
||||
await to_chat.add_contact(to_contact)
|
||||
|
||||
@@ -30,7 +30,7 @@ class Rpc:
|
||||
"deltachat-rpc-server",
|
||||
stdin=asyncio.subprocess.PIPE,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
**self._kwargs
|
||||
**self._kwargs,
|
||||
)
|
||||
self.id = 0
|
||||
self.event_queues = {}
|
||||
@@ -46,7 +46,7 @@ class Rpc:
|
||||
await self.start()
|
||||
return self
|
||||
|
||||
async def __aexit__(self, exc_type, exc, tb):
|
||||
async def __aexit__(self, _exc_type, _exc, _tb):
|
||||
await self.close()
|
||||
|
||||
async def reader_loop(self) -> None:
|
||||
@@ -97,5 +97,6 @@ class Rpc:
|
||||
raise JsonRpcError(response["error"])
|
||||
if "result" in response:
|
||||
return response["result"]
|
||||
return None
|
||||
|
||||
return method
|
||||
|
||||
Reference in New Issue
Block a user