summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDonald Stufft <donald@stufft.io>2014-12-05 22:56:45 -0500
committerDonald Stufft <donald@stufft.io>2014-12-05 22:56:45 -0500
commit16637c90d03fd6f5b9c83cb97e7ba88d39c0d8d6 (patch)
treec5c4b2a78a29eefa5ce2e97217f06fda4d4371fe
parent816a9130efd20e877166c08eccaf11ce4139b90e (diff)
downloadpy-bcrypt-git-16637c90d03fd6f5b9c83cb97e7ba88d39c0d8d6.tar.gz
Lazily load the library upon first use
-rw-r--r--bcrypt/__init__.py28
1 files changed, 26 insertions, 2 deletions
diff --git a/bcrypt/__init__.py b/bcrypt/__init__.py
index 8cd02f6..bae9c35 100644
--- a/bcrypt/__init__.py
+++ b/bcrypt/__init__.py
@@ -19,8 +19,10 @@ from __future__ import division
import binascii
import os
import sys
+import threading
from cffi import FFI
+from cffi.verifier import Verifier
import six
@@ -51,6 +53,25 @@ def _create_modulename(cdef_sources, source, sys_version):
return '_bcrypt_cffi_{0}{1}'.format(k1, k2)
+class LazyLibrary(object):
+ def __init__(self, ffi):
+ self._ffi = ffi
+ self._lib = None
+ self._lock = threading.Lock()
+
+ def __getattr__(self, name):
+ if self._lib is None:
+ with self._lock:
+ # We no cover this because this guard is here just to protect
+ # against concurrent loads of this library. This is pretty
+ # hard to test and the logic is simple and should hold fine
+ # without testing (famous last words).
+ if self._lib is None: # pragma: no cover
+ self._lib = self._ffi.verifier.load_library()
+
+ return getattr(self._lib, name)
+
+
_crypt_blowfish_dir = "crypt_blowfish-1.2"
_bundled_dir = os.path.join(os.path.dirname(__file__), _crypt_blowfish_dir)
@@ -68,8 +89,8 @@ SOURCE = """
_ffi = FFI()
_ffi.cdef(CDEF)
-
-_bcrypt_lib = _ffi.verify(
+_ffi.verifier = Verifier(
+ _ffi,
SOURCE,
sources=[
str(os.path.join(_bundled_dir, "crypt_blowfish.c")),
@@ -86,6 +107,9 @@ _bcrypt_lib = _ffi.verify(
)
+_bcrypt_lib = LazyLibrary(_ffi)
+
+
def gensalt(rounds=12):
salt = os.urandom(16)
output = _ffi.new("unsigned char[]", 30)