Coverage for .tox/coverage/lib/python3.11/site-packages/wuttaweb/views/base.py: 100%

36 statements  

« prev     ^ index     » next       coverage.py v7.6.10, created at 2024-12-28 21:19 -0600

1# -*- coding: utf-8; -*- 

2################################################################################ 

3# 

4# wuttaweb -- Web App for Wutta Framework 

5# Copyright © 2024 Lance Edgar 

6# 

7# This file is part of Wutta Framework. 

8# 

9# Wutta Framework is free software: you can redistribute it and/or modify it 

10# under the terms of the GNU General Public License as published by the Free 

11# Software Foundation, either version 3 of the License, or (at your option) any 

12# later version. 

13# 

14# Wutta Framework is distributed in the hope that it will be useful, but 

15# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 

16# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 

17# more details. 

18# 

19# You should have received a copy of the GNU General Public License along with 

20# Wutta Framework. If not, see <http://www.gnu.org/licenses/>. 

21# 

22################################################################################ 

23""" 

24Base Logic for Views 

25""" 

26 

27import os 

28 

29from pyramid import httpexceptions 

30from pyramid.renderers import render_to_response 

31from pyramid.response import FileResponse 

32 

33from wuttaweb import grids 

34 

35 

36class View: 

37 """ 

38 Base class for all class-based views. 

39 

40 Instances of this class (or rather, a subclass) are created by 

41 Pyramid when processing a request. They will have the following 

42 attributes: 

43 

44 .. attribute:: request 

45 

46 Reference to the current :term:`request` object. 

47 

48 .. attribute:: app 

49 

50 Reference to the :term:`app handler`. 

51 

52 .. attribute:: config 

53 

54 Reference to the app :term:`config object`. 

55 """ 

56 

57 def __init__(self, request, context=None): 

58 self.request = request 

59 self.config = self.request.wutta_config 

60 self.app = self.config.get_app() 

61 

62 def forbidden(self): 

63 """ 

64 Convenience method, to raise a HTTP 403 Forbidden exception:: 

65 

66 raise self.forbidden() 

67 """ 

68 return httpexceptions.HTTPForbidden() 

69 

70 def make_form(self, **kwargs): 

71 """ 

72 Make and return a new :class:`~wuttaweb.forms.base.Form` 

73 instance, per the given ``kwargs``. 

74 

75 This is the "base" factory which merely invokes the 

76 constructor. 

77 """ 

78 web = self.app.get_web_handler() 

79 return web.make_form(self.request, **kwargs) 

80 

81 def make_grid(self, **kwargs): 

82 """ 

83 Make and return a new :class:`~wuttaweb.grids.base.Grid` 

84 instance, per the given ``kwargs``. 

85 

86 This is the "base" factory which merely invokes the 

87 constructor. 

88 """ 

89 web = self.app.get_web_handler() 

90 return web.make_grid(self.request, **kwargs) 

91 

92 def make_grid_action(self, key, **kwargs): 

93 """ 

94 Make and return a new :class:`~wuttaweb.grids.base.GridAction` 

95 instance, per the given ``key`` and ``kwargs``. 

96 

97 This is the "base" factory which merely invokes the 

98 constructor. 

99 """ 

100 return grids.GridAction(self.request, key, **kwargs) 

101 

102 def notfound(self): 

103 """ 

104 Convenience method, to raise a HTTP 404 Not Found exception:: 

105 

106 raise self.notfound() 

107 """ 

108 return httpexceptions.HTTPNotFound() 

109 

110 def redirect(self, url, **kwargs): 

111 """ 

112 Convenience method to return a HTTP 302 response. 

113 

114 Note that this technically returns an "exception" - so in 

115 your code, you can either return that error, or raise it:: 

116 

117 return self.redirect('/') 

118 # ..or 

119 raise self.redirect('/') 

120 

121 Which you should do will depend on context, but raising the 

122 error is always "safe" since Pyramid will handle that 

123 correctly no matter what. 

124 """ 

125 return httpexceptions.HTTPFound(location=url, **kwargs) 

126 

127 def file_response(self, path, attachment=True, filename=None): 

128 """ 

129 Returns a generic file response for the given path. 

130 

131 :param path: Path to a file on local disk; must be accessible 

132 by the web app. 

133 

134 :param attachment: Whether the file should come down as an 

135 "attachment" instead of main payload. 

136 

137 The attachment behavior is the default here, and will cause 

138 the user to be prompted for where to save the file. 

139 

140 Set ``attachment=False`` in order to cause the browser to 

141 render the file as if it were the page being navigated to. 

142 

143 :param filename: Optional filename to use for attachment 

144 behavior. This will be the "suggested filename" when user 

145 is prompted to save the download. If not specified, the 

146 filename is derived from ``path``. 

147 

148 :returns: A :class:`~pyramid:pyramid.response.FileResponse` 

149 object with file content. 

150 """ 

151 if not os.path.exists(path): 

152 return self.notfound() 

153 

154 response = FileResponse(path, request=self.request) 

155 response.content_length = os.path.getsize(path) 

156 

157 if attachment: 

158 if not filename: 

159 filename = os.path.basename(path) 

160 response.content_disposition = f'attachment; filename="{filename}"' 

161 

162 return response 

163 

164 def json_response(self, context): 

165 """ 

166 Returns a JSON response with the given context data. 

167 

168 :param context: Context data to be rendered as JSON. 

169 

170 :returns: A :term:`response` with JSON content type. 

171 """ 

172 return render_to_response('json', context, request=self.request)