51 Commits

Author SHA1 Message Date
  heck 44db8b7510 pEpEngine=Release_2.1.49 1 month ago
  Thomas 7d2fff8083 Update Windows build 4 months ago
  heck e4482be063 pEpEngine=Release_2.1.42 4 months ago
  heck 7a8bf38984 PYADPT-116: for PR's: minimal changes please, sometimes even dead code has a reason oi put it there 4 months ago
  heck 597e5749ab PYADPT-116: formatting 4 months ago
  heck 41a0f49281 Merge pull request 'Fix Blob.data accessor for binary data, esp. bull-bytes' (#5) from htgoebel/pEpPythonAdapter:fix-PYADPT-116 into Release_2.1 4 months ago
  Hartmut Goebel 6a715e199d PYADPT-116: Add more test-cases. 4 months ago
  Hartmut Goebel f5d83b7454 PYADPT-116: Clean up test-suite. 4 months ago
  Hartmut Goebel d6568b0075 PYADPT-116: Fix Blob.data getter for binary data, esp. null-bytes. 4 months ago
  Hartmut Goebel 312c6d9b92 PYADPT-116: Make tests use binary data, esp. null-bytes. 4 months ago
  heck 3c75e518fc Merge branch 'PYADPT-116 - Blob is missing .data accessor' into Release_2.1 4 months ago
  heck 50a09206cd PYADPT-116: add tests 4 months ago
  heck 194f18b04f PYADPT-116: add get/set property Blob.data 4 months ago
  heck bc645f5da2 PYADPT-116: refactor blob.data as setter/getter (getter added) 4 months ago
  heck d8172a43aa Build: pEpEngine=Release_2.1.41 4 months ago
  heck 71cbbbdc5f Build: pEpEngine=Release_2.1.39 4 months ago
  heck 0a8527c094 Tests: Add PYADPT-124 - identity.update() on new identiy raises PEP_CANNOT_SET_PERSON 4 months ago
  heck 2fbef542e0 Build: update deps / remove sequoia dep 4 months ago
  heck e04c8ed1d3 Merge branch 'master' into Release_2.1 4 months ago
  heck b946e95e57 Merge pull request 'setup: Unpin version requirement for package wheel.' (#4) from htgoebel/pEpPythonAdapter:htgoebel-patch-1 into master 6 months ago
  htgoebel bc5a080aa5 setup: Unpin version requirement for package wheel. 6 months ago
  Thomas 6212687b62 Remove unused variable in Windows build 6 months ago
  Thomas 7b02820e5c Add script to automatically package all Windows dependencies in wheel 6 months ago
  heck 89613b713e test: sync_test.py - add --debuglog -d 7 months ago
  heck 3615191b11 Build: python_requires = >=3.7,<3.9 (since linux and mac might be different) 7 months ago
  heck a80a18f027 test: sync_handshake.py - add --debuglog -d option 7 months ago
  heck 7fb3ef584e use Adapter::inject_sync_shutdown() (libpEpAdapter > 0517b9b) 7 months ago
  heck 47205953d3 Build: Make default PREFIX=$(HOME), DEBUG=1 7 months ago
  Volker Birk 35a83abf14 always have three keys 7 months ago
  Volker Birk 010060f2ea always have three keys 7 months ago
  heck b1400519ff Merge branch 'Release_2.1' 7 months ago
  Volker Birk 7f2d884f6e add disable_all_sync_channels() and test with extra identity 7 months ago
  heck d94e5881f4 PYADPT-111: sync_handshake.py, now support single- and mutlithreaded again. but through libpEpAdapter 7 months ago
  heck 5738a2ea33 PYADPT-111: a little bit of testing 7 months ago
  heck bb70cf0169 PYADPT-111: "Add Single Threaded Sync Implementation" - Implementation 7 months ago
  heck 76ef8e0a21 Merge branch 'Release_2.1' of https://gitea.pep.foundation/pEp.foundation/pEpPythonAdapter into Release_2.1 7 months ago
  heck 9a75cab9cd Build: update supported python versions 7 months ago
  Volker Birk a35cea292e Merge branch 'Release_2.1' of ssh://gitea.pep.foundation:23065/pEp.foundation/pEpPythonAdapter into Release_2.1 7 months ago
  heck fc927ccaac FIX: thread.isAlive() replaced with thread.is_alive() (deprecated) 7 months ago
  Volker Birk 5c4dcdba4a the sync thread will continue, don't change directory 7 months ago
  Thomas 72aaa55ef5 Update Windows build 7 months ago
  heck 8623adce03 BUILD: since using venv, default make target is "make install" 7 months ago
  heck 4795d25492 BUILD: Add lxml and termcolor to test requirements 7 months ago
  heck aaaa54f6ad Merge branch 'PYADPT-110 - Add Mutlithreaded Sync Implementation' into Release_2.1 7 months ago
  heck d3d72fd95e .gitignore for "make develop" .so 7 months ago
  heck 58cff017ff PYADPT-110: Add a test for start_sync() / stop_sync() repeatedly 7 months ago
  heck 3a6058e4b5 PYADPT-110: Update sync testing (sync_handshake.py) to work with new sync impl 7 months ago
  heck f858556460 PYADPT-110: "Add Mutlithreaded Sync Implementation" - Implementation 7 months ago
  heck 4209c480a6 correct typo 7 months ago
  heck 819dae00c7 .gitignore: add .so 7 months ago
  heck e8e46cbbad Test: README.md - add link to more sync testing doc. 7 months ago
23 changed files with 723 additions and 203 deletions
Split View
  1. +5
    -0
      .gitignore
  2. +2
    -3
      DEPENDENCIES
  3. +1
    -3
      Makefile
  4. +2
    -2
      Makefile.conf
  5. +146
    -0
      build-windows/add_windows_libraries.py
  6. +0
    -31
      build-windows/pEpPythonAdapter.sln
  7. +13
    -8
      build-windows/pEpPythonAdapter.vcxproj
  8. +22
    -6
      make.mak
  9. +2
    -1
      pyproject.toml
  10. +5
    -2
      setup.cfg
  11. +4
    -5
      setup.py
  12. +103
    -4
      src/pEp/__init__.py
  13. +25
    -17
      src/pEp/_pEp/message.cc
  14. +5
    -1
      src/pEp/_pEp/message.hh
  15. +86
    -55
      src/pEp/_pEp/pEpmodule.cc
  16. +2
    -2
      src/pEp/_pEp/pEpmodule.hh
  17. +2
    -0
      test/README.md
  18. +129
    -0
      test/data/keys/inquisitor-0xA4728718_full_expired.priv.asc
  19. +58
    -0
      test/start_sync.py
  20. +56
    -56
      test/sync_handshake.py
  21. +8
    -7
      test/sync_test.py
  22. +35
    -0
      tests/test_blob.py
  23. +12
    -0
      tests/test_identity.py

+ 5
- 0
.gitignore View File

@ -7,6 +7,7 @@ build/
.pythonhist
.gnupg
.lldb
.so
.pEp_management.db*
.python_history
__pycache__/
@ -23,6 +24,7 @@ build-windows/Release/
build-windows/packages/
build-windows/.vs/
build-windows/pEpPythonAdapter.vcxproj.*
.vscode/
launch.json
settings.json
# Default ignored files
@ -73,6 +75,9 @@ __pycache__/
.idea
.spyproject
*.code-workspace
tags
ws
# platform artifacts
.DS_store
/src/pEp/_pEp.cpython-38-darwin.so

+ 2
- 3
DEPENDENCIES View File

@ -1,6 +1,5 @@
# 1st Party Dependencies
## Prefer git tags instead of SHA hashes when possible.
libpEpAdapter=Release_2.1.17
pEpEngine=Release_2.1.23
sequoia=365d00a08bec6a5a48d48a7c7893d78c27092b59
libpEpAdapter=Release_2.1.21
pEpEngine=Release_2.1.49

+ 1
- 3
Makefile View File

@ -1,7 +1,7 @@
include Makefile.conf
.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
all: install
# Build
# =====
@ -57,8 +57,6 @@ envtest:
install-test: compile
pip3 install .[test]
# TODO: maybe use setup.py test?
# --forked, because every test needs a separate process, see PYADPT-100
test:
pytest


+ 2
- 2
Makefile.conf View File

@ -11,8 +11,8 @@ PYTHON_ARTIFACTS += ./.pytest_cache
VENV_DIR = ./venv
# Build config Defaults
DEBUG=0
PREFIX=
DEBUG=1
PREFIX=$(HOME)
######### Overrides #########
-include $(HERE)local.conf


+ 146
- 0
build-windows/add_windows_libraries.py View File

@ -0,0 +1,146 @@
import os
import re
import sys
import subprocess
import winreg
import zipfile as zf
from os.path import dirname
from os.path import join
def get_bindependencies(lib, debug=False):
"""Gets the pEp dependencies of a library"""
python_location = sys.exec_prefix
bindepend = join(python_location, 'Scripts', 'pyi-bindepend.exe')
output = subprocess.run([bindepend, lib], capture_output=True)
if os.path.isfile(lib):
yield lib
if len(output.stdout) > 0:
deps = parse_bindepend_output(output.stdout)
for dep in add_full_paths(deps, debug):
for d in get_bindependencies(dep):
yield d
def parse_bindepend_output(stdout):
"""Parses the output of pyi-bindepent and returns a list of file names"""
deps = []
if stdout == None:
return None
p = re.compile('(.*){(.*)}(.*)')
str_val = bytes.decode(stdout)
raw_val = p.findall(str_val)
if len(raw_val) == 0:
return deps
else:
libs = raw_val[0][1].replace(' ', '').split(',')
for lib in libs:
lib = lib.strip("'")
if not 'api' in lib:
deps.append(lib)
return deps
def get_pEp_install_location(debug=False):
"""Gets the location where pEp is installed"""
reg_path = "SOFTWARE\\Classes\\TypeLib\\{564A4350-419E-47F1-B0DF-6FCCF0CD0BBC}\\1.0\\0\\win32"
KeyName = None
regKey = None
try:
regKey = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, reg_path, 0, winreg.KEY_READ)
# Keys: Description, FileName, FriendlyName, LoadBehavior
com_server, _ = winreg.QueryValueEx(regKey, KeyName)
except WindowsError as error:
print('Error getting install location: ' + error)
com_server = None
finally:
if winreg:
winreg.CloseKey(regKey)
location = os.path.dirname(com_server)
if debug:
location = location.strip('Release') + 'Debug'
return location
def get_boost_directories():
"""Gets the location of the boost libraries"""
for dir in [f.path for f in os.scandir(join(dirname(os.getcwd()), 'packages')) if f.is_dir()]:
if 'boost.' in dir or 'boost_python' in dir or 'boost_locale' in dir:
yield join(dir, 'lib', 'native')
def add_full_paths(libs, debug=False):
"""Combines a list of libraries with a set of common directories. Returns a list of file names that exist on this machine"""
paths = [get_pEp_install_location(debug)] + [dir for dir in get_boost_directories()] + [p for p in os.environ['PATH'].split(';')]
paths = [p for p in paths if not "system32" in p.lower()]
full_paths = []
for lib in libs:
for p in paths:
test_path = join(p, lib)
if os.path.isfile(test_path) and not test_path.casefold() in (f.casefold for f in full_paths):
full_paths.append(test_path)
return full_paths
def main():
args = sys.argv
cwd = dirname(args[0])
del args[0]
# Check for debug build
debug = False
if len(args) > 0 and args[0] == '--debug':
debug = True
del args[0]
# Get the pEp wheel and extract the pEp Python library
dist_path = join(dirname(cwd), 'dist')
print('Dist path is: ' + dist_path)
pEp_python_library = None
if os.path.exists(dist_path):
for _, _, files in os.walk(dist_path):
for f in files:
if f[:3] == 'pEp' and f[-3:] == 'whl':
wheel_name = join(dist_path, f)
with zf.ZipFile(wheel_name, 'a') as wheel:
for archive_member in wheel.namelist():
if '_pEp' in archive_member and archive_member[-3:] == 'pyd':
wheel.extract(archive_member, path=dist_path)
pEp_python_library = join(dist_path, archive_member)
print('pEp Python library found and extracted to ' + pEp_python_library)
break
break
# Get all dependencies for the pEp Python library
if pEp_python_library == None:
raise FileNotFoundError('pEp Python library not found in ' + dist_path)
pEp_python_library = pEp_python_library.replace('/', '\\')
libs = []
for lib in get_bindependencies(pEp_python_library, debug):
if not lib.casefold() in (l.casefold for l in libs) and lib.casefold() != pEp_python_library.casefold():
print('Dependency found: ' + lib)
libs.append(lib)
# Copy dependencies into the wheel
with zf.ZipFile(wheel_name, 'a') as wheel:
for lib in libs:
filename = os.path.basename(lib)
arcname = 'pEp/' + filename
if not arcname in wheel.namelist():
wheel.write(filename=lib, arcname=arcname, compress_type=zf.ZIP_DEFLATED)
# Delete the temporarily extracted pEp Python library
if os.path.isfile(pEp_python_library):
os.remove(pEp_python_library)
dir = os.path.dirname(pEp_python_library)
if dir[-3:].lower() == 'pep' and os.path.isdir(dir):
os.rmdir(dir)
if __name__ == '__main__':
main()

+ 0
- 31
build-windows/pEpPythonAdapter.sln View File

@ -1,31 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31005.135
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pEpPythonAdapter", "pEpPythonAdapter.vcxproj", "{F7D4314B-C7BA-4117-9AE7-AC5C1492153D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F7D4314B-C7BA-4117-9AE7-AC5C1492153D}.Debug|x64.ActiveCfg = Debug|x64
{F7D4314B-C7BA-4117-9AE7-AC5C1492153D}.Debug|x64.Build.0 = Debug|x64
{F7D4314B-C7BA-4117-9AE7-AC5C1492153D}.Debug|x86.ActiveCfg = Debug|Win32
{F7D4314B-C7BA-4117-9AE7-AC5C1492153D}.Debug|x86.Build.0 = Debug|Win32
{F7D4314B-C7BA-4117-9AE7-AC5C1492153D}.Release|x64.ActiveCfg = Release|x64
{F7D4314B-C7BA-4117-9AE7-AC5C1492153D}.Release|x64.Build.0 = Release|x64
{F7D4314B-C7BA-4117-9AE7-AC5C1492153D}.Release|x86.ActiveCfg = Release|Win32
{F7D4314B-C7BA-4117-9AE7-AC5C1492153D}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B63BC9BA-EF76-4FB4-9126-29CBFAD9092C}
EndGlobalSection
EndGlobal

+ 13
- 8
build-windows/pEpPythonAdapter.vcxproj View File

@ -63,7 +63,7 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<NMakeBuildCommandLine>nmake /F "$(ProjectDir)..\make.mak" all</NMakeBuildCommandLine>
<NMakeBuildCommandLine>nmake /F "$(ProjectDir)..\make.mak" debug</NMakeBuildCommandLine>
<NMakeOutput>
</NMakeOutput>
<NMakePreprocessorDefinitions>WIN32;_DEBUG;_DLL;$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
@ -76,7 +76,7 @@
<NMakePreprocessorDefinitions>_DEBUG;$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<NMakeBuildCommandLine>nmake /F "$(ProjectDir)..\make.mak" all</NMakeBuildCommandLine>
<NMakeBuildCommandLine>nmake /F "$(ProjectDir)..\make.mak" release</NMakeBuildCommandLine>
<NMakeOutput>
</NMakeOutput>
<NMakePreprocessorDefinitions>WIN32;NDEBUG;_DLL;$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
@ -95,18 +95,23 @@
<None Include="..\setup.py" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\pEpEngine\build-windows\pEpEngine.vcxproj">
<Project>{146e69f8-e1da-456a-b048-6dd29d9acf6b}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="packages\boost.1.72.0.0\build\boost.targets" Condition="Exists('packages\boost.1.72.0.0\build\boost.targets')" />
<Import Project="packages\boost_locale-vc142.1.72.0.0\build\boost_locale-vc142.targets" Condition="Exists('packages\boost_locale-vc142.1.72.0.0\build\boost_locale-vc142.targets')" />
<Import Project="packages\boost_python38-vc142.1.72.0.0\build\boost_python38-vc142.targets" Condition="Exists('packages\boost_python38-vc142.1.72.0.0\build\boost_python38-vc142.targets')" />
<Import Project="..\..\packages\boost.1.72.0.0\build\boost.targets" Condition="Exists('..\..\packages\boost.1.72.0.0\build\boost.targets')" />
<Import Project="..\..\packages\boost_locale-vc142.1.72.0.0\build\boost_locale-vc142.targets" Condition="Exists('..\..\packages\boost_locale-vc142.1.72.0.0\build\boost_locale-vc142.targets')" />
<Import Project="..\..\packages\boost_python38-vc142.1.72.0.0\build\boost_python38-vc142.targets" Condition="Exists('..\..\packages\boost_python38-vc142.1.72.0.0\build\boost_python38-vc142.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\boost.1.72.0.0\build\boost.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\boost.1.72.0.0\build\boost.targets'))" />
<Error Condition="!Exists('packages\boost_locale-vc142.1.72.0.0\build\boost_locale-vc142.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\boost_locale-vc142.1.72.0.0\build\boost_locale-vc142.targets'))" />
<Error Condition="!Exists('packages\boost_python38-vc142.1.72.0.0\build\boost_python38-vc142.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\boost_python38-vc142.1.72.0.0\build\boost_python38-vc142.targets'))" />
<Error Condition="!Exists('..\..\packages\boost.1.72.0.0\build\boost.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\boost.1.72.0.0\build\boost.targets'))" />
<Error Condition="!Exists('..\..\packages\boost_locale-vc142.1.72.0.0\build\boost_locale-vc142.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\boost_locale-vc142.1.72.0.0\build\boost_locale-vc142.targets'))" />
<Error Condition="!Exists('..\..\packages\boost_python38-vc142.1.72.0.0\build\boost_python38-vc142.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\boost_python38-vc142.1.72.0.0\build\boost_python38-vc142.targets'))" />
</Target>
</Project>

+ 22
- 6
make.mak View File

@ -1,6 +1,6 @@
# build dirs
BUILD_DIR = $(ProjectDir)..\build
DIST_DIR = $(ProjectDir)..\dist
BUILD_DIR = build
DIST_DIR = dist
# create wheel and egg package in dist
dist: dist-whl dist-egg
@ -16,12 +16,28 @@ dist-egg: compile
# build the module into build
compile:
CD..
PY -3.8-32 setup.py build_ext
PY -3.8-32 setup.py build_ext --debug
# delete output directories
clean:
@if exist $(BUILD_DIR) rmdir /S /Q $(BUILD_DIR)
@if exist $(DIST_DIR) rmdir /S /Q $(DIST_DIR)
@if exist $(BUILD_DIR) rmdir /S /Q $(BUILD_DIR)
@if exist $(DIST_DIR) rmdir /S /Q $(DIST_DIR)
# create directories and build application
all: clean dist
all: clean dist
# release build
release: clean
CD..
PY -3.8-32 setup.py build_ext
PY -3.8-32 setup.py bdist_wheel
PY -3.8-32 build-windows\add_windows_libraries.py
COPY dist\pEp* ..\Release\
#debug build
debug: clean
CD..
PY -3.8-32 setup.py build_ext --debug
PY -3.8-32 setup.py bdist_wheel
PY -3.8-32 build-windows\add_windows_libraries.py --debug
COPY dist\pEp* ..\Debug\

+ 2
- 1
pyproject.toml View File

@ -5,7 +5,8 @@
requires =[
"setuptools >=39.2.0",
"setuptools_scm >= 4.1.2",
"wheel >= 0.35.1" ]
"wheel",
]
build-backend = "setuptools.build_meta"


+ 5
- 2
setup.cfg View File

@ -27,17 +27,20 @@ classifiers =
[options]
zip_safe = false
include_package_data = true
python_requires = >= 3.6
python_requires = >=3.7,<3.9
test_suite = tests
install_requires =
# deprecated/redundant with pyproject.toml, but lets keep both ways around for now
setup_requires =
setuptools >=39.2.0
setuptools_scm >= 4.1.2
wheel >= 0.35.1
wheel
[options.extras_require]
# To install these dependencies, run pip install .[test]
test =
pytest
pytest-forked
lxml
termcolor
doc = sphinx

+ 4
- 5
setup.py View File

@ -60,7 +60,7 @@ class BuildExtCommand(build_ext):
return ret
def windowsGetBoostDirs(self):
for dir in [f.path for f in os.scandir(join(os.getcwd(), 'build-windows', 'packages')) if f.is_dir()]:
for dir in [f.path for f in os.scandir(join(os.path.dirname(os.getcwd()), 'packages')) if f.is_dir()]:
if 'boost.' in dir or 'boost_python' in dir or 'boost_locale' in dir:
yield join(dir, 'lib', 'native'), join(dir, 'lib', 'native', 'include')
@ -70,9 +70,8 @@ class BuildExtCommand(build_ext):
sys_includes = [
join(inst_prefix),
] + [d[1] for d in self.windowsGetBoostDirs()]
sys_libdirs = [
join(inst_prefix, 'Release')
] + [d[0] for d in self.windowsGetBoostDirs()]
sys_libdirs = [ join(inst_prefix, 'Debug')] if self.debug else [ join(inst_prefix, 'Release')]
sys_libdirs += [d[0] for d in self.windowsGetBoostDirs()]
libs = [
'pEpEngine',
'libpEpAdapter',
@ -82,7 +81,7 @@ class BuildExtCommand(build_ext):
compile_flags = ['/std:c++14', '/permissive']
if self.debug:
pEpLog("debug mode")
compile_flags += ['/O0', '/g', '/UNDEBUG']
compile_flags += ['/Od', '/Zi', '/DEBUG']
return (home, sys_includes, sys_libdirs, libs, compile_flags)


+ 103
- 4
src/pEp/__init__.py View File

@ -14,9 +14,11 @@ 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:
@ -30,18 +32,48 @@ from ._pEp import *
# with an underscore (of _pEp), but we dont want to import them into this module
import pEp._pEp
# 3rd party imports
from threading import Thread, Barrier
from time import sleep
# Executed on module import
def init():
print(init, "called")
# print(init, "called")
_pEp._init_after_main_module()
def start_sync() -> None:
"""starts the sync thread"""
set_sync_mode(SyncModes.Async)
def shutdown_sync() -> None:
"""call this to shut down the sync thread"""
set_sync_mode(SyncModes.Off)
def set_sync_mode(mode):
_pEp._set_sync_mode(mode)
if mode == SyncModes.Sync:
Sync.shutdown_sync()
if mode == SyncModes.Async:
Sync.start_sync()
if mode == SyncModes.Off:
Sync.shutdown_sync()
def is_sync_active() -> bool:
"""True if sync is active, False otherwise"""
return Sync.getInstance().is_alive()
def message_to_send(msg):
"""
message_to_send(msg)
override pEp.message_to_send(msg) with your own implementation
this callback is being called when a pp management message needs to be sent
GIL CAVEAT
"""
print("message_to_send() - default callback\n")
print("overwrite this method")
@ -54,10 +86,77 @@ def notify_handshake(me, partner, signal):
partner identity of communication partner
signal the handshake signal
overwrite this method with an implementation of a handshake dialog
GIL CAVEAT
"""
print("message_to_send() - default callback\n")
print("notify_handshake() - default callback\n")
print("overwrite this method")
class Sync(Thread):
__instance: 'Sync' = None
barr = Barrier(2)
def __init__(self):
if Sync.__instance != None:
raise Exception("singleton!")
else:
Sync.__instance = self
Thread.__init__(self)
@staticmethod
def getInstance() -> 'Sync':
if Sync.__instance == None:
Sync()
return Sync.__instance
def run(self):
"""
* Sync Thread
* NOPE 1. Execute registered startup function
register_sync_callbacks
* 2. Create session for the sync thread (registers: messageToSend, _inject_sync_event, _ensure_passphrase)
* 3. register_sync_callbacks() (registers: _notifyHandshake, _retrieve_next_sync_event)
* 4. Enter Sync Event Dispatching Loop (do_sync_protocol())
unregister_sync_callbacks
* 5. unregister_sync_callbacks()
* 6. Release the session
* NOPE 7. Execute registered shutdown function
"""
# TODO catch exception, and rethrow in start()
_pEp._register_sync_callbacks()
self.barr.wait()
while _pEp._do_protocol_step():
sleep(1)
_pEp._unregister_sync_callbacks()
def start(self):
"""
* (1. Done on init(): ensure session for the main thread
(registers: messageToSend, _inject_sync_event, _ensure_passphrase))
* 2. Start the sync thread
* 3. Defer execution until sync thread register_sync_callbacks() has returned
* 4. TODO: Throw pending exception from the sync thread
"""
Thread.start(self)
self.barr.wait()
# TODO: Throw exceptions from sync thread
# _pEp._notifyHandshake_sync_start()
# sleep(2)
@staticmethod
def start_sync():
if not Sync.getInstance().is_alive():
Sync.getInstance().start()
@staticmethod
def shutdown_sync():
if Sync.__instance:
if Sync.__instance.is_alive():
_pEp._inject_sync_shutdown()
Sync.__instance.join()
Sync.__instance = None
# _pEp._notifyHandshake_sync_stop()
init()

+ 25
- 17
src/pEp/_pEp/message.cc View File

@ -34,24 +34,8 @@ namespace pEp {
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->data(data);
this->mime_type(mime_type);
this->filename(filename);
}
@ -110,6 +94,30 @@ namespace pEp {
return PyBuffer_FillInfo(view, self, bl->value, bl->size, 0, flags);
}
object Message::Blob::data() {
return object(handle<>(PyBytes_FromStringAndSize(_bl->value, _bl->size)));
}
void Message::Blob::data(object data) {
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);
}
string Message::Blob::decode(string encoding) {
if (encoding == "") {
string _mime_type = _bl->mime_type ? _bl->mime_type : "";


+ 5
- 1
src/pEp/_pEp/message.hh View File

@ -59,6 +59,10 @@ namespace pEp {
size_t size() { return _bl->size; }
object data();
void data(object data);
string decode(string encoding);
string decode() { return decode(""); }
@ -191,4 +195,4 @@ namespace pEp {
} /* namespace PythonAdapter */
} /* namespace pEp */
#endif /* MESSAGE_HH */
#endif /* MESSAGE_HH */

+ 86
- 55
src/pEp/_pEp/pEpmodule.cc View File

@ -37,11 +37,20 @@ namespace pEp {
pEpLog("called");
}
// hidden init function, wrapped by hello_world.init()
// hidden init function, wrapped by _pEp.init()
void _init_after_main_module() {
pEpLog("called");
callback_dispatcher.add(_messageToSend, notifyHandshake, nullptr, nullptr);
Adapter::_messageToSend = CallbackDispatcher::messageToSend;
callback_dispatcher.add(_messageToSend, _notifyHandshake, nullptr, nullptr);
// Adapter::sync_initialize(
// Adapter::SyncModes::Off,
// CallbackDispatcher::messageToSend,
// CallbackDispatcher::notifyHandshake,
// true);
Adapter::sync_initialize(
Adapter::SyncModes::Off,
_messageToSend,
_notifyHandshake,
true);
}
@ -96,6 +105,7 @@ namespace pEp {
}
}
// TODO: GIL handling isnt really required here, i think
PEP_STATUS _messageToSend(::message *msg) {
pEpLog("called");
try {
@ -103,7 +113,7 @@ namespace pEp {
pEpLog("GIL Aquired");
object modref = import("pEp");
object funcref = modref.attr("message_to_send");
call<void>(funcref.ptr(), Message());
call<void>(funcref.ptr(), Message(msg));
PyGILState_Release(gil);
pEpLog("GIL released");
} catch (exception &e) {}
@ -111,14 +121,15 @@ namespace pEp {
return PEP_STATUS_OK;
}
PEP_STATUS notifyHandshake(pEp_identity *me, pEp_identity *partner, sync_handshake_signal signal) {
// TODO: GIL handling isnt really required here, i think
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<void>(funcref.ptr(), me, partner, signal);
call<void>(funcref.ptr(), Identity(me), Identity(partner), signal);
PyGILState_Release(gil);
pEpLog("GIL released");
} catch (exception &e) {}
@ -126,13 +137,40 @@ namespace pEp {
return PEP_STATUS_OK;
}
bool _do_protocol_step() {
pEpLog("called");
SYNC_EVENT event = Adapter::_retrieve_next_sync_event(nullptr, 0);
if (event != NULL) {
::do_sync_protocol_step(Adapter::session(), (void *)&callback_dispatcher, event);
return true;
} else {
pEpLog("null event, signaling sync shutdown");
return false;
}
}
void _register_sync_callbacks() {
pEpLog("called");
Adapter::session();
PEP_STATUS status = ::register_sync_callbacks(Adapter::session(), nullptr, Adapter::_notifyHandshake, Adapter::_retrieve_next_sync_event);
_throw_status(status);
}
void _unregister_sync_callbacks() {
::unregister_sync_callbacks(Adapter::session());
// Adapter::session(release);
}
void start_sync() {
CallbackDispatcher::start_sync();
// TODO: Integrate this (currently SEGFAULTING)
void _notifyHandshake_sync_start() {
pEpLog("all targets signal: SYNC_NOTIFY_START");
CallbackDispatcher::notifyHandshake(nullptr, nullptr, SYNC_NOTIFY_START);
}
void shutdown_sync() {
CallbackDispatcher::stop_sync();
// TODO: Integrate this (currently SEGFAULTING)
void _notifyHandshake_sync_stop() {
pEpLog("all targets signal: SYNC_NOTIFY_STOP");
CallbackDispatcher::notifyHandshake(nullptr, nullptr, SYNC_NOTIFY_STOP);
}
void debug_color(int ansi_color) {
@ -143,8 +181,8 @@ namespace pEp {
::leave_device_group(Adapter::session());
}
bool is_sync_active() {
return Adapter::is_sync_running();
void disable_all_sync_channels() {
::disable_all_sync_channels(Adapter::session());
}
void testfunc() {
@ -196,6 +234,35 @@ namespace pEp {
scope().attr("engine_version") = get_engine_version();
scope().attr("protocol_version") = get_protocol_version();
def("set_debug_log_enabled", &Adapter::pEpLog::set_enabled,
"Switch debug logging on/off");
def("_register_sync_callbacks", _register_sync_callbacks,
"");
def("_unregister_sync_callbacks", _unregister_sync_callbacks,
"");
def("_do_protocol_step", _do_protocol_step,
"");
def("_inject_sync_shutdown", Adapter::inject_sync_shutdown,
"");
def("_notifyHandshake_sync_start", _notifyHandshake_sync_start,
"");
def("_notifyHandshake_sync_stop", _notifyHandshake_sync_stop,
"");
def("_set_sync_mode", pEp::Adapter::set_sync_mode,
"");
enum_<pEp::Adapter::SyncModes>("SyncModes")
.value("Off", pEp::Adapter::SyncModes::Off)
.value("Async", pEp::Adapter::SyncModes::Async)
.value("Sync", pEp::Adapter::SyncModes::Sync);
def("passive_mode", config_passive_mode,
"do not attach pub keys to all messages");
@ -332,7 +399,10 @@ namespace pEp {
"MIME type of object in Blob")
.add_property("filename", (string(Message::Blob::*)()) &Message::Blob::filename,
(void(Message::Blob::*)(string)) &Message::Blob::filename,
"filename of object in Blob");
"filename of object in Blob")
.add_property("data", (object(Message::Blob::*)()) &Message::Blob::data,
(void(Message::Blob::*)(object)) &Message::Blob::data,
"data of object in Blob");
((PyTypeObject *)(void *)blob_class.ptr())->tp_as_buffer = &Message::Blob::bp;
@ -584,32 +654,6 @@ namespace pEp {
.value("SYNC_NOTIFY_SOLE", SYNC_NOTIFY_SOLE)
.value("SYNC_NOTIFY_IN_GROUP", SYNC_NOTIFY_IN_GROUP);
// auto user_interface_class = class_<UserInterface, UserInterface_callback, boost::noncopyable>(
// "UserInterface",
// "class MyUserInterface(UserInterface):\n"
// " def notifyHandshake(self, me, partner):\n"
// " ...\n"
// "\n"
// "p≡p User Interface class\n"
// "To be used as a mixin\n"
// )
// .def("notifyHandshake", &UserInterface::notifyHandshake,
// "notifyHandshake(self, me, partner)\n"
// "\n"
// " me own identity\n"
// " partner identity of communication partner\n"
// "\n"
// "overwrite this method with an implementation of a handshake dialog")
// .def("deliverHandshakeResult", &UserInterface::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("deliver_handshake_result", &deliverHandshakeResult, boost::python::arg("identities")=object(),
"deliverHandshakeResult(self, result, identities=None)\n"
"\n"
@ -619,18 +663,6 @@ namespace pEp {
"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");
@ -640,13 +672,12 @@ namespace pEp {
"call this for a grouped device, which should leave\n"
);
def("is_sync_active", &is_sync_active,
"is_sync_active()\n"
def("disable_all_sync_channels", &disable_all_sync_channels,
"disable_all_sync_channels()\n"
"\n"
"True if sync is active, False otherwise\n"
"Disable sync for all identities\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));


+ 2
- 2
src/pEp/_pEp/pEpmodule.hh View File

@ -27,9 +27,9 @@ namespace pEp {
PEP_STATUS _messageToSend(::message *msg);
PEP_STATUS notifyHandshake(pEp_identity *me, pEp_identity *partner, sync_handshake_signal signal);
PEP_STATUS _notifyHandshake(pEp_identity *me, pEp_identity *partner, sync_handshake_signal signal);
} /* namespace PythonAdapter */
} /* namespace pEp */
#endif /* PEPMODULE_HH */
#endif /* PEPMODULE_HH */

+ 2
- 0
test/README.md View File

@ -1,5 +1,7 @@
= Tests in this directory =
more doc under: https://dev.pep.foundation/Engine/Testing%20p%e2%89%a1p%20Sync
$ HOME=$PWD python3 basic_doctest.py -v
do some basic tests of p≡p


+ 129
- 0
test/data/keys/inquisitor-0xA4728718_full_expired.priv.asc View File

@ -0,0 +1,129 @@
-----BEGIN PGP PRIVATE KEY BLOCK-----
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
Zi5tJqJFwNBceGW3kZI=
=jOL5
-----END PGP PRIVATE KEY BLOCK-----

+ 58
- 0
test/start_sync.py View File

@ -0,0 +1,58 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import pEp
import time
pEp.set_debug_log_enabled(True)
def msg2send(message):
print("MSG2SEND")
# print(message)
def handshake(me, partner, signal):
print("HANDSHAKE")
print(me.fpr)
print(partner.fpr)
print(signal)
pEp.message_to_send = msg2send
pEp.notify_handshake = handshake
alice = pEp.Identity("tedst@alice.com", "alice", "23")
pEp.myself(alice)
print(alice.fpr)
while True:
pEp.set_sync_mode(pEp.SyncModes.Async)
print("start_sync()")
pEp.start_sync()
print("Running...")
time.sleep(3)
print("shutdown_sync()")
pEp.shutdown_sync()
print("END")
time.sleep(3)
pEp.set_sync_mode(pEp.SyncModes.Sync)
print("start_sync()")
pEp.start_sync()
print("Running...")
time.sleep(3)
print("shutdown_sync()")
pEp.shutdown_sync()
print("END")
time.sleep(3)
pEp.set_sync_mode(pEp.SyncModes.Off)
print("start_sync()")
pEp.start_sync()
print("Running...")
time.sleep(3)
print("shutdown_sync()")
pEp.shutdown_sync()
print("END")
time.sleep(3)

+ 56
- 56
test/sync_handshake.py View File

@ -45,6 +45,7 @@ inbox = pathlib.Path("..") / "TestInbox"
device_name = ""
output = print
multithreaded = False
debug_log = False
DONT_TRIGGER_SYNC = 0x200
SYNC_HANDSHAKE_ACCEPTED = 0
@ -90,6 +91,8 @@ def print_msg(p):
def messageToSend(msg):
assert msg.from_.address == "alice@peptest.ch"
assert msg.to[0].address == "alice@peptest.ch"
msg = add_debug_info(msg)
minimail.send(inbox, msg, device_name)
@ -112,37 +115,36 @@ def add_debug_info(msg):
return msg
class UserInterface(pEp.UserInterface):
def notifyHandshake(self, me, partner, signal):
print(colored(str(signal), "yellow"), end=" ")
output("on " + device_name + "" if not me.fpr else
"for identities " + str(me.fpr) + " " + str(partner.fpr))
if me.fpr and partner.fpr:
assert me.fpr != partner.fpr
if signal in (
pEp.sync_handshake_signal.SYNC_NOTIFY_INIT_ADD_OTHER_DEVICE,
pEp.sync_handshake_signal.SYNC_NOTIFY_INIT_ADD_OUR_DEVICE,
pEp.sync_handshake_signal.SYNC_NOTIFY_INIT_FORM_GROUP
):
if isinstance(end_on, list):
end_on.extend([
pEp.sync_handshake_signal.SYNC_NOTIFY_SOLE,
pEp.sync_handshake_signal.SYNC_NOTIFY_IN_GROUP,
])
sleep(.5) # user is reading message
try:
if not options.noanswer:
if options.reject:
self.deliverHandshakeResult(SYNC_HANDSHAKE_REJECTED)
else:
self.deliverHandshakeResult(SYNC_HANDSHAKE_ACCEPTED)
except NameError:
self.deliverHandshakeResult(SYNC_HANDSHAKE_ACCEPTED)
if signal in end_on:
global the_end
the_end = True
def this_notifyHandshake(me, partner, signal):
print(colored(str(signal), "yellow"), end=" ")
output("on " + device_name + "" if not me.fpr else
"for identities " + str(me.fpr) + " " + str(partner.fpr))
if me.fpr and partner.fpr:
assert me.fpr != partner.fpr
if signal in (
pEp.sync_handshake_signal.SYNC_NOTIFY_INIT_ADD_OTHER_DEVICE,
pEp.sync_handshake_signal.SYNC_NOTIFY_INIT_ADD_OUR_DEVICE,
pEp.sync_handshake_signal.SYNC_NOTIFY_INIT_FORM_GROUP
):
if isinstance(end_on, list):
end_on.extend([
pEp.sync_handshake_signal.SYNC_NOTIFY_SOLE,
pEp.sync_handshake_signal.SYNC_NOTIFY_IN_GROUP,
])
sleep(.5) # user is reading message
try:
if not options.noanswer:
if options.reject:
pEp.deliver_handshake_result(SYNC_HANDSHAKE_REJECTED)
else:
pEp.deliver_handshake_result(SYNC_HANDSHAKE_ACCEPTED)
except NameError:
pEp.deliver_handshake_result(SYNC_HANDSHAKE_ACCEPTED)
if signal in end_on:
global the_end
the_end = True
def shutdown_sync():
@ -150,10 +152,12 @@ def shutdown_sync():
def run(name, color=None, imap=False, own_ident=1, leave=False):
global device_name
device_name = name
pEp.set_debug_log_enabled(debug_log)
pEp.notify_handshake = this_notifyHandshake
if color:
global output
output = lambda x: print(colored(x, color))
@ -164,41 +168,34 @@ def run(name, color=None, imap=False, own_ident=1, leave=False):
elif color == "cyan":
pEp.debug_color(36)
if own_ident >= 2:
me2 = pEp.Identity("alice@pep.security", name + " of Alice Neuman", name)
pEp.myself(me2)
if own_ident == 3:
me3 = pEp.Identity("alice@pep.foundation", name + " of Alice Neuman", name)
pEp.myself(me3)
pEp.disable_all_sync_channels()
if imap:
import miniimap
import imap_settings
me = pEp.Identity(imap_settings.IMAP_EMAIL, name + " of " + imap_settings.IMAP_USER, name)
pEp.myself(me)
pEp.messageToSend = messageImapToSend
pEp.message_to_send = messageImapToSend
else:
me = pEp.Identity("alice@peptest.ch", name + " of Alice Neuman", name)
pEp.myself(me)
if own_ident >= 2:
me2 = pEp.Identity("alice@pep.security", name + " of Alice Neuman", name)
pEp.myself(me2)
if own_ident == 3:
me3 = pEp.Identity("alice@pep.foundation", name + " of Alice Neuman", name)
pEp.myself(me3)
pEp.messageToSend = messageToSend
pEp.message_to_send = messageToSend
if multithreaded:
from threading import Thread
def sync_thread():
print(colored("********* ", "yellow") + colored("sync_thread entered", color))
ui = UserInterface()
print(colored("********* ", "yellow") + colored("UserInterface object created", color))
pEp.do_sync_protocol()
print(colored("********* ", "yellow") + colored("leaving sync_thread", color))
sync = Thread(target=sync_thread)
sync.start()
print("Sync Start multi-threaded")
pEp.set_sync_mode(pEp.SyncModes.Async)
else:
pEp.script_is_implementing_sync()
sync = None
ui = UserInterface()
print("Sync Start single-threaded")
pEp.set_sync_mode(pEp.SyncModes.Sync);
try:
if leave:
@ -255,7 +252,9 @@ if __name__=="__main__":
dest="leave",
help="after a successful sync run this to make the device leave the "
"device group again")
optParser.add_option("-d", "--debuglog", action="store_true",
dest="debug_log",
help="print extra verbose pEpPythonAdater debug log")
options, args = optParser.parse_args()
if not options.exec_for:
@ -277,4 +276,5 @@ if __name__=="__main__":
raise ValueError("Multiple own identities not supported for imap mode")
multithreaded = options.multithreaded
debug_log = options.debug_log
run(options.exec_for, options.color, options.imap, options.own_ident, options.leave)

+ 8
- 7
test/sync_test.py View File

@ -22,7 +22,7 @@ import shutil
import pathlib
def test_for(path, color=None, end_on=None, mt=False, imap=False, own_ident=1):
def test_for(path, color=None, end_on=None, mt=False, imap=False, debuglog=False, own_ident=1):
cwd = os.getcwd();
os.chdir(path)
@ -33,11 +33,9 @@ def test_for(path, color=None, end_on=None, mt=False, imap=False, own_ident=1):
if end_on:
sync_handshake.end_on = end_on
sync_handshake.multithreaded = mt
sync_handshake.debug_log = debuglog
sync_handshake.run(path, color, imap, own_ident)
os.chdir(cwd)
def setup(path):
cwd = os.getcwd();
@ -107,6 +105,9 @@ if __name__ == "__main__":
optParser.add_option("-A", "--add-account-after-sync", action="store_true",
dest="add_account",
help="after sync add an account")
optParser.add_option("-d", "--debuglog", action="store_true",
dest="debug_log",
help="print extra verbose pEpPythonAdater debug log")
options, args = optParser.parse_args()
@ -213,14 +214,14 @@ if __name__ == "__main__":
# Phone runs with own_ident = 2
Phone = Process(target=test_for, args=("Phone", "red", end_on,
options.multithreaded, options.imap, 1))
options.multithreaded, options.imap, options.debug_log, 2))
# others run with own_ident = 1
Laptop = Process(target=test_for, args=("Laptop", "green", end_on,
options.multithreaded, options.imap))
options.multithreaded, options.imap, options.debug_log))
if options.third:
Pad = Process(target=test_for, args=("Pad", "cyan", end_on,
options.multithreaded, options.imap))
options.multithreaded, options.imap, options.debug_log))
Phone.start()
Laptop.start()


+ 35
- 0
tests/test_blob.py View File

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
# This file is under GNU Affero General Public License 3.0
# see LICENSE.txt
"""Blob unit tests."""
import pytest
from . import constants
from . import model
def test_blob_data_constructor(pEp):
bdata = b'this is binary \x00\x01\xbb\xa7\xa4\xab test data'
b = pEp.Blob(bdata)
assert b.data == bdata
assert not b.mime_type
assert not b.filename
def test_blob_data_property(pEp):
bdata = b'this is binary \x00\x01\xbb\xa7\xa4\xab test data'
b = pEp.Blob(b'dummy')
b.data = bdata
assert b.data == bdata
assert not b.mime_type
assert not b.filename
def test_blob_data_property_keeps_other_fields(pEp):
bdata = b'this is binary \x00\x01\xbb\xa7\xa4\xab test data'
b = pEp.Blob(b'dummy', 'application/x-mydata', 'myfile.dat')
b.data = bdata
assert b.data == bdata
assert b.mime_type == 'application/x-mydata'
assert b.filename == 'myfile.dat'

+ 12
- 0
tests/test_identity.py View File

@ -29,6 +29,18 @@ def test_identity_constructor(pEp, model):
assert str(alice) == str(model.alice)
# Covers PYADPT-124
def test_identity_update_cpt(pEp,model):
bob = pEp.Identity(model.bob.addr, model.bob.name)
bob.update()
assert bob.address == model.bob.addr
assert bob.username == model.bob.name
assert bob.user_id == 'TOFU_bob@peptest.org'
assert bob.fpr == ''
assert bob.comm_type == 0
assert bob.lang == ''
# TODO:
# These here are actually plenty of individual tests
# Identity.update


Loading…
Cancel
Save