From 9e18f45a80f12ce9affdd06b78068b7fdc020a6d Mon Sep 17 00:00:00 2001 From: juga Date: Fri, 24 Jan 2020 13:56:54 +0000 Subject: [PATCH 01/84] Add pytest unit tests so that they all can run with just one pytest command, they can be integrated with python test command and with tox and they can be run separately with different python versions. --- setup.py | 3 + tests/__init__.py | 0 tests/conftest.py | 45 +++++++++ tests/constants.py | 26 +++++ tests/data/README.md | 2 + tests/data/alice@openpgp.example.pub.asc | 14 +++ tests/data/alice@openpgp.example.sec.asc | 16 +++ tests/data/bob@openpgp.example.pub.asc | 42 ++++++++ tests/data/bob@openpgp.example.sec.asc | 82 +++++++++++++++ tests/test_identity.py | 121 +++++++++++++++++++++++ tests/test_message.py | 71 +++++++++++++ tox.ini | 23 +++++ 12 files changed, 445 insertions(+) create mode 100644 tests/__init__.py create mode 100644 tests/conftest.py create mode 100644 tests/constants.py create mode 100644 tests/data/README.md create mode 100644 tests/data/alice@openpgp.example.pub.asc create mode 100644 tests/data/alice@openpgp.example.sec.asc create mode 100644 tests/data/bob@openpgp.example.pub.asc create mode 100644 tests/data/bob@openpgp.example.sec.asc create mode 100644 tests/test_identity.py create mode 100644 tests/test_message.py create mode 100644 tox.ini diff --git a/setup.py b/setup.py index 4c3db47..c208f65 100644 --- a/setup.py +++ b/setup.py @@ -282,4 +282,7 @@ setup( cmdclass={ 'build_ext': BuildExtCommand, }, + extras_require={ + 'test': ['pytest'], + }, ) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..1aa45d7 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,45 @@ +"""pytest configuration for the unit tests.""" +import pytest + + +@pytest.fixture() +def datadir(request): + """Get, read, open test files from the tests "data" directory.""" + class D: + def __init__(self, basepath): + self.basepath = basepath + + def open(self, name, mode="r"): + return self.basepath.join(name).open(mode) + + def join(self, name): + return self.basepath.join(name).strpath + + def read(self, name): + with self.open(name, "r") as f: + return f.read() + + def readlines(self, name): + with self.open(name, "r") as f: + return f.readlines() + return D(request.fspath.dirpath("data")) + + +@pytest.fixture(scope='function') +def tmpdir(tmpdir_factory, request): + """Create a tmp dir for the tests""" + base = str(hash(request.node.nodeid))[:3] + bn = tmpdir_factory.mktemp(base) + return bn + + +@pytest.fixture() +def alice_sec_key_data(datadir): + key_data = datadir.read('alice@openpgp.example.sec.asc') + return key_data + + +@pytest.fixture() +def bob_pub_key_data(datadir): + key_data = datadir.read('bob@openpgp.example.pub.asc') + return key_data diff --git a/tests/constants.py b/tests/constants.py new file mode 100644 index 0000000..cf5e02b --- /dev/null +++ b/tests/constants.py @@ -0,0 +1,26 @@ +"""Constants for unit tests.""" + + +# XXX: Create these first constants as part of the adapter +OUTGOING_MSG = 1 +INCOMING_MSG = 2 + +ANGLE_ADDR = "<{}>" +NAME_ADDR = "{} {}" + +PEP_NAME = "myself" +PEP_ADDRESS = "myself@pep.fundation" + +BOB_NAME = "Bob Babagge" +BOB_ADDRESS = "bob@openpgp.example" +BOB_FP = "D1A66E1A23B182C9980F788CFBFCC82A015E7330" +BOB_NAME_ADDR = NAME_ADDR.format(BOB_NAME, ANGLE_ADDR.format(BOB_ADDRESS)) + +ALICE_NAME = "Alice Lovelace" +ALICE_ADDRESS = "alice@openpgp.example" +ALICE_FP = "EB85BB5FA33A75E15E944E63F231550C4F47E38E" +ALICE_NAME_ADDR = NAME_ADDR.format(ALICE_NAME, + ANGLE_ADDR.format(ALICE_ADDRESS)) + +SUBJECT = "This is a subject" +BODY = "Hi world!\n" diff --git a/tests/data/README.md b/tests/data/README.md new file mode 100644 index 0000000..0fcfd74 --- /dev/null +++ b/tests/data/README.md @@ -0,0 +1,2 @@ +The data in this directory comes from: +https://datatracker.ietf.org/doc/draft-bre-openpgp-samples/ diff --git a/tests/data/alice@openpgp.example.pub.asc b/tests/data/alice@openpgp.example.pub.asc new file mode 100644 index 0000000..2410510 --- /dev/null +++ b/tests/data/alice@openpgp.example.pub.asc @@ -0,0 +1,14 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: Alice's OpenPGP certificate + +mDMEXEcE6RYJKwYBBAHaRw8BAQdArjWwk3FAqyiFbFBKT4TzXcVBqPTB3gmzlC/U +b7O1u120JkFsaWNlIExvdmVsYWNlIDxhbGljZUBvcGVucGdwLmV4YW1wbGU+iJAE +ExYIADgCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AWIQTrhbtfozp14V6UTmPy +MVUMT0fjjgUCXaWfOgAKCRDyMVUMT0fjjukrAPoDnHBSogOmsHOsd9qGsiZpgRnO +dypvbm+QtXZqth9rvwD9HcDC0tC+PHAsO7OTh1S1TC9RiJsvawAfCPaQZoed8gK4 +OARcRwTpEgorBgEEAZdVAQUBAQdAQv8GIa2rSTzgqbXCpDDYMiKRVitCsy203x3s +E9+eviIDAQgHiHgEGBYIACAWIQTrhbtfozp14V6UTmPyMVUMT0fjjgUCXEcE6QIb +DAAKCRDyMVUMT0fjjlnQAQDFHUs6TIcxrNTtEZFjUFm1M0PJ1Dng/cDW4xN80fsn +0QEA22Kr7VkCjeAEC08VSTeV+QFsmz55/lntWkwYWhmvOgE= +=iIGO +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/data/alice@openpgp.example.sec.asc b/tests/data/alice@openpgp.example.sec.asc new file mode 100644 index 0000000..af11bec --- /dev/null +++ b/tests/data/alice@openpgp.example.sec.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- +Comment: Alice's OpenPGP Transferable Secret Key + +lFgEXEcE6RYJKwYBBAHaRw8BAQdArjWwk3FAqyiFbFBKT4TzXcVBqPTB3gmzlC/U +b7O1u10AAP9XBeW6lzGOLx7zHH9AsUDUTb2pggYGMzd0P3ulJ2AfvQ4RtCZBbGlj +ZSBMb3ZlbGFjZSA8YWxpY2VAb3BlbnBncC5leGFtcGxlPoiQBBMWCAA4AhsDBQsJ +CAcCBhUKCQgLAgQWAgMBAh4BAheAFiEE64W7X6M6deFelE5j8jFVDE9H444FAl2l +nzoACgkQ8jFVDE9H447pKwD6A5xwUqIDprBzrHfahrImaYEZzncqb25vkLV2arYf +a78A/R3AwtLQvjxwLDuzk4dUtUwvUYibL2sAHwj2kGaHnfICnF0EXEcE6RIKKwYB +BAGXVQEFAQEHQEL/BiGtq0k84Km1wqQw2DIikVYrQrMttN8d7BPfnr4iAwEIBwAA +/3/xFPG6U17rhTuq+07gmEvaFYKfxRB6sgAYiW6TMTpQEK6IeAQYFggAIBYhBOuF +u1+jOnXhXpROY/IxVQxPR+OOBQJcRwTpAhsMAAoJEPIxVQxPR+OOWdABAMUdSzpM +hzGs1O0RkWNQWbUzQ8nUOeD9wNbjE3zR+yfRAQDbYqvtWQKN4AQLTxVJN5X5AWyb +Pnn+We1aTBhaGa86AQ== +=n8OM +-----END PGP PRIVATE KEY BLOCK----- diff --git a/tests/data/bob@openpgp.example.pub.asc b/tests/data/bob@openpgp.example.pub.asc new file mode 100644 index 0000000..b58b8c3 --- /dev/null +++ b/tests/data/bob@openpgp.example.pub.asc @@ -0,0 +1,42 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: Bob's OpenPGP certificate + +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 +NEJd3XZRzaXZE2aAMQ== +=NXei +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/data/bob@openpgp.example.sec.asc b/tests/data/bob@openpgp.example.sec.asc new file mode 100644 index 0000000..59e981b --- /dev/null +++ b/tests/data/bob@openpgp.example.sec.asc @@ -0,0 +1,82 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- +Comment: Bob's OpenPGP Transferable Secret Key + +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 +=miES +-----END PGP PRIVATE KEY BLOCK----- diff --git a/tests/test_identity.py b/tests/test_identity.py new file mode 100644 index 0000000..59fdcb9 --- /dev/null +++ b/tests/test_identity.py @@ -0,0 +1,121 @@ +"""Identity unit tests.""" +import os + +from . import constants + + +def test_create_one_identity_succeed(tmpdir): + # Change $HOME before initializing the db + os.environ["HOME"] = str(tmpdir) + # It has to be imported here to get the management db initialized, + import pEp + alice = pEp.Identity() + alice.address = constants.ALICE_ADDRESS + alice.username = constants.ALICE_NAME + alice.fpr = constants.ALICE_FP + + expected_alice = pEp.Identity( + constants.ALICE_ADDRESS, constants.ALICE_NAME, '', + constants.ALICE_FP, 0, '' + ) + + # XXX: Can't compare objects + # assert alice == expected_alice + assert str(alice) == constants.ALICE_NAME_ADDR + assert alice.address == expected_alice.address + assert alice.username == expected_alice.username + # Cause the key is created by pEp + assert alice.fpr == expected_alice.fpr + assert alice.user_id == expected_alice.user_id + assert alice.comm_type == expected_alice.comm_type + assert alice.flags == expected_alice.flags + + # Test that data after updating. + # If the db has not been initialized this would return PEP_GET_KEY_FAILED + alice.update() + assert str(alice) == constants.ALICE_NAME_ADDR + assert alice.address == expected_alice.address + assert alice.username == expected_alice.username + # XXX: shouldn't this be he fpr of the key generated by pEp? + assert alice.fpr == '' + # After updating this changed + assert alice.user_id == "TOFU_alice@openpgp.example" + # After updating this changed + assert alice.comm_type == 3 + assert alice.flags == expected_alice.flags + + +def test_two_identities_succeed(tmpdir, bob_pub_key_data): + os.environ["HOME"] = str(tmpdir) + import pEp + + alice = pEp.Identity( + constants.ALICE_ADDRESS, constants.ALICE_NAME, '', + constants.ALICE_FP, 0, '' + ) + assert alice.address == constants.ALICE_ADDRESS + assert alice.username == constants.ALICE_NAME + assert alice.fpr == constants.ALICE_FP + assert alice.user_id == "" + assert alice.comm_type == 0 + assert alice.flags == 0 + + pEp.import_key(bob_pub_key_data) + + bob = pEp.Identity() + bob.address = constants.BOB_ADDRESS + bob.username = constants.BOB_NAME + bob.fpr = constants.BOB_FP + expected_bob = pEp.Identity( + constants.BOB_ADDRESS, constants.BOB_NAME, '', + constants.BOB_FP, 56, '' + ) + + assert str(bob) == constants.BOB_NAME_ADDR + assert bob.address == expected_bob.address + assert bob.username == expected_bob.username + assert bob.fpr == expected_bob.fpr + assert bob.user_id == "" + assert bob.comm_type == 0 + assert bob.flags == 0 + + # Test that data after updating. + bob.update() + assert str(bob) == constants.BOB_NAME_ADDR + assert bob.address == expected_bob.address + assert bob.username == expected_bob.username + assert bob.fpr == expected_bob.fpr + assert bob.user_id == "TOFU_bob@openpgp.example" + assert bob.comm_type == 56 + assert bob.flags == 0 + + +def test_set_own_key(tmpdir, alice_sec_key_data): + os.environ["HOME"] = str(tmpdir) + import pEp + + pEp.import_key(alice_sec_key_data) + alice = pEp.Identity() + alice.address = constants.ALICE_ADDRESS + alice.username = constants.ALICE_NAME + alice.fpr = constants.ALICE_FP + alice.user_id = constants.ALICE_NAME_ADDR + + expected_alice = pEp.Identity( + constants.ALICE_ADDRESS, constants.ALICE_NAME, '', + constants.ALICE_FP, 0, '' + ) + + pEp.set_own_key(alice, alice.fpr) + # assert str(alice) == constants.ALICE_NAME_ADDR + assert str(alice) == str(expected_alice) + assert alice.address == expected_alice.address + assert alice.username == expected_alice.username + # assert alice.user_id == constants.ALICE_NAME_ADDR + assert alice.user_id == str(expected_alice) + assert alice.fpr == expected_alice.fpr + assert alice.comm_type == 255 + assert alice.flags == 0 + + # After setting own key this would give ValueError: illegal value + # alice.update() diff --git a/tests/test_message.py b/tests/test_message.py new file mode 100644 index 0000000..f54bd58 --- /dev/null +++ b/tests/test_message.py @@ -0,0 +1,71 @@ +"""Message unit tests.""" +import os + +from . import constants + + +def test_msg_enc_dec_roundtrip(tmpdir, alice_sec_key_data, bob_pub_key_data): + os.environ["HOME"] = str(tmpdir) + import pEp + + alice = pEp.Identity( + constants.ALICE_ADDRESS, constants.ALICE_NAME, + constants.ALICE_NAME_ADDR, constants.ALICE_FP, 0, '' + ) + + pEp.import_key(bob_pub_key_data) + bob = pEp.Identity( + constants.BOB_ADDRESS, constants.BOB_NAME, '', + constants.BOB_FP, 56, '' + ) + + msg = pEp.Message(constants.OUTGOING_MSG, alice) + msg.to = [bob] + msg.shortmsg = constants.SUBJECT + msg.longmsg = constants.BODY + assert msg.enc_format == 0 + # XXX: No way to check MIME so far. + + # Test that creating the `Message` with `outgoing_message` is the same. + msg2 = pEp.outgoing_message(alice) + msg2.to = [bob] + msg2.shortmsg = constants.SUBJECT + msg2.longmsg = constants.BODY + assert str(msg2) == str(msg) + + # Encrypt Message + enc_msg = msg.encrypt() + + assert enc_msg.enc_format == 3 + assert str(enc_msg.from_) == constants.ALICE_NAME_ADDR + assert str(enc_msg.to[0]) == constants.BOB_NAME_ADDR + assert enc_msg.shortmsg == "p≡p" + assert enc_msg.longmsg == \ + "this message was encrypted with p≡p https://pEp-project.org" + + # Decrypt message. + dec_msg, key_list, rating, r = enc_msg.decrypt() + assert r == 0 + assert rating == pEp.PEP_rating.PEP_rating_reliable + # It is not known which key is generated for Alice, so check only the + # one for Bob. + assert key_list[-1] == constants.BOB_FP + assert dec_msg.shortmsg == constants.SUBJECT + assert dec_msg.longmsg.replace("\r", "") == msg.longmsg + dec_lines = str(dec_msg).replace("\r", "").split("\n") + expected_dec_lines = """From: Alice Lovelace +To: Bob Babagge +Subject: This is a subject +X-pEp-Version: 2.1 +X-EncStatus: reliable +X-KeyList: + X,X,D1A66E1A23B182C9980F788CFBFCC82A015E7330 +MIME-Version: 1.0 +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: quoted-printable +Content-Disposition: inline; filename="msg.txt" + +Hi world=21 +""".split("\n") + assert dec_lines[:5] == expected_dec_lines[:5] + assert dec_lines[7:] == expected_dec_lines[7:] diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..c5ca3ce --- /dev/null +++ b/tox.ini @@ -0,0 +1,23 @@ +[tox] +skip_missing_interpreters = True +; Python versions ends of life: +; - 3.6: December 2021 +; - 3.7: June 2023 +; - 3.8: October 2024 +envlist = py36, py37, py38, inst, setup, unit + +# test that it can be installed with custom commands and clean env +[testenv:inst] +skip_install = True +commands = + - pip install . +recreate = True + +[testenv:setup] +skip_install = True +commands = python setup.py install +recreate = True + +[testenv:unit] +deps = .[test] +commands = pytest -svv tests From f40ca8d8e6250e3f5b5eaac2c6461a16e63a1b11 Mon Sep 17 00:00:00 2001 From: heck Date: Fri, 9 Oct 2020 19:43:42 +0200 Subject: [PATCH 03/84] Formatting only - K&R 1TBS is the standard here --- setup.py | 35 +- src/pEp/__init__.py | 4 +- src/pEp/native_pEp/basic_api.cc | 295 ++++---- src/pEp/native_pEp/basic_api.hh | 33 +- src/pEp/native_pEp/identity.cc | 488 ++++++------ src/pEp/native_pEp/identity.hh | 125 ++-- src/pEp/native_pEp/message.cc | 708 +++++++++--------- src/pEp/native_pEp/message.hh | 224 +++--- src/pEp/native_pEp/message_api.cc | 301 ++++---- src/pEp/native_pEp/message_api.hh | 27 +- src/pEp/native_pEp/pEpmodule.cc | 1033 +++++++++++++------------- src/pEp/native_pEp/pEpmodule.hh | 31 +- src/pEp/native_pEp/str_attr.cc | 308 ++++---- src/pEp/native_pEp/user_interface.cc | 133 ++-- src/pEp/native_pEp/user_interface.hh | 59 +- 15 files changed, 1884 insertions(+), 1920 deletions(-) diff --git a/setup.py b/setup.py index 34ca5d7..d838485 100644 --- a/setup.py +++ b/setup.py @@ -27,10 +27,10 @@ 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'), @@ -155,15 +155,15 @@ class BuildExtCommand(build_ext): # Append home-dir if self.local: pEpLog("local mode") - home_include=[ join(home, 'include') ] - home_libdirs=[ join(home, 'lib') ] + 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 @@ -194,7 +194,7 @@ class BuildExtCommand(build_ext): if sys.platform == 'winnt': - if sys.version_info[0] >= 3: + if sys.version_info[0] >= 3: import winreg else: import _winreg as winreg @@ -202,18 +202,17 @@ if sys.platform == 'winnt': 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', - ], + 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', + ], ) # "MAIN" Function @@ -225,7 +224,7 @@ setup( 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={ diff --git a/src/pEp/__init__.py b/src/pEp/__init__.py index 8a32e83..0bc2c9e 100644 --- a/src/pEp/__init__.py +++ b/src/pEp/__init__.py @@ -11,6 +11,7 @@ from native_pEp import * # import the module import native_pEp + # Executed on module import def init(): print(init, "called") @@ -45,8 +46,9 @@ def notify_handshake(me, partner, signal): def main(): print("I am being run as a script") + # MAIN if __name__ == "__main__": main() else: - init() \ No newline at end of file + init() diff --git a/src/pEp/native_pEp/basic_api.cc b/src/pEp/native_pEp/basic_api.cc index c3e1097..50cc802 100644 --- a/src/pEp/native_pEp/basic_api.cc +++ b/src/pEp/native_pEp/basic_api.cc @@ -13,160 +13,149 @@ #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) { + 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); - throw bad_alloc(); + 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; } - 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 { + + 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 diff --git a/src/pEp/native_pEp/basic_api.hh b/src/pEp/native_pEp/basic_api.hh index f4714a8..e4b99f2 100644 --- a/src/pEp/native_pEp/basic_api.hh +++ b/src/pEp/native_pEp/basic_api.hh @@ -7,24 +7,31 @@ #include "pEpmodule.hh" namespace pEp { -namespace PythonAdapter { + 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 update_identity(Identity &ident); -void set_identity_flags(Identity ident, identity_flags_t flags); -void unset_identity_flags(Identity ident, identity_flags_t flags); + void myself(Identity &ident); -void key_reset_trust(Identity ident); + string _trustwords(Identity me, Identity partner, string lang, bool full); -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); + void trust_personal_key(Identity ident); -} /* namespace PythonAdapter */ + 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 */ \ No newline at end of file diff --git a/src/pEp/native_pEp/identity.cc b/src/pEp/native_pEp/identity.cc index 6849741..63fbb35 100644 --- a/src/pEp/native_pEp/identity.cc +++ b/src/pEp/native_pEp/identity.cc @@ -17,269 +17,241 @@ #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 extract_identity(value[i]); - if (!extract_identity.check()) { - free_identity_list(_il); + 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); } - pEp_identity *_ident = extract_identity(); - pEp_identity *_dup = ::identity_dup(_ident); - if (!_dup) { - free_identity_list(_il); - throw bad_alloc(); + + Identity::Identity(const Identity &second) + : _ident(second._ident) { + + } + + Identity::Identity(pEp_identity *ident) + : _ident(ident, &::free_identity) { + } - PEP_STATUS status = update_identity(Adapter::session(), _dup); - if (status != PEP_STATUS_OK) { - free_identity_list(_il); + + 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); } - _i = identity_list_add(_i, _dup); - if (!_i) { - free_identity_list(_il); - throw bad_alloc(); + + Identity Identity::deepcopy(dict &) { + return copy(); } - } - free_identity_list(il); - il = _il; -} + 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(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 { + } // namespace PythonAdapter +} // namespace pEp diff --git a/src/pEp/native_pEp/identity.hh b/src/pEp/native_pEp/identity.hh index d70133f..071ac4a 100644 --- a/src/pEp/native_pEp/identity.hh +++ b/src/pEp/native_pEp/identity.hh @@ -21,82 +21,101 @@ #include "str_attr.hh" namespace pEp { -namespace PythonAdapter { + namespace PythonAdapter { -using std::string; -using std::shared_ptr; + using std::string; + using std::shared_ptr; // Identity is owning a pEp_identity -class Identity { -protected: - shared_ptr< pEp_identity > _ident; + class Identity { + protected: + shared_ptr _ident; -public: - Identity(string address = "", string username = "", - string user_id = "", string fpr = "", int comm_type = 0, - string lang = "", identity_flags_t flags = 0); + 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; + Identity(const Identity &second); - string _repr(); - string _str(); + Identity(pEp_identity *ident); - string address() { return str_attr(_ident->address); } - void address(string value) { str_attr(_ident->address, value); } + virtual ~Identity(); - string fpr() { return str_attr(_ident->fpr); } - void fpr(string value) { str_attr(_ident->fpr, value); } + operator pEp_identity *(); - string user_id() { return str_attr(_ident->user_id); } - void user_id(string value) { str_attr(_ident->user_id, value); } + operator const pEp_identity *() const; - string username() { return str_attr(_ident->username); } - void username(string value); + string _repr(); - PEP_comm_type comm_type() { return _ident->comm_type; } - void comm_type(PEP_comm_type value) { _ident->comm_type = value; }; + string _str(); - std::string lang(); - void lang(std::string value); + string address() { return str_attr(_ident->address); } - identity_flags_t flags() { return _ident->flags; } - void flags(identity_flags_t flags) { _ident->flags = flags; } + void address(string value) { str_attr(_ident->address, value); } - int rating(); - PEP_color color(); + string fpr() { return str_attr(_ident->fpr); } - Identity copy(); - Identity deepcopy(dict& memo); + void fpr(string value) { str_attr(_ident->fpr, value); } - virtual void update(); + string user_id() { return str_attr(_ident->user_id); } - void key_reset(string fpr=""); - void key_mistrusted(); + void user_id(string value) { str_attr(_ident->user_id, value); } - bool is_pEp_user(); + string username() { return str_attr(_ident->username); } - void enable_for_sync(); - void disable_for_sync(); -}; + void username(string value); -class Myself : public Identity { -public: - Myself(string address, string username, string user_id="", string lang=""); - virtual void update(); -}; + PEP_comm_type comm_type() { return _ident->comm_type; } -Identity identity_attr(pEp_identity *&ident); -void identity_attr(pEp_identity *&ident, object value); + void comm_type(PEP_comm_type value) { _ident->comm_type = value; }; -boost::python::list identitylist_attr(identity_list *&il); -void identitylist_attr(identity_list *&il, boost::python::list value); + std::string lang(); -} /* namespace PythonAdapter */ -} /* namespace pEp */ + 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 */ \ No newline at end of file diff --git a/src/pEp/native_pEp/message.cc b/src/pEp/native_pEp/message.cc index 3d0a279..ffdcca7 100644 --- a/src/pEp/native_pEp/message.cc +++ b/src/pEp/native_pEp/message.cc @@ -19,395 +19,367 @@ #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) - filename = string(_bl->filename); - build << repr(mime_type) << ", "; - build << repr(filename); - } - build << ")"; - return build.str(); -} - -int Message::Blob::getbuffer(PyObject *self, Py_buffer *view, int flags) { - bloblist_t *bl = NULL; - - try { - Message::Blob& blob = extract< Message::Blob& >(self); - bl = blob._bl; - } - catch (exception& e) { - PyErr_SetString(PyExc_RuntimeError, "extract not possible"); - view->obj = NULL; - return -1; - } - - if (!(bl && bl->value)) { - PyErr_SetString(PyExc_RuntimeError, "no data available"); - view->obj = NULL; - return -1; - } - - return PyBuffer_FillInfo(view, self, bl->value, bl->size, 0, flags); -} - -string Message::Blob::decode(string encoding) -{ - if (encoding == "") { - string _mime_type = _bl->mime_type ? _bl->mime_type : ""; - encoding = "ascii"; - - if (_mime_type == "application/pEp.sync") - encoding = "pep.sync"; - - if (_mime_type == "application/pEp.keyreset") - encoding = "pep.distribution"; - - } - object codecs = import("codecs"); - object _decode = codecs.attr("decode"); - return call< string >(_decode.ptr(), this, encoding); -} - -PyBufferProcs Message::Blob::bp = { getbuffer, NULL }; - -Message::Message(int dir, Identity *from) - : _msg(new_message((PEP_msg_direction) dir), &free_message) -{ - if (!_msg) - throw bad_alloc(); - - if (from) { - _msg->from = ::identity_dup(*from); - if (!_msg->from) - throw bad_alloc(); - _msg->dir = (PEP_msg_direction) dir; - } -} - -Message::Message(string mimetext) - : _msg(NULL, &free_message) -{ - message *_cpy; - PEP_STATUS status = mime_decode_message(mimetext.c_str(), - mimetext.size(), &_cpy, NULL); - switch (status) { - case PEP_STATUS_OK: - if (_cpy) - _cpy->dir = PEP_dir_outgoing; - else - _cpy = new_message(PEP_dir_outgoing); - - if (!_cpy) + 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(); + } - _msg = shared_ptr< message >(_cpy); - break; + 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(); - case PEP_BUFFER_TOO_SMALL: - throw runtime_error("mime_decode_message: buffer too small"); + Py_buffer src; + int result = PyObject_GetBuffer(data.ptr(), &src, PyBUF_CONTIG_RO); + if (result) + throw invalid_argument("need a contiguous buffer to read"); - case PEP_CANNOT_CREATE_TEMP_FILE: - throw runtime_error("mime_decode_message: cannot create temp file"); + 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; - case PEP_OUT_OF_MEMORY: - throw bad_alloc(); + PyBuffer_Release(&src); - default: + 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 << "mime_decode_message: unknown error (" << (int) status << ")"; - throw runtime_error(build.str()); - } -} + 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) + filename = string(_bl->filename); + build << repr(mime_type) << ", "; + build << repr(filename); + } + build << ")"; + return build.str(); + } + + int Message::Blob::getbuffer(PyObject *self, Py_buffer *view, int flags) { + bloblist_t *bl = NULL; + + try { + Message::Blob &blob = extract(self); + bl = blob._bl; + } + catch (exception &e) { + PyErr_SetString(PyExc_RuntimeError, "extract not possible"); + view->obj = NULL; + return -1; + } + + if (!(bl && bl->value)) { + PyErr_SetString(PyExc_RuntimeError, "no data available"); + view->obj = NULL; + return -1; + } + + return PyBuffer_FillInfo(view, self, bl->value, bl->size, 0, flags); + } + + string Message::Blob::decode(string encoding) { + if (encoding == "") { + string _mime_type = _bl->mime_type ? _bl->mime_type : ""; + encoding = "ascii"; -Message::Message(const Message& second) - : _msg(second._msg) -{ - if (!_msg.get()) - throw bad_alloc(); -} + if (_mime_type == "application/pEp.sync") + encoding = "pep.sync"; -Message::Message(message *msg) - : _msg(::message_dup(msg), &free_message) -{ + if (_mime_type == "application/pEp.keyreset") + encoding = "pep.distribution"; -} + } + object codecs = import("codecs"); + object _decode = codecs.attr("decode"); + return call(_decode.ptr(), this, encoding); + } -Message::~Message() -{ + PyBufferProcs Message::Blob::bp = {getbuffer, NULL}; -} + Message::Message(int dir, Identity *from) + : _msg(new_message((PEP_msg_direction) dir), &free_message) { + if (!_msg) + throw bad_alloc(); -Message::operator message *() -{ - return _msg.get(); -} + if (from) { + _msg->from = ::identity_dup(*from); + if (!_msg->from) + throw bad_alloc(); + _msg->dir = (PEP_msg_direction) dir; + } + } -Message::operator const message *() const -{ - return _msg.get(); -} + Message::Message(string mimetext) + : _msg(NULL, &free_message) { + message *_cpy; + PEP_STATUS status = mime_decode_message(mimetext.c_str(), + mimetext.size(), &_cpy, NULL); + switch (status) { + case PEP_STATUS_OK: + if (_cpy) + _cpy->dir = PEP_dir_outgoing; + else + _cpy = new_message(PEP_dir_outgoing); + + if (!_cpy) + throw bad_alloc(); + + _msg = shared_ptr(_cpy); + break; + + case PEP_BUFFER_TOO_SMALL: + throw runtime_error("mime_decode_message: buffer too small"); + + case PEP_CANNOT_CREATE_TEMP_FILE: + throw runtime_error("mime_decode_message: cannot create temp file"); + + case PEP_OUT_OF_MEMORY: + throw bad_alloc(); + + default: + stringstream build; + build << "mime_decode_message: unknown error (" << (int) status << ")"; + throw runtime_error(build.str()); + } + } -string Message::_str() -{ - if (!(_msg->from && _msg->from->address && _msg->from->address[0])) - throw out_of_range(".from_.address missing"); + Message::Message(const Message &second) + : _msg(second._msg) { + if (!_msg.get()) + throw bad_alloc(); + } - char *mimetext; - string result; + Message::Message(message *msg) + : _msg(::message_dup(msg), &free_message) { - PEP_STATUS status = mime_encode_message(*this, false, &mimetext, false); - switch (status) { - case PEP_STATUS_OK: - result = mimetext; - free(mimetext); - break; + } - case PEP_BUFFER_TOO_SMALL: - throw runtime_error("mime_encode_message: buffer too small"); + Message::~Message() { - case PEP_CANNOT_CREATE_TEMP_FILE: - throw runtime_error("mime_encode_message: cannot create temp file"); + } - case PEP_OUT_OF_MEMORY: - throw bad_alloc(); + Message::operator message *() { + return _msg.get(); + } - default: + Message::operator const message *() const { + return _msg.get(); + } + + string Message::_str() { + if (!(_msg->from && _msg->from->address && _msg->from->address[0])) + throw out_of_range(".from_.address missing"); + + char *mimetext; + string result; + + PEP_STATUS status = mime_encode_message(*this, false, &mimetext, false); + switch (status) { + case PEP_STATUS_OK: + result = mimetext; + free(mimetext); + break; + + case PEP_BUFFER_TOO_SMALL: + throw runtime_error("mime_encode_message: buffer too small"); + + case PEP_CANNOT_CREATE_TEMP_FILE: + throw runtime_error("mime_encode_message: cannot create temp file"); + + case PEP_OUT_OF_MEMORY: + throw bad_alloc(); + + default: + stringstream build; + build << "mime_encode_message: unknown error (" << (int) status << ")"; + throw runtime_error(build.str()); + } + + return result; + } + + string Message::_repr() { stringstream build; - build << "mime_encode_message: unknown error (" << (int) status << ")"; - throw runtime_error(build.str()); - } - - return result; -} - -string Message::_repr() -{ - stringstream build; - build << "Message(" << repr(_str()) << ")"; - return build.str(); -} - -boost::python::tuple Message::attachments() -{ - boost::python::list l; - - for (bloblist_t *bl = _msg->attachments; bl && bl->value; bl = - bl->next) { - l.append(Blob(bl, true)); - } - - return boost::python::tuple(l); -} - -void Message::attachments(boost::python::list value) -{ - bloblist_t *bl = new_bloblist(NULL, 0, NULL, NULL); - if (!bl) - throw bad_alloc(); - - bloblist_t *_l = bl; - for (int i=0; i(value[i]); - _l = bloblist_add(_l, blob._bl->value, blob._bl->size, - blob._bl->mime_type, blob._bl->filename); - if (!_l) { - for (_l = bl; _l && _l->value; ) { - free(_l->mime_type); - free(_l->filename); - bloblist_t *_ll = _l; - _l = _l->next; - free(_ll); + build << "Message(" << repr(_str()) << ")"; + return build.str(); + } + + boost::python::tuple Message::attachments() { + boost::python::list l; + + for (bloblist_t *bl = _msg->attachments; bl && bl->value; bl = + bl->next) { + l.append(Blob(bl, true)); } - throw bad_alloc(); + + return boost::python::tuple(l); + } + + void Message::attachments(boost::python::list value) { + bloblist_t *bl = new_bloblist(NULL, 0, NULL, NULL); + if (!bl) + throw bad_alloc(); + + bloblist_t *_l = bl; + for (int i = 0; i < len(value); i++) { + Message::Blob &blob = extract(value[i]); + _l = bloblist_add(_l, blob._bl->value, blob._bl->size, + blob._bl->mime_type, blob._bl->filename); + if (!_l) { + for (_l = bl; _l && _l->value;) { + free(_l->mime_type); + free(_l->filename); + bloblist_t *_ll = _l; + _l = _l->next; + free(_ll); + } + throw bad_alloc(); + } + } + + for (int i = 0; i < len(value); i++) { + Message::Blob &blob = extract(value[i]); + blob._bl->value = NULL; + blob._bl->size = 0; + free(blob._bl->mime_type); + blob._bl->mime_type = NULL; + free(blob._bl->filename); + blob._bl->filename = NULL; + } + + free_bloblist(_msg->attachments); + _msg->attachments = bl; + } + + Message Message::encrypt() { + boost::python::list extra; + return encrypt_message(*this, extra, PEP_enc_PGP_MIME, 0); } - } - - for (int i=0; i(value[i]); - blob._bl->value = NULL; - blob._bl->size = 0; - free(blob._bl->mime_type); - blob._bl->mime_type = NULL; - free(blob._bl->filename); - blob._bl->filename = NULL; - } - - free_bloblist(_msg->attachments); - _msg->attachments = bl; -} - -Message Message::encrypt() -{ - boost::python::list extra; - return encrypt_message(*this, extra, PEP_enc_PGP_MIME, 0); -} - -Message Message::_encrypt(boost::python::list extra, int enc_format, int flags) -{ - if (!enc_format) - enc_format = PEP_enc_PGP_MIME; - return encrypt_message(*this, extra, enc_format, flags); -} - -boost::python::tuple Message::decrypt(int flags) { - return pEp::PythonAdapter::decrypt_message(*this, flags); -} - -PEP_rating Message::outgoing_rating() -{ - if (_msg->dir != PEP_dir_outgoing) - throw invalid_argument("Message.dir must be outgoing"); - - if (from().address() == "") - throw invalid_argument("from.address needed"); - if (from().username() == "") - throw invalid_argument("from.username needed"); - - if (len(to()) + len(cc()) == 0) - throw invalid_argument("either to or cc needed"); - - PEP_STATUS status = myself(Adapter::session(), _msg->from); - _throw_status(status); - - PEP_rating rating = PEP_rating_undefined; - status = outgoing_message_rating(Adapter::session(), *this, &rating); - _throw_status(status); - - return rating; -} - -PEP_color Message::outgoing_color() -{ - return _color(outgoing_rating()); -} - -Message Message::copy() -{ - message *dup = message_dup(*this); - if (!dup) - throw bad_alloc(); - return Message(dup); -} - -Message Message::deepcopy(dict&) -{ - return copy(); -} - -Message outgoing_message(Identity me) -{ - if (me.address().empty() || me.user_id().empty()) - throw runtime_error("at least address and user_id of own user needed"); - - ::myself(Adapter::session(), me); - auto m = Message(PEP_dir_outgoing, &me); - return m; -} - -static object update(Identity ident) -{ - if (ident.address().empty()) - throw runtime_error("at least address needed"); - update_identity(Adapter::session(), ident); - return object(ident); -} - -static boost::python::list update(boost::python::list il) -{ - for (int i=0; i(il[i])); - } - - return il; -} - -Message incoming_message(string mime_text) -{ - auto m = Message(mime_text); - m.dir(PEP_dir_incoming); - - try { - m.from(update(m.from())); - } - catch (out_of_range&) { } - - try { - m.recv_by(update(m.recv_by())); - } - catch (out_of_range&) { } - - m.to(update(m.to())); - m.cc(update(m.cc())); - m.reply_to(update(m.reply_to())); - - return m; -} - -} // namespace PythonAdapter -} // namespace pEp { + + Message Message::_encrypt(boost::python::list extra, int enc_format, int flags) { + if (!enc_format) + enc_format = PEP_enc_PGP_MIME; + return encrypt_message(*this, extra, enc_format, flags); + } + + boost::python::tuple Message::decrypt(int flags) { + return pEp::PythonAdapter::decrypt_message(*this, flags); + } + + PEP_rating Message::outgoing_rating() { + if (_msg->dir != PEP_dir_outgoing) + throw invalid_argument("Message.dir must be outgoing"); + + if (from().address() == "") + throw invalid_argument("from.address needed"); + if (from().username() == "") + throw invalid_argument("from.username needed"); + + if (len(to()) + len(cc()) == 0) + throw invalid_argument("either to or cc needed"); + + PEP_STATUS status = myself(Adapter::session(), _msg->from); + _throw_status(status); + + PEP_rating rating = PEP_rating_undefined; + status = outgoing_message_rating(Adapter::session(), *this, &rating); + _throw_status(status); + + return rating; + } + + PEP_color Message::outgoing_color() { + return _color(outgoing_rating()); + } + + Message Message::copy() { + message *dup = message_dup(*this); + if (!dup) + throw bad_alloc(); + return Message(dup); + } + + Message Message::deepcopy(dict &) { + return copy(); + } + + Message outgoing_message(Identity me) { + if (me.address().empty() || me.user_id().empty()) + throw runtime_error("at least address and user_id of own user needed"); + + ::myself(Adapter::session(), me); + auto m = Message(PEP_dir_outgoing, &me); + return m; + } + + static object update(Identity ident) { + if (ident.address().empty()) + throw runtime_error("at least address needed"); + update_identity(Adapter::session(), ident); + return object(ident); + } + + static boost::python::list update(boost::python::list il) { + for (int i = 0; i < len(il); i++) { + update(extract(il[i])); + } + + return il; + } + + Message incoming_message(string mime_text) { + auto m = Message(mime_text); + m.dir(PEP_dir_incoming); + + try { + m.from(update(m.from())); + } + catch (out_of_range &) {} + + try { + m.recv_by(update(m.recv_by())); + } + catch (out_of_range &) {} + + m.to(update(m.to())); + m.cc(update(m.cc())); + m.reply_to(update(m.reply_to())); + + return m; + } + + } // namespace PythonAdapter +} // namespace pEp diff --git a/src/pEp/native_pEp/message.hh b/src/pEp/native_pEp/message.hh index dac9a73..5eba845 100644 --- a/src/pEp/native_pEp/message.hh +++ b/src/pEp/native_pEp/message.hh @@ -18,137 +18,177 @@ #include "identity.hh" namespace pEp { -namespace PythonAdapter { -using std::string; -using std::runtime_error; -using std::invalid_argument; -using boost::lexical_cast; + namespace PythonAdapter { + using std::string; + using std::runtime_error; + using std::invalid_argument; + using boost::lexical_cast; // Message is owning a message struct -class Message { - shared_ptr< ::message > _msg; + class Message { + shared_ptr<::message> _msg; -public: - // Blob is owning a bloblist_t struct - or not and just managing - // one depending on part_of_chain + public: + // Blob is owning a bloblist_t struct - or not and just managing + // one depending on part_of_chain - class Blob { - bloblist_t *_bl; - bool part_of_chain; + class Blob { + bloblist_t *_bl; + bool part_of_chain; - public: - Blob(bloblist_t *bl = new_bloblist(NULL, 0, NULL, NULL), - bool chained = false); - Blob(object data, string mime_type = "", string filename = ""); - Blob(const Blob& second); - ~Blob(); + public: + Blob(bloblist_t *bl = new_bloblist(NULL, 0, NULL, NULL), + bool chained = false); - string _repr(); + Blob(object data, string mime_type = "", string filename = ""); - string mime_type() { return _bl ? str_attr(_bl->mime_type) : ""; } - void mime_type(string value) { str_attr(_bl->mime_type, value); } + Blob(const Blob &second); - string filename() { return str_attr(_bl->filename); } - void filename(string value) { str_attr(_bl->filename, value); } + ~Blob(); - size_t size() { return _bl->size; } - string decode(string encoding); - string decode() { return decode(""); } + string _repr(); - static PyBufferProcs bp; + string mime_type() { return _bl ? str_attr(_bl->mime_type) : ""; } - friend class Message; + void mime_type(string value) { str_attr(_bl->mime_type, value); } - protected: - static int getbuffer(PyObject *self, Py_buffer *view, int flags); - }; + string filename() { return str_attr(_bl->filename); } - Message(int dir = PEP_dir_outgoing, Identity *from = NULL); - Message(string mimetext); - Message(const Message& second); - Message(message *msg); - ~Message(); - operator message *(); - operator const message *() const; + void filename(string value) { str_attr(_bl->filename, value); } - string _str(); - string _repr(); + size_t size() { return _bl->size; } - PEP_msg_direction dir() { return _msg->dir; } - void dir(PEP_msg_direction value) { _msg->dir = value; } + string decode(string encoding); - string id() { return str_attr(_msg->id); } - void id(string value) { str_attr(_msg->id, value); } + string decode() { return decode(""); } - string shortmsg() { return str_attr(_msg->shortmsg); } - void shortmsg(string value) { str_attr(_msg->shortmsg, value); } + static PyBufferProcs bp; - string longmsg() { return str_attr(_msg->longmsg); } - void longmsg(string value) { str_attr(_msg->longmsg, value); } + friend class Message; - string longmsg_formatted() { return str_attr(_msg->longmsg_formatted); } - void longmsg_formatted(string value) { str_attr(_msg->longmsg_formatted, value); } + protected: + static int getbuffer(PyObject *self, Py_buffer *view, int flags); + }; - boost::python::tuple attachments(); - void attachments(boost::python::list value); + Message(int dir = PEP_dir_outgoing, Identity *from = NULL); - time_t sent() { return timestamp_attr(_msg->sent); } - void sent(time_t value) { timestamp_attr(_msg->sent, value); } + Message(string mimetext); - time_t recv() { return timestamp_attr(_msg->recv); } - void recv(time_t value) { timestamp_attr(_msg->recv, value); } + Message(const Message &second); - Identity from() { return identity_attr(_msg->from); } - void from(object value) { identity_attr(_msg->from, value); } + Message(message *msg); - boost::python::list to() { return identitylist_attr(_msg->to); } - void to(boost::python::list value) { identitylist_attr(_msg->to, value); } + ~Message(); - Identity recv_by() { return identity_attr(_msg->recv_by); } - void recv_by(object value) { identity_attr(_msg->recv_by, value); } + operator message *(); - boost::python::list cc() { return identitylist_attr(_msg->cc); } - void cc(boost::python::list value) { identitylist_attr(_msg->cc, value); } + operator const message *() const; - boost::python::list bcc() { return identitylist_attr(_msg->bcc); } - void bcc(boost::python::list value) { identitylist_attr(_msg->bcc, value); } + string _str(); - boost::python::list reply_to() { return identitylist_attr(_msg->reply_to); } - void reply_to(boost::python::list value) { identitylist_attr(_msg->reply_to, value); } + string _repr(); - boost::python::list in_reply_to() { return strlist_attr(_msg->in_reply_to); } - void in_reply_to(boost::python::list value) { strlist_attr(_msg->in_reply_to, value); } + PEP_msg_direction dir() { return _msg->dir; } - boost::python::list references() { return strlist_attr(_msg->references); } - void references(boost::python::list value) { strlist_attr(_msg->references, value); } + void dir(PEP_msg_direction value) { _msg->dir = value; } - boost::python::list keywords() { return strlist_attr(_msg->keywords); } - void keywords(boost::python::list value) { strlist_attr(_msg->keywords, value); } + string id() { return str_attr(_msg->id); } - string comments() { return str_attr(_msg->comments); } - void comments(string value) { str_attr(_msg->comments, value); } + void id(string value) { str_attr(_msg->id, value); } - dict opt_fields() { return strdict_attr(_msg->opt_fields); } - void opt_fields(dict value) { return strdict_attr(_msg->opt_fields, value); } + string shortmsg() { return str_attr(_msg->shortmsg); } - PEP_enc_format enc_format() { return _msg->enc_format; } - void enc_format(PEP_enc_format value) { _msg->enc_format = value; } + void shortmsg(string value) { str_attr(_msg->shortmsg, value); } - Message encrypt(); - Message _encrypt(boost::python::list extra, int enc_format=4, int flags=0); + string longmsg() { return str_attr(_msg->longmsg); } - boost::python::tuple decrypt(int flags=0); - PEP_rating outgoing_rating(); - PEP_color outgoing_color(); - Message deepcopy(dict& memo); - Message copy(); -}; + void longmsg(string value) { str_attr(_msg->longmsg, value); } -Message outgoing_message(Identity me); -Message incoming_message(string mime_text); + string longmsg_formatted() { return str_attr(_msg->longmsg_formatted); } -} /* namespace PythonAdapter */ + void longmsg_formatted(string value) { str_attr(_msg->longmsg_formatted, value); } + + boost::python::tuple attachments(); + + void attachments(boost::python::list value); + + time_t sent() { return timestamp_attr(_msg->sent); } + + void sent(time_t value) { timestamp_attr(_msg->sent, value); } + + time_t recv() { return timestamp_attr(_msg->recv); } + + void recv(time_t value) { timestamp_attr(_msg->recv, value); } + + Identity from() { return identity_attr(_msg->from); } + + void from(object value) { identity_attr(_msg->from, value); } + + boost::python::list to() { return identitylist_attr(_msg->to); } + + void to(boost::python::list value) { identitylist_attr(_msg->to, value); } + + Identity recv_by() { return identity_attr(_msg->recv_by); } + + void recv_by(object value) { identity_attr(_msg->recv_by, value); } + + boost::python::list cc() { return identitylist_attr(_msg->cc); } + + void cc(boost::python::list value) { identitylist_attr(_msg->cc, value); } + + boost::python::list bcc() { return identitylist_attr(_msg->bcc); } + + void bcc(boost::python::list value) { identitylist_attr(_msg->bcc, value); } + + boost::python::list reply_to() { return identitylist_attr(_msg->reply_to); } + + void reply_to(boost::python::list value) { identitylist_attr(_msg->reply_to, value); } + + boost::python::list in_reply_to() { return strlist_attr(_msg->in_reply_to); } + + void in_reply_to(boost::python::list value) { strlist_attr(_msg->in_reply_to, value); } + + boost::python::list references() { return strlist_attr(_msg->references); } + + void references(boost::python::list value) { strlist_attr(_msg->references, value); } + + boost::python::list keywords() { return strlist_attr(_msg->keywords); } + + void keywords(boost::python::list value) { strlist_attr(_msg->keywords, value); } + + string comments() { return str_attr(_msg->comments); } + + void comments(string value) { str_attr(_msg->comments, value); } + + dict opt_fields() { return strdict_attr(_msg->opt_fields); } + + void opt_fields(dict value) { return strdict_attr(_msg->opt_fields, value); } + + PEP_enc_format enc_format() { return _msg->enc_format; } + + void enc_format(PEP_enc_format value) { _msg->enc_format = value; } + + Message encrypt(); + + Message _encrypt(boost::python::list extra, int enc_format = 4, int flags = 0); + + boost::python::tuple decrypt(int flags = 0); + + PEP_rating outgoing_rating(); + + PEP_color outgoing_color(); + + Message deepcopy(dict &memo); + + Message copy(); + }; + + Message outgoing_message(Identity me); + + Message incoming_message(string mime_text); + + } /* namespace PythonAdapter */ } /* namespace pEp */ #endif /* MESSAGE_HH */ \ No newline at end of file diff --git a/src/pEp/native_pEp/message_api.cc b/src/pEp/native_pEp/message_api.cc index 6a4b76d..1c2e3c7 100644 --- a/src/pEp/native_pEp/message_api.cc +++ b/src/pEp/native_pEp/message_api.cc @@ -13,160 +13,149 @@ #include "basic_api.hh" namespace pEp { -namespace PythonAdapter { -using namespace std; -using namespace boost::python; - -Message encrypt_message(Message src, boost::python::list extra, int enc_format, int flags) -{ - Identity _from = src.from(); - if (_from.address() == "") - throw invalid_argument("encrypt_message: src.from_.address empty"); - if (_from.username() == "") - throw invalid_argument("encrypt_message: src.from_.username empty"); - - if (_from.user_id() == "") - src.from().user_id(_from.address()); - - stringlist_t *_extra = to_stringlist(extra); - PEP_enc_format _enc_format = (PEP_enc_format) enc_format; - PEP_encrypt_flags_t _flags = (PEP_encrypt_flags_t) flags; - message *_dst = NULL; - - message *_src = src; - PEP_STATUS status = encrypt_message(Adapter::session(), _src, _extra, &_dst, - _enc_format, _flags); - free_stringlist(_extra); - _throw_status(status); - - if (!_dst || _dst == _src) - return Message(_src); - - return Message(_dst); -} - -boost::python::tuple decrypt_message(Message src, int flags) -{ - message *_dst = NULL; - stringlist_t *_keylist = NULL; - PEP_rating _rating = PEP_rating_undefined; - PEP_decrypt_flags_t _flags = (PEP_decrypt_flags_t) flags; - message *_src = src; - - PEP_STATUS status = ::decrypt_message(Adapter::session(), _src, &_dst, &_keylist, - &_rating, &_flags); - _throw_status(status); - - boost::python::list keylist; - if (_keylist) { - keylist = from_stringlist(_keylist); - free_stringlist(_keylist); - } - - Message dst = _dst ? Message(_dst) : Message(src); - return boost::python::make_tuple(dst, keylist, _rating, _flags); -} - -PEP_color _color(int rating) -{ - return ::color_from_rating((PEP_rating) rating); -} - -boost::python::tuple sync_decode(object buffer) -{ - Py_buffer src; - int result = PyObject_GetBuffer(buffer.ptr(), &src, PyBUF_CONTIG_RO); - if (result) - throw invalid_argument("need a contiguous buffer to read"); - - char *dst = NULL; - PEP_STATUS status = PER_to_XER_Sync_msg((char *) src.buf, src.len, &dst); - PyBuffer_Release(&src); - _throw_status(status); - - string _dst(dst); - free(dst); - return boost::python::make_tuple(_dst, 0); -} - -static boost::python::tuple sync_encode(string text) -{ - char *data = NULL; - size_t size = 0; - PEP_STATUS status = XER_to_PER_Sync_msg(text.c_str(), &data, &size); - _throw_status(status); - - PyObject *ba = PyBytes_FromStringAndSize(data, size); - free(data); - if (!ba) - throw bad_alloc(); - - return boost::python::make_tuple(object(handle<>(ba)), 0); -} - -boost::python::tuple Distribution_decode(object buffer) -{ - Py_buffer src; - int result = PyObject_GetBuffer(buffer.ptr(), &src, PyBUF_CONTIG_RO); - if (result) - throw invalid_argument("need a contiguous buffer to read"); - - char *dst = NULL; - PEP_STATUS status = PER_to_XER_Distribution_msg((char *) src.buf, src.len, &dst); - PyBuffer_Release(&src); - _throw_status(status); - - string _dst(dst); - free(dst); - return boost::python::make_tuple(_dst, 0); -} - -static boost::python::tuple Distribution_encode(string text) -{ - char *data = NULL; - size_t size = 0; - PEP_STATUS status = XER_to_PER_Distribution_msg(text.c_str(), &data, &size); - _throw_status(status); - - PyObject *ba = PyBytes_FromStringAndSize(data, size); - free(data); - if (!ba) - throw bad_alloc(); - - return boost::python::make_tuple(object(handle<>(ba)), 0); -} - -object sync_search(string name) -{ - if (name != "pep.sync") { - return object(); - } - else { - object codecs = import("codecs"); - object CodecInfo = codecs.attr("CodecInfo"); - - object _sync_decode = make_function(sync_decode); - object _sync_encode = make_function(sync_encode); - - return call< object >(CodecInfo.ptr(), _sync_encode, _sync_decode); - } -} - -object distribution_search(string name) -{ - if (name != "pep.distribution") { - return object(); - } - else { - object codecs = import("codecs"); - object CodecInfo = codecs.attr("CodecInfo"); - - object _distribution_decode = make_function(Distribution_decode); - object _distribution_encode = make_function(Distribution_encode); - - return call< object >(CodecInfo.ptr(), _distribution_encode, _distribution_decode); - } -} - -} // namespace PythonAdapter + namespace PythonAdapter { + using namespace std; + using namespace boost::python; + + Message encrypt_message(Message src, boost::python::list extra, int enc_format, int flags) { + Identity _from = src.from(); + if (_from.address() == "") + throw invalid_argument("encrypt_message: src.from_.address empty"); + if (_from.username() == "") + throw invalid_argument("encrypt_message: src.from_.username empty"); + + if (_from.user_id() == "") + src.from().user_id(_from.address()); + + stringlist_t *_extra = to_stringlist(extra); + PEP_enc_format _enc_format = (PEP_enc_format) enc_format; + PEP_encrypt_flags_t _flags = (PEP_encrypt_flags_t) flags; + message *_dst = NULL; + + message *_src = src; + PEP_STATUS status = encrypt_message(Adapter::session(), _src, _extra, &_dst, + _enc_format, _flags); + free_stringlist(_extra); + _throw_status(status); + + if (!_dst || _dst == _src) + return Message(_src); + + return Message(_dst); + } + + boost::python::tuple decrypt_message(Message src, int flags) { + message *_dst = NULL; + stringlist_t *_keylist = NULL; + PEP_rating _rating = PEP_rating_undefined; + PEP_decrypt_flags_t _flags = (PEP_decrypt_flags_t) flags; + message *_src = src; + + PEP_STATUS status = ::decrypt_message(Adapter::session(), _src, &_dst, &_keylist, + &_rating, &_flags); + _throw_status(status); + + boost::python::list keylist; + if (_keylist) { + keylist = from_stringlist(_keylist); + free_stringlist(_keylist); + } + + Message dst = _dst ? Message(_dst) : Message(src); + return boost::python::make_tuple(dst, keylist, _rating, _flags); + } + + PEP_color _color(int rating) { + return ::color_from_rating((PEP_rating) rating); + } + + boost::python::tuple sync_decode(object buffer) { + Py_buffer src; + int result = PyObject_GetBuffer(buffer.ptr(), &src, PyBUF_CONTIG_RO); + if (result) + throw invalid_argument("need a contiguous buffer to read"); + + char *dst = NULL; + PEP_STATUS status = PER_to_XER_Sync_msg((char *) src.buf, src.len, &dst); + PyBuffer_Release(&src); + _throw_status(status); + + string _dst(dst); + free(dst); + return boost::python::make_tuple(_dst, 0); + } + + static boost::python::tuple sync_encode(string text) { + char *data = NULL; + size_t size = 0; + PEP_STATUS status = XER_to_PER_Sync_msg(text.c_str(), &data, &size); + _throw_status(status); + + PyObject *ba = PyBytes_FromStringAndSize(data, size); + free(data); + if (!ba) + throw bad_alloc(); + + return boost::python::make_tuple(object(handle<>(ba)), 0); + } + + boost::python::tuple Distribution_decode(object buffer) { + Py_buffer src; + int result = PyObject_GetBuffer(buffer.ptr(), &src, PyBUF_CONTIG_RO); + if (result) + throw invalid_argument("need a contiguous buffer to read"); + + char *dst = NULL; + PEP_STATUS status = PER_to_XER_Distribution_msg((char *) src.buf, src.len, &dst); + PyBuffer_Release(&src); + _throw_status(status); + + string _dst(dst); + free(dst); + return boost::python::make_tuple(_dst, 0); + } + + static boost::python::tuple Distribution_encode(string text) { + char *data = NULL; + size_t size = 0; + PEP_STATUS status = XER_to_PER_Distribution_msg(text.c_str(), &data, &size); + _throw_status(status); + + PyObject *ba = PyBytes_FromStringAndSize(data, size); + free(data); + if (!ba) + throw bad_alloc(); + + return boost::python::make_tuple(object(handle<>(ba)), 0); + } + + object sync_search(string name) { + if (name != "pep.sync") { + return object(); + } else { + object codecs = import("codecs"); + object CodecInfo = codecs.attr("CodecInfo"); + + object _sync_decode = make_function(sync_decode); + object _sync_encode = make_function(sync_encode); + + return call(CodecInfo.ptr(), _sync_encode, _sync_decode); + } + } + + object distribution_search(string name) { + if (name != "pep.distribution") { + return object(); + } else { + object codecs = import("codecs"); + object CodecInfo = codecs.attr("CodecInfo"); + + object _distribution_decode = make_function(Distribution_decode); + object _distribution_encode = make_function(Distribution_encode); + + return call(CodecInfo.ptr(), _distribution_encode, _distribution_decode); + } + } + + } // namespace PythonAdapter } // namespace pEp { diff --git a/src/pEp/native_pEp/message_api.hh b/src/pEp/native_pEp/message_api.hh index a793d32..2d153b6 100644 --- a/src/pEp/native_pEp/message_api.hh +++ b/src/pEp/native_pEp/message_api.hh @@ -7,21 +7,24 @@ #include "pEpmodule.hh" namespace pEp { -namespace PythonAdapter { + namespace PythonAdapter { -Message encrypt_message( - Message src, - boost::python::list extra = boost::python::list(), - int enc_format = 4, - int flags = 0 -); + Message encrypt_message( + Message src, + boost::python::list extra = boost::python::list(), + int enc_format = 4, + int flags = 0 + ); -boost::python::tuple decrypt_message(Message src, int flags=0); -PEP_color _color(int rating); -object sync_search(string name); -object distribution_search(string name); + boost::python::tuple decrypt_message(Message src, int flags = 0); -} /* namespace PythonAdapter */ + PEP_color _color(int rating); + + object sync_search(string name); + + object distribution_search(string name); + + } /* namespace PythonAdapter */ } /* namespace pEp */ #endif /* MESSAGE_API_HH */ \ No newline at end of file diff --git a/src/pEp/native_pEp/pEpmodule.cc b/src/pEp/native_pEp/pEpmodule.cc index 6148c95..3d2bff1 100644 --- a/src/pEp/native_pEp/pEpmodule.cc +++ b/src/pEp/native_pEp/pEpmodule.cc @@ -27,579 +27,562 @@ //#include "user_interface.hh" namespace pEp { -namespace PythonAdapter { -using namespace std; -using namespace boost::python; + namespace PythonAdapter { + using namespace std; + using namespace boost::python; -static const char *version_string = "p≡p Python adapter version 0.3"; + static const char *version_string = "p≡p Python adapter version 0.3"; -void init_before_main_module() { - pEpLog("called"); -} + void init_before_main_module() { + pEpLog("called"); + } // hidden init function, wrapped by hello_world.init() -void _init_after_main_module() { - pEpLog("called"); - callback_dispatcher.add(_messageToSend, notifyHandshake, nullptr, nullptr); - Adapter::_messageToSend = CallbackDispatcher::messageToSend; -} - - -void config_passive_mode(bool enable) -{ - ::config_passive_mode(Adapter::session(), enable); -} - -void config_unencrypted_subject(bool enable) -{ - ::config_unencrypted_subject(Adapter::session(), enable); -} - -void key_reset_user(string user_id, string fpr) -{ - if (user_id == "") - throw invalid_argument("user_id required"); - - PEP_STATUS status = ::key_reset_user(Adapter::session(), - user_id.c_str(), fpr != "" ? fpr.c_str() : nullptr); - _throw_status(status); -} - -void key_reset_user2(string user_id) -{ - key_reset_user(user_id, ""); -} - -void key_reset_all_own_keys() -{ - PEP_STATUS status = ::key_reset_all_own_keys(Adapter::session()); - _throw_status(status); -} - -static string about() -{ - string version = string(version_string) + "\np≡p version " - + PEP_VERSION + "\n"; - return version; -} - -void _throw_status(PEP_STATUS status) -{ - if (status == PEP_STATUS_OK) - return; - if (status >= 0x400 && status <= 0x4ff) - return; - if (status == PEP_OUT_OF_MEMORY) - throw bad_alloc(); - if (status == PEP_ILLEGAL_VALUE) - throw invalid_argument("illegal value"); - - if (string(pEp_status_to_string(status)) == "unknown status code") { - stringstream build; - build << setfill('0') << "p≡p 0x" << setw(4) << hex << status; - throw runtime_error(build.str()); - } - else { - throw runtime_error(pEp_status_to_string(status)); - } -} - -PEP_STATUS _messageToSend(::message *msg) -{ - pEpLog("called"); - try { - PyGILState_STATE gil = PyGILState_Ensure(); - pEpLog("GIL Aquired"); - object modref = import("pEp"); - object funcref = modref.attr("message_to_send"); - call(funcref.ptr(), Message()); - PyGILState_Release(gil); - pEpLog("GIL released"); - } catch (exception& e) { } - - return PEP_STATUS_OK; -} - -PEP_STATUS notifyHandshake(pEp_identity *me, pEp_identity *partner, sync_handshake_signal signal) -{ - pEpLog("called"); - try { - PyGILState_STATE gil = PyGILState_Ensure(); - pEpLog("GIL Aquired"); - object modref = import("pEp"); - object funcref = modref.attr("notify_handshake"); - call(funcref.ptr(), me, partner, signal); - PyGILState_Release(gil); - pEpLog("GIL released"); - } catch (exception& e) { } - - return PEP_STATUS_OK; -} - - -void start_sync() -{ - CallbackDispatcher::start_sync(); -} - -void shutdown_sync() -{ - CallbackDispatcher::stop_sync(); -} - -void debug_color(int ansi_color) -{ - ::set_debug_color(Adapter::session(), ansi_color); -} - -void leave_device_group() -{ - ::leave_device_group(Adapter::session()); -} - -bool is_sync_active() -{ - return Adapter::is_sync_running(); -} - -void testfunc() { - _messageToSend(NULL); -} - -void deliverHandshakeResult(int result, object identities) -{ - identity_list *shared_identities = nullptr; - if (identities != boost::python::api::object() && boost::python::len(identities)) { - shared_identities = new_identity_list(nullptr); - if (!shared_identities) - throw bad_alloc(); - - try { - identity_list *si = shared_identities; - for (int i=0; i < boost::python::len(identities); ++i) { - Identity ident = extract< Identity >(identities[i]); - si = identity_list_add(si, ident); - if (!si) - throw bad_alloc(); + void _init_after_main_module() { + pEpLog("called"); + callback_dispatcher.add(_messageToSend, notifyHandshake, nullptr, nullptr); + Adapter::_messageToSend = CallbackDispatcher::messageToSend; + } + + + void config_passive_mode(bool enable) { + ::config_passive_mode(Adapter::session(), enable); + } + + void config_unencrypted_subject(bool enable) { + ::config_unencrypted_subject(Adapter::session(), enable); + } + + void key_reset_user(string user_id, string fpr) { + if (user_id == "") + throw invalid_argument("user_id required"); + + PEP_STATUS status = ::key_reset_user(Adapter::session(), + user_id.c_str(), fpr != "" ? fpr.c_str() : nullptr); + _throw_status(status); + } + + void key_reset_user2(string user_id) { + key_reset_user(user_id, ""); + } + + void key_reset_all_own_keys() { + PEP_STATUS status = ::key_reset_all_own_keys(Adapter::session()); + _throw_status(status); + } + + static string about() { + string version = string(version_string) + "\np≡p version " + + PEP_VERSION + "\n"; + return version; + } + + void _throw_status(PEP_STATUS status) { + if (status == PEP_STATUS_OK) + return; + if (status >= 0x400 && status <= 0x4ff) + return; + if (status == PEP_OUT_OF_MEMORY) + throw bad_alloc(); + if (status == PEP_ILLEGAL_VALUE) + throw invalid_argument("illegal value"); + + if (string(pEp_status_to_string(status)) == "unknown status code") { + stringstream build; + build << setfill('0') << "p≡p 0x" << setw(4) << hex << status; + throw runtime_error(build.str()); + } else { + throw runtime_error(pEp_status_to_string(status)); } } - catch (exception& ex) { - free_identity_list(shared_identities); - throw ex; + + PEP_STATUS _messageToSend(::message *msg) { + pEpLog("called"); + try { + PyGILState_STATE gil = PyGILState_Ensure(); + pEpLog("GIL Aquired"); + object modref = import("pEp"); + object funcref = modref.attr("message_to_send"); + call(funcref.ptr(), Message()); + PyGILState_Release(gil); + pEpLog("GIL released"); + } catch (exception &e) {} + + return PEP_STATUS_OK; + } + + PEP_STATUS notifyHandshake(pEp_identity *me, pEp_identity *partner, sync_handshake_signal signal) { + pEpLog("called"); + try { + PyGILState_STATE gil = PyGILState_Ensure(); + pEpLog("GIL Aquired"); + object modref = import("pEp"); + object funcref = modref.attr("notify_handshake"); + call(funcref.ptr(), me, partner, signal); + PyGILState_Release(gil); + pEpLog("GIL released"); + } catch (exception &e) {} + + return PEP_STATUS_OK; } - } - PEP_STATUS status = ::deliverHandshakeResult(Adapter::session(), (sync_handshake_result) result, shared_identities); - free_identity_list(shared_identities); - _throw_status(status); -} -BOOST_PYTHON_MODULE(native_pEp) -{ - init_before_main_module(); + void start_sync() { + CallbackDispatcher::start_sync(); + } + + void shutdown_sync() { + CallbackDispatcher::stop_sync(); + } + + void debug_color(int ansi_color) { + ::set_debug_color(Adapter::session(), ansi_color); + } + + void leave_device_group() { + ::leave_device_group(Adapter::session()); + } + + bool is_sync_active() { + return Adapter::is_sync_running(); + } + + void testfunc() { + _messageToSend(NULL); + } - // Module init function called by pEp.init() - def("_init_after_main_module", _init_after_main_module); - def("testfunc", &testfunc); + void deliverHandshakeResult(int result, object identities) { + identity_list *shared_identities = nullptr; + if (identities != boost::python::api::object() && boost::python::len(identities)) { + shared_identities = new_identity_list(nullptr); + if (!shared_identities) + throw bad_alloc(); + + try { + identity_list *si = shared_identities; + for (int i = 0; i < boost::python::len(identities); ++i) { + Identity ident = extract(identities[i]); + si = identity_list_add(si, ident); + if (!si) + throw bad_alloc(); + } + } + catch (exception &ex) { + free_identity_list(shared_identities); + throw ex; + } + } + + PEP_STATUS status = ::deliverHandshakeResult(Adapter::session(), (sync_handshake_result) result, shared_identities); + free_identity_list(shared_identities); + _throw_status(status); + } - docstring_options doc_options(true, false, false); - boost::locale::generator gen; - std::locale::global(gen("")); + BOOST_PYTHON_MODULE(native_pEp) { + init_before_main_module(); + + // Module init function called by pEp.init() + def("_init_after_main_module", _init_after_main_module); + def("testfunc", &testfunc); + + docstring_options doc_options(true, false, false); + boost::locale::generator gen; + std::locale::global(gen("")); // _scope = new scope(); - scope().attr("about") = about(); - scope().attr("per_user_directory") = per_user_directory(); - scope().attr("per_machine_directory") = per_machine_directory(); - scope().attr("engine_version") = get_engine_version(); - scope().attr("protocol_version") = get_protocol_version(); - - def("passive_mode", config_passive_mode, - "do not attach pub keys to all messages"); - - def("unencrypted_subject", config_unencrypted_subject, - "do not encrypt the subject of messages"); - - def("key_reset", key_reset_user, - "reset the default database status for the user / keypair provided\n" - "This will effectively perform key_reset on each identity\n" - "associated with the key and user_id, if a key is provided, and for\n" - "each key (and all of their identities) if an fpr is not."); - - def("key_reset", key_reset_user2, - "reset the default database status for the user / keypair provided\n" - "This will effectively perform key_reset on each identity\n" - "associated with the key and user_id, if a key is provided, and for\n" - "each key (and all of their identities) if an fpr is not."); - - def("key_reset_all_own_keys", key_reset_all_own_keys, - "revoke and mistrust all own keys, generate new keys for all\n" - "own identities, and opportunistically communicate key reset\n" - "information to people we have recently contacted."); - - auto identity_class = class_("Identity", - "Identity(address, username, user_id='', fpr='', comm_type=0, lang='en')\n" - "\n" - "represents a p≡p identity\n" - "\n" - "an identity is a network address, under which a user is represented in\n" - "the network\n" - "\n" - " address network address, either an SMTP address or a URI\n" - " username real name or nickname for user\n" - " user_id ID this user is handled by the application\n" - " fpr full fingerprint of the key being used as key ID,\n" - " hex encoded\n" - " comm_type first rating level of this communication channel\n" - " lang ISO 639-1 language code for language being preferred\n" - " on this communication channel\n" - ) - .def(boost::python::init()) - .def(boost::python::init()) - .def(boost::python::init()) - .def(boost::python::init()) - .def(boost::python::init()) - .def(boost::python::init()) - .def("__repr__", &Identity::_repr) - .def("__str__", &Identity::_str, - "string representation of this identity\n" - "following the pattern 'username < address >'\n" + scope().attr("about") = about(); + scope().attr("per_user_directory") = per_user_directory(); + scope().attr("per_machine_directory") = per_machine_directory(); + scope().attr("engine_version") = get_engine_version(); + scope().attr("protocol_version") = get_protocol_version(); + + def("passive_mode", config_passive_mode, + "do not attach pub keys to all messages"); + + def("unencrypted_subject", config_unencrypted_subject, + "do not encrypt the subject of messages"); + + def("key_reset", key_reset_user, + "reset the default database status for the user / keypair provided\n" + "This will effectively perform key_reset on each identity\n" + "associated with the key and user_id, if a key is provided, and for\n" + "each key (and all of their identities) if an fpr is not."); + + def("key_reset", key_reset_user2, + "reset the default database status for the user / keypair provided\n" + "This will effectively perform key_reset on each identity\n" + "associated with the key and user_id, if a key is provided, and for\n" + "each key (and all of their identities) if an fpr is not."); + + def("key_reset_all_own_keys", key_reset_all_own_keys, + "revoke and mistrust all own keys, generate new keys for all\n" + "own identities, and opportunistically communicate key reset\n" + "information to people we have recently contacted."); + + auto identity_class = class_("Identity", + "Identity(address, username, user_id='', fpr='', comm_type=0, lang='en')\n" + "\n" + "represents a p≡p identity\n" + "\n" + "an identity is a network address, under which a user is represented in\n" + "the network\n" + "\n" + " address network address, either an SMTP address or a URI\n" + " username real name or nickname for user\n" + " user_id ID this user is handled by the application\n" + " fpr full fingerprint of the key being used as key ID,\n" + " hex encoded\n" + " comm_type first rating level of this communication channel\n" + " lang ISO 639-1 language code for language being preferred\n" + " on this communication channel\n" + ) + .def(boost::python::init()) + .def(boost::python::init()) + .def(boost::python::init()) + .def(boost::python::init()) + .def(boost::python::init()) + .def(boost::python::init()) + .def("__repr__", &Identity::_repr) + .def("__str__", &Identity::_str, + "string representation of this identity\n" + "following the pattern 'username < address >'\n" ) - .def("key_reset", &Identity::key_reset, + .def("key_reset", &Identity::key_reset, boost::python::arg("fpr")=object(""), - "reset the default database status for the identity / keypair provided. If this\n" - "corresponds to the own user and a private key, also revoke the key, generate a\n" - "new one, and communicate the reset to recently contacted pEp partners for this\n" - "identity. If it does not, remove the key from the keyring; the key's status is\n" - "completely fresh on next contact from the partner.") + "reset the default database status for the identity / keypair provided. If this\n" + "corresponds to the own user and a private key, also revoke the key, generate a\n" + "new one, and communicate the reset to recently contacted pEp partners for this\n" + "identity. If it does not, remove the key from the keyring; the key's status is\n" + "completely fresh on next contact from the partner.") - .def("key_mistrusted", &Identity::key_mistrusted, + .def("key_mistrusted", &Identity::key_mistrusted, boost::python::arg("fpr")=object(""), - "If you want updated trust on the identity, you ll have" - "to call update_identity or myself respectively after this." - "N.B. If you are calling this on a key that is the identity or user default," - "it will be removed as the default key for ANY identity and user for which" - "it is the default. Please keep in mind that the undo in undo_last_mistrust" - "will only undo the current identity's / it's user's default, not any" - "other identities which may be impacted (this will not affect most use cases)") - - .def("enable_for_sync", &Identity::enable_for_sync, + "If you want updated trust on the identity, you ll have" + "to call update_identity or myself respectively after this." + "N.B. If you are calling this on a key that is the identity or user default," + "it will be removed as the default key for ANY identity and user for which" + "it is the default. Please keep in mind that the undo in undo_last_mistrust" + "will only undo the current identity's / it's user's default, not any" + "other identities which may be impacted (this will not affect most use cases)") + + .def("enable_for_sync", &Identity::enable_for_sync, "Enable own identity for p≡p sync.\n\n" "Only use this on own identities, which are used as accounts.\n") - .def("disable_for_sync", &Identity::disable_for_sync, + .def("disable_for_sync", &Identity::disable_for_sync, "Disable own identity for p≡p sync.\n\n" "Only use this on own identities, which are used as accounts.\n") - .add_property("address", (string(Identity::*)()) &Identity::address, + .add_property("address", (string(Identity::*)()) &Identity::address, (void(Identity::*)(string)) &Identity::address, "email address or URI") - .add_property("fpr", (string(Identity::*)()) &Identity::fpr, + .add_property("fpr", (string(Identity::*)()) &Identity::fpr, (void(Identity::*)(string)) &Identity::fpr, "key ID (full fingerprint, hex encoded)") - .add_property("user_id", (string(Identity::*)()) &Identity::user_id, + .add_property("user_id", (string(Identity::*)()) &Identity::user_id, (void(Identity::*)(string)) &Identity::user_id, "ID of person associated or 'pEp_own_userId' if own identity") - .add_property("username", (string(Identity::*)()) &Identity::username, + .add_property("username", (string(Identity::*)()) &Identity::username, (void(Identity::*)(string)) &Identity::username, "name in full of person associated") - .add_property("comm_type", (int(Identity::*)()) + .add_property("comm_type", (int(Identity::*)()) (PEP_comm_type(Identity::*)()) &Identity::comm_type, (void(Identity::*)(int)) (void(Identity::*)(PEP_comm_type)) &Identity::comm_type, - "communication type, first rating level (p≡p internal)") - .add_property("lang", (string(Identity::*)()) &Identity::lang, + "communication type, first rating level (p≡p internal)") + .add_property("lang", (string(Identity::*)()) &Identity::lang, (void(Identity::*)(string)) &Identity::lang, "ISO 639-1 language code") - .add_property("flags", (identity_flags_t(Identity::*)()) &Identity::flags, + .add_property("flags", (identity_flags_t(Identity::*)()) &Identity::flags, (void(Identity::*)(identity_flags_t)) &Identity::flags, "flags (p≡p internal)") - .add_property("rating", &Identity::rating, "rating of Identity") - .add_property("color", &Identity::color, "color of Identity as PEP_color") - .add_property("is_pEp_user", &Identity::is_pEp_user, "True if this is an identity of a pEp user") - .def("__deepcopy__", &Identity::deepcopy) - .def("update", &Identity::update, "update Identity") - .def("__copy__", &Identity::copy); - - identity_class.attr("PEP_OWN_USERID") = "pEp_own_userId"; - - auto blob_class = class_("Blob", - "Blob(data, mime_type='', filename='')\n" - "\n" - "Binary large object\n" - "\n" - " data bytes-like object\n" - " mime_type MIME type for the data\n" - " filename filename to store the data\n" , - boost::python::init< object, char const*, char const* >(args("data", "mime_type", "filename"))) - .def(boost::python::init()) - .def(boost::python::init()) - .def("__repr__", &Message::Blob::_repr) - .def("__len__", &Message::Blob::size, "size of Blob data in bytes") - .def("decode", (string(Message::Blob::*)()) &Message::Blob::decode) - .def("decode", (string(Message::Blob::*)(string)) &Message::Blob::decode, - "text = blob.decode(encoding='')\n" - "\n" - "decode Blob data into string depending on MIME type if encoding=''\n" - "\n" - " mime_type='application/pEp.sync' decode as 'pEp.sync'\n" - " mime_type='application/pEp.keyreset' decode as 'pEp.keyreset'\n" - " other mime_type decode as 'ascii' by default\n" + .add_property("rating", &Identity::rating, "rating of Identity") + .add_property("color", &Identity::color, "color of Identity as PEP_color") + .add_property("is_pEp_user", &Identity::is_pEp_user, "True if this is an identity of a pEp user") + .def("__deepcopy__", &Identity::deepcopy) + .def("update", &Identity::update, "update Identity") + .def("__copy__", &Identity::copy); + + identity_class.attr("PEP_OWN_USERID") = "pEp_own_userId"; + + auto blob_class = class_("Blob", + "Blob(data, mime_type='', filename='')\n" + "\n" + "Binary large object\n" + "\n" + " data bytes-like object\n" + " mime_type MIME type for the data\n" + " filename filename to store the data\n", + boost::python::init< object, char const*, char const* >(args("data", "mime_type", "filename"))) + .def(boost::python::init()) + .def(boost::python::init()) + .def("__repr__", &Message::Blob::_repr) + .def("__len__", &Message::Blob::size, "size of Blob data in bytes") + .def("decode", (string(Message::Blob::*)()) &Message::Blob::decode) + .def("decode", (string(Message::Blob::*)(string)) &Message::Blob::decode, + "text = blob.decode(encoding='')\n" + "\n" + "decode Blob data into string depending on MIME type if encoding=''\n" + "\n" + " mime_type='application/pEp.sync' decode as 'pEp.sync'\n" + " mime_type='application/pEp.keyreset' decode as 'pEp.keyreset'\n" + " other mime_type decode as 'ascii' by default\n" ) - .add_property("mime_type", (string(Message::Blob::*)()) &Message::Blob::mime_type, + .add_property("mime_type", (string(Message::Blob::*)()) &Message::Blob::mime_type, (void(Message::Blob::*)(string)) &Message::Blob::mime_type, "MIME type of object in Blob") - .add_property("filename", (string(Message::Blob::*)()) &Message::Blob::filename, + .add_property("filename", (string(Message::Blob::*)()) &Message::Blob::filename, (void(Message::Blob::*)(string)) &Message::Blob::filename, "filename of object in Blob"); - ((PyTypeObject *)(void *)blob_class.ptr())->tp_as_buffer = &Message::Blob::bp; - - auto message_class = class_("Message", - "Message(dir=1, from=None)\n" - "\n" - "new p≡p message\n" - "\n" - " dir 1 for outgoing, 2 for incoming\n" - " from Identity() of sender\n" - "\n" - "Message(mime_text)\n" - "\n" - "new incoming p≡p message\n" - "\n" - " mime_text text in Multipurpose Internet Mail Extensions format\n" + ((PyTypeObject *)(void *)blob_class.ptr())->tp_as_buffer = &Message::Blob::bp; + + auto message_class = class_("Message", + "Message(dir=1, from=None)\n" + "\n" + "new p≡p message\n" + "\n" + " dir 1 for outgoing, 2 for incoming\n" + " from Identity() of sender\n" + "\n" + "Message(mime_text)\n" + "\n" + "new incoming p≡p message\n" + "\n" + " mime_text text in Multipurpose Internet Mail Extensions format\n" ) - .def(boost::python::init()) - .def(boost::python::init()) - .def(boost::python::init()) - .def("__str__", &Message::_str, - "the string representation of a Message is it's MIME text" + .def(boost::python::init()) + .def(boost::python::init()) + .def(boost::python::init()) + .def("__str__", &Message::_str, + "the string representation of a Message is it's MIME text" ) - .def("__repr__", &Message::_repr) - .add_property("dir", (int(Message::*)()) + .def("__repr__", &Message::_repr) + .add_property("dir", (int(Message::*)()) (PEP_msg_direction(Message::*)()) &Message::dir, (void(Message::*)(int)) (void(Message::*)(PEP_msg_direction)) &Message::dir, "0: incoming, 1: outgoing message") - .add_property("id", (string(Message::*)()) &Message::id, + .add_property("id", (string(Message::*)()) &Message::id, (void(Message::*)(string)) &Message::id, "message ID") - .add_property("shortmsg", (string(Message::*)()) &Message::shortmsg, + .add_property("shortmsg", (string(Message::*)()) &Message::shortmsg, (void(Message::*)(string)) &Message::shortmsg, "subject or short message") - .add_property("longmsg", (string(Message::*)()) &Message::longmsg, + .add_property("longmsg", (string(Message::*)()) &Message::longmsg, (void(Message::*)(string)) &Message::longmsg, "body or long version of message") - .add_property("longmsg_formatted", (string(Message::*)()) &Message::longmsg_formatted, + .add_property("longmsg_formatted", (string(Message::*)()) &Message::longmsg_formatted, (void(Message::*)(string)) &Message::longmsg_formatted, "HTML body or fromatted long version of message") - .add_property("attachments", (boost::python::tuple(Message::*)()) &Message::attachments, + .add_property("attachments", (boost::python::tuple(Message::*)()) &Message::attachments, (void(Message::*)(boost::python::list)) &Message::attachments, "tuple of Blobs with attachments; setting moves Blobs to attachment tuple") - .add_property("sent", (time_t(Message::*)()) &Message::sent, + .add_property("sent", (time_t(Message::*)()) &Message::sent, (void(Message::*)(time_t)) &Message::sent, "time when message was sent in UTC seconds since epoch") - .add_property("recv", (time_t(Message::*)()) &Message::recv, + .add_property("recv", (time_t(Message::*)()) &Message::recv, (void(Message::*)(time_t)) &Message::recv, "time when message was received in UTC seconds since epoch") - .add_property("from_", (Identity(Message::*)()) &Message::from, + .add_property("from_", (Identity(Message::*)()) &Message::from, (void(Message::*)(object)) &Message::from, "identity where message is from") - .add_property("to", (boost::python::list(Message::*)()) &Message::to, + .add_property("to", (boost::python::list(Message::*)()) &Message::to, (void(Message::*)(boost::python::list)) &Message::to, "list of identities message is going to") - .add_property("recv_by", (Identity(Message::*)()) &Message::recv_by, + .add_property("recv_by", (Identity(Message::*)()) &Message::recv_by, (void(Message::*)(object)) &Message::recv_by, "identity where message was received by") - .add_property("cc", (boost::python::list(Message::*)()) &Message::cc, + .add_property("cc", (boost::python::list(Message::*)()) &Message::cc, (void(Message::*)(boost::python::list)) &Message::cc, "list of identities message is going cc") - .add_property("bcc", (boost::python::list(Message::*)()) &Message::bcc, + .add_property("bcc", (boost::python::list(Message::*)()) &Message::bcc, (void(Message::*)(boost::python::list)) &Message::bcc, "list of identities message is going bcc") - .add_property("reply_to", (boost::python::list(Message::*)()) &Message::reply_to, + .add_property("reply_to", (boost::python::list(Message::*)()) &Message::reply_to, (void(Message::*)(boost::python::list)) &Message::reply_to, "list of identities where message will be replied to") - .add_property("in_reply_to", (boost::python::list(Message::*)()) &Message::in_reply_to, + .add_property("in_reply_to", (boost::python::list(Message::*)()) &Message::in_reply_to, (void(Message::*)(boost::python::list)) &Message::in_reply_to, "in_reply_to list") - .add_property("references", (boost::python::list(Message::*)()) &Message::references, + .add_property("references", (boost::python::list(Message::*)()) &Message::references, (void(Message::*)(boost::python::list)) &Message::references, "message IDs of messages this one is referring to") - .add_property("keywords", (boost::python::list(Message::*)()) &Message::keywords, + .add_property("keywords", (boost::python::list(Message::*)()) &Message::keywords, (void(Message::*)(boost::python::list)) &Message::keywords, "keywords this message should be stored under") - .add_property("comments", (string(Message::*)()) &Message::comments, + .add_property("comments", (string(Message::*)()) &Message::comments, (void(Message::*)(string)) &Message::comments, "comments added to message") - .add_property("opt_fields", (dict(Message::*)()) &Message::opt_fields, + .add_property("opt_fields", (dict(Message::*)()) &Message::opt_fields, (void(Message::*)(dict)) &Message::opt_fields, "opt_fields of message") - .add_property("enc_format", (int(Message::*)()) + .add_property("enc_format", (int(Message::*)()) (PEP_enc_format(Message::*)()) &Message::enc_format, (void(Message::*)(int)) (void(Message::*)(PEP_enc_format)) &Message::enc_format, "0: unencrypted, 1: inline PGP, 2: S/MIME, 3: PGP/MIME, 4: p≡p format") - .def("encrypt", (Message(Message::*)())&Message::encrypt) - .def("encrypt", (Message(Message::*)(boost::python::list))&Message::_encrypt) - .def("encrypt", (Message(Message::*)(boost::python::list,int))&Message::_encrypt) - .def("encrypt", (Message(Message::*)(boost::python::list,int,int))&Message::_encrypt, - "msg2 = msg1.encrypt(extra_keys=[], enc_format='pEp', flags=0)\n" - "\n" - "encrypts a p≡p message and returns the encrypted message\n" - "\n" - " extra_keys list of strings with fingerprints for extra keys to use\n" - " for encryption\n" - " enc_format 0 for none, 1 for partitioned, 2 for S/MIME,\n" - " 3 for PGP/MIME, 4 for pEp\n" - " flags 1 is force encryption\n" + .def("encrypt", (Message(Message::*)())&Message::encrypt) + .def("encrypt", (Message(Message::*)(boost::python::list))&Message::_encrypt) + .def("encrypt", (Message(Message::*)(boost::python::list, int))&Message::_encrypt) + .def("encrypt", (Message(Message::*)(boost::python::list, int, int))&Message::_encrypt, + "msg2 = msg1.encrypt(extra_keys=[], enc_format='pEp', flags=0)\n" + "\n" + "encrypts a p≡p message and returns the encrypted message\n" + "\n" + " extra_keys list of strings with fingerprints for extra keys to use\n" + " for encryption\n" + " enc_format 0 for none, 1 for partitioned, 2 for S/MIME,\n" + " 3 for PGP/MIME, 4 for pEp\n" + " flags 1 is force encryption\n" ) - .def("decrypt", &Message::decrypt, boost::python::arg("flags")=0, - "msg2, keys, rating, flags = msg1.decrypt()\n" - "\n" - "decrypts a p≡p message and returns a tuple with data\n" - "\n" - " msg the decrypted p≡p message\n" - " keys a list of keys being used\n" - " rating the rating of the message as integer\n" - " flags flags set while decryption\n" + .def("decrypt", &Message::decrypt, boost::python::arg("flags")=0, + "msg2, keys, rating, flags = msg1.decrypt()\n" + "\n" + "decrypts a p≡p message and returns a tuple with data\n" + "\n" + " msg the decrypted p≡p message\n" + " keys a list of keys being used\n" + " rating the rating of the message as integer\n" + " flags flags set while decryption\n" ) - .add_property("outgoing_rating", &Message::outgoing_rating, "rating outgoing message will have") - .add_property("outgoing_color", &Message::outgoing_color, "color outgoing message will have as PEP_color") - .def("__deepcopy__", &Message::deepcopy) - .def("__copy__", &Message::copy); - - // basic API and key management API - - def("update_identity", &update_identity, - "update_identity(ident)\n" - "\n" - "update identity information\n" - "call this to complete identity information when you at least have an address\n" - ); - def("myself", &myself, - "myself(ident)\n" - "\n" - "ensures that the own identity is being complete\n" - "supply ident.address and ident.username\n" - ); - def("trust_personal_key", &trust_personal_key, - "trust_personal_key(ident)\n" - "\n" - "mark a key as trusted with a person\n" - ); - - enum_("identity_flags") - .value("PEP_idf_not_for_sync", PEP_idf_not_for_sync) - .value("PEP_idf_list", PEP_idf_list) - .value("PEP_idf_devicegroup", PEP_idf_devicegroup); - - def("set_identity_flags", &set_identity_flags, - "set_identity_flags(ident, flags)\n" - "\n" - "set identity flags\n" - ); - - def("unset_identity_flags", &unset_identity_flags, - "unset_identity_flags(ident, flags)\n" - "\n" - "unset identity flags\n" - ); - - def("key_reset_trust", &key_reset_trust, - "key_reset_trust(ident)\n" - "\n" - "reset trust bit or explicitly mistrusted status for an identity and " - "its accompanying key/user_id pair\n" - ); - - def("import_key", &import_key, - "private_key_list = import_key(key_data)\n" - "\n" - "import key(s) from key_data\n" - ); - - def("export_key", &export_key, - "key_data = export_key(identity)\n" - "\n" - "export key(s) of identity\n" - ); - - def("export_secret_key", &export_secret_key, - "key_data = export_seret_key(identity)\n" - "\n" - "export secret key(s) of identity\n" - ); - - def("set_own_key", &set_own_key, - "set_own_key(me, fpr)\n" - "\n" - "mark a key as an own key, and make it the default key\n" - "\n" - "me Own identity for which to add the existing key\n" - "fpr The fingerprint of the key to be added\n" - "\n" - "me->address, me->user_id and me->username must be set to valid data\n" - "myself() is called by set_own_key() without key generation\n" - "me->flags are ignored\n" - "me->address must not be an alias\n" - "me->fpr will be ignored and replaced by fpr\n" - ); - - // message API - - enum_("rating") - .value("_undefined", PEP_rating_undefined) - .value("cannot_decrypt", PEP_rating_cannot_decrypt) - .value("have_no_key", PEP_rating_have_no_key) - .value("unencrypted", PEP_rating_unencrypted) - .value("unreliable", PEP_rating_unreliable) - .value("reliable", PEP_rating_reliable) - .value("trusted", PEP_rating_trusted) - .value("trusted_and_anonymized", PEP_rating_trusted_and_anonymized) - .value("fully_anonymous", PEP_rating_fully_anonymous) - .value("mistrust", PEP_rating_mistrust) - .value("b0rken", PEP_rating_b0rken) - .value("under_attack", PEP_rating_under_attack); - - enum_("colorvalue") - .value("no_color", PEP_color_no_color) - .value("yellow", PEP_color_yellow) - .value("green", PEP_color_green) - .value("red", PEP_color_red); - - - def("incoming_message", &incoming_message, - "msg = incoming_message(mime_text)\n" - "\n" - "create an incoming message from a MIME text" - ); - def("outgoing_message", &outgoing_message, - "msg = outgoing_message(ident)\n" - "\n" - "create an outgoing message using an own identity" - ); - def("color", &_color, - "c = color(rating)\n" - "\n" - "calculate color value out of rating. Returns PEP_color" - ); - def("trustwords", &_trustwords, - "text = trustwords(ident_own, ident_partner)\n" - "\n" - "calculate trustwords for two Identities"); - - // Sync API - - enum_("sync_handshake_signal") - .value("SYNC_NOTIFY_UNDEFINED" , SYNC_NOTIFY_UNDEFINED) - .value("SYNC_NOTIFY_INIT_ADD_OUR_DEVICE" , SYNC_NOTIFY_INIT_ADD_OUR_DEVICE) - .value("SYNC_NOTIFY_INIT_ADD_OTHER_DEVICE" , SYNC_NOTIFY_INIT_ADD_OTHER_DEVICE) - .value("SYNC_NOTIFY_INIT_FORM_GROUP" , SYNC_NOTIFY_INIT_FORM_GROUP) - .value("SYNC_NOTIFY_TIMEOUT" , SYNC_NOTIFY_TIMEOUT) - .value("SYNC_NOTIFY_ACCEPTED_DEVICE_ADDED" , SYNC_NOTIFY_ACCEPTED_DEVICE_ADDED) - .value("SYNC_NOTIFY_ACCEPTED_GROUP_CREATED", SYNC_NOTIFY_ACCEPTED_GROUP_CREATED) - .value("SYNC_NOTIFY_ACCEPTED_DEVICE_ACCEPTED", SYNC_NOTIFY_ACCEPTED_DEVICE_ACCEPTED) - .value("SYNC_NOTIFY_SOLE" , SYNC_NOTIFY_SOLE) - .value("SYNC_NOTIFY_IN_GROUP" , SYNC_NOTIFY_IN_GROUP); + .add_property("outgoing_rating", &Message::outgoing_rating, "rating outgoing message will have") + .add_property("outgoing_color", &Message::outgoing_color, "color outgoing message will have as PEP_color") + .def("__deepcopy__", &Message::deepcopy) + .def("__copy__", &Message::copy); + + // basic API and key management API + + def("update_identity", &update_identity, + "update_identity(ident)\n" + "\n" + "update identity information\n" + "call this to complete identity information when you at least have an address\n" + ); + def("myself", &myself, + "myself(ident)\n" + "\n" + "ensures that the own identity is being complete\n" + "supply ident.address and ident.username\n" + ); + def("trust_personal_key", &trust_personal_key, + "trust_personal_key(ident)\n" + "\n" + "mark a key as trusted with a person\n" + ); + + enum_("identity_flags") + .value("PEP_idf_not_for_sync", PEP_idf_not_for_sync) + .value("PEP_idf_list", PEP_idf_list) + .value("PEP_idf_devicegroup", PEP_idf_devicegroup); + + def("set_identity_flags", &set_identity_flags, + "set_identity_flags(ident, flags)\n" + "\n" + "set identity flags\n" + ); + + def("unset_identity_flags", &unset_identity_flags, + "unset_identity_flags(ident, flags)\n" + "\n" + "unset identity flags\n" + ); + + def("key_reset_trust", &key_reset_trust, + "key_reset_trust(ident)\n" + "\n" + "reset trust bit or explicitly mistrusted status for an identity and " + "its accompanying key/user_id pair\n" + ); + + def("import_key", &import_key, + "private_key_list = import_key(key_data)\n" + "\n" + "import key(s) from key_data\n" + ); + + def("export_key", &export_key, + "key_data = export_key(identity)\n" + "\n" + "export key(s) of identity\n" + ); + + def("export_secret_key", &export_secret_key, + "key_data = export_seret_key(identity)\n" + "\n" + "export secret key(s) of identity\n" + ); + + def("set_own_key", &set_own_key, + "set_own_key(me, fpr)\n" + "\n" + "mark a key as an own key, and make it the default key\n" + "\n" + "me Own identity for which to add the existing key\n" + "fpr The fingerprint of the key to be added\n" + "\n" + "me->address, me->user_id and me->username must be set to valid data\n" + "myself() is called by set_own_key() without key generation\n" + "me->flags are ignored\n" + "me->address must not be an alias\n" + "me->fpr will be ignored and replaced by fpr\n" + ); + + // message API + + enum_("rating") + .value("_undefined", PEP_rating_undefined) + .value("cannot_decrypt", PEP_rating_cannot_decrypt) + .value("have_no_key", PEP_rating_have_no_key) + .value("unencrypted", PEP_rating_unencrypted) + .value("unreliable", PEP_rating_unreliable) + .value("reliable", PEP_rating_reliable) + .value("trusted", PEP_rating_trusted) + .value("trusted_and_anonymized", PEP_rating_trusted_and_anonymized) + .value("fully_anonymous", PEP_rating_fully_anonymous) + .value("mistrust", PEP_rating_mistrust) + .value("b0rken", PEP_rating_b0rken) + .value("under_attack", PEP_rating_under_attack); + + enum_("colorvalue") + .value("no_color", PEP_color_no_color) + .value("yellow", PEP_color_yellow) + .value("green", PEP_color_green) + .value("red", PEP_color_red); + + + def("incoming_message", &incoming_message, + "msg = incoming_message(mime_text)\n" + "\n" + "create an incoming message from a MIME text" + ); + def("outgoing_message", &outgoing_message, + "msg = outgoing_message(ident)\n" + "\n" + "create an outgoing message using an own identity" + ); + def("color", &_color, + "c = color(rating)\n" + "\n" + "calculate color value out of rating. Returns PEP_color" + ); + def("trustwords", &_trustwords, + "text = trustwords(ident_own, ident_partner)\n" + "\n" + "calculate trustwords for two Identities"); + + // Sync API + + enum_("sync_handshake_signal") + .value("SYNC_NOTIFY_UNDEFINED", SYNC_NOTIFY_UNDEFINED) + .value("SYNC_NOTIFY_INIT_ADD_OUR_DEVICE", SYNC_NOTIFY_INIT_ADD_OUR_DEVICE) + .value("SYNC_NOTIFY_INIT_ADD_OTHER_DEVICE", SYNC_NOTIFY_INIT_ADD_OTHER_DEVICE) + .value("SYNC_NOTIFY_INIT_FORM_GROUP", SYNC_NOTIFY_INIT_FORM_GROUP) + .value("SYNC_NOTIFY_TIMEOUT", SYNC_NOTIFY_TIMEOUT) + .value("SYNC_NOTIFY_ACCEPTED_DEVICE_ADDED", SYNC_NOTIFY_ACCEPTED_DEVICE_ADDED) + .value("SYNC_NOTIFY_ACCEPTED_GROUP_CREATED", SYNC_NOTIFY_ACCEPTED_GROUP_CREATED) + .value("SYNC_NOTIFY_ACCEPTED_DEVICE_ACCEPTED", SYNC_NOTIFY_ACCEPTED_DEVICE_ACCEPTED) + .value("SYNC_NOTIFY_SOLE", SYNC_NOTIFY_SOLE) + .value("SYNC_NOTIFY_IN_GROUP", SYNC_NOTIFY_IN_GROUP); // auto user_interface_class = class_( // "UserInterface", @@ -627,47 +610,47 @@ BOOST_PYTHON_MODULE(native_pEp) // "call to deliver the handshake result of the handshake dialog" // ); - def("deliver_handshake_result", &deliverHandshakeResult, boost::python::arg("identities")=object(), - "deliverHandshakeResult(self, result, identities=None)\n" - "\n" - " result -1: cancel, 0: accepted, 1: rejected\n" - " identities list of identities to share or None for all\n" - "\n" - "call to deliver the handshake result of the handshake dialog" - ); - - def("start_sync", &start_sync, - "start_sync()\n" - "\n" - "starts the sync thread" - ); - - def("shutdown_sync", &shutdown_sync, - "shutdown_sync()\n" - "\n" - "call this from another thread to shut down the sync thread\n" - ); - - def("debug_color", &debug_color, - "for debug builds set ANSI color value"); - - def("leave_device_group", &leave_device_group, - "leave_device_group()\n" - "\n" - "call this for a grouped device, which should leave\n" - ); - - def("is_sync_active", &is_sync_active, - "is_sync_active()\n" - "\n" - "True if sync is active, False otherwise\n" - ); - - - // codecs - call< object >(((object)(import("codecs").attr("register"))).ptr(), make_function(sync_search)); - call< object >(((object)(import("codecs").attr("register"))).ptr(), make_function(distribution_search)); -} - -} // namespace PythonAdapter + def("deliver_handshake_result", &deliverHandshakeResult, boost::python::arg("identities")=object(), + "deliverHandshakeResult(self, result, identities=None)\n" + "\n" + " result -1: cancel, 0: accepted, 1: rejected\n" + " identities list of identities to share or None for all\n" + "\n" + "call to deliver the handshake result of the handshake dialog" + ); + + def("start_sync", &start_sync, + "start_sync()\n" + "\n" + "starts the sync thread" + ); + + def("shutdown_sync", &shutdown_sync, + "shutdown_sync()\n" + "\n" + "call this from another thread to shut down the sync thread\n" + ); + + def("debug_color", &debug_color, + "for debug builds set ANSI color value"); + + def("leave_device_group", &leave_device_group, + "leave_device_group()\n" + "\n" + "call this for a grouped device, which should leave\n" + ); + + def("is_sync_active", &is_sync_active, + "is_sync_active()\n" + "\n" + "True if sync is active, False otherwise\n" + ); + + + // codecs + call< object >(((object)(import("codecs").attr("register"))).ptr(), make_function(sync_search)); + call< object >(((object)(import("codecs").attr("register"))).ptr(), make_function(distribution_search)); + } + + } // namespace PythonAdapter } // namespace pEp diff --git a/src/pEp/native_pEp/pEpmodule.hh b/src/pEp/native_pEp/pEpmodule.hh index 0b72c96..8ae3c25 100644 --- a/src/pEp/native_pEp/pEpmodule.hh +++ b/src/pEp/native_pEp/pEpmodule.hh @@ -11,18 +11,25 @@ #include "message.hh" namespace pEp { -namespace PythonAdapter { - -extern string device_name; -void config_passive_mode(bool enable); -void config_unencrypted_subject(bool enable); -void key_reset_user(string user_id, string fpr); -void key_reset_all_own_keys(); -void _throw_status(PEP_STATUS status); -PEP_STATUS _messageToSend(::message *msg); -PEP_STATUS notifyHandshake(pEp_identity *me, pEp_identity *partner, sync_handshake_signal signal); - -} /* namespace PythonAdapter */ + namespace PythonAdapter { + + extern string device_name; + + void config_passive_mode(bool enable); + + void config_unencrypted_subject(bool enable); + + void key_reset_user(string user_id, string fpr); + + void key_reset_all_own_keys(); + + void _throw_status(PEP_STATUS status); + + PEP_STATUS _messageToSend(::message *msg); + + PEP_STATUS notifyHandshake(pEp_identity *me, pEp_identity *partner, sync_handshake_signal signal); + + } /* namespace PythonAdapter */ } /* namespace pEp */ #endif /* PEPMODULE_HH */ \ No newline at end of file diff --git a/src/pEp/native_pEp/str_attr.cc b/src/pEp/native_pEp/str_attr.cc index 96810ad..74f44ee 100644 --- a/src/pEp/native_pEp/str_attr.cc +++ b/src/pEp/native_pEp/str_attr.cc @@ -10,175 +10,163 @@ #include "str_attr.hh" namespace pEp { -namespace PythonAdapter { -using namespace std; -using namespace boost::python; -using namespace boost::locale; - -object repr(object s) -{ - return s.attr("__repr__")(); -} - -string repr(string s) -{ - str _s = s.c_str(); - object _r = _s.attr("__repr__")(); - string r = extract< string >(_r); - return r; -} - -string str_attr(char *&str) -{ - if (!str) - return string(""); - return string(str); -} - -void str_attr(char *&str, string value) -{ - string normalized = normalize(value, norm_nfc); - free(str); - str = strdup(normalized.c_str()); - if (!str) - throw bad_alloc(); -} - -time_t timestamp_attr(timestamp *&ts) -{ - if (!ts) - return 0; - - return timegm(ts); -} - -void timestamp_attr(timestamp *&ts, time_t value) -{ - free_timestamp(ts); - ts = new_timestamp(value); -} - -boost::python::list strlist_attr(stringlist_t *&sl) -{ - boost::python::list result; - - for (stringlist_t *_sl = sl; _sl && _sl->value; _sl = _sl->next) { - string s(_sl->value); - result.append(object(s)); - } - - return result; -} - -void strlist_attr(stringlist_t *&sl, boost::python::list value) -{ - stringlist_t *_sl = new_stringlist(NULL); - if (!_sl) - throw bad_alloc(); - - stringlist_t *_s = _sl; - for (int i=0; i extract_string(value[i]); - if (!extract_string.check()) { - free_stringlist(_sl); + namespace PythonAdapter { + using namespace std; + using namespace boost::python; + using namespace boost::locale; + + object repr(object s) { + return s.attr("__repr__")(); } - string s = extract_string(); - s = normalize(s, norm_nfc); - _s = stringlist_add(_s, s.c_str()); - if (!_s) { - free_stringlist(_sl); - throw bad_alloc(); + + string repr(string s) { + str _s = s.c_str(); + object _r = _s.attr("__repr__")(); + string r = extract(_r); + return r; } - } - free_stringlist(sl); - sl = _sl; -} + string str_attr(char *&str) { + if (!str) + return string(""); + return string(str); + } -dict strdict_attr(stringpair_list_t *&spl) -{ - dict result; + void str_attr(char *&str, string value) { + string normalized = normalize(value, norm_nfc); + free(str); + str = strdup(normalized.c_str()); + if (!str) + throw bad_alloc(); + } - for (stringpair_list_t *_spl = spl; _spl && _spl->value; _spl = - _spl->next) { - stringpair_t *p = _spl->value; - if (p->key && p->value) { - string key(p->key); - string value(p->value); + time_t timestamp_attr(timestamp *&ts) { + if (!ts) + return 0; - result[key] = value; + return timegm(ts); } - } - - return result; -} - -void strdict_attr(stringpair_list_t *&spl, dict value) -{ - stringpair_list_t *_spl = new_stringpair_list(NULL); - if (!_spl) - throw bad_alloc(); - - stringpair_list_t *_s = _spl; - for (int i=0; i extract_key(value.keys()[i]); - extract< string > extract_value(value.values()[i]); - - if (!(extract_key.check() && extract_value.check())) - free_stringpair_list(_spl); - - string key = extract_key(); - key = normalize(key, norm_nfc); - string _value = extract_value(); - _value = normalize(_value, norm_nfc); - stringpair_t *pair = new_stringpair(key.c_str(), _value.c_str()); - if (!pair) { - free_stringpair_list(_spl); - throw bad_alloc(); + + void timestamp_attr(timestamp *&ts, time_t value) { + free_timestamp(ts); + ts = new_timestamp(value); } - _s = stringpair_list_add(_s, pair); - if (!_s) { - free_stringpair_list(_spl); - throw bad_alloc(); + + boost::python::list strlist_attr(stringlist_t *&sl) { + boost::python::list result; + + for (stringlist_t *_sl = sl; _sl && _sl->value; _sl = _sl->next) { + string s(_sl->value); + result.append(object(s)); + } + + return result; } - } - - free_stringpair_list(spl); - spl = _spl; -} - -stringlist_t *to_stringlist(boost::python::list l) -{ - stringlist_t *result = new_stringlist(NULL); - if (!result) - throw bad_alloc(); - - stringlist_t *_s = result; - for (int i=0; i extract_string(l[i]); - if (!extract_string.check()) - free_stringlist(result); - string s = extract_string(); - _s = stringlist_add(_s, s.c_str()); - if (!_s) { - free_stringlist(result); - throw bad_alloc(); + + void strlist_attr(stringlist_t *&sl, boost::python::list value) { + stringlist_t *_sl = new_stringlist(NULL); + if (!_sl) + throw bad_alloc(); + + stringlist_t *_s = _sl; + for (int i = 0; i < len(value); i++) { + extract extract_string(value[i]); + if (!extract_string.check()) { + free_stringlist(_sl); + } + string s = extract_string(); + s = normalize(s, norm_nfc); + _s = stringlist_add(_s, s.c_str()); + if (!_s) { + free_stringlist(_sl); + throw bad_alloc(); + } + } + + free_stringlist(sl); + sl = _sl; } - } - - return result; -} - -boost::python::list from_stringlist(const stringlist_t *sl) -{ - boost::python::list result; - for (const stringlist_t *_sl = sl; _sl && _sl->value; _sl = _sl->next) { - string s = _sl->value; - result.append(s); - } - return result; -} - -} // namespace PythonAdapter + + dict strdict_attr(stringpair_list_t *&spl) { + dict result; + + for (stringpair_list_t *_spl = spl; _spl && _spl->value; _spl = + _spl->next) { + stringpair_t *p = _spl->value; + if (p->key && p->value) { + string key(p->key); + string value(p->value); + + result[key] = value; + } + } + + return result; + } + + void strdict_attr(stringpair_list_t *&spl, dict value) { + stringpair_list_t *_spl = new_stringpair_list(NULL); + if (!_spl) + throw bad_alloc(); + + stringpair_list_t *_s = _spl; + for (int i = 0; i < len(value); i++) { + extract extract_key(value.keys()[i]); + extract extract_value(value.values()[i]); + + if (!(extract_key.check() && extract_value.check())) + free_stringpair_list(_spl); + + string key = extract_key(); + key = normalize(key, norm_nfc); + string _value = extract_value(); + _value = normalize(_value, norm_nfc); + stringpair_t *pair = new_stringpair(key.c_str(), _value.c_str()); + if (!pair) { + free_stringpair_list(_spl); + throw bad_alloc(); + } + _s = stringpair_list_add(_s, pair); + if (!_s) { + free_stringpair_list(_spl); + throw bad_alloc(); + } + } + + free_stringpair_list(spl); + spl = _spl; + } + + stringlist_t *to_stringlist(boost::python::list l) { + stringlist_t *result = new_stringlist(NULL); + if (!result) + throw bad_alloc(); + + stringlist_t *_s = result; + for (int i = 0; i < len(l); i++) { + extract extract_string(l[i]); + if (!extract_string.check()) + free_stringlist(result); + string s = extract_string(); + _s = stringlist_add(_s, s.c_str()); + if (!_s) { + free_stringlist(result); + throw bad_alloc(); + } + } + + return result; + } + + boost::python::list from_stringlist(const stringlist_t *sl) { + boost::python::list result; + for (const stringlist_t *_sl = sl; _sl && _sl->value; _sl = _sl->next) { + string s = _sl->value; + result.append(s); + } + return result; + } + + } // namespace PythonAdapter } // namespace pEp { diff --git a/src/pEp/native_pEp/user_interface.cc b/src/pEp/native_pEp/user_interface.cc index 22be5db..f31ad82 100644 --- a/src/pEp/native_pEp/user_interface.cc +++ b/src/pEp/native_pEp/user_interface.cc @@ -8,82 +8,76 @@ #include "user_interface.hh" namespace pEp { -namespace PythonAdapter { -using namespace std; -using namespace boost::python; - -UserInterface *UserInterface::_ui = nullptr; - -UserInterface::UserInterface() -{ - if (_ui) - throw runtime_error("only one UserInterface thread allowed"); - _ui = this; -} - -UserInterface::~UserInterface() -{ - _ui = nullptr; -} - -UserInterface_callback::UserInterface_callback(PyObject *self) : - UserInterface(), _self(self) -{ + namespace PythonAdapter { + using namespace std; + using namespace boost::python; + + UserInterface *UserInterface::_ui = nullptr; + + UserInterface::UserInterface() { + if (_ui) + throw runtime_error("only one UserInterface thread allowed"); + _ui = this; + } + + UserInterface::~UserInterface() { + _ui = nullptr; + } + + UserInterface_callback::UserInterface_callback(PyObject *self) : + UserInterface(), _self(self) { // adapter.ui_object(self); // PEP_STATUS status = ::register_sync_callbacks(Adapter::session(), // (void *) this, _notifyHandshake, retrieve_next_sync_event); // assert(status == PEP_STATUS_OK); // if (status) // _throw_status(status); -} + } -UserInterface_callback::~UserInterface_callback() -{ + UserInterface_callback::~UserInterface_callback() { // ::unregister_sync_callbacks(Adapter::session()); -} - -PEP_STATUS UserInterface::_notifyHandshake( - pEp_identity *me, pEp_identity *partner, - sync_handshake_signal signal - ) -{ - if (!(me && partner)) - return PEP_ILLEGAL_VALUE; - - auto that = dynamic_cast< UserInterface_callback * >(_ui); - that->notifyHandshake(Identity(me), Identity(partner), signal); - - return PEP_STATUS_OK; -} - -void UserInterface::deliverHandshakeResult(int result, object identities) -{ - identity_list *shared_identities = nullptr; - if (identities != boost::python::api::object() && boost::python::len(identities)) { - shared_identities = new_identity_list(nullptr); - if (!shared_identities) - throw bad_alloc(); - - try { - identity_list *si = shared_identities; - for (int i=0; i < boost::python::len(identities); ++i) { - Identity ident = extract< Identity >(identities[i]); - si = identity_list_add(si, ident); - if (!si) + } + + PEP_STATUS UserInterface::_notifyHandshake( + pEp_identity *me, pEp_identity *partner, + sync_handshake_signal signal + ) { + if (!(me && partner)) + return PEP_ILLEGAL_VALUE; + + auto that = dynamic_cast< UserInterface_callback * >(_ui); + that->notifyHandshake(Identity(me), Identity(partner), signal); + + return PEP_STATUS_OK; + } + + void UserInterface::deliverHandshakeResult(int result, object identities) { + identity_list *shared_identities = nullptr; + if (identities != boost::python::api::object() && boost::python::len(identities)) { + shared_identities = new_identity_list(nullptr); + if (!shared_identities) throw bad_alloc(); + + try { + identity_list *si = shared_identities; + for (int i = 0; i < boost::python::len(identities); ++i) { + Identity ident = extract(identities[i]); + si = identity_list_add(si, ident); + if (!si) + throw bad_alloc(); + } + } + catch (exception &ex) { + free_identity_list(shared_identities); + throw ex; + } } - } - catch (exception& ex) { + + PEP_STATUS status = ::deliverHandshakeResult(Adapter::session(), + (sync_handshake_result) result, shared_identities); free_identity_list(shared_identities); - throw ex; + _throw_status(status); } - } - - PEP_STATUS status = ::deliverHandshakeResult(Adapter::session(), - (sync_handshake_result) result, shared_identities); - free_identity_list(shared_identities); - _throw_status(status); -} //PEP_rating UserInterface::get_key_rating_for_user(string user_id, string fpr) //{ @@ -119,12 +113,11 @@ void UserInterface::deliverHandshakeResult(int result, object identities) // return adapter.queue().pop_front(); //} -void UserInterface_callback::notifyHandshake( - Identity me, Identity partner, sync_handshake_signal signal) -{ - call_method< void >(_self, "notifyHandshake", me, partner, signal); -} + void UserInterface_callback::notifyHandshake( + Identity me, Identity partner, sync_handshake_signal signal) { + call_method(_self, "notifyHandshake", me, partner, signal); + } -} // namespace PythonAdapter + } // namespace PythonAdapter } // namespace pEp { diff --git a/src/pEp/native_pEp/user_interface.hh b/src/pEp/native_pEp/user_interface.hh index f609a41..59e17fe 100644 --- a/src/pEp/native_pEp/user_interface.hh +++ b/src/pEp/native_pEp/user_interface.hh @@ -16,44 +16,45 @@ namespace pEp { -namespace PythonAdapter { + namespace PythonAdapter { -class UserInterface { - static UserInterface *_ui; -public: - UserInterface(); - virtual ~UserInterface(); + class UserInterface { + static UserInterface *_ui; + public: + UserInterface(); - virtual void notifyHandshake( - Identity me, - Identity partner, - sync_handshake_signal signal) - { - throw runtime_error("override this method"); - } + virtual ~UserInterface(); - virtual void deliverHandshakeResult(int result, object identities); + virtual void notifyHandshake( + Identity me, + Identity partner, + sync_handshake_signal signal) { + throw runtime_error("override this method"); + } + + virtual void deliverHandshakeResult(int result, object identities); // PEP_rating get_key_rating_for_user(string user_id, string fpr); -protected: - static PEP_STATUS _notifyHandshake(pEp_identity *me, pEp_identity *partner, sync_handshake_signal signal); -}; + protected: + static PEP_STATUS _notifyHandshake(pEp_identity *me, pEp_identity *partner, sync_handshake_signal signal); + }; + + class UserInterface_callback : public UserInterface { + PyObject *_self; + public: + UserInterface_callback(PyObject *self); -class UserInterface_callback : public UserInterface { - PyObject *_self; -public: - UserInterface_callback(PyObject *self); - ~UserInterface_callback(); + ~UserInterface_callback(); - void notifyHandshake( - Identity me, - Identity partner, - sync_handshake_signal signal - ); -}; + void notifyHandshake( + Identity me, + Identity partner, + sync_handshake_signal signal + ); + }; -} /* namespace PythonAdapter */ + } /* namespace PythonAdapter */ } /* namespace pEp */ #endif /* USER_INTERFACE_HH */ From e2625e25e09c644132ebffaecaa459a0c359b2f8 Mon Sep 17 00:00:00 2001 From: heck Date: Mon, 19 Oct 2020 21:08:17 +0200 Subject: [PATCH 04/84] Adding .editorconfig --- .editorconfig | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c3d65e6 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,17 @@ +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 + +# I know these keys are unknown, regard it as documentation +indent_brace_style = K&R +curly_bracket_next_line = false +spaces_around_operators = true +spaces_around_brackets = true +quote_type = double From 0a5d8de6e5b1bc2bf2fd30e3819667dcb546a6b4 Mon Sep 17 00:00:00 2001 From: heck Date: Mon, 19 Oct 2020 21:24:29 +0200 Subject: [PATCH 05/84] .editorconfig C++ imaginary settings --- .editorconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.editorconfig b/.editorconfig index c3d65e6..159f286 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,7 +9,9 @@ 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 From 3e76763128a80fc1e13883ee4a72f1f7dd3237be Mon Sep 17 00:00:00 2001 From: heck Date: Mon, 19 Oct 2020 22:46:46 +0200 Subject: [PATCH 06/84] start getting the deps into setup.cfg --- setup.cfg | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index bc1d57b..3a2990f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,7 @@ [metadata] name = pEp -version = 2.1.0-RC2 +#TODO: automate version pull from hg/git +version = 2.2.0-RC1 url = https://pep.foundation author = Volker Birk author_email = vb@pep-project.org @@ -21,3 +22,16 @@ 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 +setup_requires = + setuptools >=38.3.0 +install_requires = + +tests_require = + pytest + tox From b31507992a5264c7d5a3d96a207f77b323ac1902 Mon Sep 17 00:00:00 2001 From: heck Date: Mon, 19 Oct 2020 22:47:31 +0200 Subject: [PATCH 07/84] remove redundancies, information source should be setup.cfg, (setup.py just only code, no data) --- setup.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/setup.py b/setup.py index d838485..1d563c5 100644 --- a/setup.py +++ b/setup.py @@ -217,13 +217,6 @@ module_pEp = Extension( # "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'}, packages=['pEp'], ext_modules=[module_pEp], From eef024b25f7153e06252e90a51c4465ddf6f91df Mon Sep 17 00:00:00 2001 From: heck Date: Tue, 20 Oct 2020 13:11:51 +0200 Subject: [PATCH 08/84] setup.cfg some keys added, values are all WIP still --- setup.cfg | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 3a2990f..7e82510 100644 --- a/setup.cfg +++ b/setup.cfg @@ -3,6 +3,8 @@ name = pEp #TODO: automate version pull from hg/git version = 2.2.0-RC1 url = https://pep.foundation +download_url = +ext_package = pEp author = Volker Birk author_email = vb@pep-project.org maintainer = Matthias Heckmann @@ -12,6 +14,7 @@ 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 +platforms = linux, macOs classifiers = Intended Audience :: Developers Topic :: Utilities @@ -31,7 +34,7 @@ test_suite = tests setup_requires = setuptools >=38.3.0 install_requires = - + setuptools >=38.3.0 tests_require = pytest tox From ee3cbb1a011c898c1b1c981a968a95504fd58bfd Mon Sep 17 00:00:00 2001 From: heck Date: Tue, 20 Oct 2020 13:12:31 +0200 Subject: [PATCH 09/84] .editorconfig more filetype specifics --- .editorconfig | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 159f286..45d1dfb 100644 --- a/.editorconfig +++ b/.editorconfig @@ -16,4 +16,15 @@ indent_brace_style = K&R curly_bracket_next_line = false spaces_around_operators = true spaces_around_brackets = true -quote_type = double + +[*.py] +indent_size = 4 + +[Makefile] +indent_style = tab + +[*.ini] +indent_size = 2 + +[*.cfg] +indent_size = 2 From 12c182f1acaf8f9404966ebfa97481c907c1a3a6 Mon Sep 17 00:00:00 2001 From: juga Date: Tue, 20 Oct 2020 16:54:56 +0000 Subject: [PATCH 10/84] Obtain package version from SCM It can be tested with `python setup.py version`. Note that it's needed to add a tag that conforms semantic versioning. --- setup.cfg | 7 +++++-- setup.py | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/setup.cfg b/setup.cfg index 7e82510..105445f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,7 +1,5 @@ [metadata] name = pEp -#TODO: automate version pull from hg/git -version = 2.2.0-RC1 url = https://pep.foundation download_url = ext_package = pEp @@ -33,6 +31,11 @@ python_requires = >= 3.6 test_suite = tests setup_requires = setuptools >=38.3.0 + # To automatically write the version from a SCM. + # Note: It fails with tags named as `Release_2.2.0-RC0`, because it is + # not conforming to semantic versioning, but it succeed with tags as + # `2.2.0-rc0`. + setuptools_scm install_requires = setuptools >=38.3.0 tests_require = diff --git a/setup.py b/setup.py index 1d563c5..7884d27 100644 --- a/setup.py +++ b/setup.py @@ -223,4 +223,7 @@ setup( 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=True, ) From 922c88fbbe9a78a1dd78ab5f35f7ba5b22a8a2fa Mon Sep 17 00:00:00 2001 From: juga Date: Tue, 20 Oct 2020 17:01:40 +0000 Subject: [PATCH 12/84] Remove unneded install dependency --- setup.cfg | 2 -- 1 file changed, 2 deletions(-) diff --git a/setup.cfg b/setup.cfg index 105445f..ca1e6df 100644 --- a/setup.cfg +++ b/setup.cfg @@ -36,8 +36,6 @@ setup_requires = # not conforming to semantic versioning, but it succeed with tags as # `2.2.0-rc0`. setuptools_scm -install_requires = - setuptools >=38.3.0 tests_require = pytest tox From d9b0ae91ec22537fe2e961898e9d861a59cb991c Mon Sep 17 00:00:00 2001 From: juga Date: Tue, 20 Oct 2020 17:02:35 +0000 Subject: [PATCH 13/84] Format correctly tests extra dependencies --- setup.cfg | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index ca1e6df..a4ddd05 100644 --- a/setup.cfg +++ b/setup.cfg @@ -36,6 +36,8 @@ setup_requires = # not conforming to semantic versioning, but it succeed with tags as # `2.2.0-rc0`. setuptools_scm -tests_require = +[options.extras_require] +# To install these dependencies, run pip install .[test] +test = pytest tox From 18f01bed7eb7104bc2b8cf3f84ddacb176acefb9 Mon Sep 17 00:00:00 2001 From: juga Date: Wed, 21 Oct 2020 13:15:39 +0000 Subject: [PATCH 15/84] Programatically obtain package version Closes PYADPT-96 --- src/pEp/__init__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/pEp/__init__.py b/src/pEp/__init__.py index 0bc2c9e..ab29698 100644 --- a/src/pEp/__init__.py +++ b/src/pEp/__init__.py @@ -2,7 +2,7 @@ # This file is being exectued upon 'import pEp' # # __all__ could be used to limit the symbols exported when using from import * - +from pkg_resources import DistributionNotFound, get_distribution # Import all symbols EXCEPT the ones beginning with underscore into the current namespace from native_pEp import * @@ -11,6 +11,10 @@ from native_pEp import * # import the module import native_pEp +try: + __version__ = get_distribution(__name__).version +except DistributionNotFound: + print("Package is not installed.") # Executed on module import def init(): From 2dc44380f14ced474be0bd23809572e8cb210f01 Mon Sep 17 00:00:00 2001 From: juga Date: Wed, 21 Oct 2020 13:37:11 +0000 Subject: [PATCH 16/84] Test the package version --- tests/test_pep.py | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tests/test_pep.py diff --git a/tests/test_pep.py b/tests/test_pep.py new file mode 100644 index 0000000..3e63973 --- /dev/null +++ b/tests/test_pep.py @@ -0,0 +1,11 @@ +"""Unit test for pEp package, not for subpackages or modules.""" + +from pEp import __version__ + + +def test_pep_version(): + """ Test that __version__ is not None or empty and is not 0.0.0.""" + # We could also test that match the regex, but that is already a test in + # setuptools_scm itself. + assert __version__ + assert __version__ != "0.0.0" From 4fba1cf12dad7b06c5c9e5f257b51240dfaf47f5 Mon Sep 17 00:00:00 2001 From: juga Date: Thu, 22 Oct 2020 12:05:48 +0000 Subject: [PATCH 17/84] Add initial docs structure Generated with `sphinx-quickstart` --- .hgignore | 1 + docs/Makefile | 19 +++++ docs/make.bat | 35 ++++++++ docs/source/conf.py | 191 ++++++++++++++++++++++++++++++++++++++++++ docs/source/index.rst | 18 ++++ setup.cfg | 3 + tox.ini | 18 +++- 7 files changed, 284 insertions(+), 1 deletion(-) create mode 100644 docs/Makefile create mode 100644 docs/make.bat create mode 100644 docs/source/conf.py create mode 100644 docs/source/index.rst diff --git a/.hgignore b/.hgignore index 8850bfe..447f728 100644 --- a/.hgignore +++ b/.hgignore @@ -26,3 +26,4 @@ launch.json settings.json # Default ignored files .idea/ +docs/build/ diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..69fe55e --- /dev/null +++ b/docs/Makefile @@ -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) \ No newline at end of file diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..543c6b1 --- /dev/null +++ b/docs/make.bat @@ -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 diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..59b8664 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,191 @@ +# -*- 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('.')) + + +# -- Project information ----------------------------------------------------- +from pkg_resources import get_distribution + +project = 'pEpPythonAdapter' +copyright = '2020, Volker Birk, Matthias Heckmann, juga' +author = 'Volker Birk, Matthias Heckmann, juga' +# The full version, including alpha/beta/rc tags +release = get_distribution('pEp').version +# The short X.Y version +version = '.'.join(release.split('.')[:2]) + +# -- 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 = '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 = {} + +# 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, Matthias Heckmann, 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 diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..55b3ca4 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,18 @@ +.. 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: + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/setup.cfg b/setup.cfg index 7e82510..bd1e94f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -38,3 +38,6 @@ install_requires = tests_require = pytest tox + +[options.extras_require] +doc = sphinx diff --git a/tox.ini b/tox.ini index 0015150..6026f39 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] skip_missing_interpreters = True -envlist = py36, py37, py38, inst, setup, unit +envlist = py36, py37, py38, inst, setup, unit, doc # test that it can be installed with custom commands and clean env [testenv:inst] @@ -17,3 +17,19 @@ recreate = True [testenv:unit] deps = .[test] commands = pytest -svv tests + +[testenv:doc] +deps = .[doc] +whitelist_externals = make +changedir = docs +commands = + make html + make man + +# this requires Internet, it should not be in envlist +[testenv:doclinks] +deps = .[doc] +whitelist_externals = make +changedir = docs +commands = + make linkcheck From df469442c591183285e02edf89c51077046a7482 Mon Sep 17 00:00:00 2001 From: juga Date: Wed, 21 Oct 2020 16:06:36 +0000 Subject: [PATCH 18/84] Add page about software that depends on this --- docs/source/index.rst | 2 ++ docs/source/software_using.rst | 4 ++++ 2 files changed, 6 insertions(+) create mode 100644 docs/source/software_using.rst diff --git a/docs/source/index.rst b/docs/source/index.rst index 55b3ca4..cd788cf 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -10,6 +10,8 @@ Welcome to pEpPythonAdapter's documentation! :maxdepth: 2 :caption: Contents: + software_using + Indices and tables ================== diff --git a/docs/source/software_using.rst b/docs/source/software_using.rst new file mode 100644 index 0000000..59eb6fa --- /dev/null +++ b/docs/source/software_using.rst @@ -0,0 +1,4 @@ +Software using pEpPythonAdapter +=============================== + +- `pEpPythonMixnet `_ From c5044ffcdbfc408b3ae15d88a8e33403ab1cf880 Mon Sep 17 00:00:00 2001 From: juga Date: Wed, 21 Oct 2020 16:07:49 +0000 Subject: [PATCH 19/84] Add API documentation generated automatically with `sphinx-apidoc` --- docs/source/api/pEp.rst | 10 ++++++++++ docs/source/index.rst | 1 + 2 files changed, 11 insertions(+) create mode 100644 docs/source/api/pEp.rst diff --git a/docs/source/api/pEp.rst b/docs/source/api/pEp.rst new file mode 100644 index 0000000..693d892 --- /dev/null +++ b/docs/source/api/pEp.rst @@ -0,0 +1,10 @@ +pEp package +=========== + +Module contents +--------------- + +.. automodule:: pEp + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/index.rst b/docs/source/index.rst index cd788cf..e29f04d 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -11,6 +11,7 @@ Welcome to pEpPythonAdapter's documentation! :caption: Contents: software_using + api/pEp Indices and tables ================== From eb0f27cd472c061546619a5cbe9abb2912946aa8 Mon Sep 17 00:00:00 2001 From: juga Date: Wed, 21 Oct 2020 16:25:37 +0000 Subject: [PATCH 20/84] Add installation page and move heck's instructions also add other minimal info to the README. --- README.md | 42 ++++----------------- docs/source/index.rst | 1 + docs/source/install.rst | 84 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 34 deletions(-) create mode 100644 docs/source/install.rst diff --git a/README.md b/README.md index d6ae5ed..a680001 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,16 @@ # pEpPythonAdapter -## Build Insttructions +Python adapter for the [pEpEngine](https://pep.foundation/dev/repos/pEpEngine/) -These build instructions should work on: - * Linux (Verified 26.4.20 - heck) - * MacOS (Verified 26.4.20 - heck) - * Windows +## Documentation -### Build -To build against system wide pEp installation (libs/includes) -```bash -python3 setup.py build_ext -``` +See documentation in the `docs` directory. -To build against a pEp installation in your home dir (libs/includes): -```bash -python3 setup.py build_ext --local -``` +## Issues -To build against a pEp installation in a custom installation root (libs/includes) -```bash -python3 setup.py build_ext --prefix= -``` +Currently it's only possible to report bugs or features for pEp developers in +the internal jira. -### Install +## License -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= -``` -Attention: The ~ (tilde) does not get expanded, but env vars work ($HOME). \ No newline at end of file +GPLv3 diff --git a/docs/source/index.rst b/docs/source/index.rst index e29f04d..04dab42 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -10,6 +10,7 @@ Welcome to pEpPythonAdapter's documentation! :maxdepth: 2 :caption: Contents: + install software_using api/pEp diff --git a/docs/source/install.rst b/docs/source/install.rst new file mode 100644 index 0000000..2670f4a --- /dev/null +++ b/docs/source/install.rst @@ -0,0 +1,84 @@ +Installation +============ + +Requirements +------------ + +[Sequoia](https://gitlab.com/sequoia-pgp/sequoia) +[pEpEngine](https://pep.foundation/dev/repos/pEpEngine/) +[libpEpAdapter](https://pep.foundation/dev/repos/libpEpAdapter/) + +## Build Instructions + +To install all the dependencies, referer to their respective documentation. + +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= +``` + +Installation in all platforms +----------------------------- + +It is possible to install `pEpPythonAdapter` without building it first, since +the installation process will build it when it has not been built yet, but you +need to have all the dependencies already installed. + +You can install this adapter in the in the following ways: + +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= +``` +Attention: The ~ (tilde) does not get expanded, but env vars work ($HOME). + +If you're working on different Python projects, it's recommended to use +[virtualenv](https://virtualenv.pypa.io/en/stable/) to have different +libraries versions. + +If you're working in a virtualenv you can also install the package with +`pip install .` + +To install the package in "develop mode", run `python setup.py develop` +or `pip install -e .` + +Debian installation +-------------------- + +You can also install the dependencies using the scripts +http://pep-security.lu/gitlab/juga/Internal-Deployment/-/blob/master/install-sys-deps-debian.sh +and +http://pep-security.lu/gitlab/juga/Internal-Deployment/-/blob/master/build-pep-stack.sh + +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. From f8d6db3be87f8ac411ff46980374c0198c4aa015 Mon Sep 17 00:00:00 2001 From: juga Date: Wed, 21 Oct 2020 16:28:46 +0000 Subject: [PATCH 21/84] Add testing page with instructions on how to run the tests. --- docs/source/conf.py | 71 ++++++++++++++++++++++++----------------- docs/source/index.rst | 1 + docs/source/testing.rst | 15 +++++++++ 3 files changed, 58 insertions(+), 29 deletions(-) create mode 100644 docs/source/testing.rst diff --git a/docs/source/conf.py b/docs/source/conf.py index 59b8664..c889b10 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -20,13 +20,13 @@ # -- Project information ----------------------------------------------------- from pkg_resources import get_distribution -project = 'pEpPythonAdapter' -copyright = '2020, Volker Birk, Matthias Heckmann, juga' -author = 'Volker Birk, Matthias Heckmann, juga' +project = "pEpPythonAdapter" +copyright = "2020, Volker Birk, Matthias Heckmann, juga" +author = "Volker Birk, Matthias Heckmann, juga" # The full version, including alpha/beta/rc tags -release = get_distribution('pEp').version +release = get_distribution("pEp").version # The short X.Y version -version = '.'.join(release.split('.')[:2]) +version = ".".join(release.split(".")[:2]) # -- General configuration --------------------------------------------------- @@ -38,25 +38,25 @@ version = '.'.join(release.split('.')[:2]) # 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', + "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'] +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' +source_suffix = ".rst" # The master toctree document. -master_doc = 'index' +master_doc = "index" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -79,7 +79,7 @@ pygments_style = None # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'alabaster' +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 @@ -90,7 +90,7 @@ html_theme = 'alabaster' # 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'] +html_static_path = ["_static"] # Custom sidebar templates, must be a dictionary that maps document names # to template names. @@ -106,7 +106,7 @@ html_static_path = ['_static'] # -- Options for HTMLHelp output --------------------------------------------- # Output file base name for HTML help builder. -htmlhelp_basename = 'pEpPythonAdapterdoc' +htmlhelp_basename = "pEpPythonAdapterdoc" # -- Options for LaTeX output ------------------------------------------------ @@ -115,15 +115,12 @@ 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', @@ -133,8 +130,13 @@ latex_elements = { # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'pEpPythonAdapter.tex', 'pEpPythonAdapter Documentation', - '2020, Volker Birk, Matthias Heckmann, juga', 'manual'), + ( + master_doc, + "pEpPythonAdapter.tex", + "pEpPythonAdapter Documentation", + "2020, Volker Birk, Matthias Heckmann, juga", + "manual", + ) ] @@ -143,8 +145,13 @@ latex_documents = [ # 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) + ( + master_doc, + "peppythonadapter", + "pEpPythonAdapter Documentation", + [author], + 1, + ) ] @@ -154,9 +161,15 @@ man_pages = [ # (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'), + ( + master_doc, + "pEpPythonAdapter", + "pEpPythonAdapter Documentation", + author, + "pEpPythonAdapter", + "One line description of project.", + "Miscellaneous", + ) ] @@ -175,7 +188,7 @@ epub_title = project # epub_uid = '' # A list of files that should not be packed into the epub file. -epub_exclude_files = ['search.html'] +epub_exclude_files = ["search.html"] # -- Extension configuration ------------------------------------------------- @@ -183,7 +196,7 @@ epub_exclude_files = ['search.html'] # -- Options for intersphinx extension --------------------------------------- # Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'https://docs.python.org/': None} +intersphinx_mapping = {"https://docs.python.org/": None} # -- Options for todo extension ---------------------------------------------- diff --git a/docs/source/index.rst b/docs/source/index.rst index 04dab42..477527b 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -11,6 +11,7 @@ Welcome to pEpPythonAdapter's documentation! :caption: Contents: install + testing software_using api/pEp diff --git a/docs/source/testing.rst b/docs/source/testing.rst new file mode 100644 index 0000000..31c4a87 --- /dev/null +++ b/docs/source/testing.rst @@ -0,0 +1,15 @@ +Testing +======= + +See :ref:`install` to install the dependencies. + +See `test/README.md` to run the tests in `test`. + +To run the tests that use `pytest`, install the testing dependencies running +``pip install .[test]``. + +In Debian, you can install the testing dependencies in the system running ``apt +install tox``. + +Run the tests with the command `tox`. You can run individual tests by running +``tox -e ``, eg. ``tox -e py37`` or ``tox -e unit``. From 81113ca5b2aa6785a2e5cb89d09930c31b75357a Mon Sep 17 00:00:00 2001 From: juga Date: Thu, 22 Oct 2020 12:07:05 +0000 Subject: [PATCH 22/84] Add page on how to build the documentation Closes PYADAPT-97. --- docs/source/documentation.rst | 13 +++++++++++++ docs/source/index.rst | 1 + 2 files changed, 14 insertions(+) create mode 100644 docs/source/documentation.rst diff --git a/docs/source/documentation.rst b/docs/source/documentation.rst new file mode 100644 index 0000000..929eae9 --- /dev/null +++ b/docs/source/documentation.rst @@ -0,0 +1,13 @@ +Building the documentation +========================= + +This documentation uses `Sphinx `_ + +It can be built in different formats. + +Run ``cd docs; make`` to see the possible formats. + +Run ``cd docs; make html`` to build the documentation in HTML format. + +You can see the generated HTML documentation in a browser opening the directory +`docs/build/html`. diff --git a/docs/source/index.rst b/docs/source/index.rst index 477527b..f9b4955 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -12,6 +12,7 @@ Welcome to pEpPythonAdapter's documentation! install testing + documentation software_using api/pEp From 15b97543eea709cba2ec9b2533fa861a6cd6ce17 Mon Sep 17 00:00:00 2001 From: juga Date: Thu, 22 Oct 2020 11:54:27 +0000 Subject: [PATCH 23/84] hg ignore .eggs and .tox Generated by setuptools_scm and tox. --- .hgignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.hgignore b/.hgignore index 447f728..10c99f0 100644 --- a/.hgignore +++ b/.hgignore @@ -27,3 +27,5 @@ settings.json # Default ignored files .idea/ docs/build/ +.eggs +.tox From 072563a34333ed8d902850e3233f576713076aeb Mon Sep 17 00:00:00 2001 From: juga Date: Mon, 26 Oct 2020 10:52:22 +0000 Subject: [PATCH 24/84] tests: Update pytests created with older version Closes PYADPT-98. --- tests/test_message.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/tests/test_message.py b/tests/test_message.py index 062b65b..c6bc979 100644 --- a/tests/test_message.py +++ b/tests/test_message.py @@ -46,14 +46,24 @@ def test_msg_enc_dec_roundtrip(tmpdir, alice_sec_key_data, bob_pub_key_data): # Decrypt message. dec_msg, key_list, rating, r = enc_msg.decrypt() assert r == 0 - assert rating == pEp.PEP_rating.PEP_rating_reliable + # pEp version 2.2 throws this error: + # AttributeError: module 'pEp' has no attribute 'PEP_rating' + # assert rating == pEp.PEP_rating.PEP_rating_reliable + # It seems to have changed to the following. + assert rating == pEp.native_pEp.rating.reliable - # It is not known which key is generated for Alice, so check only the - # one for Bob. + # The first 2 keys are Alice's ones, the last is Bob's one. + assert key_list[0] == key_list[1] == constants.ALICE_FP assert key_list[-1] == constants.BOB_FP assert dec_msg.shortmsg == constants.SUBJECT assert dec_msg.longmsg.replace("\r", "") == msg.longmsg dec_lines = str(dec_msg).replace("\r", "").split("\n") + # pEp version 2.2 seems to have fixed some of the replaced characters. + # and changed also: + # Content-Type: doesn't pring `; charset="utf-8"` anymore. + # Content-Transfer-Encoding: doesn't print `quoted-printable` anymore. + # Content-Disposition: is not present anymore. + # `!` is not replaced by `=21` anymore. expected_dec_lines = """From: Alice Lovelace To: Bob Babagge Subject: This is a subject @@ -62,11 +72,10 @@ X-EncStatus: reliable X-KeyList: X,X,D1A66E1A23B182C9980F788CFBFCC82A015E7330 MIME-Version: 1.0 -Content-Type: text/plain; charset="utf-8" -Content-Transfer-Encoding: quoted-printable -Content-Disposition: inline; filename="msg.txt" +Content-Type: text/plain +Content-Transfer-Encoding: 7bit -Hi world=21 +Hi world! """.split("\n") assert dec_lines[:5] == expected_dec_lines[:5] assert dec_lines[7:] == expected_dec_lines[7:] From d0a94e20cd7b09aaf3aa0726bd94ffd0cd938720 Mon Sep 17 00:00:00 2001 From: juga Date: Mon, 26 Oct 2020 10:55:17 +0000 Subject: [PATCH 25/84] tests: Create identities fixture to use in message Since the identities are not being tested in the message tests, facilitate to create them. --- tests/conftest.py | 30 ++++++++++++++++++++++++++++++ tests/test_message.py | 16 +++------------- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 1aa45d7..cac2a3b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,9 @@ """pytest configuration for the unit tests.""" +import os import pytest +from . import constants + @pytest.fixture() def datadir(request): @@ -43,3 +46,30 @@ def alice_sec_key_data(datadir): def bob_pub_key_data(datadir): key_data = datadir.read('bob@openpgp.example.pub.asc') return key_data + + +@pytest.fixture() +def create_alice_identity(tmpdir, alice_sec_key_data, bob_pub_key_data): + os.environ["HOME"] = str(tmpdir) + import pEp + + pEp.import_key(alice_sec_key_data) + alice = pEp.Identity( + constants.ALICE_ADDRESS, constants.ALICE_NAME, + constants.ALICE_NAME_ADDR, constants.ALICE_FP, 0, '' + ) + pEp.set_own_key(alice, constants.ALICE_FP) + return alice + + +@pytest.fixture() +def create_bob_identity(tmpdir, bob_pub_key_data): + os.environ["HOME"] = str(tmpdir) + import pEp + + pEp.import_key(bob_pub_key_data) + bob = pEp.Identity( + constants.BOB_ADDRESS, constants.BOB_NAME, '', + constants.BOB_FP, 56, '' + ) + return bob diff --git a/tests/test_message.py b/tests/test_message.py index c6bc979..10b59fd 100644 --- a/tests/test_message.py +++ b/tests/test_message.py @@ -1,23 +1,13 @@ """Message unit tests.""" -import os from . import constants -def test_msg_enc_dec_roundtrip(tmpdir, alice_sec_key_data, bob_pub_key_data): - os.environ["HOME"] = str(tmpdir) +def test_msg_enc_dec_roundtrip(create_alice_identity, create_bob_identity): import pEp - alice = pEp.Identity( - constants.ALICE_ADDRESS, constants.ALICE_NAME, - constants.ALICE_NAME_ADDR, constants.ALICE_FP, 0, '' - ) - - pEp.import_key(bob_pub_key_data) - bob = pEp.Identity( - constants.BOB_ADDRESS, constants.BOB_NAME, '', - constants.BOB_FP, 56, '' - ) + alice = create_alice_identity + bob = create_bob_identity msg = pEp.Message(constants.OUTGOING_MSG, alice) msg.to = [bob] From c4487042659b5f2111348a1ee2384189064cad2f Mon Sep 17 00:00:00 2001 From: juga Date: Mon, 26 Oct 2020 10:55:53 +0000 Subject: [PATCH 26/84] tests: Remove unused constant myself --- tests/constants.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/constants.py b/tests/constants.py index cf5e02b..f83f3bb 100644 --- a/tests/constants.py +++ b/tests/constants.py @@ -8,9 +8,6 @@ INCOMING_MSG = 2 ANGLE_ADDR = "<{}>" NAME_ADDR = "{} {}" -PEP_NAME = "myself" -PEP_ADDRESS = "myself@pep.fundation" - BOB_NAME = "Bob Babagge" BOB_ADDRESS = "bob@openpgp.example" BOB_FP = "D1A66E1A23B182C9980F788CFBFCC82A015E7330" From 31087b6a29ae3d4fe5f7c24d365a2036161d3c4b Mon Sep 17 00:00:00 2001 From: juga Date: Mon, 26 Oct 2020 12:59:13 +0000 Subject: [PATCH 27/84] tests: Show that message encrypt modifies the original one which is probably not what we want. If we decide to fix it, the tests' assertions need to be changed. Closes PYADAPT-99. --- tests/test_message.py | 101 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/tests/test_message.py b/tests/test_message.py index 10b59fd..b3a0388 100644 --- a/tests/test_message.py +++ b/tests/test_message.py @@ -69,3 +69,104 @@ Hi world! """.split("\n") assert dec_lines[:5] == expected_dec_lines[:5] assert dec_lines[7:] == expected_dec_lines[7:] + + +def test_msg_len_changes(create_alice_identity, create_bob_identity): + """Test that the original message is modified after encryption. + + Headers are added and therefore the modified unencrypted message length + is different to the original. + XXX: The original message should be left unchanged. + There could be another method previous to `encrypt` that adds the + extra headers and modify the subject returning a new message. + + """ + import pEp + + alice = create_alice_identity + bob = create_bob_identity + + msg = pEp.outgoing_message(alice) + msg.to = [bob] + msg.shortmsg = constants.SUBJECT + msg.longmsg = constants.BODY + msg_len = len(str(msg)) + # Encrypt Message + msg.encrypt() + + # After encryption, the original message is modified!! + # It contains one more header and the alice's public key, if it's the first + # msg to bob. + # XXX: if/when this is fixed, change the following `!=` to `==` + msg_after_encrypt_len = len(str(msg)) + assert msg.shortmsg != constants.SUBJECT + assert msg.longmsg == constants.BODY + assert msg_after_encrypt_len != msg_len + + +def test_dec_msg_len(create_alice_identity, create_bob_identity): + """ + Test that the decrypted message length is different from the original. + + Because it adds extra headers. + + """ + import pEp + + alice = create_alice_identity + bob = create_bob_identity + + msg = pEp.outgoing_message(alice) + msg.to = [bob] + msg.shortmsg = constants.SUBJECT + msg.longmsg = constants.BODY + msg_len = len(str(msg)) + # Encrypt Message + enc_msg = msg.encrypt() + + # Decrypt message. + dec_msg, _key_list, _rating, _r = enc_msg.decrypt() + dec_msg_len = len(str(dec_msg)) + + assert dec_msg.longmsg.replace("\r", "") == constants.BODY # msg.longmsg + expected_dec_msg = """From: Alice Lovelace \r +To: Bob Babagge \r +Subject: This is a subject\r +X-pEp-Version: 2.1\r +X-EncStatus: reliable\r +X-KeyList: \r + EB85BB5FA33A75E15E944E63F231550C4F47E38E,EB85BB5FA33A75E15E944E63F231550C4F47E38E,D1A66E1A23B182C9980F788CFBFCC82A015E7330\r +MIME-Version: 1.0\r +Content-Type: text/plain\r +Content-Transfer-Encoding: 7bit\r +\r +Hi world!\r +""" + assert expected_dec_msg == str(dec_msg) + # The decrypted message length should then be equal to the original message + # minus the extra headers added. + dec_lines = str(dec_msg).split("\n") + extra_headers_lines = dec_lines[3:7] + extra_headers = "\n".join(extra_headers_lines) + "\n" + len_extra_headers = len(extra_headers) + print("len_extra_headers", len_extra_headers) + assert dec_msg_len - len_extra_headers == msg_len + + +def test_null_char_rmed(create_alice_identity, create_bob_identity): + """Test that null characters and anything after them is removed.""" + import pEp + + alice = create_alice_identity + bob = create_bob_identity + + msg = pEp.outgoing_message(alice) + msg.to = [bob] + msg.shortmsg = constants.SUBJECT + + # Message with null chars, potentially for padding. + body = "Hi Bob,\n" + "\0" * 255 + "\nBye,\nAlice." + msg.longmsg = body + # PYADAPT-91: The null characters and anything after them is removed. + # If/when this is fixed, change the following assertion. + assert msg.longmsg != body From 5f9495970a7de4d9b394ce13645b3ca3df0556a3 Mon Sep 17 00:00:00 2001 From: heck Date: Tue, 27 Oct 2020 12:20:26 +0100 Subject: [PATCH 28/84] update Readme topic "Issues" --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a680001..db4eb70 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,9 @@ See documentation in the `docs` directory. ## Issues -Currently it's only possible to report bugs or features for pEp developers in -the internal jira. +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 [bugtracker](https://pep.foundation/jira/projects/PYADPT/) and for any questions, you are always welome on #adapter. ## License From 58c3399307055e43f9c995d8ec3de53111818767 Mon Sep 17 00:00:00 2001 From: heck Date: Tue, 27 Oct 2020 13:59:50 +0100 Subject: [PATCH 29/84] name correction --- docs/source/conf.py | 6 +++--- setup.cfg | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index c889b10..a4e1f53 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -21,8 +21,8 @@ from pkg_resources import get_distribution project = "pEpPythonAdapter" -copyright = "2020, Volker Birk, Matthias Heckmann, juga" -author = "Volker Birk, Matthias Heckmann, juga" +copyright = "2020, Volker Birk, heck, juga" +author = "Volker Birk, heck, juga" # The full version, including alpha/beta/rc tags release = get_distribution("pEp").version # The short X.Y version @@ -134,7 +134,7 @@ latex_documents = [ master_doc, "pEpPythonAdapter.tex", "pEpPythonAdapter Documentation", - "2020, Volker Birk, Matthias Heckmann, juga", + "2020, Volker Birk, heck, juga", "manual", ) ] diff --git a/setup.cfg b/setup.cfg index 0733f52..456c99b 100755 --- a/setup.cfg +++ b/setup.cfg @@ -5,7 +5,7 @@ download_url = ext_package = pEp author = Volker Birk 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 From 28a29a1c654991c8d9e67d1383de0b6b8b1954c0 Mon Sep 17 00:00:00 2001 From: heck Date: Tue, 27 Oct 2020 14:01:28 +0100 Subject: [PATCH 30/84] hartmut recommends: setuptools >= 39.2.0, which supports the `version` file attribute --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 456c99b..3e65e40 100755 --- a/setup.cfg +++ b/setup.cfg @@ -30,7 +30,7 @@ include_package_data = true python_requires = >= 3.6 test_suite = tests setup_requires = - setuptools >=38.3.0 + setuptools >=39.2.0 # To automatically write the version from a SCM. # Note: It fails with tags named as `Release_2.2.0-RC0`, because it is # not conforming to semantic versioning, but it succeed with tags as From d1ffedf47851883193e48897adc91800ba4ef1dd Mon Sep 17 00:00:00 2001 From: heck Date: Tue, 27 Oct 2020 19:37:35 +0100 Subject: [PATCH 32/84] Makefile correct target devenv --- Makefile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 1cce38f..16181bf 100644 --- a/Makefile +++ b/Makefile @@ -40,10 +40,8 @@ clean: devenv: 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 \ + PYTHONPATH=`pwd`/build/lib.linux-x86_64-3.7:`pwd`/build/lib.macosx-10.9-x86_64-3.8: \ bash -l envtest: - python3 -c 'import pEp' \ No newline at end of file + python3 -c 'import pEp' From b5d3177292415a61ca3bea63cd498e8229489738 Mon Sep 17 00:00:00 2001 From: heck Date: Tue, 27 Oct 2020 19:43:10 +0100 Subject: [PATCH 33/84] PYADPT-86 - "Rename `native_pEp` into `_pEp`" PYADPT-89 - "Make `native_pep` / `_pEp` a submodule of `pEp`" More doc --- setup.py | 16 ++++----- src/pEp/__init__.py | 36 ++++++++++++------- src/pEp/{native_pEp => _pEp}/basic_api.cc | 0 src/pEp/{native_pEp => _pEp}/basic_api.hh | 0 src/pEp/{native_pEp => _pEp}/identity.cc | 0 src/pEp/{native_pEp => _pEp}/identity.hh | 0 src/pEp/{native_pEp => _pEp}/message.cc | 0 src/pEp/{native_pEp => _pEp}/message.hh | 0 src/pEp/{native_pEp => _pEp}/message_api.cc | 0 src/pEp/{native_pEp => _pEp}/message_api.hh | 0 src/pEp/{native_pEp => _pEp}/pEpmodule.cc | 2 +- src/pEp/{native_pEp => _pEp}/pEpmodule.hh | 0 src/pEp/{native_pEp => _pEp}/str_attr.cc | 0 src/pEp/{native_pEp => _pEp}/str_attr.hh | 0 .../{native_pEp => _pEp}/user_interface.cc | 0 .../{native_pEp => _pEp}/user_interface.hh | 0 tests/test_message.py | 2 +- 17 files changed, 33 insertions(+), 23 deletions(-) rename src/pEp/{native_pEp => _pEp}/basic_api.cc (100%) rename src/pEp/{native_pEp => _pEp}/basic_api.hh (100%) rename src/pEp/{native_pEp => _pEp}/identity.cc (100%) rename src/pEp/{native_pEp => _pEp}/identity.hh (100%) rename src/pEp/{native_pEp => _pEp}/message.cc (100%) rename src/pEp/{native_pEp => _pEp}/message.hh (100%) rename src/pEp/{native_pEp => _pEp}/message_api.cc (100%) rename src/pEp/{native_pEp => _pEp}/message_api.hh (100%) rename src/pEp/{native_pEp => _pEp}/pEpmodule.cc (99%) rename src/pEp/{native_pEp => _pEp}/pEpmodule.hh (100%) rename src/pEp/{native_pEp => _pEp}/str_attr.cc (100%) rename src/pEp/{native_pEp => _pEp}/str_attr.hh (100%) rename src/pEp/{native_pEp => _pEp}/user_interface.cc (100%) rename src/pEp/{native_pEp => _pEp}/user_interface.hh (100%) diff --git a/setup.py b/setup.py index 7884d27..10f3ca5 100755 --- a/setup.py +++ b/setup.py @@ -203,15 +203,15 @@ if sys.version_info[0] < 3: FileNotFoundError = EnvironmentError module_pEp = Extension( - 'native_pEp', + 'pEp._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', + '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', ], ) diff --git a/src/pEp/__init__.py b/src/pEp/__init__.py index ab29698..1af6eac 100755 --- a/src/pEp/__init__.py +++ b/src/pEp/__init__.py @@ -1,25 +1,35 @@ +# -*- coding: UTF-8 -*- # pEp package -# This file is being exectued upon 'import pEp' +# +# 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() # # __all__ could be used to limit the symbols exported when using from import * -from pkg_resources import DistributionNotFound, get_distribution +# TODO: Commented out until problems solved +# from pkg_resources import DistributionNotFound, get_distribution + +# Imports all symbols EXCEPT the ones beginning with underscore +from ._pEp import * -# 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 +# 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 -try: - __version__ = get_distribution(__name__).version -except DistributionNotFound: - print("Package is not installed.") +# TODO: Commented out until problems solved +# try: +# __version__ = get_distribution(__name__).version +# except DistributionNotFound: +# print("Package is not installed.") # 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): diff --git a/src/pEp/native_pEp/basic_api.cc b/src/pEp/_pEp/basic_api.cc similarity index 100% rename from src/pEp/native_pEp/basic_api.cc rename to src/pEp/_pEp/basic_api.cc diff --git a/src/pEp/native_pEp/basic_api.hh b/src/pEp/_pEp/basic_api.hh similarity index 100% rename from src/pEp/native_pEp/basic_api.hh rename to src/pEp/_pEp/basic_api.hh diff --git a/src/pEp/native_pEp/identity.cc b/src/pEp/_pEp/identity.cc similarity index 100% rename from src/pEp/native_pEp/identity.cc rename to src/pEp/_pEp/identity.cc diff --git a/src/pEp/native_pEp/identity.hh b/src/pEp/_pEp/identity.hh similarity index 100% rename from src/pEp/native_pEp/identity.hh rename to src/pEp/_pEp/identity.hh diff --git a/src/pEp/native_pEp/message.cc b/src/pEp/_pEp/message.cc similarity index 100% rename from src/pEp/native_pEp/message.cc rename to src/pEp/_pEp/message.cc diff --git a/src/pEp/native_pEp/message.hh b/src/pEp/_pEp/message.hh similarity index 100% rename from src/pEp/native_pEp/message.hh rename to src/pEp/_pEp/message.hh diff --git a/src/pEp/native_pEp/message_api.cc b/src/pEp/_pEp/message_api.cc similarity index 100% rename from src/pEp/native_pEp/message_api.cc rename to src/pEp/_pEp/message_api.cc diff --git a/src/pEp/native_pEp/message_api.hh b/src/pEp/_pEp/message_api.hh similarity index 100% rename from src/pEp/native_pEp/message_api.hh rename to src/pEp/_pEp/message_api.hh diff --git a/src/pEp/native_pEp/pEpmodule.cc b/src/pEp/_pEp/pEpmodule.cc similarity index 99% rename from src/pEp/native_pEp/pEpmodule.cc rename to src/pEp/_pEp/pEpmodule.cc index 3d2bff1..73a1f6d 100644 --- a/src/pEp/native_pEp/pEpmodule.cc +++ b/src/pEp/_pEp/pEpmodule.cc @@ -178,7 +178,7 @@ namespace pEp { _throw_status(status); } - BOOST_PYTHON_MODULE(native_pEp) { + BOOST_PYTHON_MODULE(_pEp) { init_before_main_module(); // Module init function called by pEp.init() diff --git a/src/pEp/native_pEp/pEpmodule.hh b/src/pEp/_pEp/pEpmodule.hh similarity index 100% rename from src/pEp/native_pEp/pEpmodule.hh rename to src/pEp/_pEp/pEpmodule.hh diff --git a/src/pEp/native_pEp/str_attr.cc b/src/pEp/_pEp/str_attr.cc similarity index 100% rename from src/pEp/native_pEp/str_attr.cc rename to src/pEp/_pEp/str_attr.cc diff --git a/src/pEp/native_pEp/str_attr.hh b/src/pEp/_pEp/str_attr.hh similarity index 100% rename from src/pEp/native_pEp/str_attr.hh rename to src/pEp/_pEp/str_attr.hh diff --git a/src/pEp/native_pEp/user_interface.cc b/src/pEp/_pEp/user_interface.cc similarity index 100% rename from src/pEp/native_pEp/user_interface.cc rename to src/pEp/_pEp/user_interface.cc diff --git a/src/pEp/native_pEp/user_interface.hh b/src/pEp/_pEp/user_interface.hh similarity index 100% rename from src/pEp/native_pEp/user_interface.hh rename to src/pEp/_pEp/user_interface.hh diff --git a/tests/test_message.py b/tests/test_message.py index b3a0388..9787133 100644 --- a/tests/test_message.py +++ b/tests/test_message.py @@ -40,7 +40,7 @@ def test_msg_enc_dec_roundtrip(create_alice_identity, create_bob_identity): # AttributeError: module 'pEp' has no attribute 'PEP_rating' # assert rating == pEp.PEP_rating.PEP_rating_reliable # It seems to have changed to the following. - assert rating == pEp.native_pEp.rating.reliable + assert rating == pEp._pEp.rating.reliable # The first 2 keys are Alice's ones, the last is Bob's one. assert key_list[0] == key_list[1] == constants.ALICE_FP From 2b5793ff63be429690830bd3285658b1aa2022e7 Mon Sep 17 00:00:00 2001 From: heck Date: Tue, 27 Oct 2020 19:58:39 +0100 Subject: [PATCH 35/84] PYADPT-87 - "Drop usless `__main__` part form module" --- src/pEp/__init__.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/pEp/__init__.py b/src/pEp/__init__.py index 1af6eac..24c1c06 100755 --- a/src/pEp/__init__.py +++ b/src/pEp/__init__.py @@ -56,13 +56,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() From b5e4aee667b0d5c8e849682c3f5f1f9c69a3635e Mon Sep 17 00:00:00 2001 From: heck Date: Mon, 2 Nov 2020 17:51:06 +0100 Subject: [PATCH 37/84] .hgignore tidy up --- .hgignore | 73 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 27 deletions(-) diff --git a/.hgignore b/.hgignore index 10c99f0..c575f6a 100644 --- a/.hgignore +++ b/.hgignore @@ -1,31 +1,50 @@ syntax: glob +# Build config 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 + +# 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/ -docs/build/ -.eggs -.tox +*~ +.\#* +\#*# +*.swp +.idea +.spyproject +*.code-workspace + +# platform artifacts +.DS_store + + + From 2a1c053d562727fc19ef7f5b5beeced48d237aaf Mon Sep 17 00:00:00 2001 From: heck Date: Mon, 2 Nov 2020 17:51:55 +0100 Subject: [PATCH 38/84] setuptools_scm min version --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 3e65e40..022d177 100755 --- a/setup.cfg +++ b/setup.cfg @@ -35,7 +35,7 @@ setup_requires = # Note: It fails with tags named as `Release_2.2.0-RC0`, because it is # not conforming to semantic versioning, but it succeed with tags as # `2.2.0-rc0`. - setuptools_scm + setuptools_scm >= 4.1.2 [options.extras_require] # To install these dependencies, run pip install .[test] test = From 0af1ba949e3cd9516318ea1e5be148ecdd768973 Mon Sep 17 00:00:00 2001 From: heck Date: Mon, 2 Nov 2020 17:54:31 +0100 Subject: [PATCH 39/84] define the pEpPythonAdapter version at compile-time. Fallback to setuptools_scm. --- setup.py | 6 +++++- src/pEp/__init__.py | 18 ++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/setup.py b/setup.py index 10f3ca5..5541c98 100755 --- a/setup.py +++ b/setup.py @@ -225,5 +225,9 @@ setup( }, # While not using a pyproject.toml, support setuptools_scm setup.cfg usage, # see https://github.com/pypa/setuptools_scm/#setupcfg-usage - use_scm_version=True, + 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' + } ) diff --git a/src/pEp/__init__.py b/src/pEp/__init__.py index 24c1c06..88d5204 100755 --- a/src/pEp/__init__.py +++ b/src/pEp/__init__.py @@ -8,17 +8,27 @@ # Example: # def underscore_function(): # _pEp._underscore_function() -# + # __all__ could be used to limit the symbols exported when using from import * -# TODO: Commented out until problems solved -# from pkg_resources import DistributionNotFound, get_distribution +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 +import pEp._pEp # TODO: Commented out until problems solved # try: From d8ec815423c3399374f6fbe9bcdffad5f6b2ce51 Mon Sep 17 00:00:00 2001 From: heck Date: Thu, 5 Nov 2020 15:42:57 +0100 Subject: [PATCH 40/84] version info cant be taken from installed pkg, but must be taken from the locally compiled pEp module --- docs/source/conf.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index a4e1f53..0ab999a 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -12,22 +12,25 @@ # 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('.')) - - +import os +import sys +sys.path.insert(0, os.path.abspath('../../src')) # -- Project information ----------------------------------------------------- -from pkg_resources import get_distribution +#from pkg_resources import get_distribution project = "pEpPythonAdapter" copyright = "2020, Volker Birk, heck, juga" author = "Volker Birk, heck, juga" + +import pEp # The full version, including alpha/beta/rc tags -release = get_distribution("pEp").version +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. From f62af62e61b8d72f6f0ee6c5124a9b28bd704aec Mon Sep 17 00:00:00 2001 From: heck Date: Thu, 5 Nov 2020 15:44:32 +0100 Subject: [PATCH 41/84] basically no doc got generated, need to include :imported-members: --- docs/source/api/pEp.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/api/pEp.rst b/docs/source/api/pEp.rst index 693d892..586e991 100644 --- a/docs/source/api/pEp.rst +++ b/docs/source/api/pEp.rst @@ -6,5 +6,7 @@ Module contents .. automodule:: pEp :members: + :imported-members: :undoc-members: :show-inheritance: + From 2a7ed3bb32fe3d98c5782766b4e14f01a1a6c48d Mon Sep 17 00:00:00 2001 From: heck Date: Thu, 5 Nov 2020 15:45:41 +0100 Subject: [PATCH 42/84] no tox for now, too many unfinished things in this repo that dont work atm. --- docs/source/testing.rst | 8 -------- setup.cfg | 5 ----- tox.ini | 35 ----------------------------------- 3 files changed, 48 deletions(-) delete mode 100644 tox.ini diff --git a/docs/source/testing.rst b/docs/source/testing.rst index 31c4a87..ad67ca2 100644 --- a/docs/source/testing.rst +++ b/docs/source/testing.rst @@ -3,13 +3,5 @@ Testing See :ref:`install` to install the dependencies. -See `test/README.md` to run the tests in `test`. - To run the tests that use `pytest`, install the testing dependencies running ``pip install .[test]``. - -In Debian, you can install the testing dependencies in the system running ``apt -install tox``. - -Run the tests with the command `tox`. You can run individual tests by running -``tox -e ``, eg. ``tox -e py37`` or ``tox -e unit``. diff --git a/setup.cfg b/setup.cfg index 022d177..89e6e6f 100755 --- a/setup.cfg +++ b/setup.cfg @@ -31,14 +31,9 @@ python_requires = >= 3.6 test_suite = tests setup_requires = setuptools >=39.2.0 - # To automatically write the version from a SCM. - # Note: It fails with tags named as `Release_2.2.0-RC0`, because it is - # not conforming to semantic versioning, but it succeed with tags as - # `2.2.0-rc0`. setuptools_scm >= 4.1.2 [options.extras_require] # To install these dependencies, run pip install .[test] test = pytest - tox doc = sphinx diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 6026f39..0000000 --- a/tox.ini +++ /dev/null @@ -1,35 +0,0 @@ -[tox] -skip_missing_interpreters = True -envlist = py36, py37, py38, inst, setup, unit, doc - -# test that it can be installed with custom commands and clean env -[testenv:inst] -skip_install = True -commands = - - pip install . -recreate = True - -[testenv:setup] -skip_install = True -commands = python setup.py install -recreate = True - -[testenv:unit] -deps = .[test] -commands = pytest -svv tests - -[testenv:doc] -deps = .[doc] -whitelist_externals = make -changedir = docs -commands = - make html - make man - -# this requires Internet, it should not be in envlist -[testenv:doclinks] -deps = .[doc] -whitelist_externals = make -changedir = docs -commands = - make linkcheck From 08a03c0afa10570ba29dd3d4adaa659af8516942 Mon Sep 17 00:00:00 2001 From: heck Date: Thu, 5 Nov 2020 15:46:36 +0100 Subject: [PATCH 43/84] unix style newline at end of file required --- docs/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Makefile b/docs/Makefile index 69fe55e..ba501f6 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -16,4 +16,4 @@ help: # 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) \ No newline at end of file + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) From 5d6013ea9cc1e2d66c78dfada8084babeea1053b Mon Sep 17 00:00:00 2001 From: heck Date: Thu, 5 Nov 2020 16:30:35 +0100 Subject: [PATCH 44/84] option --local is superfluous, use --prefix --- setup.py | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/setup.py b/setup.py index 5541c98..335380e 100755 --- a/setup.py +++ b/setup.py @@ -32,13 +32,11 @@ def pEpLog(*msg): 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): @@ -130,7 +128,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) @@ -152,13 +149,6 @@ 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: From a3f117666bcce22e7b6e3264556828dae87d83f4 Mon Sep 17 00:00:00 2001 From: heck Date: Thu, 5 Nov 2020 18:00:21 +0100 Subject: [PATCH 45/84] nice theme "nature" --- docs/source/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 0ab999a..8e3ed74 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -82,7 +82,7 @@ pygments_style = None # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = "alabaster" +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 From 8f816dafb7014337743a003870c98189d7ba0f19 Mon Sep 17 00:00:00 2001 From: heck Date: Thu, 5 Nov 2020 18:00:41 +0100 Subject: [PATCH 46/84] overhaul install instructions --- docs/source/install.rst | 93 +++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 51 deletions(-) diff --git a/docs/source/install.rst b/docs/source/install.rst index 2670f4a..9c25ad8 100644 --- a/docs/source/install.rst +++ b/docs/source/install.rst @@ -3,79 +3,70 @@ Installation Requirements ------------ +In order to build, use or install this extension module, you need to have some +system dependencies already installed: -[Sequoia](https://gitlab.com/sequoia-pgp/sequoia) -[pEpEngine](https://pep.foundation/dev/repos/pEpEngine/) -[libpEpAdapter](https://pep.foundation/dev/repos/libpEpAdapter/) +* pEp-base (sequoia, libetpan, asn1c, yml2, pEpEngine, libpEpAdapter) +* boost-python -## Build Instructions +These `build instructions `_ will get you all setup. -To install all the dependencies, referer to their respective documentation. +Additionally, there is a `build script `_ +that executes these build instructions automatically (Debian and MacOS): -These build instructions should work on: - * Linux (Verified 26.4.20 - heck) - * MacOS (Verified 26.4.20 - heck) - * Windows +.. 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 -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 -``` +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. -To build against a pEp installation in a custom installation root (libs/includes) -```bash -python3 setup.py build_ext --prefix= -``` +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. -Installation in all platforms ------------------------------ +``cp local.conf.example local.conf`` -It is possible to install `pEpPythonAdapter` without building it first, since -the installation process will build it when it has not been built yet, but you -need to have all the dependencies already installed. +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`` + +Installation +------------ You can install this adapter in the in the following ways: -To install the extension module system wide, as root, run: -```bash -python3 setup.py install -``` +To install the extension module system wide or into a venv: -To install the extension module into you home dir -```bash -python3 setup.py install --user -``` +``make install`` + + +To install the extension module into you home dir: + +``make install-user`` -To install the extension module into a custom destination -```bash -python3 setup.py install --prefix= -``` -Attention: The ~ (tilde) does not get expanded, but env vars work ($HOME). If you're working on different Python projects, it's recommended to use -[virtualenv](https://virtualenv.pypa.io/en/stable/) to have different +`virtualenv `_ to have different libraries versions. If you're working in a virtualenv you can also install the package with -`pip install .` - -To install the package in "develop mode", run `python setup.py develop` -or `pip install -e .` +``pip install .`` -Debian installation --------------------- +To install the package in "develop mode", run ``python setup.py develop`` +or ``pip install -e .`` -You can also install the dependencies using the scripts -http://pep-security.lu/gitlab/juga/Internal-Deployment/-/blob/master/install-sys-deps-debian.sh -and -http://pep-security.lu/gitlab/juga/Internal-Deployment/-/blob/master/build-pep-stack.sh +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. From 32c70ecf7cea2798e2ab4f4d4a33b5f4f05e1abf Mon Sep 17 00:00:00 2001 From: heck Date: Thu, 5 Nov 2020 18:01:14 +0100 Subject: [PATCH 47/84] we build egg and wheel pkg --- setup.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.cfg b/setup.cfg index 89e6e6f..18ba1f0 100755 --- a/setup.cfg +++ b/setup.cfg @@ -32,6 +32,7 @@ test_suite = tests 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 = From 4499cbc60e818ddcb87ab00798c830cda0da26d9 Mon Sep 17 00:00:00 2001 From: heck Date: Thu, 5 Nov 2020 18:03:01 +0100 Subject: [PATCH 48/84] make install is now install sys wide, install-prefix gone, not needed. --- Makefile | 13 ++++--------- Makefile.conf | 6 ++++-- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 16181bf..28658da 100644 --- a/Makefile +++ b/Makefile @@ -16,18 +16,13 @@ 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) - # installs the package system wide -install-sys: compile +install: compile python3 setup.py install --force +# installs the package into your user home +install-user: compile + python3 setup.py install --force --user # build the module into build/ compile: diff --git a/Makefile.conf b/Makefile.conf index e83e1e8..d288202 100644 --- a/Makefile.conf +++ b/Makefile.conf @@ -6,7 +6,7 @@ DIST_DIR = ./dist # Build config Defaults DEBUG=0 -PREFIX?=$(HOME) +PREFIX= ######### Overrides ######### -include $(HERE)local.conf @@ -15,4 +15,6 @@ ifeq ($(DEBUG),1) DEBUG_OPT+=--debug endif -PREFIX_OPT += --prefix=$(PREFIX) \ No newline at end of file +ifneq ($(PREFIX),) + PREFIX_OPT += --prefix=$(PREFIX) +endif From 86ab223a30e6fbd99e5c593277ea26314e9c3e61 Mon Sep 17 00:00:00 2001 From: heck Date: Thu, 5 Nov 2020 18:09:12 +0100 Subject: [PATCH 49/84] Switch all doc to rst format --- README.md | 17 ----------------- README.rst | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 17 deletions(-) delete mode 100644 README.md create mode 100644 README.rst diff --git a/README.md b/README.md deleted file mode 100644 index db4eb70..0000000 --- a/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# pEpPythonAdapter - -Python adapter for the [pEpEngine](https://pep.foundation/dev/repos/pEpEngine/) - -## Documentation - -See 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 [bugtracker](https://pep.foundation/jira/projects/PYADPT/) and for any questions, you are always welome on #adapter. - -## License - -GPLv3 diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..e7186be --- /dev/null +++ b/README.rst @@ -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 `_. + + +License +------- +|GNU AFFERO GENERAL PUBLIC LICENSE +|Version 3, 19 November 2007 +|See LICENSE.txt From 9851fe28b63c4eecea2f73d44a95e7c997561f86 Mon Sep 17 00:00:00 2001 From: heck Date: Thu, 5 Nov 2020 18:24:13 +0100 Subject: [PATCH 50/84] Makefike structure, add targets for docs/sphinx --- Makefile | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 28658da..c4364af 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,16 @@ include Makefile.conf -.PHONY: all dist dist-egg dist-whl install install-prefix install-sys compile clean devenv envtest +.PHONY: all dist dist-egg dist-whl install install-prefix install-sys compile clean devenv envtest docs clean-docs all: dist +# Build +# ===== +compile: + python3 setup.py build_ext $(DEBUG_OPT) $(PREFIX_OPT) + +# Packaging +# ========= # create wheel and egg package in dist/ dist: dist-whl dist-egg @@ -15,7 +22,8 @@ dist-whl: compile dist-egg: compile python3 setup.py bdist_egg - +# Installation +# ============ # installs the package system wide install: compile python3 setup.py install --force @@ -24,19 +32,27 @@ install: compile install-user: compile python3 setup.py install --force --user -# build the module into build/ -compile: - python3 setup.py build_ext $(DEBUG_OPT) $(PREFIX_OPT) -clean: +clean: clean-docs rm -r $(BUILD_DIR) rm -r $(DIST_DIR) +# Creates an ad-hoc dev env using the compiled module devenv: LD_LIBRARY_PATH=$(PREFIX)/lib \ DYLD_LIBRARY_PATH=$(PREFIX)/lib \ PYTHONPATH=`pwd`/build/lib.linux-x86_64-3.7:`pwd`/build/lib.macosx-10.9-x86_64-3.8: \ bash -l +# Tests if the current environment is able to load the pEp module envtest: python3 -c 'import pEp' + + +# Documentation +# ============= +docs: + make html -C docs/ + +clean-docs + make clean -C docs/ From a88419824fc07b42408c794bd525824392ffec71 Mon Sep 17 00:00:00 2001 From: heck Date: Thu, 5 Nov 2020 22:51:39 +0100 Subject: [PATCH 51/84] from https://setuptools.readthedocs.io/en/latest/userguide/quickstart.html: All python package must provide a pyproject.toml and specify the backend (build system) it wants to use --- pyproject.toml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 pyproject.toml diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..8fab321 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools >=39.2.0", "setuptools_scm >= 4.1.2", "wheel >= 0.35.1"] +build-backend = "setuptools.build_meta" From d24ef6888e94699cc39fcfef89281e0aaf8b7cbc Mon Sep 17 00:00:00 2001 From: heck Date: Thu, 5 Nov 2020 22:52:30 +0100 Subject: [PATCH 52/84] yes, install doest require anything. (yet) --- setup.cfg | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 18ba1f0..09c3b60 100755 --- a/setup.cfg +++ b/setup.cfg @@ -11,7 +11,7 @@ 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 @@ -29,6 +29,8 @@ 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 From 08d1a5b3b56daca228740181ed82c3c70f2e1a8a Mon Sep 17 00:00:00 2001 From: heck Date: Thu, 5 Nov 2020 22:54:43 +0100 Subject: [PATCH 53/84] convenience target for creating venv that has LD_LIBRARY_PATH set already. make clean --- Makefile | 28 ++++++++++++++++++---------- Makefile.conf | 6 ++++++ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index c4364af..c1ae983 100644 --- a/Makefile +++ b/Makefile @@ -22,27 +22,35 @@ dist-whl: compile dist-egg: compile python3 setup.py bdist_egg + # Installation # ============ # installs the package system wide install: compile - python3 setup.py install --force + pip3 install . # installs the package into your user home install-user: compile - python3 setup.py install --force --user - + pip3 install . --user clean: clean-docs - rm -r $(BUILD_DIR) - rm -r $(DIST_DIR) + rm -rf $(BUILD_DIR) + rm -rf $(DIST_DIR) + rm -rf $(PYTHON_ARTIFACTS) + rm -rf $(VERSION_FILE) + rm -rf $(BUILD_INPLACE) + -# Creates an ad-hoc dev env using the compiled module -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 LD_LIBRARY_PATH=$(PREFIX)/lib \ DYLD_LIBRARY_PATH=$(PREFIX)/lib \ - PYTHONPATH=`pwd`/build/lib.linux-x86_64-3.7:`pwd`/build/lib.macosx-10.9-x86_64-3.8: \ - bash -l + bash --rcfile _venv/bin/activate # Tests if the current environment is able to load the pEp module envtest: @@ -54,5 +62,5 @@ envtest: docs: make html -C docs/ -clean-docs +clean-docs: make clean -C docs/ diff --git a/Makefile.conf b/Makefile.conf index d288202..4ed313a 100644 --- a/Makefile.conf +++ b/Makefile.conf @@ -3,6 +3,12 @@ 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 + + # Build config Defaults DEBUG=0 From c86c95bd77d7728b57d178ec132c3e12b0bd9b35 Mon Sep 17 00:00:00 2001 From: heck Date: Fri, 6 Nov 2020 00:30:29 +0100 Subject: [PATCH 54/84] More documentation on all operations --- Makefile | 41 ++++++++++++++++++++++++--------- Makefile.conf | 4 ++-- docs/source/install.rst | 50 ++++++++++++++++++++++++++++++++--------- src/pEp/__init__.py | 6 ----- 4 files changed, 72 insertions(+), 29 deletions(-) diff --git a/Makefile b/Makefile index c1ae983..449b53c 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,6 @@ include Makefile.conf -.PHONY: all dist dist-egg dist-whl install install-prefix install-sys compile clean devenv envtest docs clean-docs - +.PHONY: all dist dist-egg dist-whl install install-prefix install-sys compile clean devenv envtest docs clean-docs test all: dist # Build @@ -33,13 +32,6 @@ install: compile install-user: compile pip3 install . --user -clean: clean-docs - rm -rf $(BUILD_DIR) - rm -rf $(DIST_DIR) - rm -rf $(PYTHON_ARTIFACTS) - rm -rf $(VERSION_FILE) - rm -rf $(BUILD_INPLACE) - # Envrionment # =========== @@ -47,20 +39,47 @@ clean: clean-docs # already set for the prefix specified in local.conf # Only activates venv if already existing venv: - python3 -m venv _venv + python3 -m venv $(VENV_DIR) LD_LIBRARY_PATH=$(PREFIX)/lib \ DYLD_LIBRARY_PATH=$(PREFIX)/lib \ - bash --rcfile _venv/bin/activate + bash --rcfile $(VENV_DIR)/bin/activate # Tests if the current environment is able to load the pEp module envtest: python3 -c 'import pEp' +# Test +# ==== +# Use these targets only in venv created with 'make venv' +install-test: compile + pip3 install .[test] + +test: install-test + pytest + + +# Development +develop: compile + pip install -e . + # Documentation # ============= docs: 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/ diff --git a/Makefile.conf b/Makefile.conf index 4ed313a..23a8380 100644 --- a/Makefile.conf +++ b/Makefile.conf @@ -7,8 +7,8 @@ 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 diff --git a/docs/source/install.rst b/docs/source/install.rst index 9c25ad8..f1790f5 100644 --- a/docs/source/install.rst +++ b/docs/source/install.rst @@ -30,7 +30,6 @@ 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". @@ -40,29 +39,60 @@ 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. + Installation ------------ -You can install this adapter in the in the following ways: +You can install the module in the in the following ways: To install the extension module system wide or into a venv: ``make install`` - To install the extension module into you home dir: ``make install-user`` -If you're working on different Python projects, it's recommended to use -`virtualenv `_ to have different -libraries versions. +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 is not existing 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`` + +Test +---- +To run the whole testsuite you need to create/activate the venv, and then invoke the make target 'test'. +You can do this from a clean clone of the repo, no prior actions required, the whole module and all dependencies +will be compiled and installed into the venv. + +``make venv`` +``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. -If you're working in a virtualenv you can also install the package with -``pip install .`` +``make develop`` -To install the package in "develop mode", run ``python setup.py develop`` -or ``pip install -e .`` +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. Docker diff --git a/src/pEp/__init__.py b/src/pEp/__init__.py index 88d5204..596266b 100755 --- a/src/pEp/__init__.py +++ b/src/pEp/__init__.py @@ -30,12 +30,6 @@ from ._pEp import * # with an underscore (of _pEp), but we dont want to import them into this module import pEp._pEp -# TODO: Commented out until problems solved -# try: -# __version__ = get_distribution(__name__).version -# except DistributionNotFound: -# print("Package is not installed.") - # Executed on module import def init(): print(init, "called") From fab052a75bc1666c10602b3302b1d5c99d6020a9 Mon Sep 17 00:00:00 2001 From: heck Date: Fri, 6 Nov 2020 01:17:44 +0100 Subject: [PATCH 55/84] Fix sphinx make targets Re structure documentation, more simple for now. --- Makefile | 5 ++++- docs/source/conf.py | 3 +-- docs/source/documentation.rst | 13 ------------- docs/source/index.rst | 3 --- docs/source/install.rst | 32 ++++++++++++++++++++++++++++++++ docs/source/testing.rst | 7 ------- 6 files changed, 37 insertions(+), 26 deletions(-) delete mode 100644 docs/source/documentation.rst delete mode 100644 docs/source/testing.rst diff --git a/Makefile b/Makefile index 449b53c..a1bbb25 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,9 @@ all: dist 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/ @@ -65,7 +68,7 @@ develop: compile # Documentation # ============= -docs: +docs: compile-inplace make html -C docs/ diff --git a/docs/source/conf.py b/docs/source/conf.py index 8e3ed74..d8c5892 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -11,12 +11,11 @@ # 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 ----------------------------------------------------- -#from pkg_resources import get_distribution project = "pEpPythonAdapter" copyright = "2020, Volker Birk, heck, juga" diff --git a/docs/source/documentation.rst b/docs/source/documentation.rst deleted file mode 100644 index 929eae9..0000000 --- a/docs/source/documentation.rst +++ /dev/null @@ -1,13 +0,0 @@ -Building the documentation -========================= - -This documentation uses `Sphinx `_ - -It can be built in different formats. - -Run ``cd docs; make`` to see the possible formats. - -Run ``cd docs; make html`` to build the documentation in HTML format. - -You can see the generated HTML documentation in a browser opening the directory -`docs/build/html`. diff --git a/docs/source/index.rst b/docs/source/index.rst index f9b4955..8c59365 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -11,11 +11,8 @@ Welcome to pEpPythonAdapter's documentation! :caption: Contents: install - testing - documentation software_using api/pEp - Indices and tables ================== diff --git a/docs/source/install.rst b/docs/source/install.rst index f1790f5..8c4a45b 100644 --- a/docs/source/install.rst +++ b/docs/source/install.rst @@ -76,6 +76,7 @@ You can do this from a clean clone of the repo, no prior actions required, the w will be compiled and installed into the venv. ``make venv`` + ``make test`` @@ -94,6 +95,37 @@ changes to the C/C++ part of the module (_pEp). If you change just python code, 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 `_ +Refer to the `Sphinx installation instructions `_ 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 ------ diff --git a/docs/source/testing.rst b/docs/source/testing.rst deleted file mode 100644 index ad67ca2..0000000 --- a/docs/source/testing.rst +++ /dev/null @@ -1,7 +0,0 @@ -Testing -======= - -See :ref:`install` to install the dependencies. - -To run the tests that use `pytest`, install the testing dependencies running -``pip install .[test]``. From 6fefb8a0c97b67abd03206c3b03ccb8c672b81ff Mon Sep 17 00:00:00 2001 From: heck Date: Fri, 6 Nov 2020 13:45:22 +0100 Subject: [PATCH 56/84] typos etc.. --- README.rst | 2 +- docs/source/install.rst | 32 +++++++++++++++++--------------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/README.rst b/README.rst index e7186be..ee26c8c 100644 --- a/README.rst +++ b/README.rst @@ -1,6 +1,6 @@ pEpPythonAdapter ================ -Python adapter for the [pEpEngine](https://pep.foundation/dev/repos/pEpEngine/) +Python adapter for the `pEpEngine `_ Documentation diff --git a/docs/source/install.rst b/docs/source/install.rst index 8c4a45b..b3696d0 100644 --- a/docs/source/install.rst +++ b/docs/source/install.rst @@ -14,7 +14,7 @@ These `build instructions `_ 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/ +.. 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. @@ -42,25 +42,13 @@ To build the module just type: 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. -Installation ------------- -You can install the module in the in the following ways: - -To install the extension module system wide or into a venv: - -``make install`` - -To install the extension module into you home dir: - -``make install-user`` - 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 is not existing yet it will be created and activated. +or DYLD_LIBRARY_PATH set according to your ``local.conf``. +If the venv does not yet it will be created and activated. If the venv already exists it will only be activated. ``make venv`` @@ -69,6 +57,20 @@ 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 create/activate the venv, and then invoke the make target 'test'. From 8adb4a01f949305b0d1fa75ff6905535fcae5114 Mon Sep 17 00:00:00 2001 From: heck Date: Tue, 10 Nov 2020 00:09:48 +0100 Subject: [PATCH 57/84] some IDEs (pycharm, intellij) seem to have problems with a venv folder called _venv --- Makefile | 4 ++-- Makefile.conf | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index a1bbb25..c608c12 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ include Makefile.conf -.PHONY: all dist dist-egg dist-whl install install-prefix install-sys compile clean devenv envtest docs clean-docs test +.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 @@ -42,7 +42,7 @@ install-user: compile # already set for the prefix specified in local.conf # Only activates venv if already existing venv: - python3 -m venv $(VENV_DIR) + python -m venv $(VENV_DIR) LD_LIBRARY_PATH=$(PREFIX)/lib \ DYLD_LIBRARY_PATH=$(PREFIX)/lib \ bash --rcfile $(VENV_DIR)/bin/activate diff --git a/Makefile.conf b/Makefile.conf index 23a8380..126cc86 100644 --- a/Makefile.conf +++ b/Makefile.conf @@ -8,7 +8,7 @@ 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 +VENV_DIR = ./venv # Build config Defaults DEBUG=0 From 90a59ccce62f2459dea074cf3a22983d0535647f Mon Sep 17 00:00:00 2001 From: heck Date: Tue, 10 Nov 2020 10:27:38 +0100 Subject: [PATCH 58/84] for debian (python alias not working for make invocation) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c608c12..323a9c0 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ install-user: compile # already set for the prefix specified in local.conf # Only activates venv if already existing venv: - python -m venv $(VENV_DIR) + python3 -m venv $(VENV_DIR) LD_LIBRARY_PATH=$(PREFIX)/lib \ DYLD_LIBRARY_PATH=$(PREFIX)/lib \ bash --rcfile $(VENV_DIR)/bin/activate From f07f6e060cb8d30d75be32140189588b160accf4 Mon Sep 17 00:00:00 2001 From: heck Date: Tue, 10 Nov 2020 10:28:10 +0100 Subject: [PATCH 59/84] lets try moving env setup to fixtures --- tests/conftest.py | 2 ++ tests/test_identity.py | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index cac2a3b..c1bb7d8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -33,6 +33,8 @@ def tmpdir(tmpdir_factory, request): """Create a tmp dir for the tests""" base = str(hash(request.node.nodeid))[:3] bn = tmpdir_factory.mktemp(base) + import os + os.environ["HOME"] = str(bn) return bn diff --git a/tests/test_identity.py b/tests/test_identity.py index 59fdcb9..03829d0 100644 --- a/tests/test_identity.py +++ b/tests/test_identity.py @@ -5,8 +5,6 @@ from . import constants def test_create_one_identity_succeed(tmpdir): - # Change $HOME before initializing the db - os.environ["HOME"] = str(tmpdir) # It has to be imported here to get the management db initialized, import pEp alice = pEp.Identity() From e3c53a0d3cb6aa554cc1c72e4a963bda74d27d46 Mon Sep 17 00:00:00 2001 From: heck Date: Wed, 11 Nov 2020 15:19:06 +0100 Subject: [PATCH 60/84] Rebuild and fix pytest based tests in new dir tests_new. To work with defined env for engine using separate process per test. --- Makefile | 3 ++- pyproject.toml | 8 ++++++++ setup.cfg | 3 ++- {tests => tests_new}/conftest.py | 20 +++++++++---------- {tests => tests_new}/constants.py | 3 +-- {tests => tests_new}/data/README.md | 0 .../data/alice@openpgp.example.pub.asc | 0 .../data/alice@openpgp.example.sec.asc | 0 .../data/bob@openpgp.example.pub.asc | 0 .../data/bob@openpgp.example.sec.asc | 0 {tests => tests_new}/test_identity.py | 16 +++++++-------- {tests => tests_new}/test_message.py | 9 +++++---- {tests => tests_new}/test_pep.py | 2 +- 13 files changed, 36 insertions(+), 28 deletions(-) rename {tests => tests_new}/conftest.py (82%) rename {tests => tests_new}/constants.py (82%) rename {tests => tests_new}/data/README.md (100%) rename {tests => tests_new}/data/alice@openpgp.example.pub.asc (100%) rename {tests => tests_new}/data/alice@openpgp.example.sec.asc (100%) rename {tests => tests_new}/data/bob@openpgp.example.pub.asc (100%) rename {tests => tests_new}/data/bob@openpgp.example.sec.asc (100%) rename {tests => tests_new}/test_identity.py (93%) rename {tests => tests_new}/test_message.py (95%) rename {tests => tests_new}/test_pep.py (91%) diff --git a/Makefile b/Makefile index 323a9c0..e57f2a3 100644 --- a/Makefile +++ b/Makefile @@ -57,8 +57,9 @@ envtest: install-test: compile pip3 install .[test] +# TODO: maybe use setup.py test? test: install-test - pytest + pytest --forked # Development diff --git a/pyproject.toml b/pyproject.toml index 8fab321..ada2cf0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,11 @@ [build-system] 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 = "" +testpaths = [ + "tests_new", +] + diff --git a/setup.cfg b/setup.cfg index 09c3b60..e65917a 100755 --- a/setup.cfg +++ b/setup.cfg @@ -28,7 +28,7 @@ classifiers = zip_safe = false include_package_data = true python_requires = >= 3.6 -test_suite = tests +test_suite = tests_new install_requires = # deprecated/redundant with pyproject.toml, but lets keep both ways around for now setup_requires = @@ -39,4 +39,5 @@ setup_requires = # To install these dependencies, run pip install .[test] test = pytest + pytest-forked doc = sphinx diff --git a/tests/conftest.py b/tests_new/conftest.py similarity index 82% rename from tests/conftest.py rename to tests_new/conftest.py index c1bb7d8..23e220a 100644 --- a/tests/conftest.py +++ b/tests_new/conftest.py @@ -1,4 +1,5 @@ """pytest configuration for the unit tests.""" + import os import pytest @@ -28,14 +29,15 @@ def datadir(request): return D(request.fspath.dirpath("data")) -@pytest.fixture(scope='function') -def tmpdir(tmpdir_factory, request): +@pytest.fixture() +def ctx_init(tmpdir_factory, request): """Create a tmp dir for the tests""" - base = str(hash(request.node.nodeid))[:3] + base = str(abs(hash(request.node.nodeid)))[:3] bn = tmpdir_factory.mktemp(base) + print(bn) import os + os.environ["PEP_HOME"] = str(bn) os.environ["HOME"] = str(bn) - return bn @pytest.fixture() @@ -51,27 +53,25 @@ def bob_pub_key_data(datadir): @pytest.fixture() -def create_alice_identity(tmpdir, alice_sec_key_data, bob_pub_key_data): - os.environ["HOME"] = str(tmpdir) +def create_alice_identity(ctx_init, alice_sec_key_data): import pEp pEp.import_key(alice_sec_key_data) alice = pEp.Identity( constants.ALICE_ADDRESS, constants.ALICE_NAME, constants.ALICE_NAME_ADDR, constants.ALICE_FP, 0, '' - ) + ) pEp.set_own_key(alice, constants.ALICE_FP) return alice @pytest.fixture() -def create_bob_identity(tmpdir, bob_pub_key_data): - os.environ["HOME"] = str(tmpdir) +def create_bob_identity(ctx_init, bob_pub_key_data): import pEp pEp.import_key(bob_pub_key_data) bob = pEp.Identity( constants.BOB_ADDRESS, constants.BOB_NAME, '', constants.BOB_FP, 56, '' - ) + ) return bob diff --git a/tests/constants.py b/tests_new/constants.py similarity index 82% rename from tests/constants.py rename to tests_new/constants.py index f83f3bb..57d21aa 100644 --- a/tests/constants.py +++ b/tests_new/constants.py @@ -16,8 +16,7 @@ BOB_NAME_ADDR = NAME_ADDR.format(BOB_NAME, ANGLE_ADDR.format(BOB_ADDRESS)) ALICE_NAME = "Alice Lovelace" ALICE_ADDRESS = "alice@openpgp.example" ALICE_FP = "EB85BB5FA33A75E15E944E63F231550C4F47E38E" -ALICE_NAME_ADDR = NAME_ADDR.format(ALICE_NAME, - ANGLE_ADDR.format(ALICE_ADDRESS)) +ALICE_NAME_ADDR = NAME_ADDR.format(ALICE_NAME, ANGLE_ADDR.format(ALICE_ADDRESS)) SUBJECT = "This is a subject" BODY = "Hi world!\n" diff --git a/tests/data/README.md b/tests_new/data/README.md similarity index 100% rename from tests/data/README.md rename to tests_new/data/README.md diff --git a/tests/data/alice@openpgp.example.pub.asc b/tests_new/data/alice@openpgp.example.pub.asc similarity index 100% rename from tests/data/alice@openpgp.example.pub.asc rename to tests_new/data/alice@openpgp.example.pub.asc diff --git a/tests/data/alice@openpgp.example.sec.asc b/tests_new/data/alice@openpgp.example.sec.asc similarity index 100% rename from tests/data/alice@openpgp.example.sec.asc rename to tests_new/data/alice@openpgp.example.sec.asc diff --git a/tests/data/bob@openpgp.example.pub.asc b/tests_new/data/bob@openpgp.example.pub.asc similarity index 100% rename from tests/data/bob@openpgp.example.pub.asc rename to tests_new/data/bob@openpgp.example.pub.asc diff --git a/tests/data/bob@openpgp.example.sec.asc b/tests_new/data/bob@openpgp.example.sec.asc similarity index 100% rename from tests/data/bob@openpgp.example.sec.asc rename to tests_new/data/bob@openpgp.example.sec.asc diff --git a/tests/test_identity.py b/tests_new/test_identity.py similarity index 93% rename from tests/test_identity.py rename to tests_new/test_identity.py index 03829d0..329458d 100644 --- a/tests/test_identity.py +++ b/tests_new/test_identity.py @@ -4,7 +4,7 @@ import os from . import constants -def test_create_one_identity_succeed(tmpdir): +def test_create_one_identity_succeed(ctx_init): # It has to be imported here to get the management db initialized, import pEp alice = pEp.Identity() @@ -15,7 +15,7 @@ def test_create_one_identity_succeed(tmpdir): expected_alice = pEp.Identity( constants.ALICE_ADDRESS, constants.ALICE_NAME, '', constants.ALICE_FP, 0, '' - ) + ) # XXX: Can't compare objects # assert alice == expected_alice @@ -43,14 +43,13 @@ def test_create_one_identity_succeed(tmpdir): assert alice.flags == expected_alice.flags -def test_two_identities_succeed(tmpdir, bob_pub_key_data): - os.environ["HOME"] = str(tmpdir) +def test_two_identities_succeed(ctx_init, bob_pub_key_data): import pEp alice = pEp.Identity( constants.ALICE_ADDRESS, constants.ALICE_NAME, '', constants.ALICE_FP, 0, '' - ) + ) assert alice.address == constants.ALICE_ADDRESS assert alice.username == constants.ALICE_NAME assert alice.fpr == constants.ALICE_FP @@ -67,7 +66,7 @@ def test_two_identities_succeed(tmpdir, bob_pub_key_data): expected_bob = pEp.Identity( constants.BOB_ADDRESS, constants.BOB_NAME, '', constants.BOB_FP, 56, '' - ) + ) assert str(bob) == constants.BOB_NAME_ADDR assert bob.address == expected_bob.address @@ -88,8 +87,7 @@ def test_two_identities_succeed(tmpdir, bob_pub_key_data): assert bob.flags == 0 -def test_set_own_key(tmpdir, alice_sec_key_data): - os.environ["HOME"] = str(tmpdir) +def test_set_own_key(ctx_init, alice_sec_key_data): import pEp pEp.import_key(alice_sec_key_data) @@ -102,7 +100,7 @@ def test_set_own_key(tmpdir, alice_sec_key_data): expected_alice = pEp.Identity( constants.ALICE_ADDRESS, constants.ALICE_NAME, '', constants.ALICE_FP, 0, '' - ) + ) pEp.set_own_key(alice, alice.fpr) # assert str(alice) == constants.ALICE_NAME_ADDR diff --git a/tests/test_message.py b/tests_new/test_message.py similarity index 95% rename from tests/test_message.py rename to tests_new/test_message.py index 9787133..45fc4e4 100644 --- a/tests/test_message.py +++ b/tests_new/test_message.py @@ -30,8 +30,7 @@ def test_msg_enc_dec_roundtrip(create_alice_identity, create_bob_identity): assert str(enc_msg.from_) == constants.ALICE_NAME_ADDR assert str(enc_msg.to[0]) == constants.BOB_NAME_ADDR assert enc_msg.shortmsg == "p≡p" - assert enc_msg.longmsg == \ - "this message was encrypted with p≡p https://pEp-project.org" + assert enc_msg.longmsg == "this message was encrypted with p≡p https://pEp-project.org" # Decrypt message. dec_msg, key_list, rating, r = enc_msg.decrypt() @@ -54,7 +53,8 @@ def test_msg_enc_dec_roundtrip(create_alice_identity, create_bob_identity): # Content-Transfer-Encoding: doesn't print `quoted-printable` anymore. # Content-Disposition: is not present anymore. # `!` is not replaced by `=21` anymore. - expected_dec_lines = """From: Alice Lovelace + expected_dec_lines = \ +"""From: Alice Lovelace To: Bob Babagge Subject: This is a subject X-pEp-Version: 2.1 @@ -129,7 +129,8 @@ def test_dec_msg_len(create_alice_identity, create_bob_identity): dec_msg_len = len(str(dec_msg)) assert dec_msg.longmsg.replace("\r", "") == constants.BODY # msg.longmsg - expected_dec_msg = """From: Alice Lovelace \r + expected_dec_msg = \ +"""From: Alice Lovelace \r To: Bob Babagge \r Subject: This is a subject\r X-pEp-Version: 2.1\r diff --git a/tests/test_pep.py b/tests_new/test_pep.py similarity index 91% rename from tests/test_pep.py rename to tests_new/test_pep.py index 3e63973..79c052c 100755 --- a/tests/test_pep.py +++ b/tests_new/test_pep.py @@ -1,10 +1,10 @@ """Unit test for pEp package, not for subpackages or modules.""" -from pEp import __version__ def test_pep_version(): """ Test that __version__ is not None or empty and is not 0.0.0.""" + from pEp import __version__ # We could also test that match the regex, but that is already a test in # setuptools_scm itself. assert __version__ From cccabb66c3760d99337184defd8e7ce354d66cd5 Mon Sep 17 00:00:00 2001 From: heck Date: Wed, 11 Nov 2020 15:23:58 +0100 Subject: [PATCH 61/84] now rename the tests suite to tests again --- pyproject.toml | 2 +- setup.cfg | 2 +- tests/__init__.py | 0 {tests_new => tests}/conftest.py | 0 {tests_new => tests}/constants.py | 0 {tests_new => tests}/data/README.md | 0 {tests_new => tests}/data/alice@openpgp.example.pub.asc | 0 {tests_new => tests}/data/alice@openpgp.example.sec.asc | 0 {tests_new => tests}/data/bob@openpgp.example.pub.asc | 0 {tests_new => tests}/data/bob@openpgp.example.sec.asc | 0 {tests_new => tests}/test_identity.py | 0 {tests_new => tests}/test_message.py | 0 {tests_new => tests}/test_pep.py | 0 13 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 tests/__init__.py rename {tests_new => tests}/conftest.py (100%) rename {tests_new => tests}/constants.py (100%) rename {tests_new => tests}/data/README.md (100%) rename {tests_new => tests}/data/alice@openpgp.example.pub.asc (100%) rename {tests_new => tests}/data/alice@openpgp.example.sec.asc (100%) rename {tests_new => tests}/data/bob@openpgp.example.pub.asc (100%) rename {tests_new => tests}/data/bob@openpgp.example.sec.asc (100%) rename {tests_new => tests}/test_identity.py (100%) rename {tests_new => tests}/test_message.py (100%) rename {tests_new => tests}/test_pep.py (100%) diff --git a/pyproject.toml b/pyproject.toml index ada2cf0..d8a081d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,6 +6,6 @@ build-backend = "setuptools.build_meta" minversion = "6.0" addopts = "" testpaths = [ - "tests_new", + "tests", ] diff --git a/setup.cfg b/setup.cfg index e65917a..88d8f22 100755 --- a/setup.cfg +++ b/setup.cfg @@ -28,7 +28,7 @@ classifiers = zip_safe = false include_package_data = true python_requires = >= 3.6 -test_suite = tests_new +test_suite = tests install_requires = # deprecated/redundant with pyproject.toml, but lets keep both ways around for now setup_requires = diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests_new/conftest.py b/tests/conftest.py similarity index 100% rename from tests_new/conftest.py rename to tests/conftest.py diff --git a/tests_new/constants.py b/tests/constants.py similarity index 100% rename from tests_new/constants.py rename to tests/constants.py diff --git a/tests_new/data/README.md b/tests/data/README.md similarity index 100% rename from tests_new/data/README.md rename to tests/data/README.md diff --git a/tests_new/data/alice@openpgp.example.pub.asc b/tests/data/alice@openpgp.example.pub.asc similarity index 100% rename from tests_new/data/alice@openpgp.example.pub.asc rename to tests/data/alice@openpgp.example.pub.asc diff --git a/tests_new/data/alice@openpgp.example.sec.asc b/tests/data/alice@openpgp.example.sec.asc similarity index 100% rename from tests_new/data/alice@openpgp.example.sec.asc rename to tests/data/alice@openpgp.example.sec.asc diff --git a/tests_new/data/bob@openpgp.example.pub.asc b/tests/data/bob@openpgp.example.pub.asc similarity index 100% rename from tests_new/data/bob@openpgp.example.pub.asc rename to tests/data/bob@openpgp.example.pub.asc diff --git a/tests_new/data/bob@openpgp.example.sec.asc b/tests/data/bob@openpgp.example.sec.asc similarity index 100% rename from tests_new/data/bob@openpgp.example.sec.asc rename to tests/data/bob@openpgp.example.sec.asc diff --git a/tests_new/test_identity.py b/tests/test_identity.py similarity index 100% rename from tests_new/test_identity.py rename to tests/test_identity.py diff --git a/tests_new/test_message.py b/tests/test_message.py similarity index 100% rename from tests_new/test_message.py rename to tests/test_message.py diff --git a/tests_new/test_pep.py b/tests/test_pep.py similarity index 100% rename from tests_new/test_pep.py rename to tests/test_pep.py From 91c2056d9d4c8b78e0aa6affac18fde240493832 Mon Sep 17 00:00:00 2001 From: heck Date: Wed, 11 Nov 2020 15:25:01 +0100 Subject: [PATCH 62/84] forgot __init__.py for tests package --- tests/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/__init__.py diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 From 9abb0dd46d53090fa5669ed5d1f9da1bcda84c14 Mon Sep 17 00:00:00 2001 From: heck Date: Wed, 11 Nov 2020 16:49:31 +0100 Subject: [PATCH 63/84] 'make test' and 'make install-test' independent --- Makefile | 3 ++- docs/source/install.rst | 10 +++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index e57f2a3..c8b5a0d 100644 --- a/Makefile +++ b/Makefile @@ -58,7 +58,8 @@ install-test: compile pip3 install .[test] # TODO: maybe use setup.py test? -test: install-test +# --forked, because every test needs a separate process, see PYADPT-100 +test: pytest --forked diff --git a/docs/source/install.rst b/docs/source/install.rst index b3696d0..1fd1408 100644 --- a/docs/source/install.rst +++ b/docs/source/install.rst @@ -73,12 +73,16 @@ To install the extension module into your home dir, use: Test ---- -To run the whole testsuite you need to create/activate the venv, and then invoke the make target 'test'. -You can do this from a clean clone of the repo, no prior actions required, the whole module and all dependencies -will be compiled and installed into the venv. +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`` From bf4d618a8a96efc2fc06950cc643390a24ecb014 Mon Sep 17 00:00:00 2001 From: heck Date: Wed, 11 Nov 2020 17:04:35 +0100 Subject: [PATCH 64/84] Software using pEpPythonAdapter --- docs/source/software_using.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/source/software_using.rst b/docs/source/software_using.rst index 59eb6fa..11274c0 100644 --- a/docs/source/software_using.rst +++ b/docs/source/software_using.rst @@ -1,4 +1,7 @@ Software using pEpPythonAdapter =============================== +- `pEpProxy `_ +- `command-line-tool `_ - `pEpPythonMixnet `_ +- `pEpSimulator `_ From 59637238535be58c838ca9e0df9cee7165141a2f Mon Sep 17 00:00:00 2001 From: heck Date: Wed, 11 Nov 2020 17:43:21 +0100 Subject: [PATCH 65/84] just add encoding header to all test files "# -*- coding: utf-8 -*-" --- tests/__init__.py | 1 + tests/conftest.py | 1 + tests/constants.py | 1 + tests/test_identity.py | 1 + tests/test_message.py | 1 + tests/test_pep.py | 1 + 6 files changed, 6 insertions(+) diff --git a/tests/__init__.py b/tests/__init__.py index e69de29..40a96af 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/tests/conftest.py b/tests/conftest.py index 23e220a..c06073c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- """pytest configuration for the unit tests.""" import os diff --git a/tests/constants.py b/tests/constants.py index 57d21aa..dd75304 100644 --- a/tests/constants.py +++ b/tests/constants.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- """Constants for unit tests.""" diff --git a/tests/test_identity.py b/tests/test_identity.py index 329458d..87bca4b 100644 --- a/tests/test_identity.py +++ b/tests/test_identity.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- """Identity unit tests.""" import os diff --git a/tests/test_message.py b/tests/test_message.py index 45fc4e4..39563a2 100644 --- a/tests/test_message.py +++ b/tests/test_message.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- """Message unit tests.""" from . import constants diff --git a/tests/test_pep.py b/tests/test_pep.py index 79c052c..976c74f 100755 --- a/tests/test_pep.py +++ b/tests/test_pep.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- """Unit test for pEp package, not for subpackages or modules.""" From 61174d0136a415a421bd38c846c9622fa5a25fa1 Mon Sep 17 00:00:00 2001 From: heck Date: Wed, 11 Nov 2020 17:52:16 +0100 Subject: [PATCH 66/84] rename fixtures, make distinction between import and create. (create == myself()) --- tests/conftest.py | 4 ++-- tests/test_message.py | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index c06073c..8806cbe 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -54,7 +54,7 @@ def bob_pub_key_data(datadir): @pytest.fixture() -def create_alice_identity(ctx_init, alice_sec_key_data): +def import_identity_alice(ctx_init, alice_sec_key_data): import pEp pEp.import_key(alice_sec_key_data) @@ -67,7 +67,7 @@ def create_alice_identity(ctx_init, alice_sec_key_data): @pytest.fixture() -def create_bob_identity(ctx_init, bob_pub_key_data): +def import_identity_bob(ctx_init, bob_pub_key_data): import pEp pEp.import_key(bob_pub_key_data) diff --git a/tests/test_message.py b/tests/test_message.py index 39563a2..e333514 100644 --- a/tests/test_message.py +++ b/tests/test_message.py @@ -4,11 +4,11 @@ from . import constants -def test_msg_enc_dec_roundtrip(create_alice_identity, create_bob_identity): +def test_msg_enc_dec_roundtrip(import_identity_alice, import_identity_bob): import pEp - alice = create_alice_identity - bob = create_bob_identity + alice = import_identity_alice + bob = import_identity_bob msg = pEp.Message(constants.OUTGOING_MSG, alice) msg.to = [bob] @@ -72,7 +72,7 @@ Hi world! assert dec_lines[7:] == expected_dec_lines[7:] -def test_msg_len_changes(create_alice_identity, create_bob_identity): +def test_msg_len_changes(import_identity_alice, import_identity_bob): """Test that the original message is modified after encryption. Headers are added and therefore the modified unencrypted message length @@ -84,8 +84,8 @@ def test_msg_len_changes(create_alice_identity, create_bob_identity): """ import pEp - alice = create_alice_identity - bob = create_bob_identity + alice = import_identity_alice + bob = import_identity_bob msg = pEp.outgoing_message(alice) msg.to = [bob] @@ -105,7 +105,7 @@ def test_msg_len_changes(create_alice_identity, create_bob_identity): assert msg_after_encrypt_len != msg_len -def test_dec_msg_len(create_alice_identity, create_bob_identity): +def test_dec_msg_len(import_identity_alice, import_identity_bob): """ Test that the decrypted message length is different from the original. @@ -114,8 +114,8 @@ def test_dec_msg_len(create_alice_identity, create_bob_identity): """ import pEp - alice = create_alice_identity - bob = create_bob_identity + alice = import_identity_alice + bob = import_identity_bob msg = pEp.outgoing_message(alice) msg.to = [bob] @@ -155,12 +155,12 @@ Hi world!\r assert dec_msg_len - len_extra_headers == msg_len -def test_null_char_rmed(create_alice_identity, create_bob_identity): +def test_null_char_rmed(import_identity_alice, import_identity_bob): """Test that null characters and anything after them is removed.""" import pEp - alice = create_alice_identity - bob = create_bob_identity + alice = import_identity_alice + bob = import_identity_bob msg = pEp.outgoing_message(alice) msg.to = [bob] From 23829e25078957d7f0dba81ebf81fe89b14c6ae5 Mon Sep 17 00:00:00 2001 From: heck Date: Wed, 11 Nov 2020 18:00:32 +0100 Subject: [PATCH 67/84] just renaming --- tests/conftest.py | 18 +++++++++--------- tests/constants.py | 4 ++-- tests/test_identity.py | 24 ++++++++++++------------ tests/test_message.py | 4 ++-- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 8806cbe..98bdedc 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -42,37 +42,37 @@ def ctx_init(tmpdir_factory, request): @pytest.fixture() -def alice_sec_key_data(datadir): +def alice_key_sec(datadir): key_data = datadir.read('alice@openpgp.example.sec.asc') return key_data @pytest.fixture() -def bob_pub_key_data(datadir): +def bob_key_pub(datadir): key_data = datadir.read('bob@openpgp.example.pub.asc') return key_data @pytest.fixture() -def import_identity_alice(ctx_init, alice_sec_key_data): +def import_identity_alice(ctx_init, alice_key_sec): import pEp - pEp.import_key(alice_sec_key_data) + pEp.import_key(alice_key_sec) alice = pEp.Identity( constants.ALICE_ADDRESS, constants.ALICE_NAME, - constants.ALICE_NAME_ADDR, constants.ALICE_FP, 0, '' + constants.ALICE_NAME_ADDR, constants.ALICE_FPR, 0, '' ) - pEp.set_own_key(alice, constants.ALICE_FP) + pEp.set_own_key(alice, constants.ALICE_FPR) return alice @pytest.fixture() -def import_identity_bob(ctx_init, bob_pub_key_data): +def import_identity_bob(ctx_init, bob_key_pub): import pEp - pEp.import_key(bob_pub_key_data) + pEp.import_key(bob_key_pub) bob = pEp.Identity( constants.BOB_ADDRESS, constants.BOB_NAME, '', - constants.BOB_FP, 56, '' + constants.BOB_FPR, 56, '' ) return bob diff --git a/tests/constants.py b/tests/constants.py index dd75304..6924129 100644 --- a/tests/constants.py +++ b/tests/constants.py @@ -11,12 +11,12 @@ NAME_ADDR = "{} {}" BOB_NAME = "Bob Babagge" BOB_ADDRESS = "bob@openpgp.example" -BOB_FP = "D1A66E1A23B182C9980F788CFBFCC82A015E7330" +BOB_FPR = "D1A66E1A23B182C9980F788CFBFCC82A015E7330" BOB_NAME_ADDR = NAME_ADDR.format(BOB_NAME, ANGLE_ADDR.format(BOB_ADDRESS)) ALICE_NAME = "Alice Lovelace" ALICE_ADDRESS = "alice@openpgp.example" -ALICE_FP = "EB85BB5FA33A75E15E944E63F231550C4F47E38E" +ALICE_FPR = "EB85BB5FA33A75E15E944E63F231550C4F47E38E" ALICE_NAME_ADDR = NAME_ADDR.format(ALICE_NAME, ANGLE_ADDR.format(ALICE_ADDRESS)) SUBJECT = "This is a subject" diff --git a/tests/test_identity.py b/tests/test_identity.py index 87bca4b..86307d9 100644 --- a/tests/test_identity.py +++ b/tests/test_identity.py @@ -11,11 +11,11 @@ def test_create_one_identity_succeed(ctx_init): alice = pEp.Identity() alice.address = constants.ALICE_ADDRESS alice.username = constants.ALICE_NAME - alice.fpr = constants.ALICE_FP + alice.fpr = constants.ALICE_FPR expected_alice = pEp.Identity( constants.ALICE_ADDRESS, constants.ALICE_NAME, '', - constants.ALICE_FP, 0, '' + constants.ALICE_FPR, 0, '' ) # XXX: Can't compare objects @@ -44,29 +44,29 @@ def test_create_one_identity_succeed(ctx_init): assert alice.flags == expected_alice.flags -def test_two_identities_succeed(ctx_init, bob_pub_key_data): +def test_two_identities_succeed(ctx_init, bob_key_pub): import pEp alice = pEp.Identity( constants.ALICE_ADDRESS, constants.ALICE_NAME, '', - constants.ALICE_FP, 0, '' + constants.ALICE_FPR, 0, '' ) assert alice.address == constants.ALICE_ADDRESS assert alice.username == constants.ALICE_NAME - assert alice.fpr == constants.ALICE_FP + assert alice.fpr == constants.ALICE_FPR assert alice.user_id == "" assert alice.comm_type == 0 assert alice.flags == 0 - pEp.import_key(bob_pub_key_data) + pEp.import_key(bob_key_pub) bob = pEp.Identity() bob.address = constants.BOB_ADDRESS bob.username = constants.BOB_NAME - bob.fpr = constants.BOB_FP + bob.fpr = constants.BOB_FPR expected_bob = pEp.Identity( constants.BOB_ADDRESS, constants.BOB_NAME, '', - constants.BOB_FP, 56, '' + constants.BOB_FPR, 56, '' ) assert str(bob) == constants.BOB_NAME_ADDR @@ -88,19 +88,19 @@ def test_two_identities_succeed(ctx_init, bob_pub_key_data): assert bob.flags == 0 -def test_set_own_key(ctx_init, alice_sec_key_data): +def test_set_own_key(ctx_init, alice_key_sec): import pEp - pEp.import_key(alice_sec_key_data) + pEp.import_key(alice_key_sec) alice = pEp.Identity() alice.address = constants.ALICE_ADDRESS alice.username = constants.ALICE_NAME - alice.fpr = constants.ALICE_FP + alice.fpr = constants.ALICE_FPR alice.user_id = constants.ALICE_NAME_ADDR expected_alice = pEp.Identity( constants.ALICE_ADDRESS, constants.ALICE_NAME, '', - constants.ALICE_FP, 0, '' + constants.ALICE_FPR, 0, '' ) pEp.set_own_key(alice, alice.fpr) diff --git a/tests/test_message.py b/tests/test_message.py index e333514..1641614 100644 --- a/tests/test_message.py +++ b/tests/test_message.py @@ -43,8 +43,8 @@ def test_msg_enc_dec_roundtrip(import_identity_alice, import_identity_bob): assert rating == pEp._pEp.rating.reliable # The first 2 keys are Alice's ones, the last is Bob's one. - assert key_list[0] == key_list[1] == constants.ALICE_FP - assert key_list[-1] == constants.BOB_FP + assert key_list[0] == key_list[1] == constants.ALICE_FPR + assert key_list[-1] == constants.BOB_FPR assert dec_msg.shortmsg == constants.SUBJECT assert dec_msg.longmsg.replace("\r", "") == msg.longmsg dec_lines = str(dec_msg).replace("\r", "").split("\n") From 5b12e284c88ff79b1d45ba69a572e6d0d391c367 Mon Sep 17 00:00:00 2001 From: heck Date: Wed, 11 Nov 2020 18:28:16 +0100 Subject: [PATCH 68/84] structuring fixtures... --- tests/conftest.py | 41 ++++++++++++++++++++++------------------- tests/test_identity.py | 11 +++-------- tests/test_message.py | 32 ++++++++++++-------------------- 3 files changed, 37 insertions(+), 47 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 98bdedc..0c78e12 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -6,7 +6,7 @@ import pytest from . import constants - +# Static Data @pytest.fixture() def datadir(request): """Get, read, open test files from the tests "data" directory.""" @@ -29,47 +29,50 @@ def datadir(request): return f.readlines() return D(request.fspath.dirpath("data")) - -@pytest.fixture() -def ctx_init(tmpdir_factory, request): - """Create a tmp dir for the tests""" - base = str(abs(hash(request.node.nodeid)))[:3] - bn = tmpdir_factory.mktemp(base) - print(bn) - import os - os.environ["PEP_HOME"] = str(bn) - os.environ["HOME"] = str(bn) - - @pytest.fixture() def alice_key_sec(datadir): key_data = datadir.read('alice@openpgp.example.sec.asc') return key_data - @pytest.fixture() def bob_key_pub(datadir): key_data = datadir.read('bob@openpgp.example.pub.asc') return key_data +# Init +@pytest.fixture() +def env_init(tmpdir_factory, request): + """Create a tmp dir for the tests""" + base = str(abs(hash(request.node.nodeid)))[:3] + bn = tmpdir_factory.mktemp(base) + print(bn) + import os + os.environ["PEP_HOME"] = str(bn) + os.environ["HOME"] = str(bn) @pytest.fixture() -def import_identity_alice(ctx_init, alice_key_sec): +def pEp(env_init): import pEp + return pEp +# Identities +@pytest.fixture() +def import_ident_alice(pEp, alice_key_sec): pEp.import_key(alice_key_sec) alice = pEp.Identity( constants.ALICE_ADDRESS, constants.ALICE_NAME, constants.ALICE_NAME_ADDR, constants.ALICE_FPR, 0, '' ) - pEp.set_own_key(alice, constants.ALICE_FPR) return alice - @pytest.fixture() -def import_identity_bob(ctx_init, bob_key_pub): - import pEp +def import_ident_alice_as_own_ident(pEp, import_ident_alice): + alice = import_ident_alice + pEp.set_own_key(alice, constants.ALICE_FPR) + return alice +@pytest.fixture() +def import_ident_bob(pEp, bob_key_pub): pEp.import_key(bob_key_pub) bob = pEp.Identity( constants.BOB_ADDRESS, constants.BOB_NAME, '', diff --git a/tests/test_identity.py b/tests/test_identity.py index 86307d9..f3161da 100644 --- a/tests/test_identity.py +++ b/tests/test_identity.py @@ -5,9 +5,8 @@ import os from . import constants -def test_create_one_identity_succeed(ctx_init): +def test_create_one_identity_succeed(pEp): # It has to be imported here to get the management db initialized, - import pEp alice = pEp.Identity() alice.address = constants.ALICE_ADDRESS alice.username = constants.ALICE_NAME @@ -44,9 +43,7 @@ def test_create_one_identity_succeed(ctx_init): assert alice.flags == expected_alice.flags -def test_two_identities_succeed(ctx_init, bob_key_pub): - import pEp - +def test_two_identities_succeed(pEp, bob_key_pub): alice = pEp.Identity( constants.ALICE_ADDRESS, constants.ALICE_NAME, '', constants.ALICE_FPR, 0, '' @@ -88,9 +85,7 @@ def test_two_identities_succeed(ctx_init, bob_key_pub): assert bob.flags == 0 -def test_set_own_key(ctx_init, alice_key_sec): - import pEp - +def test_set_own_key(pEp, alice_key_sec): pEp.import_key(alice_key_sec) alice = pEp.Identity() alice.address = constants.ALICE_ADDRESS diff --git a/tests/test_message.py b/tests/test_message.py index 1641614..0d5c810 100644 --- a/tests/test_message.py +++ b/tests/test_message.py @@ -4,11 +4,9 @@ from . import constants -def test_msg_enc_dec_roundtrip(import_identity_alice, import_identity_bob): - import pEp - - alice = import_identity_alice - bob = import_identity_bob +def test_msg_enc_dec_roundtrip(pEp, import_ident_alice_as_own_ident, import_ident_bob): + alice = import_ident_alice_as_own_ident + bob = import_ident_bob msg = pEp.Message(constants.OUTGOING_MSG, alice) msg.to = [bob] @@ -72,7 +70,7 @@ Hi world! assert dec_lines[7:] == expected_dec_lines[7:] -def test_msg_len_changes(import_identity_alice, import_identity_bob): +def test_msg_len_changes(pEp, import_ident_alice_as_own_ident, import_ident_bob): """Test that the original message is modified after encryption. Headers are added and therefore the modified unencrypted message length @@ -82,10 +80,8 @@ def test_msg_len_changes(import_identity_alice, import_identity_bob): extra headers and modify the subject returning a new message. """ - import pEp - - alice = import_identity_alice - bob = import_identity_bob + alice = import_ident_alice_as_own_ident + bob = import_ident_bob msg = pEp.outgoing_message(alice) msg.to = [bob] @@ -105,17 +101,15 @@ def test_msg_len_changes(import_identity_alice, import_identity_bob): assert msg_after_encrypt_len != msg_len -def test_dec_msg_len(import_identity_alice, import_identity_bob): +def test_dec_msg_len(pEp, import_ident_alice_as_own_ident, import_ident_bob): """ Test that the decrypted message length is different from the original. Because it adds extra headers. """ - import pEp - - alice = import_identity_alice - bob = import_identity_bob + alice = import_ident_alice_as_own_ident + bob = import_ident_bob msg = pEp.outgoing_message(alice) msg.to = [bob] @@ -155,12 +149,10 @@ Hi world!\r assert dec_msg_len - len_extra_headers == msg_len -def test_null_char_rmed(import_identity_alice, import_identity_bob): +def test_null_char_rmed(pEp, import_ident_alice_as_own_ident, import_ident_bob): """Test that null characters and anything after them is removed.""" - import pEp - - alice = import_identity_alice - bob = import_identity_bob + alice = import_ident_alice_as_own_ident + bob = import_ident_bob msg = pEp.outgoing_message(alice) msg.to = [bob] From f70c58685afec4961a54ada61b5011c446c529c8 Mon Sep 17 00:00:00 2001 From: heck Date: Wed, 11 Nov 2020 18:34:39 +0100 Subject: [PATCH 69/84] default pytest opts belong into pyproject.toml --- Makefile | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c8b5a0d..494ad53 100644 --- a/Makefile +++ b/Makefile @@ -60,7 +60,7 @@ install-test: compile # TODO: maybe use setup.py test? # --forked, because every test needs a separate process, see PYADPT-100 test: - pytest --forked + pytest # Development diff --git a/pyproject.toml b/pyproject.toml index d8a081d..d624b05 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [tool.pytest.ini_options] minversion = "6.0" -addopts = "" +addopts = "-sv --forked" testpaths = [ "tests", ] From 938639b379c59c7ce17fd30cde716518e4237cdd Mon Sep 17 00:00:00 2001 From: heck Date: Wed, 11 Nov 2020 18:56:13 +0100 Subject: [PATCH 70/84] constants add user id, etc... --- tests/constants.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tests/constants.py b/tests/constants.py index 6924129..15ce0c9 100644 --- a/tests/constants.py +++ b/tests/constants.py @@ -9,15 +9,17 @@ INCOMING_MSG = 2 ANGLE_ADDR = "<{}>" NAME_ADDR = "{} {}" -BOB_NAME = "Bob Babagge" -BOB_ADDRESS = "bob@openpgp.example" -BOB_FPR = "D1A66E1A23B182C9980F788CFBFCC82A015E7330" -BOB_NAME_ADDR = NAME_ADDR.format(BOB_NAME, ANGLE_ADDR.format(BOB_ADDRESS)) - -ALICE_NAME = "Alice Lovelace" +ALICE_USERNAME = "Alice Lovelace" ALICE_ADDRESS = "alice@openpgp.example" +ALICE_ID = 23 ALICE_FPR = "EB85BB5FA33A75E15E944E63F231550C4F47E38E" -ALICE_NAME_ADDR = NAME_ADDR.format(ALICE_NAME, ANGLE_ADDR.format(ALICE_ADDRESS)) +ALICE_NAME_ADDR = NAME_ADDR.format(ALICE_USERNAME, ANGLE_ADDR.format(ALICE_ADDRESS)) + +BOB_USERNAME = "Bob Babagge" +BOB_ADDRESS = "bob@openpgp.example" +BOB_ID = 23 +BOB_FPR = "D1A66E1A23B182C9980F788CFBFCC82A015E7330" +BOB_NAME_ADDR = NAME_ADDR.format(BOB_USERNAME, ANGLE_ADDR.format(BOB_ADDRESS)) SUBJECT = "This is a subject" BODY = "Hi world!\n" From 04cd048ee41ac17dda468f6f04a738531f0b69df Mon Sep 17 00:00:00 2001 From: heck Date: Thu, 12 Nov 2020 18:05:00 +0100 Subject: [PATCH 71/84] Update author credits --- AUTHORS.txt | 9 +++++++++ docs/source/conf.py | 4 ++-- setup.cfg | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 AUTHORS.txt diff --git a/AUTHORS.txt b/AUTHORS.txt new file mode 100644 index 0000000..40ce2c3 --- /dev/null +++ b/AUTHORS.txt @@ -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 +Heck +Hartmut Goebel +juga diff --git a/docs/source/conf.py b/docs/source/conf.py index d8c5892..3a966f5 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -18,8 +18,8 @@ sys.path.insert(0, os.path.abspath('../../src')) # -- Project information ----------------------------------------------------- project = "pEpPythonAdapter" -copyright = "2020, Volker Birk, heck, juga" -author = "Volker Birk, heck, juga" +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 diff --git a/setup.cfg b/setup.cfg index 88d8f22..6a82799 100755 --- a/setup.cfg +++ b/setup.cfg @@ -3,7 +3,7 @@ name = pEp url = https://pep.foundation download_url = ext_package = pEp -author = Volker Birk +author = Volker Birk, heck, Hartmut Goebel, juga author_email = vb@pep-project.org maintainer = heck maintainer_email = heck@pep.foundation From e6f6a1f6abc311810c066e56521ea184da1d4412 Mon Sep 17 00:00:00 2001 From: heck Date: Fri, 13 Nov 2020 02:49:35 +0100 Subject: [PATCH 72/84] test infrastructure --- pyproject.toml | 2 +- tests/conftest.py | 78 ++++------- tests/constants.py | 18 +-- ...63D8319D6885F638C5AA81E1B5457A2B40.pub.asc | 24 ++++ ...63D8319D6885F638C5AA81E1B5457A2B40.sec.asc | 26 ++++ ...1B9C754564CBAD15D2D18F7444594F2283.pub.asc | 24 ++++ ...1B9C754564CBAD15D2D18F7444594F2283.sec.asc | 26 ++++ ...5EE953EBBEB948F11A6A03DB2A17FB9D15.pub.asc | 24 ++++ ...5EE953EBBEB948F11A6A03DB2A17FB9D15.sec.asc | 26 ++++ ...699EF1215F1558A496D9C1D4B0984094E5.pub.asc | 24 ++++ ...699EF1215F1558A496D9C1D4B0984094E5.sec.asc | 26 ++++ tests/data/README.md | 2 - tests/data/alice@openpgp.example.pub.asc | 14 -- tests/data/alice@openpgp.example.sec.asc | 16 --- tests/data/bob@openpgp.example.pub.asc | 42 ------ tests/data/bob@openpgp.example.sec.asc | 82 ------------ tests/model.py | 125 ++++++++++++++++++ tests/test_basic.py | 28 ++++ tests/test_identity.py | 73 +++++----- tests/test_message.py | 26 ++-- tests/utils.py | 9 ++ 21 files changed, 438 insertions(+), 277 deletions(-) create mode 100644 tests/data/1A97F263D8319D6885F638C5AA81E1B5457A2B40.pub.asc create mode 100644 tests/data/1A97F263D8319D6885F638C5AA81E1B5457A2B40.sec.asc create mode 100644 tests/data/2D35731B9C754564CBAD15D2D18F7444594F2283.pub.asc create mode 100644 tests/data/2D35731B9C754564CBAD15D2D18F7444594F2283.sec.asc create mode 100644 tests/data/3E45175EE953EBBEB948F11A6A03DB2A17FB9D15.pub.asc create mode 100644 tests/data/3E45175EE953EBBEB948F11A6A03DB2A17FB9D15.sec.asc create mode 100644 tests/data/6A9835699EF1215F1558A496D9C1D4B0984094E5.pub.asc create mode 100644 tests/data/6A9835699EF1215F1558A496D9C1D4B0984094E5.sec.asc delete mode 100644 tests/data/README.md delete mode 100644 tests/data/alice@openpgp.example.pub.asc delete mode 100644 tests/data/alice@openpgp.example.sec.asc delete mode 100644 tests/data/bob@openpgp.example.pub.asc delete mode 100644 tests/data/bob@openpgp.example.sec.asc create mode 100644 tests/model.py create mode 100644 tests/test_basic.py create mode 100644 tests/utils.py diff --git a/pyproject.toml b/pyproject.toml index d624b05..15e3cb3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [tool.pytest.ini_options] minversion = "6.0" -addopts = "-sv --forked" +addopts = "-rP --forked" testpaths = [ "tests", ] diff --git a/tests/conftest.py b/tests/conftest.py index 0c78e12..d687614 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,43 +1,7 @@ # -*- coding: utf-8 -*- """pytest configuration for the unit tests.""" -import os -import pytest - -from . import constants - -# Static Data -@pytest.fixture() -def datadir(request): - """Get, read, open test files from the tests "data" directory.""" - class D: - def __init__(self, basepath): - self.basepath = basepath - - def open(self, name, mode="r"): - return self.basepath.join(name).open(mode) - - def join(self, name): - return self.basepath.join(name).strpath - - def read(self, name): - with self.open(name, "r") as f: - return f.read() - - def readlines(self, name): - with self.open(name, "r") as f: - return f.readlines() - return D(request.fspath.dirpath("data")) - -@pytest.fixture() -def alice_key_sec(datadir): - key_data = datadir.read('alice@openpgp.example.sec.asc') - return key_data - -@pytest.fixture() -def bob_key_pub(datadir): - key_data = datadir.read('bob@openpgp.example.pub.asc') - return key_data +from .model import * # Init @pytest.fixture() @@ -50,32 +14,48 @@ def env_init(tmpdir_factory, request): os.environ["PEP_HOME"] = str(bn) os.environ["HOME"] = str(bn) + @pytest.fixture() def pEp(env_init): import pEp return pEp -# Identities + +@pytest.fixture() +def alice_myself(pEp, model): + alice = pEp.Identity( + model.alice.addr, + model.alice.name, + model.alice.user_id + ) + pEp.myself(alice) + return alice + + @pytest.fixture() -def import_ident_alice(pEp, alice_key_sec): - pEp.import_key(alice_key_sec) +def alice_imported(pEp, model): + pEp.import_key(model.alice.key_sec) alice = pEp.Identity( - constants.ALICE_ADDRESS, constants.ALICE_NAME, - constants.ALICE_NAME_ADDR, constants.ALICE_FPR, 0, '' + model.alice.addr, + model.alice.name, + model.alice.user_id ) return alice + @pytest.fixture() -def import_ident_alice_as_own_ident(pEp, import_ident_alice): - alice = import_ident_alice - pEp.set_own_key(alice, constants.ALICE_FPR) +def import_ident_alice_as_own_ident(pEp, model, alice_imported): + alice = alice_imported + pEp.set_own_key(alice, model.alice.fpr) return alice + @pytest.fixture() -def import_ident_bob(pEp, bob_key_pub): - pEp.import_key(bob_key_pub) +def import_ident_bob(pEp, model): + pEp.import_key(model.bob.key_pub) bob = pEp.Identity( - constants.BOB_ADDRESS, constants.BOB_NAME, '', - constants.BOB_FPR, 56, '' + model.bob.addr, + model.bob.name, ) + bob.update() return bob diff --git a/tests/constants.py b/tests/constants.py index 15ce0c9..77f6157 100644 --- a/tests/constants.py +++ b/tests/constants.py @@ -1,25 +1,9 @@ # -*- coding: utf-8 -*- """Constants for unit tests.""" +DATADIR = "data" - -# XXX: Create these first constants as part of the adapter OUTGOING_MSG = 1 INCOMING_MSG = 2 -ANGLE_ADDR = "<{}>" -NAME_ADDR = "{} {}" - -ALICE_USERNAME = "Alice Lovelace" -ALICE_ADDRESS = "alice@openpgp.example" -ALICE_ID = 23 -ALICE_FPR = "EB85BB5FA33A75E15E944E63F231550C4F47E38E" -ALICE_NAME_ADDR = NAME_ADDR.format(ALICE_USERNAME, ANGLE_ADDR.format(ALICE_ADDRESS)) - -BOB_USERNAME = "Bob Babagge" -BOB_ADDRESS = "bob@openpgp.example" -BOB_ID = 23 -BOB_FPR = "D1A66E1A23B182C9980F788CFBFCC82A015E7330" -BOB_NAME_ADDR = NAME_ADDR.format(BOB_USERNAME, ANGLE_ADDR.format(BOB_ADDRESS)) - SUBJECT = "This is a subject" BODY = "Hi world!\n" diff --git a/tests/data/1A97F263D8319D6885F638C5AA81E1B5457A2B40.pub.asc b/tests/data/1A97F263D8319D6885F638C5AA81E1B5457A2B40.pub.asc new file mode 100644 index 0000000..945be9a --- /dev/null +++ b/tests/data/1A97F263D8319D6885F638C5AA81E1B5457A2B40.pub.asc @@ -0,0 +1,24 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: 1A97 F263 D831 9D68 85F6 38C5 AA81 E1B5 457A 2B40 +Comment: bob_work@peptest.org + +xjMEXyp4RRYJKwYBBAHaRw8BAQdAdA0qiUaazZJrnWAtqQ+V/XevsZkNHyspsD8M +jWv69i3ChAQfFgoAFQWCXyp4RQWJBaSPvQIVCgKbAQIeAQAhCRCqgeG1RXorQBYh +BBqX8mPYMZ1ohfY4xaqB4bVFeitA1j0BAONtcJp4KI4CTjVJps7udMFPRqAPDXU6 +0YJzHWXK0mspAQCA2kZ2mJKFvMiKl3mY79N08eF2QE4zOVHYQYR+GZrtAc0UYm9i +X3dvcmtAcGVwdGVzdC5vcmfChAQTFgoAFQWCXyp4RQWJBaSPvQIVCgKbAQIeAQAh +CRCqgeG1RXorQBYhBBqX8mPYMZ1ohfY4xaqB4bVFeitA0NsA/i+jZZ8jVJVjTN9d +OPlCSg2rgMoW4CMudbvCeJ05HBGgAQDfpHv0mceDpw0Xb7JvSCZGpcnx7JvnrijO +o7s0km1fB84zBF8qeEUWCSsGAQQB2kcPAQEHQCqxykiuw5mJk7ulNeeS9ZRmNMh+ +A5Za3/Mqwr8neCElwsA7BBgWCgAVBYJfKnhFBYkFpI+9AhUKApsCAh4BAJgJEKqB +4bVFeitAdqAEGRYKAAYFgl8qeEUAIQkQZIW7NIu2E2oWIQQjjCvzjFveMgb5MvZk +hbs0i7YTav2zAQCDuIDQu3vO31HUiGvSc2/ZYRKUAHJsVfnCovZSFiBaHwD+MNgr +QYydV0jkx2hyaQV7GGml132sKCVmHW6t+8+B8AYWIQQal/Jj2DGdaIX2OMWqgeG1 +RXorQI6IAP0RuRRGJV8zg9ax3HSpBYsqQCTjq/Kswiskrzlda77RrwD9EnohAaPF +0yd5MrZ0H01+RJseLhF20mznjYX4ucKckQrOOARfKnhFEgorBgEEAZdVAQUBAQdA +/QOYQ28riHwdqlzL1SS89+sK52RUSGJ+z2jMEGZXrg4DAQgJwoQEGBYKABUFgl8q +eEUFiQWkj70CCwkCmwwCHgEAIQkQqoHhtUV6K0AWIQQal/Jj2DGdaIX2OMWqgeG1 +RXorQAI/AQCVdZqaCPSHI8KQ75SmjCHOrizFJ5OvRQIxLcgFYnbf4QD/RK8/na7X +t3H5zFD9yjCeNtTKuBubz8wnlV48V6F8NQk= +=71Mh +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/data/1A97F263D8319D6885F638C5AA81E1B5457A2B40.sec.asc b/tests/data/1A97F263D8319D6885F638C5AA81E1B5457A2B40.sec.asc new file mode 100644 index 0000000..5fea9ad --- /dev/null +++ b/tests/data/1A97F263D8319D6885F638C5AA81E1B5457A2B40.sec.asc @@ -0,0 +1,26 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- +Comment: 1A97 F263 D831 9D68 85F6 38C5 AA81 E1B5 457A 2B40 +Comment: bob_work@peptest.org + +xVgEXyp4RRYJKwYBBAHaRw8BAQdAdA0qiUaazZJrnWAtqQ+V/XevsZkNHyspsD8M +jWv69i0AAP9vlqqd0FjnC219hFfUH3NWDyNkE+qLncgL8iauLJJW2xApwoQEHxYK +ABUFgl8qeEUFiQWkj70CFQoCmwECHgEAIQkQqoHhtUV6K0AWIQQal/Jj2DGdaIX2 +OMWqgeG1RXorQNY9AQDjbXCaeCiOAk41SabO7nTBT0agDw11OtGCcx1lytJrKQEA +gNpGdpiShbzIipd5mO/TdPHhdkBOMzlR2EGEfhma7QHNFGJvYl93b3JrQHBlcHRl +c3Qub3JnwoQEExYKABUFgl8qeEUFiQWkj70CFQoCmwECHgEAIQkQqoHhtUV6K0AW +IQQal/Jj2DGdaIX2OMWqgeG1RXorQNDbAP4vo2WfI1SVY0zfXTj5QkoNq4DKFuAj +LnW7wnidORwRoAEA36R79JnHg6cNF2+yb0gmRqXJ8eyb564ozqO7NJJtXwfHWARf +KnhFFgkrBgEEAdpHDwEBB0AqscpIrsOZiZO7pTXnkvWUZjTIfgOWWt/zKsK/J3gh +JQABAJW6BesKSs2CgM+fx+SKkv+di6b1aTLirOmVdfbse0R9E5TCwDsEGBYKABUF +gl8qeEUFiQWkj70CFQoCmwICHgEAmAkQqoHhtUV6K0B2oAQZFgoABgWCXyp4RQAh +CRBkhbs0i7YTahYhBCOMK/OMW94yBvky9mSFuzSLthNq/bMBAIO4gNC7e87fUdSI +a9Jzb9lhEpQAcmxV+cKi9lIWIFofAP4w2CtBjJ1XSOTHaHJpBXsYaaXXfawoJWYd +bq37z4HwBhYhBBqX8mPYMZ1ohfY4xaqB4bVFeitAjogA/RG5FEYlXzOD1rHcdKkF +iypAJOOr8qzCKySvOV1rvtGvAP0SeiEBo8XTJ3kytnQfTX5Emx4uEXbSbOeNhfi5 +wpyRCsddBF8qeEUSCisGAQQBl1UBBQEBB0D9A5hDbyuIfB2qXMvVJLz36wrnZFRI +Yn7PaMwQZleuDgMBCAkAAP99a9Hrl/wNGP8ohfOaTkMYE9zuBEo8FHsCpLT+/Yz9 +8BIBwoQEGBYKABUFgl8qeEUFiQWkj70CCwkCmwwCHgEAIQkQqoHhtUV6K0AWIQQa +l/Jj2DGdaIX2OMWqgeG1RXorQAI/AQCVdZqaCPSHI8KQ75SmjCHOrizFJ5OvRQIx +LcgFYnbf4QD/RK8/na7Xt3H5zFD9yjCeNtTKuBubz8wnlV48V6F8NQk= +=Yzdu +-----END PGP PRIVATE KEY BLOCK----- diff --git a/tests/data/2D35731B9C754564CBAD15D2D18F7444594F2283.pub.asc b/tests/data/2D35731B9C754564CBAD15D2D18F7444594F2283.pub.asc new file mode 100644 index 0000000..229ab9b --- /dev/null +++ b/tests/data/2D35731B9C754564CBAD15D2D18F7444594F2283.pub.asc @@ -0,0 +1,24 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: 2D35 731B 9C75 4564 CBAD 15D2 D18F 7444 594F 2283 +Comment: alice@peptest.org + +xjMEXxFT2hYJKwYBBAHaRw8BAQdA/q3RICIqQ4FHd6RfqP6QY1gd2trvJn0DBg/1 +jIfdpKfChAQfFgoAFQWCXxFT2gWJBaSPvQIVCgKbAQIeAQAhCRDRj3REWU8igxYh +BC01cxucdUVky60V0tGPdERZTyKDUnYBAMT6z+rJ6HvoAhE531BWhsSU9X0QKLC7 +UYLQ3/ZGBVAbAQC14aJX1sODCKCPK6eivyhfd8l6W69vCBpPa55TgQ3GD80RYWxp +Y2VAcGVwdGVzdC5vcmfChAQTFgoAFQWCXxFT2gWJBaSPvQIVCgKbAQIeAQAhCRDR +j3REWU8igxYhBC01cxucdUVky60V0tGPdERZTyKDQlMBAPhingJLnqAjx+DnEWdu +nPRwnhxWSgY31GRAD8LG36zlAP94BN2pRvv6sPSCSla+yUvVcYQt927MvI1B3mOI +2jnlAM4zBF8RU9oWCSsGAQQB2kcPAQEHQCxlXfe9mHyk7Z9Cd+/12i5kYm6ljyKV +Jsst1oxMj/CnwsA7BBgWCgAVBYJfEVPaBYkFpI+9AhUKApsCAh4BAJgJENGPdERZ +TyKDdqAEGRYKAAYFgl8RU9oAIQkQYvLo9HBcHrAWIQTnCIjW7qTg/Ju3h6Ni8uj0 +cFwesAy3AP4uHp91sH/DWv5Ac7jppfEXpg+CW/RoKdJ32N5S6BnWZQEAn5jtnve2 +cBx2jgUQEKkGZ6AprrrdCnPgH8AOxNOWbAYWIQQtNXMbnHVFZMutFdLRj3REWU8i +g9JRAQCHR0PJVrsyy91jLA0oAYaEyf743XlrJY8yhM3H4HKKzQEAishD4vi9cpCj +tx4EXIwoqxy2wfLbwfkGulENJS38DAbOOARfEVPaEgorBgEEAZdVAQUBAQdAo7WR +Up2ZLQbkUhTB9Aqw3Z6uKGNUUiOp7GsVu3fpAScDAQgJwoQEGBYKABUFgl8RU9oF +iQWkj70CCwkCmwwCHgEAIQkQ0Y90RFlPIoMWIQQtNXMbnHVFZMutFdLRj3REWU8i +g1QJAP9l9Xyw8j22fFUa6iKzD68SP7zLb4LbGpHdKXcBd86kigD+O0zwJp7S/Ogq +LpOoJOD6xX50+0JnlPnIxZWwhgYPrAs= +=S7O4 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/data/2D35731B9C754564CBAD15D2D18F7444594F2283.sec.asc b/tests/data/2D35731B9C754564CBAD15D2D18F7444594F2283.sec.asc new file mode 100644 index 0000000..db4c9e1 --- /dev/null +++ b/tests/data/2D35731B9C754564CBAD15D2D18F7444594F2283.sec.asc @@ -0,0 +1,26 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- +Comment: 2D35 731B 9C75 4564 CBAD 15D2 D18F 7444 594F 2283 +Comment: alice@peptest.org + +xVgEXxFT2hYJKwYBBAHaRw8BAQdA/q3RICIqQ4FHd6RfqP6QY1gd2trvJn0DBg/1 +jIfdpKcAAP0W8bWDwzy2kpwqa5gx9T/DWt4kDCoa7tGzMU+dv0FBnBCMwoQEHxYK +ABUFgl8RU9oFiQWkj70CFQoCmwECHgEAIQkQ0Y90RFlPIoMWIQQtNXMbnHVFZMut +FdLRj3REWU8ig1J2AQDE+s/qyeh76AIROd9QVobElPV9ECiwu1GC0N/2RgVQGwEA +teGiV9bDgwigjyunor8oX3fJeluvbwgaT2ueU4ENxg/NEWFsaWNlQHBlcHRlc3Qu +b3JnwoQEExYKABUFgl8RU9oFiQWkj70CFQoCmwECHgEAIQkQ0Y90RFlPIoMWIQQt +NXMbnHVFZMutFdLRj3REWU8ig0JTAQD4Yp4CS56gI8fg5xFnbpz0cJ4cVkoGN9Rk +QA/Cxt+s5QD/eATdqUb7+rD0gkpWvslL1XGELfduzLyNQd5jiNo55QDHWARfEVPa +FgkrBgEEAdpHDwEBB0AsZV33vZh8pO2fQnfv9douZGJupY8ilSbLLdaMTI/wpwAA +/RU5lcZzjrlWdEh95e12IjqpCKt1VpwQhT617pSZyYpqELbCwDsEGBYKABUFgl8R +U9oFiQWkj70CFQoCmwICHgEAmAkQ0Y90RFlPIoN2oAQZFgoABgWCXxFT2gAhCRBi +8uj0cFwesBYhBOcIiNbupOD8m7eHo2Ly6PRwXB6wDLcA/i4en3Wwf8Na/kBzuOml +8RemD4Jb9Ggp0nfY3lLoGdZlAQCfmO2e97ZwHHaOBRAQqQZnoCmuut0Kc+AfwA7E +05ZsBhYhBC01cxucdUVky60V0tGPdERZTyKD0lEBAIdHQ8lWuzLL3WMsDSgBhoTJ +/vjdeWsljzKEzcfgcorNAQCKyEPi+L1ykKO3HgRcjCirHLbB8tvB+Qa6UQ0lLfwM +BsddBF8RU9oSCisGAQQBl1UBBQEBB0CjtZFSnZktBuRSFMH0CrDdnq4oY1RSI6ns +axW7d+kBJwMBCAkAAP9kY8sKTIAbQiR7PVRDPfI49ccZmoDSjNG6nPBeT7JwEA/h +woQEGBYKABUFgl8RU9oFiQWkj70CCwkCmwwCHgEAIQkQ0Y90RFlPIoMWIQQtNXMb +nHVFZMutFdLRj3REWU8ig1QJAP9l9Xyw8j22fFUa6iKzD68SP7zLb4LbGpHdKXcB +d86kigD+O0zwJp7S/OgqLpOoJOD6xX50+0JnlPnIxZWwhgYPrAs= +=uIGP +-----END PGP PRIVATE KEY BLOCK----- diff --git a/tests/data/3E45175EE953EBBEB948F11A6A03DB2A17FB9D15.pub.asc b/tests/data/3E45175EE953EBBEB948F11A6A03DB2A17FB9D15.pub.asc new file mode 100644 index 0000000..ea98c2a --- /dev/null +++ b/tests/data/3E45175EE953EBBEB948F11A6A03DB2A17FB9D15.pub.asc @@ -0,0 +1,24 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: 3E45 175E E953 EBBE B948 F11A 6A03 DB2A 17FB 9D15 +Comment: alice_work@peptest.org + +xjMEXxFT7BYJKwYBBAHaRw8BAQdAToI/CRX5M3LjPpSCfmJtOngHTos502W02e4e +I1CyNE/ChAQfFgoAFQWCXxFT7AWJBaSPvQIVCgKbAQIeAQAhCRBqA9sqF/udFRYh +BD5FF17pU+u+uUjxGmoD2yoX+50VV9cA/1HmBlEd6SVkhAK7dP46yGQtEJLix5x+ +Z14COnk/EKETAP9Roz7sJakpqC/VejESHekpt5DterDWAXc4hjf1ADutDc0WYWxp +Y2Vfd29ya0BwZXB0ZXN0Lm9yZ8KEBBMWCgAVBYJfEVPsBYkFpI+9AhUKApsBAh4B +ACEJEGoD2yoX+50VFiEEPkUXXulT6765SPEaagPbKhf7nRVc2wD/Q7ISeG3cDbji +W+17gSnlYEYtG5EjIzGavYMr2tPhAlcA/RpuaaYkB+9FGYapXpKEZfOa9gRfg4sY +l2jIK5QNWYcDzjMEXxFT7BYJKwYBBAHaRw8BAQdAnljLgkOQD0jx8eoIbV0rUN1o +m5mux0+pLHZ6sIt+yD7CwDsEGBYKABUFgl8RU+wFiQWkj70CFQoCmwICHgEAmAkQ +agPbKhf7nRV2oAQZFgoABgWCXxFT7AAhCRBLlptQp2yWJxYhBMqF7w4SDl18JRD6 +akuWm1CnbJYnUBEBAM55LvWxQ7Mi65AJEGhRlqGzCexUDheuXgVZYbqboc2wAQDc +SUxqP5Jbq66pAWSpHBTgT1rrZW9RbsA+yOA9B6DpBxYhBD5FF17pU+u+uUjxGmoD +2yoX+50VAjgBANay4I3jqeDBCkUlxPQZr0wlcxhiZW4m6NSamTqQvsLCAPwPivrv +YXaMc4zGSAesvk0Mwo5+2eX984EiHzsW+1mUAM44BF8RU+wSCisGAQQBl1UBBQEB +B0C0Ix+Z8q+NmQ7W64bAZwf1lYbDIykmtmh4pOCu9/XGdQMBCAnChAQYFgoAFQWC +XxFT7AWJBaSPvQILCQKbDAIeAQAhCRBqA9sqF/udFRYhBD5FF17pU+u+uUjxGmoD +2yoX+50VvKMBAOHyhqD60oJJpA1G116lL7LjKjnFuJG/6tG4xfvFi2fPAQCxPM+N +Pm5OZkyuDqsmY1RkrsbPCMOer3nrCNaKWYBcCg== +=FGLu +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/data/3E45175EE953EBBEB948F11A6A03DB2A17FB9D15.sec.asc b/tests/data/3E45175EE953EBBEB948F11A6A03DB2A17FB9D15.sec.asc new file mode 100644 index 0000000..505ce3b --- /dev/null +++ b/tests/data/3E45175EE953EBBEB948F11A6A03DB2A17FB9D15.sec.asc @@ -0,0 +1,26 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- +Comment: 3E45 175E E953 EBBE B948 F11A 6A03 DB2A 17FB 9D15 +Comment: alice_work@peptest.org + +xVgEXxFT7BYJKwYBBAHaRw8BAQdAToI/CRX5M3LjPpSCfmJtOngHTos502W02e4e +I1CyNE8AAP9nsNGRiCaR0Rd9A0zQ8olYfdApaEGAtlI7Ke5AjnRGvRBMwoQEHxYK +ABUFgl8RU+wFiQWkj70CFQoCmwECHgEAIQkQagPbKhf7nRUWIQQ+RRde6VPrvrlI +8RpqA9sqF/udFVfXAP9R5gZRHeklZIQCu3T+OshkLRCS4secfmdeAjp5PxChEwD/ +UaM+7CWpKagv1XoxEh3pKbeQ7Xqw1gF3OIY39QA7rQ3NFmFsaWNlX3dvcmtAcGVw +dGVzdC5vcmfChAQTFgoAFQWCXxFT7AWJBaSPvQIVCgKbAQIeAQAhCRBqA9sqF/ud +FRYhBD5FF17pU+u+uUjxGmoD2yoX+50VXNsA/0OyEnht3A244lvte4Ep5WBGLRuR +IyMxmr2DK9rT4QJXAP0abmmmJAfvRRmGqV6ShGXzmvYEX4OLGJdoyCuUDVmHA8dY +BF8RU+wWCSsGAQQB2kcPAQEHQJ5Yy4JDkA9I8fHqCG1dK1DdaJuZrsdPqSx2erCL +fsg+AAEA9dzB32gcqp1IQ3GXFZ7gu6ay46pdfrlUNNvnyzUxW8wSOcLAOwQYFgoA +FQWCXxFT7AWJBaSPvQIVCgKbAgIeAQCYCRBqA9sqF/udFXagBBkWCgAGBYJfEVPs +ACEJEEuWm1CnbJYnFiEEyoXvDhIOXXwlEPpqS5abUKdslidQEQEAznku9bFDsyLr +kAkQaFGWobMJ7FQOF65eBVlhupuhzbABANxJTGo/klurrqkBZKkcFOBPWutlb1Fu +wD7I4D0HoOkHFiEEPkUXXulT6765SPEaagPbKhf7nRUCOAEA1rLgjeOp4MEKRSXE +9BmvTCVzGGJlbibo1JqZOpC+wsIA/A+K+u9hdoxzjMZIB6y+TQzCjn7Z5f3zgSIf +Oxb7WZQAx10EXxFT7BIKKwYBBAGXVQEFAQEHQLQjH5nyr42ZDtbrhsBnB/WVhsMj +KSa2aHik4K739cZ1AwEICQAA/2iRtG/26b2MEAaxszNxbwdaeE39GU5HvdLmnuVQ +kTwgENbChAQYFgoAFQWCXxFT7AWJBaSPvQILCQKbDAIeAQAhCRBqA9sqF/udFRYh +BD5FF17pU+u+uUjxGmoD2yoX+50VvKMBAOHyhqD60oJJpA1G116lL7LjKjnFuJG/ +6tG4xfvFi2fPAQCxPM+NPm5OZkyuDqsmY1RkrsbPCMOer3nrCNaKWYBcCg== +=Vrqy +-----END PGP PRIVATE KEY BLOCK----- diff --git a/tests/data/6A9835699EF1215F1558A496D9C1D4B0984094E5.pub.asc b/tests/data/6A9835699EF1215F1558A496D9C1D4B0984094E5.pub.asc new file mode 100644 index 0000000..8219779 --- /dev/null +++ b/tests/data/6A9835699EF1215F1558A496D9C1D4B0984094E5.pub.asc @@ -0,0 +1,24 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: 6A98 3569 9EF1 215F 1558 A496 D9C1 D4B0 9840 94E5 +Comment: bob@peptest.org + +xjMEXxFT+xYJKwYBBAHaRw8BAQdAAYt8QUG+i4GQyfwaUQL+cmGKUcWHkcWX87IC +qmNpm//ChAQfFgoAFQWCXxFT+wWJBaSPvQIVCgKbAQIeAQAhCRDZwdSwmECU5RYh +BGqYNWme8SFfFVikltnB1LCYQJTlle4A/3Xl+WA2cHvE5pYsuhxZGqwABxaOmIx8 +AMxj0TBpuObXAP9y/flFpkK15Et/wl/T7iwAn2HAbQWRaPMoX694iQGjB80PYm9i +QHBlcHRlc3Qub3JnwoQEExYKABUFgl8RU/sFiQWkj70CFQoCmwECHgEAIQkQ2cHU +sJhAlOUWIQRqmDVpnvEhXxVYpJbZwdSwmECU5cmFAQDNarwFonE0e3rmjt1eI6CK +e8VjWgMpOYRa05xPdONVsQD/cejxjE+vsMlw3xVprNbKeJeXN+ZPJjNI4LIcw1B/ +igrOMwRfEVP7FgkrBgEEAdpHDwEBB0DdURvGONC+G8dZa0Q1vFGp5WVnrtahfJ0T +PRx5LPdvC8LAOwQYFgoAFQWCXxFT+wWJBaSPvQIVCgKbAgIeAQCYCRDZwdSwmECU +5XagBBkWCgAGBYJfEVP7ACEJENwMujbE/mf1FiEEvRHaDz+iRkPLimpN3Ay6NsT+ +Z/VX8QD/eKyJ/O2yF4jaNDDjzNrEzOZg7pvqiKZolV2WMlA4msUBANdN8PkKCH5G +HPo/T3mWl+xYkOVqZuw90Ay6npS6++wJFiEEapg1aZ7xIV8VWKSW2cHUsJhAlOUQ +UwEAhWLV69mEyxA1FrixumNan7vulofahcc7ox5cfZAANbEA/jBNmTPtROEaSeuU +IPyQ0lO+DS+Gmh9FYIfa35uAaQYKzjgEXxFT+xIKKwYBBAGXVQEFAQEHQL3nDAFV +lgBfUmw5C9OEv0txcP98NUgtADUmr5p9MdswAwEICcKEBBgWCgAVBYJfEVP7BYkF +pI+9AgsJApsMAh4BACEJENnB1LCYQJTlFiEEapg1aZ7xIV8VWKSW2cHUsJhAlOWl +CQD+O3xgfil6wkuenJEEWOWRHm0ft2u50DeP3/mJiRRdefoBAOwurevk+Ky1ZGqo +gpTmsS/1vAf/fz2DLWWN61hIyOEM +=/DS+ +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/data/6A9835699EF1215F1558A496D9C1D4B0984094E5.sec.asc b/tests/data/6A9835699EF1215F1558A496D9C1D4B0984094E5.sec.asc new file mode 100644 index 0000000..916d123 --- /dev/null +++ b/tests/data/6A9835699EF1215F1558A496D9C1D4B0984094E5.sec.asc @@ -0,0 +1,26 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- +Comment: 6A98 3569 9EF1 215F 1558 A496 D9C1 D4B0 9840 94E5 +Comment: bob@peptest.org + +xVgEXxFT+xYJKwYBBAHaRw8BAQdAAYt8QUG+i4GQyfwaUQL+cmGKUcWHkcWX87IC +qmNpm/8AAQCrGsb0A0+Vfxn13bwcs9cotQzf4f8gP4AN6oX3wiMgQxB1woQEHxYK +ABUFgl8RU/sFiQWkj70CFQoCmwECHgEAIQkQ2cHUsJhAlOUWIQRqmDVpnvEhXxVY +pJbZwdSwmECU5ZXuAP915flgNnB7xOaWLLocWRqsAAcWjpiMfADMY9Ewabjm1wD/ +cv35RaZCteRLf8Jf0+4sAJ9hwG0FkWjzKF+veIkBowfND2JvYkBwZXB0ZXN0Lm9y +Z8KEBBMWCgAVBYJfEVP7BYkFpI+9AhUKApsBAh4BACEJENnB1LCYQJTlFiEEapg1 +aZ7xIV8VWKSW2cHUsJhAlOXJhQEAzWq8BaJxNHt65o7dXiOginvFY1oDKTmEWtOc +T3TjVbEA/3Ho8YxPr7DJcN8VaazWyniXlzfmTyYzSOCyHMNQf4oKx1gEXxFT+xYJ +KwYBBAHaRw8BAQdA3VEbxjjQvhvHWWtENbxRqeVlZ67WoXydEz0ceSz3bwsAAPsF +YmCVyg8ega1rLrOGVRhphlUGpGwiAvUd8C56L/ZGlg3kwsA7BBgWCgAVBYJfEVP7 +BYkFpI+9AhUKApsCAh4BAJgJENnB1LCYQJTldqAEGRYKAAYFgl8RU/sAIQkQ3Ay6 +NsT+Z/UWIQS9EdoPP6JGQ8uKak3cDLo2xP5n9VfxAP94rIn87bIXiNo0MOPM2sTM +5mDum+qIpmiVXZYyUDiaxQEA103w+QoIfkYc+j9PeZaX7FiQ5Wpm7D3QDLqelLr7 +7AkWIQRqmDVpnvEhXxVYpJbZwdSwmECU5RBTAQCFYtXr2YTLEDUWuLG6Y1qfu+6W +h9qFxzujHlx9kAA1sQD+ME2ZM+1E4RpJ65Qg/JDSU74NL4aaH0Vgh9rfm4BpBgrH +XQRfEVP7EgorBgEEAZdVAQUBAQdAvecMAVWWAF9SbDkL04S/S3Fw/3w1SC0ANSav +mn0x2zADAQgJAAD/cLLc4Gss5eq6v0PO/sCLyyA69hsz5FAyDFX7F3nMBygRzMKE +BBgWCgAVBYJfEVP7BYkFpI+9AgsJApsMAh4BACEJENnB1LCYQJTlFiEEapg1aZ7x +IV8VWKSW2cHUsJhAlOWlCQD+O3xgfil6wkuenJEEWOWRHm0ft2u50DeP3/mJiRRd +efoBAOwurevk+Ky1ZGqogpTmsS/1vAf/fz2DLWWN61hIyOEM +=4nOw +-----END PGP PRIVATE KEY BLOCK----- diff --git a/tests/data/README.md b/tests/data/README.md deleted file mode 100644 index 0fcfd74..0000000 --- a/tests/data/README.md +++ /dev/null @@ -1,2 +0,0 @@ -The data in this directory comes from: -https://datatracker.ietf.org/doc/draft-bre-openpgp-samples/ diff --git a/tests/data/alice@openpgp.example.pub.asc b/tests/data/alice@openpgp.example.pub.asc deleted file mode 100644 index 2410510..0000000 --- a/tests/data/alice@openpgp.example.pub.asc +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Comment: Alice's OpenPGP certificate - -mDMEXEcE6RYJKwYBBAHaRw8BAQdArjWwk3FAqyiFbFBKT4TzXcVBqPTB3gmzlC/U -b7O1u120JkFsaWNlIExvdmVsYWNlIDxhbGljZUBvcGVucGdwLmV4YW1wbGU+iJAE -ExYIADgCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AWIQTrhbtfozp14V6UTmPy -MVUMT0fjjgUCXaWfOgAKCRDyMVUMT0fjjukrAPoDnHBSogOmsHOsd9qGsiZpgRnO -dypvbm+QtXZqth9rvwD9HcDC0tC+PHAsO7OTh1S1TC9RiJsvawAfCPaQZoed8gK4 -OARcRwTpEgorBgEEAZdVAQUBAQdAQv8GIa2rSTzgqbXCpDDYMiKRVitCsy203x3s -E9+eviIDAQgHiHgEGBYIACAWIQTrhbtfozp14V6UTmPyMVUMT0fjjgUCXEcE6QIb -DAAKCRDyMVUMT0fjjlnQAQDFHUs6TIcxrNTtEZFjUFm1M0PJ1Dng/cDW4xN80fsn -0QEA22Kr7VkCjeAEC08VSTeV+QFsmz55/lntWkwYWhmvOgE= -=iIGO ------END PGP PUBLIC KEY BLOCK----- diff --git a/tests/data/alice@openpgp.example.sec.asc b/tests/data/alice@openpgp.example.sec.asc deleted file mode 100644 index af11bec..0000000 --- a/tests/data/alice@openpgp.example.sec.asc +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN PGP PRIVATE KEY BLOCK----- -Comment: Alice's OpenPGP Transferable Secret Key - -lFgEXEcE6RYJKwYBBAHaRw8BAQdArjWwk3FAqyiFbFBKT4TzXcVBqPTB3gmzlC/U -b7O1u10AAP9XBeW6lzGOLx7zHH9AsUDUTb2pggYGMzd0P3ulJ2AfvQ4RtCZBbGlj -ZSBMb3ZlbGFjZSA8YWxpY2VAb3BlbnBncC5leGFtcGxlPoiQBBMWCAA4AhsDBQsJ -CAcCBhUKCQgLAgQWAgMBAh4BAheAFiEE64W7X6M6deFelE5j8jFVDE9H444FAl2l -nzoACgkQ8jFVDE9H447pKwD6A5xwUqIDprBzrHfahrImaYEZzncqb25vkLV2arYf -a78A/R3AwtLQvjxwLDuzk4dUtUwvUYibL2sAHwj2kGaHnfICnF0EXEcE6RIKKwYB -BAGXVQEFAQEHQEL/BiGtq0k84Km1wqQw2DIikVYrQrMttN8d7BPfnr4iAwEIBwAA -/3/xFPG6U17rhTuq+07gmEvaFYKfxRB6sgAYiW6TMTpQEK6IeAQYFggAIBYhBOuF -u1+jOnXhXpROY/IxVQxPR+OOBQJcRwTpAhsMAAoJEPIxVQxPR+OOWdABAMUdSzpM -hzGs1O0RkWNQWbUzQ8nUOeD9wNbjE3zR+yfRAQDbYqvtWQKN4AQLTxVJN5X5AWyb -Pnn+We1aTBhaGa86AQ== -=n8OM ------END PGP PRIVATE KEY BLOCK----- diff --git a/tests/data/bob@openpgp.example.pub.asc b/tests/data/bob@openpgp.example.pub.asc deleted file mode 100644 index b58b8c3..0000000 --- a/tests/data/bob@openpgp.example.pub.asc +++ /dev/null @@ -1,42 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Comment: Bob's OpenPGP certificate - -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 -NEJd3XZRzaXZE2aAMQ== -=NXei ------END PGP PUBLIC KEY BLOCK----- diff --git a/tests/data/bob@openpgp.example.sec.asc b/tests/data/bob@openpgp.example.sec.asc deleted file mode 100644 index 59e981b..0000000 --- a/tests/data/bob@openpgp.example.sec.asc +++ /dev/null @@ -1,82 +0,0 @@ ------BEGIN PGP PRIVATE KEY BLOCK----- -Comment: Bob's OpenPGP Transferable Secret Key - -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 -=miES ------END PGP PRIVATE KEY BLOCK----- diff --git a/tests/model.py b/tests/model.py new file mode 100644 index 0000000..d2d9aa3 --- /dev/null +++ b/tests/model.py @@ -0,0 +1,125 @@ +from . import utils + +import pytest + +@pytest.fixture() +def model(): + "Returns the whole data model" + return Model() + +identities = \ + { + "alice": { + "name": "alice", + "user_id": "23", + "accounts": + { + "work": { + "addr": "alice_work@peptest.org", + "fpr": "3E45175EE953EBBEB948F11A6A03DB2A17FB9D15" + }, + "home": { + "addr": "alice@peptest.org", + "fpr": "2D35731B9C754564CBAD15D2D18F7444594F2283" + } + } + }, + "bob": { + "name": "bob", + "user_id": "uuid:1-2-3-4", + "accounts": \ + { + "work": { + "addr": "bob_work@peptest.org", + "fpr": "1A97F263D8319D6885F638C5AA81E1B5457A2B40" + }, + "home": { + "addr": "bob@peptest.org", + "fpr": "6A9835699EF1215F1558A496D9C1D4B0984094E5" + } + } + } + } + +# An Identity class that is read-only (const) +class Identity: + __name = "" + __user_id = "" + __addr = "" + __fpr = "" + __key_sec = "" + __key_pub = "" + + def __init__(self, name="", user_id="", addr="", fpr="", key_sec="", key_pub=""): + self.__name = name + self.__user_id = user_id + self.__addr = addr + self.__fpr = fpr + self.__key_sec = key_sec + self.__key_pub = key_pub + + def get_name(self): + return self.__name + + def get_user_id(self): + return self.__user_id + + def get_addr(self): + return self.__addr + + def get_fpr(self): + return self.__fpr + + def get_key_sec(self): + return self.__key_sec + + def get_key_pub(self): + return self.__key_pub + + name = property(get_name) + user_id = property(get_user_id) + addr = property(get_addr) + fpr = property(get_fpr) + key_sec = property(get_key_sec) + key_pub = property(get_key_pub) + + def debug(self) -> str: + ret = "name:" + self.__name + ret +="user_id:" + self.__user_id + ret +="addr:" + self.__addr + ret +="fpr:" + self.__fpr + ret +="key_sec:" + self.__key_sec[0:255] + ret +="key_pub:" + self.__key_pub[0:255] + return ret + + def __str__(self): + return "{} {}".format(self.name, "<{}>".format(self.addr)) + + + +# The Data Model +class Model: + alice = None + alice_work = None + bob = None + bob_work = None + + def getIdentity(self, name, account) -> Identity: + # fetch keys for ident from data folder + key_sec = utils.data_file_contents(identities[name]['accounts'][account]['fpr'] + ".sec.asc") + key_pub = utils.data_file_contents(identities[name]['accounts'][account]['fpr'] + ".pub.asc") + ident = Identity(name=identities[name]['name'], + user_id=identities[name]['user_id'], + addr=identities[name]['accounts'][account]['addr'], + fpr=identities[name]['accounts'][account]['fpr'], + key_pub=key_pub, + key_sec=key_sec + ) + return ident + + def __init__(self): + self.alice = self.getIdentity("alice", "home") + self.alice_work = self.getIdentity("alice", "work") + + self.bob = self.getIdentity("bob", "home") + self.bob_work = self.getIdentity("bob", "work") diff --git a/tests/test_basic.py b/tests/test_basic.py new file mode 100644 index 0000000..dca161b --- /dev/null +++ b/tests/test_basic.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# from . import constants +import pytest + + +# @pytest.mark.skip() +# def test_basic(): +# import pEp +# me = pEp.Identity("alice.smith@peptest.ch", "Alice Smith", "23") +# me.username +# 'Alice Smith' +# print(me) +# Alice Smith +# you = pEp.Identity("bob.bourne@peptest.ch", "Bob Bourne", "42") +# print(you) +# Bob Bourne +# m = pEp.outgoing_message(me) +# m.to = [you] +# m.shortmsg = "let's meet next week" +# m.longmsg = "Please call me back" +# m2 = m.encrypt() +# print(m2) +# m3, keys, rating, flags = m2.decrypt() +# assert(rating == pEp.rating.reliable) + + diff --git a/tests/test_identity.py b/tests/test_identity.py index f3161da..3e044ff 100644 --- a/tests/test_identity.py +++ b/tests/test_identity.py @@ -1,68 +1,58 @@ # -*- coding: utf-8 -*- """Identity unit tests.""" -import os + +import pytest from . import constants +from . import model -def test_create_one_identity_succeed(pEp): - # It has to be imported here to get the management db initialized, - alice = pEp.Identity() - alice.address = constants.ALICE_ADDRESS - alice.username = constants.ALICE_NAME - alice.fpr = constants.ALICE_FPR +# TODO: test_get_identity_by_{name,addr,etc..} +# def test_create_ident_myself(pEp, alice_myself): +# def test_create_ident_import(pEp, alice_myself): +# def test_create_ident_nokey(pEp, alice_myself): - expected_alice = pEp.Identity( - constants.ALICE_ADDRESS, constants.ALICE_NAME, '', - constants.ALICE_FPR, 0, '' + +def test_identity_constructor(pEp, model): + alice = pEp.Identity( + model.alice.addr, + model.alice.name, + model.alice.user_id ) - # XXX: Can't compare objects - # assert alice == expected_alice - assert str(alice) == constants.ALICE_NAME_ADDR - assert alice.address == expected_alice.address - assert alice.username == expected_alice.username - # Cause the key is created by pEp - assert alice.fpr == expected_alice.fpr - assert alice.user_id == expected_alice.user_id - assert alice.comm_type == expected_alice.comm_type - assert alice.flags == expected_alice.flags + assert alice.address == model.alice.addr + assert alice.username == model.alice.name + assert alice.user_id == model.alice.user_id + assert str(alice) == str(model.alice) - # Test that data after updating. - # If the db has not been initialized this would return PEP_GET_KEY_FAILED - alice.update() - assert str(alice) == constants.ALICE_NAME_ADDR - assert alice.address == expected_alice.address - assert alice.username == expected_alice.username - # XXX: shouldn't this be he fpr of the key generated by pEp? - assert alice.fpr == '' - # After updating this changed - assert alice.user_id == "TOFU_alice@openpgp.example" - # After updating this changed - assert alice.comm_type == 3 - assert alice.flags == expected_alice.flags +# TODO: +# These here are actually plenty of individual tests +# Identity.update +# key_import +# set_own_key -def test_two_identities_succeed(pEp, bob_key_pub): +@pytest.mark.skip(reason="needs to be decomposed and migrated to new data model") +def test_two_identities_succeed(pEp, model): alice = pEp.Identity( - constants.ALICE_ADDRESS, constants.ALICE_NAME, '', + constants.ALICE_ADDRESS, constants.ALICE_USERNAME, '', constants.ALICE_FPR, 0, '' ) assert alice.address == constants.ALICE_ADDRESS - assert alice.username == constants.ALICE_NAME + assert alice.username == constants.ALICE_USERNAME assert alice.fpr == constants.ALICE_FPR assert alice.user_id == "" assert alice.comm_type == 0 assert alice.flags == 0 - pEp.import_key(bob_key_pub) + pEp.import_key(model.bob.key_pub) bob = pEp.Identity() bob.address = constants.BOB_ADDRESS - bob.username = constants.BOB_NAME + bob.username = constants.BOB_USERNAME bob.fpr = constants.BOB_FPR expected_bob = pEp.Identity( - constants.BOB_ADDRESS, constants.BOB_NAME, '', + constants.BOB_ADDRESS, constants.BOB_USERNAME, '', constants.BOB_FPR, 56, '' ) @@ -85,16 +75,17 @@ def test_two_identities_succeed(pEp, bob_key_pub): assert bob.flags == 0 +@pytest.mark.skip(reason="needs to be decomposed and migrated to new data model") def test_set_own_key(pEp, alice_key_sec): pEp.import_key(alice_key_sec) alice = pEp.Identity() alice.address = constants.ALICE_ADDRESS - alice.username = constants.ALICE_NAME + alice.username = constants.ALICE_USERNAME alice.fpr = constants.ALICE_FPR alice.user_id = constants.ALICE_NAME_ADDR expected_alice = pEp.Identity( - constants.ALICE_ADDRESS, constants.ALICE_NAME, '', + constants.ALICE_ADDRESS, constants.ALICE_USERNAME, '', constants.ALICE_FPR, 0, '' ) diff --git a/tests/test_message.py b/tests/test_message.py index 0d5c810..e527206 100644 --- a/tests/test_message.py +++ b/tests/test_message.py @@ -4,7 +4,7 @@ from . import constants -def test_msg_enc_dec_roundtrip(pEp, import_ident_alice_as_own_ident, import_ident_bob): +def test_msg_enc_dec_roundtrip(pEp, model, import_ident_alice_as_own_ident, import_ident_bob): alice = import_ident_alice_as_own_ident bob = import_ident_bob @@ -26,8 +26,8 @@ def test_msg_enc_dec_roundtrip(pEp, import_ident_alice_as_own_ident, import_iden enc_msg = msg.encrypt() assert enc_msg.enc_format == 3 - assert str(enc_msg.from_) == constants.ALICE_NAME_ADDR - assert str(enc_msg.to[0]) == constants.BOB_NAME_ADDR + assert str(enc_msg.from_) == str(model.alice) + assert str(enc_msg.to[0]) == str(model.bob) assert enc_msg.shortmsg == "p≡p" assert enc_msg.longmsg == "this message was encrypted with p≡p https://pEp-project.org" @@ -41,8 +41,8 @@ def test_msg_enc_dec_roundtrip(pEp, import_ident_alice_as_own_ident, import_iden assert rating == pEp._pEp.rating.reliable # The first 2 keys are Alice's ones, the last is Bob's one. - assert key_list[0] == key_list[1] == constants.ALICE_FPR - assert key_list[-1] == constants.BOB_FPR + assert key_list[0] == key_list[1] == model.alice.fpr + assert key_list[-1] == model.bob.fpr assert dec_msg.shortmsg == constants.SUBJECT assert dec_msg.longmsg.replace("\r", "") == msg.longmsg dec_lines = str(dec_msg).replace("\r", "").split("\n") @@ -53,13 +53,13 @@ def test_msg_enc_dec_roundtrip(pEp, import_ident_alice_as_own_ident, import_iden # Content-Disposition: is not present anymore. # `!` is not replaced by `=21` anymore. expected_dec_lines = \ -"""From: Alice Lovelace -To: Bob Babagge +"""From: alice +To: bob Subject: This is a subject X-pEp-Version: 2.1 X-EncStatus: reliable X-KeyList: - X,X,D1A66E1A23B182C9980F788CFBFCC82A015E7330 + X,X,6A9835699EF1215F1558A496D9C1D4B0984094E5 MIME-Version: 1.0 Content-Type: text/plain Content-Transfer-Encoding: 7bit @@ -125,13 +125,13 @@ def test_dec_msg_len(pEp, import_ident_alice_as_own_ident, import_ident_bob): assert dec_msg.longmsg.replace("\r", "") == constants.BODY # msg.longmsg expected_dec_msg = \ -"""From: Alice Lovelace \r -To: Bob Babagge \r +"""From: alice \r +To: bob \r Subject: This is a subject\r X-pEp-Version: 2.1\r X-EncStatus: reliable\r X-KeyList: \r - EB85BB5FA33A75E15E944E63F231550C4F47E38E,EB85BB5FA33A75E15E944E63F231550C4F47E38E,D1A66E1A23B182C9980F788CFBFCC82A015E7330\r + 2D35731B9C754564CBAD15D2D18F7444594F2283,2D35731B9C754564CBAD15D2D18F7444594F2283,6A9835699EF1215F1558A496D9C1D4B0984094E5\r MIME-Version: 1.0\r Content-Type: text/plain\r Content-Transfer-Encoding: 7bit\r @@ -148,9 +148,9 @@ Hi world!\r print("len_extra_headers", len_extra_headers) assert dec_msg_len - len_extra_headers == msg_len - +#@pytest.mark.skip(reason="PYADAPT-91") def test_null_char_rmed(pEp, import_ident_alice_as_own_ident, import_ident_bob): - """Test that null characters and anything after them is removed.""" + """Test that null characters and anything after them are not removed.""" alice = import_ident_alice_as_own_ident bob = import_ident_bob diff --git a/tests/utils.py b/tests/utils.py new file mode 100644 index 0000000..008978b --- /dev/null +++ b/tests/utils.py @@ -0,0 +1,9 @@ +from . import constants + +import pathlib + +def data_file_contents(name) -> str: + """grab the contents of a file in the data folder""" + path = pathlib.Path(__file__).parent / constants.DATADIR / name + with path.open(mode='r') as fid: + return fid.read() From 9a3fb3918d5f5d8b08c2d86905f0542093ad0fa5 Mon Sep 17 00:00:00 2001 From: heck Date: Fri, 13 Nov 2020 02:49:56 +0100 Subject: [PATCH 73/84] authors roles --- AUTHORS.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/AUTHORS.txt b/AUTHORS.txt index 40ce2c3..efddf90 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -3,7 +3,7 @@ # 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 -Heck -Hartmut Goebel -juga +Volker Birk (original author and maintainer) +Heck (current maintainer and author) +Hartmut Goebel (contributions) +juga (contributions) From a03295b495b9763a990ce3ed1c0c0961326fa1f4 Mon Sep 17 00:00:00 2001 From: heck Date: Fri, 13 Nov 2020 02:54:45 +0100 Subject: [PATCH 74/84] AGPL 3.0 headers --- tests/__init__.py | 2 ++ tests/conftest.py | 3 +++ tests/constants.py | 3 +++ tests/model.py | 6 +++++- tests/test_basic.py | 3 ++- tests/test_identity.py | 3 +++ tests/test_message.py | 3 +++ tests/test_pep.py | 3 +++ tests/utils.py | 6 +++++- utils/pEp | 2 ++ 10 files changed, 31 insertions(+), 3 deletions(-) diff --git a/tests/__init__.py b/tests/__init__.py index 40a96af..7934bb2 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1 +1,3 @@ # -*- coding: utf-8 -*- +# This file is under GNU Affero General Public License 3.0 +# see LICENSE.txt diff --git a/tests/conftest.py b/tests/conftest.py index d687614..71bd834 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,7 @@ # -*- coding: utf-8 -*- +# This file is under GNU Affero General Public License 3.0 +# see LICENSE.txt + """pytest configuration for the unit tests.""" from .model import * diff --git a/tests/constants.py b/tests/constants.py index 77f6157..a141ea6 100644 --- a/tests/constants.py +++ b/tests/constants.py @@ -1,4 +1,7 @@ # -*- coding: utf-8 -*- +# This file is under GNU Affero General Public License 3.0 +# see LICENSE.txt + """Constants for unit tests.""" DATADIR = "data" diff --git a/tests/model.py b/tests/model.py index d2d9aa3..28bf5a2 100644 --- a/tests/model.py +++ b/tests/model.py @@ -1,4 +1,8 @@ -from . import utils +# -*- coding: utf-8 -*- +# This file is under GNU Affero General Public License 3.0 +# see LICENSE.txt + +# from . import utils import pytest diff --git a/tests/test_basic.py b/tests/test_basic.py index dca161b..3b1cacf 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -1,5 +1,6 @@ -#!/usr/bin/env python3 # -*- coding: utf-8 -*- +# This file is under GNU Affero General Public License 3.0 +# see LICENSE.txt # from . import constants import pytest diff --git a/tests/test_identity.py b/tests/test_identity.py index 3e044ff..62125b6 100644 --- a/tests/test_identity.py +++ b/tests/test_identity.py @@ -1,4 +1,7 @@ # -*- coding: utf-8 -*- +# This file is under GNU Affero General Public License 3.0 +# see LICENSE.txt + """Identity unit tests.""" import pytest diff --git a/tests/test_message.py b/tests/test_message.py index e527206..58b99f2 100644 --- a/tests/test_message.py +++ b/tests/test_message.py @@ -1,4 +1,7 @@ # -*- coding: utf-8 -*- +# This file is under GNU Affero General Public License 3.0 +# see LICENSE.txt + """Message unit tests.""" from . import constants diff --git a/tests/test_pep.py b/tests/test_pep.py index 976c74f..75a5222 100755 --- a/tests/test_pep.py +++ b/tests/test_pep.py @@ -1,4 +1,7 @@ # -*- coding: utf-8 -*- +# This file is under GNU Affero General Public License 3.0 +# see LICENSE.txt + """Unit test for pEp package, not for subpackages or modules.""" diff --git a/tests/utils.py b/tests/utils.py index 008978b..931ead0 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,4 +1,8 @@ -from . import constants +# -*- coding: utf-8 -*- +# This file is under GNU Affero General Public License 3.0 +# see LICENSE.txt + +# from . import constants import pathlib diff --git a/utils/pEp b/utils/pEp index 086eff0..1710163 100755 --- a/utils/pEp +++ b/utils/pEp @@ -1,5 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +# This file is under GNU Affero General Public License 3.0 +# see LICENSE.txt """ From 8b202b6bf7f695b3785600ab40402fa21a87473b Mon Sep 17 00:00:00 2001 From: heck Date: Fri, 13 Nov 2020 13:56:23 +0100 Subject: [PATCH 75/84] basic_doctest.py: rewrite as pytest --- test/basic_doctest.py | 73 +++++++++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/test/basic_doctest.py b/test/basic_doctest.py index 2207bed..9ac1055 100755 --- a/test/basic_doctest.py +++ b/test/basic_doctest.py @@ -1,27 +1,54 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -""" ->>> import pEp ->>> me = pEp.Identity("alice.smith@peptest.ch", "Alice Smith", "23") ->>> me.username -'Alice Smith' ->>> print(me) -Alice Smith ->>> you = pEp.Identity("bob.bourne@peptest.ch", "Bob Bourne", "42") ->>> print(you) -Bob Bourne ->>> m = pEp.outgoing_message(me) ->>> m.to = [you] ->>> m.shortmsg = "let's meet next week" ->>> m.longmsg = "Please call me back" ->>> m2 = m.encrypt() ->>> print(m2) ->>> m3, keys, rating, flags = m2.decrypt() ->>> rating -pEp.rating.reliable -""" +from . import constants +import pytest -if __name__ == "__main__": - import doctest - doctest.testmod() +# """ +# >>> import pEp +# >>> me = pEp.Identity("alice.smith@peptest.ch", "Alice Smith", "23") +# >>> me.username +# 'Alice Smith' +# >>> print(me) +# Alice Smith +# >>> you = pEp.Identity("bob.bourne@peptest.ch", "Bob Bourne", "42") +# >>> print(you) +# Bob Bourne +# >>> m = pEp.outgoing_message(me) +# >>> m.to = [you] +# >>> m.shortmsg = "let's meet next week" +# >>> m.longmsg = "Please call me back" +# >>> m2 = m.encrypt() +# >>> print(m2) +# >>> m3, keys, rating, flags = m2.decrypt() +# >>> rating +# pEp.rating.reliable +# """ +# +# if __name__ == "__main__": +# import doctest +# doctest.testmod() + +def test_basic(pEp, model): + me = pEp.Identity( + model.alice.addr, + model.alice.name, + model.alice.user_id + ) + assert me.username == model.alice.name + assert str(me) == str(model.alice) + you = pEp.Identity( + model.bob.addr, + model.bob.name, + model.bob.user_id + ) + assert str(you) == str(model.bob) + #TODO: pEp.outgoing_message() needs to return type pEp.Message not None + m = pEp.outgoing_message(me) + m.to = [you] + m.shortmsg = constants.SUBJECT + m.longmsg = constants.BODY + #TODO: encrypt needs to return message type + m2 = m.encrypt() + m3, keys, rating, flags = m2.decrypt() + assert rating == pEp._pEp.rating.reliable From dcea22558bd45abf38bfd0cd0de10f551fcc8e8f Mon Sep 17 00:00:00 2001 From: heck Date: Fri, 13 Nov 2020 13:58:15 +0100 Subject: [PATCH 76/84] basic_doctest.py: rewrite as pytest, move to pytests --- test/basic_doctest.py | 54 -------------------------------- tests/test_basic.py | 73 +++++++++++++++++++++++++++++-------------- 2 files changed, 49 insertions(+), 78 deletions(-) delete mode 100755 test/basic_doctest.py mode change 100644 => 100755 tests/test_basic.py diff --git a/test/basic_doctest.py b/test/basic_doctest.py deleted file mode 100755 index 9ac1055..0000000 --- a/test/basic_doctest.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -from . import constants -import pytest - -# """ -# >>> import pEp -# >>> me = pEp.Identity("alice.smith@peptest.ch", "Alice Smith", "23") -# >>> me.username -# 'Alice Smith' -# >>> print(me) -# Alice Smith -# >>> you = pEp.Identity("bob.bourne@peptest.ch", "Bob Bourne", "42") -# >>> print(you) -# Bob Bourne -# >>> m = pEp.outgoing_message(me) -# >>> m.to = [you] -# >>> m.shortmsg = "let's meet next week" -# >>> m.longmsg = "Please call me back" -# >>> m2 = m.encrypt() -# >>> print(m2) -# >>> m3, keys, rating, flags = m2.decrypt() -# >>> rating -# pEp.rating.reliable -# """ -# -# if __name__ == "__main__": -# import doctest -# doctest.testmod() - -def test_basic(pEp, model): - me = pEp.Identity( - model.alice.addr, - model.alice.name, - model.alice.user_id - ) - assert me.username == model.alice.name - assert str(me) == str(model.alice) - you = pEp.Identity( - model.bob.addr, - model.bob.name, - model.bob.user_id - ) - assert str(you) == str(model.bob) - #TODO: pEp.outgoing_message() needs to return type pEp.Message not None - m = pEp.outgoing_message(me) - m.to = [you] - m.shortmsg = constants.SUBJECT - m.longmsg = constants.BODY - #TODO: encrypt needs to return message type - m2 = m.encrypt() - m3, keys, rating, flags = m2.decrypt() - assert rating == pEp._pEp.rating.reliable diff --git a/tests/test_basic.py b/tests/test_basic.py old mode 100644 new mode 100755 index 3b1cacf..9ac1055 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -1,29 +1,54 @@ +#!/usr/bin/env python3 # -*- coding: utf-8 -*- -# This file is under GNU Affero General Public License 3.0 -# see LICENSE.txt -# from . import constants +from . import constants import pytest +# """ +# >>> import pEp +# >>> me = pEp.Identity("alice.smith@peptest.ch", "Alice Smith", "23") +# >>> me.username +# 'Alice Smith' +# >>> print(me) +# Alice Smith +# >>> you = pEp.Identity("bob.bourne@peptest.ch", "Bob Bourne", "42") +# >>> print(you) +# Bob Bourne +# >>> m = pEp.outgoing_message(me) +# >>> m.to = [you] +# >>> m.shortmsg = "let's meet next week" +# >>> m.longmsg = "Please call me back" +# >>> m2 = m.encrypt() +# >>> print(m2) +# >>> m3, keys, rating, flags = m2.decrypt() +# >>> rating +# pEp.rating.reliable +# """ +# +# if __name__ == "__main__": +# import doctest +# doctest.testmod() -# @pytest.mark.skip() -# def test_basic(): -# import pEp -# me = pEp.Identity("alice.smith@peptest.ch", "Alice Smith", "23") -# me.username -# 'Alice Smith' -# print(me) -# Alice Smith -# you = pEp.Identity("bob.bourne@peptest.ch", "Bob Bourne", "42") -# print(you) -# Bob Bourne -# m = pEp.outgoing_message(me) -# m.to = [you] -# m.shortmsg = "let's meet next week" -# m.longmsg = "Please call me back" -# m2 = m.encrypt() -# print(m2) -# m3, keys, rating, flags = m2.decrypt() -# assert(rating == pEp.rating.reliable) - - +def test_basic(pEp, model): + me = pEp.Identity( + model.alice.addr, + model.alice.name, + model.alice.user_id + ) + assert me.username == model.alice.name + assert str(me) == str(model.alice) + you = pEp.Identity( + model.bob.addr, + model.bob.name, + model.bob.user_id + ) + assert str(you) == str(model.bob) + #TODO: pEp.outgoing_message() needs to return type pEp.Message not None + m = pEp.outgoing_message(me) + m.to = [you] + m.shortmsg = constants.SUBJECT + m.longmsg = constants.BODY + #TODO: encrypt needs to return message type + m2 = m.encrypt() + m3, keys, rating, flags = m2.decrypt() + assert rating == pEp._pEp.rating.reliable From 94bc07aaddd7dacd8f2656815394421e448bf98d Mon Sep 17 00:00:00 2001 From: heck Date: Fri, 13 Nov 2020 13:58:39 +0100 Subject: [PATCH 77/84] fix imports --- tests/model.py | 9 +++++++-- tests/utils.py | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/model.py b/tests/model.py index 28bf5a2..4fd6f9d 100644 --- a/tests/model.py +++ b/tests/model.py @@ -2,7 +2,7 @@ # This file is under GNU Affero General Public License 3.0 # see LICENSE.txt -# from . import utils +from . import utils import pytest @@ -45,8 +45,13 @@ identities = \ } } -# An Identity class that is read-only (const) class Identity: + """ + An Identity class that is: + - can represent pEp.Identity + - is read-only (const) + """ + __name = "" __user_id = "" __addr = "" diff --git a/tests/utils.py b/tests/utils.py index 931ead0..d65fc2a 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -2,7 +2,7 @@ # This file is under GNU Affero General Public License 3.0 # see LICENSE.txt -# from . import constants +from . import constants import pathlib From a3d25c67a565421010be20b5279a8b16751f9815 Mon Sep 17 00:00:00 2001 From: heck Date: Fri, 13 Nov 2020 16:20:59 +0100 Subject: [PATCH 78/84] use decorators, its neat. --- tests/model.py | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/tests/model.py b/tests/model.py index 4fd6f9d..5724119 100644 --- a/tests/model.py +++ b/tests/model.py @@ -52,13 +52,6 @@ class Identity: - is read-only (const) """ - __name = "" - __user_id = "" - __addr = "" - __fpr = "" - __key_sec = "" - __key_pub = "" - def __init__(self, name="", user_id="", addr="", fpr="", key_sec="", key_pub=""): self.__name = name self.__user_id = user_id @@ -67,31 +60,30 @@ class Identity: self.__key_sec = key_sec self.__key_pub = key_pub - def get_name(self): + @property + def name(self): return self.__name - def get_user_id(self): + @property + def user_id(self): return self.__user_id - def get_addr(self): + @property + def addr(self): return self.__addr - def get_fpr(self): + @property + def fpr(self): return self.__fpr - def get_key_sec(self): + @property + def key_sec(self): return self.__key_sec - def get_key_pub(self): + @property + def key_pub(self): return self.__key_pub - name = property(get_name) - user_id = property(get_user_id) - addr = property(get_addr) - fpr = property(get_fpr) - key_sec = property(get_key_sec) - key_pub = property(get_key_pub) - def debug(self) -> str: ret = "name:" + self.__name ret +="user_id:" + self.__user_id From 49af7303a9ba55af8ddfa0d361086837db7ae42d Mon Sep 17 00:00:00 2001 From: heck Date: Fri, 13 Nov 2020 21:24:13 +0100 Subject: [PATCH 79/84] TODO: fix pEp.rating --- tests/test_basic.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_basic.py b/tests/test_basic.py index 9ac1055..06dc60b 100755 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -51,4 +51,5 @@ def test_basic(pEp, model): #TODO: encrypt needs to return message type m2 = m.encrypt() m3, keys, rating, flags = m2.decrypt() - assert rating == pEp._pEp.rating.reliable + #TODO: fix pEp.rating + # assert rating == pEp. From b9e1054c3c837ec6186af46cd835f9e91a1df64b Mon Sep 17 00:00:00 2001 From: heck Date: Tue, 24 Nov 2020 14:59:13 +0100 Subject: [PATCH 80/84] minor typo --- docs/source/install.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/install.rst b/docs/source/install.rst index 1fd1408..4b94108 100644 --- a/docs/source/install.rst +++ b/docs/source/install.rst @@ -48,7 +48,7 @@ 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 yet it will be created and activated. +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`` From 11d257d2c39a0ba4df6e61871028de60cb63d6fa Mon Sep 17 00:00:00 2001 From: heck Date: Tue, 24 Nov 2020 15:00:15 +0100 Subject: [PATCH 81/84] .gitignore: mercurial to git migration completed --- .hgignore => .gitignore | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .hgignore => .gitignore (100%) diff --git a/.hgignore b/.gitignore similarity index 100% rename from .hgignore rename to .gitignore From 7627b6aba1c43a414832b0a64338bd9c16aebf21 Mon Sep 17 00:00:00 2001 From: heck Date: Tue, 1 Dec 2020 02:12:42 +0100 Subject: [PATCH 82/84] aww always these typos... --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index ee26c8c..80f9118 100644 --- a/README.rst +++ b/README.rst @@ -12,7 +12,7 @@ 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 `_. +If you are pEp internal, please open a ticket in our `jira bugtracker . License From 533477bf64a216a09ffcb0a5098e211d9dc73b47 Mon Sep 17 00:00:00 2001 From: heck Date: Tue, 1 Dec 2020 02:12:57 +0100 Subject: [PATCH 83/84] formatting --- pyproject.toml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 15e3cb3..a25f0cb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,12 @@ + [build-system] -requires = ["setuptools >=39.2.0", "setuptools_scm >= 4.1.2", "wheel >= 0.35.1"] +# 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] From c643f1ff4c363a41c07047fe5305ff1dd3f0982f Mon Sep 17 00:00:00 2001 From: heck Date: Thu, 3 Dec 2020 01:22:40 +0100 Subject: [PATCH 84/84] C++ class Myself : Identity unused --- src/pEp/_pEp/identity.cc | 52 +++++++++++++++++++-------------------- src/pEp/_pEp/identity.hh | 14 +++++------ src/pEp/_pEp/pEpmodule.cc | 2 +- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/pEp/_pEp/identity.cc b/src/pEp/_pEp/identity.cc index 63fbb35..5274c1a 100644 --- a/src/pEp/_pEp/identity.cc +++ b/src/pEp/_pEp/identity.cc @@ -166,28 +166,28 @@ namespace pEp { _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); - } +// 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); + pEp_identity *_dup = ::identity_dup(ident); if (!_dup) throw bad_alloc(); @@ -200,9 +200,9 @@ namespace pEp { pEp_identity *_dup = ::identity_dup(_ident); if (!_dup) throw bad_alloc(); - PEP_STATUS status = update_identity(Adapter::session(), _dup); + PEP_STATUS status = ::update_identity(Adapter::session(), _dup); _throw_status(status); - free_identity(ident); + ::free_identity(ident); ident = _dup; } @@ -220,7 +220,7 @@ namespace pEp { } void identitylist_attr(identity_list *&il, boost::python::list value) { - identity_list *_il = new_identity_list(NULL); + identity_list *_il = ::new_identity_list(NULL); if (!_il) throw bad_alloc(); @@ -233,22 +233,22 @@ namespace pEp { pEp_identity *_ident = extract_identity(); pEp_identity *_dup = ::identity_dup(_ident); if (!_dup) { - free_identity_list(_il); + ::free_identity_list(_il); throw bad_alloc(); } - PEP_STATUS status = update_identity(Adapter::session(), _dup); + PEP_STATUS status = ::update_identity(Adapter::session(), _dup); if (status != PEP_STATUS_OK) { - free_identity_list(_il); + ::free_identity_list(_il); _throw_status(status); } - _i = identity_list_add(_i, _dup); + _i = ::identity_list_add(_i, _dup); if (!_i) { - free_identity_list(_il); + ::free_identity_list(_il); throw bad_alloc(); } } - free_identity_list(il); + ::free_identity_list(il); il = _il; } diff --git a/src/pEp/_pEp/identity.hh b/src/pEp/_pEp/identity.hh index 071ac4a..9149aaf 100644 --- a/src/pEp/_pEp/identity.hh +++ b/src/pEp/_pEp/identity.hh @@ -100,12 +100,12 @@ namespace pEp { void disable_for_sync(); }; - class Myself : public Identity { - public: - Myself(string address, string username, string user_id = "", string lang = ""); - - virtual void update(); - }; +// class Myself : public Identity { +// public: +// Myself(string address, string username, string user_id = "", string lang = ""); +// +// virtual void update(); +// }; Identity identity_attr(pEp_identity *&ident); @@ -118,4 +118,4 @@ namespace pEp { } // namespace PythonAdapter } // namespace pEp -#endif /* IDENTITY_HH */ \ No newline at end of file +#endif /* IDENTITY_HH */ diff --git a/src/pEp/_pEp/pEpmodule.cc b/src/pEp/_pEp/pEpmodule.cc index 73a1f6d..73c1969 100644 --- a/src/pEp/_pEp/pEpmodule.cc +++ b/src/pEp/_pEp/pEpmodule.cc @@ -189,7 +189,7 @@ namespace pEp { boost::locale::generator gen; std::locale::global(gen("")); -// _scope = new scope(); + scope().attr("about") = about(); scope().attr("per_user_directory") = per_user_directory(); scope().attr("per_machine_directory") = per_machine_directory();