Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit38035fe

Browse files
gildeagpshead
andauthored
gh-90890: New methods to access mailbox.Maildir message info and flags (#103905)
New methods to access mailbox.Maildir message info and flags:get_info, set_info, get_flags, set_flags, add_flag, remove_flag.These methods speed up accessing a message's info and/or flags and areuseful when it is not necessary to access the message's contents,as when iterating over a Maildir to find messages with specific flags.---------* Add more str type checking* modernize to f-strings instead of %Co-authored-by: Gregory P. Smith <greg@krypto.org>
1 parentfa84e5f commit38035fe

File tree

5 files changed

+247
-1
lines changed

5 files changed

+247
-1
lines changed

‎Doc/library/mailbox.rst‎

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,108 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF.
424424
remove the underlying message while the returned file remains open.
425425

426426

427+
..method::get_flags(key)
428+
429+
Return as a string the flags that are set on the message
430+
corresponding to *key*.
431+
This is the same as ``get_message(key).get_flags()`` but much
432+
faster, because it does not open the message file.
433+
Use this method when iterating over the keys to determine which
434+
messages are interesting to get.
435+
436+
If you do have a:class:`MaildirMessage` object, use
437+
its:meth:`~MaildirMessage.get_flags` method instead, because
438+
changes made by the message's:meth:`~MaildirMessage.set_flags`,
439+
:meth:`~MaildirMessage.add_flag` and:meth:`~MaildirMessage.remove_flag`
440+
methods are not reflected here until the mailbox's
441+
:meth:`__setitem__` method is called.
442+
443+
..versionadded::3.13
444+
445+
446+
..method::set_flags(key, flags)
447+
448+
On the message corresponding to *key*, set the flags specified
449+
by *flags* and unset all others.
450+
Calling ``some_mailbox.set_flags(key, flags)`` is similar to ::
451+
452+
one_message = some_mailbox.get_message(key)
453+
one_message.set_flags(flags)
454+
some_mailbox[key] = one_message
455+
456+
but faster, because it does not open the message file.
457+
458+
If you do have a:class:`MaildirMessage` object, use
459+
its:meth:`~MaildirMessage.set_flags` method instead, because
460+
changes made with this mailbox method will not be visible to the
461+
message object's method,:meth:`~MaildirMessage.get_flags`.
462+
463+
..versionadded::3.13
464+
465+
466+
..method::add_flag(key, flag)
467+
468+
On the message corresponding to *key*, set the flags specified
469+
by *flag* without changing other flags. To add more than one
470+
flag at a time, *flag* may be a string of more than one character.
471+
472+
Considerations for using this method versus the message object's
473+
:meth:`~MaildirMessage.add_flag` method are similar to
474+
those for:meth:`set_flags`; see the discussion there.
475+
476+
..versionadded::3.13
477+
478+
479+
..method::remove_flag(key, flag)
480+
481+
On the message corresponding to *key*, unset the flags specified
482+
by *flag* without changing other flags. To remove more than one
483+
flag at a time, *flag* may be a string of more than one character.
484+
485+
Considerations for using this method versus the message object's
486+
:meth:`~MaildirMessage.remove_flag` method are similar to
487+
those for:meth:`set_flags`; see the discussion there.
488+
489+
..versionadded::3.13
490+
491+
492+
..method::get_info(key)
493+
494+
Return a string containing the info for the message
495+
corresponding to *key*.
496+
This is the same as ``get_message(key).get_info()`` but much
497+
faster, because it does not open the message file.
498+
Use this method when iterating over the keys to determine which
499+
messages are interesting to get.
500+
501+
If you do have a:class:`MaildirMessage` object, use
502+
its:meth:`~MaildirMessage.get_info` method instead, because
503+
changes made by the message's:meth:`~MaildirMessage.set_info` method
504+
are not reflected here until the mailbox's:meth:`__setitem__` method
505+
is called.
506+
507+
..versionadded::3.13
508+
509+
510+
..method::set_info(key, info)
511+
512+
Set the info of the message corresponding to *key* to *info*.
513+
Calling ``some_mailbox.set_info(key, flags)`` is similar to ::
514+
515+
one_message = some_mailbox.get_message(key)
516+
one_message.set_info(info)
517+
some_mailbox[key] = one_message
518+
519+
but faster, because it does not open the message file.
520+
521+
If you do have a:class:`MaildirMessage` object, use
522+
its:meth:`~MaildirMessage.set_info` method instead, because
523+
changes made with this mailbox method will not be visible to the
524+
message object's method,:meth:`~MaildirMessage.get_info`.
525+
526+
..versionadded::3.13
527+
528+
427529
..seealso::
428530

429531
`maildir man page from Courier<https://www.courier-mta.org/maildir.html>`_
@@ -838,7 +940,7 @@ Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF.
838940
..note::
839941

840942
A message is typically moved from:file:`new` to:file:`cur` after its
841-
mailbox has been accessed, whether or not the messageishas been
943+
mailbox has been accessed, whether or not the message has been
842944
read. A message ``msg`` has been read if ``"S" in msg.get_flags()`` is
843945
``True``.
844946

‎Lib/mailbox.py‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,56 @@ def get_file(self, key):
395395
f=open(os.path.join(self._path,self._lookup(key)),'rb')
396396
return_ProxyFile(f)
397397

398+
defget_info(self,key):
399+
"""Get the keyed message's "info" as a string."""
400+
subpath=self._lookup(key)
401+
ifself.coloninsubpath:
402+
returnsubpath.split(self.colon)[-1]
403+
return''
404+
405+
defset_info(self,key,info:str):
406+
"""Set the keyed message's "info" string."""
407+
ifnotisinstance(info,str):
408+
raiseTypeError(f'info must be a string:{type(info)}')
409+
old_subpath=self._lookup(key)
410+
new_subpath=old_subpath.split(self.colon)[0]
411+
ifinfo:
412+
new_subpath+=self.colon+info
413+
ifnew_subpath==old_subpath:
414+
return
415+
old_path=os.path.join(self._path,old_subpath)
416+
new_path=os.path.join(self._path,new_subpath)
417+
os.rename(old_path,new_path)
418+
self._toc[key]=new_subpath
419+
420+
defget_flags(self,key):
421+
"""Return as a string the standard flags that are set on the keyed message."""
422+
info=self.get_info(key)
423+
ifinfo.startswith('2,'):
424+
returninfo[2:]
425+
return''
426+
427+
defset_flags(self,key,flags:str):
428+
"""Set the given flags and unset all others on the keyed message."""
429+
ifnotisinstance(flags,str):
430+
raiseTypeError(f'flags must be a string:{type(flags)}')
431+
# TODO: check if flags are valid standard flag characters?
432+
self.set_info(key,'2,'+''.join(sorted(set(flags))))
433+
434+
defadd_flag(self,key,flag:str):
435+
"""Set the given flag(s) without changing others on the keyed message."""
436+
ifnotisinstance(flag,str):
437+
raiseTypeError(f'flag must be a string:{type(flag)}')
438+
# TODO: check that flag is a valid standard flag character?
439+
self.set_flags(key,''.join(set(self.get_flags(key))|set(flag)))
440+
441+
defremove_flag(self,key,flag:str):
442+
"""Unset the given string flag(s) without changing others on the keyed message."""
443+
ifnotisinstance(flag,str):
444+
raiseTypeError(f'flag must be a string:{type(flag)}')
445+
ifself.get_flags(key):
446+
self.set_flags(key,''.join(set(self.get_flags(key))-set(flag)))
447+
398448
defiterkeys(self):
399449
"""Return an iterator over keys."""
400450
self._refresh()

‎Lib/test/test_mailbox.py‎

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,92 @@ def test_lock_unlock(self):
847847
self._box.lock()
848848
self._box.unlock()
849849

850+
deftest_get_info(self):
851+
# Test getting message info from Maildir, not the message.
852+
msg=mailbox.MaildirMessage(self._template%0)
853+
key=self._box.add(msg)
854+
self.assertEqual(self._box.get_info(key),'')
855+
msg.set_info('OurTestInfo')
856+
self._box[key]=msg
857+
self.assertEqual(self._box.get_info(key),'OurTestInfo')
858+
859+
deftest_set_info(self):
860+
# Test setting message info from Maildir, not the message.
861+
# This should immediately rename the message file.
862+
msg=mailbox.MaildirMessage(self._template%0)
863+
key=self._box.add(msg)
864+
defcheck_info(oldinfo,newinfo):
865+
oldfilename=os.path.join(self._box._path,self._box._lookup(key))
866+
newsubpath=self._box._lookup(key).split(self._box.colon)[0]
867+
ifnewinfo:
868+
newsubpath+=self._box.colon+newinfo
869+
newfilename=os.path.join(self._box._path,newsubpath)
870+
# assert initial conditions
871+
self.assertEqual(self._box.get_info(key),oldinfo)
872+
ifnotoldinfo:
873+
self.assertNotIn(self._box._lookup(key),self._box.colon)
874+
self.assertTrue(os.path.exists(oldfilename))
875+
ifoldinfo!=newinfo:
876+
self.assertFalse(os.path.exists(newfilename))
877+
# do the rename
878+
self._box.set_info(key,newinfo)
879+
# assert post conditions
880+
ifnotnewinfo:
881+
self.assertNotIn(self._box._lookup(key),self._box.colon)
882+
ifoldinfo!=newinfo:
883+
self.assertFalse(os.path.exists(oldfilename))
884+
self.assertTrue(os.path.exists(newfilename))
885+
self.assertEqual(self._box.get_info(key),newinfo)
886+
# none -> has info
887+
check_info('','info1')
888+
# has info -> same info
889+
check_info('info1','info1')
890+
# has info -> different info
891+
check_info('info1','info2')
892+
# has info -> none
893+
check_info('info2','')
894+
# none -> none
895+
check_info('','')
896+
897+
deftest_get_flags(self):
898+
# Test getting message flags from Maildir, not the message.
899+
msg=mailbox.MaildirMessage(self._template%0)
900+
key=self._box.add(msg)
901+
self.assertEqual(self._box.get_flags(key),'')
902+
msg.set_flags('T')
903+
self._box[key]=msg
904+
self.assertEqual(self._box.get_flags(key),'T')
905+
906+
deftest_set_flags(self):
907+
msg=mailbox.MaildirMessage(self._template%0)
908+
key=self._box.add(msg)
909+
self.assertEqual(self._box.get_flags(key),'')
910+
self._box.set_flags(key,'S')
911+
self.assertEqual(self._box.get_flags(key),'S')
912+
913+
deftest_add_flag(self):
914+
msg=mailbox.MaildirMessage(self._template%0)
915+
key=self._box.add(msg)
916+
self.assertEqual(self._box.get_flags(key),'')
917+
self._box.add_flag(key,'B')
918+
self.assertEqual(self._box.get_flags(key),'B')
919+
self._box.add_flag(key,'B')
920+
self.assertEqual(self._box.get_flags(key),'B')
921+
self._box.add_flag(key,'AC')
922+
self.assertEqual(self._box.get_flags(key),'ABC')
923+
924+
deftest_remove_flag(self):
925+
msg=mailbox.MaildirMessage(self._template%0)
926+
key=self._box.add(msg)
927+
self._box.set_flags(key,'abc')
928+
self.assertEqual(self._box.get_flags(key),'abc')
929+
self._box.remove_flag(key,'b')
930+
self.assertEqual(self._box.get_flags(key),'ac')
931+
self._box.remove_flag(key,'b')
932+
self.assertEqual(self._box.get_flags(key),'ac')
933+
self._box.remove_flag(key,'ac')
934+
self.assertEqual(self._box.get_flags(key),'')
935+
850936
deftest_folder (self):
851937
# Test for bug #1569790: verify that folders returned by .get_folder()
852938
# use the same factory function.

‎Misc/ACKS‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,7 @@ Dinu Gherman
630630
Subhendu Ghosh
631631
Jonathan Giddy
632632
Johannes Gijsbers
633+
Stephen Gildea
633634
Michael Gilfix
634635
Julian Gindi
635636
Yannick Gingras
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
New methods:meth:`mailbox.Maildir.get_info`,
2+
:meth:`mailbox.Maildir.set_info`,:meth:`mailbox.Maildir.get_flags`,
3+
:meth:`mailbox.Maildir.set_flags`,:meth:`mailbox.Maildir.add_flag`,
4+
:meth:`mailbox.Maildir.remove_flag`. These methods speed up accessing a
5+
message's info and/or flags and are useful when it is not necessary to
6+
access the message's contents, as when iterating over a Maildir to find
7+
messages with specific flags.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp