Coverage for src/django_resume/plugins/identity.py: 55%

1 from django import forms

2 from django.core.files.base import ContentFile

3 from django.core.files.storage import default_storage

4 from django.core.files.uploadedfile import InMemoryUploadedFile

5 from django.forms.widgets import ClearableFileInput

6 from django.http import HttpRequest

7

8 from .base import SimplePlugin, SimpleTemplates, ContextDict

9

10

11 class CustomFileObject:

12 def __init__(self, filename):

13 self.name = filename

14 self.url = default_storage.url(filename)

15

16 def __str__(self):

17 return self.name

18

19

20 class CustomClearableFileInput(ClearableFileInput):

21 template_name = "custom_clearable_file_input.html"

22

23 def get_context(self, name, value, attrs):

24 value = CustomFileObject(value)

25 context = super().get_context(name, value, attrs)

26 context["widget"]["is_initial"] = self.is_initial(value)

27 return context

28

29

30 class IdentityForm(forms.Form):

31 template_name = "django_resume/identity/plain/form_as_div.html"

32 name = forms.CharField(label="Your name", max_length=100, initial="Your name")

33 pronouns = forms.CharField(

34 label="Pronouns", max_length=100, initial="your/pronouns"

35 )

36 tagline = forms.CharField(

37 label="Tagline", max_length=512, initial="Some tagline text."

38 )

39 location_name = forms.CharField(

40 label="Location", max_length=100, initial="City, Country, Timezone"

41 )

42 location_url = forms.URLField(

43 label="Location url",

44 max_length=100,

45 initial="https://maps.app.goo.gl/TkuHEzeGpr7u2aCD7",

46 assume_scheme="https",

47 )

48 avatar_img = forms.FileField(

49 label="Profile Image",

50 max_length=100,

51 required=False,

52 widget=CustomClearableFileInput,

53 )

54 avatar_alt = forms.CharField(

55 label="Profile photo alt text",

56 max_length=100,

57 initial="Profile photo",

58 required=False,

59 )

60 clear_avatar = forms.BooleanField(

61 widget=forms.CheckboxInput, initial=False, required=False

62 )

63 email = forms.EmailField(

64 label="Email address",

65 max_length=100,

66 initial="foobar@example.com",

67 )

68 phone = forms.CharField(

69 label="Phone number",

70 max_length=100,

71 initial="+1 555 555 5555",

72 )

73 github = forms.URLField(

74 label="GitHub url",

75 max_length=100,

76 initial="https://github.com/foobar/",

77 assume_scheme="https",

78 )

79 linkedin = forms.URLField(

80 label="LinkedIn profile url",

81 max_length=100,

82 initial="https://linkedin.com/foobar/",

83 assume_scheme="https",

84 )

85 mastodon = forms.URLField(

86 label="Mastodon url",

87 max_length=100,

88 initial="https://fosstodon.org/@foobar",

89 assume_scheme="https",

90 )

91

92 def __init__(self, *args, **kwargs):

93 super().__init__(*args, **kwargs)

94 initial_avatar_img_filename = self.initial.get("avatar_img")

95 print("initial avatar img: ", initial_avatar_img_filename)

96 if initial_avatar_img_filename is not None: 96 ↛ 97line 96 didn't jump to line 97 because the condition on line 96 was never true

97 self.fields["avatar_img"].initial = CustomFileObject(

98 initial_avatar_img_filename

99 )

100 print("initial avatar img: ", self.fields["avatar_img"].initial)

101

102 @property

103 def avatar_img_url(self):

104 return default_storage.url(self.initial.get("avatar_img", ""))

105

106 def clean(self):

107 # super ugly - FIXME

108 cleaned_data = super().clean()

109 avatar_img = cleaned_data.get("avatar_img")

110 clear_avatar = cleaned_data.get("clear_avatar")

111 print("cleaned_data: ", cleaned_data)

112

113 avatar_handled = False

114 just_clear_the_avatar = clear_avatar and not hasattr(

115 avatar_img, "temporary_file_path"

116 )

117 if just_clear_the_avatar:

118 cleaned_data["avatar_img"] = None

119 avatar_handled = True

120

121 set_new_avatar_image = (

122 isinstance(avatar_img, InMemoryUploadedFile) and not avatar_handled

123 )

124 if set_new_avatar_image:

125 if avatar_img.size > 2 * 1024 * 1024:

126 raise forms.ValidationError("Image file too large ( > 2mb )")

127 cleaned_data["avatar_img"] = default_storage.save(

128 f"uploads/{avatar_img.name}", ContentFile(avatar_img.read())

129 )

130 avatar_handled = True

131

132 keep_current_avatar = (

133 not clear_avatar and isinstance(avatar_img, str) and not avatar_handled

134 )

135 if keep_current_avatar:

136 cleaned_data["avatar_img"] = avatar_img

137

138 del cleaned_data["clear_avatar"] # reset the clear_avatar field

139 return cleaned_data

140

141

142 class IdentityPlugin(SimplePlugin):

143 name: str = "identity"

144 verbose_name: str = "Identity Information"

145 templates = SimpleTemplates(

146 main="django_resume/identity/plain/content.html",

147 form="django_resume/identity/plain/form.html",

148 )

149 admin_form_class = inline_form_class = IdentityForm

150

151 def get_context(

152 self,

153 _request: HttpRequest,

154 plugin_data: dict,

155 resume_pk: int,

156 *,

157 context: ContextDict,

158 edit: bool = False,

159 ) -> ContextDict:

160 context = super().get_context(

161 _request, plugin_data, resume_pk, context=context, edit=edit

162 )

163 context["avatar_img_url"] = default_storage.url(

164 plugin_data.get("avatar_img", "")

165 )

166 return context