1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

# Copyright 2013-2016 The Distro Tracker Developers 

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

# at https://deb.li/DTAuthors 

# 

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

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

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

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

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

""" 

Implements a management command which adds a new keyword. 

""" 

from django.core.management.base import BaseCommand, CommandError 

from django.db import transaction 

 

from distro_tracker.core.models import ( 

EmailSettings, 

Keyword, 

Subscription, 

UserEmail 

) 

from distro_tracker.core.utils import get_or_none 

 

 

class Command(BaseCommand): 

""" 

A management command that adds a new keyword. 

 

It supports simply adding a new keyword and allowing users to add it to 

their subscriptions or to automatically add it to users' lists that 

already contain a different keyword (given as a parameter to the command). 

""" 

help = ("Add a new keyword.\n." # noqa 

"The command supports simply adding a new keyword and allowing" 

" users to add it to their subscriptions or to automatically add" 

" it to users' lists that already contain a different keyword" 

" (given as a parameter to the command).") 

 

def add_arguments(self, parser): 

parser.add_argument('keyword') 

parser.add_argument('existing_keyword', nargs='?', default=None) 

parser.add_argument( 

'--set-default', 

action='store_true', 

dest='is_default_keyword', 

default=False, 

help='Make the new keyword a default one' 

) 

 

def warning(self, msg, *args): 

if self.verbose > 1: 

text = msg % args 

self.stdout.write("Warning: {text}".format(text=text)) 

 

def add_keyword_to_user_defaults(self, keyword, user_set): 

""" 

Adds the given ``keyword`` to the 

:py:attr:`default_keywords 

<distro_tracker.core.models.EmailSettings.default_keywords>` 

list of each user found in the given QuerySet ``user_set``. 

 

:param keyword: The keyword which should be added to all the users' 

:py:attr:`default_keywords 

<distro_tracker.core.models.EmailSettings.default_keywords>` 

:type keyword: :py:class:`Keyword <distro_tracker.core.models.Keyword>` 

 

:param user_set: The set of users to which the given keyword should be 

added as a default keyword. 

:type user_set: :py:class:`QuerySet <django.db.models.query.QuerySet>` 

or other iterable of 

:py:class:`UserEmail <distro_tracker.core.models.UserEmail>` 

instances 

""" 

for user_email in user_set: 

email_settings, _ = \ 

EmailSettings.objects.get_or_create(user_email=user_email) 

email_settings.default_keywords.add(keyword) 

 

def add_keyword_to_subscriptions(self, new_keyword, existing_keyword): 

""" 

Adds the given ``new_keyword`` to each 

:py:class:`Subscription <distro_tracker.core.models.Subscription>`'s 

keywords list which already contains the ``existing_keyword``. 

 

:param new_keyword: The keyword to add to the 

:py:class:`Subscription <distro_tracker.core.models.Subscription>`'s 

keywords 

:type new_keyword: 

:py:class:`Keyword <distro_tracker.core.models.Keyword>` 

 

:param existing_keyword: The keyword or name of the keyword based on 

which all 

:py:class:`Subscription <distro_tracker.core.models.Subscription>` 

to which the ``new_keyword`` should be added are chosen. 

:type existing_keyword: 

:py:class:`Keyword <distro_tracker.core.models.Keyword>` 

or string 

""" 

99 ↛ 105line 99 didn't jump to line 105, because the condition on line 99 was never false if not isinstance(existing_keyword, Keyword): 

existing_keyword = get_or_none(Keyword, name=existing_keyword) 

if not existing_keyword: 

raise CommandError("Given keyword does not exist. " 

"No actions taken.") 

 

self.add_keyword_to_user_defaults( 

new_keyword, 

UserEmail.objects.filter( 

emailsettings__default_keywords=existing_keyword) 

) 

for subscription in Subscription.objects.all(): 

if existing_keyword in subscription.keywords.all(): 

112 ↛ 115line 112 didn't jump to line 115, because the condition on line 112 was never true if subscription._use_user_default_keywords: 

# Skip these subscriptions since the keyword was already 

# added to user's default lists. 

continue 

else: 

subscription.keywords.add(new_keyword) 

 

@transaction.atomic 

def handle(self, *args, **kwargs): 

self.verbose = int(kwargs.get('verbosity', 1)) > 1 

keyword = kwargs['keyword'] 

123 ↛ 124line 123 didn't jump to line 124, because the condition on line 123 was never true if not keyword: 

raise CommandError("The name of the new keyword must be given") 

 

default = kwargs['is_default_keyword'] 

keyword, created = Keyword.objects.get_or_create( 

name=keyword, 

defaults={ 

'default': default, 

} 

) 

 

134 ↛ 135line 134 didn't jump to line 135, because the condition on line 134 was never true if not created: 

self.warning("The given keyword already exists") 

return 

 

if default: 

self.add_keyword_to_user_defaults( 

keyword, 

UserEmail.objects.exclude(emailsettings__isnull=True) 

) 

 

if kwargs['existing_keyword'] is not None: 

# Add the new keyword to all subscribers and subscriptions which 

# contain the parameter keyword 

other_keyword = kwargs['existing_keyword'] 

self.add_keyword_to_subscriptions(keyword, other_keyword) 

 

150 ↛ 151line 150 didn't jump to line 151, because the condition on line 150 was never true if self.verbose: 

self.stdout.write('Successfully added new keyword {keyword}'.format( 

keyword=keyword))