Skip to content

Commit

Permalink
Use modern Python3 syntax (#372)
Browse files Browse the repository at this point in the history
* Use modern Python syntax

These edits were suggested by Ruff linter. I've selected only the most
obvious fixes to make it easier to review.

* Sort imports

Imports are sorted using default ruff linter configuration.

* Fix merge issue

* Fix merge issue in pykeepass.py
  • Loading branch information
ekuler authored Mar 11, 2024
1 parent 18ec462 commit e43ca6c
Show file tree
Hide file tree
Showing 14 changed files with 160 additions and 75 deletions.
2 changes: 0 additions & 2 deletions pykeepass/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
from __future__ import absolute_import
from .pykeepass import PyKeePass, create_database

from .version import __version__

__all__ = ["PyKeePass", "create_database", "__version__"]
3 changes: 2 additions & 1 deletion pykeepass/attachment.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from . import entry
from .exceptions import BinaryError

class Attachment(object):

class Attachment:
def __init__(self, element=None, kp=None, id=None, filename=None):
self._element = element
self._kp = kp
Expand Down
6 changes: 4 additions & 2 deletions pykeepass/baseelement.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import base64
import uuid
from datetime import datetime, timezone


from lxml import etree
from lxml.builder import E
from datetime import datetime, timezone


class BaseElement():
class BaseElement:
"""Entry and Group inherit from this class"""

def __init__(self, element, kp=None, icon=None, expires=False,
Expand Down
6 changes: 3 additions & 3 deletions pykeepass/entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def __init__(self, title=None, username=None, password=None, url=None,
)
if tags:
self._element.append(
E.Tags(';'.join(tags) if type(tags) is list else tags)
E.Tags(';'.join(tags) if isinstance(tags, list) else tags)
)
self._element.append(
E.AutoType(
Expand Down Expand Up @@ -221,7 +221,7 @@ def tags(self):
@tags.setter
def tags(self, value, sep=';'):
# Accept both str or list
v = sep.join(value if type(value) is list else [value])
v = sep.join(value if isinstance(value, list) else [value])
return self._set_subelement_text('Tags', v)

@property
Expand Down Expand Up @@ -403,7 +403,7 @@ def delete_history(self, history_entry=None, all=False):

def __str__(self):
# filter out NoneTypes and join into string
pathstr = '/'.join('' if p==None else p for p in self.path)
pathstr = '/'.join('' if p is None else p for p in self.path)
return 'Entry: "{} ({})"'.format(pathstr, self.username)


Expand Down
2 changes: 1 addition & 1 deletion pykeepass/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ class BinaryError(Exception):
# ----- RecycleBin exceptions -----

class UnableToSendToRecycleBin(Exception):
pass
pass
6 changes: 3 additions & 3 deletions pykeepass/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
from lxml.etree import Element, _Element
from lxml.objectify import ObjectifiedElement

from .entry import Entry
from .baseelement import BaseElement
from .entry import Entry


class Group(BaseElement):
Expand Down Expand Up @@ -93,13 +93,13 @@ def append(self, entries):
Args:
entries (:obj:`Entry` or :obj:`list` of :obj:`Entry`)
"""
if type(entries) is list:
if isinstance(entries, list):
for e in entries:
self._element.append(e._element)
else:
self._element.append(entries._element)

def __str__(self):
# filter out NoneTypes and join into string
pathstr = '/'.join('' if p==None else p for p in self.path)
pathstr = '/'.join('' if p is None else p for p in self.path)
return 'Group: "{}"'.format(pathstr)
41 changes: 26 additions & 15 deletions pykeepass/kdbx_parsing/common.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,32 @@
from Cryptodome.Cipher import AES, ChaCha20, Salsa20
from .twofish import Twofish
from Cryptodome.Util import Padding as CryptoPadding
import base64
import codecs
import hashlib
import logging
import re
import zlib
from binascii import Error as BinasciiError
from collections import OrderedDict
from copy import deepcopy
from io import BytesIO

from construct import (
Adapter, BitStruct, BitsSwapped, Container, Flag, Padding, ListContainer, Mapping, GreedyBytes, Int32ul, Switch
Adapter,
BitsSwapped,
BitStruct,
Container,
Flag,
GreedyBytes,
Int32ul,
ListContainer,
Mapping,
Padding,
Switch,
)
from Cryptodome.Cipher import AES, ChaCha20, Salsa20
from Cryptodome.Util import Padding as CryptoPadding
from lxml import etree
from copy import deepcopy
import base64
from binascii import Error as BinasciiError
import unicodedata
import zlib
import re
import codecs
from io import BytesIO
from collections import OrderedDict
import logging

from .twofish import Twofish

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -208,7 +219,7 @@ def _decode(self, tree, con, path):
result = cipher.decrypt(base64.b64decode(elem.text)).decode('utf-8')
# strip invalid XML characters - https://stackoverflow.com/questions/8733233
result = re.sub(
u'[^\u0020-\uD7FF\u0009\u000A\u000D\uE000-\uFFFD\U00010000-\U0010FFFF]+',
'[^\u0020-\uD7FF\u0009\u000A\u000D\uE000-\uFFFD\U00010000-\U0010FFFF]+',
'',
result
)
Expand Down
8 changes: 5 additions & 3 deletions pykeepass/kdbx_parsing/kdbx.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from construct import Struct, Switch, Bytes, Int16ul, RawCopy, Check, this
from .kdbx3 import DynamicHeader as DynamicHeader3
from construct import Bytes, Check, Int16ul, RawCopy, Struct, Switch, this

from .kdbx3 import Body as Body3
from .kdbx4 import DynamicHeader as DynamicHeader4
from .kdbx3 import DynamicHeader as DynamicHeader3
from .kdbx4 import Body as Body4
from .kdbx4 import DynamicHeader as DynamicHeader4


# verify file signature
def check_signature(ctx):
Expand Down
44 changes: 37 additions & 7 deletions pykeepass/kdbx_parsing/kdbx3.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,48 @@
# keepass decrypt experimentation

import hashlib

from construct import (
Byte, Bytes, Int16ul, Int32ul, Int64ul, RepeatUntil, GreedyBytes, Struct,
this, Mapping, Switch, Prefixed, Padding, Checksum, Computed, IfThenElse,
Pointer, Tell, len_, If
Byte,
Bytes,
Checksum,
Computed,
GreedyBytes,
If,
IfThenElse,
Int16ul,
Int32ul,
Int64ul,
Mapping,
Padding,
Pointer,
Prefixed,
RepeatUntil,
Struct,
Switch,
Tell,
len_,
this,
)

from .common import (
aes_kdf, AES256Payload, ChaCha20Payload, TwoFishPayload, Concatenated,
DynamicDict, compute_key_composite, Decompressed, Reparsed,
compute_master, CompressionFlags, XML, CipherId, ProtectedStreamId, Unprotect
XML,
AES256Payload,
ChaCha20Payload,
CipherId,
CompressionFlags,
Concatenated,
Decompressed,
DynamicDict,
ProtectedStreamId,
Reparsed,
TwoFishPayload,
Unprotect,
aes_kdf,
compute_key_composite,
compute_master,
)


# -------------------- Key Derivation --------------------

# https://github.com/keepassxreboot/keepassxc/blob/8324d03f0a015e62b6182843b4478226a5197090/src/format/KeePass2.cpp#L24-L26
Expand Down
51 changes: 42 additions & 9 deletions pykeepass/kdbx_parsing/kdbx4.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,55 @@
# Evan Widloski - 2018-04-11
# keepass decrypt experimentation

import struct
import hashlib
import argon2
import hmac
import struct

import argon2
from construct import (
Byte, Bytes, Int32ul, RepeatUntil, GreedyBytes, Struct, this, Mapping,
Switch, Flag, Prefixed, Int64ul, Int32sl, Int64sl, GreedyString, Padding,
Peek, Checksum, Computed, IfThenElse, Pointer, Tell, If
Byte,
Bytes,
Checksum,
Computed,
Flag,
GreedyBytes,
GreedyString,
If,
IfThenElse,
Int32sl,
Int32ul,
Int64sl,
Int64ul,
Mapping,
Padding,
Peek,
Pointer,
Prefixed,
RepeatUntil,
Struct,
Switch,
Tell,
this,
)

from .common import (
aes_kdf, Concatenated, AES256Payload, ChaCha20Payload, TwoFishPayload,
DynamicDict, compute_key_composite, Reparsed, Decompressed,
compute_master, CompressionFlags, XML, CipherId, ProtectedStreamId, Unprotect
XML,
AES256Payload,
ChaCha20Payload,
CipherId,
CompressionFlags,
Concatenated,
Decompressed,
DynamicDict,
ProtectedStreamId,
Reparsed,
TwoFishPayload,
Unprotect,
aes_kdf,
compute_key_composite,
compute_master,
)


# -------------------- Key Derivation --------------------

# https://github.com/keepassxreboot/keepassxc/blob/bc55974ff304794e53c925442784c50a2fdaf6ee/src/format/KeePass2.cpp#L30-L33
Expand Down
1 change: 1 addition & 0 deletions pykeepass/kdbx_parsing/pytwofish.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ def get_key_size(self):

import struct


def rotr32(x, n):
return (x >> n) | ((x << (32 - n)) & 0xFFFFFFFF)

Expand Down
5 changes: 3 additions & 2 deletions pykeepass/kdbx_parsing/twofish.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@

__all__ = ['Twofish']

from . import pytwofish
from Cryptodome.Util.strxor import strxor
from Cryptodome.Util.Padding import pad
from Cryptodome.Util.strxor import strxor

from . import pytwofish

MODE_ECB = 1
MODE_CBC = 2
Expand Down
Loading

0 comments on commit e43ca6c

Please sign in to comment.