Hello community,
here is the log from the commit of package python-pykeepass for
openSUSE:Factory checked in at 2020-08-05 20:28:07
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pykeepass (Old)
and /work/SRC/openSUSE:Factory/.python-pykeepass.new.3592 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pykeepass"
Wed Aug 5 20:28:07 2020 rev:4 rq:824365 version:3.2.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pykeepass/python-pykeepass.changes
2020-05-03 22:46:21.463047654 +0200
+++
/work/SRC/openSUSE:Factory/.python-pykeepass.new.3592/python-pykeepass.changes
2020-08-05 20:28:20.619065567 +0200
@@ -1,0 +2,15 @@
+Sat Aug 1 16:44:02 UTC 2020 - Atri Bhattacharya <[email protected]>
+
+- Update to version 3.2.1:
+ * Pin construct version to last supporting python2
+ * Hard dependency on pycryptodomex
+ * Fixed kp.groups, kp.entries not returning elements with
+ name/title None [gh#libkeepass/pykeepass#193].
+- Replace pycryptodome in BuildRequires and Requires, with
+ pycryptodomex.
+- Update version of python-construct in BuildRequires and
+ Requires.
+- Update %check section to run tests directly as recommended by
+ upstream.
+
+-------------------------------------------------------------------
Old:
----
pykeepass-3.2.0.tar.gz
New:
----
pykeepass-3.2.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-pykeepass.spec ++++++
--- /var/tmp/diff_new_pack.jqjNtn/_old 2020-08-05 20:28:21.599066078 +0200
+++ /var/tmp/diff_new_pack.jqjNtn/_new 2020-08-05 20:28:21.603066080 +0200
@@ -18,7 +18,7 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-pykeepass
-Version: 3.2.0
+Version: 3.2.1
Release: 0
Summary: Low-level library to interact with keepass databases
License: GPL-3.0-only
@@ -30,18 +30,19 @@
BuildRequires: fdupes
BuildRequires: python-rpm-macros
Requires: python-argon2-cffi
-Requires: python-construct >= 2.9.31
+Requires: python-construct >= 2.10.54
Requires: python-future
Requires: python-lxml
-Requires: python-pycryptodome
+Requires: python-pycryptodomex >= 3.6.2
Requires: python-python-dateutil
BuildArch: noarch
# SECTION test requirements
BuildRequires: %{python_module argon2-cffi}
-BuildRequires: %{python_module construct >= 2.9.31}
+BuildRequires: %{python_module construct >= 2.10.54}
BuildRequires: %{python_module future}
BuildRequires: %{python_module lxml}
-BuildRequires: %{python_module pycryptodome}
+BuildRequires: %{python_module pycryptodomex >= 3.6.2}
+BuildRequires: %{python_module pytest}
BuildRequires: %{python_module python-dateutil}
# /SECTION
%python_subpackages
@@ -62,13 +63,14 @@
%python_expand %fdupes %{buildroot}%{$python_sitelib}
%check
-export PYTHONPATH=${PWD}
-# python2 seg faults after 65 successful tests
-python3 setup.py test
+%python_expand export PYTHONPATH=%{buildroot}%{python3_sitelib}
+export PYTHONDONTWRITEBYTECODE=1
+%python_exec tests/tests.py
%files %{python_files}
%license LICENSE
%doc README.rst
-%{python_sitelib}/*
+%{python_sitelib}/pykeepass/
+%{python_sitelib}/pykeepass-%{version}-py%{python_version}.egg-info/
%changelog
++++++ pykeepass-3.2.0.tar.gz -> pykeepass-3.2.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-3.2.0/.gitignore
new/pykeepass-3.2.1/.gitignore
--- old/pykeepass-3.2.0/.gitignore 2020-01-19 05:13:52.000000000 +0100
+++ new/pykeepass-3.2.1/.gitignore 2020-07-20 00:47:29.000000000 +0200
@@ -5,3 +5,4 @@
build/
*.xml
Pipfile.lock
+*.kdbx
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-3.2.0/.travis.yml
new/pykeepass-3.2.1/.travis.yml
--- old/pykeepass-3.2.0/.travis.yml 2020-01-19 05:13:52.000000000 +0100
+++ new/pykeepass-3.2.1/.travis.yml 2020-07-20 00:47:29.000000000 +0200
@@ -3,13 +3,12 @@
jobs:
include:
- python: '2.7'
- - python: '3.4'
- python: '3.5'
- python: '3.6'
- python: '3.7'
- dist: xenial
+ - python: '3.8'
# command to install dependencies
-install: "pip install -r requirements.txt"
+install: pip install -r requirements.txt
# command to run tests
-script: "python -m unittest tests.tests"
+script: python -m unittest tests.tests
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-3.2.0/CHANGELOG.rst
new/pykeepass-3.2.1/CHANGELOG.rst
--- old/pykeepass-3.2.0/CHANGELOG.rst 2020-01-19 05:13:52.000000000 +0100
+++ new/pykeepass-3.2.1/CHANGELOG.rst 2020-07-20 00:47:29.000000000 +0200
@@ -1,4 +1,10 @@
-3.2.0 - 2019-01-18
+3.2.1 - 2020-07-19
+------------------
+- pin construct version to last supporting python2
+- hard dependency on pycryptodomex
+- fixed #193 - kp.groups, kp.entries not returning elements with name/title
None
+
+3.2.0 - 2020-01-18
------------------
- added PyKeePass.xml()
- added create_database()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-3.2.0/README.rst
new/pykeepass-3.2.1/README.rst
--- old/pykeepass-3.2.0/README.rst 2020-01-19 05:13:52.000000000 +0100
+++ new/pykeepass-3.2.1/README.rst 2020-07-20 00:47:29.000000000 +0200
@@ -226,7 +226,7 @@
**delete_binary** (id)
-where ``id`` is an int. Removes binary data from the database and deletes any
attachments that reference it. Since attachments reference binaries by their
positional index, attachments that reference binaries id > ``id`` will
automatically be decremented.
+where ``id`` is an int. Removes binary data from the database and deletes any
attachments that reference it. Since attachments reference binaries by their
positional index, attachments that reference binaries with id > ``id`` will
automatically be decremented.
**find_attachments** (id=None, filename=None, element=None, recursive=True,
regex=False, flags=None, history=False, first=False)
@@ -237,7 +237,7 @@
**binaries**
-list of bytes containing binary data. List index corresponds to attachment id.
+list of bytestrings containing binary data. List index corresponds to
attachment id.
**attachments**
@@ -245,7 +245,7 @@
**Entry.add_attachment** (id, filename)
-where ``id`` is an int and ``filename`` is a string. Creates a reference
using the given filename to a database binary. The existence of an binary with
the given id is not checked. Returns ``Attachment``.
+where ``id`` is an int and ``filename`` is a string. Creates a reference
using the given filename to a database binary. The existence of a binary with
the given id is not checked. Returns ``Attachment``.
**Entry.delete_attachment** (attachment)
@@ -314,10 +314,12 @@
Miscellaneous
-------------
-**read** (filename, password=None, keyfile=None, transformed_key=None)
+**read** (filename=None, password=None, keyfile=None, transformed_key=None)
where ``filename``, ``password``, and ``keyfile`` are strings. ``filename``
is the path to the database, ``password`` is the master password string, and
``keyfile`` is the path to the database keyfile. At least one of ``password``
and ``keyfile`` is required. Alternatively, the derived key can be supplied
directly through ``transformed_key``.
+Can raise ``CredentialsError``, ``HeaderChecksumError``, or
``PayloadChecksumError``.
+
**save** (filename=None)
where ``filename`` is the path of the file to save to. If ``filename`` is not
given, the path given in ``read`` will be used.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-3.2.0/pykeepass/exceptions.py
new/pykeepass-3.2.1/pykeepass/exceptions.py
--- old/pykeepass-3.2.0/pykeepass/exceptions.py 2020-01-19 05:13:52.000000000
+0100
+++ new/pykeepass-3.2.1/pykeepass/exceptions.py 2020-07-20 00:47:29.000000000
+0200
@@ -1,15 +1,19 @@
# ----- binary parsing exceptions -----
+class CredentialsError(Exception):
+ pass
+
+class PayloadChecksumError(Exception):
+ pass
+
+class HeaderChecksumError(Exception):
+ pass
+
# ----- pykeepass exceptions -----
+
class BinaryError(Exception):
pass
-# raised on invalid credentials, header corruption, payload corruption
-# this may be split into multiple exceptions when python-construct supports it
-class CredentialsIntegrityError(Exception):
- def __init__(self, msg='Credentials are wrong or integrity check failed'):
- super(Exception, self).__init__(msg)
-
# ----- Entry exceptions -----
# ----- Group exceptions -----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-3.2.0/pykeepass/kdbx_parsing/common.py
new/pykeepass-3.2.1/pykeepass/kdbx_parsing/common.py
--- old/pykeepass-3.2.0/pykeepass/kdbx_parsing/common.py 2020-01-19
05:13:52.000000000 +0100
+++ new/pykeepass-3.2.1/pykeepass/kdbx_parsing/common.py 2020-07-20
00:47:29.000000000 +0200
@@ -1,6 +1,6 @@
-from Crypto.Cipher import AES, ChaCha20, Salsa20
+from Cryptodome.Cipher import AES, ChaCha20, Salsa20
from .twofish import Twofish
-from Crypto.Util import Padding as CryptoPadding
+from Cryptodome.Util import Padding as CryptoPadding
import hashlib
from construct import (
Adapter, BitStruct, BitsSwapped, Container, Flag, Padding, ListContainer,
Mapping, GreedyBytes, Int32ul, Switch
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-3.2.0/pykeepass/kdbx_parsing/kdbx3.py
new/pykeepass-3.2.1/pykeepass/kdbx_parsing/kdbx3.py
--- old/pykeepass-3.2.0/pykeepass/kdbx_parsing/kdbx3.py 2020-01-19
05:13:52.000000000 +0100
+++ new/pykeepass-3.2.1/pykeepass/kdbx_parsing/kdbx3.py 2020-07-20
00:47:29.000000000 +0200
@@ -1,4 +1,3 @@
-#!/bin/env python3
# Evan Widloski - 2018-04-11
# keepass decrypt experimentation
@@ -129,7 +128,7 @@
UnpackedPayload = Reparsed(
Struct(
# validate payload decryption
- Checksum(
+ "cred_check" / Checksum(
Bytes(32),
lambda this:
this._._.header.value.dynamic_header.stream_start_bytes.data,
this,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-3.2.0/pykeepass/kdbx_parsing/kdbx4.py
new/pykeepass-3.2.1/pykeepass/kdbx_parsing/kdbx4.py
--- old/pykeepass-3.2.0/pykeepass/kdbx_parsing/kdbx4.py 2020-01-19
05:13:52.000000000 +0100
+++ new/pykeepass-3.2.1/pykeepass/kdbx_parsing/kdbx4.py 2020-07-20
00:47:29.000000000 +0200
@@ -1,4 +1,3 @@
-#!/bin/env python3
# Evan Widloski - 2018-04-11
# keepass decrypt experimentation
@@ -259,7 +258,7 @@
this._.header.data,
# exception=HeaderChecksumError,
),
- "hmac" / Checksum(
+ "cred_check" / Checksum(
Bytes(32),
compute_header_hmac_hash,
this,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-3.2.0/pykeepass/kdbx_parsing/twofish.py
new/pykeepass-3.2.1/pykeepass/kdbx_parsing/twofish.py
--- old/pykeepass-3.2.0/pykeepass/kdbx_parsing/twofish.py 2020-01-19
05:13:52.000000000 +0100
+++ new/pykeepass-3.2.1/pykeepass/kdbx_parsing/twofish.py 2020-07-20
00:47:29.000000000 +0200
@@ -25,8 +25,8 @@
__all__ = ['Twofish']
from . import pytwofish
-from Crypto.Util.strxor import strxor
-from Crypto.Util.Padding import pad
+from Cryptodome.Util.strxor import strxor
+from Cryptodome.Util.Padding import pad
MODE_ECB = 1
MODE_CBC = 2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-3.2.0/pykeepass/pykeepass.py
new/pykeepass-3.2.1/pykeepass/pykeepass.py
--- old/pykeepass-3.2.0/pykeepass/pykeepass.py 2020-01-19 05:13:52.000000000
+0100
+++ new/pykeepass-3.2.1/pykeepass/pykeepass.py 2020-07-20 00:47:29.000000000
+0200
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
# coding: utf-8
# FIXME python2
@@ -25,7 +24,6 @@
from pykeepass.kdbx_parsing.kdbx4 import kdf_uuids
from pykeepass.xpath import attachment_xp, entry_xp, group_xp, path_xp
-logging.basicConfig()
logger = logging.getLogger(__name__)
@@ -37,12 +35,35 @@
# FIXME python2
@python_2_unicode_compatible
class PyKeePass(object):
+ """Open a KeePass database
+
+ Args:
+ filename (:obj:`str`, optional): path to database. If None, the
+ path given when the database was opened is used.
+ password (:obj:`str`, optional): database password. If None,
+ database is assumed to have no password
+ keyfile (:obj:`str`, optional): path to keyfile. If None,
+ database is assumed to have no keyfile
+ transformed_key (:obj:`bytes`, optional): precomputed transformed
+ key.
+
+ Raises:
+ CredentialsError: raised when password/keyfile or transformed key
+ are wrong
+ HeaderChecksumError: raised when checksum in database header is
+ is wrong. e.g. database tampering or file corruption
+ PayloadChecksumError: raised when payload blocks checksum is wrong,
+ e.g. corruption during database saving
+
+ Todo:
+ - raise, no filename provided, database not open
+ """
def __init__(self, filename, password=None, keyfile=None,
transformed_key=None):
- self.filename = filename
self.read(
+ filename=filename,
password=password,
keyfile=keyfile,
transformed_key=transformed_key
@@ -57,9 +78,17 @@
def read(self, filename=None, password=None, keyfile=None,
transformed_key=None):
+ """
+ See class docstring.
+
+ Todo:
+ - raise, no filename provided, database not open
+ """
self.password = password
self.keyfile = keyfile
- if not filename:
+ if filename:
+ self.filename = filename
+ else:
filename = self.filename
try:
@@ -69,10 +98,31 @@
keyfile=keyfile,
transformed_key=transformed_key
)
- except ChecksumError:
- raise CredentialsIntegrityError
+ except ChecksumError as e:
+ if e.path in (
+ '(parsing) -> body -> cred_check', # KDBX4
+ '(parsing) -> cred_check' # KDBX3
+ ):
+ raise CredentialsError
+ elif e.path == '(parsing) -> body -> sha256':
+ raise HeaderChecksumError
+ elif e.path in (
+ '(parsing) -> body -> payload -> hmac_hash', # KDBX4
+ '(parsing) -> xml -> block_hash' # KDBX3
+ ):
+ raise PayloadChecksumError
+ else:
+ raise
def save(self, filename=None, transformed_key=None):
+ """Save current database object to disk.
+
+ Args:
+ filename (:obj:`str`, optional): path to database. If None, the
+ path given when the database was opened is used.
+ transformed_key (:obj:`bytes`, optional): precomputed transformed
+ key.
+ """
if not filename:
filename = self.filename
@@ -86,6 +136,8 @@
@property
def version(self):
+ """tuple: Length 2 tuple of ints containing major and minor versions.
+ Generally (3, 1) or (4, 0)."""
return (
self.kdbx.header.value.major_version,
self.kdbx.header.value.minor_version
@@ -93,10 +145,14 @@
@property
def encryption_algorithm(self):
+ """str: encryption algorithm used by database during decryption.
+ Can be one of 'aes256', 'chacha20', or 'twofish'."""
return self.kdbx.header.value.dynamic_header.cipher_id.data
@property
def kdf_algorithm(self):
+ """str: key derivation algorithm used by database during decryption.
+ Can be one of 'aeskdf', 'argon2', or 'aeskdf'"""
if self.version == (3, 1):
return 'aeskdf'
elif self.version == (4, 0):
@@ -108,25 +164,38 @@
@property
def transformed_key(self):
+ """bytes: transformed key used in database decryption. May be cached
+ and passed to `open` for faster database opening"""
return self.kdbx.body.transformed_key
@property
def tree(self):
+ """lxml.etree._ElementTree: database XML payload"""
return self.kdbx.body.payload.xml
@property
def root_group(self):
+ """Group: root Group of database"""
return self.find_groups(path='', first=True)
@property
def groups(self):
- return self.find_groups_by_name('.*', regex=True)
+ """:obj:`list` of :obj:`Group`: list of all Group objects in database
+ """
+ return self._xpath('//Group', cast=True)
@property
def entries(self):
- return self.find_entries_by_title('.*', regex=True)
+ """:obj:`list` of :obj:`Entry`: list of all Entry objects in database,
+ excluding history"""
+ return self._xpath('//Entry', cast=True)
def xml(self):
+ """Get XML part of database as string
+
+ Returns:
+ str: XML payload section of database.
+ """
return etree.tostring(
self.tree,
pretty_print=True,
@@ -134,12 +203,13 @@
encoding='unicode'
)
- def dump_xml(self, outfile):
- '''
- Dump the content of the database to a file
- NOTE The file is unencrypted!
- '''
- with open(outfile, 'wb') as f:
+ def dump_xml(self, filename):
+ """ Dump the contents of the database to file as XML
+
+ Args:
+ filename (str): path to output file
+ """
+ with open(filename, 'wb') as f:
f.write(
etree.tostring(
self.tree,
@@ -151,6 +221,26 @@
def _xpath(self, xpath_str, tree=None, first=False, history=False,
cast=False, **kwargs):
+ """Look up elements in the XML payload and return corresponding object.
+
+ Internal function which searches the payload lxml ElementTree for
+ elements via XPath. Matched entry, group, and attachment elements are
+ automatically cast to their corresponding objects, otherwise an error
+ is raised.
+
+ Args:
+ xpath_str (str): XPath query for finding element(s)
+ tree (:obj:`_ElementTree`, :obj:`Element`, optional): use this
+ element as root node when searching
+ first (bool): If True, function returns first result or None. If
+ False, function returns list of matches or empty list. Default
+ is False.
+ history (bool): If True, history entries are included in results.
+ Default is False.
+ cast (bool): If True, matches are instead instantiated as
+ pykeepass Group, Entry, or Attachment objects. An exception
+ is raised if a match cannot be cast. Default is False.
+ """
if tree is None:
tree = self.tree
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-3.2.0/requirements.txt
new/pykeepass-3.2.1/requirements.txt
--- old/pykeepass-3.2.0/requirements.txt 2020-01-19 05:13:52.000000000
+0100
+++ new/pykeepass-3.2.1/requirements.txt 2020-07-20 00:47:29.000000000
+0200
@@ -1,6 +1,6 @@
lxml==4.3.5
-pycryptodome==3.9.4
-construct==2.9.51
+pycryptodomex==3.9.4
+construct==2.10.54
argon2-cffi==19.2.0
python-dateutil==2.8.0
future==0.17.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-3.2.0/setup.py new/pykeepass-3.2.1/setup.py
--- old/pykeepass-3.2.0/setup.py 2020-01-19 05:13:52.000000000 +0100
+++ new/pykeepass-3.2.1/setup.py 2020-07-20 00:47:29.000000000 +0200
@@ -3,7 +3,7 @@
setup(
name="pykeepass",
- version="3.2.0",
+ version="3.2.1",
license="GPL3",
description="Python library to interact with keepass databases "
"(supports KDBX3 and KDBX4)",
@@ -14,9 +14,10 @@
packages=find_packages(),
install_requires=[
"python-dateutil",
- "construct",
+ # FIXME python2 - last version to support python2
+ "construct==2.10.54",
"argon2_cffi",
- "pycryptodome",
+ "pycryptodomex>=3.6.2",
"lxml",
# FIXME python2
"future"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pykeepass-3.2.0/tests/tests.py
new/pykeepass-3.2.1/tests/tests.py
--- old/pykeepass-3.2.0/tests/tests.py 2020-01-19 05:13:52.000000000 +0100
+++ new/pykeepass-3.2.1/tests/tests.py 2020-07-20 00:47:29.000000000 +0200
@@ -18,7 +18,7 @@
from pykeepass.exceptions import BinaryError
from pykeepass.group import Group
from pykeepass.kdbx_parsing import KDBX
-from pykeepass.exceptions import BinaryError, CredentialsIntegrityError
+from pykeepass.exceptions import BinaryError, CredentialsError
"""
Missing Tests:
@@ -45,11 +45,21 @@
# get some things ready before testing
def setUp(self):
+ shutil.copy(
+ os.path.join(base_dir, self.database),
+ os.path.join(base_dir, 'change_creds.kdbx')
+ )
self.kp = PyKeePass(
os.path.join(base_dir, self.database),
password=self.password,
keyfile=os.path.join(base_dir, self.keyfile)
)
+ # for tests which modify the database, use this
+ self.kp_tmp = PyKeePass(
+ os.path.join(base_dir, 'change_creds.kdbx'),
+ password=self.password,
+ keyfile=os.path.join(base_dir, self.keyfile)
+ )
class KDBX4Tests(KDBX3Tests):
@@ -687,30 +697,15 @@
class PyKeePassTests3(KDBX3Tests):
- def setUp(self):
- shutil.copy(
- os.path.join(base_dir, self.database),
- os.path.join(base_dir, 'change_creds.kdbx')
- )
- self.kp = PyKeePass(
- os.path.join(base_dir, self.database),
- password=self.password,
- keyfile=os.path.join(base_dir, self.keyfile)
- )
- self.kp_tmp = PyKeePass(
- os.path.join(base_dir, 'change_creds.kdbx'),
- password=self.password,
- keyfile=os.path.join(base_dir, self.keyfile)
- )
def test_set_credentials(self):
self.kp_tmp.password = 'f00bar'
self.kp_tmp.keyfile = os.path.join(base_dir, 'change.key')
self.kp_tmp.save()
self.kp_tmp = PyKeePass(
- os.path.join(base_dir, 'change_creds.kdbx'),
- password='f00bar',
- keyfile=os.path.join(base_dir, 'change.key')
+ self.kp_tmp.filename,
+ 'f00bar',
+ self.kp_tmp.keyfile
)
results = self.kp.find_entries_by_username('foobar_user', first=True)
@@ -727,20 +722,35 @@
class BugRegressionTests3(KDBX3Tests):
- def test_129(self):
+ def test_issue129(self):
# issue 129 - protected multiline string fields lose newline
e = self.kp.find_entries(title='foobar_entry', first=True)
self.assertEqual(e.get_custom_property('multiline'), 'hello\nworld')
def test_pull102(self):
# PR 102 - entries are protected after save
- # reset self.kp
+ # reset self.kp_tmp
self.setUp()
- e = self.kp.find_entries(title='foobar_entry', first=True)
+ e = self.kp_tmp.find_entries(title='foobar_entry', first=True)
self.assertEqual(e.password, 'foobar')
- self.kp.save()
+ self.kp_tmp.save()
self.assertEqual(e.password, 'foobar')
+ def test_issue193(self):
+ # issue 193 - kp.entries doesn't return entries with title=None
+ e = self.kp.add_entry(self.kp.root_group, 'test', 'user', 'pass')
+ prop = e._xpath('String/Key[text()="Title"]/..', first=True)
+ e._element.remove(prop)
+ self.assertTrue(e.title is None)
+ self.assertTrue(e in self.kp.entries)
+ # also test for kp.groups
+ g = self.kp.add_group(self.kp.root_group, 'test_g')
+ prop = g._xpath('Name', first=True)
+ g._element.remove(prop)
+ self.assertTrue(g.name is None)
+ self.assertTrue(g in self.kp.groups)
+
+
class EntryFindTests4(KDBX4Tests, EntryFindTests3):
pass
@@ -882,7 +892,7 @@
)
def test_open_error(self):
- with self.assertRaises(CredentialsIntegrityError):
+ with self.assertRaises(CredentialsError):
database = 'test4.kdbx'
invalid_password = 'foobar'
keyfile = os.path.join(base_dir, 'test4.key')
@@ -891,7 +901,7 @@
password=invalid_password,
keyfile=keyfile
)
- with self.assertRaises(CredentialsIntegrityError):
+ with self.assertRaises(CredentialsError):
database = 'test4.kdbx'
password = 'password'
invalid_keyfile = os.path.join(base_dir, 'test3.key')