slidge 0.3.2__py3-none-any.whl → 0.3.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
slidge/command/user.py CHANGED
@@ -6,7 +6,7 @@ from slixmpp import JID
6
6
  from slixmpp.exceptions import XMPPError
7
7
 
8
8
  from ..group.room import LegacyMUC
9
- from ..util.types import AnyBaseSession, LegacyGroupIdType, UserPreferences
9
+ from ..util.types import AnyBaseSession, LegacyGroupIdType, MucType, UserPreferences
10
10
  from .base import (
11
11
  Command,
12
12
  CommandAccess,
@@ -157,7 +157,9 @@ class ListGroups(Command):
157
157
  async def run(self, session, _ifrom, *_):
158
158
  assert session is not None
159
159
  await session.ready
160
- groups = sorted(session.bookmarks, key=lambda g: g.DISCO_NAME.casefold())
160
+ groups = sorted(
161
+ session.bookmarks, key=lambda g: (g.name or g.jid.localpart).casefold()
162
+ )
161
163
  return TableResult(
162
164
  description="Your groups",
163
165
  fields=[FormField("name"), FormField("jid", type="jid-single")],
@@ -364,3 +366,21 @@ class LeaveGroup(Command):
364
366
  async def finish(session: AnyBaseSession, _ifrom, group: LegacyMUC) -> None:
365
367
  await session.on_leave_group(group.legacy_id)
366
368
  await session.bookmarks.remove(group, reason="You left this group via slidge.")
369
+
370
+
371
+ class InviteInGroups(Command):
372
+ NAME = "💌 Re-invite me in my groups"
373
+ HELP = "Ask the gateway to send invitations for all your private groups"
374
+ CHAT_COMMAND = "re-invite"
375
+ NODE = GROUPS.node + "/" + CHAT_COMMAND
376
+ ACCESS = CommandAccess.USER_LOGGED
377
+ CATEGORY = GROUPS
378
+
379
+ async def run(self, session, _ifrom, *_):
380
+ assert session is not None
381
+ await session.ready
382
+ for muc in session.bookmarks:
383
+ if muc.type == MucType.GROUP:
384
+ session.send_gateway_invite(
385
+ muc, reason="You asked to be re-invited in all groups."
386
+ )
slidge/contact/contact.py CHANGED
@@ -120,8 +120,7 @@ class LegacyContact(
120
120
  def is_friend(self, value: bool) -> None:
121
121
  if value == self.is_friend:
122
122
  return
123
- self.stored.is_friend = value
124
- self.commit()
123
+ self.update_stored_attribute(is_friend=value)
125
124
 
126
125
  @property
127
126
  def added_to_roster(self) -> bool:
@@ -131,8 +130,7 @@ class LegacyContact(
131
130
  def added_to_roster(self, value: bool) -> None:
132
131
  if value == self.added_to_roster:
133
132
  return
134
- self.stored.added_to_roster = value
135
- self.commit()
133
+ self.update_stored_attribute(added_to_roster=value)
136
134
 
137
135
  @property
138
136
  def participants(self) -> Iterator["LegacyParticipant"]:
@@ -170,8 +168,7 @@ class LegacyContact(
170
168
  def client_type(self, value: ClientType) -> None:
171
169
  if self.stored.client_type == value:
172
170
  return
173
- self.stored.client_type = value
174
- self.commit()
171
+ self.update_stored_attribute(client_type=value)
175
172
 
176
173
  def _set_logger(self) -> None:
177
174
  self.log = logging.getLogger(f"{self.user_jid.bare}:contact:{self}")
@@ -290,13 +287,12 @@ class LegacyContact(
290
287
  def name(self, n: Optional[str]) -> None:
291
288
  if self.stored.nick == n:
292
289
  return
293
- self.stored.nick = n
290
+ self.update_stored_attribute(nick=n)
294
291
  self._set_logger()
295
292
  if self.is_friend and self.added_to_roster:
296
293
  self.xmpp.pubsub.broadcast_nick(
297
294
  user_jid=self.user_jid, jid=self.jid.bare, nick=n
298
295
  )
299
- self.commit()
300
296
  for p in self.participants:
301
297
  p.nickname = n or str(self.legacy_id)
302
298
 
@@ -361,14 +357,11 @@ class LegacyContact(
361
357
  if pronouns:
362
358
  vcard["pronouns"]["text"] = pronouns
363
359
 
364
- self.stored.vcard = str(vcard)
365
- self.stored.vcard_fetched = True
360
+ self.update_stored_attribute(vcard=str(vcard), vcard_fetched=True)
366
361
  self.session.create_task(
367
362
  self.xmpp.pubsub.broadcast_vcard_event(self.jid, self.user_jid, vcard)
368
363
  )
369
364
 
370
- self.commit()
371
-
372
365
  def get_roster_item(self):
373
366
  item = {
374
367
  "subscription": self.__get_subscription_string(),
@@ -57,8 +57,7 @@ class CapsMixin(DispatcherMixin):
57
57
  ver = contact.stored.caps_ver
58
58
  else:
59
59
  ver = await contact.get_caps_ver(pfrom)
60
- contact.stored.caps_ver = ver
61
- contact.commit()
60
+ contact.update_stored_attribute(caps_ver=ver)
62
61
  else:
63
62
  ver = await caps.get_verstring(pfrom)
64
63
 
slidge/core/mixins/db.py CHANGED
@@ -2,6 +2,8 @@ import logging
2
2
  import typing
3
3
  from contextlib import contextmanager
4
4
 
5
+ import sqlalchemy as sa
6
+
5
7
  from ...db.models import Base, Contact, Room
6
8
 
7
9
  if typing.TYPE_CHECKING:
@@ -86,3 +88,16 @@ class UpdateInfoMixin(DBMixin):
86
88
  else:
87
89
  self.stored.extra_attributes = self.serialize_extra_attributes()
88
90
  super().commit(merge=merge)
91
+
92
+ def update_stored_attribute(self, **kwargs) -> None:
93
+ for key, value in kwargs.items():
94
+ setattr(self.stored, key, value)
95
+ if self._updating_info:
96
+ return
97
+ with self.xmpp.store.session() as orm:
98
+ orm.execute(
99
+ sa.update(self.stored.__class__)
100
+ .where(self.stored.__class__.id == self.stored.id)
101
+ .values(**kwargs)
102
+ )
103
+ orm.commit()
@@ -96,22 +96,14 @@ class PresenceMixin(BaseSender, DBMixin):
96
96
  )
97
97
 
98
98
  def _store_last_presence(self, new: CachedPresence) -> None:
99
- stored_contact = self.__stored()
100
- if stored_contact is None:
101
- return
102
- stored_contact.cached_presence = True
103
- for k, v in new._asdict().items():
104
- setattr(stored_contact, k, v)
105
- if self.__is_contact() and self._updating_info:
99
+ if self.__is_contact():
100
+ contact = self
101
+ elif (contact := getattr(self, "contact", None)) is None: # type:ignore[assignment]
106
102
  return
107
- with self.xmpp.store.session(expire_on_commit=False) as orm:
108
- try:
109
- orm.add(stored_contact)
110
- except InvalidRequestError:
111
- stored_contact = orm.merge(stored_contact)
112
- orm.add(stored_contact)
113
-
114
- orm.commit()
103
+ contact.update_stored_attribute( # type:ignore[attr-defined]
104
+ cached_presence=True,
105
+ **new._asdict(),
106
+ )
115
107
 
116
108
  def _make_presence(
117
109
  self,
slidge/db/models.py CHANGED
@@ -9,7 +9,7 @@ from slixmpp.types import MucAffiliation, MucRole
9
9
  from sqlalchemy import JSON, ForeignKey, Index, UniqueConstraint
10
10
  from sqlalchemy.orm import Mapped, mapped_column, relationship
11
11
 
12
- from ..util.types import ClientType, MucType
12
+ from ..util.types import ClientType, Hat, MucType
13
13
  from .meta import Base, JSONSerializable, JSONSerializableTypes
14
14
 
15
15
 
@@ -344,7 +344,7 @@ class Participant(Base):
344
344
  nickname: Mapped[str] = mapped_column(nullable=False, default=None)
345
345
  nickname_no_illegal: Mapped[str] = mapped_column(nullable=False, default=None)
346
346
 
347
- hats: Mapped[list[tuple[str, str]]] = mapped_column(JSON, default=list)
347
+ hats: Mapped[list[Hat]] = mapped_column(JSON, default=list)
348
348
 
349
349
  extra_attributes: Mapped[Optional[JSONSerializable]] = mapped_column(default=None)
350
350
 
slidge/group/room.py CHANGED
@@ -169,8 +169,7 @@ class LegacyMUC(
169
169
  def type(self, type_: MucType) -> None:
170
170
  if self.type == type_:
171
171
  return
172
- self.stored.muc_type = type_
173
- self.commit()
172
+ self.update_stored_attribute(muc_type=type_)
174
173
 
175
174
  @property
176
175
  def n_participants(self):
@@ -180,8 +179,7 @@ class LegacyMUC(
180
179
  def n_participants(self, n_participants: Optional[int]) -> None:
181
180
  if self.stored.n_participants == n_participants:
182
181
  return
183
- self.stored.n_participants = n_participants
184
- self.commit()
182
+ self.update_stored_attribute(n_participants=n_participants)
185
183
 
186
184
  @property
187
185
  def user_jid(self):
@@ -203,8 +201,7 @@ class LegacyMUC(
203
201
  def subject_date(self, when: Optional[datetime]) -> None:
204
202
  if self.subject_date == when:
205
203
  return
206
- self.stored.subject_date = when
207
- self.commit()
204
+ self.update_stored_attribute(subject_date=when)
208
205
 
209
206
  def __send_configuration_change(self, codes) -> None:
210
207
  part = self.get_system_participant()
@@ -222,18 +219,16 @@ class LegacyMUC(
222
219
  def user_nick(self, nick: str) -> None:
223
220
  if nick == self.user_nick:
224
221
  return
225
- self.stored.user_nick = nick
226
- self.commit()
222
+ self.update_stored_attribute(user_nick=nick)
227
223
 
228
224
  def add_user_resource(self, resource: str) -> None:
229
225
  stored_set = self.get_user_resources()
230
226
  if resource in stored_set:
231
227
  return
232
228
  stored_set.add(resource)
233
- self.stored.user_resources = (
234
- json.dumps(list(stored_set)) if stored_set else None
229
+ self.update_stored_attribute(
230
+ user_resources=(json.dumps(list(stored_set)) if stored_set else None)
235
231
  )
236
- self.commit()
237
232
 
238
233
  def get_user_resources(self) -> set[str]:
239
234
  stored_str = self.stored.user_resources
@@ -246,10 +241,9 @@ class LegacyMUC(
246
241
  if resource not in stored_set:
247
242
  return
248
243
  stored_set.remove(resource)
249
- self.stored.user_resources = (
250
- json.dumps(list(stored_set)) if stored_set else None
244
+ self.update_stored_attribute(
245
+ user_resources=(json.dumps(list(stored_set)) if stored_set else None)
251
246
  )
252
- self.commit()
253
247
 
254
248
  @asynccontextmanager
255
249
  async def lock(self, id_: str) -> AsyncIterator[None]:
@@ -346,8 +340,7 @@ class LegacyMUC(
346
340
  def name(self, n: str | None) -> None:
347
341
  if self.name == n:
348
342
  return
349
- self.stored.name = n
350
- self.commit()
343
+ self.update_stored_attribute(name=n)
351
344
  self._set_logger()
352
345
  self.__send_configuration_change((104,))
353
346
 
@@ -359,8 +352,7 @@ class LegacyMUC(
359
352
  def description(self, d: str) -> None:
360
353
  if self.description == d:
361
354
  return
362
- self.stored.description = d
363
- self.commit()
355
+ self.update_stored_attribute(description=d)
364
356
  self.__send_configuration_change((104,))
365
357
 
366
358
  def on_presence_unavailable(self, p: Presence) -> None:
@@ -440,8 +432,7 @@ class LegacyMUC(
440
432
  if s == self.subject:
441
433
  return
442
434
 
443
- self.stored.subject = s
444
- self.commit()
435
+ self.update_stored_attribute(subject=s)
445
436
  self.__get_subject_setter_participant().set_room_subject(
446
437
  s, None, self.subject_date, False
447
438
  )
@@ -464,8 +455,7 @@ class LegacyMUC(
464
455
  if subject_setter == self.subject_setter:
465
456
  return
466
457
  assert isinstance(subject_setter, str | None)
467
- self.stored.subject_setter = subject_setter
468
- self.commit()
458
+ self.update_stored_attribute(subject_setter=subject_setter)
469
459
 
470
460
  def __get_subject_setter_participant(self) -> LegacyParticipant:
471
461
  if self.subject_setter is None:
slidge/util/types.py CHANGED
@@ -178,6 +178,8 @@ class Mention(NamedTuple):
178
178
  class Hat(NamedTuple):
179
179
  uri: str
180
180
  title: str
181
+ hue: float = 0.0 # Default value is not great here, but an OK workaround for the
182
+ # slixmpp 1.11→1.12 API update
181
183
 
182
184
 
183
185
  class UserPreferences(TypedDict):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: slidge
3
- Version: 0.3.2
3
+ Version: 0.3.3
4
4
  Summary: XMPP bridging framework
5
5
  Author-email: Nicolas Cedilnik <nicoco@nicoco.fr>
6
6
  License-Expression: AGPL-3.0-or-later
@@ -10,9 +10,9 @@ slidge/command/base.py,sha256=h6lQ6ypb5uNrppZ_N8mS7ObJpnOINYZS6QokGlWVgAk,13527
10
10
  slidge/command/categories.py,sha256=vF0KGDV9sEn8TNkcMoDRw-u3gEyNHSXghOU2JRHQtKs,351
11
11
  slidge/command/chat_command.py,sha256=r_qalygOCsEoS-OgWw8IIlAzTufhXNjduONbeoepUIA,11557
12
12
  slidge/command/register.py,sha256=BduDI31Kx8CbWWEdjybimTA5Wcfhn-Jkt8sSPsySCpo,6724
13
- slidge/command/user.py,sha256=xt7NTb8Fdj_Mx91BgiszSii6QF67LtsyowQ1vhBJSIU,12660
13
+ slidge/command/user.py,sha256=3aJ60bvXGyCqjgBH1r6HPbBh4IwgH40rHBilTkeFiv4,13325
14
14
  slidge/contact/__init__.py,sha256=WMMaHk7UW7YT9EH2LtPdkU0bHQaOp4ikBhbBQskmoc8,191
15
- slidge/contact/contact.py,sha256=ASNjGj-fxueC7rReMw4qMDUQxJ58W1F8i4Ipu_wfsTE,19617
15
+ slidge/contact/contact.py,sha256=pexE6DU1WsxUoTeF-nENuEqOi7quYQtQot1hD816cl8,19565
16
16
  slidge/contact/roster.py,sha256=ZbhPC_5opMXdKrdCaQZiHTErxQD4EyWn5Susl6W7M6k,10003
17
17
  slidge/core/__init__.py,sha256=RG7Jj5JCJERjhqJ31lOLYV-7bH_oblClQD1KF9LsTXo,68
18
18
  slidge/core/config.py,sha256=yFD1RGBZ6Xl115oMqDiF7DFkShlNjF9HEB56Eb_BR_E,7664
@@ -20,7 +20,7 @@ slidge/core/gateway.py,sha256=G_ZX8ibKFe-oEXXOY-eRVkZjqRb_VdadIhTezwZEUCA,41698
20
20
  slidge/core/pubsub.py,sha256=2Em3PvYz-PX-WM7ZqkEU9estNYCyQ--JdJq22DhrUlA,12145
21
21
  slidge/core/session.py,sha256=XJRZrtAmwqqjaqkLEUPK8xUBxdJrKeraubYYNiiuT7I,29897
22
22
  slidge/core/dispatcher/__init__.py,sha256=1EXcjXietUKlxEqdrCWCV3xZ3q_DSsjHoqWrPMbtYao,84
23
- slidge/core/dispatcher/caps.py,sha256=gISaHtFwFDXtkSrSsAkZfPiHQyXfmXg3v_YYU0w9iDg,2254
23
+ slidge/core/dispatcher/caps.py,sha256=7gvJLeushBtiyqCzBapzbwallH7l3tVN9PYe8MXiKIo,2237
24
24
  slidge/core/dispatcher/disco.py,sha256=xVPyBFnnkON-JjjM1oydRa-dqnDbwAZER2MGQACRhVk,2309
25
25
  slidge/core/dispatcher/presence.py,sha256=MkSOY7uZQnujTwhIU_nVxygTul63VBaPjTT3X4iTMu4,7090
26
26
  slidge/core/dispatcher/registration.py,sha256=R4bsyiR8elbLKiFMYv2E54VAUg6qTo-_2CzdbCOZjrY,3419
@@ -42,17 +42,17 @@ slidge/core/mixins/__init__.py,sha256=Zea39CCwjJU5XfHwcYPEZ9Sin8z1BZxoV68G2RwC3n
42
42
  slidge/core/mixins/attachment.py,sha256=k-4nwteql4TmhsZDLqPVgzVyuaRQzk-JEOG-k7w-VxM,23938
43
43
  slidge/core/mixins/avatar.py,sha256=0E0mQxdTUcJQrYXlBkYqkNl4bYuga4cIC1s4XA2rED8,5559
44
44
  slidge/core/mixins/base.py,sha256=getXMptzJwIc4fEbeMoJCSKcC3awi8UbKnx5FVCthjc,783
45
- slidge/core/mixins/db.py,sha256=lryMfRB-1-St2f7TZqW4sCl4xrWPWNlwgvn37T8wQPE,2678
45
+ slidge/core/mixins/db.py,sha256=MlaTJcZjOZAL77oise0kY12tvx-SzPLcxS29QxxwEMM,3160
46
46
  slidge/core/mixins/disco.py,sha256=mrYhWO9qpnLMAVtKKqwbDh6CNOH2dPNERpyfmWzZGg8,3684
47
47
  slidge/core/mixins/message.py,sha256=xk4bgiJF9ATe-rgtH4sHU8hUwecBF4KjGIujm90mbXQ,8014
48
48
  slidge/core/mixins/message_maker.py,sha256=jdY0dhpN_RcKwajI0XrV194ruNW120Gfdq333B1Fv1o,6556
49
49
  slidge/core/mixins/message_text.py,sha256=Unzmwr8TnPC2uuZ2fFiIalOGpQF7YYyT1AbB8i0l6Qc,9637
50
- slidge/core/mixins/presence.py,sha256=hNttLzQ83q6jTQumG-ATpTj85DiUpF50FebYQV_Nazg,10530
50
+ slidge/core/mixins/presence.py,sha256=SiKd-RUIHybrxs5Ie6Ig3aunQ7Is9t6c7TOm-2HbjbA,10252
51
51
  slidge/core/mixins/recipient.py,sha256=b0uFnpym-hOFgYxGjXT1xQcZ4YRbDSBftPcNWLzSwEI,1336
52
52
  slidge/db/__init__.py,sha256=EBDH1JSEhgqYcli2Bw11CRC749wJk8AOucgBzmhDSvU,105
53
53
  slidge/db/avatar.py,sha256=MXFd1oe0eL5CCUYbc5CpsIcbio3cY3xVoKt39RAoj9I,8240
54
54
  slidge/db/meta.py,sha256=NtjGWcqPfG7uPfwR_cC6_23zyo8ftqgKX8CbP9IBq6U,2185
55
- slidge/db/models.py,sha256=HMSiNY0j-sm0VsikkVED1swPhX687613uW7NEHB8UTs,12826
55
+ slidge/db/models.py,sha256=n_Xmgtfug-ygE2CL0ezvEgeyaSM6dgn7YfaYm78B_7c,12819
56
56
  slidge/db/store.py,sha256=yhvYgoXpbueprjVUXBmA25wFyEbzDXMxVzqv8aZi5tw,20308
57
57
  slidge/db/alembic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
58
  slidge/db/alembic/env.py,sha256=hsBlRNs0zF5diSHGRSa8Fi3qRVQDA2rJdR41AEIdvxc,1642
@@ -62,7 +62,7 @@ slidge/group/__init__.py,sha256=yFt7cHqeaKIMN6f9ZyhhspOcJJvBtLedGv-iICG7lto,258
62
62
  slidge/group/archive.py,sha256=gNHpGlUstPtBcnBgOarSYzkZHo9E8bNxl_ZY3wM6wHg,6108
63
63
  slidge/group/bookmarks.py,sha256=eiXtlgirE59dBi1BT1349wCrGuHDkCoak1phCepzkqI,7653
64
64
  slidge/group/participant.py,sha256=2yDJL2bL0w-EiWjq6V96UEhXUgmih5-GpKsoKfG2zdY,18734
65
- slidge/group/room.py,sha256=QXNEbJBY5gbSpVbr1-u-M2YOoIU1qGhWM7SvtdyiETs,49583
65
+ slidge/group/room.py,sha256=03c6WrSptld6SqA_ndxPJOU9Cz7s0Qq-R8PvXdi-r3A,49523
66
66
  slidge/slixfix/__init__.py,sha256=LvaYZQYjr4l_45AYYpod1dB3MUaZye18vKF-4H8Bm20,4758
67
67
  slidge/slixfix/delivery_receipt.py,sha256=JmogxsiXYEbTmCM4fvC5wkQs0jBsaJtKl4j_B_18riE,1415
68
68
  slidge/slixfix/roster.py,sha256=DjjHQqCsKsPChUxV7S0Pm4IAgjfrwgm5tcTdJi3N_gY,1670
@@ -85,11 +85,11 @@ slidge/util/conf.py,sha256=Wv-xr1fQfz6jDCBpj2e5Nm-igMpdIjsYsVfoY8grJoo,7380
85
85
  slidge/util/jid_escaping.py,sha256=QJ2Yj_j1gTmiO9g2r187iVCu7kia_O5ABhRiLAO2TG4,1073
86
86
  slidge/util/lock.py,sha256=ZnUi3LGiz271-YeYKo9JzxovJCoSwlP9P65pNyHIO9o,1029
87
87
  slidge/util/test.py,sha256=o86wX1ksnvAgN47k5facDPc4zgiK7J5oWyThgJsv_vQ,13986
88
- slidge/util/types.py,sha256=nilphTeJU3yb0MSqb86tZeWXis495oDvHSDDBs0hn_4,5747
88
+ slidge/util/types.py,sha256=BA1vhByeaeni3Z5FTIVYafORpU44OOJOTMByL-QqfLs,5870
89
89
  slidge/util/util.py,sha256=g6jFu5xgAtRA9FBCIBJT3079t_bQKZYOUvi9L5pTbbk,9595
90
- slidge-0.3.2.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
91
- slidge-0.3.2.dist-info/METADATA,sha256=Ptqr6X39gL1nyceti9rOscoPzsVcCBb8u93QsqRV6zU,5054
92
- slidge-0.3.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
93
- slidge-0.3.2.dist-info/entry_points.txt,sha256=py3_x834fFJ2TEzPd18Wt2DnysdAfuVqJ5zzBrXbAZs,44
94
- slidge-0.3.2.dist-info/top_level.txt,sha256=2LRjDYHaGZ5ieCMF8xy58JIiabRMzX-MGMbCZwfE17c,7
95
- slidge-0.3.2.dist-info/RECORD,,
90
+ slidge-0.3.3.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
91
+ slidge-0.3.3.dist-info/METADATA,sha256=Q_WFVFDDTzOc3M9AuY_eRg5zpclCTxaNzqeP0Rp7gRU,5054
92
+ slidge-0.3.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
93
+ slidge-0.3.3.dist-info/entry_points.txt,sha256=py3_x834fFJ2TEzPd18Wt2DnysdAfuVqJ5zzBrXbAZs,44
94
+ slidge-0.3.3.dist-info/top_level.txt,sha256=2LRjDYHaGZ5ieCMF8xy58JIiabRMzX-MGMbCZwfE17c,7
95
+ slidge-0.3.3.dist-info/RECORD,,
File without changes