1import os
2import warnings
3
4class YAJLImportError(ImportError):
5 pass
6
7
8def require_version(version, required):
9 '''
10 Asserts that the major component of 'version' is equal to 'required'.
11 Raises YAJLImportError otherwise.
12 '''
13 major, rest = divmod(version, 10000)
14 minor, micro = divmod(rest, 100)
15 if major != required:
16 raise YAJLImportError('YAJL version %s.x required, found %s.%s.%s' % (required, major, minor, micro))
17
18def get_yajl_version(yajl):
19 try:
20 return yajl.yajl_version()
21 except AttributeError:
22 warnings.warn('Cannot determine yajl version, assuming <1.0.12')
23 return 10000
24
25def find_yajl_ctypes(required):
26 '''
27 Finds and loads yajl shared object of the required major
28 version (1, 2, ...) using ctypes.
29 '''
30 # Importing ``ctypes`` should be in scope of this function to prevent failure
31 # of `backends`` package load in a runtime where ``ctypes`` is not available.
32 # Example of such environment is Google App Engine (GAE).
33 from ctypes import util, cdll
34
35 so_name = os.getenv('YAJL_DLL') or util.find_library('yajl')
36 if so_name is None:
37 raise YAJLImportError('YAJL shared object not found.')
38 try:
39 yajl = cdll.LoadLibrary(so_name)
40 except OSError:
41 raise YAJLImportError('Unable to load YAJL.')
42 require_version(get_yajl_version(yajl), required)
43 return yajl
44
45def find_yajl_cffi(ffi, required):
46 '''
47 Finds and loads yajl shared object of the required major
48 version (1, 2, ...) using cffi.
49 '''
50 try:
51 yajl = ffi.dlopen(os.getenv('YAJL_DLL') or 'yajl')
52 except OSError:
53 raise YAJLImportError('Unable to load YAJL.')
54 require_version(get_yajl_version(yajl), required)
55 return yajl