python: avoid careless calls to unref functions

This commit is contained in:
adbenitez
2022-06-10 23:13:29 -04:00
parent e280ca9db8
commit f5ef650b4d
7 changed files with 36 additions and 20 deletions

View File

@@ -19,6 +19,7 @@ from .cutil import (
from_dc_charpointer,
from_optional_dc_charpointer,
iter_array,
safe_unref,
)
from .events import EventThread
from .message import Message
@@ -38,7 +39,7 @@ def get_core_info():
return get_dc_info_as_dict(
ffi.gc(
lib.dc_context_new(as_dc_charpointer(""), as_dc_charpointer(path.name), ffi.NULL),
lib.dc_context_unref,
safe_unref(lib.dc_context_unref),
)
)
@@ -84,7 +85,7 @@ class Account(object):
self._dc_context = ffi.gc(
lib.dc_context_new_closed(db_path) if closed else lib.dc_context_new(ffi.NULL, db_path, ffi.NULL),
lib.dc_context_unref,
safe_unref(lib.dc_context_unref),
)
if self._dc_context == ffi.NULL:
raise ValueError("Could not dc_context_new: {} {}".format(os_name, db_path))
@@ -342,7 +343,7 @@ class Account(object):
:returns: list of :class:`deltachat.contact.Contact` objects.
"""
dc_array = ffi.gc(lib.dc_get_blocked_contacts(self._dc_context), lib.dc_array_unref)
dc_array = ffi.gc(lib.dc_get_blocked_contacts(self._dc_context), safe_unref(lib.dc_array_unref))
return list(iter_array(dc_array, lambda x: Contact(self, x)))
def get_contacts(
@@ -365,12 +366,12 @@ class Account(object):
flags |= const.DC_GCL_VERIFIED_ONLY
if with_self:
flags |= const.DC_GCL_ADD_SELF
dc_array = ffi.gc(lib.dc_get_contacts(self._dc_context, flags, query), lib.dc_array_unref)
dc_array = ffi.gc(lib.dc_get_contacts(self._dc_context, flags, query), safe_unref(lib.dc_array_unref))
return list(iter_array(dc_array, lambda x: Contact(self, x)))
def get_fresh_messages(self) -> Generator[Message, None, None]:
"""yield all fresh messages from all chats."""
dc_array = ffi.gc(lib.dc_get_fresh_msgs(self._dc_context), lib.dc_array_unref)
dc_array = ffi.gc(lib.dc_get_fresh_msgs(self._dc_context), safe_unref(lib.dc_array_unref))
yield from iter_array(dc_array, lambda x: Message.from_db(self, x))
def create_chat(self, obj) -> Chat:
@@ -404,7 +405,7 @@ class Account(object):
:returns: a list of :class:`deltachat.chat.Chat` objects.
"""
dc_chatlist = ffi.gc(lib.dc_get_chatlist(self._dc_context, 0, ffi.NULL, 0), lib.dc_chatlist_unref)
dc_chatlist = ffi.gc(lib.dc_get_chatlist(self._dc_context, 0, ffi.NULL, 0), safe_unref(lib.dc_chatlist_unref))
assert dc_chatlist != ffi.NULL
chatlist = []
@@ -545,7 +546,7 @@ class Account(object):
def check_qr(self, qr):
"""check qr code and return :class:`ScannedQRCode` instance representing the result"""
res = ffi.gc(lib.dc_check_qr(self._dc_context, as_dc_charpointer(qr)), lib.dc_lot_unref)
res = ffi.gc(lib.dc_check_qr(self._dc_context, as_dc_charpointer(qr)), safe_unref(lib.dc_lot_unref))
lot = DCLot(res)
if lot.state() == const.DC_QR_ERROR:
raise ValueError("invalid or unknown QR code: {}".format(lot.text1()))

View File

@@ -14,6 +14,7 @@ from .cutil import (
from_dc_charpointer,
from_optional_dc_charpointer,
iter_array,
safe_unref,
)
from .message import Message
@@ -44,7 +45,7 @@ class Chat(object):
@property
def _dc_chat(self):
return ffi.gc(lib.dc_get_chat(self.account._dc_context, self.id), lib.dc_chat_unref)
return ffi.gc(lib.dc_get_chat(self.account._dc_context, self.id), safe_unref(lib.dc_chat_unref))
def delete(self) -> None:
"""Delete this chat and all its messages.
@@ -416,7 +417,7 @@ class Chat(object):
"""
dc_array = ffi.gc(
lib.dc_get_chat_msgs(self.account._dc_context, self.id, 0, 0),
lib.dc_array_unref,
safe_unref(lib.dc_array_unref),
)
return list(iter_array(dc_array, lambda x: Message.from_db(self.account, x)))
@@ -469,7 +470,7 @@ class Chat(object):
dc_array = ffi.gc(
lib.dc_get_chat_contacts(self.account._dc_context, self.id),
lib.dc_array_unref,
safe_unref(lib.dc_array_unref),
)
return list(iter_array(dc_array, lambda id: Contact(self.account, id)))
@@ -477,7 +478,7 @@ class Chat(object):
"""return number of contacts in this chat."""
dc_array = ffi.gc(
lib.dc_get_chat_contacts(self.account._dc_context, self.id),
lib.dc_array_unref,
safe_unref(lib.dc_array_unref),
)
return lib.dc_array_get_cnt(dc_array)

View File

@@ -6,6 +6,14 @@ from .capi import ffi, lib
T = TypeVar("T")
def safe_unref(unref: Callable) -> Callable:
def wrapper(obj) -> None:
if obj != ffi.NULL:
unref(obj)
return wrapper
def as_dc_charpointer(obj):
if obj == ffi.NULL or obj is None:
return ffi.NULL

View File

@@ -11,7 +11,7 @@ from queue import Empty, Queue
import deltachat
from .capi import ffi, lib
from .cutil import from_optional_dc_charpointer
from .cutil import from_optional_dc_charpointer, safe_unref
from .hookspec import account_hookimpl
from .message import map_system_message
@@ -229,7 +229,7 @@ class EventThread(threading.Thread):
def _inner_run(self):
event_emitter = ffi.gc(
lib.dc_get_event_emitter(self.account._dc_context),
lib.dc_event_emitter_unref,
safe_unref(lib.dc_event_emitter_unref),
)
while not self._marked_for_shutdown:
event = lib.dc_get_next_event(event_emitter)

View File

@@ -8,7 +8,12 @@ from typing import Optional, Union
from . import const, props
from .capi import ffi, lib
from .cutil import as_dc_charpointer, from_dc_charpointer, from_optional_dc_charpointer
from .cutil import (
as_dc_charpointer,
from_dc_charpointer,
from_optional_dc_charpointer,
safe_unref,
)
class Message(object):
@@ -49,7 +54,7 @@ class Message(object):
@classmethod
def from_db(cls, account, id):
assert id > 0
return cls(account, ffi.gc(lib.dc_get_msg(account._dc_context, id), lib.dc_msg_unref))
return cls(account, ffi.gc(lib.dc_get_msg(account._dc_context, id), safe_unref(lib.dc_msg_unref)))
@classmethod
def new_empty(cls, account, view_type):
@@ -64,7 +69,7 @@ class Message(object):
view_type_code = get_viewtype_code_from_name(view_type)
return Message(
account,
ffi.gc(lib.dc_msg_new(account._dc_context, view_type_code), lib.dc_msg_unref),
ffi.gc(lib.dc_msg_new(account._dc_context, view_type_code), safe_unref(lib.dc_msg_unref)),
)
def create_chat(self):
@@ -278,7 +283,7 @@ class Message(object):
mime_headers = lib.dc_get_mime_headers(self.account._dc_context, self.id)
if mime_headers:
s = ffi.string(ffi.gc(mime_headers, lib.dc_str_unref))
s = ffi.string(ffi.gc(mime_headers, safe_unref(lib.dc_str_unref)))
if isinstance(s, bytes):
return email.message_from_bytes(s)
return email.message_from_string(s)
@@ -337,7 +342,7 @@ class Message(object):
dc_msg = self._dc_msg
else:
# load message from db to get a fresh/current state
dc_msg = ffi.gc(lib.dc_get_msg(self.account._dc_context, self.id), lib.dc_msg_unref)
dc_msg = ffi.gc(lib.dc_get_msg(self.account._dc_context, self.id), safe_unref(lib.dc_msg_unref))
return lib.dc_msg_get_state(dc_msg)
def is_in_fresh(self):

View File

@@ -1,7 +1,7 @@
"""Provider info class."""
from .capi import ffi, lib
from .cutil import as_dc_charpointer, from_dc_charpointer
from .cutil import as_dc_charpointer, from_dc_charpointer, safe_unref
class ProviderNotFoundError(Exception):
@@ -17,7 +17,7 @@ class Provider(object):
def __init__(self, account, addr) -> None:
provider = ffi.gc(
lib.dc_provider_new_from_email(account._dc_context, as_dc_charpointer(addr)),
lib.dc_provider_unref,
safe_unref(lib.dc_provider_unref),
)
if provider == ffi.NULL:
raise ProviderNotFoundError("Provider not found")