1# Copyright 2013 The Distro Tracker Developers 

2# See the COPYRIGHT file at the top-level directory of this distribution and 

3# at https://deb.li/DTAuthors 

4# 

5# This file is part of Distro Tracker. It is subject to the license terms 

6# in the LICENSE file found in the top-level directory of this 

7# distribution and at https://deb.li/DTLicense. No part of Distro Tracker, 

8# including this file, may be copied, modified, propagated, or distributed 

9# except according to the terms contained in the LICENSE file. 

10 

11""" 

12A module which defines functions to allow other parts of Distro Tracker to hook 

13into the vendor-specific functionality. 

14""" 

15from django.conf import settings 

16 

17 

18class InvalidPluginException(Exception): 

19 pass 

20 

21 

22class PluginProcessingError(RuntimeError): 

23 pass 

24 

25 

26def get_callable(name): 

27 """ 

28 Returns a callable object from the vendor-provided module based on the 

29 string name given as the parameter. 

30 If no callable object with the given name is found in the vendor module 

31 an exception is raised. 

32 

33 :param name: The name of the callable which should be returned 

34 :type name: string 

35 """ 

36 import importlib 

37 if (not hasattr(settings, 'DISTRO_TRACKER_VENDOR_RULES') or 

38 not settings.DISTRO_TRACKER_VENDOR_RULES): 

39 raise InvalidPluginException("No vendor specific module set.") 

40 

41 vendor_module = \ 

42 importlib.import_module(settings.DISTRO_TRACKER_VENDOR_RULES) 

43 

44 function = getattr(vendor_module, name, None) 

45 if not function: 45 ↛ 46line 45 didn't jump to line 46, because the condition on line 45 was never true

46 raise InvalidPluginException("{name} not found in {module}".format( 

47 name=name, module=settings.DISTRO_TRACKER_VENDOR_RULES)) 

48 if not callable(function): 48 ↛ 49line 48 didn't jump to line 49, because the condition on line 48 was never true

49 raise InvalidPluginException("{name} is not callable.".format( 

50 name=name)) 

51 

52 return function 

53 

54 

55def call(name, *args, **kwargs): 

56 """ 

57 Function which executes the vendor-specific function with the given name by 

58 passing it the given arguments. 

59 

60 It returns a tuple ``(result, implemented)`` where the values represent: 

61 

62 - result -- the corresponding function's return value. If the function was 

63 not found, ``None`` is given. 

64 - implemented -- a Boolean indicating whether the package implements the 

65 given function. This way clients can differentiate between functions with 

66 no return value and non-implemented functions. 

67 

68 :param name: The name of the vendor-specific function that should be 

69 called. 

70 """ 

71 try: 

72 func = get_callable(name) 

73 except (ImportError, InvalidPluginException): 

74 return None, False 

75 

76 return func(*args, **kwargs), True