mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-11-25 12:28:09 +01:00
python: refactor the python bindings
Move the Directory class into its own file, merge the two Filenames classes into one, deprecate Filenames.as_iterator, update the documentation accordingly. Signed-off-by: Justus Winter <4winter@informatik.uni-hamburg.de>
This commit is contained in:
parent
1736488ecf
commit
ba95980cf1
5 changed files with 256 additions and 263 deletions
|
@ -254,26 +254,28 @@ More information on specific topics can be found on the following pages:
|
||||||
:class:`Filenames` -- An iterator over filenames
|
:class:`Filenames` -- An iterator over filenames
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
.. autoclass:: notmuch.database.Filenames
|
.. autoclass:: notmuch.Filenames
|
||||||
|
|
||||||
.. automethod:: notmuch.database.Filenames.__len__
|
.. automethod:: notmuch.Filenames.__len__
|
||||||
|
|
||||||
|
.. automethod:: notmuch.Filenames.as_generator
|
||||||
|
|
||||||
:class:`notmuch.database.Directoy` -- A directory entry in the database
|
:class:`notmuch.database.Directoy` -- A directory entry in the database
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
.. autoclass:: notmuch.database.Directory
|
.. autoclass:: notmuch.Directory
|
||||||
|
|
||||||
.. automethod:: notmuch.database.Directory.get_child_files
|
.. automethod:: notmuch.Directory.get_child_files
|
||||||
|
|
||||||
.. automethod:: notmuch.database.Directory.get_child_directories
|
.. automethod:: notmuch.Directory.get_child_directories
|
||||||
|
|
||||||
.. automethod:: notmuch.database.Directory.get_mtime
|
.. automethod:: notmuch.Directory.get_mtime
|
||||||
|
|
||||||
.. automethod:: notmuch.database.Directory.set_mtime
|
.. automethod:: notmuch.Directory.set_mtime
|
||||||
|
|
||||||
.. autoattribute:: notmuch.database.Directory.mtime
|
.. autoattribute:: notmuch.Directory.mtime
|
||||||
|
|
||||||
.. autoattribute:: notmuch.database.Directory.path
|
.. autoattribute:: notmuch.Directory.path
|
||||||
|
|
||||||
|
|
||||||
The `next page <status_and_errors.html>`_ contains information on possible Status and Error values.
|
The `next page <status_and_errors.html>`_ contains information on possible Status and Error values.
|
||||||
|
|
|
@ -51,11 +51,14 @@ along with notmuch. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Copyright 2010-2011 Sebastian Spaeth <Sebastian@SSpaeth.de>
|
Copyright 2010-2011 Sebastian Spaeth <Sebastian@SSpaeth.de>
|
||||||
"""
|
"""
|
||||||
from notmuch.database import Database, Query
|
from .database import Database
|
||||||
from notmuch.message import Messages, Message
|
from .directory import Directory
|
||||||
from notmuch.thread import Threads, Thread
|
from .filename import Filenames
|
||||||
from notmuch.tag import Tags
|
from .message import Messages, Message
|
||||||
from notmuch.globals import (
|
from .query import Query
|
||||||
|
from .tag import Tags
|
||||||
|
from .thread import Threads, Thread
|
||||||
|
from .globals import (
|
||||||
nmlib,
|
nmlib,
|
||||||
STATUS,
|
STATUS,
|
||||||
NotmuchError,
|
NotmuchError,
|
||||||
|
@ -71,6 +74,6 @@ from notmuch.globals import (
|
||||||
UnbalancedAtomicError,
|
UnbalancedAtomicError,
|
||||||
NotInitializedError,
|
NotInitializedError,
|
||||||
)
|
)
|
||||||
from notmuch.version import __VERSION__
|
from .version import __VERSION__
|
||||||
__LICENSE__ = "GPL v3+"
|
__LICENSE__ = "GPL v3+"
|
||||||
__AUTHOR__ = 'Sebastian Spaeth <Sebastian@SSpaeth.de>'
|
__AUTHOR__ = 'Sebastian Spaeth <Sebastian@SSpaeth.de>'
|
||||||
|
|
|
@ -19,7 +19,7 @@ Copyright 2010 Sebastian Spaeth <Sebastian@SSpaeth.de>'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import codecs
|
import codecs
|
||||||
from ctypes import c_char_p, c_void_p, c_uint, c_long, byref, POINTER
|
from ctypes import c_char_p, c_void_p, c_uint, byref, POINTER
|
||||||
from notmuch.globals import (
|
from notmuch.globals import (
|
||||||
nmlib,
|
nmlib,
|
||||||
STATUS,
|
STATUS,
|
||||||
|
@ -34,11 +34,11 @@ from notmuch.globals import (
|
||||||
NotmuchDirectoryP,
|
NotmuchDirectoryP,
|
||||||
NotmuchMessageP,
|
NotmuchMessageP,
|
||||||
NotmuchTagsP,
|
NotmuchTagsP,
|
||||||
NotmuchFilenamesP
|
|
||||||
)
|
)
|
||||||
from notmuch.message import Message
|
from notmuch.message import Message
|
||||||
from notmuch.tag import Tags
|
from notmuch.tag import Tags
|
||||||
from .query import Query
|
from .query import Query
|
||||||
|
from .directory import Directory
|
||||||
|
|
||||||
class Database(object):
|
class Database(object):
|
||||||
"""The :class:`Database` is the highest-level object that notmuch
|
"""The :class:`Database` is the highest-level object that notmuch
|
||||||
|
@ -603,238 +603,3 @@ class Database(object):
|
||||||
guaranteed to remain stable in future versions).
|
guaranteed to remain stable in future versions).
|
||||||
"""
|
"""
|
||||||
return self._db
|
return self._db
|
||||||
|
|
||||||
|
|
||||||
class Directory(object):
|
|
||||||
"""Represents a directory entry in the notmuch directory
|
|
||||||
|
|
||||||
Modifying attributes of this object will modify the
|
|
||||||
database, not the real directory attributes.
|
|
||||||
|
|
||||||
The Directory object is usually derived from another object
|
|
||||||
e.g. via :meth:`Database.get_directory`, and will automatically be
|
|
||||||
become invalid whenever that parent is deleted. You should
|
|
||||||
therefore initialized this object handing it a reference to the
|
|
||||||
parent, preventing the parent from automatically being garbage
|
|
||||||
collected.
|
|
||||||
"""
|
|
||||||
|
|
||||||
"""notmuch_directory_get_mtime"""
|
|
||||||
_get_mtime = nmlib.notmuch_directory_get_mtime
|
|
||||||
_get_mtime.argtypes = [NotmuchDirectoryP]
|
|
||||||
_get_mtime.restype = c_long
|
|
||||||
|
|
||||||
"""notmuch_directory_set_mtime"""
|
|
||||||
_set_mtime = nmlib.notmuch_directory_set_mtime
|
|
||||||
_set_mtime.argtypes = [NotmuchDirectoryP, c_long]
|
|
||||||
_set_mtime.restype = c_uint
|
|
||||||
|
|
||||||
"""notmuch_directory_get_child_files"""
|
|
||||||
_get_child_files = nmlib.notmuch_directory_get_child_files
|
|
||||||
_get_child_files.argtypes = [NotmuchDirectoryP]
|
|
||||||
_get_child_files.restype = NotmuchFilenamesP
|
|
||||||
|
|
||||||
"""notmuch_directory_get_child_directories"""
|
|
||||||
_get_child_directories = nmlib.notmuch_directory_get_child_directories
|
|
||||||
_get_child_directories.argtypes = [NotmuchDirectoryP]
|
|
||||||
_get_child_directories.restype = NotmuchFilenamesP
|
|
||||||
|
|
||||||
def _assert_dir_is_initialized(self):
|
|
||||||
"""Raises a NotmuchError(:attr:`STATUS`.NOT_INITIALIZED)
|
|
||||||
if dir_p is None"""
|
|
||||||
if not self._dir_p:
|
|
||||||
raise NotInitializedError()
|
|
||||||
|
|
||||||
def __init__(self, path, dir_p, parent):
|
|
||||||
"""
|
|
||||||
:param path: The absolute path of the directory object.
|
|
||||||
:param dir_p: The pointer to an internal notmuch_directory_t object.
|
|
||||||
:param parent: The object this Directory is derived from
|
|
||||||
(usually a :class:`Database`). We do not directly use
|
|
||||||
this, but store a reference to it as long as
|
|
||||||
this Directory object lives. This keeps the
|
|
||||||
parent object alive.
|
|
||||||
"""
|
|
||||||
self._path = path
|
|
||||||
self._dir_p = dir_p
|
|
||||||
self._parent = parent
|
|
||||||
|
|
||||||
def set_mtime(self, mtime):
|
|
||||||
"""Sets the mtime value of this directory in the database
|
|
||||||
|
|
||||||
The intention is for the caller to use the mtime to allow efficient
|
|
||||||
identification of new messages to be added to the database. The
|
|
||||||
recommended usage is as follows:
|
|
||||||
|
|
||||||
* Read the mtime of a directory from the filesystem
|
|
||||||
|
|
||||||
* Call :meth:`Database.add_message` for all mail files in
|
|
||||||
the directory
|
|
||||||
|
|
||||||
* Call notmuch_directory_set_mtime with the mtime read from the
|
|
||||||
filesystem. Then, when wanting to check for updates to the
|
|
||||||
directory in the future, the client can call :meth:`get_mtime`
|
|
||||||
and know that it only needs to add files if the mtime of the
|
|
||||||
directory and files are newer than the stored timestamp.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
:meth:`get_mtime` function does not allow the caller to
|
|
||||||
distinguish a timestamp of 0 from a non-existent timestamp. So
|
|
||||||
don't store a timestamp of 0 unless you are comfortable with
|
|
||||||
that.
|
|
||||||
|
|
||||||
:param mtime: A (time_t) timestamp
|
|
||||||
:raises: :exc:`XapianError` a Xapian exception occurred, mtime
|
|
||||||
not stored
|
|
||||||
:raises: :exc:`ReadOnlyDatabaseError` the database was opened
|
|
||||||
in read-only mode so directory mtime cannot be modified
|
|
||||||
:raises: :exc:`NotInitializedError` the directory object has not
|
|
||||||
been initialized
|
|
||||||
"""
|
|
||||||
self._assert_dir_is_initialized()
|
|
||||||
status = Directory._set_mtime(self._dir_p, mtime)
|
|
||||||
|
|
||||||
if status != STATUS.SUCCESS:
|
|
||||||
raise NotmuchError(status)
|
|
||||||
|
|
||||||
def get_mtime(self):
|
|
||||||
"""Gets the mtime value of this directory in the database
|
|
||||||
|
|
||||||
Retrieves a previously stored mtime for this directory.
|
|
||||||
|
|
||||||
:param mtime: A (time_t) timestamp
|
|
||||||
:raises: :exc:`NotmuchError`:
|
|
||||||
|
|
||||||
:attr:`STATUS`.NOT_INITIALIZED
|
|
||||||
The directory has not been initialized
|
|
||||||
"""
|
|
||||||
self._assert_dir_is_initialized()
|
|
||||||
return Directory._get_mtime(self._dir_p)
|
|
||||||
|
|
||||||
# Make mtime attribute a property of Directory()
|
|
||||||
mtime = property(get_mtime, set_mtime, doc="""Property that allows getting
|
|
||||||
and setting of the Directory *mtime* (read-write)
|
|
||||||
|
|
||||||
See :meth:`get_mtime` and :meth:`set_mtime` for usage and
|
|
||||||
possible exceptions.""")
|
|
||||||
|
|
||||||
def get_child_files(self):
|
|
||||||
"""Gets a Filenames iterator listing all the filenames of
|
|
||||||
messages in the database within the given directory.
|
|
||||||
|
|
||||||
The returned filenames will be the basename-entries only (not
|
|
||||||
complete paths.
|
|
||||||
"""
|
|
||||||
self._assert_dir_is_initialized()
|
|
||||||
files_p = Directory._get_child_files(self._dir_p)
|
|
||||||
return Filenames(files_p, self)
|
|
||||||
|
|
||||||
def get_child_directories(self):
|
|
||||||
"""Gets a :class:`Filenames` iterator listing all the filenames of
|
|
||||||
sub-directories in the database within the given directory
|
|
||||||
|
|
||||||
The returned filenames will be the basename-entries only (not
|
|
||||||
complete paths.
|
|
||||||
"""
|
|
||||||
self._assert_dir_is_initialized()
|
|
||||||
files_p = Directory._get_child_directories(self._dir_p)
|
|
||||||
return Filenames(files_p, self)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def path(self):
|
|
||||||
"""Returns the absolute path of this Directory (read-only)"""
|
|
||||||
return self._path
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
"""Object representation"""
|
|
||||||
return "<notmuch Directory object '%s'>" % self._path
|
|
||||||
|
|
||||||
_destroy = nmlib.notmuch_directory_destroy
|
|
||||||
_destroy.argtypes = [NotmuchDirectoryP]
|
|
||||||
_destroy.argtypes = None
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
"""Close and free the Directory"""
|
|
||||||
if self._dir_p is not None:
|
|
||||||
self._destroy(self._dir_p)
|
|
||||||
|
|
||||||
|
|
||||||
class Filenames(object):
|
|
||||||
"""An iterator over File- or Directory names stored in the database"""
|
|
||||||
|
|
||||||
#notmuch_filenames_get
|
|
||||||
_get = nmlib.notmuch_filenames_get
|
|
||||||
_get.argtypes = [NotmuchFilenamesP]
|
|
||||||
_get.restype = c_char_p
|
|
||||||
|
|
||||||
def __init__(self, files_p, parent):
|
|
||||||
"""
|
|
||||||
:param files_p: The pointer to an internal notmuch_filenames_t object.
|
|
||||||
:param parent: The object this Directory is derived from
|
|
||||||
(usually a Directory()). We do not directly use
|
|
||||||
this, but store a reference to it as long as
|
|
||||||
this Directory object lives. This keeps the
|
|
||||||
parent object alive.
|
|
||||||
"""
|
|
||||||
self._files_p = files_p
|
|
||||||
self._parent = parent
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
""" Make Filenames an iterator """
|
|
||||||
return self
|
|
||||||
|
|
||||||
_valid = nmlib.notmuch_filenames_valid
|
|
||||||
_valid.argtypes = [NotmuchFilenamesP]
|
|
||||||
_valid.restype = bool
|
|
||||||
|
|
||||||
_move_to_next = nmlib.notmuch_filenames_move_to_next
|
|
||||||
_move_to_next.argtypes = [NotmuchFilenamesP]
|
|
||||||
_move_to_next.restype = None
|
|
||||||
|
|
||||||
def __next__(self):
|
|
||||||
if not self._files_p:
|
|
||||||
raise NotInitializedError()
|
|
||||||
|
|
||||||
if not self._valid(self._files_p):
|
|
||||||
self._files_p = None
|
|
||||||
raise StopIteration
|
|
||||||
|
|
||||||
file_ = Filenames._get(self._files_p)
|
|
||||||
self._move_to_next(self._files_p)
|
|
||||||
return file_.decode('utf-8', 'ignore')
|
|
||||||
next = __next__ # python2.x iterator protocol compatibility
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
"""len(:class:`Filenames`) returns the number of contained files
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
As this iterates over the files, we will not be able to
|
|
||||||
iterate over them again! So this will fail::
|
|
||||||
|
|
||||||
#THIS FAILS
|
|
||||||
files = Database().get_directory('').get_child_files()
|
|
||||||
if len(files) > 0: # this 'exhausts' msgs
|
|
||||||
# next line raises
|
|
||||||
# NotmuchError(:attr:`STATUS`.NOT_INITIALIZED)
|
|
||||||
for file in files: print file
|
|
||||||
"""
|
|
||||||
if not self._files_p:
|
|
||||||
raise NotInitializedError()
|
|
||||||
|
|
||||||
i = 0
|
|
||||||
while self._valid(self._files_p):
|
|
||||||
self._move_to_next(self._files_p)
|
|
||||||
i += 1
|
|
||||||
self._files_p = None
|
|
||||||
return i
|
|
||||||
|
|
||||||
_destroy = nmlib.notmuch_filenames_destroy
|
|
||||||
_destroy.argtypes = [NotmuchFilenamesP]
|
|
||||||
_destroy.restype = None
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
"""Close and free Filenames"""
|
|
||||||
if self._files_p is not None:
|
|
||||||
self._destroy(self._files_p)
|
|
||||||
|
|
183
bindings/python/notmuch/directory.py
Normal file
183
bindings/python/notmuch/directory.py
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
"""
|
||||||
|
This file is part of notmuch.
|
||||||
|
|
||||||
|
Notmuch is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
Notmuch is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with notmuch. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Copyright 2010 Sebastian Spaeth <Sebastian@SSpaeth.de>'
|
||||||
|
"""
|
||||||
|
|
||||||
|
from ctypes import c_uint, c_long
|
||||||
|
from notmuch.globals import (
|
||||||
|
nmlib,
|
||||||
|
STATUS,
|
||||||
|
NotmuchError,
|
||||||
|
NotInitializedError,
|
||||||
|
NotmuchDirectoryP,
|
||||||
|
NotmuchFilenamesP
|
||||||
|
)
|
||||||
|
from .filename import Filenames
|
||||||
|
|
||||||
|
class Directory(object):
|
||||||
|
"""Represents a directory entry in the notmuch directory
|
||||||
|
|
||||||
|
Modifying attributes of this object will modify the
|
||||||
|
database, not the real directory attributes.
|
||||||
|
|
||||||
|
The Directory object is usually derived from another object
|
||||||
|
e.g. via :meth:`Database.get_directory`, and will automatically be
|
||||||
|
become invalid whenever that parent is deleted. You should
|
||||||
|
therefore initialized this object handing it a reference to the
|
||||||
|
parent, preventing the parent from automatically being garbage
|
||||||
|
collected.
|
||||||
|
"""
|
||||||
|
|
||||||
|
"""notmuch_directory_get_mtime"""
|
||||||
|
_get_mtime = nmlib.notmuch_directory_get_mtime
|
||||||
|
_get_mtime.argtypes = [NotmuchDirectoryP]
|
||||||
|
_get_mtime.restype = c_long
|
||||||
|
|
||||||
|
"""notmuch_directory_set_mtime"""
|
||||||
|
_set_mtime = nmlib.notmuch_directory_set_mtime
|
||||||
|
_set_mtime.argtypes = [NotmuchDirectoryP, c_long]
|
||||||
|
_set_mtime.restype = c_uint
|
||||||
|
|
||||||
|
"""notmuch_directory_get_child_files"""
|
||||||
|
_get_child_files = nmlib.notmuch_directory_get_child_files
|
||||||
|
_get_child_files.argtypes = [NotmuchDirectoryP]
|
||||||
|
_get_child_files.restype = NotmuchFilenamesP
|
||||||
|
|
||||||
|
"""notmuch_directory_get_child_directories"""
|
||||||
|
_get_child_directories = nmlib.notmuch_directory_get_child_directories
|
||||||
|
_get_child_directories.argtypes = [NotmuchDirectoryP]
|
||||||
|
_get_child_directories.restype = NotmuchFilenamesP
|
||||||
|
|
||||||
|
def _assert_dir_is_initialized(self):
|
||||||
|
"""Raises a NotmuchError(:attr:`STATUS`.NOT_INITIALIZED)
|
||||||
|
if dir_p is None"""
|
||||||
|
if not self._dir_p:
|
||||||
|
raise NotInitializedError()
|
||||||
|
|
||||||
|
def __init__(self, path, dir_p, parent):
|
||||||
|
"""
|
||||||
|
:param path: The absolute path of the directory object.
|
||||||
|
:param dir_p: The pointer to an internal notmuch_directory_t object.
|
||||||
|
:param parent: The object this Directory is derived from
|
||||||
|
(usually a :class:`Database`). We do not directly use
|
||||||
|
this, but store a reference to it as long as
|
||||||
|
this Directory object lives. This keeps the
|
||||||
|
parent object alive.
|
||||||
|
"""
|
||||||
|
self._path = path
|
||||||
|
self._dir_p = dir_p
|
||||||
|
self._parent = parent
|
||||||
|
|
||||||
|
def set_mtime(self, mtime):
|
||||||
|
"""Sets the mtime value of this directory in the database
|
||||||
|
|
||||||
|
The intention is for the caller to use the mtime to allow efficient
|
||||||
|
identification of new messages to be added to the database. The
|
||||||
|
recommended usage is as follows:
|
||||||
|
|
||||||
|
* Read the mtime of a directory from the filesystem
|
||||||
|
|
||||||
|
* Call :meth:`Database.add_message` for all mail files in
|
||||||
|
the directory
|
||||||
|
|
||||||
|
* Call notmuch_directory_set_mtime with the mtime read from the
|
||||||
|
filesystem. Then, when wanting to check for updates to the
|
||||||
|
directory in the future, the client can call :meth:`get_mtime`
|
||||||
|
and know that it only needs to add files if the mtime of the
|
||||||
|
directory and files are newer than the stored timestamp.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
:meth:`get_mtime` function does not allow the caller to
|
||||||
|
distinguish a timestamp of 0 from a non-existent timestamp. So
|
||||||
|
don't store a timestamp of 0 unless you are comfortable with
|
||||||
|
that.
|
||||||
|
|
||||||
|
:param mtime: A (time_t) timestamp
|
||||||
|
:raises: :exc:`XapianError` a Xapian exception occurred, mtime
|
||||||
|
not stored
|
||||||
|
:raises: :exc:`ReadOnlyDatabaseError` the database was opened
|
||||||
|
in read-only mode so directory mtime cannot be modified
|
||||||
|
:raises: :exc:`NotInitializedError` the directory object has not
|
||||||
|
been initialized
|
||||||
|
"""
|
||||||
|
self._assert_dir_is_initialized()
|
||||||
|
status = Directory._set_mtime(self._dir_p, mtime)
|
||||||
|
|
||||||
|
if status != STATUS.SUCCESS:
|
||||||
|
raise NotmuchError(status)
|
||||||
|
|
||||||
|
def get_mtime(self):
|
||||||
|
"""Gets the mtime value of this directory in the database
|
||||||
|
|
||||||
|
Retrieves a previously stored mtime for this directory.
|
||||||
|
|
||||||
|
:param mtime: A (time_t) timestamp
|
||||||
|
:raises: :exc:`NotmuchError`:
|
||||||
|
|
||||||
|
:attr:`STATUS`.NOT_INITIALIZED
|
||||||
|
The directory has not been initialized
|
||||||
|
"""
|
||||||
|
self._assert_dir_is_initialized()
|
||||||
|
return Directory._get_mtime(self._dir_p)
|
||||||
|
|
||||||
|
# Make mtime attribute a property of Directory()
|
||||||
|
mtime = property(get_mtime, set_mtime, doc="""Property that allows getting
|
||||||
|
and setting of the Directory *mtime* (read-write)
|
||||||
|
|
||||||
|
See :meth:`get_mtime` and :meth:`set_mtime` for usage and
|
||||||
|
possible exceptions.""")
|
||||||
|
|
||||||
|
def get_child_files(self):
|
||||||
|
"""Gets a Filenames iterator listing all the filenames of
|
||||||
|
messages in the database within the given directory.
|
||||||
|
|
||||||
|
The returned filenames will be the basename-entries only (not
|
||||||
|
complete paths.
|
||||||
|
"""
|
||||||
|
self._assert_dir_is_initialized()
|
||||||
|
files_p = Directory._get_child_files(self._dir_p)
|
||||||
|
return Filenames(files_p, self)
|
||||||
|
|
||||||
|
def get_child_directories(self):
|
||||||
|
"""Gets a :class:`Filenames` iterator listing all the filenames of
|
||||||
|
sub-directories in the database within the given directory
|
||||||
|
|
||||||
|
The returned filenames will be the basename-entries only (not
|
||||||
|
complete paths.
|
||||||
|
"""
|
||||||
|
self._assert_dir_is_initialized()
|
||||||
|
files_p = Directory._get_child_directories(self._dir_p)
|
||||||
|
return Filenames(files_p, self)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def path(self):
|
||||||
|
"""Returns the absolute path of this Directory (read-only)"""
|
||||||
|
return self._path
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
"""Object representation"""
|
||||||
|
return "<notmuch Directory object '%s'>" % self._path
|
||||||
|
|
||||||
|
_destroy = nmlib.notmuch_directory_destroy
|
||||||
|
_destroy.argtypes = [NotmuchDirectoryP]
|
||||||
|
_destroy.argtypes = None
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
"""Close and free the Directory"""
|
||||||
|
if self._dir_p is not None:
|
||||||
|
self._destroy(self._dir_p)
|
|
@ -78,10 +78,14 @@ class Filenames(Python3StringMixIn):
|
||||||
if not files_p:
|
if not files_p:
|
||||||
raise NullPointerError()
|
raise NullPointerError()
|
||||||
|
|
||||||
self._files = files_p
|
self._files_p = files_p
|
||||||
#save reference to parent object so we keep it alive
|
#save reference to parent object so we keep it alive
|
||||||
self._parent = parent
|
self._parent = parent
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
""" Make Filenames an iterator """
|
||||||
|
return self
|
||||||
|
|
||||||
_valid = nmlib.notmuch_filenames_valid
|
_valid = nmlib.notmuch_filenames_valid
|
||||||
_valid.argtypes = [NotmuchFilenamesP]
|
_valid.argtypes = [NotmuchFilenamesP]
|
||||||
_valid.restype = bool
|
_valid.restype = bool
|
||||||
|
@ -90,19 +94,30 @@ class Filenames(Python3StringMixIn):
|
||||||
_move_to_next.argtypes = [NotmuchFilenamesP]
|
_move_to_next.argtypes = [NotmuchFilenamesP]
|
||||||
_move_to_next.restype = None
|
_move_to_next.restype = None
|
||||||
|
|
||||||
|
def __next__(self):
|
||||||
|
if not self._files_p:
|
||||||
|
raise NotInitializedError()
|
||||||
|
|
||||||
|
if not self._valid(self._files_p):
|
||||||
|
self._files_p = None
|
||||||
|
raise StopIteration
|
||||||
|
|
||||||
|
file_ = Filenames._get(self._files_p)
|
||||||
|
self._move_to_next(self._files_p)
|
||||||
|
return file_.decode('utf-8', 'ignore')
|
||||||
|
next = __next__ # python2.x iterator protocol compatibility
|
||||||
|
|
||||||
def as_generator(self):
|
def as_generator(self):
|
||||||
"""Return generator of Filenames
|
"""Return generator of Filenames
|
||||||
|
|
||||||
This is the main function that will usually be used by the
|
This is the main function that will usually be used by the
|
||||||
user."""
|
user.
|
||||||
if not self._files:
|
|
||||||
raise NotInitializedError()
|
|
||||||
|
|
||||||
while self._valid(self._files):
|
.. deprecated:: 0.12
|
||||||
yield Filenames._get(self._files).decode('utf-8', 'ignore')
|
:class:`Filenames` objects implement the
|
||||||
self._move_to_next(self._files)
|
iterator protocol.
|
||||||
|
"""
|
||||||
self._files = None
|
return self
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
"""Represent Filenames() as newline-separated list of full paths
|
"""Represent Filenames() as newline-separated list of full paths
|
||||||
|
@ -123,5 +138,30 @@ class Filenames(Python3StringMixIn):
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
"""Close and free the notmuch filenames"""
|
"""Close and free the notmuch filenames"""
|
||||||
if self._files is not None:
|
if self._files_p is not None:
|
||||||
self._destroy(self._files)
|
self._destroy(self._files_p)
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
"""len(:class:`Filenames`) returns the number of contained files
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
As this iterates over the files, we will not be able to
|
||||||
|
iterate over them again! So this will fail::
|
||||||
|
|
||||||
|
#THIS FAILS
|
||||||
|
files = Database().get_directory('').get_child_files()
|
||||||
|
if len(files) > 0: # this 'exhausts' msgs
|
||||||
|
# next line raises
|
||||||
|
# NotmuchError(:attr:`STATUS`.NOT_INITIALIZED)
|
||||||
|
for file in files: print file
|
||||||
|
"""
|
||||||
|
if not self._files_p:
|
||||||
|
raise NotInitializedError()
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
while self._valid(self._files_p):
|
||||||
|
self._move_to_next(self._files_p)
|
||||||
|
i += 1
|
||||||
|
self._files_p = None
|
||||||
|
return i
|
||||||
|
|
Loading…
Reference in a new issue