liblore 0.8.1__tar.gz → 0.8.2__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: liblore
3
- Version: 0.8.1
3
+ Version: 0.8.2
4
4
  Summary: Shared library for public-inbox / lore.kernel.org access
5
5
  Author-email: Konstantin Ryabitsev <konstantin@linuxfoundation.org>
6
6
  License-Expression: GPL-2.0-or-later
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
5
5
 
6
6
  [project]
7
7
  name = "liblore"
8
- version = "0.8.1"
8
+ version = "0.8.2"
9
9
  description = "Shared library for public-inbox / lore.kernel.org access"
10
10
  readme = "README.md"
11
11
  requires-python = ">=3.9"
@@ -6,7 +6,7 @@ import email.charset
6
6
  import email.policy
7
7
  from email.message import EmailMessage
8
8
 
9
- __version__ = '0.8.1'
9
+ __version__ = '0.8.2'
10
10
 
11
11
  # Email policy used for parsing and serialising messages
12
12
  emlpolicy = email.policy.EmailPolicy(
@@ -394,6 +394,13 @@ def get_strict_thread(
394
394
  for hval in msg.get_all(hdr_name, []):
395
395
  raw_refs += re.findall(r'<([^>]+)>', str(hval))
396
396
 
397
+ # Some tooling emits messages that reference their own Message-ID.
398
+ # A self-reference is never meaningful for threading, so drop it
399
+ # before it can be mistaken for a parent.
400
+ if c_msgid in raw_refs:
401
+ logger.debug('Ignoring self-reference in %s', c_msgid)
402
+ raw_refs = [ref for ref in raw_refs if ref != c_msgid]
403
+
397
404
  # If noparent, pretend our target message has no references
398
405
  if noparent and msgid == c_msgid:
399
406
  logger.info('Breaking thread to remove parents of %s', msgid)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: liblore
3
- Version: 0.8.1
3
+ Version: 0.8.2
4
4
  Summary: Shared library for public-inbox / lore.kernel.org access
5
5
  Author-email: Konstantin Ryabitsev <konstantin@linuxfoundation.org>
6
6
  License-Expression: GPL-2.0-or-later
@@ -47,6 +47,57 @@ class TestGetStrictThread:
47
47
  assert 'child@x.com' in ids
48
48
  assert 'grandchild@x.com' in ids
49
49
 
50
+ def test_noparent_self_referencing_cover(self, make_msg: MsgFactory) -> None:
51
+ # Some tooling emits a cover letter whose In-Reply-To/References point
52
+ # at its own Message-ID. Breaking the thread there must not treat the
53
+ # cover's own msgid as a reference to ignore, or every patch that
54
+ # legitimately replies to the cover gets dropped.
55
+ cover = make_msg(
56
+ msgid='cover@x.com',
57
+ subject='[PATCH 0/2] Something',
58
+ in_reply_to='cover@x.com',
59
+ references=['cover@x.com'],
60
+ )
61
+ patch1 = make_msg(
62
+ msgid='p1@x.com',
63
+ subject='[PATCH 1/2] First',
64
+ in_reply_to='cover@x.com',
65
+ references=['cover@x.com'],
66
+ )
67
+ patch2 = make_msg(
68
+ msgid='p2@x.com',
69
+ subject='[PATCH 2/2] Second',
70
+ in_reply_to='cover@x.com',
71
+ references=['cover@x.com'],
72
+ )
73
+ review = make_msg(
74
+ msgid='review@x.com',
75
+ subject='Re: [PATCH 2/2] Second',
76
+ in_reply_to='p2@x.com',
77
+ references=['cover@x.com', 'p2@x.com'],
78
+ )
79
+ want = {'cover@x.com', 'p1@x.com', 'p2@x.com', 'review@x.com'}
80
+ # Cover first in the list is the worst case: without the fix only the
81
+ # cover survives. Ordering must not matter, so check both.
82
+ for msgs in ([cover, patch1, patch2, review], [patch1, cover, patch2, review]):
83
+ result = get_strict_thread(msgs, 'cover@x.com', noparent=True)
84
+ assert result is not None
85
+ assert {get_clean_msgid(m) for m in result} == want
86
+
87
+ def test_self_reference_is_not_a_parent(self, make_msg: MsgFactory) -> None:
88
+ # A self-referencing message must not be treated as a reply to itself,
89
+ # even without noparent: it is a thread root, and starting the walk at
90
+ # its child still has to pull it in.
91
+ root = make_msg(
92
+ msgid='root@x.com',
93
+ in_reply_to='root@x.com',
94
+ references=['root@x.com'],
95
+ )
96
+ reply = make_msg(msgid='reply@x.com', in_reply_to='root@x.com')
97
+ result = get_strict_thread([root, reply], 'reply@x.com')
98
+ assert result is not None
99
+ assert {get_clean_msgid(m) for m in result} == {'root@x.com', 'reply@x.com'}
100
+
50
101
  def test_references_chain(self, make_msg: MsgFactory) -> None:
51
102
  msg1 = make_msg(msgid='a@x.com')
52
103
  msg2 = make_msg(msgid='b@x.com', references=['a@x.com'])
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes