diff --git a/doc/_ext/docstring.py b/doc/_ext/docstring.py
index d1034ffc..cf172120 100644
--- a/doc/_ext/docstring.py
+++ b/doc/_ext/docstring.py
@@ -4,16 +4,13 @@
def process_docstring(app, what, name, obj, options, lines):
- lines[:] = [
- l.replace("@param", ":param").replace("@raise", ":raises")
- for l in lines
- ]
+ lines[:] = [l.replace("@param", ":param").replace("@raise", ":raises") for l in lines]
def setup(app):
app.connect("autodoc-process-docstring", process_docstring)
return {
- 'version': '0.1',
- 'parallel_read_safe': True,
- 'parallel_write_safe': True,
+ "version": "0.1",
+ "parallel_read_safe": True,
+ "parallel_write_safe": True,
}
diff --git a/doc/conf.py b/doc/conf.py
index f3dfd071..831488d4 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -1,4 +1,3 @@
-
#
# Configuration file for the Sphinx documentation builder.
#
@@ -24,9 +23,9 @@ sys.path.insert(0, os.path.abspath("./_ext"))
# -- Project information -----------------------------------------------------
-project = 'Libervia Backend'
-copyright = '2019-2023 Libervia'
-author = 'Libervia team'
+project = "Libervia Backend"
+copyright = "2019-2023 Libervia"
+author = "Libervia team"
version = __version__
@@ -60,22 +59,19 @@ rst_prolog = """
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
-extensions = [
- "sphinx.ext.autodoc",
- "docstring"
-]
+extensions = ["sphinx.ext.autodoc", "docstring"]
# Add any paths that contain templates here, relative to this directory.
-templates_path = ['.templates']
+templates_path = [".templates"]
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
-source_suffix = '.rst'
+source_suffix = ".rst"
# The master toctree document.
-master_doc = 'index'
+master_doc = "index"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -87,7 +83,7 @@ language = "en"
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
-exclude_patterns = [u'.build', 'Thumbs.db', '.DS_Store']
+exclude_patterns = [".build", "Thumbs.db", ".DS_Store"]
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = None
@@ -98,7 +94,7 @@ pygments_style = None
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
-html_theme = 'alabaster'
+html_theme = "alabaster"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
@@ -109,7 +105,7 @@ html_theme = 'alabaster'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['.static']
+html_static_path = [".static"]
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
@@ -125,7 +121,7 @@ html_static_path = ['.static']
# -- Options for HTMLHelp output ---------------------------------------------
# Output file base name for HTML help builder.
-htmlhelp_basename = 'SalutToidoc'
+htmlhelp_basename = "SalutToidoc"
# -- Options for LaTeX output ------------------------------------------------
@@ -134,15 +130,12 @@ latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
-
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
-
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
-
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
@@ -152,8 +145,7 @@ latex_elements = {
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
- (master_doc, 'SalutToi.tex', u'Libervia Documentation',
- u'Libervia team', 'manual'),
+ (master_doc, "SalutToi.tex", "Libervia Documentation", "Libervia team", "manual"),
]
@@ -161,10 +153,7 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
-man_pages = [
- (master_doc, 'saluttoi', u'Libervia Documentation',
- [author], 1)
-]
+man_pages = [(master_doc, "saluttoi", "Libervia Documentation", [author], 1)]
# -- Options for Texinfo output ----------------------------------------------
@@ -173,9 +162,15 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
- (master_doc, 'SalutToi', u'Libervia Documentation',
- author, 'SalutToi', 'One line description of project.',
- 'Miscellaneous'),
+ (
+ master_doc,
+ "SalutToi",
+ "Libervia Documentation",
+ author,
+ "SalutToi",
+ "One line description of project.",
+ "Miscellaneous",
+ ),
]
@@ -194,7 +189,7 @@ epub_title = project
# epub_uid = ''
# A list of files that should not be packed into the epub file.
-epub_exclude_files = ['search.html']
+epub_exclude_files = ["search.html"]
# -- Extension configuration -------------------------------------------------
diff --git a/libervia/backend/__init__.py b/libervia/backend/__init__.py
index 9aaa7566..ed145ad4 100644
--- a/libervia/backend/__init__.py
+++ b/libervia/backend/__init__.py
@@ -47,4 +47,5 @@ class Global:
def storage(self) -> "Storage":
return self.host.memory.storage
+
G = Global()
diff --git a/libervia/backend/core/core_types.py b/libervia/backend/core/core_types.py
index 8baaa2b8..a2cd660e 100644
--- a/libervia/backend/core/core_types.py
+++ b/libervia/backend/core/core_types.py
@@ -46,7 +46,9 @@ class EncryptionSession(TypedDict):
# Incomplete types built through observation rather than code inspection.
MessageDataExtra = TypedDict(
- "MessageDataExtra", {"encrypted": bool, "origin_id": str, "headers": dict[str, Any]}, total=False
+ "MessageDataExtra",
+ {"encrypted": bool, "origin_id": str, "headers": dict[str, Any]},
+ total=False,
)
@@ -135,7 +137,7 @@ class SatXMPPEntity(ABC):
def generate_message_xml(
self,
data: MessageData,
- post_xml_treatments: defer.Deferred|None = None,
+ post_xml_treatments: defer.Deferred | None = None,
) -> MessageData:
"""Generate stanza from message data
@@ -177,7 +179,7 @@ class SatXMPPEntity(ABC):
def send(self, obj: domish.Element) -> None:
# We need to call super() due to mulitple inheritance: Wokkel XMPPClient or
# Component's `send` needs to be called.
- super().send(obj) # type: ignore
+ super().send(obj) # type: ignore
@abstractmethod
async def send_message_data(self, mess_data: MessageData) -> MessageData:
diff --git a/libervia/backend/core/xmpp.py b/libervia/backend/core/xmpp.py
index 736d2d31..89d3e480 100644
--- a/libervia/backend/core/xmpp.py
+++ b/libervia/backend/core/xmpp.py
@@ -515,7 +515,7 @@ class SatXMPPEntity(core_types.SatXMPPEntity):
xs.add_hook(C.STREAM_HOOK_SEND, hook)
super(SatXMPPEntity, self)._connected(xs)
- def disconnect_profile(self, reason: failure.Failure|None) -> None:
+ def disconnect_profile(self, reason: failure.Failure | None) -> None:
if self._connected_d is not None:
self.host_app.bridge.disconnected(
self.profile
@@ -616,11 +616,11 @@ class SatXMPPEntity(core_types.SatXMPPEntity):
return iq_elt
def sendError(
- self,
- iq_elt: domish.Element,
- condition: str,
- text: str|None = None,
- appCondition: str|None = None
+ self,
+ iq_elt: domish.Element,
+ condition: str,
+ text: str | None = None,
+ appCondition: str | None = None,
) -> None:
"""Send error stanza build from iq_elt
@@ -1355,17 +1355,19 @@ class SatMessageProtocol(xmppim.MessageProtocol):
message = {}
subject = {}
extra = {}
- data = MessageData({
- "from": from_jid,
- "to": jid.JID(message_elt["to"]),
- "uid": message_elt.getAttribute(
- "uid", str(uuid.uuid4())
- ), # XXX: uid is not a standard attribute but may be added by plugins
- "message": message,
- "subject": subject,
- "type": message_elt.getAttribute("type", "normal"),
- "extra": extra,
- })
+ data = MessageData(
+ {
+ "from": from_jid,
+ "to": jid.JID(message_elt["to"]),
+ "uid": message_elt.getAttribute(
+ "uid", str(uuid.uuid4())
+ ), # XXX: uid is not a standard attribute but may be added by plugins
+ "message": message,
+ "subject": subject,
+ "type": message_elt.getAttribute("type", "normal"),
+ "extra": extra,
+ }
+ )
try:
message_id = extra["message_id"] = message_elt["id"]
diff --git a/libervia/backend/memory/disco.py b/libervia/backend/memory/disco.py
index ef1d3775..bbc1e5f1 100755
--- a/libervia/backend/memory/disco.py
+++ b/libervia/backend/memory/disco.py
@@ -207,9 +207,9 @@ class Discovery(object):
def get_infos(
self,
client: SatXMPPEntity,
- jid_: jid.JID|None=None,
- node: str="",
- use_cache: bool=True
+ jid_: jid.JID | None = None,
+ node: str = "",
+ use_cache: bool = True,
) -> defer.Deferred[disco.DiscoInfo]:
"""get disco infos from jid_, filling capability hash if needed
diff --git a/libervia/backend/memory/encryption.py b/libervia/backend/memory/encryption.py
index 1a14fef7..37bb15f4 100644
--- a/libervia/backend/memory/encryption.py
+++ b/libervia/backend/memory/encryption.py
@@ -82,8 +82,8 @@ class EncryptionHandler:
plg_instance,
name: str,
namespace: str,
- priority: int=0,
- directed: bool=False
+ priority: int = 0,
+ directed: bool = False,
) -> None:
"""Register a plugin handling an encryption algorithm
diff --git a/libervia/backend/memory/memory.py b/libervia/backend/memory/memory.py
index d9c50372..2666922b 100644
--- a/libervia/backend/memory/memory.py
+++ b/libervia/backend/memory/memory.py
@@ -1672,7 +1672,7 @@ class Memory:
access: dict | None = None,
extra: dict | None = None,
peer_jid: Any | None = None,
- perms_to_check: tuple[str]|None = (C.ACCESS_PERM_WRITE,),
+ perms_to_check: tuple[str] | None = (C.ACCESS_PERM_WRITE,),
) -> None:
"""Set a file metadata.
diff --git a/libervia/backend/memory/migration/versions/29f85e56b6d4_use_json_type_in_history_and_for_.py b/libervia/backend/memory/migration/versions/29f85e56b6d4_use_json_type_in_history_and_for_.py
index e347b926..adcfcba1 100644
--- a/libervia/backend/memory/migration/versions/29f85e56b6d4_use_json_type_in_history_and_for_.py
+++ b/libervia/backend/memory/migration/versions/29f85e56b6d4_use_json_type_in_history_and_for_.py
@@ -5,52 +5,47 @@ Revises: fe3a02cb4bec
Create Date: 2025-05-02 11:20:11.555189
"""
+
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
-revision = '29f85e56b6d4'
-down_revision = 'fe3a02cb4bec'
+revision = "29f85e56b6d4"
+down_revision = "fe3a02cb4bec"
branch_labels = None
depends_on = None
def upgrade():
- with op.batch_alter_table('history', schema=None) as batch_op:
- batch_op.alter_column('extra',
- existing_type=sa.TEXT(),
- type_=sa.JSON(),
- existing_nullable=True)
+ with op.batch_alter_table("history", schema=None) as batch_op:
+ batch_op.alter_column(
+ "extra", existing_type=sa.TEXT(), type_=sa.JSON(), existing_nullable=True
+ )
- with op.batch_alter_table('private_gen_bin', schema=None) as batch_op:
- batch_op.alter_column('value',
- existing_type=sa.TEXT(),
- type_=sa.JSON(),
- existing_nullable=True)
+ with op.batch_alter_table("private_gen_bin", schema=None) as batch_op:
+ batch_op.alter_column(
+ "value", existing_type=sa.TEXT(), type_=sa.JSON(), existing_nullable=True
+ )
- with op.batch_alter_table('private_ind_bin', schema=None) as batch_op:
- batch_op.alter_column('value',
- existing_type=sa.TEXT(),
- type_=sa.JSON(),
- existing_nullable=True)
+ with op.batch_alter_table("private_ind_bin", schema=None) as batch_op:
+ batch_op.alter_column(
+ "value", existing_type=sa.TEXT(), type_=sa.JSON(), existing_nullable=True
+ )
def downgrade():
- with op.batch_alter_table('private_ind_bin', schema=None) as batch_op:
- batch_op.alter_column('value',
- existing_type=sa.JSON(),
- type_=sa.TEXT(),
- existing_nullable=True)
+ with op.batch_alter_table("private_ind_bin", schema=None) as batch_op:
+ batch_op.alter_column(
+ "value", existing_type=sa.JSON(), type_=sa.TEXT(), existing_nullable=True
+ )
- with op.batch_alter_table('private_gen_bin', schema=None) as batch_op:
- batch_op.alter_column('value',
- existing_type=sa.JSON(),
- type_=sa.TEXT(),
- existing_nullable=True)
+ with op.batch_alter_table("private_gen_bin", schema=None) as batch_op:
+ batch_op.alter_column(
+ "value", existing_type=sa.JSON(), type_=sa.TEXT(), existing_nullable=True
+ )
- with op.batch_alter_table('history', schema=None) as batch_op:
- batch_op.alter_column('extra',
- existing_type=sa.JSON(),
- type_=sa.TEXT(),
- existing_nullable=True)
+ with op.batch_alter_table("history", schema=None) as batch_op:
+ batch_op.alter_column(
+ "extra", existing_type=sa.JSON(), type_=sa.TEXT(), existing_nullable=True
+ )
diff --git a/libervia/backend/memory/migration/versions/6af2d8f6be76_add_is_retroactive_to_thread_and_fix_.py b/libervia/backend/memory/migration/versions/6af2d8f6be76_add_is_retroactive_to_thread_and_fix_.py
index 0ecc4df0..dc3c938f 100644
--- a/libervia/backend/memory/migration/versions/6af2d8f6be76_add_is_retroactive_to_thread_and_fix_.py
+++ b/libervia/backend/memory/migration/versions/6af2d8f6be76_add_is_retroactive_to_thread_and_fix_.py
@@ -5,29 +5,34 @@ Revises: 29f85e56b6d4
Create Date: 2025-05-02 11:21:54.023587
"""
+
from alembic import op
import sqlalchemy as sa
from sqlalchemy.sql import false
# revision identifiers, used by Alembic.
-revision = '6af2d8f6be76'
-down_revision = '29f85e56b6d4'
+revision = "6af2d8f6be76"
+down_revision = "29f85e56b6d4"
branch_labels = None
depends_on = None
def upgrade():
- with op.batch_alter_table('thread', schema=None) as batch_op:
- batch_op.add_column(sa.Column('is_retroactive', sa.Boolean(), server_default=false(), nullable=False, comment="Indicates if thread ID was added after the original message was sent (e.g. to link a parent message which didn't have a thread ID to a thread)."))
- batch_op.alter_column('thread_id',
- existing_type=sa.TEXT(),
- nullable=False)
+ with op.batch_alter_table("thread", schema=None) as batch_op:
+ batch_op.add_column(
+ sa.Column(
+ "is_retroactive",
+ sa.Boolean(),
+ server_default=false(),
+ nullable=False,
+ comment="Indicates if thread ID was added after the original message was sent (e.g. to link a parent message which didn't have a thread ID to a thread).",
+ )
+ )
+ batch_op.alter_column("thread_id", existing_type=sa.TEXT(), nullable=False)
def downgrade():
- with op.batch_alter_table('thread', schema=None) as batch_op:
- batch_op.alter_column('thread_id',
- existing_type=sa.TEXT(),
- nullable=True)
- batch_op.drop_column('is_retroactive')
+ with op.batch_alter_table("thread", schema=None) as batch_op:
+ batch_op.alter_column("thread_id", existing_type=sa.TEXT(), nullable=True)
+ batch_op.drop_column("is_retroactive")
diff --git a/libervia/backend/memory/migration/versions/8db042adb973_add_affiliations_access_model_and_.py b/libervia/backend/memory/migration/versions/8db042adb973_add_affiliations_access_model_and_.py
index 80d6edde..f2b61072 100644
--- a/libervia/backend/memory/migration/versions/8db042adb973_add_affiliations_access_model_and_.py
+++ b/libervia/backend/memory/migration/versions/8db042adb973_add_affiliations_access_model_and_.py
@@ -5,36 +5,74 @@ Revises: 6af2d8f6be76
Create Date: 2025-08-02 12:03:19.726497
"""
+
from alembic import op
import sqlalchemy as sa
from libervia.backend.memory.sqla_mapping import JID
# revision identifiers, used by Alembic.
-revision = '8db042adb973'
-down_revision = '6af2d8f6be76'
+revision = "8db042adb973"
+down_revision = "6af2d8f6be76"
branch_labels = None
depends_on = None
def upgrade():
- op.create_table('pubsub_affiliations',
- sa.Column('id', sa.Integer(), nullable=False),
- sa.Column('node_id', sa.Integer(), nullable=False),
- sa.Column('entity', JID(), nullable=False),
- sa.Column('affiliation', sa.Enum('outcast', 'member', 'publisher', 'owner', name='affiliation', create_constraint=True), nullable=False),
- sa.ForeignKeyConstraint(['node_id'], ['pubsub_nodes.id'], name=op.f('fk_pubsub_affiliations_node_id_pubsub_nodes'), ondelete='CASCADE'),
- sa.PrimaryKeyConstraint('id', name=op.f('pk_pubsub_affiliations')),
- sa.UniqueConstraint('node_id', 'entity', name=op.f('uq_pubsub_affiliations_node_id'))
+ op.create_table(
+ "pubsub_affiliations",
+ sa.Column("id", sa.Integer(), nullable=False),
+ sa.Column("node_id", sa.Integer(), nullable=False),
+ sa.Column("entity", JID(), nullable=False),
+ sa.Column(
+ "affiliation",
+ sa.Enum(
+ "outcast",
+ "member",
+ "publisher",
+ "owner",
+ name="affiliation",
+ create_constraint=True,
+ ),
+ nullable=False,
+ ),
+ sa.ForeignKeyConstraint(
+ ["node_id"],
+ ["pubsub_nodes.id"],
+ name=op.f("fk_pubsub_affiliations_node_id_pubsub_nodes"),
+ ondelete="CASCADE",
+ ),
+ sa.PrimaryKeyConstraint("id", name=op.f("pk_pubsub_affiliations")),
+ sa.UniqueConstraint(
+ "node_id", "entity", name=op.f("uq_pubsub_affiliations_node_id")
+ ),
)
- with op.batch_alter_table('pubsub_nodes', schema=None) as batch_op:
- batch_op.add_column(sa.Column('access_model', sa.Enum('open', 'whitelist', name='accessmodel', create_constraint=True), nullable=True))
- batch_op.add_column(sa.Column('publish_model', sa.Enum('publishers', 'subscribers', 'open', name='publishmodel', create_constraint=True), nullable=True))
+ with op.batch_alter_table("pubsub_nodes", schema=None) as batch_op:
+ batch_op.add_column(
+ sa.Column(
+ "access_model",
+ sa.Enum("open", "whitelist", name="accessmodel", create_constraint=True),
+ nullable=True,
+ )
+ )
+ batch_op.add_column(
+ sa.Column(
+ "publish_model",
+ sa.Enum(
+ "publishers",
+ "subscribers",
+ "open",
+ name="publishmodel",
+ create_constraint=True,
+ ),
+ nullable=True,
+ )
+ )
def downgrade():
- with op.batch_alter_table('pubsub_nodes', schema=None) as batch_op:
- batch_op.drop_column('publish_model')
- batch_op.drop_column('access_model')
+ with op.batch_alter_table("pubsub_nodes", schema=None) as batch_op:
+ batch_op.drop_column("publish_model")
+ batch_op.drop_column("access_model")
- op.drop_table('pubsub_affiliations')
+ op.drop_table("pubsub_affiliations")
diff --git a/libervia/backend/memory/migration/versions/ece2a6d7e4bb_add_parent_node_id_and_linked_mode_id_.py b/libervia/backend/memory/migration/versions/ece2a6d7e4bb_add_parent_node_id_and_linked_mode_id_.py
index 93ca30bf..f6dfca64 100644
--- a/libervia/backend/memory/migration/versions/ece2a6d7e4bb_add_parent_node_id_and_linked_mode_id_.py
+++ b/libervia/backend/memory/migration/versions/ece2a6d7e4bb_add_parent_node_id_and_linked_mode_id_.py
@@ -5,28 +5,45 @@ Revises: 8db042adb973
Create Date: 2025-08-16 16:47:48.242973
"""
+
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
-revision = 'ece2a6d7e4bb'
-down_revision = '8db042adb973'
+revision = "ece2a6d7e4bb"
+down_revision = "8db042adb973"
branch_labels = None
depends_on = None
def upgrade():
- with op.batch_alter_table('pubsub_nodes', schema=None) as batch_op:
- batch_op.add_column(sa.Column('linked_node_id', sa.Integer(), nullable=True))
- batch_op.add_column(sa.Column('parent_node_id', sa.Integer(), nullable=True))
- batch_op.create_foreign_key(batch_op.f('fk_pubsub_nodes_parent_node_id_pubsub_nodes'), 'pubsub_nodes', ['parent_node_id'], ['id'], ondelete='CASCADE')
- batch_op.create_foreign_key(batch_op.f('fk_pubsub_nodes_linked_node_id_pubsub_nodes'), 'pubsub_nodes', ['linked_node_id'], ['id'], ondelete='CASCADE')
+ with op.batch_alter_table("pubsub_nodes", schema=None) as batch_op:
+ batch_op.add_column(sa.Column("linked_node_id", sa.Integer(), nullable=True))
+ batch_op.add_column(sa.Column("parent_node_id", sa.Integer(), nullable=True))
+ batch_op.create_foreign_key(
+ batch_op.f("fk_pubsub_nodes_parent_node_id_pubsub_nodes"),
+ "pubsub_nodes",
+ ["parent_node_id"],
+ ["id"],
+ ondelete="CASCADE",
+ )
+ batch_op.create_foreign_key(
+ batch_op.f("fk_pubsub_nodes_linked_node_id_pubsub_nodes"),
+ "pubsub_nodes",
+ ["linked_node_id"],
+ ["id"],
+ ondelete="CASCADE",
+ )
def downgrade():
- with op.batch_alter_table('pubsub_nodes', schema=None) as batch_op:
- batch_op.drop_constraint(batch_op.f('fk_pubsub_nodes_linked_node_id_pubsub_nodes'), type_='foreignkey')
- batch_op.drop_constraint(batch_op.f('fk_pubsub_nodes_parent_node_id_pubsub_nodes'), type_='foreignkey')
- batch_op.drop_column('parent_node_id')
- batch_op.drop_column('linked_node_id')
+ with op.batch_alter_table("pubsub_nodes", schema=None) as batch_op:
+ batch_op.drop_constraint(
+ batch_op.f("fk_pubsub_nodes_linked_node_id_pubsub_nodes"), type_="foreignkey"
+ )
+ batch_op.drop_constraint(
+ batch_op.f("fk_pubsub_nodes_parent_node_id_pubsub_nodes"), type_="foreignkey"
+ )
+ batch_op.drop_column("parent_node_id")
+ batch_op.drop_column("linked_node_id")
diff --git a/libervia/backend/memory/sqla.py b/libervia/backend/memory/sqla.py
index 989ceeb3..ba609f5a 100644
--- a/libervia/backend/memory/sqla.py
+++ b/libervia/backend/memory/sqla.py
@@ -500,7 +500,7 @@ class Storage:
@aio
async def get_history_from_xmpp_id(
- self, client: SatXMPPEntity, message_id: str, message_type: str|None
+ self, client: SatXMPPEntity, message_id: str, message_type: str | None
) -> History | None:
"""Retrieves history row that match a specific message ID.
@@ -520,12 +520,11 @@ class Storage:
)
else:
query = select(History).where(
- History.profile_id == profile_id, History.origin_id == message_id
+ History.profile_id == profile_id, History.origin_id == message_id
)
query = (
- query
- .outerjoin(History.messages)
+ query.outerjoin(History.messages)
.outerjoin(History.subjects)
.outerjoin(History.thread)
.options(
@@ -540,7 +539,6 @@ class Storage:
return history
-
@aio
async def history_get(
self,
@@ -676,9 +674,7 @@ class Storage:
# FIXME: "json_each" works with SQLite, but when PostGreSQL support will
# be added, "json_array_elements" may have to be used with it.
subquery = func.json_each(History.extra["keywords"]).table_valued("value")
- stmt = stmt.where(
- exists().where(subquery.c.value == keyword)
- )
+ stmt = stmt.where(exists().where(subquery.c.value == keyword))
if "origin" in filters:
stmt = stmt.where(
History.extra["origin"].as_string() == filters["origin"]
@@ -752,7 +748,7 @@ class Storage:
self,
message_uid: str,
thread_id: str,
- parent_id: str|None,
+ parent_id: str | None,
is_retroactive: bool,
) -> None:
"""Add a thread to a message.
@@ -1180,8 +1176,8 @@ class Storage:
with_subscriptions: bool = False,
with_affiliations: bool = False,
create: bool = False,
- create_kwargs: dict|None = None,
- ) -> PubsubNode|None:
+ create_kwargs: dict | None = None,
+ ) -> PubsubNode | None:
"""Retrieve a PubsubNode from DB
@param service: service hosting the node
@@ -1238,9 +1234,9 @@ class Storage:
@aio
async def get_pubsub_nodes(
self,
- client: SatXMPPEntity|None,
- service: jid.JID|None,
- node_name: str|None = None,
+ client: SatXMPPEntity | None,
+ service: jid.JID | None,
+ node_name: str | None = None,
linked_node: bool = False,
depth: int = 0,
with_items: bool = False,
@@ -1279,7 +1275,7 @@ class Storage:
if depth > 0:
options = [
selectinload(PubsubNode.child_nodes),
- joinedload(PubsubNode.parent_node)
+ joinedload(PubsubNode.parent_node),
]
else:
options = []
@@ -1323,24 +1319,21 @@ class Storage:
base_node_ids = [node.id for node in base_nodes]
# Create recursive CTE to find child base nodes.
- hierarchy = select(
- PubsubNode.id,
- literal(0).label('depth')
- ).filter(
- PubsubNode.id.in_(base_node_ids),
- PubsubNode.linked_node_id.is_(None)
- ).cte(name="hierarchy", recursive=True)
+ hierarchy = (
+ select(PubsubNode.id, literal(0).label("depth"))
+ .filter(
+ PubsubNode.id.in_(base_node_ids),
+ PubsubNode.linked_node_id.is_(None),
+ )
+ .cte(name="hierarchy", recursive=True)
+ )
# Recursive part: get direct children that are also base nodes.
children = (
- select(
- PubsubNode.id,
- hierarchy.c.depth + 1
- )
+ select(PubsubNode.id, hierarchy.c.depth + 1)
.join(hierarchy, PubsubNode.parent_node_id == hierarchy.c.id)
.filter(
- hierarchy.c.depth < depth,
- PubsubNode.linked_node_id.is_(None)
+ hierarchy.c.depth < depth, PubsubNode.linked_node_id.is_(None)
)
)
@@ -1348,11 +1341,8 @@ class Storage:
full_hierarchy = hierarchy.union_all(children)
# Final query for all base nodes in the hierarchy.
- hierarchy_query = (
- select(PubsubNode)
- .filter(PubsubNode.id.in_(
- select(full_hierarchy.c.id)
- ))
+ hierarchy_query = select(PubsubNode).filter(
+ PubsubNode.id.in_(select(full_hierarchy.c.id))
)
# Apply the same eager loading options.
@@ -1377,18 +1367,18 @@ class Storage:
client: SatXMPPEntity,
service: jid.JID,
name: str,
- access_model: AccessModel|None = None,
- publish_model: PublishModel|None = None,
+ access_model: AccessModel | None = None,
+ publish_model: PublishModel | None = None,
analyser: Optional[str] = None,
type_: Optional[str] = None,
subtype: Optional[str] = None,
subscribed: bool = False,
- extra: dict|None = None,
- items: list[PubsubItem]|None = None,
- affiliations: list[PubsubAffiliation]|None = None,
- subscriptions: list[PubsubSub]|None = None,
- parent_node: PubsubNode|None = None,
- linked_node: PubsubNode|None = None
+ extra: dict | None = None,
+ items: list[PubsubItem] | None = None,
+ affiliations: list[PubsubAffiliation] | None = None,
+ subscriptions: list[PubsubSub] | None = None,
+ parent_node: PubsubNode | None = None,
+ linked_node: PubsubNode | None = None,
) -> PubsubNode:
node = PubsubNode(
profile_id=self.profiles[client.profile],
@@ -1400,12 +1390,12 @@ class Storage:
analyser=analyser,
type_=type_,
subtype=subtype,
- extra = extra,
- items = items or [],
- affiliations = affiliations or [],
- subscriptions = subscriptions or [],
- parent_node = parent_node,
- linked_node = linked_node
+ extra=extra,
+ items=items or [],
+ affiliations=affiliations or [],
+ subscriptions=subscriptions or [],
+ parent_node=parent_node,
+ linked_node=linked_node,
)
async with self.session() as session:
async with session.begin():
diff --git a/libervia/backend/memory/sqla_mapping.py b/libervia/backend/memory/sqla_mapping.py
index 4eeb078f..e8dd682f 100644
--- a/libervia/backend/memory/sqla_mapping.py
+++ b/libervia/backend/memory/sqla_mapping.py
@@ -462,7 +462,7 @@ class Thread(Base):
comment=(
"Indicates if thread ID was added after the original message was sent (e.g. "
"to link a parent message which didn't have a thread ID to a thread)."
- )
+ ),
)
history = relationship("History", uselist=False, back_populates="thread")
@@ -653,18 +653,24 @@ class PubsubNode(Base):
subtype = Column(Text, nullable=True)
extra = Column(JSON)
- linked_node_id = Column(Integer, ForeignKey("pubsub_nodes.id", ondelete="CASCADE"), nullable=True)
- parent_node_id = Column(Integer, ForeignKey("pubsub_nodes.id", ondelete="CASCADE"), nullable=True)
+ linked_node_id = Column(
+ Integer, ForeignKey("pubsub_nodes.id", ondelete="CASCADE"), nullable=True
+ )
+ parent_node_id = Column(
+ Integer, ForeignKey("pubsub_nodes.id", ondelete="CASCADE"), nullable=True
+ )
items = relationship("PubsubItem", back_populates="node", passive_deletes=True)
- affiliations = relationship("PubsubAffiliation", back_populates="node", passive_deletes=True)
+ affiliations = relationship(
+ "PubsubAffiliation", back_populates="node", passive_deletes=True
+ )
subscriptions = relationship("PubsubSub", back_populates="node", passive_deletes=True)
linked_node = relationship(
"PubsubNode",
remote_side=[id],
foreign_keys=[linked_node_id],
- back_populates="linking_nodes"
+ back_populates="linking_nodes",
)
linking_nodes = relationship(
"PubsubNode",
@@ -676,7 +682,7 @@ class PubsubNode(Base):
"PubsubNode",
remote_side=[id],
foreign_keys=[parent_node_id],
- back_populates="child_nodes"
+ back_populates="child_nodes",
)
child_nodes = relationship(
"PubsubNode",
@@ -693,10 +699,10 @@ class PubsubAffiliation(Base):
User by components managing a pubsub service.
"""
+
__tablename__ = "pubsub_affiliations"
__table_args__ = (UniqueConstraint("node_id", "entity"),)
-
id = Column(Integer, primary_key=True)
node_id = Column(ForeignKey("pubsub_nodes.id", ondelete="CASCADE"), nullable=False)
entity = Column(JID, nullable=False)
diff --git a/libervia/backend/plugins/plugin_comp_ap_gateway/pubsub_service.py b/libervia/backend/plugins/plugin_comp_ap_gateway/pubsub_service.py
index 30adaadf..d2357d03 100644
--- a/libervia/backend/plugins/plugin_comp_ap_gateway/pubsub_service.py
+++ b/libervia/backend/plugins/plugin_comp_ap_gateway/pubsub_service.py
@@ -286,9 +286,7 @@ class APPubsubService(rsm.PubSubService):
client, requestor_actor_id, ap_account
)
if "base64" not in avatar_data:
- await threads.deferToThread(
- self._blocking_b64encode_avatar, avatar_data
- )
+ await threads.deferToThread(self._blocking_b64encode_avatar, avatar_data)
else:
if len(itemIdentifiers) > 1:
# only a single item ID is supported
diff --git a/libervia/backend/plugins/plugin_comp_email_gateway/__init__.py b/libervia/backend/plugins/plugin_comp_email_gateway/__init__.py
index 85c1f75e..77ab4d63 100644
--- a/libervia/backend/plugins/plugin_comp_email_gateway/__init__.py
+++ b/libervia/backend/plugins/plugin_comp_email_gateway/__init__.py
@@ -52,7 +52,13 @@ from libervia.backend.core.i18n import D_, _
from libervia.backend.core.log import getLogger
from libervia.backend.memory.persistent import LazyPersistentBinaryDict
from libervia.backend.memory.sqla import select
-from libervia.backend.memory.sqla_mapping import AccessModel, Affiliation, PrivateIndBin, PublishModel, PubsubAffiliation
+from libervia.backend.memory.sqla_mapping import (
+ AccessModel,
+ Affiliation,
+ PrivateIndBin,
+ PublishModel,
+ PubsubAffiliation,
+)
from libervia.backend.models.core import MessageData
from libervia.backend.plugins.plugin_comp_email_gateway.pubsub_service import (
EmailGWPubsubService,
@@ -96,8 +102,17 @@ PLUGIN_INFO = {
C.PI_TYPE: C.PLUG_TYPE_ENTRY_POINT,
C.PI_PROTOCOLS: [],
C.PI_DEPENDENCIES: [
- "XEP-0033", "XEP-0077", "XEP-0106", "XEP-0277", "XEP-0498", "XEP-0499", "GRE", "GRE-MIME",
- "GRE-OpenPGP", "PUBSUB_CACHE", "TEXT_SYNTAXES"
+ "XEP-0033",
+ "XEP-0077",
+ "XEP-0106",
+ "XEP-0277",
+ "XEP-0498",
+ "XEP-0499",
+ "GRE",
+ "GRE-MIME",
+ "GRE-OpenPGP",
+ "PUBSUB_CACHE",
+ "TEXT_SYNTAXES",
],
C.PI_RECOMMENDATIONS: [],
C.PI_MAIN: "EmailGatewayComponent",
@@ -276,26 +291,30 @@ class EmailGatewayComponent(GetDataHandler):
assert to_email is not None
subject = "This is an encrypted message."
- outer = MIMEMultipart('encrypted', protocol="application/pgp-encrypted")
+ outer = MIMEMultipart("encrypted", protocol="application/pgp-encrypted")
outer["Subject"] = subject
# FIXME: use credentials here.
outer["From"] = from_jid.userhost()
outer["To"] = to_email
- outer["Content-Type"] = "multipart/encrypted; protocol=\"application/pgp-encrypted\""
+ outer["Content-Type"] = (
+ 'multipart/encrypted; protocol="application/pgp-encrypted"'
+ )
version = MIMEApplication(
"Version: 1\n",
- _subtype='pgp-encrypted',
- _encoder=encoders.encode_7or8bit
+ _subtype="pgp-encrypted",
+ _encoder=encoders.encode_7or8bit,
)
version["Content-Description"] = "PGP/MIME version identification"
encrypted_part = MIMEApplication(
encrypted_payload,
- _subtype='octet-stream',
- _encoder=encoders.encode_7or8bit
+ _subtype="octet-stream",
+ _encoder=encoders.encode_7or8bit,
)
encrypted_part["Content-Description"] = "OpenPGP encrypted message"
- encrypted_part["Content-Type"] = "application/octet-stream; name=\"encrypted.asc\""
- encrypted_part["Content-Disposition"] = "inline; filename=\"encrypted.asc\""
+ encrypted_part["Content-Type"] = (
+ 'application/octet-stream; name="encrypted.asc"'
+ )
+ encrypted_part["Content-Disposition"] = 'inline; filename="encrypted.asc"'
outer.attach(version)
outer.attach(encrypted_part)
body = outer.as_bytes()
@@ -497,9 +516,7 @@ class EmailGatewayComponent(GetDataHandler):
msg = MIMEText(body, "plain", "UTF-8")
if subject is not None:
msg["Subject"] = subject
- msg["From"] = formataddr(
- (credentials.user_name or None, credentials.user_email)
- )
+ msg["From"] = formataddr((credentials.user_name or None, credentials.user_email))
if extra.addresses:
assert extra.addresses.to
main_to_address = extra.addresses.to[0]
@@ -810,7 +827,9 @@ class EmailGatewayComponent(GetDataHandler):
user_email = user_data.credentials.user_email
author_name, author_email = parseaddr(email["from"])
author_email = author_email.lower()
- from_jid = jid.JID(None, (self._e.escape(author_email), self.client.jid.host, None))
+ from_jid = jid.JID(
+ None, (self._e.escape(author_email), self.client.jid.host, None)
+ )
# Get the email body
body_mime = email.get_body(("plain",))
@@ -937,7 +956,7 @@ class EmailGatewayComponent(GetDataHandler):
client = self.client.get_virtual_client(from_jid)
# Now that the message is parsed, we check if it's a mailing list.
- list_ids = email.get_all("list-id")
+ list_ids = email.get_all("list-id")
if list_ids:
try:
await self.handle_mailing_list(
@@ -950,7 +969,7 @@ class EmailGatewayComponent(GetDataHandler):
user_jid,
body,
subject,
- extra
+ extra,
)
except exceptions.DataError as e:
log.warning(f"Can't parse mailing list email: {e}.")
@@ -963,6 +982,7 @@ class EmailGatewayComponent(GetDataHandler):
{"": subject} if subject else None,
extra=extra,
)
+
def parse_references(self, email: EmailMessage) -> list[str]:
"""Extract message IDs from the "References" header.
@@ -970,7 +990,7 @@ class EmailGatewayComponent(GetDataHandler):
@returns: Message IDs
"""
references = []
- for header in email.get_all('references', []):
+ for header in email.get_all("references", []):
for token in header.split():
_, address = parseaddr(token)
if address:
@@ -984,7 +1004,7 @@ class EmailGatewayComponent(GetDataHandler):
node: str,
item_id: str,
author_name: str,
- author_email: str
+ author_email: str,
) -> MbData:
"""Convert an email to blog data.
@@ -994,16 +1014,18 @@ class EmailGatewayComponent(GetDataHandler):
tags = set()
# Title
- title = email.get('subject', '')
+ title = email.get("subject", "")
+
def strip_tags(m):
value = m.group()[1:-1].strip().lower()
if value:
tags.add(value)
return ""
+
title = re.sub(r"\[.+?\]", strip_tags, title).strip()
# Dates
- date_header = email.get('Date')
+ date_header = email.get("Date")
if date_header:
try:
published = date_utils.date_parse(date_header)
@@ -1023,10 +1045,10 @@ class EmailGatewayComponent(GetDataHandler):
for part in email.walk():
content_type = part.get_content_type()
- content_disposition = part.get('Content-Disposition', '').lower()
+ content_disposition = part.get("Content-Disposition", "").lower()
# Skip attachments
- if 'attachment' in content_disposition:
+ if "attachment" in content_disposition:
continue
payload = part.get_payload(decode=True)
@@ -1034,15 +1056,15 @@ class EmailGatewayComponent(GetDataHandler):
continue
payload = cast(bytes, payload)
- charset = part.get_content_charset() or 'utf-8'
+ charset = part.get_content_charset() or "utf-8"
try:
- payload_text = payload.decode(charset, errors='replace')
+ payload_text = payload.decode(charset, errors="replace")
except (LookupError, TypeError):
- payload_text = payload.decode('utf-8', errors='replace')
+ payload_text = payload.decode("utf-8", errors="replace")
- if content_type == 'text/plain':
+ if content_type == "text/plain":
plain_parts.append(payload_text)
- elif content_type == 'text/html':
+ elif content_type == "text/html":
html_parts.append(payload_text)
# Prefer first valid parts for safety
@@ -1055,17 +1077,17 @@ class EmailGatewayComponent(GetDataHandler):
payload = email.get_payload(decode=True)
if payload is not None:
payload = cast(bytes, payload)
- charset = email.get_content_charset() or 'utf-8'
+ charset = email.get_content_charset() or "utf-8"
try:
- content_text = payload.decode(charset, errors='replace')
+ content_text = payload.decode(charset, errors="replace")
except (LookupError, TypeError):
- content_text = payload.decode('utf-8', errors='replace')
+ content_text = payload.decode("utf-8", errors="replace")
content_type = email.get_content_type()
- if content_type == 'text/plain':
+ if content_type == "text/plain":
content = content_text
- elif content_type == 'text/html':
+ elif content_type == "text/html":
content_xhtml = content_text
if content_xhtml is None:
@@ -1086,13 +1108,11 @@ class EmailGatewayComponent(GetDataHandler):
content_xhtml=content_xhtml,
author=author_name,
author_email=author_email,
- tags=list(tags)
+ tags=list(tags),
)
async def mb_data_to_email(
- self,
- credentials: Credentials,
- mb_data: MbData
+ self, credentials: Credentials, mb_data: MbData
) -> EmailMessage:
"""Convert blog data to an email message.
@@ -1113,28 +1133,28 @@ class EmailGatewayComponent(GetDataHandler):
if mb_data.title:
title_parts.append(mb_data.title)
- email['Subject'] = ' '.join(title_parts)
+ email["Subject"] = " ".join(title_parts)
if tags:
- email['Keywords'] = ', '.join(tags)
+ email["Keywords"] = ", ".join(tags)
# From
# FIXME: Check email according to sender.
if mb_data.author and mb_data.author_email:
- email['From'] = f"{mb_data.author} <{mb_data.author_email}>"
+ email["From"] = f"{mb_data.author} <{mb_data.author_email}>"
elif mb_data.author:
- email['From'] = f"{mb_data.author} <{credentials.user_email}>"
+ email["From"] = f"{mb_data.author} <{credentials.user_email}>"
elif mb_data.author_email:
- email['From'] = mb_data.author_email
+ email["From"] = mb_data.author_email
else:
- email['From'] = credentials.user_email
+ email["From"] = credentials.user_email
# Message ID
if mb_data.id:
- email['Message-ID'] = f"<{mb_data.id}>"
+ email["Message-ID"] = f"<{mb_data.id}>"
else:
msg_id = make_msgid()
- email['Message-ID'] = msg_id
+ email["Message-ID"] = msg_id
mb_data.id = msg_id[1:-1]
# In-Reply-To
@@ -1142,20 +1162,20 @@ class EmailGatewayComponent(GetDataHandler):
# Use the first reply-to reference
in_reply_to = mb_data.in_reply_tos[0]
if in_reply_to.ref:
- email['In-Reply-To'] = f"<{in_reply_to.ref}>"
+ email["In-Reply-To"] = f"<{in_reply_to.ref}>"
# Dates
date_set = False
if mb_data.published is not None:
try:
- email['Date'] = formatdate(mb_data.published, localtime=True)
+ email["Date"] = formatdate(mb_data.published, localtime=True)
date_set = True
except Exception:
pass
if not date_set and mb_data.updated is not None:
try:
- email['Date'] = formatdate(mb_data.updated, localtime=True)
+ email["Date"] = formatdate(mb_data.updated, localtime=True)
except Exception:
pass
@@ -1172,7 +1192,7 @@ class EmailGatewayComponent(GetDataHandler):
)
email.set_content(mb_data.content)
- email.add_alternative(xhtml_content, subtype='html')
+ email.add_alternative(xhtml_content, subtype="html")
elif mb_data.content:
email.set_content(mb_data.content)
else:
@@ -1190,8 +1210,8 @@ class EmailGatewayComponent(GetDataHandler):
email: EmailMessage,
user_jid: jid.JID,
body: str,
- subject: str|None,
- extra: dict
+ subject: str | None,
+ extra: dict,
) -> None:
"""Handle emails from mailing lists.
@@ -1224,16 +1244,15 @@ class EmailGatewayComponent(GetDataHandler):
create_kwargs={
"access_model": AccessModel.whitelist,
"publish_model": PublishModel.publishers,
- "affiliations": [PubsubAffiliation(
- entity = user_jid,
- affiliation = Affiliation.owner
- )],
- "subscribed": True
+ "affiliations": [
+ PubsubAffiliation(entity=user_jid, affiliation=Affiliation.owner)
+ ],
+ "subscribed": True,
},
)
assert root_node is not None
- in_reply_to_value = ''.join(email.get_all("in-reply-to", []))
+ in_reply_to_value = "".join(email.get_all("in-reply-to", []))
__, in_reply_to = parseaddr(in_reply_to_value)
references = self.parse_references(email)
if in_reply_to:
@@ -1269,14 +1288,12 @@ class EmailGatewayComponent(GetDataHandler):
Comment(
uri=parent_node_uri,
service=pubsub_service,
- node=parent_node_name
+ node=parent_node_name,
)
- ]
+ ],
)
await G.storage.cache_pubsub_items(
- client,
- root_node,
- [await empty_item_data.to_element(client)]
+ client, root_node, [await empty_item_data.to_element(client)]
)
parent_node = await G.storage.get_pubsub_node(
client,
@@ -1288,11 +1305,10 @@ class EmailGatewayComponent(GetDataHandler):
"access_model": AccessModel.whitelist,
"publish_model": PublishModel.publishers,
"subscribed": True,
- "affiliations": [PubsubAffiliation(
- entity = user_jid,
- affiliation = Affiliation.owner
- )],
- "parent_node": root_node
+ "affiliations": [
+ PubsubAffiliation(entity=user_jid, affiliation=Affiliation.owner)
+ ],
+ "parent_node": root_node,
},
)
else:
@@ -1300,24 +1316,19 @@ class EmailGatewayComponent(GetDataHandler):
parent_node_name = cast(str, root_node.name)
mb_data = self.email_to_mb_data(
- email,
- pubsub_service,
- parent_node_name,
- message_id,
- author_name,
- author_email
+ email, pubsub_service, parent_node_name, message_id, author_name, author_email
)
mb_data.comments.append(
Comment(
- service = pubsub_service,
- node = self._mb.get_comments_node(message_id),
+ service=pubsub_service,
+ node=self._mb.get_comments_node(message_id),
)
)
await G.storage.cache_pubsub_items(
client,
parent_node,
[await mb_data.to_element(client)],
- [mb_data.model_dump(mode="json")]
+ [mb_data.model_dump(mode="json")],
)
async def handle_attachment(self, part: EmailMessage, recipient_jid: jid.JID) -> None:
@@ -1393,9 +1404,7 @@ class EmailGatewayComponent(GetDataHandler):
partial(self.on_new_email, user_data, from_jid.userhostJID()),
connected,
)
- reactor.connectTCP(
- credentials.imap_host, int(credentials.imap_port), factory
- )
+ reactor.connectTCP(credentials.imap_host, int(credentials.imap_port), factory)
await connected
async def _on_registration_submit(
@@ -1436,9 +1445,9 @@ class EmailGatewayComponent(GetDataHandler):
return True
self.validate_imap_smtp_form(submit_form)
- credentials = Credentials(**{
- key: field.value for key, field in submit_form.fields.items()
- })
+ credentials = Credentials(
+ **{key: field.value for key, field in submit_form.fields.items()}
+ )
user_data = self.users_data.get(from_jid)
if user_data is None:
# The user is not in cache, we cache current credentials.
@@ -1460,19 +1469,14 @@ class EmailGatewayComponent(GetDataHandler):
await self.storage.aset(key, credentials)
return True
-
async def on_relayed_encryption_data(
- self,
- client: SatXMPPEntity,
- iq_elt: domish.Element,
- form: data_form.Form
+ self, client: SatXMPPEntity, iq_elt: domish.Element, form: data_form.Form
) -> None:
from_jid = jid.JID(iq_elt["from"]).userhostJID()
credentials = await self.get_credentials(from_jid)
form.addField(data_form.Field(var="sender_id", value=credentials.user_email))
-
@implementer(iwokkel.IDisco)
class EmailGatewayHandler(XMPPHandler):
@@ -1482,28 +1486,13 @@ class EmailGatewayHandler(XMPPHandler):
"result",
formNamespace="urn:xmpp:data-policy:0",
fields=(
- data_form.Field(
- "list-single",
- "auth_data",
- "plain"
- ),
- data_form.Field(
- "list-single",
- "data-transmission",
- "encrypted"
-
- ),
- data_form.Field(
- "text-single",
- "encryption_algorithm",
- "TLS"
-
- ),
+ data_form.Field("list-single", "auth_data", "plain"),
+ data_form.Field("list-single", "data-transmission", "encrypted"),
+ data_form.Field("text-single", "encryption_algorithm", "TLS"),
data_form.Field(
"text-single",
"data_retention",
"0",
-
),
),
),
@@ -1515,7 +1504,6 @@ class EmailGatewayHandler(XMPPHandler):
"text-multi",
"extra_info",
"This gateway acts as a relay to external IMAP/SMTP servers. Data policies depend entirely on the external server chosen by the user. This gateway does not store or process user data.",
-
),
),
),
diff --git a/libervia/backend/plugins/plugin_comp_email_gateway/models.py b/libervia/backend/plugins/plugin_comp_email_gateway/models.py
index 412309d8..46f850a5 100644
--- a/libervia/backend/plugins/plugin_comp_email_gateway/models.py
+++ b/libervia/backend/plugins/plugin_comp_email_gateway/models.py
@@ -22,7 +22,7 @@ from twisted.mail import imap4
class Credentials(BaseModel):
- model_config = ConfigDict(extra='forbid')
+ model_config = ConfigDict(extra="forbid")
user_name: str
user_email: str
smtp_host: str
@@ -36,7 +36,6 @@ class Credentials(BaseModel):
imap_password: str
-
@dataclass
class UserData:
credentials: Credentials
diff --git a/libervia/backend/plugins/plugin_comp_email_gateway/pubsub_service.py b/libervia/backend/plugins/plugin_comp_email_gateway/pubsub_service.py
index 820e7912..4070ea6b 100644
--- a/libervia/backend/plugins/plugin_comp_email_gateway/pubsub_service.py
+++ b/libervia/backend/plugins/plugin_comp_email_gateway/pubsub_service.py
@@ -31,8 +31,14 @@ from libervia.backend.core.log import getLogger
from libervia.backend.memory.sqla_mapping import AccessModel, Affiliation
from libervia.backend.plugins.plugin_pubsub_cache import PubsubCache
from libervia.backend.plugins.plugin_xep_0498 import NodeData
-from libervia.backend.plugins.plugin_xep_0499 import ExtDiscoOptions, ExtDiscoResult, DiscoPubsubItem, DiscoPubsubNode
+from libervia.backend.plugins.plugin_xep_0499 import (
+ ExtDiscoOptions,
+ ExtDiscoResult,
+ DiscoPubsubItem,
+ DiscoPubsubNode,
+)
from libervia.backend.tools.utils import ensure_deferred
+
if TYPE_CHECKING:
from . import EmailGatewayComponent
@@ -77,10 +83,7 @@ class EmailGWPubsubResource(pubsub.PubSubResource):
return defer.ensureDeferred(self.get_nodes(requestor, service, nodeIdentifier))
async def get_nodes(
- self,
- requestor: jid.JID,
- service: jid.JID,
- node_id: str
+ self, requestor: jid.JID, service: jid.JID, node_id: str
) -> list[str]:
nodes = await G.storage.get_pubsub_nodes(self.client, self.client.jid)
return [self._pfs.namespace] + [cast(str, node.name) for node in nodes]
@@ -103,10 +106,8 @@ class EmailGWPubsubResource(pubsub.PubSubResource):
return node_data.to_elements(), None
async def items_from_mailing_list(
- self,
- request: rsm.PubSubRequest,
- requestor_jid: jid.JID
- ) -> tuple[list[domish.Element], rsm.RSMResponse|None]:
+ self, request: rsm.PubSubRequest, requestor_jid: jid.JID
+ ) -> tuple[list[domish.Element], rsm.RSMResponse | None]:
"""Handle items coming from mailing lists.
@param request: Pubsub request.
@@ -118,10 +119,7 @@ class EmailGWPubsubResource(pubsub.PubSubResource):
"""
node = request.nodeIdentifier
node = await G.storage.get_pubsub_node(
- self.client,
- self.client.jid,
- node,
- with_affiliations=True
+ self.client, self.client.jid, node, with_affiliations=True
)
if node is None:
raise error.StanzaError("item-not-found")
@@ -133,9 +131,8 @@ class EmailGWPubsubResource(pubsub.PubSubResource):
for affiliation in node.affiliations:
if (
affiliation.entity == requestor_jid
- and affiliation.affiliation in {
- Affiliation.owner, Affiliation.publisher, Affiliation.member
- }
+ and affiliation.affiliation
+ in {Affiliation.owner, Affiliation.publisher, Affiliation.member}
):
break
else:
@@ -151,7 +148,7 @@ class EmailGWPubsubResource(pubsub.PubSubResource):
request.maxItems,
request.itemIdentifiers,
request.subscriptionIdentifier,
- request.rsm
+ request.rsm,
)
if rsm_data := metadata.get("rsm"):
rsm_response = rsm.RSMResponse(**rsm_data)
@@ -159,7 +156,7 @@ class EmailGWPubsubResource(pubsub.PubSubResource):
rsm_response = None
return (
[cast(domish.Element, ps_item.data) for ps_item in pubsub_items],
- rsm_response
+ rsm_response,
)
@ensure_deferred
@@ -241,7 +238,7 @@ class EmailGWPubsubService(rsm.PubSubService):
self,
client: SatXMPPComponent,
iq_elt: domish.Element,
- ext_disco_options: ExtDiscoOptions
+ ext_disco_options: ExtDiscoOptions,
) -> ExtDiscoResult:
"""Handle pubsub extended disco"""
query_elt = iq_elt.query
@@ -253,25 +250,26 @@ class EmailGWPubsubService(rsm.PubSubService):
nodes = await G.storage.get_pubsub_nodes(
client,
service=client.jid,
- node_name = node,
+ node_name=node,
linked_node=ext_disco_options.linked_nodes,
depth=depth,
- with_items="items" in ext_disco_options.type
+ with_items="items" in ext_disco_options.type,
)
if depth == 0:
# If depth == 0, we don't want to use `from_sqlalchemy_full_hierarchy` to
# avoid returning children, and because children `parent` and `child_nodes`
# fields are not loaded.
- return ExtDiscoResult([
- DiscoPubsubNode.from_sqlalchemy(node, self.client.jid)
- for node in nodes
- ])
+ return ExtDiscoResult(
+ [DiscoPubsubNode.from_sqlalchemy(node, self.client.jid) for node in nodes]
+ )
else:
- return ExtDiscoResult([
- DiscoPubsubNode.from_sqlalchemy_full_hierarchy(node, self.client.jid)
- for node in nodes
- ])
+ return ExtDiscoResult(
+ [
+ DiscoPubsubNode.from_sqlalchemy_full_hierarchy(node, self.client.jid)
+ for node in nodes
+ ]
+ )
@ensure_deferred
async def getDiscoInfo(
diff --git a/libervia/backend/plugins/plugin_misc_groupblog.py b/libervia/backend/plugins/plugin_misc_groupblog.py
index 3c2c842e..f71d3252 100644
--- a/libervia/backend/plugins/plugin_misc_groupblog.py
+++ b/libervia/backend/plugins/plugin_misc_groupblog.py
@@ -121,7 +121,7 @@ class GroupBlog(object):
client: SatXMPPClient,
mb_data: MbData,
entry_elt: domish.Element,
- item_elt: domish.Element
+ item_elt: domish.Element,
) -> None:
"""Build fine access permission if needed
diff --git a/libervia/backend/plugins/plugin_misc_jid_search.py b/libervia/backend/plugins/plugin_misc_jid_search.py
index 2636fbeb..40615cad 100644
--- a/libervia/backend/plugins/plugin_misc_jid_search.py
+++ b/libervia/backend/plugins/plugin_misc_jid_search.py
@@ -46,7 +46,7 @@ PLUGIN_INFO = {
C.PI_DESCRIPTION: _("""Search for XMPP entities"""),
}
RATIO_CUTOFF = 0.6
-# Used when a search term matches a substring of a relevant data.
+# Used when a search term matches a substring of a relevant data.
PARTIAL_MATCH_RATIO = 0.8
MAX_CACHE_SIZE = 10
@@ -103,9 +103,7 @@ class Options(BaseModel):
entities: bool = Field(
default=False, description="Search for entities for direct chat"
)
- groupchat: bool = Field(
- default=False, description="Search for group chats."
- )
+ groupchat: bool = Field(default=False, description="Search for group chats.")
allow_external: bool = Field(
default=False, description="Authorise doing request to external services."
)
@@ -221,7 +219,9 @@ class JidSearch:
matches.sort(
key=lambda item: (
- item.exact_match, item.relevance or 0, getattr(item, "in_roster", False)
+ item.exact_match,
+ item.relevance or 0,
+ getattr(item, "in_roster", False),
),
reverse=True,
)
diff --git a/libervia/backend/plugins/plugin_misc_text_syntaxes.py b/libervia/backend/plugins/plugin_misc_text_syntaxes.py
index 0b5bad6e..14aa3b59 100644
--- a/libervia/backend/plugins/plugin_misc_text_syntaxes.py
+++ b/libervia/backend/plugins/plugin_misc_text_syntaxes.py
@@ -197,7 +197,7 @@ SAFE_CLASSES = {
"write",
# "noise" class is used by gateways (in particular email gateway) to mark annoying and
# not useful content.
- "noise"
+ "noise",
}
STYLES_VALUES_REGEX = (
"^("
diff --git a/libervia/backend/plugins/plugin_pubsub_cache.py b/libervia/backend/plugins/plugin_pubsub_cache.py
index c6af8cbe..5a93345f 100644
--- a/libervia/backend/plugins/plugin_pubsub_cache.py
+++ b/libervia/backend/plugins/plugin_pubsub_cache.py
@@ -350,7 +350,7 @@ class PubsubCache:
client: SatXMPPEntity,
service: jid.JID,
node: str,
- pubsub_node: PubsubNode|None = None,
+ pubsub_node: PubsubNode | None = None,
) -> dict:
"""Use registered analysers on a node to determine what it is used for"""
analyse = {"service": service, "node": node}
diff --git a/libervia/backend/plugins/plugin_sec_autocrypt.py b/libervia/backend/plugins/plugin_sec_autocrypt.py
index 79227453..4f50bbdd 100644
--- a/libervia/backend/plugins/plugin_sec_autocrypt.py
+++ b/libervia/backend/plugins/plugin_sec_autocrypt.py
@@ -232,7 +232,9 @@ class Autocrypt:
post_treat.addCallback(partial(self._check_headers, client))
return True
- async def add_autocrypt_header(self, client, mess_data: MessageDataLegacy) -> MessageDataLegacy:
+ async def add_autocrypt_header(
+ self, client, mess_data: MessageDataLegacy
+ ) -> MessageDataLegacy:
to_jid = mess_data["to"]
if await self.host.memory.disco.has_identity(
client, "gateway", "smtp", jid.JID(to_jid.host)
diff --git a/libervia/backend/plugins/plugin_sec_gre_encrypter_openpgp.py b/libervia/backend/plugins/plugin_sec_gre_encrypter_openpgp.py
index b85d2bcb..e7625017 100644
--- a/libervia/backend/plugins/plugin_sec_gre_encrypter_openpgp.py
+++ b/libervia/backend/plugins/plugin_sec_gre_encrypter_openpgp.py
@@ -83,9 +83,7 @@ class GREEncrypterOpenPGP(Encrypter):
raise exceptions.NotFound(
f"No public keys found for {recipient_id!r}, we can't encrypt."
)
- encrypted_data = gpg_provider.encrypt(
- formatted_payload, public_keys
- )
+ encrypted_data = gpg_provider.encrypt(formatted_payload, public_keys)
return base64.b64encode(encrypted_data).decode("ASCII")
diff --git a/libervia/backend/plugins/plugin_xep_0045.py b/libervia/backend/plugins/plugin_xep_0045.py
index 9eb5ca9b..75bf94fa 100644
--- a/libervia/backend/plugins/plugin_xep_0045.py
+++ b/libervia/backend/plugins/plugin_xep_0045.py
@@ -264,24 +264,21 @@ class XEP_0045:
search_term: str,
options: plugin_misc_jid_search.Options,
sequence_matcher: difflib.SequenceMatcher,
- matches: plugin_misc_jid_search.SearchItems
+ matches: plugin_misc_jid_search.SearchItems,
) -> bool:
if options.groupchat:
if client.muc_service is not None:
# FIXME: RSM is not handled, we need proper RSM handling as number of
# rooms may be large.
disco_items = await self.host.memory.disco.get_items(
- client,
- client.muc_service
+ client, client.muc_service
)
for disco_item in disco_items:
search_item = plugin_misc_jid_search.RoomSearchItem(
- entity = disco_item.entity,
- name = disco_item.name or "",
- local = True
+ entity=disco_item.entity, name=disco_item.name or "", local=True
)
self._jid_search.process_matching(
- search_term, sequence_matcher, matches,search_item
+ search_term, sequence_matcher, matches, search_item
)
return True
diff --git a/libervia/backend/plugins/plugin_xep_0059.py b/libervia/backend/plugins/plugin_xep_0059.py
index 8a2cef4d..1afcf40d 100644
--- a/libervia/backend/plugins/plugin_xep_0059.py
+++ b/libervia/backend/plugins/plugin_xep_0059.py
@@ -47,12 +47,13 @@ RSM_PREFIX = "rsm_"
class RSMRequest(BaseModel):
"""Pydantic model for RSM request parameters"""
+
max: int = Field(default=10, gt=0)
after: str | None = None
before: str | None = None
index: int | None = None
- @field_validator('after')
+ @field_validator("after")
def check_after_not_empty(cls, v: str | None) -> str | None:
"""Validate that after value isn't empty string
@@ -62,7 +63,7 @@ class RSMRequest(BaseModel):
@raise ValueError: if value is an empty string
"""
if v == "":
- raise ValueError("RSM \"after\" can't be empty")
+ raise ValueError('RSM "after" can\'t be empty')
return v
def to_wokkel_request(self) -> rsm.RSMRequest:
@@ -71,10 +72,7 @@ class RSMRequest(BaseModel):
@return: wokkel RSMRequest instance
"""
return rsm.RSMRequest(
- max_=self.max,
- after=self.after,
- before=self.before,
- index=self.index
+ max_=self.max, after=self.after, before=self.before, index=self.index
)
@classmethod
@@ -88,7 +86,7 @@ class RSMRequest(BaseModel):
max=request.max,
after=request.after,
before=request.before,
- index=request.index
+ index=request.index,
)
def to_element(self) -> domish.Element:
@@ -117,6 +115,7 @@ class RSMRequest(BaseModel):
class RSMResponse(BaseModel):
"""Pydantic model for RSM response parameters"""
+
first: str | None = None
last: str | None = None
index: int | None = None
@@ -128,10 +127,7 @@ class RSMResponse(BaseModel):
@return: wokkel RSMResponse instance
"""
return rsm.RSMResponse(
- first=self.first,
- last=self.last,
- index=self.index,
- count=self.count
+ first=self.first, last=self.last, index=self.index, count=self.count
)
@classmethod
@@ -145,7 +141,7 @@ class RSMResponse(BaseModel):
first=response.first,
last=response.last,
index=response.index,
- count=response.count
+ count=response.count,
)
def to_element(self) -> domish.Element:
@@ -180,7 +176,7 @@ class XEP_0059:
"""
log.info(f"Plugin {PLUGIN_INFO[C.PI_NAME]!r} initialization.")
- def get_handler(self, client) -> 'XEP_0059_handler':
+ def get_handler(self, client) -> "XEP_0059_handler":
"""Get the XMPP handler for this plugin
@param client: client instance
@@ -209,9 +205,7 @@ class XEP_0059:
return RSMRequest(**rsm_args).to_wokkel_request() if rsm_args else None
def response2dict(
- self,
- rsm_response: rsm.RSMResponse,
- data: dict[str, str] | None = None
+ self, rsm_response: rsm.RSMResponse, data: dict[str, str] | None = None
) -> dict[str, str]:
"""Return a dict with RSM response data
@@ -281,19 +275,13 @@ class XEP_0059:
log.warning('Can\'t do pagination, no "last" received.')
return None
- return RSMRequest(
- max=rsm_request.max,
- after=rsm_response.last
- )
+ return RSMRequest(max=rsm_request.max, after=rsm_response.last)
@implementer(iwokkel.IDisco)
class XEP_0059_handler(xmlstream.XMPPHandler):
def getDiscoInfo(
- self,
- requestor: str,
- target: str,
- nodeIdentifier: str = ""
+ self, requestor: str, target: str, nodeIdentifier: str = ""
) -> list[disco.DiscoFeature]:
"""Get disco info for RSM
@@ -305,10 +293,7 @@ class XEP_0059_handler(xmlstream.XMPPHandler):
return [disco.DiscoFeature(rsm.NS_RSM)]
def getDiscoItems(
- self,
- requestor: str,
- target: str,
- nodeIdentifier: str = ""
+ self, requestor: str, target: str, nodeIdentifier: str = ""
) -> list:
"""Get disco items for RSM
diff --git a/libervia/backend/plugins/plugin_xep_0060.py b/libervia/backend/plugins/plugin_xep_0060.py
index 88d81594..c4af6f8b 100644
--- a/libervia/backend/plugins/plugin_xep_0060.py
+++ b/libervia/backend/plugins/plugin_xep_0060.py
@@ -19,7 +19,18 @@
from collections import namedtuple
from functools import reduce
-from typing import Any, Callable, ClassVar, Dict, Iterable, List, Optional, Self, Set, Union
+from typing import (
+ Any,
+ Callable,
+ ClassVar,
+ Dict,
+ Iterable,
+ List,
+ Optional,
+ Self,
+ Set,
+ Union,
+)
import urllib.parse
from pydantic import BaseModel, Field
@@ -79,9 +90,8 @@ DEFAULT_PUBSUB_MIN_FEAT = {
class NodeMetadata(BaseModel):
"""Node metadata model."""
- model_config = {
- "extra": "allow"
- }
+
+ model_config = {"extra": "allow"}
type: str | None = None
creator: JIDType | None = None
@@ -199,9 +209,7 @@ class NodeMetadata(BaseModel):
"pubsub#owner": self.owner,
"pubsub#publisher": self.publisher,
"pubsub#num_subscribers": (
- str(self.num_subscribers)
- if self.num_subscribers is not None
- else None
+ str(self.num_subscribers) if self.num_subscribers is not None else None
),
}
form.makeFields(
diff --git a/libervia/backend/plugins/plugin_xep_0277.py b/libervia/backend/plugins/plugin_xep_0277.py
index f554ca59..a6f1ad8a 100644
--- a/libervia/backend/plugins/plugin_xep_0277.py
+++ b/libervia/backend/plugins/plugin_xep_0277.py
@@ -90,20 +90,20 @@ class Comment(BaseModel):
service: JIDType | None = None
node: str = ""
- @model_validator(mode='after')
+ @model_validator(mode="after")
def set_uri_if_missing(self) -> Self:
if not self.uri and self.service is not None and self.node:
self.uri = xmpp_uri.build_xmpp_uri(
- "pubsub",
- path=self.service.full(),
- node=self.node
+ "pubsub", path=self.service.full(), node=self.node
)
return self
+
class InReplyTo(BaseModel):
ref: str
- href: str|None
- type: str|None = None
+ href: str | None
+ type: str | None = None
+
class Attachment(BaseModel):
sources: list[dict[str, str]] = Field(default_factory=list)
@@ -157,7 +157,6 @@ class MbData(BaseModel):
updated: float | None = None
language: str | None = None
-
title: str | None = None
title_xhtml: str | None = None
title_rich: str | None = Field(default=None, exclude=True)
@@ -172,7 +171,7 @@ class MbData(BaseModel):
allow_comments: bool | None = None
comments: list[Comment] = Field(default_factory=list)
- in_reply_tos: list[InReplyTo]|None = None
+ in_reply_tos: list[InReplyTo] | None = None
tags: list[str] = Field(default_factory=list)
extra: MbExtra = Field(default_factory=MbExtra)
@@ -365,7 +364,7 @@ class MbData(BaseModel):
in_reply_to = InReplyTo(
ref=in_reply_to_elt.getAttribute("ref", ""),
href=in_reply_to_elt.getAttribute("href"),
- type=in_reply_to_elt.getAttribute("type")
+ type=in_reply_to_elt.getAttribute("type"),
)
if not in_reply_to_elt.ref:
log.warning(
@@ -722,7 +721,7 @@ class MbData(BaseModel):
if href := in_reply_to.href is not None:
in_reply_to_elt["href"] = href
if type_ := in_reply_to.type is not None:
- in_reply_to_elt["type"] = type_
+ in_reply_to_elt["type"] = type_
## Reposts ##
if self.extra.repeated:
diff --git a/libervia/backend/plugins/plugin_xep_0297.py b/libervia/backend/plugins/plugin_xep_0297.py
index b4ec1a18..93b8a839 100644
--- a/libervia/backend/plugins/plugin_xep_0297.py
+++ b/libervia/backend/plugins/plugin_xep_0297.py
@@ -41,11 +41,9 @@ from libervia.backend.plugins.plugin_xep_0428 import XEP_0428
from libervia.backend.tools.common.date_utils import date_fmt
-
log = getLogger(__name__)
-
PLUGIN_INFO = {
C.PI_NAME: "Stanza Forwarding",
C.PI_IMPORT_NAME: "XEP-0297",
@@ -97,32 +95,27 @@ class XEP_0297:
XEP_0297.update_uri(child, uri)
def _forward(
- self,
- message_id: str,
- recipient_jid_s: str,
- profile_key: str
+ self, message_id: str, recipient_jid_s: str, profile_key: str
) -> defer.Deferred[None]:
client = self.host.get_client(profile_key)
recipient_jid = jid.JID(recipient_jid_s)
return defer.ensureDeferred(self.forward_by_id(client, message_id, recipient_jid))
async def forward_by_id(
- self,
- client: SatXMPPEntity,
- message_id: str,
- recipient_jid: jid.JID
+ self, client: SatXMPPEntity, message_id: str, recipient_jid: jid.JID
) -> None:
- history = cast(History, await G.storage.get(
- client,
+ history = cast(
History,
- History.uid,
- message_id,
- joined_loads=[History.messages, History.subjects, History.thread],
- ))
+ await G.storage.get(
+ client,
+ History,
+ History.uid,
+ message_id,
+ joined_loads=[History.messages, History.subjects, History.thread],
+ ),
+ )
if not history:
- raise exceptions.NotFound(
- f"No history found with message {message_id!r}."
- )
+ raise exceptions.NotFound(f"No history found with message {message_id!r}.")
# FIXME: Q&D way to get MessageData from History. History should have a proper
# way to do that.
serialised_history = history.serialise()
@@ -138,7 +131,7 @@ class XEP_0297:
f"{client.jid.userhost()} is forwarding this message to you:",
f"[{date_fmt(timestamp_float)}]",
f"From: {history.source_jid.full()}",
- f"To: {history.dest_jid.full()}"
+ f"To: {history.dest_jid.full()}",
]
for subject in history.subjects:
@@ -162,8 +155,8 @@ class XEP_0297:
client: SatXMPPEntity,
stanza: domish.Element,
to_jid: jid.JID,
- timestamp: datetime|None,
- fallback_msg: str | None = None
+ timestamp: datetime | None,
+ fallback_msg: str | None = None,
):
"""Forward a message to the given JID.
diff --git a/libervia/backend/plugins/plugin_xep_0373.py b/libervia/backend/plugins/plugin_xep_0373.py
index 25b8b423..d19a22dc 100644
--- a/libervia/backend/plugins/plugin_xep_0373.py
+++ b/libervia/backend/plugins/plugin_xep_0373.py
@@ -120,8 +120,8 @@ def crc24(data: bytes) -> int:
def binary_to_ascii_armor(
data: bytes,
armor_type: str = "MESSAGE",
- headers: dict|None = None,
- line_length: int = 76
+ headers: dict | None = None,
+ line_length: int = 76,
) -> str:
"""Convert binary data to OpenPGP ASCII Armor format.
@@ -131,14 +131,15 @@ def binary_to_ascii_armor(
@param line_length: Maximum length of each line.
@return: The ASCII Armor encoded string.
"""
- encoded_data = base64.b64encode(data).decode('ascii')
+ encoded_data = base64.b64encode(data).decode("ascii")
encoded_lines = [
- encoded_data[i:i+line_length] for i in range(0, len(encoded_data), line_length)
+ encoded_data[i : i + line_length]
+ for i in range(0, len(encoded_data), line_length)
]
checksum = crc24(data)
- checksum_str = base64.b64encode(checksum.to_bytes(3, 'big')).decode('ascii')
+ checksum_str = base64.b64encode(checksum.to_bytes(3, "big")).decode("ascii")
header_lines = []
if headers:
@@ -153,7 +154,7 @@ def binary_to_ascii_armor(
armor.append(f"={checksum_str}")
armor.append(f"-----END PGP {armor_type}-----")
- return '\n'.join(armor)
+ return "\n".join(armor)
class VerificationError(Exception):
diff --git a/libervia/backend/plugins/plugin_xep_0376.py b/libervia/backend/plugins/plugin_xep_0376.py
index f0ff59a6..2cb0c51f 100644
--- a/libervia/backend/plugins/plugin_xep_0376.py
+++ b/libervia/backend/plugins/plugin_xep_0376.py
@@ -142,7 +142,7 @@ class XEP_0376:
self,
client: SatXMPPEntity,
service: Optional[jid.JID],
- node: str|None,
+ node: str | None,
) -> Tuple[bool, Optional[List[Dict[str, Any]]]]:
if not await self.host.has_feature(client, NS_PAM):
return True, None
diff --git a/libervia/backend/plugins/plugin_xep_0428.py b/libervia/backend/plugins/plugin_xep_0428.py
index 54352d3c..88f3f949 100644
--- a/libervia/backend/plugins/plugin_xep_0428.py
+++ b/libervia/backend/plugins/plugin_xep_0428.py
@@ -50,10 +50,7 @@ class XEP_0428:
host.register_namespace("fallback", NS_FALLBACK)
def add_fallback_elt(
- self,
- message_elt: domish.Element,
- for_: str,
- msg: str|None = None
+ self, message_elt: domish.Element, for_: str, msg: str | None = None
) -> None:
"""Add the fallback indication element
diff --git a/libervia/backend/plugins/plugin_xep_0461.py b/libervia/backend/plugins/plugin_xep_0461.py
index 7aec7a2a..3c954b00 100644
--- a/libervia/backend/plugins/plugin_xep_0461.py
+++ b/libervia/backend/plugins/plugin_xep_0461.py
@@ -63,7 +63,7 @@ class ReplyTo(BaseModel):
internal_uid: bool = Field(
default=True,
description="True if the id is a message UID, i.e. Libervia internal ID of "
- "message, otherwise it's an XMPP stanza ID or origin ID as specified in the XEP"
+ "message, otherwise it's an XMPP stanza ID or origin ID as specified in the XEP",
)
async def ensure_xmpp_id(self, client: SatXMPPEntity) -> None:
@@ -118,7 +118,8 @@ class ReplyTo(BaseModel):
if self.internal_uid:
raise exceptions.DataError(
'"id" must be converted to XMPP id before calling "to_element". Please '
- '"use ensure_xmpp_id" first.')
+ '"use ensure_xmpp_id" first.'
+ )
reply_elt = domish.Element((NS_REPLY, "reply"), attribs={"id": self.id})
if self.to is not None:
reply_elt["to"] = self.to.full()
@@ -188,7 +189,9 @@ class XEP_0461:
return True
@ensure_deferred
- async def _add_reply_to_elt(self, mess_data: MessageData, client: SatXMPPEntity) -> MessageData:
+ async def _add_reply_to_elt(
+ self, mess_data: MessageData, client: SatXMPPEntity
+ ) -> MessageData:
try:
# FIXME: Once MessageData is fully moved to Pydantic, we should have directly
# the ReplyTo instance here.
diff --git a/libervia/backend/test/helpers_plugins.py b/libervia/backend/test/helpers_plugins.py
index ce039f94..0ec643a2 100644
--- a/libervia/backend/test/helpers_plugins.py
+++ b/libervia/backend/test/helpers_plugins.py
@@ -18,7 +18,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-""" Helpers class for plugin dependencies """
+"""Helpers class for plugin dependencies"""
from twisted.internet import defer
diff --git a/libervia/backend/test/test_helpers_plugins.py b/libervia/backend/test/test_helpers_plugins.py
index 754ea45f..a019d764 100644
--- a/libervia/backend/test/test_helpers_plugins.py
+++ b/libervia/backend/test/test_helpers_plugins.py
@@ -18,7 +18,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-""" Test the helper classes to see if they behave well"""
+"""Test the helper classes to see if they behave well"""
from libervia.backend.test import helpers
from libervia.backend.test import helpers_plugins
diff --git a/libervia/backend/test/test_memory_crypto.py b/libervia/backend/test/test_memory_crypto.py
index 9e306a67..76e9870c 100644
--- a/libervia/backend/test/test_memory_crypto.py
+++ b/libervia/backend/test/test_memory_crypto.py
@@ -19,7 +19,7 @@
# along with this program. If not, see .
-""" Tests for the plugin radiocol """
+"""Tests for the plugin radiocol"""
from libervia.backend.test import helpers
from libervia.backend.memory.crypto import BlockCipher, PasswordHasher
diff --git a/libervia/backend/test/test_plugin_misc_groupblog.py b/libervia/backend/test/test_plugin_misc_groupblog.py
index 8bcde755..89d73fcc 100644
--- a/libervia/backend/test/test_plugin_misc_groupblog.py
+++ b/libervia/backend/test/test_plugin_misc_groupblog.py
@@ -18,7 +18,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-""" Plugin groupblogs """
+"""Plugin groupblogs"""
from .constants import Const as C
from libervia.backend.test import helpers, helpers_plugins
diff --git a/libervia/backend/test/test_plugin_misc_radiocol.py b/libervia/backend/test/test_plugin_misc_radiocol.py
index b053bf07..76fe4621 100644
--- a/libervia/backend/test/test_plugin_misc_radiocol.py
+++ b/libervia/backend/test/test_plugin_misc_radiocol.py
@@ -18,7 +18,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-""" Tests for the plugin radiocol """
+"""Tests for the plugin radiocol"""
from libervia.backend.core import exceptions
from libervia.backend.test import helpers, helpers_plugins
diff --git a/libervia/backend/test/test_plugin_misc_room_game.py b/libervia/backend/test/test_plugin_misc_room_game.py
index 3db9e279..2b43f6aa 100644
--- a/libervia/backend/test/test_plugin_misc_room_game.py
+++ b/libervia/backend/test/test_plugin_misc_room_game.py
@@ -18,7 +18,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-""" Tests for the plugin room game (base class for MUC games) """
+"""Tests for the plugin room game (base class for MUC games)"""
from libervia.backend.core.i18n import _
from .constants import Const
diff --git a/libervia/backend/test/test_plugin_misc_text_syntaxes.py b/libervia/backend/test/test_plugin_misc_text_syntaxes.py
index 656a86cc..c04c7a61 100644
--- a/libervia/backend/test/test_plugin_misc_text_syntaxes.py
+++ b/libervia/backend/test/test_plugin_misc_text_syntaxes.py
@@ -17,7 +17,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-""" Plugin text syntaxes tests """
+"""Plugin text syntaxes tests"""
from libervia.backend.test import helpers
from libervia.backend.plugins import plugin_misc_text_syntaxes
diff --git a/libervia/backend/test/test_plugin_xep_0085.py b/libervia/backend/test/test_plugin_xep_0085.py
index 32356294..f87ccb19 100644
--- a/libervia/backend/test/test_plugin_xep_0085.py
+++ b/libervia/backend/test/test_plugin_xep_0085.py
@@ -18,7 +18,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-""" Plugin chat states notification tests """
+"""Plugin chat states notification tests"""
from .constants import Const
from libervia.backend.test import helpers
diff --git a/libervia/backend/test/test_plugin_xep_0203.py b/libervia/backend/test/test_plugin_xep_0203.py
index 1493dc06..6b5cd3bb 100644
--- a/libervia/backend/test/test_plugin_xep_0203.py
+++ b/libervia/backend/test/test_plugin_xep_0203.py
@@ -18,7 +18,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-""" Plugin XEP-0203 """
+"""Plugin XEP-0203"""
from libervia.backend.test import helpers
from libervia.backend.plugins.plugin_xep_0203 import XEP_0203
diff --git a/libervia/backend/test/test_plugin_xep_0277.py b/libervia/backend/test/test_plugin_xep_0277.py
index 45619a31..730dcc4b 100644
--- a/libervia/backend/test/test_plugin_xep_0277.py
+++ b/libervia/backend/test/test_plugin_xep_0277.py
@@ -17,7 +17,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-""" Plugin XEP-0277 tests """
+"""Plugin XEP-0277 tests"""
from libervia.backend.test import helpers
from libervia.backend.plugins import plugin_xep_0277
diff --git a/libervia/backend/test/test_plugin_xep_0297.py b/libervia/backend/test/test_plugin_xep_0297.py
index 30d33c99..c54cd8bb 100644
--- a/libervia/backend/test/test_plugin_xep_0297.py
+++ b/libervia/backend/test/test_plugin_xep_0297.py
@@ -18,7 +18,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-""" Plugin XEP-0297 """
+"""Plugin XEP-0297"""
from .constants import Const as C
from libervia.backend.test import helpers
diff --git a/libervia/backend/test/test_plugin_xep_0313.py b/libervia/backend/test/test_plugin_xep_0313.py
index 140558eb..212d2c75 100644
--- a/libervia/backend/test/test_plugin_xep_0313.py
+++ b/libervia/backend/test/test_plugin_xep_0313.py
@@ -18,7 +18,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-""" Plugin XEP-0313 """
+"""Plugin XEP-0313"""
from .constants import Const as C
from libervia.backend.test import helpers
diff --git a/libervia/backend/test/test_plugin_xep_0334.py b/libervia/backend/test/test_plugin_xep_0334.py
index bb6249a9..3205019b 100644
--- a/libervia/backend/test/test_plugin_xep_0334.py
+++ b/libervia/backend/test/test_plugin_xep_0334.py
@@ -18,7 +18,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-""" Plugin XEP-0334 """
+"""Plugin XEP-0334"""
from .constants import Const as C
from libervia.backend.test import helpers
diff --git a/libervia/backend/tools/common/data_format.py b/libervia/backend/tools/common/data_format.py
index edd57f71..19b16a01 100644
--- a/libervia/backend/tools/common/data_format.py
+++ b/libervia/backend/tools/common/data_format.py
@@ -17,7 +17,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-""" tools common to backend and frontends """
+"""tools common to backend and frontends"""
# FIXME: json may be more appropriate than manual serialising like done here
from typing import Any
diff --git a/libervia/backend/tools/common/date_utils.py b/libervia/backend/tools/common/date_utils.py
index cfbfcc17..bee595be 100644
--- a/libervia/backend/tools/common/date_utils.py
+++ b/libervia/backend/tools/common/date_utils.py
@@ -61,7 +61,7 @@ TZ_UTC = tz.tzutc()
TZ_LOCAL = tz.gettz()
-def date_parse(value: str, default_tz: datetime.tzinfo=TZ_UTC) -> int:
+def date_parse(value: str, default_tz: datetime.tzinfo = TZ_UTC) -> int:
"""Parse a date and return corresponding unix timestamp
@param value: date to parse, in any format supported by parser
diff --git a/libervia/backend/tools/common/dynamic_import.py b/libervia/backend/tools/common/dynamic_import.py
index 68cc50bc..45a85b59 100644
--- a/libervia/backend/tools/common/dynamic_import.py
+++ b/libervia/backend/tools/common/dynamic_import.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-""" tools dynamic import """
+"""tools dynamic import"""
from importlib import import_module
from libervia.backend.core.log import getLogger
diff --git a/libervia/backend/tools/common/regex.py b/libervia/backend/tools/common/regex.py
index e2d703d1..dd000af8 100644
--- a/libervia/backend/tools/common/regex.py
+++ b/libervia/backend/tools/common/regex.py
@@ -17,7 +17,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-""" regex tools common to backend and frontends """
+"""regex tools common to backend and frontends"""
import re
import unicodedata
diff --git a/libervia/backend/tools/common/template_xmlui.py b/libervia/backend/tools/common/template_xmlui.py
index da52c8fa..81ec3162 100644
--- a/libervia/backend/tools/common/template_xmlui.py
+++ b/libervia/backend/tools/common/template_xmlui.py
@@ -17,7 +17,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-""" template XMLUI parsing
+"""template XMLUI parsing
XMLUI classes from this modules can then be iterated to create the template
"""
diff --git a/libervia/backend/tools/common/uri.py b/libervia/backend/tools/common/uri.py
index e7c39423..c5c9d8bc 100644
--- a/libervia/backend/tools/common/uri.py
+++ b/libervia/backend/tools/common/uri.py
@@ -17,7 +17,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-""" XMPP uri parsing tools """
+"""XMPP uri parsing tools"""
from typing import Optional
import sys
diff --git a/libervia/backend/tools/config.py b/libervia/backend/tools/config.py
index 007932c1..e3504ced 100644
--- a/libervia/backend/tools/config.py
+++ b/libervia/backend/tools/config.py
@@ -18,7 +18,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-""" Configuration related useful methods """
+"""Configuration related useful methods"""
import os
import csv
diff --git a/libervia/backend/tools/stream.py b/libervia/backend/tools/stream.py
index 87514248..4315b7d5 100644
--- a/libervia/backend/tools/stream.py
+++ b/libervia/backend/tools/stream.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-""" interfaces """
+"""interfaces"""
from argparse import OPTIONAL
from pathlib import Path
diff --git a/libervia/backend/tools/utils.py b/libervia/backend/tools/utils.py
index b4c43efb..57a39a89 100644
--- a/libervia/backend/tools/utils.py
+++ b/libervia/backend/tools/utils.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-""" various useful methods """
+"""various useful methods"""
from typing import Optional, Union
import unicodedata
diff --git a/libervia/cli/base.py b/libervia/cli/base.py
index 3375977a..bf89aef0 100644
--- a/libervia/cli/base.py
+++ b/libervia/cli/base.py
@@ -54,7 +54,6 @@ log.basicConfig(level=log.WARNING, format="[%(name)s] %(message)s")
###
-
## bridge handling
# we get bridge name from conf and initialise the right class accordingly
main_config = config.parse_main_conf()
@@ -91,6 +90,7 @@ PROGRESS_DELAY = 0.1 # the progression will be checked every PROGRESS_DELAY s
def date_decoder(arg):
return date_utils.date_parse_ext(arg, default_tz=date_utils.TZ_LOCAL)
+
def optional_bool_decoder(arg: str) -> bool:
"""Decode an optional string to a boolean value.
@@ -99,9 +99,9 @@ def optional_bool_decoder(arg: str) -> bool:
@raise ValueError: If the input string is not a valid boolean representation.
"""
lower_arg = arg.lower()
- if lower_arg in ['true', '1', 't', 'y', 'yes']:
+ if lower_arg in ["true", "1", "t", "y", "yes"]:
return True
- elif lower_arg in ['false', '0', 'f', 'n', 'no']:
+ elif lower_arg in ["false", "0", "f", "n", "no"]:
return False
else:
raise ValueError(f"Invalid boolean value: {arg}")
diff --git a/libervia/cli/cmd_bookmarks.py b/libervia/cli/cmd_bookmarks.py
index 8e9c80b9..c44091bb 100644
--- a/libervia/cli/cmd_bookmarks.py
+++ b/libervia/cli/cmd_bookmarks.py
@@ -33,9 +33,11 @@ class BookmarksList(base.CommandBase):
def __init__(self, host):
extra_outputs = {"default": self.default_output}
super().__init__(
- host, "list", help=_("list bookmarks"),
+ host,
+ "list",
+ help=_("list bookmarks"),
use_output=C.OUTPUT_COMPLEX,
- extra_outputs=extra_outputs
+ extra_outputs=extra_outputs,
)
def add_parser_options(self):
@@ -55,16 +57,16 @@ class BookmarksList(base.CommandBase):
conference_data.get("name", ""),
conference_data.get("nick", ""),
conference_data.get("password", ""),
- "✅" if conference_data.get("autojoin", False) else "❌"
+ "✅" if conference_data.get("autojoin", False) else "❌",
)
self.console.print(table)
async def start(self):
try:
- data = data_format.deserialise(await self.host.bridge.bookmarks_list(
- "", self.host.profile
- ))
+ data = data_format.deserialise(
+ await self.host.bridge.bookmarks_list("", self.host.profile)
+ )
except Exception as e:
self.disp(f"can't get bookmarks list: {e}", error=True)
self.host.quit(C.EXIT_BRIDGE_ERRBACK)
@@ -79,9 +81,7 @@ class BookmarksRemove(base.CommandBase):
super().__init__(host, "remove", help=_("remove a bookmark"))
def add_parser_options(self):
- self.parser.add_argument(
- "bookmark", help=_("jid of the bookmark to remove")
- )
+ self.parser.add_argument("bookmark", help=_("jid of the bookmark to remove"))
self.parser.add_argument(
"-f",
"--force",
@@ -92,14 +92,13 @@ class BookmarksRemove(base.CommandBase):
async def start(self):
if not self.args.force:
await self.host.confirm_or_quit(
- _("Are you sure to delete the bookmark {bookmark_id!r}?")
- .format(bookmark_id=self.args.bookmark)
+ _("Are you sure to delete the bookmark {bookmark_id!r}?").format(
+ bookmark_id=self.args.bookmark
+ )
)
try:
- await self.host.bridge.bookmark_remove(
- self.args.bookmark, self.host.profile
- )
+ await self.host.bridge.bookmark_remove(self.args.bookmark, self.host.profile)
except Exception as e:
self.disp(_("can't delete bookmark: {e}").format(e=e), error=True)
self.host.quit(C.EXIT_BRIDGE_ERRBACK)
@@ -110,9 +109,7 @@ class BookmarksRemove(base.CommandBase):
class BookmarksSet(base.CommandBase):
def __init__(self, host):
- super().__init__(
- host, "set", help=_("add or update a bookmark")
- )
+ super().__init__(host, "set", help=_("add or update a bookmark"))
def add_parser_options(self):
self.parser.add_argument("bookmark", help=_("jid of the chat room"))
@@ -133,18 +130,16 @@ class BookmarksSet(base.CommandBase):
help=_("join the conference room"),
)
self.parser.add_argument(
- "-N",
- "--nick", help=_("preferred roomnick for the chatroom")
+ "-N", "--nick", help=_("preferred roomnick for the chatroom")
)
self.parser.add_argument(
- "-P",
- "--password", help=_("password used to access the chatroom")
+ "-P", "--password", help=_("password used to access the chatroom")
)
self.parser.add_argument(
"-u",
"--update",
action="store_true",
- help=_("update bookmark data instead of replacing")
+ help=_("update bookmark data instead of replacing"),
)
async def start(self):
@@ -167,7 +162,7 @@ class BookmarksSet(base.CommandBase):
self.disp(
f"Can't find existing bookmark {self.args.bookmark!r}: {e}. We "
"create it.",
- error=True
+ error=True,
)
else:
old_conference_data.update(conference_data)
@@ -190,6 +185,4 @@ class Bookmarks(base.CommandBase):
subcommands = (BookmarksList, BookmarksSet, BookmarksRemove, BookmarksLegacy)
def __init__(self, host):
- super().__init__(
- host, "bookmarks", use_profile=False, help=_("manage bookmarks")
- )
+ super().__init__(host, "bookmarks", use_profile=False, help=_("manage bookmarks"))
diff --git a/libervia/cli/cmd_pubsub.py b/libervia/cli/cmd_pubsub.py
index 2cfa0210..4331eb9f 100644
--- a/libervia/cli/cmd_pubsub.py
+++ b/libervia/cli/cmd_pubsub.py
@@ -1592,9 +1592,7 @@ class List(base.CommandBase):
)
async def start(self):
- options = {
- "depth": self.args.depth
- }
+ options = {"depth": self.args.depth}
try:
result_s = await self.host.bridge.ps_disco_get(
self.args.service,
@@ -1617,7 +1615,6 @@ class List(base.CommandBase):
node_tree.add(self.recursive_tree(child))
return node_tree
-
def default_output(self, data: list) -> None:
"""Output the node as a tree view."""
for item in data:
diff --git a/libervia/frontends/quick_frontend/quick_contact_list.py b/libervia/frontends/quick_frontend/quick_contact_list.py
index 5add0031..70c6d483 100644
--- a/libervia/frontends/quick_frontend/quick_contact_list.py
+++ b/libervia/frontends/quick_frontend/quick_contact_list.py
@@ -17,7 +17,7 @@
# along with this program. If not, see .
"""Contact List handling multi profiles at once,
- should replace quick_contact_list module in the future"""
+should replace quick_contact_list module in the future"""
from libervia.backend.core.i18n import _
from libervia.backend.core.log import getLogger
diff --git a/libervia/frontends/tools/xmltools.py b/libervia/frontends/tools/xmltools.py
index ba6779f1..6b3816db 100644
--- a/libervia/frontends/tools/xmltools.py
+++ b/libervia/frontends/tools/xmltools.py
@@ -17,7 +17,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-"""This library help manage XML used in SàT frontends """
+"""This library help manage XML used in SàT frontends"""
# we don't import minidom as a different class can be used in frontends
# (e.g. NativeDOM in Libervia)
diff --git a/stubs/twisted/words/protocols/jabber/error.pyi b/stubs/twisted/words/protocols/jabber/error.pyi
index f9d17790..1dc57ff1 100644
--- a/stubs/twisted/words/protocols/jabber/error.pyi
+++ b/stubs/twisted/words/protocols/jabber/error.pyi
@@ -2,7 +2,6 @@ from typing import Optional
from twisted.words.xish import domish
-
class BaseError(Exception):
namespace: str
condition: str
@@ -10,5 +9,4 @@ class BaseError(Exception):
textLang: Optional[str]
appCondition: Optional[domish.Element]
-class StanzaError(BaseError):
- ...
+class StanzaError(BaseError): ...
diff --git a/stubs/twisted/words/protocols/jabber/jid.pyi b/stubs/twisted/words/protocols/jabber/jid.pyi
index 7363a5ad..51ad9af8 100644
--- a/stubs/twisted/words/protocols/jabber/jid.pyi
+++ b/stubs/twisted/words/protocols/jabber/jid.pyi
@@ -1,11 +1,9 @@
from typing import Tuple, overload
-
User = str
Host = str
Resource = str
-
# Note: these typings are incomplete and evolve as needed.
class JID:
user: User
@@ -13,18 +11,9 @@ class JID:
resource: Resource
@overload
- def __init__(self, str: str, tuple: None = None) -> None:
- ...
-
+ def __init__(self, str: str, tuple: None = None) -> None: ...
@overload
- def __init__(self, str: None, tuple: Tuple[User, Host, Resource]) -> None:
- ...
-
- def userhost(self) -> str:
- ...
-
- def userhostJID(self) -> "JID":
- ...
-
- def full(self) -> str:
- ...
+ def __init__(self, str: None, tuple: Tuple[User, Host, Resource]) -> None: ...
+ def userhost(self) -> str: ...
+ def userhostJID(self) -> "JID": ...
+ def full(self) -> str: ...
diff --git a/stubs/twisted/words/xish/domish.pyi b/stubs/twisted/words/xish/domish.pyi
index a55538ee..38dd7636 100644
--- a/stubs/twisted/words/xish/domish.pyi
+++ b/stubs/twisted/words/xish/domish.pyi
@@ -1,8 +1,15 @@
from typing import (
- Dict, Iterator, List, Literal, Optional, Tuple, TypeVar, Union, overload
+ Dict,
+ Iterator,
+ List,
+ Literal,
+ Optional,
+ Tuple,
+ TypeVar,
+ Union,
+ overload,
)
-
URI = str
Name = str
QName = Tuple[Optional[URI], Name]
@@ -10,10 +17,8 @@ AttributeKey = Union[QName, Name]
Attributes = Dict[AttributeKey, str]
Prefix = str
-
D = TypeVar("D")
-
# Note: these typings are incomplete and evolve as needed.
class Element:
uri: Optional[URI]
@@ -27,54 +32,31 @@ class Element:
qname: QName,
defaultUri: Optional[URI] = None,
attribs: Optional[Attributes] = None,
- localPrefixes: Optional[Dict[URI, Prefix]] = None
- ) -> None:
- ...
-
- def __getitem__(self, key: AttributeKey) -> str:
- ...
-
- def __setitem__(self, key: AttributeKey, value: str) -> None:
- ...
-
+ localPrefixes: Optional[Dict[URI, Prefix]] = None,
+ ) -> None: ...
+ def __getitem__(self, key: AttributeKey) -> str: ...
+ def __setitem__(self, key: AttributeKey, value: str) -> None: ...
@overload
def getAttribute(
- self,
- attribname: AttributeKey,
- default: None = None
- ) -> Union[str, None]:
- ...
-
+ self, attribname: AttributeKey, default: None = None
+ ) -> Union[str, None]: ...
@overload
- def getAttribute(self, attribname: AttributeKey, default: D) -> Union[str, D]:
- ...
-
- def addChild(self, node: "Element") -> "Element":
- ...
-
- def addContent(self, text: str) -> str:
- ...
-
+ def getAttribute(self, attribname: AttributeKey, default: D) -> Union[str, D]: ...
+ def addChild(self, node: "Element") -> "Element": ...
+ def addContent(self, text: str) -> str: ...
def addElement(
self,
name: Union[QName, Name],
defaultUri: Optional[URI] = None,
- content: Optional[str] = None
- ) -> "Element":
- ...
-
+ content: Optional[str] = None,
+ ) -> "Element": ...
def elements(
- self,
- uri: Optional[URI] = None,
- name: Optional[Name] = None
- ) -> Iterator["Element"]:
- ...
-
+ self, uri: Optional[URI] = None, name: Optional[Name] = None
+ ) -> Iterator["Element"]: ...
def toXml(
self,
prefixes: Optional[Dict[URI, Prefix]] = None,
closeElement: Literal[0, 1] = 1,
defaultUri: str = "",
- prefixesInScope: Optional[List[Prefix]] = None
- ) -> str:
- ...
+ prefixesInScope: Optional[List[Prefix]] = None,
+ ) -> str: ...
diff --git a/tests/unit/test_email_gateway.py b/tests/unit/test_email_gateway.py
index 7f045811..747dfa2b 100644
--- a/tests/unit/test_email_gateway.py
+++ b/tests/unit/test_email_gateway.py
@@ -42,6 +42,7 @@ from libervia.backend.plugins.plugin_comp_email_gateway.pubsub_service import (
)
from libervia.backend.plugins.plugin_xep_0131 import HeadersData, Urgency
+
@pytest.fixture
def email_gw(host):
email_gw = EmailGatewayComponent(host)
@@ -49,6 +50,7 @@ def email_gw(host):
email_gw.users_data = {}
return email_gw
+
class TestEmailGatewayComponent:
def test_jid_to_email_gateway_jid(self, email_gw):
@@ -284,12 +286,26 @@ class TestPubsubService:
request.sender = client.jid
request.nodeIdentifier = pubsub_resource._pfs.namespace
files = [
- {"id": "1", "name": "file1", "media_type": "application", "media_subtype":
- "octet-stream", "size": 123, "hash_algo": "sha-256", "file_hash": "0123456789abcdef",
- "created": 123},
- {"id": "2", "name": "file2", "media_type": "application", "media_subtype":
- "octet-stream", "size": 456, "hash_algo": "sha-256", "file_hash": "0123456789abcdef",
- "created": 123},
+ {
+ "id": "1",
+ "name": "file1",
+ "media_type": "application",
+ "media_subtype": "octet-stream",
+ "size": 123,
+ "hash_algo": "sha-256",
+ "file_hash": "0123456789abcdef",
+ "created": 123,
+ },
+ {
+ "id": "2",
+ "name": "file2",
+ "media_type": "application",
+ "media_subtype": "octet-stream",
+ "size": 456,
+ "hash_algo": "sha-256",
+ "file_hash": "0123456789abcdef",
+ "created": 123,
+ },
]
host.memory.get_files = AsyncMock(return_value=files)
result, _ = await pubsub_resource.items(request)
diff --git a/tests/unit/test_memory_sqla.py b/tests/unit/test_memory_sqla.py
index 4f48fee3..b6c0eb5b 100644
--- a/tests/unit/test_memory_sqla.py
+++ b/tests/unit/test_memory_sqla.py
@@ -51,14 +51,13 @@ class TestSQLA:
from_jid=None,
to_jid=None,
filters={"keyword": "test"},
- profile="test_profile"
+ profile="test_profile",
)
# We check that the SQL query is as expected.
executed_stmt = mock_session_instance.execute.call_args[0][0]
compiled = executed_stmt.compile(
- dialect=sqlite.dialect(),
- compile_kwargs={"literal_binds": True}
+ dialect=sqlite.dialect(), compile_kwargs={"literal_binds": True}
)
sql = str(compiled)
assert "json_each" in sql
diff --git a/tests/unit/test_plugin_xep_0215.py b/tests/unit/test_plugin_xep_0215.py
index 799a880e..5b9ff1b9 100644
--- a/tests/unit/test_plugin_xep_0215.py
+++ b/tests/unit/test_plugin_xep_0215.py
@@ -31,7 +31,6 @@ class TestXEP0215:
host.memory.disco.has_feature = AsyncMock()
host.memory.disco.has_feature.return_value = True
-
services_elt = xml_tools.parse(
"""
diff --git a/tests/unit/test_plugin_xep_0461.py b/tests/unit/test_plugin_xep_0461.py
index 69b44df4..c4701912 100644
--- a/tests/unit/test_plugin_xep_0461.py
+++ b/tests/unit/test_plugin_xep_0461.py
@@ -35,7 +35,9 @@ class TestXEP0461:
async def test_reply_to_from_element(self):
""" element parsing works."""
# Test correct case
- element = domish.Element((NS_REPLY, "reply"), attribs={"id": "123", "to": "user@example.com"})
+ element = domish.Element(
+ (NS_REPLY, "reply"), attribs={"id": "123", "to": "user@example.com"}
+ )
reply = ReplyTo.from_element(element)
assert reply.to == jid.JID("user@example.com")
assert reply.id == "123"
@@ -92,5 +94,7 @@ class TestXEP0461:
mess_data = MessageData(extra={"reply": {"id": "123", "internal_uid": False}})
pre_xml_treatments = MagicMock()
post_xml_treatments = MagicMock()
- xep._sendMessage_trigger(client, mess_data, pre_xml_treatments, post_xml_treatments)
+ xep._sendMessage_trigger(
+ client, mess_data, pre_xml_treatments, post_xml_treatments
+ )
assert post_xml_treatments.addCallback.called
diff --git a/twisted/plugins/libervia_backend_plugin.py b/twisted/plugins/libervia_backend_plugin.py
index c28d7517..571086a1 100644
--- a/twisted/plugins/libervia_backend_plugin.py
+++ b/twisted/plugins/libervia_backend_plugin.py
@@ -36,6 +36,7 @@ def initialise(options):
"""Method to initialise global modules"""
# XXX: We need to configure logs before any log method is used, so here is the best place.
from libervia.backend.core import log_config
+
log_config.libervia_configure(C.LOG_BACKEND_TWISTED, C, backend_data=options)
@@ -52,11 +53,13 @@ class LiberviaMaker:
def set_debugger(self):
from twisted.internet import defer
+
if defer.Deferred.debug:
# if we are in debug mode, we want to use ipdb instead of pdb
try:
import ipdb
import pdb
+
pdb.set_trace = ipdb.set_trace
pdb.post_mortem = ipdb.post_mortem
except ImportError:
@@ -64,12 +67,14 @@ class LiberviaMaker:
def makeService(self, options):
from twisted.internet import asyncioreactor
+
asyncioreactor.install()
self.set_debugger()
# XXX: Libervia must be imported after log configuration,
# because it write stuff to logs
initialise(options.parent)
from libervia.backend.core.main import LiberviaBackend
+
return LiberviaBackend()