Browse Source

Merge commit 'c643f1ff' into Release_2.1

PYADPT-110 2.1.1
heck 8 months ago
parent
commit
c9864de24e
65 changed files with 3880 additions and 2615 deletions
  1. +30
    -0
      .editorconfig
  2. +46
    -4
      .gitignore
  3. +0
    -28
      .hgignore
  4. +9
    -0
      AUTHORS.txt
  5. +66
    -25
      Makefile
  6. +10
    -2
      Makefile.conf
  7. +0
    -42
      README.md
  8. +22
    -0
      README.rst
  9. +19
    -0
      docs/Makefile
  10. +35
    -0
      docs/make.bat
  11. +12
    -0
      docs/source/api/pEp.rst
  12. +206
    -0
      docs/source/conf.py
  13. +21
    -0
      docs/source/index.rst
  14. +143
    -0
      docs/source/install.rst
  15. +7
    -0
      docs/source/software_using.rst
  16. +18
    -0
      pyproject.toml
  17. +24
    -4
      setup.cfg
  18. +23
    -34
      setup.py
  19. +30
    -19
      src/pEp/__init__.py
  20. +161
    -0
      src/pEp/_pEp/basic_api.cc
  21. +37
    -0
      src/pEp/_pEp/basic_api.hh
  22. +257
    -0
      src/pEp/_pEp/identity.cc
  23. +121
    -0
      src/pEp/_pEp/identity.hh
  24. +385
    -0
      src/pEp/_pEp/message.cc
  25. +194
    -0
      src/pEp/_pEp/message.hh
  26. +161
    -0
      src/pEp/_pEp/message_api.cc
  27. +30
    -0
      src/pEp/_pEp/message_api.hh
  28. +656
    -0
      src/pEp/_pEp/pEpmodule.cc
  29. +35
    -0
      src/pEp/_pEp/pEpmodule.hh
  30. +172
    -0
      src/pEp/_pEp/str_attr.cc
  31. +0
    -0
      src/pEp/_pEp/str_attr.hh
  32. +123
    -0
      src/pEp/_pEp/user_interface.cc
  33. +61
    -0
      src/pEp/_pEp/user_interface.hh
  34. +0
    -172
      src/pEp/native_pEp/basic_api.cc
  35. +0
    -30
      src/pEp/native_pEp/basic_api.hh
  36. +0
    -285
      src/pEp/native_pEp/identity.cc
  37. +0
    -102
      src/pEp/native_pEp/identity.hh
  38. +0
    -413
      src/pEp/native_pEp/message.cc
  39. +0
    -154
      src/pEp/native_pEp/message.hh
  40. +0
    -172
      src/pEp/native_pEp/message_api.cc
  41. +0
    -27
      src/pEp/native_pEp/message_api.hh
  42. +0
    -673
      src/pEp/native_pEp/pEpmodule.cc
  43. +0
    -28
      src/pEp/native_pEp/pEpmodule.hh
  44. +0
    -184
      src/pEp/native_pEp/str_attr.cc
  45. +0
    -130
      src/pEp/native_pEp/user_interface.cc
  46. +0
    -60
      src/pEp/native_pEp/user_interface.hh
  47. +0
    -27
      test/basic_doctest.py
  48. +3
    -0
      tests/__init__.py
  49. +64
    -0
      tests/conftest.py
  50. +12
    -0
      tests/constants.py
  51. +24
    -0
      tests/data/1A97F263D8319D6885F638C5AA81E1B5457A2B40.pub.asc
  52. +26
    -0
      tests/data/1A97F263D8319D6885F638C5AA81E1B5457A2B40.sec.asc
  53. +24
    -0
      tests/data/2D35731B9C754564CBAD15D2D18F7444594F2283.pub.asc
  54. +26
    -0
      tests/data/2D35731B9C754564CBAD15D2D18F7444594F2283.sec.asc
  55. +24
    -0
      tests/data/3E45175EE953EBBEB948F11A6A03DB2A17FB9D15.pub.asc
  56. +26
    -0
      tests/data/3E45175EE953EBBEB948F11A6A03DB2A17FB9D15.sec.asc
  57. +24
    -0
      tests/data/6A9835699EF1215F1558A496D9C1D4B0984094E5.pub.asc
  58. +26
    -0
      tests/data/6A9835699EF1215F1558A496D9C1D4B0984094E5.sec.asc
  59. +126
    -0
      tests/model.py
  60. +55
    -0
      tests/test_basic.py
  61. +107
    -0
      tests/test_identity.py
  62. +169
    -0
      tests/test_message.py
  63. +15
    -0
      tests/test_pep.py
  64. +13
    -0
      tests/utils.py
  65. +2
    -0
      utils/pEp

+ 30
- 0
.editorconfig View File

@ -0,0 +1,30 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
max_line_length = 300
tab_width = 4
# C++ Coding style
# I know these keys are unknown, regard it as documentation
[*.{cc,hh}]
indent_brace_style = K&R
curly_bracket_next_line = false
spaces_around_operators = true
spaces_around_brackets = true
[*.py]
indent_size = 4
[Makefile]
indent_style = tab
[*.ini]
indent_size = 2
[*.cfg]
indent_size = 2

+ 46
- 4
.gitignore View File

@ -1,10 +1,6 @@
syntax: glob
local.conf
*.swp
ws/
tags/
.DS_Store/
pEp.egg-info/
dist/
build/
@ -34,3 +30,49 @@ settings.json
docs/build/
.eggs/
.tox/
=======
# Build config
local.conf
# Python artifacts
/build/
/dist/
__pycache__/
*.py[co]
/.tox
.pytest_cache
/venv/
/_venv/
*.egg-info/
/*.egg-link
/*.egg
/.eggs/
/pip-wheel-metadata/
# file generated by setuptools_scm
/src/pEp/__version__.py
# Doc artifacts
/docs/build/
# Test artifacts
/test/Laptop
/test/Library
/test/Phone
/test/TestInbox
/test/Backup
/test/lib
/test/imap_settings.py
# Editor artifacts and config
.idea/
*~
.\#*
\#*#
*.swp
.idea
.spyproject
*.code-workspace
# platform artifacts
.DS_store

+ 0
- 28
.hgignore View File

@ -1,28 +0,0 @@
syntax: glob
local.conf
*.swp
ws
tags
.DS_Store
pEp.egg-info
dist
build
.pythonhist
.gnupg
.lldb
.pEp_management.db*
.python_history
__pycache__
test/Laptop
test/Library
test/Phone
test/TestInbox
test/Backup
test/lib
test/imap_settings.py
venv
launch.json
settings.json
# Default ignored files
.idea/

+ 9
- 0
AUTHORS.txt View File

@ -0,0 +1,9 @@
# This is the list of pEpPythonAdapter's significant contributors.
#
# This does not necessarily list everyone who has contributed code
# To see the full list of contributors, see the revision history in
# source control.
Volker Birk <vb@pep-project.org> (original author and maintainer)
Heck <heck@pep.foundation> (current maintainer and author)
Hartmut Goebel <h.goebel@crazy-compilers.com> (contributions)
juga <juga@pep.foundation> (contributions)

+ 66
- 25
Makefile View File

@ -1,9 +1,18 @@
include Makefile.conf
.PHONY: all dist dist-egg dist-whl install install-prefix install-sys compile clean devenv envtest
.PHONY: all compile compile-inplace dist dist-egg dist-whl install install-user venv envtest install-test test develop docs clean clean-all clean-docs
all: dist
# Build
# =====
compile:
python3 setup.py build_ext $(DEBUG_OPT) $(PREFIX_OPT)
compile-inplace:
python3 setup.py build_ext $(DEBUG_OPT) $(PREFIX_OPT) --inplace
# Packaging
# =========
# create wheel and egg package in dist/
dist: dist-whl dist-egg
@ -16,34 +25,66 @@ dist-egg: compile
python3 setup.py bdist_egg
# installs the package into the user home
install: compile
python3 setup.py install --force --user
# installs the package into PREFIX path
install-prefix: compile
python3 setup.py install --force $(PREFIX_OPT)
# Installation
# ============
# installs the package system wide
install-sys: compile
python3 setup.py install --force
install: compile
pip3 install .
# build the module into build/
compile:
python3 setup.py build_ext $(DEBUG_OPT) $(PREFIX_OPT)
# installs the package into your user home
install-user: compile
pip3 install . --user
clean:
rm -r $(BUILD_DIR)
rm -r $(DIST_DIR)
devenv:
# Envrionment
# ===========
# Creates and activates a new venv that has the LD_LIBRARY_PATH/DYLD_LIBRARY_PATH
# already set for the prefix specified in local.conf
# Only activates venv if already existing
venv:
python3 -m venv $(VENV_DIR)
LD_LIBRARY_PATH=$(PREFIX)/lib \
DYLD_LIBRARY_PATH=$(PREFIX)/lib \
PYTHONPATH=$PYTHONPATH:`pwd`/build/lib.linux-x86_64-3.7:\
PYTHONPATH=$PYTHONPATH:`pwd`/build/lib.macosx-10.9-x86_64-3.8:\
`pwd`/src \
bash -l
bash --rcfile $(VENV_DIR)/bin/activate
# Tests if the current environment is able to load the pEp module
envtest:
python3 -c 'import pEp'
python3 -c 'import pEp'
# Test
# ====
# Use these targets only in venv created with 'make venv'
install-test: compile
pip3 install .[test]
# TODO: maybe use setup.py test?
# --forked, because every test needs a separate process, see PYADPT-100
test:
pytest
# Development
develop: compile
pip install -e .
# Documentation
# =============
docs: compile-inplace
make html -C docs/
# Housekeeping
# ============
clean-all: clean
rm -rf $(VENV_DIR)
clean: clean-docs
rm -rf $(BUILD_DIR)
rm -rf $(DIST_DIR)
rm -rf $(PYTHON_ARTIFACTS)
rm -rf $(VERSION_FILE)
rm -rf $(BUILD_INPLACE)
clean-docs:
make clean -C docs/

+ 10
- 2
Makefile.conf View File

@ -3,10 +3,16 @@ HERE:=$(dir $(lastword $(MAKEFILE_LIST)))
# Constants
BUILD_DIR = ./build
DIST_DIR = ./dist
VERSION_FILE = ./src/pEp/__version__.py
BUILD_INPLACE = ./src/pEp/_pEp.cpython-38-darwin.so
PYTHON_ARTIFACTS += ./.eggs
PYTHON_ARTIFACTS += ./src/pEp.egg-info
PYTHON_ARTIFACTS += ./.pytest_cache
VENV_DIR = ./venv
# Build config Defaults
DEBUG=0
PREFIX?=$(HOME)
PREFIX=
######### Overrides #########
-include $(HERE)local.conf
@ -15,4 +21,6 @@ ifeq ($(DEBUG),1)
DEBUG_OPT+=--debug
endif
PREFIX_OPT += --prefix=$(PREFIX)
ifneq ($(PREFIX),)
PREFIX_OPT += --prefix=$(PREFIX)
endif

+ 0
- 42
README.md View File

@ -1,42 +0,0 @@
# pEpPythonAdapter
## Build Insttructions
These build instructions should work on:
* Linux (Verified 26.4.20 - heck)
* MacOS (Verified 26.4.20 - heck)
* Windows
### Build
To build against system wide pEp installation (libs/includes)
```bash
python3 setup.py build_ext
```
To build against a pEp installation in your home dir (libs/includes):
```bash
python3 setup.py build_ext --local
```
To build against a pEp installation in a custom installation root (libs/includes)
```bash
python3 setup.py build_ext --prefix=<path_to_your_install_root>
```
### Install
To install the extension module system wide, as root, run:
```bash
python3 setup.py install
```
To install the extension module into you home dir
```bash
python3 setup.py install --user
```
To install the extension module into a custom destination
```bash
python3 setup.py install --prefix=<custom_destination_root>
```
Attention: The ~ (tilde) does not get expanded, but env vars work ($HOME).

+ 22
- 0
README.rst View File

@ -0,0 +1,22 @@
pEpPythonAdapter
================
Python adapter for the `pEpEngine <https://pep.foundation/dev/repos/pEpEngine/>`_
Documentation
-------------
Please find the documentation in the ``docs`` directory.
Issues
------
If you are not pEp internal, please send a mail to: heck@pep.foundation
If you are pEp internal, please open a ticket in our `jira bugtracker <https://pep.foundation/jira/projects/PYADPT/)`_ and for any questions, you are always welcome on #adapter>.
License
-------
|GNU AFFERO GENERAL PUBLIC LICENSE
|Version 3, 19 November 2007
|See LICENSE.txt

+ 19
- 0
docs/Makefile View File

@ -0,0 +1,19 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
SOURCEDIR = source
BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

+ 35
- 0
docs/make.bat View File

@ -0,0 +1,35 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set BUILDDIR=build
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
:end
popd

+ 12
- 0
docs/source/api/pEp.rst View File

@ -0,0 +1,12 @@
pEp package
===========
Module contents
---------------
.. automodule:: pEp
:members:
:imported-members:
:undoc-members:
:show-inheritance:

+ 206
- 0
docs/source/conf.py View File

@ -0,0 +1,206 @@
# -*- coding: utf-8 -*-
#
# Configuration file for the Sphinx documentation builder.
#
# This file does only contain a selection of the most common options. For a
# full list see the documentation:
# http://www.sphinx-doc.org/en/master/config
# -- Path setup --------------------------------------------------------------
# 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.
import os
import sys
sys.path.insert(0, os.path.abspath('../../src'))
# -- Project information -----------------------------------------------------
project = "pEpPythonAdapter"
copyright = "2020, Volker Birk, heck, Hartmut Goebel, juga"
author = "Volker Birk, heck, Hartmut Goebel, juga"
import pEp
# The full version, including alpha/beta/rc tags
release = pEp.__version__
# The short X.Y version
version = ".".join(release.split(".")[:2])
# DEBUG
print("release:", release)
print("version:", version)
# -- 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.doctest",
"sphinx.ext.intersphinx",
"sphinx.ext.todo",
"sphinx.ext.coverage",
"sphinx.ext.viewcode",
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = ".rst"
# The master toctree document.
master_doc = "index"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = None
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = "nature"
# 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 = {}
# 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"]
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
#
# The default sidebars (for documents that don't match any pattern) are
# defined by theme itself. Builtin themes are using these templates by
# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
# 'searchbox.html']``.
#
# html_sidebars = {}
# -- Options for HTMLHelp output ---------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = "pEpPythonAdapterdoc"
# -- 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': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(
master_doc,
"pEpPythonAdapter.tex",
"pEpPythonAdapter Documentation",
"2020, Volker Birk, heck, juga",
"manual",
)
]
# -- Options for manual page output ------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(
master_doc,
"peppythonadapter",
"pEpPythonAdapter Documentation",
[author],
1,
)
]
# -- 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 = [
(
master_doc,
"pEpPythonAdapter",
"pEpPythonAdapter Documentation",
author,
"pEpPythonAdapter",
"One line description of project.",
"Miscellaneous",
)
]
# -- Options for Epub output -------------------------------------------------
# Bibliographic Dublin Core info.
epub_title = project
# The unique identifier of the text. This can be a ISBN number
# or the project homepage.
#
# epub_identifier = ''
# A unique identification for the text.
#
# epub_uid = ''
# A list of files that should not be packed into the epub file.
epub_exclude_files = ["search.html"]
# -- Extension configuration -------------------------------------------------
# -- Options for intersphinx extension ---------------------------------------
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {"https://docs.python.org/": None}
# -- Options for todo extension ----------------------------------------------
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = True

+ 21
- 0
docs/source/index.rst View File

@ -0,0 +1,21 @@
.. pEpPythonAdapter documentation master file, created by
sphinx-quickstart on Wed Oct 21 12:35:11 2020.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to pEpPythonAdapter's documentation!
============================================
.. toctree::
:maxdepth: 2
:caption: Contents:
install
software_using
api/pEp
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

+ 143
- 0
docs/source/install.rst View File

@ -0,0 +1,143 @@
Installation
============
Requirements
------------
In order to build, use or install this extension module, you need to have some
system dependencies already installed:
* pEp-base (sequoia, libetpan, asn1c, yml2, pEpEngine, libpEpAdapter)
* boost-python
These `build instructions <https://dev.pep.foundation/Common%20Adapter%20Documentation/Adapter_Build_Instructions>`_ will get you all setup.
Additionally, there is a `build script <http://pep-security.lu/gitlab/juga/Internal-Deployment/-/blob/master/build-pep-stack.sh>`_
that executes these build instructions automatically (Debian and MacOS):
.. Note:: If you dont install pEp-base system wide, but under a prefix, like /home/foo/local/,
you will need to have LD_LIBARY_PATH/DYLD_LIBRARY_PATH adjusted for all the following operations.
Build
-----
The pEpPythonAdapter is a python extension module that contains C/C++ code that needs to be
compiled first. So, before any use or installation, the module needs to be built.
Build config
~~~~~~~~~~~~
Create a local build config by creating a 'local.conf' file. There is a 'local.conf.example' describing
all the build options. You can use this as a template.
``cp local.conf.example local.conf``
If you have pEp-base installed under a custom prefix (e.g. /home/foo/local) it is important
that you specify "PREFIX".
Build
~~~~~
To build the module just type:
``make``
This will compile the C/C++ parts of the module and create the python packages in the .egg and .wheel format
in the dist/ dir.
Virtualenv
----------
We recommend using a venv to work on/with the pEpPythonAdapter.
There is a convenience make target that will create and activate a venv that already has the LD_LIBRARY_PATH
or DYLD_LIBRARY_PATH set according to your ``local.conf``.
If the venv does not exist yet it will be created and activated.
If the venv already exists it will only be activated.
``make venv``
After that, to install the pEp module into the venv, do:
``make install``
Installation
------------
You can install the module in the in the following ways.
To install the extension module system wide or into a venv, use:
``make install``
To install the extension module into your home dir, use:
``make install-user``
Test
----
To run the whole testsuite you need to first create/activate the venv:
``make venv``
then install the test-dependencies:
``make install-test``
And finally run the test-suite:
``make test``
Module Development
------------------
To develop on the module itself, first of all create and activate a venv:
``make venv``
Then, in the venv install the module in development mode.
``make develop``
While developing there are two levels of changes. Changes to the python part of the module (pEp), and
changes to the C/C++ part of the module (_pEp). If you change just python code, the changes are effective immediately.
If you do changes to the C/C++ part you need to issue ``make develop`` again, to recompile the extension and install
the new binary (.so/.dylib) of the module into the venv.
Documentation
-------------
The documentation of the pEpPythonAdapter uses `Sphinx <https://www.sphinx-doc.org/>`_
Refer to the `Sphinx installation instructions <https://www.sphinx-doc.org/en/master/usage/installation.html>`_ to install it.
To generate the documentation in the HTML format, there is a make target "docs"
But first, you need to create/activate the venv or set the LD_LIBRARY_PATH manually.
``make venv``
``make docs``
You can see the generated HTML documentation in a browser opening the directory
`docs/build/html`.
Housekeeping
------------
There are the following "clean" targets.
To delete all the generated documentation, run:
``make docs-clean``
To delete all the "derived" files including eggs, wheels, shared libs, build files and caches, run:
``make clean``
To delete all of make clean plus the venv (should equal a complete reset), run:
``make clean-all``
Docker
------
If you know how to use docker, you can avoid having to install all
the dependencies using the image
https://registry.gitlab.com/juga0/pepdocker/peppythonadapter.
.. Note:: This docker image is not officially maintained and it exists only
until there is an official Debian one.

+ 7
- 0
docs/source/software_using.rst View File

@ -0,0 +1,7 @@
Software using pEpPythonAdapter
===============================
- `pEpProxy <https://pep-security.lu/gitlab/marcel/pepproxy>`_
- `command-line-tool <https://pep-security.lu/gitlab/enterprise-editon/command-line-tool>`_
- `pEpPythonMixnet <https://gitea.pep.foundation/pEp.foundation/pEpPythonMixnet>`_
- `pEpSimulator <URL???>`_

+ 18
- 0
pyproject.toml View File

@ -0,0 +1,18 @@
[build-system]
# Preparing for PEP-517/PEP-518, but not in effect yet.
# These requires are not effective yet, setup.cfg is.
requires =[
"setuptools >=39.2.0",
"setuptools_scm >= 4.1.2",
"wheel >= 0.35.1" ]
build-backend = "setuptools.build_meta"
[tool.pytest.ini_options]
minversion = "6.0"
addopts = "-rP --forked"
testpaths = [
"tests",
]

+ 24
- 4
setup.cfg View File

@ -1,16 +1,18 @@
[metadata]
name = pEp
version = 2.1.0-RC2
url = https://pep.foundation
author = Volker Birk
download_url =
ext_package = pEp
author = Volker Birk, heck, Hartmut Goebel, juga
author_email = vb@pep-project.org
maintainer = Matthias Heckmann
maintainer = heck
maintainer_email = heck@pep.foundation
description = p≡p for Python
long_description = file: README.md
keywords = pEp, crypto, end-to-end, python adapter, key management, high-level
license = GNU Affero General Public License
license_files = LICENSE
license_files = LICENSE.txt
platforms = linux, macOs
classifiers =
Intended Audience :: Developers
Topic :: Utilities
@ -21,3 +23,21 @@ classifiers =
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Development Status :: 3 - Alpha
[options]
zip_safe = false
include_package_data = true
python_requires = >= 3.6
test_suite = tests
install_requires =
# deprecated/redundant with pyproject.toml, but lets keep both ways around for now
setup_requires =
setuptools >=39.2.0
setuptools_scm >= 4.1.2
wheel >= 0.35.1
[options.extras_require]
# To install these dependencies, run pip install .[test]
test =
pytest
pytest-forked
doc = sphinx

+ 23
- 34
setup.py View File

@ -27,18 +27,16 @@ def pEpLog(*msg):
msgstr += str(m)
msgstr += separator
func = inspect.currentframe().f_back.f_code
print(func.co_filename + " : " + func.co_name + " : " + msgstr)
print(func.co_filename + " : " + func.co_name + " : " + msgstr)
class BuildExtCommand(build_ext):
class BuildExtCommand(build_ext):
user_options = build_ext.user_options + [
('local', None, 'Use local pEp install in HOME/USERPROFILE for libs/includes'),
('prefix=', None, 'Use local pEp install in prefix for libs/includes'),
('prefix=', None, 'Use pEp-base installation in prefix (libs/includes)'),
]
def initialize_options(self):
build_ext.initialize_options(self)
self.local = None != environ.get('PER_USER_DIRECTORY')
self.prefix = getattr(self, "prefix=", None)
def windowsGetInstallLocation(self):
@ -139,7 +137,6 @@ class BuildExtCommand(build_ext):
def finalize_options(self):
build_ext.finalize_options(self)
pEpLog("local: ", self.local)
pEpLog("prefix: ", self.prefix)
pEpLog("sys.platform: ", sys.platform)
@ -162,18 +159,11 @@ class BuildExtCommand(build_ext):
includes = []
libdirs = []
# Append home-dir
if self.local:
pEpLog("local mode")
home_include=[ join(home, 'include') ]
home_libdirs=[ join(home, 'lib') ]
includes += home_include
libdirs += home_libdirs
# Append prefix-dir
if self.prefix:
prefix_include=[ join(self.prefix, 'include') ]
prefix_libdirs=[ join(self.prefix, 'lib') ]
prefix_include = [join(self.prefix, 'include')]
prefix_libdirs = [join(self.prefix, 'lib')]
includes += prefix_include
libdirs += prefix_libdirs
@ -206,33 +196,32 @@ if sys.platform == 'win32':
if sys.version_info[0] < 3:
FileNotFoundError = EnvironmentError
module_pEp = Extension(
'native_pEp',
sources = [
'src/pEp/native_pEp/pEpmodule.cc',
'src/pEp/native_pEp/basic_api.cc',
'src/pEp/native_pEp/identity.cc',
'src/pEp/native_pEp/message.cc',
'src/pEp/native_pEp/message_api.cc',
'src/pEp/native_pEp/str_attr.cc',
# 'src/pEp/native_pEp/user_interface.cc',
],
'pEp._pEp',
sources=[
'src/pEp/_pEp/pEpmodule.cc',
'src/pEp/_pEp/basic_api.cc',
'src/pEp/_pEp/identity.cc',
'src/pEp/_pEp/message.cc',
'src/pEp/_pEp/message_api.cc',
'src/pEp/_pEp/str_attr.cc',
# 'src/pEp/_pEp/user_interface.cc',
],
)
# "MAIN" Function
setup(
name='pEp',
version='2.1.0-RC2',
description='p≡p for Python',
author="Volker Birk",
author_email="vb@pep-project.org",
maintainer="Heck",
maintainer_email="heck@pep.foundation",
package_dir={'':'src'},
package_dir={'': 'src'},
packages=['pEp'],
ext_modules=[module_pEp],
cmdclass={
'build_ext': BuildExtCommand,
},
# While not using a pyproject.toml, support setuptools_scm setup.cfg usage,
# see https://github.com/pypa/setuptools_scm/#setupcfg-usage
use_scm_version={
'write_to': 'src/pEp/__version__.py',
#TODO: fallback_version does not seem to work in case os missing tag
'fallback_version' : '0.0.0-RC0'
}
)

+ 30
- 19
src/pEp/__init__.py View File

@ -1,20 +1,39 @@
# -*- coding: UTF-8 -*-
# pEp package
# This file is being exectued upon 'import pEp'
#
# __all__ could be used to limit the symbols exported when using from <pkg> import *
# The names that are in _pEp that do not begin with an underscore, will be be imported into, and "re-exported" from this module.
# They are defined in boost-python/C++, and are directly part of the pEpPythonAdapter API
# The names that are in _pEp that DO begin with an underscore, will not be imported into this module, but will be accessible like _pEp._underscore_function().
# They are not directly part of the pEpPythonAdapter API, and are meant to be wrapped in this module.
# Example:
# def underscore_function():
# _pEp._underscore_function()
# Import all symbols EXCEPT the ones beginning with underscore into the current namespace
from native_pEp import *
# TODO: inter-pkg ref to make sure which native_pEp in sys.path gets loaded
# like: pEp.native_pEp
# import the module
import native_pEp
# __all__ could be used to limit the symbols exported when using from <pkg> import *
try:
from .__version__ import version as __version__
except ImportError:
import warnings
warnings.warn("Error loading build-time defined __version__.py, trying setuptools now...")
try:
import setuptools_scm
__version__ = setuptools_scm.get_version()
del setuptools_scm
except Exception:
warnings.warn('could not determine %s package version' % __name__)
__version__ = '0.0.dev0+unknown'
# Imports all symbols EXCEPT the ones beginning with underscore
from ._pEp import *
# import the native module into the current namespace because we also need to access the names beginning
# with an underscore (of _pEp), but we dont want to import them into this module
import pEp._pEp
# Executed on module import
def init():
print(init, "called")
native_pEp._init_after_main_module()
_pEp._init_after_main_module()
def message_to_send(msg):
@ -41,12 +60,4 @@ def notify_handshake(me, partner, signal):
print("overwrite this method")
# Executed when run as script
def main():
print("I am being run as a script")
# MAIN
if __name__ == "__main__":
main()
else:
init()
init()

+ 161
- 0
src/pEp/_pEp/basic_api.cc View File

@ -0,0 +1,161 @@
// This file is under GNU Affero General Public License 3.0
// see LICENSE.txt
// System
#include <sstream>
// Engine
#include <pEp/keymanagement.h>
#include <pEp/message_api.h>
#include <pEp/Adapter.hh>
// local
#include "basic_api.hh"
namespace pEp {
namespace PythonAdapter {
using namespace std;
void update_identity(Identity &ident) {
if (ident.address() == "")
throw invalid_argument("address needed");
if (ident.user_id() == PEP_OWN_USERID)
throw runtime_error("update_identity: '"
PEP_OWN_USERID
"' may only be used for own identities");
PEP_STATUS status = update_identity(Adapter::session(), ident);
_throw_status(status);
}
void myself(Identity &ident) {
if (ident.address() == "")
throw invalid_argument("address needed");
if (ident.username() == "")
throw invalid_argument("username needed");
if (ident.user_id() == "")
ident.user_id(ident.address());
PEP_STATUS status = myself(Adapter::session(), ident);
_throw_status(status);
}
string _trustwords(Identity me, Identity partner, string lang, bool full) {
if (me.fpr() == "" || partner.fpr() == "")
throw invalid_argument("fingerprint needed in Identities");
if (lang == "" && me.lang() == partner.lang())
lang = me.lang();
char *words = NULL;
size_t size = 0;
PEP_STATUS status = get_trustwords(Adapter::session(), me, partner,
lang.c_str(), &words, &size, full);
_throw_status(status);
return words;
}
void trust_personal_key(Identity ident) {
if (ident.fpr() == "")
throw invalid_argument("fingerprint needed in Identities");
if (ident.user_id() == "")
throw invalid_argument("user_id must be provided");
PEP_STATUS status = trust_personal_key(Adapter::session(), ident);
_throw_status(status);
}
void set_identity_flags(Identity ident, identity_flags_t flags) {
if (ident.address() == "")
throw invalid_argument("address needed");
if (ident.user_id() == "")
throw invalid_argument("user_id needed");
PEP_STATUS status = set_identity_flags(Adapter::session(), ident, flags);
_throw_status(status);
}
void unset_identity_flags(Identity ident, identity_flags_t flags) {
if (ident.address() == "")
throw invalid_argument("address needed");
if (ident.user_id() == "")
throw invalid_argument("user_id needed");
PEP_STATUS status = unset_identity_flags(Adapter::session(), ident, flags);
_throw_status(status);
}
void key_reset_trust(Identity ident) {
if (ident.fpr() == "")
throw invalid_argument("fpr needed");
if (ident.address() == "")
throw invalid_argument("address needed");
if (ident.user_id() == "")
throw invalid_argument("user_id needed");
PEP_STATUS status = key_reset_trust(Adapter::session(), ident);
_throw_status(status);
}
boost::python::list import_key(string key_data) {
::identity_list *private_keys = NULL;
PEP_STATUS status = ::import_key(Adapter::session(), key_data.c_str(), key_data.size(), &private_keys);
if (status && status != PEP_KEY_IMPORTED)
_throw_status(status);
auto result = boost::python::list();
for (::identity_list *il = private_keys; il && il->ident; il = il->next) {
::pEp_identity *ident = ::identity_dup(il->ident);
if (!ident) {
free_identity_list(private_keys);
throw bad_alloc();
}
result.append(Identity(ident));
}
free_identity_list(private_keys);
return result;
}
string export_key(Identity ident) {
PEP_STATUS status = PEP_STATUS_OK;
char *key_data = NULL;
size_t size;
status = ::export_key(Adapter::session(), ident.fpr().c_str(), &key_data, &size);
_throw_status(status);
return key_data;
}
string export_secret_key(Identity ident) {
PEP_STATUS status = PEP_STATUS_OK;
char *key_data = NULL;
size_t size;
status = ::export_secret_key(Adapter::session(), ident.fpr().c_str(), &key_data, &size);
_throw_status(status);
return key_data;
}
void set_own_key(Identity &ident, string fpr) {
if (ident.address() == "")
throw invalid_argument("address needed");
if (ident.username() == "")
throw invalid_argument("username needed");
if (ident.user_id() == "")
throw invalid_argument("user_id needed");
if (fpr == "")
throw invalid_argument("fpr needed");
const char *fpr_c = fpr.c_str();
PEP_STATUS status = set_own_key(Adapter::session(), ident, fpr_c);
_throw_status(status);
}
} // namespace PythonAdapter
} // namespace pEp

+ 37
- 0
src/pEp/_pEp/basic_api.hh View File

@ -0,0 +1,37 @@
// This file is under GNU Affero General Public License 3.0
// see LICENSE.txt
#ifndef BASIC_API_HH
#define BASIC_API_HH
#include "pEpmodule.hh"
namespace pEp {
namespace PythonAdapter {
void update_identity(Identity &ident);
void myself(Identity &ident);
string _trustwords(Identity me, Identity partner, string lang, bool full);
void trust_personal_key(Identity ident);
void set_identity_flags(Identity ident, identity_flags_t flags);
void unset_identity_flags(Identity ident, identity_flags_t flags);
void key_reset_trust(Identity ident);
boost::python::list import_key(string key_data);
string export_key(Identity ident);
string export_secret_key(Identity ident);
void set_own_key(Identity &ident, string fpr);
} /* namespace PythonAdapter */
} /* namespace pEp */
#endif /* BASIC_API_HH */

+ 257
- 0
src/pEp/_pEp/identity.cc View File

@ -0,0 +1,257 @@
// This file is under GNU Affero General Public License 3.0
// see LICENSE.txt
// System
#include <typeinfo>
#include <sstream>
// Engine
#include <pEp/identity_list.h>
#include <pEp/keymanagement.h>
#include <pEp/key_reset.h>
// local
#include "identity.hh"
#include "pEpmodule.hh"
#include "basic_api.hh"
#include "message_api.hh"
namespace pEp {
namespace PythonAdapter {
using namespace std;
using namespace boost::python;
Identity::Identity(string address, string username, string user_id,
string fpr, int comm_type, string lang, identity_flags_t flags)
: _ident(new_identity(address.c_str(), fpr.c_str(), user_id.c_str(),
username.c_str()), &::free_identity) {
if (!_ident)
throw bad_alloc();
_ident->comm_type = (PEP_comm_type) comm_type;
_ident->flags = (identity_flags_t) flags;
this->lang(lang);
}
Identity::Identity(const Identity &second)
: _ident(second._ident) {
}
Identity::Identity(pEp_identity *ident)
: _ident(ident, &::free_identity) {
}
Identity::~Identity() {
}
Identity::operator pEp_identity *() {
return _ident.get();
}
Identity::operator const pEp_identity *() const {
return _ident.get();
}
string Identity::_repr() {
stringstream build;
build << "Identity(";
string address;
if (_ident->address)
address = string(_ident->address);
build << repr(address) << ", ";
string username;
if (_ident->username)
username = string(_ident->username);
build << repr(username) << ", ";
string user_id;
if (_ident->user_id)
user_id = string(_ident->user_id);
build << repr(user_id) << ", ";
string fpr;
if (_ident->fpr)
fpr = string(_ident->fpr);
build << repr(fpr) << ", ";
build << (int) _ident->comm_type << ", ";
string lang = _ident->lang;
build << repr(lang) << ")";
return build.str();
}
string Identity::_str() {
if (!(_ident->address && _ident->address[0]))
return "";
if (!(_ident->username && _ident->username[0]))
return _ident->address;
return string(_ident->username) + " <" + _ident->address + ">";
}
void Identity::username(string value) {
if (value.length() && value.length() < 5)
throw length_error("username must be at least 5 characters");
str_attr(_ident->username, value);
}
void Identity::lang(string value) {
if (value == "")
memset(_ident->lang, 0, 3);
else if (value.length() != 2)
throw length_error("length of lang must be 2");
else
memcpy(_ident->lang, value.c_str(), 3);
}
string Identity::lang() {
return _ident->lang;
}
int Identity::rating() {
if (!(_ident->address))
throw invalid_argument("address must be given");
PEP_rating rating = PEP_rating_undefined;
PEP_STATUS status = ::identity_rating(Adapter::session(), _ident.get(), &rating);
_throw_status(status);
return (int) rating;
}
PEP_color Identity::color() {
return _color(rating());
}
Identity Identity::copy() {
pEp_identity *dup = ::identity_dup(*this);
if (!dup)
throw bad_alloc();
return Identity(dup);
}
Identity Identity::deepcopy(dict &) {
return copy();
}
void Identity::update() {
update_identity(*this);
}
void Identity::key_reset(string fpr) {
PEP_STATUS status = ::key_reset_identity(Adapter::session(), *this,
fpr != "" ? fpr.c_str() : nullptr);
_throw_status(status);
}
void Identity::key_mistrusted() {
PEP_STATUS status = ::key_mistrusted(Adapter::session(), *this);
_throw_status(status);
}
bool Identity::is_pEp_user() {
bool result;
PEP_STATUS status = ::is_pEp_user(Adapter::session(), *this, &result);
_throw_status(status);
return result;
}
void Identity::enable_for_sync() {
PEP_STATUS status = ::enable_identity_for_sync(Adapter::session(), *this);
_throw_status(status);
}
void Identity::disable_for_sync() {
PEP_STATUS status = ::disable_identity_for_sync(Adapter::session(), *this);
_throw_status(status);
}
// Myself::Myself(string address, string username, string user_id, string lang)
// : Identity(address, username, user_id, "", 0, lang) {
// if (!(address.length() && username.length()))
// throw invalid_argument("address and username must be set");
// if (lang.length() && lang.length() != 2)
// throw length_error("lang must be an ISO 639-1 language code or empty");
//
// // FIXME: should set .me
// // _ident->me = true;
// if (user_id.length())
// throw runtime_error("user_id feature not yet implemented for Myself");
// }
// void Myself::update() {
// pEp::PythonAdapter::myself(*this);
// }
Identity identity_attr(pEp_identity *&ident) {
if (!ident)
throw out_of_range("no identity assigned");
pEp_identity *_dup = ::identity_dup(ident);
if (!_dup)
throw bad_alloc();
Identity _ident(_dup);
return _ident;
}
void identity_attr(pEp_identity *&ident, object value) {
Identity &_ident = extract<Identity &>(value);
pEp_identity *_dup = ::identity_dup(_ident);
if (!_dup)
throw bad_alloc();
PEP_STATUS status = ::update_identity(Adapter::session(), _dup);
_throw_status(status);
::free_identity(ident);
ident = _dup;
}
boost::python::list identitylist_attr(identity_list *&il) {
boost::python::list result;
for (identity_list *_il = il; _il && _il->ident; _il = _il->next) {
pEp_identity *ident = ::identity_dup(_il->ident);
if (!ident)
throw bad_alloc();
result.append(object(Identity(ident)));
}
return result;
}
void identitylist_attr(identity_list *&il, boost::python::list value) {
identity_list *_il = ::new_identity_list(NULL);
if (!_il)
throw bad_alloc();
identity_list *_i = _il;
for (int i = 0; i < len(value); i++) {
extract < Identity & > extract_identity(value[i]);
if (!extract_identity.check()) {
free_identity_list(_il);
}
pEp_identity *_ident = extract_identity();
pEp_identity *_dup = ::identity_dup(_ident);
if (!_dup) {
::free_identity_list(_il);
throw bad_alloc();
}
PEP_STATUS status = ::update_identity(Adapter::session(), _dup);
if (status != PEP_STATUS_OK) {
::free_identity_list(_il);
_throw_status(status);
}
_i = ::identity_list_add(_i, _dup);
if (!_i) {
::free_identity_list(_il);
throw bad_alloc();
}
}
::free_identity_list(il);
il = _il;
}
} // namespace PythonAdapter
} // namespace pEp

+ 121
- 0
src/pEp/_pEp/identity.hh View File

@ -0,0 +1,121 @@
// This file is under GNU Affero General Public License 3.0
// see LICENSE.txt
#ifndef IDENTITY_HH
#define IDENTITY_HH
// System
#include <boost/python.hpp>
#include <string>
#include <memory>
#include <cstddef>
// Engine
#include <pEp/pEpEngine.h>
#include <pEp/message_api.h>
//libpEpAdapter
#include "pEp/Adapter.hh"
// local
#include "str_attr.hh"
namespace pEp {
namespace PythonAdapter {
using std::string;
using std::shared_ptr;
// Identity is owning a pEp_identity
class Identity {
protected:
shared_ptr <pEp_identity> _ident;
public:
Identity(string address = "", string username = "",
string user_id = "", string fpr = "", int comm_type = 0,
string lang = "", identity_flags_t flags = 0);
Identity(const Identity &second);
Identity(pEp_identity *ident);
virtual ~Identity();
operator pEp_identity *();
operator const pEp_identity *() const;
string _repr();
string _str();
string address() { return str_attr(_ident->address); }
void address(string value) { str_attr(_ident->address, value); }
string fpr() { return str_attr(_ident->fpr); }
void fpr(string value) { str_attr(_ident->fpr, value); }
string user_id() { return str_attr(_ident->user_id); }
void user_id(string value) { str_attr(_ident->user_id, value); }
string username() { return str_attr(_ident->username); }
void username(string value);
PEP_comm_type comm_type() { return _ident->comm_type; }
void comm_type(PEP_comm_type value) { _ident->comm_type = value; };
std::string lang();
void lang(std::string value);
identity_flags_t flags() { return _ident->flags; }
void flags(identity_flags_t flags) { _ident->flags = flags; }
int rating();
PEP_color color();
Identity copy();
Identity deepcopy(dict &memo);
virtual void update();
void key_reset(string fpr = "");
void key_mistrusted();
bool is_pEp_user();
void enable_for_sync();
void disable_for_sync();
};
// class Myself : public Identity {
// public:
// Myself(string address, string username, string user_id = "", string lang = "");
//
// virtual void update();
// };
Identity identity_attr(pEp_identity *&ident);
void identity_attr(pEp_identity *&ident, object value);
boost::python::list identitylist_attr(identity_list *&il);
void identitylist_attr(identity_list *&il, boost::python::list value);
} // namespace PythonAdapter
} // namespace pEp
#endif /* IDENTITY_HH */

+ 385
- 0
src/pEp/_pEp/message.cc View File

@ -0,0 +1,385 @@
// This file is under GNU Affero General Public License 3.0
// see LICENSE.txt
// System
#include <cstdlib>
#include <cstring>
#include <stdexcept>
#include <sstream>
#include <vector>
#include <Python.h>
// Engine
#include <pEp/mime.h>
#include <pEp/keymanagement.h>
#include <pEp/message_api.h>
// local
#include "message.hh"
#include "message_api.hh"
namespace pEp {
namespace PythonAdapter {
using namespace std;
using namespace boost::python;
Message::Blob::Blob(bloblist_t *bl, bool chained) :
_bl(bl), part_of_chain(chained) {
if (!_bl)
throw bad_alloc();
}
Message::Blob::Blob(object data, string mime_type, string filename) :
_bl(new_bloblist(NULL, 0, NULL, NULL)), part_of_chain(false) {
if (!_bl)
throw bad_alloc();
Py_buffer src;
int result = PyObject_GetBuffer(data.ptr(), &src, PyBUF_CONTIG_RO);
if (result)
throw invalid_argument("need a contiguous buffer to read");
char *mem = (char *) malloc(src.len);
if (!mem) {
PyBuffer_Release(&src);
throw bad_alloc();
}
memcpy(mem, src.buf, src.len);
free(_bl->value);
_bl->size = src.len;
_bl->value = mem;
PyBuffer_Release(&src);
this->mime_type(mime_type);
this->filename(filename);
}
Message::Blob::Blob(const Message::Blob &second) :
_bl(second._bl), part_of_chain(true) {
}
Message::Blob::~Blob() {
if (!part_of_chain) {
free(_bl->value);
free(_bl);
}
}
string Message::Blob::_repr() {
stringstream build;
build << "Blob(";
if (!_bl) {
build << "b'', '', ''";
} else {
build << "bytes(" << _bl->size << "), ";
string mime_type;
if (_bl->mime_type)
mime_type = string(_bl->mime_type);
string filename;
if (_bl->filename)