Skip to content

Commit

Permalink
Merge 'stable' into 'master'
Browse files Browse the repository at this point in the history
Resolved conflicts due to asyncio removal.
  • Loading branch information
link2xt committed Oct 8, 2023
2 parents a119b24 + 09798df commit 37383c1
Show file tree
Hide file tree
Showing 21 changed files with 644 additions and 650 deletions.
23 changes: 8 additions & 15 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
name: Lint Rust
runs-on: ubuntu-latest
env:
RUSTUP_TOOLCHAIN: 1.72.0
RUSTUP_TOOLCHAIN: 1.73.0
steps:
- uses: actions/checkout@v3
- name: Install rustfmt and clippy
Expand Down Expand Up @@ -81,11 +81,11 @@ jobs:
matrix:
include:
- os: ubuntu-latest
rust: 1.71.0
rust: 1.73.0
- os: windows-latest
rust: 1.71.0
rust: 1.73.0
- os: macos-latest
rust: 1.71.0
rust: 1.73.0

# Minimum Supported Rust Version = 1.67.0
- os: ubuntu-latest
Expand Down Expand Up @@ -229,27 +229,20 @@ jobs:
fail-fast: false
matrix:
include:
# Async Python bindings do not depend on Python version,
# but are tested on Python 3.11 until Python 3.12 support
# is added to `aiohttp` dependency:
# https://github.com/aio-libs/aiohttp/issues/7646
- os: ubuntu-latest
python: 3.11
python: 3.12
- os: macos-latest
python: 3.11
python: 3.12

# PyPy tests
- os: ubuntu-latest
python: pypy3.10
- os: macos-latest
python: pypy3.10

# Minimum Supported Python Version = 3.8
#
# Python 3.7 has at least one known bug related to starting subprocesses
# in asyncio programs: <https://bugs.python.org/issue35621>
# Minimum Supported Python Version = 3.7
- os: ubuntu-latest
python: 3.8
python: 3.7

runs-on: ${{ matrix.os }}
steps:
Expand Down
9 changes: 4 additions & 5 deletions deltachat-repl/src/cmdline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,7 @@ async fn poke_spec(context: &Context, spec: Option<&str>) -> bool {
/* import a directory */
let dir_name = std::path::Path::new(&real_spec);
let dir = fs::read_dir(dir_name).await;
if dir.is_err() {
error!(context, "Import: Cannot open directory \"{}\".", &real_spec,);
return false;
} else {
let mut dir = dir.unwrap();
if let Ok(mut dir) = dir {
while let Ok(Some(entry)) = dir.next_entry().await {
let name_f = entry.file_name();
let name = name_f.to_string_lossy();
Expand All @@ -155,6 +151,9 @@ async fn poke_spec(context: &Context, spec: Option<&str>) -> bool {
}
}
}
} else {
error!(context, "Import: Cannot open directory \"{}\".", &real_spec);
return false;
}
}
println!("Import: {} items read from \"{}\".", read_cnt, &real_spec);
Expand Down
25 changes: 10 additions & 15 deletions deltachat-rpc-client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,14 @@ $ tox --devenv env
$ . env/bin/activate
```

It is recommended to use IPython, because it supports using `await` directly
from the REPL.

```
$ pip install ipython
$ PATH="../target/debug:$PATH" ipython
...
In [1]: from deltachat_rpc_client import *
In [2]: rpc = Rpc()
In [3]: await rpc.start()
In [4]: dc = DeltaChat(rpc)
In [5]: system_info = await dc.get_system_info()
In [6]: system_info["level"]
Out[6]: 'awesome'
In [7]: await rpc.close()
```
$ python
>>> from deltachat_rpc_client import *
>>> rpc = Rpc()
>>> rpc.start()
>>> dc = DeltaChat(rpc)
>>> system_info = dc.get_system_info()
>>> system_info["level"]
'awesome'
>>> rpc.close()
```
10 changes: 4 additions & 6 deletions deltachat-rpc-client/examples/echobot.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,21 @@
it will echo back any text send to it, it also will print to console all Delta Chat core events.
Pass --help to the CLI to see available options.
"""
import asyncio

from deltachat_rpc_client import events, run_bot_cli

hooks = events.HookCollection()


@hooks.on(events.RawEvent)
async def log_event(event):
def log_event(event):
print(event)


@hooks.on(events.NewMessage)
async def echo(event):
def echo(event):
snapshot = event.message_snapshot
await snapshot.chat.send_text(snapshot.text)
snapshot.chat.send_text(snapshot.text)


if __name__ == "__main__":
asyncio.run(run_bot_cli(hooks))
run_bot_cli(hooks)
40 changes: 20 additions & 20 deletions deltachat-rpc-client/examples/echobot_advanced.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,72 +3,72 @@
it will echo back any message that has non-empty text and also supports the /help command.
"""
import asyncio
import logging
import sys
from threading import Thread

from deltachat_rpc_client import Bot, DeltaChat, EventType, Rpc, events

hooks = events.HookCollection()


@hooks.on(events.RawEvent)
async def log_event(event):
def log_event(event):
if event.kind == EventType.INFO:
logging.info(event.msg)
elif event.kind == EventType.WARNING:
logging.warning(event.msg)


@hooks.on(events.RawEvent(EventType.ERROR))
async def log_error(event):
def log_error(event):
logging.error(event.msg)


@hooks.on(events.MemberListChanged)
async def on_memberlist_changed(event):
def on_memberlist_changed(event):
logging.info("member %s was %s", event.member, "added" if event.member_added else "removed")


@hooks.on(events.GroupImageChanged)
async def on_group_image_changed(event):
def on_group_image_changed(event):
logging.info("group image %s", "deleted" if event.image_deleted else "changed")


@hooks.on(events.GroupNameChanged)
async def on_group_name_changed(event):
def on_group_name_changed(event):
logging.info("group name changed, old name: %s", event.old_name)


@hooks.on(events.NewMessage(func=lambda e: not e.command))
async def echo(event):
def echo(event):
snapshot = event.message_snapshot
if snapshot.text or snapshot.file:
await snapshot.chat.send_message(text=snapshot.text, file=snapshot.file)
snapshot.chat.send_message(text=snapshot.text, file=snapshot.file)


@hooks.on(events.NewMessage(command="/help"))
async def help_command(event):
def help_command(event):
snapshot = event.message_snapshot
await snapshot.chat.send_text("Send me any message and I will echo it back")
snapshot.chat.send_text("Send me any message and I will echo it back")


async def main():
async with Rpc() as rpc:
def main():
with Rpc() as rpc:
deltachat = DeltaChat(rpc)
system_info = await deltachat.get_system_info()
system_info = deltachat.get_system_info()
logging.info("Running deltachat core %s", system_info.deltachat_core_version)

accounts = await deltachat.get_all_accounts()
account = accounts[0] if accounts else await deltachat.add_account()
accounts = deltachat.get_all_accounts()
account = accounts[0] if accounts else deltachat.add_account()

bot = Bot(account, hooks)
if not await bot.is_configured():
# Save a reference to avoid garbage collection of the task.
_configure_task = asyncio.create_task(bot.configure(email=sys.argv[1], password=sys.argv[2]))
await bot.run_forever()
if not bot.is_configured():
configure_thread = Thread(run=bot.configure, kwargs={"email": sys.argv[1], "password": sys.argv[2]})
configure_thread.start()
bot.run_forever()


if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
asyncio.run(main())
main()
41 changes: 20 additions & 21 deletions deltachat-rpc-client/examples/echobot_no_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,44 @@
"""
Example echo bot without using hooks
"""
import asyncio
import logging
import sys

from deltachat_rpc_client import DeltaChat, EventType, Rpc, SpecialContactId


async def main():
async with Rpc() as rpc:
def main():
with Rpc() as rpc:
deltachat = DeltaChat(rpc)
system_info = await deltachat.get_system_info()
system_info = deltachat.get_system_info()
logging.info("Running deltachat core %s", system_info["deltachat_core_version"])

accounts = await deltachat.get_all_accounts()
account = accounts[0] if accounts else await deltachat.add_account()
accounts = deltachat.get_all_accounts()
account = accounts[0] if accounts else deltachat.add_account()

await account.set_config("bot", "1")
if not await account.is_configured():
account.set_config("bot", "1")
if not account.is_configured():
logging.info("Account is not configured, configuring")
await account.set_config("addr", sys.argv[1])
await account.set_config("mail_pw", sys.argv[2])
await account.configure()
account.set_config("addr", sys.argv[1])
account.set_config("mail_pw", sys.argv[2])
account.configure()
logging.info("Configured")
else:
logging.info("Account is already configured")
await deltachat.start_io()
deltachat.start_io()

async def process_messages():
for message in await account.get_next_messages():
snapshot = await message.get_snapshot()
def process_messages():
for message in account.get_next_messages():
snapshot = message.get_snapshot()
if snapshot.from_id != SpecialContactId.SELF and not snapshot.is_bot and not snapshot.is_info:
await snapshot.chat.send_text(snapshot.text)
await snapshot.message.mark_seen()
snapshot.chat.send_text(snapshot.text)
snapshot.message.mark_seen()

# Process old messages.
await process_messages()
process_messages()

while True:
event = await account.wait_for_event()
event = account.wait_for_event()
if event["type"] == EventType.INFO:
logging.info("%s", event["msg"])
elif event["type"] == EventType.WARNING:
Expand All @@ -49,9 +48,9 @@ async def process_messages():
logging.error("%s", event["msg"])
elif event["type"] == EventType.INCOMING_MSG:
logging.info("Got an incoming message")
await process_messages()
process_messages()


if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
asyncio.run(main())
main()
3 changes: 0 additions & 3 deletions deltachat-rpc-client/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ build-backend = "setuptools.build_meta"
[project]
name = "deltachat-rpc-client"
description = "Python client for Delta Chat core JSON-RPC interface"
dependencies = [
"aiohttp"
]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Framework :: AsyncIO",
Expand Down
2 changes: 1 addition & 1 deletion deltachat-rpc-client/src/deltachat_rpc_client/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Delta Chat asynchronous high-level API"""
"""Delta Chat JSON-RPC high-level API"""
from ._utils import AttrDict, run_bot_cli, run_client_cli
from .account import Account
from .chat import Chat
Expand Down
28 changes: 14 additions & 14 deletions deltachat-rpc-client/src/deltachat_rpc_client/_utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import argparse
import asyncio
import re
import sys
from threading import Thread
from typing import TYPE_CHECKING, Callable, Iterable, Optional, Tuple, Type, Union

if TYPE_CHECKING:
Expand Down Expand Up @@ -43,7 +43,7 @@ def __setattr__(self, attr, val):
super().__setattr__(attr, val)


async def run_client_cli(
def run_client_cli(
hooks: Optional[Iterable[Tuple[Callable, Union[type, "EventFilter"]]]] = None,
argv: Optional[list] = None,
**kwargs,
Expand All @@ -54,10 +54,10 @@ async def run_client_cli(
"""
from .client import Client

await _run_cli(Client, hooks, argv, **kwargs)
_run_cli(Client, hooks, argv, **kwargs)


async def run_bot_cli(
def run_bot_cli(
hooks: Optional[Iterable[Tuple[Callable, Union[type, "EventFilter"]]]] = None,
argv: Optional[list] = None,
**kwargs,
Expand All @@ -68,10 +68,10 @@ async def run_bot_cli(
"""
from .client import Bot

await _run_cli(Bot, hooks, argv, **kwargs)
_run_cli(Bot, hooks, argv, **kwargs)


async def _run_cli(
def _run_cli(
client_type: Type["Client"],
hooks: Optional[Iterable[Tuple[Callable, Union[type, "EventFilter"]]]] = None,
argv: Optional[list] = None,
Expand All @@ -93,20 +93,20 @@ async def _run_cli(
parser.add_argument("--password", action="store", help="password")
args = parser.parse_args(argv[1:])

async with Rpc(accounts_dir=args.accounts_dir, **kwargs) as rpc:
with Rpc(accounts_dir=args.accounts_dir, **kwargs) as rpc:
deltachat = DeltaChat(rpc)
core_version = (await deltachat.get_system_info()).deltachat_core_version
accounts = await deltachat.get_all_accounts()
account = accounts[0] if accounts else await deltachat.add_account()
core_version = (deltachat.get_system_info()).deltachat_core_version
accounts = deltachat.get_all_accounts()
account = accounts[0] if accounts else deltachat.add_account()

client = client_type(account, hooks)
client.logger.debug("Running deltachat core %s", core_version)
if not await client.is_configured():
if not client.is_configured():
assert args.email, "Account is not configured and email must be provided"
assert args.password, "Account is not configured and password must be provided"
# Save a reference to avoid garbage collection of the task.
_configure_task = asyncio.create_task(client.configure(email=args.email, password=args.password))
await client.run_forever()
configure_thread = Thread(run=client.configure, kwargs={"email": args.email, "password": args.password})
configure_thread.start()
client.run_forever()


def extract_addr(text: str) -> str:
Expand Down
Loading

0 comments on commit 37383c1

Please sign in to comment.