diff --git a/python/doc/api.rst b/python/doc/api.rst
new file mode 100644
index 00000000..c28cc6f3
--- /dev/null
+++ b/python/doc/api.rst
@@ -0,0 +1,14 @@
+
+deltachat API Reference
+==============================
+
+.. autosummary::
+
+ deltachat.account
+
+account module
+--------------
+
+.. automodule:: deltachat.account
+ :members:
+
diff --git a/python/doc/changelog.rst b/python/doc/changelog.rst
new file mode 100644
index 00000000..db2b47a6
--- /dev/null
+++ b/python/doc/changelog.rst
@@ -0,0 +1,4 @@
+Changelog for deltachat-core's Python bindings
+==============================================
+
+.. include:: ../CHANGELOG
diff --git a/python/doc/conf.py b/python/doc/conf.py
new file mode 100644
index 00000000..79973fc2
--- /dev/null
+++ b/python/doc/conf.py
@@ -0,0 +1,285 @@
+# -*- coding: utf-8 -*-
+#
+# devpi documentation build configuration file, created by
+# sphinx-quickstart on Mon Jun 3 16:11:22 2013.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+from deltachat import __version__ as release
+version = ".".join(release.split(".")[:2])
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# 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',
+ 'sphinx.ext.autosummary',
+ #'sphinx.ext.intersphinx',
+ 'sphinx.ext.todo',
+ 'sphinx.ext.viewcode',
+ #'sphinx.ext.githubpages',
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'deltachat'
+copyright = u'2018, holger krekel and contributors'
+
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['sketch', '_build', "attic"]
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+sys.path.append(os.path.abspath('_themes'))
+html_theme_path = ['_themes']
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+# html_theme = 'flask'
+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
+# documentation.
+html_theme_options = {
+ # 'index_logo': '_static/delta-chat.svg',
+}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = ["_themes"]
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# " v documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+html_logo = "_static/delta-chat.svg"
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# 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']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#
+html_sidebars = {
+ 'index': [
+ 'sidebarintro.html',
+ 'globaltoc.html',
+ 'searchbox.html'
+ ],
+ '**': [
+ 'sidebarintro.html',
+ 'globaltoc.html',
+ 'relations.html',
+ 'searchbox.html'
+ ]
+}
+
+
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+html_show_sourcelink = False
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+html_show_sphinx = False
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+html_use_opensearch = 'https://doc.devpi.net'
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'deltachat-python'
+
+# -- Options for LaTeX output --------------------------------------------------
+
+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': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('index', 'devpi.tex', u'deltachat documentation',
+ u'holger krekel', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('index', 'deltachat', u'deltachat documentation',
+ [u'holger krekel'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ ('index', 'devpi', u'devpi Documentation',
+ u'holger krekel', 'devpi', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+
+# Example configuration for intersphinx: refer to the Python standard library.
+intersphinx_mapping = {'http://docs.python.org/': None}
+
+# autodoc options
+autodoc_member_order = "bysource"
+# always document __init__ functions
+def skip(app, what, name, obj, skip, options):
+ import attr
+ if name == "__init__":
+ if not hasattr(obj.im_class, "__attrs_attrs__"):
+ return False
+ return skip
+
+def setup(app):
+ app.connect("autodoc-skip-member", skip)
+
diff --git a/python/doc/getting-started.rst b/python/doc/getting-started.rst
new file mode 100644
index 00000000..a2d283a6
--- /dev/null
+++ b/python/doc/getting-started.rst
@@ -0,0 +1,19 @@
+
+
+Getting started
+================
+
+::
+
+ # instantiate and configure deltachat account
+ import deltachat
+ ac1 = deltachat.Account("/tmp/db")
+ ac.set_config(addr="test2@hq5.merlinux.eu", mail_pw="********")
+
+ # start configuration activity and smtp/imap threads
+ ac.start()
+
+ # create a contact and send a message
+ contact = ac.create_contact("test3@hq5.merlinux.eu")
+
+ ...
diff --git a/python/doc/index.rst b/python/doc/index.rst
new file mode 100644
index 00000000..13a41b08
--- /dev/null
+++ b/python/doc/index.rst
@@ -0,0 +1,39 @@
+deltachat: e-mail messaging/chatting API / deltachat-core C lib bindings
+========================================================================
+
+.. include:: links.rst
+
+The deltachat library provides interfaces into the core
+C-library for https://delta.chat:
+
+- **low level bindings to deltachat-core**: ``deltachat.capi.lib`` exposes
+ a CFFI-interface to the `deltachat-core C-API `.
+
+- **higher level bindings**: :class:`deltachat.Account` serves as a high
+ level object through which you can configure, send and receive messages,
+ create and manage groups.
+
+Getting started
+-----------------------------------------
+
+.. toctree::
+ :maxdepth: 2
+
+ install
+ getting-started
+ api
+
+.. toctree::
+ :hidden:
+
+ links
+ changelog
+
+..
+ Indices and tables
+ ==================
+
+ * :ref:`genindex`
+ * :ref:`modindex`
+ * :ref:`search`
+
diff --git a/python/doc/install.rst b/python/doc/install.rst
new file mode 100644
index 00000000..d7f69305
--- /dev/null
+++ b/python/doc/install.rst
@@ -0,0 +1,50 @@
+
+deltachat python bindings
+=========================
+
+This package provides bindings to the delta-core_ C-library
+which provides imap/smtp/crypto handling as well as chat/group/messages
+handling to Android, Desktop and IO user interfaces.
+
+Install
+-------
+
+.. note::
+
+ Currently the install instructions exist only for Debian based systems (Ubuntu etc.).
+
+First you need to execute all the build steps to install the delta-core C-library,
+see https://github.com/deltachat/deltachat-core/blob/master/README.md#build
+
+Next, you need to perform::
+
+ pip install -e .
+
+Afterwards you should be able to successfully import the bindings::
+
+ python -c "import deltachat"
+
+
+Running tests
+-------------
+
+Install the delta-core C-library and the deltachat bindings (see _Install)
+and then type the following to execute tests::
+
+ pip install tox
+ tox
+
+If you want to run functional tests that run against real
+e-mail accounts, generate a "liveconfig" file where each
+lines contains account settings, for example::
+
+ # 'liveconfig' file specifying imap/smtp accounts
+ addr=some-email@example.org mail_pw=password
+ addr=other-email@example.org mail_pw=otherpassword
+
+And then run the tests with this live-accounts config file::
+
+ tox -- --liveconfig liveconfig
+
+
+.. _`delta-core`: https://github.com/deltachat/deltachat-core
diff --git a/python/doc/links.rst b/python/doc/links.rst
new file mode 100644
index 00000000..432775e1
--- /dev/null
+++ b/python/doc/links.rst
@@ -0,0 +1,11 @@
+
+links
+================================
+
+.. _`deltachat`: https://delta.chat
+.. _`deltachat-core repo`: https://github.com/deltachat
+.. _pip: http://pypi.org/project/pip/
+.. _virtualenv: http://pypi.org/project/virtualenv/
+.. _merlinux: http://merlinux.eu
+.. _pypi: http://pypi.org/
+.. _`issue-tracker`: https://github.com/deltachat/deltachat-core
diff --git a/python/doc/make.bat b/python/doc/make.bat
new file mode 100644
index 00000000..1a48d1e6
--- /dev/null
+++ b/python/doc/make.bat
@@ -0,0 +1,190 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+ set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+ set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+ :help
+ echo.Please use `make ^` where ^ is one of
+ echo. html to make standalone HTML files
+ echo. dirhtml to make HTML files named index.html in directories
+ echo. singlehtml to make a single large HTML file
+ echo. pickle to make pickle files
+ echo. json to make JSON files
+ echo. htmlhelp to make HTML files and a HTML help project
+ echo. qthelp to make HTML files and a qthelp project
+ echo. devhelp to make HTML files and a Devhelp project
+ echo. epub to make an epub
+ echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+ echo. text to make text files
+ echo. man to make manual pages
+ echo. texinfo to make Texinfo files
+ echo. gettext to make PO message catalogs
+ echo. changes to make an overview over all changed/added/deprecated items
+ echo. linkcheck to check all external links for integrity
+ echo. doctest to run all doctests embedded in the documentation if enabled
+ goto end
+)
+
+if "%1" == "clean" (
+ for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+ del /q /s %BUILDDIR%\*
+ goto end
+)
+
+if "%1" == "html" (
+ %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+ goto end
+)
+
+if "%1" == "dirhtml" (
+ %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+ goto end
+)
+
+if "%1" == "singlehtml" (
+ %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+ goto end
+)
+
+if "%1" == "pickle" (
+ %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the pickle files.
+ goto end
+)
+
+if "%1" == "json" (
+ %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the JSON files.
+ goto end
+)
+
+if "%1" == "htmlhelp" (
+ %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+ goto end
+)
+
+if "%1" == "qthelp" (
+ %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+ echo.^> qcollectiongenerator %BUILDDIR%\qthelp\devpi.qhcp
+ echo.To view the help file:
+ echo.^> assistant -collectionFile %BUILDDIR%\qthelp\devpi.ghc
+ goto end
+)
+
+if "%1" == "devhelp" (
+ %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished.
+ goto end
+)
+
+if "%1" == "epub" (
+ %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The epub file is in %BUILDDIR%/epub.
+ goto end
+)
+
+if "%1" == "latex" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "text" (
+ %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The text files are in %BUILDDIR%/text.
+ goto end
+)
+
+if "%1" == "man" (
+ %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The manual pages are in %BUILDDIR%/man.
+ goto end
+)
+
+if "%1" == "texinfo" (
+ %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+ goto end
+)
+
+if "%1" == "gettext" (
+ %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+ goto end
+)
+
+if "%1" == "changes" (
+ %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.The overview file is in %BUILDDIR%/changes.
+ goto end
+)
+
+if "%1" == "linkcheck" (
+ %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+ goto end
+)
+
+if "%1" == "doctest" (
+ %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+ goto end
+)
+
+:end
diff --git a/python/setup.py b/python/setup.py
index ec921db3..32137937 100644
--- a/python/setup.py
+++ b/python/setup.py
@@ -1,17 +1,18 @@
import setuptools
+import os
+import re
+
def main():
- with open('README.rst') as fd:
- long_description = fd.read()
-
+ long_description, version = read_meta()
setuptools.setup(
name='deltachat',
- version='0.1',
+ version=version,
description='Python bindings for deltachat-core using CFFI',
long_description = long_description,
- author='holger krekel and contributors',
+ author='holger krekel, bjoern petersen and contributors',
setup_requires=['cffi>=1.0.0'],
- install_requires=['cffi>=1.0.0', 'requests', 'attr'],
+ install_requires=['cffi>=1.0.0', 'requests', 'attrs'],
packages=setuptools.find_packages('src'),
package_dir={'': 'src'},
cffi_modules=['src/deltachat/_build.py:ffibuilder'],
@@ -25,6 +26,21 @@ def main():
],
)
+
+def read_meta():
+ with open('README.rst') as fd:
+ long_description = fd.read()
+ with open(os.path.join("src", "deltachat", "__init__.py")) as f:
+ for line in f:
+ m = re.match('__version__ = "(\S*).*"', line)
+ if m:
+ version, = m.groups()
+
+ with open("README.rst") as f:
+ long_desc = f.read()
+ return long_desc, version
+
+
if __name__ == "__main__":
main()
diff --git a/python/src/deltachat/__init__.py b/python/src/deltachat/__init__.py
index 255c6573..8dceec43 100644
--- a/python/src/deltachat/__init__.py
+++ b/python/src/deltachat/__init__.py
@@ -3,6 +3,9 @@ from deltachat.capi import ffi
from deltachat.account import Account # noqa
+__version__ = "0.5.dev"
+
+
_DC_CALLBACK_MAP = {}
diff --git a/python/src/deltachat/account.py b/python/src/deltachat/account.py
index d11dd71a..af466677 100644
--- a/python/src/deltachat/account.py
+++ b/python/src/deltachat/account.py
@@ -1,3 +1,5 @@
+""" Delta.Chat high level API objects. """
+
from __future__ import print_function
import threading
import re
@@ -11,7 +13,7 @@ except ImportError:
import deltachat
from . import capi
from .capi import ffi, lib
-from .types import cached_property
+from .types import cached_property, property_with_doc
import attr
from attr import validators as v
@@ -81,6 +83,10 @@ class EventLogger:
@attr.s
class Contact(object):
+ """ Delta-Chat Contact. You obtain instances of it through the :class:`Account`.
+
+ :ivar id: integer id of this chat.
+ """
dc_context = attr.ib(validator=v.instance_of(ffi.CData))
id = attr.ib(validator=v.instance_of(int))
@@ -92,12 +98,14 @@ class Contact(object):
if self._property_cache:
dc_contact_unref(self.dc_contact_t)
- @property
+ @property_with_doc
def addr(self):
+ """ normalized e-mail address for this account. """
return ffi_unicode(capi.lib.dc_contact_get_addr(self.dc_contact_t))
- @property
+ @property_with_doc
def display_name(self):
+ """ display name for this contact. """
return ffi_unicode(capi.lib.dc_contact_get_display_name(self.dc_contact_t))
def is_blocked(self):
@@ -111,6 +119,9 @@ class Contact(object):
@attr.s
class Chat(object):
+ """ Chat object which manages members and through which you can send and retrieve messages.
+ """
+
dc_context = attr.ib(validator=v.instance_of(ffi.CData))
id = attr.ib(validator=v.instance_of(int))
@@ -127,19 +138,29 @@ class Chat(object):
return self.id == lib.DC_CHAT_ID_DEADDROP
def send_text_message(self, msg):
- """ send a text message and return the resulting Message instance. """
+ """ send a text message and return the resulting Message instance.
+
+ :param msg: unicode text
+ :returns: the resulting :class:`Message` instance
+ """
msg = convert_to_bytes_utf8(msg)
print ("chat id", self.id)
msg_id = capi.lib.dc_send_text_msg(self.dc_context, self.id, msg)
return Message(self.dc_context, msg_id)
def get_messages(self):
- """ return list of messages in this chat. """
+ """ return list of messages in this chat.
+
+ :returns: list of Message objects for this chat.
+ """
dc_array_t = lib.dc_get_chat_msgs(self.dc_context, self.id, 0, 0)
return list(iter_array_and_unref(dc_array_t, lambda x: Message(self.dc_context, x)))
def count_fresh_messages(self):
- """ return number of fresh messages in this chat. """
+ """ return number of fresh messages in this chat.
+
+ :returns: number of fresh messages
+ """
return lib.dc_get_fresh_msg_cnt(self.dc_context, self.id)
def mark_noticed(self):
@@ -152,6 +173,7 @@ class Chat(object):
@attr.s
class Message(object):
+ """ Message object. """
dc_context = attr.ib(validator=v.instance_of(ffi.CData))
id = attr.ib(validator=v.instance_of(int))
@@ -163,18 +185,34 @@ class Message(object):
if self._property_cache:
dc_msg_unref(self.dc_msg_t)
- @property
+ @property_with_doc
def text(self):
+ """unicode representation. """
return ffi_unicode(capi.lib.dc_msg_get_text(self.dc_msg_t))
@property
def chat(self):
+ """chat this message was posted in.
+
+ :returns: :class:`Chat` object
+ """
chat_id = capi.lib.dc_msg_get_chat_id(self.dc_msg_t)
return Chat(self.dc_context, chat_id)
class Account(object):
+ """ An account contains configuration and provides methods
+ for configuration, contact and chat creation and manipulation.
+ """
def __init__(self, db_path, logid=None):
+ """ initialize account object.
+
+ :param db_path: a path to the account database. The database
+ will be created if it doesn't exist.
+ :param logid: an optional logging prefix that should be used with
+ the default internal logging.
+ """
+
self.dc_context = ctx = capi.lib.dc_context_new(
capi.lib.py_dc_callback,
capi.ffi.NULL, capi.ffi.NULL)
@@ -189,39 +227,66 @@ class Account(object):
dc_context_unref(self.dc_context)
def set_config(self, **kwargs):
+ """ set configuration values.
+
+ :param kwargs: name=value settings for this account.
+ values need to be unicode.
+ :returns: None
+ """
for name, value in kwargs.items():
name = name.encode("utf8")
value = value.encode("utf8")
capi.lib.dc_set_config(self.dc_context, name, value)
def get_config(self, name):
+ """ return unicode string value.
+
+ :param name: configuration key to lookup (eg "addr" or "mail_pw")
+ :returns: unicode value
+ """
name = name.encode("utf8")
res = capi.lib.dc_get_config(self.dc_context, name, b'')
return ffi_unicode(res)
def is_configured(self):
+ """ determine if the account is configured already.
+
+ :returns: True if account is configured.
+ """
return capi.lib.dc_is_configured(self.dc_context)
def check_is_configured(self):
+ """ Raise ValueError if this account is not configured. """
if not self.is_configured():
raise ValueError("need to configure first")
def get_self_contact(self):
+ """ return this account's identity as a :class:`Contact`.
+
+ :returns: :class:`Contact`
+ """
self.check_is_configured()
return Contact(self.dc_context, capi.lib.DC_CONTACT_ID_SELF)
def create_contact(self, email, name=ffi.NULL):
+ """ Return a :class:`Contact` object.
+
+ :param email: email-address (text type)
+ :param name: display name for this contact (optional)
+ :returns: :class:`Contact` instance.
+ """
name = convert_to_bytes_utf8(name)
email = convert_to_bytes_utf8(email)
contact_id = capi.lib.dc_create_contact(self.dc_context, name, email)
return Contact(self.dc_context, contact_id)
def get_contacts(self, query=ffi.NULL, with_self=False, only_verified=False):
- """ return list of :pyclass:`Contact` objects.
+ """ return list of :class:`Contact` objects.
- :query: if a string is specified, only return contacts whose name or e-mail matches query.
- :only_verified: if true only return verified contacts.
- :with_self: if true the self-contact is also returned.
+ :param query: if a string is specified, only return contacts
+ whose name or e-mail matches query.
+ :param only_verified: if true only return verified contacts.
+ :param with_self: if true the self-contact is also returned.
"""
flags = 0
query = convert_to_bytes_utf8(query)
@@ -235,7 +300,7 @@ class Account(object):
def create_chat_by_contact(self, contact):
""" return a Chat object with the specified contact.
- @param contact: chat_id (int) or contact object.
+ :param contact: chat_id (int) or contact object.
"""
contact_id = getattr(contact, "id", contact)
assert isinstance(contact_id, int)
@@ -246,7 +311,7 @@ class Account(object):
def create_chat_by_message(self, message):
""" return a Chat object for the given message.
- @param message: messsage id or message instance.
+ :param message: messsage id or message instance.
"""
msg_id = getattr(message, "id", message)
assert isinstance(msg_id, int)
@@ -254,12 +319,16 @@ class Account(object):
return Chat(self.dc_context, chat_id)
def get_message_by_id(self, msg_id):
+ """ return a message object.
+
+ :returns: :class:`Message` instance.
+ """
return Message(self.dc_context, msg_id)
def mark_seen_messages(self, messages):
""" mark the given set of messages as seen.
- :messages: a list of message ids or Message instances.
+ :param messages: a list of message ids or Message instances.
"""
arr = array("i")
for msg in messages:
@@ -269,11 +338,14 @@ class Account(object):
lib.dc_markseen_msgs(self.dc_context, msg_ids, len(messages))
def start(self):
+ """ configure this account object, start receiving events,
+ start IMAP/SMTP threads. """
deltachat.set_context_callback(self.dc_context, self._process_event)
capi.lib.dc_configure(self.dc_context)
self._threads.start()
def shutdown(self):
+ """ shutdown IMAP/SMTP threads and stop receiving events"""
deltachat.clear_context_callback(self.dc_context)
self._threads.stop(wait=True)
diff --git a/python/src/deltachat/types.py b/python/src/deltachat/types.py
index 3fe68c17..a2e7f072 100644
--- a/python/src/deltachat/types.py
+++ b/python/src/deltachat/types.py
@@ -1,7 +1,12 @@
+
+
+def property_with_doc(f):
+ return property(f, None, None, f.__doc__)
+
+
# copied over unmodified from
# https://github.com/devpi/devpi/blob/master/common/devpi_common/types.py
-
def cached_property(f):
"""returns a cached property that is calculated by function f"""
def get(self):
diff --git a/python/tox.ini b/python/tox.ini
index 40eaf318..362cec18 100644
--- a/python/tox.ini
+++ b/python/tox.ini
@@ -1,11 +1,10 @@
[tox]
-minversion = 2.0
-distshare = {homedir}/.tox/distshare
# make sure to update environment list in travis.yml and appveyor.yml
envlist =
py27
py35
lint
+ doc
[testenv]
commands = pytest {posargs:tests}
@@ -29,6 +28,17 @@ commands =
flake8 tests/
rst-lint --encoding 'utf-8' README.rst
+[testenv:doc]
+usedevelop = True
+deps =
+ sphinx
+
+whitelist_externals = make
+changedir = doc
+commands =
+ make html
+
+
[pytest]
python_files = tests/test_*.py
norecursedirs = .tox