Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-pykeepass for 
openSUSE:Factory checked in at 2022-06-25 10:24:27
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pykeepass (Old)
 and      /work/SRC/openSUSE:Factory/.python-pykeepass.new.1548 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pykeepass"

Sat Jun 25 10:24:27 2022 rev:8 rq:984909 version:4.0.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pykeepass/python-pykeepass.changes        
2022-06-03 14:17:18.597366665 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-pykeepass.new.1548/python-pykeepass.changes  
    2022-06-25 10:24:49.922722567 +0200
@@ -1,0 +2,7 @@
+Tue Jun 21 23:10:46 UTC 2022 - Atri Bhattacharya <badshah...@gmail.com>
+
+- Update to version 4.0.3:
+  * Add otp support.
+  * Add debug_setup() function.
+
+-------------------------------------------------------------------

Old:
----
  pykeepass-4.0.2.tar.gz

New:
----
  pykeepass-4.0.3.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-pykeepass.spec ++++++
--- /var/tmp/diff_new_pack.uC6mgW/_old  2022-06-25 10:24:50.682723652 +0200
+++ /var/tmp/diff_new_pack.uC6mgW/_new  2022-06-25 10:24:50.686723658 +0200
@@ -18,7 +18,7 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-pykeepass
-Version:        4.0.2
+Version:        4.0.3
 Release:        0
 Summary:        Low-level library to interact with keepass databases
 License:        GPL-3.0-only

++++++ pykeepass-4.0.2.tar.gz -> pykeepass-4.0.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pykeepass-4.0.2/CHANGELOG.rst 
new/pykeepass-4.0.3/CHANGELOG.rst
--- old/pykeepass-4.0.2/CHANGELOG.rst   2022-05-22 01:06:31.000000000 +0200
+++ new/pykeepass-4.0.3/CHANGELOG.rst   2022-06-21 18:19:30.000000000 +0200
@@ -1,10 +1,14 @@
-4.0.2 -
+4.0.3 - 2022-06-21
+------------------
+- add otp support
+- add debug_setup() function
+
+4.0.2 - 2022-05-21
 ------------------
 - added support for argon2id key derivation function
 - added credential expiry functions
 - fixes #223 - safe saving
 
-
 4.0.1 - 2021-05-22
 ------------------
 - added Entry.delete_history()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pykeepass-4.0.2/README.rst 
new/pykeepass-4.0.3/README.rst
--- old/pykeepass-4.0.2/README.rst      2022-05-22 01:06:31.000000000 +0200
+++ new/pykeepass-4.0.3/README.rst      2022-06-21 18:19:30.000000000 +0200
@@ -22,7 +22,7 @@
 .. _#pykeepass\:matrix.org: https://matrix.to/#/%23pykeepass:matrix.org 
 
 Example
---------------
+-------
 .. code:: python
 
    from pykeepass import PyKeePass
@@ -58,12 +58,15 @@
    >>> kp.save()
 
 
+..
+    TODO: add `Entry` and `Group` sections to document attributes of each
+
 Finding Entries
-----------------------
+---------------
 
-**find_entries** (title=None, username=None, password=None, url=None, 
notes=None, path=None, uuid=None, tags=None, string=None, group=None, 
recursive=True, regex=False, flags=None, history=False, first=False)
+**find_entries** (title=None, username=None, password=None, url=None, 
notes=None, otp=None, path=None, uuid=None, tags=None, string=None, group=None, 
recursive=True, regex=False, flags=None, history=False, first=False)
 
-Returns entries which match all provided parameters, where ``title``, 
``username``, ``password``, ``url``, ``notes``, and ``autotype_sequence`` are 
strings, ``path`` is a list, ``string`` is a dict, ``autotype_enabled`` is a 
boolean, ``uuid`` is a ``uuid.UUID`` and ``tags`` is a list of strings.  This 
function has optional ``regex`` boolean and ``flags`` string arguments, which 
means to interpret search strings as `XSLT style`_ regular expressions with 
`flags`_.
+Returns entries which match all provided parameters, where ``title``, 
``username``, ``password``, ``url``, ``notes``, ``otp``, and 
``autotype_sequence`` are strings, ``path`` is a list, ``string`` is a dict, 
``autotype_enabled`` is a boolean, ``uuid`` is a ``uuid.UUID`` and ``tags`` is 
a list of strings.  This function has optional ``regex`` boolean and ``flags`` 
string arguments, which means to interpret search strings as `XSLT style`_ 
regular expressions with `flags`_.
 
 .. _XSLT style: https://www.xml.com/pub/a/2003/06/04/tr.html
 .. _flags: https://www.w3.org/TR/xpath-functions/#flags 
@@ -101,14 +104,19 @@
    'facebook.com'
    >>> entry.title
    'foo_entry'
+   >>> entry.title = 'hello'
 
    >>> group = kp.find_group(name='social', first=True)
    >>> kp.find_entries(title='facebook', group=group, recursive=False, 
first=True)
    Entry: "social/facebook (myusername)"
 
+   >>> entry.otp
+   
otpauth://totp/test:lkj?secret=TEST%3D%3D%3D%3D&period=30&digits=6&issuer=test
+
+
 
 Finding Groups
-----------------------
+--------------
 
 **find_groups** (name=None, path=None, uuid=None, notes=None, group=None, 
recursive=True, regex=False, flags=None, first=False)
 
@@ -156,7 +164,7 @@
 
 
 Entry Functions
---------------
+---------------
 **add_entry** (destination_group, title, username, password, url=None, 
notes=None, tags=None, expiry_time=None, icon=None, force_creation=False)
 
 **delete_entry** (entry)
@@ -206,7 +214,7 @@
 
 **empty_group** (group)
 
-delete all entries and subgroups of a group.  ``group`` is an instance of 
``Group**.
+delete all entries and subgroups of a group.  ``group`` is an instance of 
``Group``.
 
 **move_group** (group, destination_group)
 
@@ -360,7 +368,7 @@
 
 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**.
+Can raise ``CredentialsError``, ``HeaderChecksumError``, or 
``PayloadChecksumError``.
 
 **reload** ()
 
@@ -402,7 +410,20 @@
 
 pretty print database XML to file
 
-Tests
--------------
 
-To run them issue :code:`python tests/tests.py`
+Tests and Debugging
+-------------------
+
+Run tests with :code:`python tests/tests.py`
+
+Enable debugging when doing tests in console:
+
+   >>> from pykeepass.pykeepass import debug_setup
+   >>> debug_setup()
+   >>> kp.entries[0]
+   DEBUG:pykeepass.pykeepass:xpath query: //Entry
+   DEBUG:pykeepass.pykeepass:xpath query: (ancestor::Group)[last()]
+   DEBUG:pykeepass.pykeepass:xpath query: (ancestor::Group)[last()]
+   DEBUG:pykeepass.pykeepass:xpath query: String/Key[text()="Title"]/../Value
+   DEBUG:pykeepass.pykeepass:xpath query: 
String/Key[text()="UserName"]/../Value
+   Entry: "root_entry (foobar_user)"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pykeepass-4.0.2/pykeepass/entry.py 
new/pykeepass-4.0.3/pykeepass/entry.py
--- old/pykeepass-4.0.2/pykeepass/entry.py      2022-05-22 01:06:31.000000000 
+0200
+++ new/pykeepass-4.0.3/pykeepass/entry.py      2022-06-21 18:19:30.000000000 
+0200
@@ -24,7 +24,8 @@
     'IconID',
     'Times',
     'History',
-    'Notes'
+    'Notes',
+    'otp'
 ]
 
 # FIXME python2
@@ -32,7 +33,7 @@
 class Entry(BaseElement):
 
     def __init__(self, title=None, username=None, password=None, url=None,
-                 notes=None, tags=None, expires=False, expiry_time=None,
+                 notes=None, otp=None, tags=None, expires=False, 
expiry_time=None,
                  icon=None, autotype_sequence=None, autotype_enabled=True,
                  element=None, kp=None):
 
@@ -55,6 +56,8 @@
                 self._element.append(E.String(E.Key('URL'), E.Value(url)))
             if notes:
                 self._element.append(E.String(E.Key('Notes'), E.Value(notes)))
+            if otp:
+                self._element.append(E.String(E.Key('otp'), E.Value(otp)))
             if tags:
                 self._element.append(
                     E.Tags(';'.join(tags) if type(tags) is list else tags)
@@ -178,6 +181,14 @@
         return self._set_subelement_text('Tags', v)
 
     @property
+    def otp(self):
+        return self._get_string_field('otp')
+
+    @otp.setter
+    def otp(self, value):
+        return self._set_string_field('otp', value)
+
+    @property
     def history(self):
         if self._element.find('History') is not None:
             return [HistoryEntry(element=x, kp=self._kp) for x in 
self._element.find('History').findall('Entry')]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pykeepass-4.0.2/pykeepass/pykeepass.py 
new/pykeepass-4.0.3/pykeepass/pykeepass.py
--- old/pykeepass-4.0.2/pykeepass/pykeepass.py  2022-05-22 01:06:31.000000000 
+0200
+++ new/pykeepass-4.0.3/pykeepass/pykeepass.py  2022-06-21 18:19:30.000000000 
+0200
@@ -365,8 +365,8 @@
             for key, value in kwargs.items():
                 if key not in keys_xp[regex].keys():
                     raise TypeError('Invalid keyword argument 
"{}"'.format(key))
-
-                xp += keys_xp[regex][key].format(value, flags=flags)
+                if value is not None:
+                    xp += keys_xp[regex][key].format(value, flags=flags)
 
         res = self._xpath(
             xp,
@@ -614,7 +614,7 @@
 
     def add_entry(self, destination_group, title, username,
                   password, url=None, notes=None, expiry_time=None,
-                  tags=None, icon=None, force_creation=False):
+                  tags=None, otp=None, icon=None, force_creation=False):
 
         entries = self.find_entries(
             title=title,
@@ -637,6 +637,7 @@
                 username=username,
                 password=password,
                 notes=notes,
+                otp=otp,
                 url=url,
                 tags=tags,
                 expires=True if expiry_time else False,
@@ -911,3 +912,9 @@
 
     keepass_instance.save(transformed_key)
     return keepass_instance
+
+def debug_setup():
+    """Convenience function to quickly enable debug messages"""
+
+    logging.basicConfig()
+    logger.setLevel(logging.DEBUG)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pykeepass-4.0.2/pykeepass/version.py 
new/pykeepass-4.0.3/pykeepass/version.py
--- old/pykeepass-4.0.2/pykeepass/version.py    2022-05-22 01:06:31.000000000 
+0200
+++ new/pykeepass-4.0.3/pykeepass/version.py    2022-06-21 18:19:30.000000000 
+0200
@@ -1,3 +1,3 @@
-__version__ = "4.0.2"
+__version__ = "4.0.3"
 
 __all__= ["__version__"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pykeepass-4.0.2/pykeepass/xpath.py 
new/pykeepass-4.0.3/pykeepass/xpath.py
--- old/pykeepass-4.0.2/pykeepass/xpath.py      2022-05-22 01:06:31.000000000 
+0200
+++ new/pykeepass-4.0.3/pykeepass/xpath.py      2022-06-21 18:19:30.000000000 
+0200
@@ -35,6 +35,7 @@
         'string': '/String/Key[text()="{}"]/../Value[text()="{}"]/../..',
         'autotype_sequence': '/AutoType/DefaultSequence[text()="{}"]/../..',
         'autotype_enabled': '/AutoType/Enabled[text()="{}"]/../..',
+        'otp': '/String/Key[text()="otp"]/../Value[text()="{}"]/../..',
     },
     True: {
         'title': '/String/Key[text()="Title"]/../Value[re:test(text(), "{}", 
"{flags}")]/../..',
@@ -47,6 +48,7 @@
         'string': '/String/Key[text()="{}"]/../Value[re:test(text(), "{}", 
"{flags}")]/../..',
         'autotype_sequence': '/AutoType/DefaultSequence[re:test(text(), "{}", 
"{flags}")]/../..',
         'autotype_enabled': '/AutoType/Enabled[re:test(text(), "{}", 
"{flags}")]/../..',
+        'otp': '/String/Key[text()="otp"]/../Value[re:test(text(), "{}", 
"{flags}")]/../..',
     }
 }
 
Binary files old/pykeepass-4.0.2/tests/test3.kdbx and 
new/pykeepass-4.0.3/tests/test3.kdbx differ
Binary files old/pykeepass-4.0.2/tests/test4.kdbx and 
new/pykeepass-4.0.3/tests/test4.kdbx differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pykeepass-4.0.2/tests/tests.py 
new/pykeepass-4.0.3/tests/tests.py
--- old/pykeepass-4.0.2/tests/tests.py  2022-05-22 01:06:31.000000000 +0200
+++ new/pykeepass-4.0.3/tests/tests.py  2022-06-21 18:19:30.000000000 +0200
@@ -151,6 +151,11 @@
         results = self.kp.find_entries(autotype_enabled=True)
         self.assertEqual(len(results), len(self.kp.entries) - 1)
 
+    def test_find_entries_by_otp(self):
+        results = self.kp.find_entries(otp='otpsecret', regex=True, flags='i')
+        self.assertEqual(len(results), 1)
+        self.assertEqual('foobar_entry', results[0].title)
+
     def test_find_entries(self):
         results = self.kp.find_entries(title='Root_entry', regex=True)
         self.assertEqual(len(results), 0)
@@ -434,6 +439,7 @@
             url='url',
             notes='notes',
             tags='tags',
+            otp='otp',
             expires=True,
             expiry_time=time,
             icon=icons.KEY,
@@ -446,6 +452,7 @@
         self.assertEqual(entry.url, 'url')
         self.assertEqual(entry.notes, 'notes')
         self.assertEqual(entry.tags, ['tags'])
+        self.assertEqual(entry.otp, 'otp')
         self.assertEqual(entry.expires, True)
         self.assertEqual(entry.expiry_time,
                          
time.replace(tzinfo=tz.gettz()).astimezone(tz.gettz('UTC')))
@@ -498,6 +505,7 @@
         entry.icon = icons.GLOBE
         entry.set_custom_property('foo', 'bar')
         entry.set_custom_property('multiline', 'hello\nworld')
+        entry.otp = "otpsecret"
 
         self.assertEqual(entry.title, changed_string + 'title')
         self.assertEqual(entry.username, changed_string + 'username')
@@ -507,6 +515,7 @@
         self.assertEqual(entry.icon, icons.GLOBE)
         self.assertEqual(entry.get_custom_property('foo'), 'bar')
         self.assertEqual(entry.get_custom_property('multiline'), 
'hello\nworld')
+        self.assertEqual(entry.otp, 'otpsecret')
         self.assertIn('foo', entry.custom_properties)
         entry.delete_custom_property('foo')
         self.assertEqual(entry.get_custom_property('foo'), None)
@@ -920,6 +929,14 @@
         self.kp_tmp.keyfile = self.keyfile_tmp
         PyKeePass(stream, self.password, self.keyfile_tmp)
 
+    def test_issue308(self):
+        # find_entries/find_groups() break when supplied None values directly
+
+        results = self.kp.find_entries(title='foobar_entry')
+        results2 = self.kp.find_entries(title='foobar_entry', username=None)
+
+        self.assertEqual(results, results2)
+
 
 class EntryFindTests4(KDBX4Tests, EntryFindTests3):
     pass

Reply via email to