Merge lp:~dobey/ubuntu/oneiric/ubuntuone-control-panel/release-113 into lp:ubuntu/oneiric/ubuntuone-control-panel
- Oneiric (11.10)
- release-113
- Merge into oneiric
Proposed by
dobey
Status: | Merged |
---|---|
Merged at revision: | 29 |
Proposed branch: | lp:~dobey/ubuntu/oneiric/ubuntuone-control-panel/release-113 |
Merge into: | lp:ubuntu/oneiric/ubuntuone-control-panel |
Diff against target: |
5305 lines (+1530/-1352) 42 files modified
PKG-INFO (+2/-2) bin/ubuntuone-control-panel-gtk (+3/-3) bin/ubuntuone-control-panel-qt (+3/-3) data/qt/account.ui (+2/-2) data/qt/controlpanel.ui (+42/-39) data/qt/device.ui (+3/-0) data/qt/filesyncstatus.ui (+4/-2) data/qt/folders.ui (+8/-5) data/qt/images.qrc (+2/-0) data/qt/mainwindow.ui (+1/-1) data/qt/preferences.ui (+4/-1) data/qt/ubuntuone.qss (+63/-46) debian/changelog (+7/-0) po/ubuntuone-control-panel.pot (+1/-1) run-tests (+4/-2) run-tests.bat (+1/-1) setup.py (+13/-7) ubuntuone/controlpanel/backend.py (+65/-57) ubuntuone/controlpanel/dbus_service.py (+12/-4) ubuntuone/controlpanel/dbustests/test_dbus_service.py (+1/-1) ubuntuone/controlpanel/dbustests/test_sd_client/test_linux.py (+2/-1) ubuntuone/controlpanel/gui/gtk/gui.py (+48/-77) ubuntuone/controlpanel/gui/gtk/tests/__init__.py (+12/-14) ubuntuone/controlpanel/gui/gtk/tests/test_gui.py (+24/-23) ubuntuone/controlpanel/gui/gtk/tests/test_gui_basic.py (+126/-81) ubuntuone/controlpanel/gui/qt/filesyncstatus.py (+8/-0) ubuntuone/controlpanel/gui/qt/tests/test_filesyncstatus.py (+12/-0) ubuntuone/controlpanel/gui/qt/ui/account_ui.py (+3/-3) ubuntuone/controlpanel/gui/qt/ui/controlpanel_ui.py (+24/-12) ubuntuone/controlpanel/gui/qt/ui/device_ui.py (+2/-1) ubuntuone/controlpanel/gui/qt/ui/devices_ui.py (+1/-1) ubuntuone/controlpanel/gui/qt/ui/filesyncstatus_ui.py (+2/-1) ubuntuone/controlpanel/gui/qt/ui/folders_ui.py (+3/-4) ubuntuone/controlpanel/gui/qt/ui/images_rc.py (+459/-447) ubuntuone/controlpanel/gui/qt/ui/loadingoverlay_ui.py (+1/-1) ubuntuone/controlpanel/gui/qt/ui/mainwindow_ui.py (+2/-2) ubuntuone/controlpanel/gui/qt/ui/preferences_ui.py (+3/-2) ubuntuone/controlpanel/login_client.py (+18/-5) ubuntuone/controlpanel/sd_client/__init__.py (+176/-211) ubuntuone/controlpanel/tests/test_backend.py (+205/-168) ubuntuone/controlpanel/tests/test_login_client.py (+48/-6) ubuntuone/controlpanel/tests/test_sd_client.py (+110/-115) |
To merge this branch: | bzr merge lp:~dobey/ubuntu/oneiric/ubuntuone-control-panel/release-113 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu branches | Pending | ||
Review via email: mp+72945@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'PKG-INFO' | |||
2 | --- PKG-INFO 2011-08-12 19:12:08 +0000 | |||
3 | +++ PKG-INFO 2011-08-25 19:40:18 +0000 | |||
4 | @@ -1,12 +1,12 @@ | |||
5 | 1 | Metadata-Version: 1.1 | 1 | Metadata-Version: 1.1 |
6 | 2 | Name: ubuntuone-control-panel | 2 | Name: ubuntuone-control-panel |
8 | 3 | Version: 1.1.2 | 3 | Version: 1.1.3 |
9 | 4 | Summary: Ubuntu One Control Panel | 4 | Summary: Ubuntu One Control Panel |
10 | 5 | Home-page: https://launchpad.net/ubuntuone-control-panel | 5 | Home-page: https://launchpad.net/ubuntuone-control-panel |
11 | 6 | Author: Natalia Bidart | 6 | Author: Natalia Bidart |
12 | 7 | Author-email: natalia.bidart@canonical.com | 7 | Author-email: natalia.bidart@canonical.com |
13 | 8 | License: GPL v3 | 8 | License: GPL v3 |
15 | 9 | Description: Application to manage a Ubuntu One account. Provides aDBus service to query/modify all the Ubuntu One bits. | 9 | Description: Application to manage a Ubuntu One account. Provides a DBus service to query/modify all the Ubuntu One bits. |
16 | 10 | Platform: UNKNOWN | 10 | Platform: UNKNOWN |
17 | 11 | Requires: PyQt4 | 11 | Requires: PyQt4 |
18 | 12 | Requires: apt | 12 | Requires: apt |
19 | 13 | 13 | ||
20 | === modified file 'bin/ubuntuone-control-panel-gtk' | |||
21 | --- bin/ubuntuone-control-panel-gtk 2011-07-22 21:26:48 +0000 | |||
22 | +++ bin/ubuntuone-control-panel-gtk 2011-08-25 19:40:18 +0000 | |||
23 | @@ -39,12 +39,12 @@ | |||
24 | 39 | result = OptionParser(usage=usage) | 39 | result = OptionParser(usage=usage) |
25 | 40 | result.add_option("", "--switch-to", dest="switch_to", type="string", | 40 | result.add_option("", "--switch-to", dest="switch_to", type="string", |
26 | 41 | metavar="PANEL_NAME", default="", | 41 | metavar="PANEL_NAME", default="", |
28 | 42 | help="Start the Ubuntu One Control Panel (GTK) in the " | 42 | help="Start Ubuntu One in the " |
29 | 43 | "PANEL_NAME tab. Possible values are: " | 43 | "PANEL_NAME tab. Possible values are: " |
30 | 44 | "dashboard, volumes, devices, applications") | 44 | "dashboard, volumes, devices, applications") |
31 | 45 | result.add_option("-a", "--alert", dest="alert", action="store_true", | 45 | result.add_option("-a", "--alert", dest="alert", action="store_true", |
34 | 46 | default=False, help="Start the Ubuntu One Control Panel " | 46 | default=False, help="Start Ubuntu One " |
35 | 47 | "(GTK) alerting the user to its presence.") | 47 | "alerting the user to its presence.") |
36 | 48 | return result | 48 | return result |
37 | 49 | 49 | ||
38 | 50 | 50 | ||
39 | 51 | 51 | ||
40 | === modified file 'bin/ubuntuone-control-panel-qt' | |||
41 | --- bin/ubuntuone-control-panel-qt 2011-07-22 21:26:48 +0000 | |||
42 | +++ bin/ubuntuone-control-panel-qt 2011-08-25 19:40:18 +0000 | |||
43 | @@ -39,12 +39,12 @@ | |||
44 | 39 | result = OptionParser(usage=usage) | 39 | result = OptionParser(usage=usage) |
45 | 40 | result.add_option("", "--switch-to", dest="switch_to", type="string", | 40 | result.add_option("", "--switch-to", dest="switch_to", type="string", |
46 | 41 | metavar="PANEL_NAME", default="", | 41 | metavar="PANEL_NAME", default="", |
48 | 42 | help="Start the Ubuntu One Control Panel (QT) in the " | 42 | help="Start Ubuntu One in the " |
49 | 43 | "PANEL_NAME tab. Possible values are: " | 43 | "PANEL_NAME tab. Possible values are: " |
50 | 44 | "dashboard, volumes, devices, applications") | 44 | "dashboard, volumes, devices, applications") |
51 | 45 | result.add_option("-a", "--alert", dest="alert", action="store_true", | 45 | result.add_option("-a", "--alert", dest="alert", action="store_true", |
54 | 46 | default=False, help="Start the Ubuntu One Control Panel " | 46 | default=False, help="Start Ubuntu One " |
55 | 47 | "(QT) alerting the user to its presence.") | 47 | "alerting the user to its presence.") |
56 | 48 | return result | 48 | return result |
57 | 49 | 49 | ||
58 | 50 | 50 | ||
59 | 51 | 51 | ||
60 | === modified file 'data/facebook.png' | |||
61 | 52 | Binary files data/facebook.png 2011-01-25 19:08:59 +0000 and data/facebook.png 2011-08-25 19:40:18 +0000 differ | 52 | Binary files data/facebook.png 2011-01-25 19:08:59 +0000 and data/facebook.png 2011-08-25 19:40:18 +0000 differ |
62 | === modified file 'data/qt/account.ui' | |||
63 | --- data/qt/account.ui 2011-08-12 19:12:08 +0000 | |||
64 | +++ data/qt/account.ui 2011-08-25 19:40:18 +0000 | |||
65 | @@ -22,7 +22,7 @@ | |||
66 | 22 | <property name="verticalSpacing"> | 22 | <property name="verticalSpacing"> |
67 | 23 | <number>30</number> | 23 | <number>30</number> |
68 | 24 | </property> | 24 | </property> |
70 | 25 | <item row="2" column="2"> | 25 | <item row="0" column="2"> |
71 | 26 | <widget class="GoToWebButton" name="edit_profile_button"> | 26 | <widget class="GoToWebButton" name="edit_profile_button"> |
72 | 27 | <property name="text"> | 27 | <property name="text"> |
73 | 28 | <string>Edit personal details online</string> | 28 | <string>Edit personal details online</string> |
74 | @@ -85,7 +85,7 @@ | |||
75 | 85 | </layout> | 85 | </layout> |
76 | 86 | </widget> | 86 | </widget> |
77 | 87 | </item> | 87 | </item> |
79 | 88 | <item row="0" column="2"> | 88 | <item row="2" column="2"> |
80 | 89 | <widget class="GoToWebButton" name="edit_services_button"> | 89 | <widget class="GoToWebButton" name="edit_services_button"> |
81 | 90 | <property name="text"> | 90 | <property name="text"> |
82 | 91 | <string>Edit your services online</string> | 91 | <string>Edit your services online</string> |
83 | 92 | 92 | ||
84 | === modified file 'data/qt/controlpanel.ui' | |||
85 | --- data/qt/controlpanel.ui 2011-08-12 19:12:08 +0000 | |||
86 | +++ data/qt/controlpanel.ui 2011-08-25 19:40:18 +0000 | |||
87 | @@ -6,8 +6,8 @@ | |||
88 | 6 | <rect> | 6 | <rect> |
89 | 7 | <x>0</x> | 7 | <x>0</x> |
90 | 8 | <y>0</y> | 8 | <y>0</y> |
93 | 9 | <width>387</width> | 9 | <width>367</width> |
94 | 10 | <height>203</height> | 10 | <height>142</height> |
95 | 11 | </rect> | 11 | </rect> |
96 | 12 | </property> | 12 | </property> |
97 | 13 | <property name="sizePolicy"> | 13 | <property name="sizePolicy"> |
98 | @@ -221,7 +221,7 @@ | |||
99 | 221 | </widget> | 221 | </widget> |
100 | 222 | <widget class="PreferencesPanel" name="preferences_tab"> | 222 | <widget class="PreferencesPanel" name="preferences_tab"> |
101 | 223 | <attribute name="title"> | 223 | <attribute name="title"> |
103 | 224 | <string>Preferences</string> | 224 | <string>Settings</string> |
104 | 225 | </attribute> | 225 | </attribute> |
105 | 226 | </widget> | 226 | </widget> |
106 | 227 | <widget class="AccountPanel" name="account_tab"> | 227 | <widget class="AccountPanel" name="account_tab"> |
107 | @@ -233,22 +233,25 @@ | |||
108 | 233 | </item> | 233 | </item> |
109 | 234 | <item> | 234 | <item> |
110 | 235 | <widget class="QFrame" name="frame_footer"> | 235 | <widget class="QFrame" name="frame_footer"> |
111 | 236 | <property name="sizePolicy"> | ||
112 | 237 | <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> | ||
113 | 238 | <horstretch>0</horstretch> | ||
114 | 239 | <verstretch>0</verstretch> | ||
115 | 240 | </sizepolicy> | ||
116 | 241 | </property> | ||
117 | 242 | <property name="maximumSize"> | ||
118 | 243 | <size> | ||
119 | 244 | <width>16777215</width> | ||
120 | 245 | <height>30</height> | ||
121 | 246 | </size> | ||
122 | 247 | </property> | ||
123 | 236 | <layout class="QHBoxLayout" name="horizontalLayout"> | 248 | <layout class="QHBoxLayout" name="horizontalLayout"> |
124 | 237 | <property name="spacing"> | 249 | <property name="spacing"> |
125 | 238 | <number>5</number> | 250 | <number>5</number> |
126 | 239 | </property> | 251 | </property> |
131 | 240 | <property name="leftMargin"> | 252 | <property name="margin"> |
128 | 241 | <number>3</number> | ||
129 | 242 | </property> | ||
130 | 243 | <property name="topMargin"> | ||
132 | 244 | <number>0</number> | 253 | <number>0</number> |
133 | 245 | </property> | 254 | </property> |
134 | 246 | <property name="rightMargin"> | ||
135 | 247 | <number>3</number> | ||
136 | 248 | </property> | ||
137 | 249 | <property name="bottomMargin"> | ||
138 | 250 | <number>3</number> | ||
139 | 251 | </property> | ||
140 | 252 | <item> | 255 | <item> |
141 | 253 | <widget class="GoToWebButton" name="help_button"> | 256 | <widget class="GoToWebButton" name="help_button"> |
142 | 254 | <property name="text"> | 257 | <property name="text"> |
143 | @@ -282,49 +285,49 @@ | |||
144 | 282 | </widget> | 285 | </widget> |
145 | 283 | </item> | 286 | </item> |
146 | 284 | <item> | 287 | <item> |
148 | 285 | <widget class="QToolButton" name="twitter_button"> | 288 | <widget class="QPushButton" name="twitter_button"> |
149 | 289 | <property name="sizePolicy"> | ||
150 | 290 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
151 | 291 | <horstretch>0</horstretch> | ||
152 | 292 | <verstretch>0</verstretch> | ||
153 | 293 | </sizepolicy> | ||
154 | 294 | </property> | ||
155 | 295 | <property name="maximumSize"> | ||
156 | 296 | <size> | ||
157 | 297 | <width>16</width> | ||
158 | 298 | <height>16</height> | ||
159 | 299 | </size> | ||
160 | 300 | </property> | ||
161 | 286 | <property name="cursor"> | 301 | <property name="cursor"> |
162 | 287 | <cursorShape>PointingHandCursor</cursorShape> | 302 | <cursorShape>PointingHandCursor</cursorShape> |
163 | 288 | </property> | 303 | </property> |
164 | 289 | <property name="styleSheet"> | ||
165 | 290 | <string notr="true">border: 0;</string> | ||
166 | 291 | </property> | ||
167 | 292 | <property name="text"> | ||
168 | 293 | <string/> | ||
169 | 294 | </property> | ||
170 | 295 | <property name="icon"> | 304 | <property name="icon"> |
171 | 296 | <iconset resource="images.qrc"> | 305 | <iconset resource="images.qrc"> |
172 | 297 | <normaloff>:/twitter.png</normaloff>:/twitter.png</iconset> | 306 | <normaloff>:/twitter.png</normaloff>:/twitter.png</iconset> |
173 | 298 | </property> | 307 | </property> |
174 | 299 | <property name="iconSize"> | ||
175 | 300 | <size> | ||
176 | 301 | <width>22</width> | ||
177 | 302 | <height>22</height> | ||
178 | 303 | </size> | ||
179 | 304 | </property> | ||
180 | 305 | </widget> | 308 | </widget> |
181 | 306 | </item> | 309 | </item> |
182 | 307 | <item> | 310 | <item> |
184 | 308 | <widget class="QToolButton" name="facebook_button"> | 311 | <widget class="QPushButton" name="facebook_button"> |
185 | 312 | <property name="sizePolicy"> | ||
186 | 313 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
187 | 314 | <horstretch>0</horstretch> | ||
188 | 315 | <verstretch>0</verstretch> | ||
189 | 316 | </sizepolicy> | ||
190 | 317 | </property> | ||
191 | 318 | <property name="maximumSize"> | ||
192 | 319 | <size> | ||
193 | 320 | <width>16</width> | ||
194 | 321 | <height>16</height> | ||
195 | 322 | </size> | ||
196 | 323 | </property> | ||
197 | 309 | <property name="cursor"> | 324 | <property name="cursor"> |
198 | 310 | <cursorShape>PointingHandCursor</cursorShape> | 325 | <cursorShape>PointingHandCursor</cursorShape> |
199 | 311 | </property> | 326 | </property> |
200 | 312 | <property name="styleSheet"> | ||
201 | 313 | <string notr="true">border: 0;</string> | ||
202 | 314 | </property> | ||
203 | 315 | <property name="text"> | ||
204 | 316 | <string/> | ||
205 | 317 | </property> | ||
206 | 318 | <property name="icon"> | 327 | <property name="icon"> |
207 | 319 | <iconset resource="images.qrc"> | 328 | <iconset resource="images.qrc"> |
208 | 320 | <normaloff>:/facebook.png</normaloff>:/facebook.png</iconset> | 329 | <normaloff>:/facebook.png</normaloff>:/facebook.png</iconset> |
209 | 321 | </property> | 330 | </property> |
210 | 322 | <property name="iconSize"> | ||
211 | 323 | <size> | ||
212 | 324 | <width>22</width> | ||
213 | 325 | <height>22</height> | ||
214 | 326 | </size> | ||
215 | 327 | </property> | ||
216 | 328 | </widget> | 331 | </widget> |
217 | 329 | </item> | 332 | </item> |
218 | 330 | </layout> | 333 | </layout> |
219 | 331 | 334 | ||
220 | === modified file 'data/qt/device.ui' | |||
221 | --- data/qt/device.ui 2011-08-12 19:12:08 +0000 | |||
222 | +++ data/qt/device.ui 2011-08-25 19:40:18 +0000 | |||
223 | @@ -46,6 +46,9 @@ | |||
224 | 46 | <property name="text"> | 46 | <property name="text"> |
225 | 47 | <string>Remove</string> | 47 | <string>Remove</string> |
226 | 48 | </property> | 48 | </property> |
227 | 49 | <property name="secondary" stdset="0"> | ||
228 | 50 | <bool>true</bool> | ||
229 | 51 | </property> | ||
230 | 49 | </widget> | 52 | </widget> |
231 | 50 | </item> | 53 | </item> |
232 | 51 | </layout> | 54 | </layout> |
233 | 52 | 55 | ||
234 | === modified file 'data/qt/filesyncstatus.ui' | |||
235 | --- data/qt/filesyncstatus.ui 2011-08-12 19:12:08 +0000 | |||
236 | +++ data/qt/filesyncstatus.ui 2011-08-25 19:40:18 +0000 | |||
237 | @@ -20,8 +20,7 @@ | |||
238 | 20 | <item> | 20 | <item> |
239 | 21 | <layout class="QHBoxLayout" name="horizontalLayout"> | 21 | <layout class="QHBoxLayout" name="horizontalLayout"> |
240 | 22 | <item> | 22 | <item> |
243 | 23 | <widget class="QLabel" name="sync_status_icon"> | 23 | <widget class="QLabel" name="sync_status_icon"/> |
242 | 24 | </widget> | ||
244 | 25 | </item> | 24 | </item> |
245 | 26 | <item> | 25 | <item> |
246 | 27 | <widget class="QLabel" name="sync_status_label"> | 26 | <widget class="QLabel" name="sync_status_label"> |
247 | @@ -40,6 +39,9 @@ | |||
248 | 40 | </item> | 39 | </item> |
249 | 41 | <item> | 40 | <item> |
250 | 42 | <widget class="QPushButton" name="sync_status_button"> | 41 | <widget class="QPushButton" name="sync_status_button"> |
251 | 42 | <property name="secondary" stdset="0"> | ||
252 | 43 | <bool>true</bool> | ||
253 | 44 | </property> | ||
254 | 43 | </widget> | 45 | </widget> |
255 | 44 | </item> | 46 | </item> |
256 | 45 | </layout> | 47 | </layout> |
257 | 46 | 48 | ||
258 | === modified file 'data/qt/folders.ui' | |||
259 | --- data/qt/folders.ui 2011-08-12 19:12:08 +0000 | |||
260 | +++ data/qt/folders.ui 2011-08-25 19:40:18 +0000 | |||
261 | @@ -13,9 +13,6 @@ | |||
262 | 13 | <property name="windowTitle"> | 13 | <property name="windowTitle"> |
263 | 14 | <string notr="true">Form</string> | 14 | <string notr="true">Form</string> |
264 | 15 | </property> | 15 | </property> |
265 | 16 | <property name="styleSheet"> | ||
266 | 17 | <string notr="true">padding: 0px;</string> | ||
267 | 18 | </property> | ||
268 | 19 | <layout class="QVBoxLayout" name="verticalLayout"> | 16 | <layout class="QVBoxLayout" name="verticalLayout"> |
269 | 20 | <property name="spacing"> | 17 | <property name="spacing"> |
270 | 21 | <number>0</number> | 18 | <number>0</number> |
271 | @@ -38,7 +35,7 @@ | |||
272 | 38 | <item> | 35 | <item> |
273 | 39 | <widget class="GoToWebButton" name="share_publish_button"> | 36 | <widget class="GoToWebButton" name="share_publish_button"> |
274 | 40 | <property name="sizePolicy"> | 37 | <property name="sizePolicy"> |
276 | 41 | <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> | 38 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> |
277 | 42 | <horstretch>0</horstretch> | 39 | <horstretch>0</horstretch> |
278 | 43 | <verstretch>0</verstretch> | 40 | <verstretch>0</verstretch> |
279 | 44 | </sizepolicy> | 41 | </sizepolicy> |
280 | @@ -136,6 +133,9 @@ | |||
281 | 136 | <property name="orientation"> | 133 | <property name="orientation"> |
282 | 137 | <enum>Qt::Horizontal</enum> | 134 | <enum>Qt::Horizontal</enum> |
283 | 138 | </property> | 135 | </property> |
284 | 136 | <property name="sizeType"> | ||
285 | 137 | <enum>QSizePolicy::Expanding</enum> | ||
286 | 138 | </property> | ||
287 | 139 | <property name="sizeHint" stdset="0"> | 139 | <property name="sizeHint" stdset="0"> |
288 | 140 | <size> | 140 | <size> |
289 | 141 | <width>53</width> | 141 | <width>53</width> |
290 | @@ -147,7 +147,7 @@ | |||
291 | 147 | <item> | 147 | <item> |
292 | 148 | <widget class="AddFolderButton" name="add_folder_button"> | 148 | <widget class="AddFolderButton" name="add_folder_button"> |
293 | 149 | <property name="sizePolicy"> | 149 | <property name="sizePolicy"> |
295 | 150 | <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> | 150 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> |
296 | 151 | <horstretch>0</horstretch> | 151 | <horstretch>0</horstretch> |
297 | 152 | <verstretch>0</verstretch> | 152 | <verstretch>0</verstretch> |
298 | 153 | </sizepolicy> | 153 | </sizepolicy> |
299 | @@ -162,6 +162,9 @@ | |||
300 | 162 | <property name="orientation"> | 162 | <property name="orientation"> |
301 | 163 | <enum>Qt::Horizontal</enum> | 163 | <enum>Qt::Horizontal</enum> |
302 | 164 | </property> | 164 | </property> |
303 | 165 | <property name="sizeType"> | ||
304 | 166 | <enum>QSizePolicy::Expanding</enum> | ||
305 | 167 | </property> | ||
306 | 165 | <property name="sizeHint" stdset="0"> | 168 | <property name="sizeHint" stdset="0"> |
307 | 166 | <size> | 169 | <size> |
308 | 167 | <width>40</width> | 170 | <width>40</width> |
309 | 168 | 171 | ||
310 | === modified file 'data/qt/images.qrc' | |||
311 | --- data/qt/images.qrc 2011-07-22 21:26:48 +0000 | |||
312 | +++ data/qt/images.qrc 2011-08-25 19:40:18 +0000 | |||
313 | @@ -10,6 +10,8 @@ | |||
314 | 10 | <file>../computer.png</file> | 10 | <file>../computer.png</file> |
315 | 11 | <file>../phone.png</file> | 11 | <file>../phone.png</file> |
316 | 12 | <file>../twitter.png</file> | 12 | <file>../twitter.png</file> |
317 | 13 | <file>../twitter.png</file> | ||
318 | 14 | <file>../facebook.png</file> | ||
319 | 13 | <file>../facebook.png</file> | 15 | <file>../facebook.png</file> |
320 | 14 | <file>../external_icon_white.png</file> | 16 | <file>../external_icon_white.png</file> |
321 | 15 | <file>../Ubuntu-R.ttf</file> | 17 | <file>../Ubuntu-R.ttf</file> |
322 | 16 | 18 | ||
323 | === modified file 'data/qt/mainwindow.ui' | |||
324 | --- data/qt/mainwindow.ui 2011-07-22 21:26:48 +0000 | |||
325 | +++ data/qt/mainwindow.ui 2011-08-25 19:40:18 +0000 | |||
326 | @@ -23,7 +23,7 @@ | |||
327 | 23 | </size> | 23 | </size> |
328 | 24 | </property> | 24 | </property> |
329 | 25 | <property name="windowTitle"> | 25 | <property name="windowTitle"> |
331 | 26 | <string>Ubuntu One Control Panel</string> | 26 | <string>Ubuntu One</string> |
332 | 27 | </property> | 27 | </property> |
333 | 28 | <property name="windowIcon"> | 28 | <property name="windowIcon"> |
334 | 29 | <iconset resource="images.qrc"> | 29 | <iconset resource="images.qrc"> |
335 | 30 | 30 | ||
336 | === modified file 'data/qt/preferences.ui' | |||
337 | --- data/qt/preferences.ui 2011-08-12 19:12:08 +0000 | |||
338 | +++ data/qt/preferences.ui 2011-08-25 19:40:18 +0000 | |||
339 | @@ -23,7 +23,7 @@ | |||
340 | 23 | <item> | 23 | <item> |
341 | 24 | <widget class="QGroupBox" name="bandwidth_settings"> | 24 | <widget class="QGroupBox" name="bandwidth_settings"> |
342 | 25 | <property name="title"> | 25 | <property name="title"> |
344 | 26 | <string>Bandwidth settings</string> | 26 | <string>Bandwidth Settings</string> |
345 | 27 | </property> | 27 | </property> |
346 | 28 | <layout class="QGridLayout" name="gridLayout"> | 28 | <layout class="QGridLayout" name="gridLayout"> |
347 | 29 | <property name="margin"> | 29 | <property name="margin"> |
348 | @@ -202,6 +202,9 @@ | |||
349 | 202 | <property name="text"> | 202 | <property name="text"> |
350 | 203 | <string>Default settings</string> | 203 | <string>Default settings</string> |
351 | 204 | </property> | 204 | </property> |
352 | 205 | <property name="secondary" stdset="0"> | ||
353 | 206 | <bool>true</bool> | ||
354 | 207 | </property> | ||
355 | 205 | </widget> | 208 | </widget> |
356 | 206 | </item> | 209 | </item> |
357 | 207 | </layout> | 210 | </layout> |
358 | 208 | 211 | ||
359 | === modified file 'data/qt/ubuntuone.qss' | |||
360 | --- data/qt/ubuntuone.qss 2011-08-12 19:12:08 +0000 | |||
361 | +++ data/qt/ubuntuone.qss 2011-08-25 19:40:18 +0000 | |||
362 | @@ -4,6 +4,8 @@ | |||
363 | 4 | 4 | ||
364 | 5 | QWidget { | 5 | QWidget { |
365 | 6 | font-family: "Ubuntu"; | 6 | font-family: "Ubuntu"; |
366 | 7 | font-size: 13px; | ||
367 | 8 | color: #333333; | ||
368 | 7 | } | 9 | } |
369 | 8 | 10 | ||
370 | 9 | QFrame { | 11 | QFrame { |
371 | @@ -42,59 +44,82 @@ | |||
372 | 42 | border-bottom-width: 1px; | 44 | border-bottom-width: 1px; |
373 | 43 | } | 45 | } |
374 | 44 | 46 | ||
375 | 47 | QFrame#frm_box { /*The Loading Overlay frame.*/ | ||
376 | 48 | background: #ffffff; | ||
377 | 49 | border-radius: 5px; | ||
378 | 50 | border-style: solid; | ||
379 | 51 | border-color: #939389; | ||
380 | 52 | border-width: 1px; | ||
381 | 53 | color: white; | ||
382 | 54 | min-height: 100px; | ||
383 | 55 | } | ||
384 | 56 | |||
385 | 57 | QFrame#frm_box > QLabel { | ||
386 | 58 | font-size: 24px; | ||
387 | 59 | } | ||
388 | 60 | |||
389 | 61 | QPushButton { | ||
390 | 62 | border-radius: 5px; | ||
391 | 63 | border-style: solid; | ||
392 | 64 | padding: 6px; | ||
393 | 65 | padding-left: 20px; | ||
394 | 66 | padding-right: 20px; | ||
395 | 67 | border-width: 1px; | ||
396 | 68 | } | ||
397 | 69 | |||
398 | 45 | QPushButton[enabled="true"] { | 70 | QPushButton[enabled="true"] { |
399 | 46 | background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, | 71 | background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, |
404 | 47 | stop: 0 #fecfc2, stop: 1.0 #e44e19); | 72 | stop: 0 #fe9e84,stop: 1.0 #dd4814); |
401 | 48 | border-radius: 5px; | ||
402 | 49 | border-style: solid; | ||
403 | 50 | padding: 6px; | ||
405 | 51 | color: white; | 73 | color: white; |
409 | 52 | border-color: #939389; | 74 | border-color: #999999; |
407 | 53 | border-width: 1px; | ||
408 | 54 | height: 14px; | ||
410 | 55 | } | 75 | } |
411 | 56 | 76 | ||
412 | 57 | QPushButton:hover[enabled="true"] { | 77 | QPushButton:hover[enabled="true"] { |
413 | 58 | background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, | 78 | background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, |
418 | 59 | stop: 0 #fedad1,stop: 1.0 #e47a55); | 79 | stop: 0 #ffb19c,stop: 1.0 #dd4814); |
415 | 60 | border-radius: 5px; | ||
416 | 61 | border-style: solid; | ||
417 | 62 | padding: 6px; | ||
419 | 63 | color: white; | 80 | color: white; |
423 | 64 | border-color: #939389; | 81 | border-color: #999999; |
421 | 65 | border-width: 1px; | ||
422 | 66 | height: 12px; | ||
424 | 67 | } | 82 | } |
425 | 68 | 83 | ||
426 | 69 | QPushButton:pressed[enabled="true"] { | 84 | QPushButton:pressed[enabled="true"] { |
427 | 70 | background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, | 85 | background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, |
432 | 71 | stop: 0 #e44e19,stop: 1.0 #fecfc2); | 86 | stop: 0 #b93f14,stop: 1.0 #dd4814); |
429 | 72 | border-radius: 5px; | ||
430 | 73 | border-style: solid; | ||
431 | 74 | padding: 6px; | ||
433 | 75 | color: white; | 87 | color: white; |
437 | 76 | border-color: #939389; | 88 | border-color: #999999; |
438 | 77 | border-width: 1px; | 89 | } |
439 | 78 | height: 12px; | 90 | |
440 | 91 | QPushButton[secondary="true"] { | ||
441 | 92 | background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, | ||
442 | 93 | stop: 0 #ffffff,stop: 1.0 #e6e6e6); | ||
443 | 94 | color: #333333; | ||
444 | 95 | border-color: #999999; | ||
445 | 96 | } | ||
446 | 97 | |||
447 | 98 | QPushButton:hover[secondary="true"] { | ||
448 | 99 | background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, | ||
449 | 100 | stop: 0 #ffffff,stop: 1.0 #ededed); | ||
450 | 101 | color: #333333; | ||
451 | 102 | border-color: #999999; | ||
452 | 103 | } | ||
453 | 104 | |||
454 | 105 | QPushButton:pressed[secondary="true"] { | ||
455 | 106 | background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, | ||
456 | 107 | stop: 0 #d9d9d9,stop: 1.0 #fefefe); | ||
457 | 108 | color: #333333; | ||
458 | 109 | border-color: #999999; | ||
459 | 79 | } | 110 | } |
460 | 80 | 111 | ||
461 | 81 | QPushButton[enabled="false"] { | 112 | QPushButton[enabled="false"] { |
462 | 82 | background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, | 113 | background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, |
463 | 83 | stop: 0 #eaeaea, stop: 1.0 #cacaca); | 114 | stop: 0 #eaeaea, stop: 1.0 #cacaca); |
464 | 84 | border-radius: 5px; | ||
465 | 85 | border-style: solid; | ||
466 | 86 | padding: 6px; | ||
467 | 87 | color: #595959; | 115 | color: #595959; |
468 | 88 | border-color: #939389; | 116 | border-color: #939389; |
469 | 89 | border-width: 1px; | ||
470 | 90 | height: 12px; | ||
471 | 91 | } | 117 | } |
472 | 92 | 118 | ||
473 | 93 | QPushButton#help_button { | 119 | QPushButton#help_button { |
474 | 94 | background: transparent; | 120 | background: transparent; |
475 | 95 | border: none; | 121 | border: none; |
476 | 96 | color: white; | 122 | color: white; |
477 | 97 | height: 20px; | ||
478 | 98 | text-decoration: underline; | 123 | text-decoration: underline; |
479 | 99 | padding: 0px; | 124 | padding: 0px; |
480 | 100 | } | 125 | } |
481 | @@ -103,10 +128,13 @@ | |||
482 | 103 | border: none; | 128 | border: none; |
483 | 104 | background: none; | 129 | background: none; |
484 | 105 | color: #595959; | 130 | color: #595959; |
485 | 131 | padding-left: 10px; | ||
486 | 132 | padding-right: 10px; | ||
487 | 106 | } | 133 | } |
488 | 107 | 134 | ||
491 | 108 | QPushButton#add_folder_button { | 135 | QPushButton#twitter_button, |
492 | 109 | padding: 5px; | 136 | QPushButton#facebook_button { |
493 | 137 | border: none; | ||
494 | 110 | } | 138 | } |
495 | 111 | 139 | ||
496 | 112 | GoToWebButton#share_publish_button { | 140 | GoToWebButton#share_publish_button { |
497 | @@ -158,9 +186,7 @@ | |||
498 | 158 | } | 186 | } |
499 | 159 | 187 | ||
500 | 160 | QTabBar::tab:hover { | 188 | QTabBar::tab:hover { |
504 | 161 | background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, | 189 | background: #f6f6f6; |
502 | 162 | stop: 0 #fafafa, stop: 0.4 #f4f4f4, | ||
503 | 163 | stop: 0.5 #e7e7e7, stop: 1.0 #fafafa); | ||
505 | 164 | text-decoration: underline; | 190 | text-decoration: underline; |
506 | 165 | } | 191 | } |
507 | 166 | 192 | ||
508 | @@ -223,20 +249,11 @@ | |||
509 | 223 | color: white; | 249 | color: white; |
510 | 224 | } | 250 | } |
511 | 225 | 251 | ||
512 | 226 | QFrame#frm_box { /* the loadingoverlay frame */ | ||
513 | 227 | background: #ffffff; | ||
514 | 228 | border-radius: 5px; | ||
515 | 229 | border-style: solid; | ||
516 | 230 | border-color: #939389; | ||
517 | 231 | border-width: 1px; | ||
518 | 232 | color: white; | ||
519 | 233 | min-height: 100px; | ||
520 | 234 | } | ||
521 | 235 | |||
522 | 236 | QAbstractItemView { | 252 | QAbstractItemView { |
523 | 237 | border-style: solid; | 253 | border-style: solid; |
528 | 238 | border-color: #333333; | 254 | border-color: #898989; |
529 | 239 | border-width: 1px; | 255 | border-top-width: 1px; |
530 | 240 | alternate-background-color: #efedec; | 256 | border-bottom-width: 1px; |
531 | 241 | background: #f7f6f5; | 257 | alternate-background-color: #f7f6f5; |
532 | 258 | background: #efedec; | ||
533 | 242 | } | 259 | } |
534 | 243 | 260 | ||
535 | === modified file 'data/twitter.png' | |||
536 | 244 | Binary files data/twitter.png 2011-01-25 19:08:59 +0000 and data/twitter.png 2011-08-25 19:40:18 +0000 differ | 261 | Binary files data/twitter.png 2011-01-25 19:08:59 +0000 and data/twitter.png 2011-08-25 19:40:18 +0000 differ |
537 | === modified file 'debian/changelog' | |||
538 | --- debian/changelog 2011-08-12 19:13:51 +0000 | |||
539 | +++ debian/changelog 2011-08-25 19:40:18 +0000 | |||
540 | @@ -1,3 +1,10 @@ | |||
541 | 1 | ubuntuone-control-panel (1.1.3-0ubuntu1) oneiric; urgency=low | ||
542 | 2 | |||
543 | 3 | * New upstream release. | ||
544 | 4 | - Work correctly with static and GI bindings of gobject (LP: #829186) | ||
545 | 5 | |||
546 | 6 | -- Rodney Dawes <rodney.dawes@ubuntu.com> Thu, 25 Aug 2011 15:37:15 -0400 | ||
547 | 7 | |||
548 | 1 | ubuntuone-control-panel (1.1.2-0ubuntu1) oneiric; urgency=low | 8 | ubuntuone-control-panel (1.1.2-0ubuntu1) oneiric; urgency=low |
549 | 2 | 9 | ||
550 | 3 | * New upstream release. | 10 | * New upstream release. |
551 | 4 | 11 | ||
552 | === modified file 'po/ubuntuone-control-panel.pot' | |||
553 | --- po/ubuntuone-control-panel.pot 2011-08-12 19:12:08 +0000 | |||
554 | +++ po/ubuntuone-control-panel.pot 2011-08-25 19:40:18 +0000 | |||
555 | @@ -8,7 +8,7 @@ | |||
556 | 8 | msgstr "" | 8 | msgstr "" |
557 | 9 | "Project-Id-Version: PACKAGE VERSION\n" | 9 | "Project-Id-Version: PACKAGE VERSION\n" |
558 | 10 | "Report-Msgid-Bugs-To: \n" | 10 | "Report-Msgid-Bugs-To: \n" |
560 | 11 | "POT-Creation-Date: 2011-08-12 15:07-0400\n" | 11 | "POT-Creation-Date: 2011-08-25 15:26-0400\n" |
561 | 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
562 | 13 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | 13 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
563 | 14 | "Language-Team: LANGUAGE <LL@li.org>\n" | 14 | "Language-Team: LANGUAGE <LL@li.org>\n" |
564 | 15 | 15 | ||
565 | === modified file 'run-tests' | |||
566 | --- run-tests 2011-07-22 21:26:48 +0000 | |||
567 | +++ run-tests 2011-08-25 19:40:18 +0000 | |||
568 | @@ -37,14 +37,16 @@ | |||
569 | 37 | fi | 37 | fi |
570 | 38 | 38 | ||
571 | 39 | style_check() { | 39 | style_check() { |
573 | 40 | u1lint --ignore ubuntuone/controlpanel/gui/qt/ui ubuntuone/ | 40 | u1lint --ignore ubuntuone/controlpanel/gui/qt/ui |
574 | 41 | if [ -x `which pep8` ]; then | 41 | if [ -x `which pep8` ]; then |
576 | 42 | pep8 --exclude '.svn,CVS,.bzr,.hg,.git,*_ui.py,*_rc.py' --repeat bin/ $MODULE | 42 | pep8 --exclude '.svn,CVS,.bzr,.hg,.git,*_ui.py,*_rc.py' --repeat . |
577 | 43 | else | 43 | else |
578 | 44 | echo "Please install the 'pep8' package." | 44 | echo "Please install the 'pep8' package." |
579 | 45 | fi | 45 | fi |
580 | 46 | } | 46 | } |
581 | 47 | 47 | ||
582 | 48 | unset GTK_MODULES | ||
583 | 49 | |||
584 | 48 | ./setup.py build | 50 | ./setup.py build |
585 | 49 | echo "Running test suite for ""$MODULE" | 51 | echo "Running test suite for ""$MODULE" |
586 | 50 | if [ "$USE_QT" -eq 0 ]; then | 52 | if [ "$USE_QT" -eq 0 ]; then |
587 | 51 | 53 | ||
588 | === modified file 'run-tests.bat' | |||
589 | --- run-tests.bat 2011-07-22 21:26:48 +0000 | |||
590 | +++ run-tests.bat 2011-08-25 19:40:18 +0000 | |||
591 | @@ -30,7 +30,7 @@ | |||
592 | 30 | ECHO Cleaning the generated code before running the style checks... | 30 | ECHO Cleaning the generated code before running the style checks... |
593 | 31 | "%PYTHONEXEPATH%\python.exe" setup.py clean | 31 | "%PYTHONEXEPATH%\python.exe" setup.py clean |
594 | 32 | ECHO Performing style checks... | 32 | ECHO Performing style checks... |
596 | 33 | "%PYTHONEXEPATH%\Scripts\u1lint.exe" --ignore ubuntuone\controlpanel\gui\qt\ui "%MODULE%" | 33 | "%PYTHONEXEPATH%\python.exe" "%PYTHONEXEPATH%\Scripts\u1lint" --ignore ubuntuone\controlpanel\gui\qt\ui "%MODULE%" |
597 | 34 | "%PYTHONEXEPATH%\Scripts\pep8.exe" --exclude ".svn,CVS,.bzr,.hg,.git,*_ui.py,*_rc.py" --repeat . | 34 | "%PYTHONEXEPATH%\Scripts\pep8.exe" --exclude ".svn,CVS,.bzr,.hg,.git,*_ui.py,*_rc.py" --repeat . |
598 | 35 | :: Delete the temp folders | 35 | :: Delete the temp folders |
599 | 36 | RMDIR /s /q _trial_temp | 36 | RMDIR /s /q _trial_temp |
600 | 37 | 37 | ||
601 | === modified file 'setup.py' | |||
602 | --- setup.py 2011-08-12 19:12:08 +0000 | |||
603 | +++ setup.py 2011-08-25 19:40:18 +0000 | |||
604 | @@ -46,6 +46,7 @@ | |||
605 | 46 | CLEANFILES = [ | 46 | CLEANFILES = [ |
606 | 47 | SERVICE_FILE, GUI_SERVICE_FILE, MESSAGE_ENTRY, CONSTANTS, POT_FILE, | 47 | SERVICE_FILE, GUI_SERVICE_FILE, MESSAGE_ENTRY, CONSTANTS, POT_FILE, |
607 | 48 | 'MANIFEST'] | 48 | 'MANIFEST'] |
608 | 49 | QT_UI_DIR = os.path.join('ubuntuone', 'controlpanel', 'gui', 'qt', 'ui') | ||
609 | 49 | 50 | ||
610 | 50 | 51 | ||
611 | 51 | def replace_prefix(prefix): | 52 | def replace_prefix(prefix): |
612 | @@ -64,7 +65,7 @@ | |||
613 | 64 | def run(self): | 65 | def run(self): |
614 | 65 | """Do the install. | 66 | """Do the install. |
615 | 66 | 67 | ||
617 | 67 | Read from *.service.in and generate .service files with reeplacing | 68 | Read from *.service.in and generate .service files by replacing |
618 | 68 | @prefix@ by self.prefix. | 69 | @prefix@ by self.prefix. |
619 | 69 | 70 | ||
620 | 70 | """ | 71 | """ |
621 | @@ -75,7 +76,6 @@ | |||
622 | 75 | class ControlPanelBuild(build_extra.build_extra): | 76 | class ControlPanelBuild(build_extra.build_extra): |
623 | 76 | """Build PyQt (.ui) files and resources.""" | 77 | """Build PyQt (.ui) files and resources.""" |
624 | 77 | 78 | ||
625 | 78 | QT_UI_DIR = os.path.join('ubuntuone', 'controlpanel', 'gui', 'qt', 'ui') | ||
626 | 79 | description = "build PyQt GUIs (.ui) and resources (.qrc)" | 79 | description = "build PyQt GUIs (.ui) and resources (.qrc)" |
627 | 80 | 80 | ||
628 | 81 | def compile_ui(self, ui_file, py_file=None): | 81 | def compile_ui(self, ui_file, py_file=None): |
629 | @@ -86,7 +86,7 @@ | |||
630 | 86 | # python file in the qt moodule | 86 | # python file in the qt moodule |
631 | 87 | py_file = os.path.split(ui_file)[1] | 87 | py_file = os.path.split(ui_file)[1] |
632 | 88 | py_file = os.path.splitext(py_file)[0] + '_ui.py' | 88 | py_file = os.path.splitext(py_file)[0] + '_ui.py' |
634 | 89 | py_file = os.path.join(self.QT_UI_DIR, py_file) | 89 | py_file = os.path.join(QT_UI_DIR, py_file) |
635 | 90 | # we indeed want to catch Exception, is ugly but we need it | 90 | # we indeed want to catch Exception, is ugly but we need it |
636 | 91 | # pylint: disable=W0703 | 91 | # pylint: disable=W0703 |
637 | 92 | try: | 92 | try: |
638 | @@ -112,7 +112,7 @@ | |||
639 | 112 | if py_file is None: | 112 | if py_file is None: |
640 | 113 | py_file = os.path.split(qrc_file)[1] | 113 | py_file = os.path.split(qrc_file)[1] |
641 | 114 | py_file = os.path.splitext(py_file)[0] + '_rc.py' | 114 | py_file = os.path.splitext(py_file)[0] + '_rc.py' |
643 | 115 | py_file = os.path.join(self.QT_UI_DIR, py_file) | 115 | py_file = os.path.join(QT_UI_DIR, py_file) |
644 | 116 | path = os.getenv('PATH') | 116 | path = os.getenv('PATH') |
645 | 117 | os.putenv('PATH', path + os.path.pathsep + os.path.join( | 117 | os.putenv('PATH', path + os.path.pathsep + os.path.join( |
646 | 118 | os.path.dirname(PyQt4.__file__), 'bin')) | 118 | os.path.dirname(PyQt4.__file__), 'bin')) |
647 | @@ -218,18 +218,24 @@ | |||
648 | 218 | if os.path.exists(built_file): | 218 | if os.path.exists(built_file): |
649 | 219 | os.unlink(built_file) | 219 | os.unlink(built_file) |
650 | 220 | 220 | ||
651 | 221 | for dirpath, _, filenames in os.walk(os.path.join(QT_UI_DIR)): | ||
652 | 222 | for current_file in filenames: | ||
653 | 223 | if current_file.endswith('_ui.py') or\ | ||
654 | 224 | current_file.endswith('_rc.py'): | ||
655 | 225 | os.unlink(os.path.join(dirpath, current_file)) | ||
656 | 226 | |||
657 | 221 | DistUtilsExtra.auto.clean_build_tree.run(self) | 227 | DistUtilsExtra.auto.clean_build_tree.run(self) |
658 | 222 | 228 | ||
659 | 223 | 229 | ||
660 | 224 | DistUtilsExtra.auto.setup( | 230 | DistUtilsExtra.auto.setup( |
661 | 225 | name='ubuntuone-control-panel', | 231 | name='ubuntuone-control-panel', |
663 | 226 | version='1.1.2', | 232 | version='1.1.3', |
664 | 227 | license='GPL v3', | 233 | license='GPL v3', |
665 | 228 | author='Natalia Bidart', | 234 | author='Natalia Bidart', |
666 | 229 | author_email='natalia.bidart@canonical.com', | 235 | author_email='natalia.bidart@canonical.com', |
667 | 230 | description='Ubuntu One Control Panel', | 236 | description='Ubuntu One Control Panel', |
670 | 231 | long_description='Application to manage a Ubuntu One account. Provides a'\ | 237 | long_description='Application to manage a Ubuntu One account. Provides' \ |
671 | 232 | 'DBus service to query/modify all the Ubuntu One bits.', | 238 | ' a DBus service to query/modify all the Ubuntu One bits.', |
672 | 233 | url='https://launchpad.net/ubuntuone-control-panel', | 239 | url='https://launchpad.net/ubuntuone-control-panel', |
673 | 234 | packages=[ | 240 | packages=[ |
674 | 235 | 'ubuntuone', 'ubuntuone.controlpanel', 'ubuntuone.controlpanel.gui', | 241 | 'ubuntuone', 'ubuntuone.controlpanel', 'ubuntuone.controlpanel.gui', |
675 | 236 | 242 | ||
676 | === modified file 'ubuntuone/controlpanel/backend.py' | |||
677 | --- ubuntuone/controlpanel/backend.py 2011-08-12 19:12:08 +0000 | |||
678 | +++ ubuntuone/controlpanel/backend.py 2011-08-25 19:40:18 +0000 | |||
679 | @@ -27,11 +27,12 @@ | |||
680 | 27 | 27 | ||
681 | 28 | from twisted.internet.defer import inlineCallbacks, returnValue | 28 | from twisted.internet.defer import inlineCallbacks, returnValue |
682 | 29 | # No name 'is_link' in module 'ubuntuone.platform' | 29 | # No name 'is_link' in module 'ubuntuone.platform' |
684 | 30 | # pylint: disable=E0611 | 30 | # pylint: disable=E0611, F0401 |
685 | 31 | from ubuntuone.platform import is_link | 31 | from ubuntuone.platform import is_link |
687 | 32 | # pylint: enable=E0611 | 32 | from ubuntuone.platform.credentials import CredentialsManagementTool |
688 | 33 | # pylint: enable=E0611, F0401 | ||
689 | 33 | 34 | ||
691 | 34 | from ubuntuone.controlpanel import login_client, sd_client, replication_client | 35 | from ubuntuone.controlpanel import sd_client, replication_client |
692 | 35 | from ubuntuone.controlpanel.logger import setup_logging, log_call | 36 | from ubuntuone.controlpanel.logger import setup_logging, log_call |
693 | 36 | # pylint: disable=W0611 | 37 | # pylint: disable=W0611 |
694 | 37 | from ubuntuone.controlpanel.web_client import (UnauthorizedError, | 38 | from ubuntuone.controlpanel.web_client import (UnauthorizedError, |
695 | @@ -92,13 +93,13 @@ | |||
696 | 92 | 93 | ||
697 | 93 | @inlineCallbacks | 94 | @inlineCallbacks |
698 | 94 | @wraps(f) | 95 | @wraps(f) |
700 | 95 | def inner(*args, **kwargs): | 96 | def inner(instance, *args, **kwargs): |
701 | 96 | """Handle UnauthorizedError and clear credentials.""" | 97 | """Handle UnauthorizedError and clear credentials.""" |
702 | 97 | try: | 98 | try: |
704 | 98 | result = yield f(*args, **kwargs) | 99 | result = yield f(instance, *args, **kwargs) |
705 | 99 | except UnauthorizedError, e: | 100 | except UnauthorizedError, e: |
706 | 100 | logger.exception('process_unauthorized (clearing credentials):') | 101 | logger.exception('process_unauthorized (clearing credentials):') |
708 | 101 | yield login_client.clear_credentials() | 102 | yield instance.login_client.clear_credentials() |
709 | 102 | raise e | 103 | raise e |
710 | 103 | 104 | ||
711 | 104 | returnValue(result) | 105 | returnValue(result) |
712 | @@ -126,13 +127,17 @@ | |||
713 | 126 | 127 | ||
714 | 127 | def __init__(self, shutdown_func=None): | 128 | def __init__(self, shutdown_func=None): |
715 | 128 | """Initialize the web_client.""" | 129 | """Initialize the web_client.""" |
716 | 129 | self.shutdown_func = shutdown_func | ||
717 | 130 | self.wc = web_client_factory(login_client.get_credentials) | ||
718 | 131 | self._status_changed_handler = None | 130 | self._status_changed_handler = None |
720 | 132 | 131 | self._credentials = None | |
721 | 133 | self._volumes = {} # cache last known volume info | 132 | self._volumes = {} # cache last known volume info |
722 | 133 | |||
723 | 134 | self.shutdown_func = shutdown_func | ||
724 | 134 | self.file_sync_disabled = False | 135 | self.file_sync_disabled = False |
725 | 135 | 136 | ||
726 | 137 | self.login_client = CredentialsManagementTool() | ||
727 | 138 | self.sd_client = sd_client.SyncDaemonClient() | ||
728 | 139 | self.wc = web_client_factory(self.get_credentials) | ||
729 | 140 | |||
730 | 136 | def _process_file_sync_status(self, status): | 141 | def _process_file_sync_status(self, status): |
731 | 137 | """Process raw file sync status into custom format. | 142 | """Process raw file sync status into custom format. |
732 | 138 | 143 | ||
733 | @@ -194,11 +199,7 @@ | |||
734 | 194 | handler(result) | 199 | handler(result) |
735 | 195 | 200 | ||
736 | 196 | self._status_changed_handler = handler | 201 | self._status_changed_handler = handler |
742 | 197 | 202 | self.sd_client.set_status_changed_handler(process_and_callback) | |
738 | 198 | # XXX: since windows version of sd_client still don't have a way of | ||
739 | 199 | # setting a status changed handler, we'll be robust by doing this check | ||
740 | 200 | if getattr(sd_client, 'set_status_changed_handler', None) is not None: | ||
741 | 201 | sd_client.set_status_changed_handler(process_and_callback) | ||
743 | 202 | 203 | ||
744 | 203 | def _get_status_changed_handler(self): | 204 | def _get_status_changed_handler(self): |
745 | 204 | """Return the handler to be called when file sync status changes.""" | 205 | """Return the handler to be called when file sync status changes.""" |
746 | @@ -263,7 +264,7 @@ | |||
747 | 263 | If all the file sync settings are None, do not attach that info. | 264 | If all the file sync settings are None, do not attach that info. |
748 | 264 | 265 | ||
749 | 265 | """ | 266 | """ |
751 | 266 | credentials = yield login_client.get_credentials() | 267 | credentials = yield self.get_credentials() |
752 | 267 | 268 | ||
753 | 268 | local_device = {} | 269 | local_device = {} |
754 | 269 | local_device["type"] = DEVICE_TYPE_COMPUTER | 270 | local_device["type"] = DEVICE_TYPE_COMPUTER |
755 | @@ -294,9 +295,16 @@ | |||
756 | 294 | return result | 295 | return result |
757 | 295 | 296 | ||
758 | 296 | @inlineCallbacks | 297 | @inlineCallbacks |
759 | 298 | def get_credentials(self): | ||
760 | 299 | """Find credentials.""" | ||
761 | 300 | if self._credentials is None: | ||
762 | 301 | self._credentials = yield self.login_client.find_credentials() | ||
763 | 302 | returnValue(self._credentials) | ||
764 | 303 | |||
765 | 304 | @inlineCallbacks | ||
766 | 297 | def get_token(self): | 305 | def get_token(self): |
767 | 298 | """Return the token from the credentials.""" | 306 | """Return the token from the credentials.""" |
769 | 299 | credentials = yield login_client.get_credentials() | 307 | credentials = yield self.get_credentials() |
770 | 300 | returnValue(credentials["token"]) | 308 | returnValue(credentials["token"]) |
771 | 301 | 309 | ||
772 | 302 | @inlineCallbacks | 310 | @inlineCallbacks |
773 | @@ -344,25 +352,25 @@ | |||
774 | 344 | autoconnect = show_notifs = None | 352 | autoconnect = show_notifs = None |
775 | 345 | share_autosubscribe = udf_autosubscribe = None | 353 | share_autosubscribe = udf_autosubscribe = None |
776 | 346 | 354 | ||
778 | 347 | enabled = yield sd_client.files_sync_enabled() | 355 | enabled = yield self.sd_client.files_sync_enabled() |
779 | 348 | enabled = bool(enabled) | 356 | enabled = bool(enabled) |
780 | 349 | if enabled: | 357 | if enabled: |
782 | 350 | sd_res = yield sd_client.autoconnect_enabled() | 358 | sd_res = yield self.sd_client.autoconnect_enabled() |
783 | 351 | autoconnect = bool(sd_res) | 359 | autoconnect = bool(sd_res) |
784 | 352 | 360 | ||
786 | 353 | sd_res = yield sd_client.show_all_notifications_enabled() | 361 | sd_res = yield self.sd_client.show_all_notifications_enabled() |
787 | 354 | show_notifs = bool(sd_res) | 362 | show_notifs = bool(sd_res) |
788 | 355 | 363 | ||
790 | 356 | sd_res = yield sd_client.share_autosubscribe_enabled() | 364 | sd_res = yield self.sd_client.share_autosubscribe_enabled() |
791 | 357 | share_autosubscribe = bool(sd_res) | 365 | share_autosubscribe = bool(sd_res) |
792 | 358 | 366 | ||
794 | 359 | sd_res = yield sd_client.udf_autosubscribe_enabled() | 367 | sd_res = yield self.sd_client.udf_autosubscribe_enabled() |
795 | 360 | udf_autosubscribe = bool(sd_res) | 368 | udf_autosubscribe = bool(sd_res) |
796 | 361 | 369 | ||
798 | 362 | sd_res = yield sd_client.bandwidth_throttling_enabled() | 370 | sd_res = yield self.sd_client.bandwidth_throttling_enabled() |
799 | 363 | limit_bw = bool(sd_res) | 371 | limit_bw = bool(sd_res) |
800 | 364 | 372 | ||
802 | 365 | limits = yield sd_client.get_throttling_limits() | 373 | limits = yield self.sd_client.get_throttling_limits() |
803 | 366 | 374 | ||
804 | 367 | logger.debug('devices_info: file sync enabled? %s limit_bw %s, limits ' | 375 | logger.debug('devices_info: file sync enabled? %s limit_bw %s, limits ' |
805 | 368 | '%s, autoconnect %s, show_notifs %s, ' | 376 | '%s, autoconnect %s, show_notifs %s, ' |
806 | @@ -432,19 +440,19 @@ | |||
807 | 432 | 440 | ||
808 | 433 | if is_local and SHOW_ALL_NOTIFICATIONS_KEY in settings: | 441 | if is_local and SHOW_ALL_NOTIFICATIONS_KEY in settings: |
809 | 434 | if not settings[SHOW_ALL_NOTIFICATIONS_KEY]: | 442 | if not settings[SHOW_ALL_NOTIFICATIONS_KEY]: |
811 | 435 | yield sd_client.disable_show_all_notifications() | 443 | yield self.sd_client.disable_show_all_notifications() |
812 | 436 | else: | 444 | else: |
814 | 437 | yield sd_client.enable_show_all_notifications() | 445 | yield self.sd_client.enable_show_all_notifications() |
815 | 438 | 446 | ||
816 | 439 | if is_local and LIMIT_BW_KEY in settings: | 447 | if is_local and LIMIT_BW_KEY in settings: |
817 | 440 | if not settings[LIMIT_BW_KEY]: | 448 | if not settings[LIMIT_BW_KEY]: |
819 | 441 | yield sd_client.disable_bandwidth_throttling() | 449 | yield self.sd_client.disable_bandwidth_throttling() |
820 | 442 | else: | 450 | else: |
822 | 443 | yield sd_client.enable_bandwidth_throttling() | 451 | yield self.sd_client.enable_bandwidth_throttling() |
823 | 444 | 452 | ||
824 | 445 | if is_local and (UPLOAD_KEY in settings or | 453 | if is_local and (UPLOAD_KEY in settings or |
825 | 446 | DOWNLOAD_KEY in settings): | 454 | DOWNLOAD_KEY in settings): |
827 | 447 | current_limits = yield sd_client.get_throttling_limits() | 455 | current_limits = yield self.sd_client.get_throttling_limits() |
828 | 448 | limits = { | 456 | limits = { |
829 | 449 | "download": current_limits["download"], | 457 | "download": current_limits["download"], |
830 | 450 | "upload": current_limits["upload"], | 458 | "upload": current_limits["upload"], |
831 | @@ -453,7 +461,7 @@ | |||
832 | 453 | limits["upload"] = settings[UPLOAD_KEY] | 461 | limits["upload"] = settings[UPLOAD_KEY] |
833 | 454 | if DOWNLOAD_KEY in settings: | 462 | if DOWNLOAD_KEY in settings: |
834 | 455 | limits["download"] = settings[DOWNLOAD_KEY] | 463 | limits["download"] = settings[DOWNLOAD_KEY] |
836 | 456 | sd_client.set_throttling_limits(limits) | 464 | self.sd_client.set_throttling_limits(limits) |
837 | 457 | 465 | ||
838 | 458 | # still pending: more work on the settings dict (LP: #673674) | 466 | # still pending: more work on the settings dict (LP: #673674) |
839 | 459 | returnValue(device_id) | 467 | returnValue(device_id) |
840 | @@ -472,7 +480,7 @@ | |||
841 | 472 | if is_local: | 480 | if is_local: |
842 | 473 | logger.warning('remove_device: device is local! removing and ' | 481 | logger.warning('remove_device: device is local! removing and ' |
843 | 474 | 'clearing credentials.') | 482 | 'clearing credentials.') |
845 | 475 | yield login_client.clear_credentials() | 483 | yield self.login_client.clear_credentials() |
846 | 476 | 484 | ||
847 | 477 | returnValue(device_id) | 485 | returnValue(device_id) |
848 | 478 | 486 | ||
849 | @@ -480,9 +488,9 @@ | |||
850 | 480 | @inlineCallbacks | 488 | @inlineCallbacks |
851 | 481 | def file_sync_status(self): | 489 | def file_sync_status(self): |
852 | 482 | """Return the status of the file sync service.""" | 490 | """Return the status of the file sync service.""" |
854 | 483 | enabled = yield sd_client.files_sync_enabled() | 491 | enabled = yield self.sd_client.files_sync_enabled() |
855 | 484 | if enabled: | 492 | if enabled: |
857 | 485 | status = yield sd_client.get_current_status() | 493 | status = yield self.sd_client.get_current_status() |
858 | 486 | else: | 494 | else: |
859 | 487 | status = {} | 495 | status = {} |
860 | 488 | returnValue(self._process_file_sync_status(status)) | 496 | returnValue(self._process_file_sync_status(status)) |
861 | @@ -491,46 +499,46 @@ | |||
862 | 491 | @inlineCallbacks | 499 | @inlineCallbacks |
863 | 492 | def enable_files(self): | 500 | def enable_files(self): |
864 | 493 | """Enable the files service.""" | 501 | """Enable the files service.""" |
866 | 494 | yield sd_client.set_files_sync_enabled(True) | 502 | yield self.sd_client.set_files_sync_enabled(True) |
867 | 495 | self.file_sync_disabled = False | 503 | self.file_sync_disabled = False |
868 | 496 | 504 | ||
869 | 497 | @log_call(logger.debug) | 505 | @log_call(logger.debug) |
870 | 498 | @inlineCallbacks | 506 | @inlineCallbacks |
871 | 499 | def disable_files(self): | 507 | def disable_files(self): |
872 | 500 | """Enable the files service.""" | 508 | """Enable the files service.""" |
874 | 501 | yield sd_client.set_files_sync_enabled(False) | 509 | yield self.sd_client.set_files_sync_enabled(False) |
875 | 502 | self.file_sync_disabled = True | 510 | self.file_sync_disabled = True |
876 | 503 | 511 | ||
877 | 504 | @log_call(logger.debug) | 512 | @log_call(logger.debug) |
878 | 505 | @inlineCallbacks | 513 | @inlineCallbacks |
879 | 506 | def connect_files(self): | 514 | def connect_files(self): |
880 | 507 | """Connect the files service.""" | 515 | """Connect the files service.""" |
882 | 508 | yield sd_client.connect_file_sync() | 516 | yield self.sd_client.connect_file_sync() |
883 | 509 | 517 | ||
884 | 510 | @log_call(logger.debug) | 518 | @log_call(logger.debug) |
885 | 511 | @inlineCallbacks | 519 | @inlineCallbacks |
886 | 512 | def disconnect_files(self): | 520 | def disconnect_files(self): |
887 | 513 | """Disconnect the files service.""" | 521 | """Disconnect the files service.""" |
889 | 514 | yield sd_client.disconnect_file_sync() | 522 | yield self.sd_client.disconnect_file_sync() |
890 | 515 | 523 | ||
891 | 516 | @log_call(logger.debug) | 524 | @log_call(logger.debug) |
892 | 517 | @inlineCallbacks | 525 | @inlineCallbacks |
893 | 518 | def restart_files(self): | 526 | def restart_files(self): |
894 | 519 | """restart the files service.""" | 527 | """restart the files service.""" |
897 | 520 | yield sd_client.stop_file_sync() | 528 | yield self.sd_client.stop_file_sync() |
898 | 521 | yield sd_client.start_file_sync() | 529 | yield self.sd_client.start_file_sync() |
899 | 522 | 530 | ||
900 | 523 | @log_call(logger.debug) | 531 | @log_call(logger.debug) |
901 | 524 | @inlineCallbacks | 532 | @inlineCallbacks |
902 | 525 | def start_files(self): | 533 | def start_files(self): |
903 | 526 | """start the files service.""" | 534 | """start the files service.""" |
905 | 527 | yield sd_client.start_file_sync() | 535 | yield self.sd_client.start_file_sync() |
906 | 528 | 536 | ||
907 | 529 | @log_call(logger.debug) | 537 | @log_call(logger.debug) |
908 | 530 | @inlineCallbacks | 538 | @inlineCallbacks |
909 | 531 | def stop_files(self): | 539 | def stop_files(self): |
910 | 532 | """stop the files service.""" | 540 | """stop the files service.""" |
912 | 533 | yield sd_client.stop_file_sync() | 541 | yield self.sd_client.stop_file_sync() |
913 | 534 | 542 | ||
914 | 535 | @log_call(logger.debug) | 543 | @log_call(logger.debug) |
915 | 536 | @inlineCallbacks | 544 | @inlineCallbacks |
916 | @@ -547,11 +555,11 @@ | |||
917 | 547 | else: | 555 | else: |
918 | 548 | free_bytes = account['quota_total'] - account['quota_used'] | 556 | free_bytes = account['quota_total'] - account['quota_used'] |
919 | 549 | 557 | ||
925 | 550 | root_dir = yield sd_client.get_root_dir() | 558 | root_dir = yield self.sd_client.get_root_dir() |
926 | 551 | shares_dir = yield sd_client.get_shares_dir() | 559 | shares_dir = yield self.sd_client.get_shares_dir() |
927 | 552 | shares_dir_link = yield sd_client.get_shares_dir_link() | 560 | shares_dir_link = yield self.sd_client.get_shares_dir_link() |
928 | 553 | folders = yield sd_client.get_folders() | 561 | folders = yield self.sd_client.get_folders() |
929 | 554 | shares = yield sd_client.get_shares() | 562 | shares = yield self.sd_client.get_shares() |
930 | 555 | 563 | ||
931 | 556 | root_volume = {u'volume_id': u'', u'path': root_dir, | 564 | root_volume = {u'volume_id': u'', u'path': root_dir, |
932 | 557 | u'subscribed': True, u'type': self.ROOT_TYPE, | 565 | u'subscribed': True, u'type': self.ROOT_TYPE, |
933 | @@ -630,23 +638,23 @@ | |||
934 | 630 | def subscribe_volume(self, volume_id): | 638 | def subscribe_volume(self, volume_id): |
935 | 631 | """Subscribe to 'volume_id'.""" | 639 | """Subscribe to 'volume_id'.""" |
936 | 632 | if self._volumes[volume_id][u'type'] == self.FOLDER_TYPE: | 640 | if self._volumes[volume_id][u'type'] == self.FOLDER_TYPE: |
938 | 633 | yield sd_client.subscribe_folder(volume_id) | 641 | yield self.sd_client.subscribe_folder(volume_id) |
939 | 634 | elif self._volumes[volume_id][u'type'] == self.SHARE_TYPE: | 642 | elif self._volumes[volume_id][u'type'] == self.SHARE_TYPE: |
941 | 635 | yield sd_client.subscribe_share(volume_id) | 643 | yield self.sd_client.subscribe_share(volume_id) |
942 | 636 | 644 | ||
943 | 637 | @inlineCallbacks | 645 | @inlineCallbacks |
944 | 638 | def unsubscribe_volume(self, volume_id): | 646 | def unsubscribe_volume(self, volume_id): |
945 | 639 | """Unsubscribe from 'volume_id'.""" | 647 | """Unsubscribe from 'volume_id'.""" |
946 | 640 | if self._volumes[volume_id][u'type'] == self.FOLDER_TYPE: | 648 | if self._volumes[volume_id][u'type'] == self.FOLDER_TYPE: |
948 | 641 | yield sd_client.unsubscribe_folder(volume_id) | 649 | yield self.sd_client.unsubscribe_folder(volume_id) |
949 | 642 | elif self._volumes[volume_id][u'type'] == self.SHARE_TYPE: | 650 | elif self._volumes[volume_id][u'type'] == self.SHARE_TYPE: |
951 | 643 | yield sd_client.unsubscribe_share(volume_id) | 651 | yield self.sd_client.unsubscribe_share(volume_id) |
952 | 644 | 652 | ||
953 | 645 | @log_call(logger.debug) | 653 | @log_call(logger.debug) |
954 | 646 | @inlineCallbacks | 654 | @inlineCallbacks |
955 | 647 | def create_folder(self, folder_path): | 655 | def create_folder(self, folder_path): |
956 | 648 | """Create a new User Defined Folder pointing to 'folder_path'.""" | 656 | """Create a new User Defined Folder pointing to 'folder_path'.""" |
958 | 649 | yield sd_client.create_folder(path=folder_path) | 657 | yield self.sd_client.create_folder(path=folder_path) |
959 | 650 | 658 | ||
960 | 651 | @log_call(logger.debug) | 659 | @log_call(logger.debug) |
961 | 652 | @inlineCallbacks | 660 | @inlineCallbacks |
962 | @@ -728,11 +736,11 @@ | |||
963 | 728 | 736 | ||
964 | 729 | for name in (AUTOCONNECT_KEY, SHOW_ALL_NOTIFICATIONS_KEY, | 737 | for name in (AUTOCONNECT_KEY, SHOW_ALL_NOTIFICATIONS_KEY, |
965 | 730 | SHARE_AUTOSUBSCRIBE_KEY, UDF_AUTOSUBSCRIBE_KEY): | 738 | SHARE_AUTOSUBSCRIBE_KEY, UDF_AUTOSUBSCRIBE_KEY): |
967 | 731 | sd_method = getattr(sd_client, '%s_enabled' % name) | 739 | sd_method = getattr(self.sd_client, '%s_enabled' % name) |
968 | 732 | value = yield sd_method() | 740 | value = yield sd_method() |
969 | 733 | result[name] = bool(value) | 741 | result[name] = bool(value) |
970 | 734 | 742 | ||
972 | 735 | limits = yield sd_client.get_throttling_limits() | 743 | limits = yield self.sd_client.get_throttling_limits() |
973 | 736 | result[DOWNLOAD_KEY] = limits['download'] | 744 | result[DOWNLOAD_KEY] = limits['download'] |
974 | 737 | result[UPLOAD_KEY] = limits['upload'] | 745 | result[UPLOAD_KEY] = limits['upload'] |
975 | 738 | 746 | ||
976 | @@ -744,7 +752,7 @@ | |||
977 | 744 | if setting_name in settings: | 752 | if setting_name in settings: |
978 | 745 | new_value = settings[setting_name] | 753 | new_value = settings[setting_name] |
979 | 746 | sd_method_name = 'enable_%s' if new_value else 'disable_%s' | 754 | sd_method_name = 'enable_%s' if new_value else 'disable_%s' |
981 | 747 | sd_method = getattr(sd_client, sd_method_name % setting_name) | 755 | sd_method = getattr(self.sd_client, sd_method_name % setting_name) |
982 | 748 | yield sd_method() | 756 | yield sd_method() |
983 | 749 | 757 | ||
984 | 750 | @log_call(logger.info) | 758 | @log_call(logger.info) |
985 | @@ -756,7 +764,7 @@ | |||
986 | 756 | yield self._change_boolean_file_sync_setting(name, settings) | 764 | yield self._change_boolean_file_sync_setting(name, settings) |
987 | 757 | 765 | ||
988 | 758 | if DOWNLOAD_KEY in settings or UPLOAD_KEY in settings: | 766 | if DOWNLOAD_KEY in settings or UPLOAD_KEY in settings: |
990 | 759 | current_limits = yield sd_client.get_throttling_limits() | 767 | current_limits = yield self.sd_client.get_throttling_limits() |
991 | 760 | limits = { | 768 | limits = { |
992 | 761 | "download": current_limits["download"], | 769 | "download": current_limits["download"], |
993 | 762 | "upload": current_limits["upload"], | 770 | "upload": current_limits["upload"], |
994 | @@ -765,13 +773,13 @@ | |||
995 | 765 | limits["upload"] = settings[UPLOAD_KEY] | 773 | limits["upload"] = settings[UPLOAD_KEY] |
996 | 766 | if DOWNLOAD_KEY in settings: | 774 | if DOWNLOAD_KEY in settings: |
997 | 767 | limits["download"] = settings[DOWNLOAD_KEY] | 775 | limits["download"] = settings[DOWNLOAD_KEY] |
999 | 768 | yield sd_client.set_throttling_limits(limits) | 776 | yield self.sd_client.set_throttling_limits(limits) |
1000 | 769 | 777 | ||
1001 | 770 | throttling_disabled = sum(limits.itervalues()) == -2 | 778 | throttling_disabled = sum(limits.itervalues()) == -2 |
1002 | 771 | if throttling_disabled: | 779 | if throttling_disabled: |
1004 | 772 | yield sd_client.disable_bandwidth_throttling() | 780 | yield self.sd_client.disable_bandwidth_throttling() |
1005 | 773 | else: | 781 | else: |
1007 | 774 | yield sd_client.enable_bandwidth_throttling() | 782 | yield self.sd_client.enable_bandwidth_throttling() |
1008 | 775 | 783 | ||
1009 | 776 | @log_call(logger.info) | 784 | @log_call(logger.info) |
1010 | 777 | @inlineCallbacks | 785 | @inlineCallbacks |
1011 | 778 | 786 | ||
1012 | === modified file 'ubuntuone/controlpanel/dbus_service.py' | |||
1013 | --- ubuntuone/controlpanel/dbus_service.py 2011-07-22 21:26:48 +0000 | |||
1014 | +++ ubuntuone/controlpanel/dbus_service.py 2011-08-25 19:40:18 +0000 | |||
1015 | @@ -20,9 +20,17 @@ | |||
1016 | 20 | """Export the control backend thru DBus.""" | 20 | """Export the control backend thru DBus.""" |
1017 | 21 | 21 | ||
1018 | 22 | from functools import wraps | 22 | from functools import wraps |
1019 | 23 | import sys | ||
1020 | 23 | 24 | ||
1021 | 24 | import dbus.service | 25 | import dbus.service |
1023 | 25 | import gobject | 26 | # pylint: disable=E0611 |
1024 | 27 | # pylint: disable=W0404 | ||
1025 | 28 | if 'gobject' in sys.modules: | ||
1026 | 29 | import gobject as GObject | ||
1027 | 30 | else: | ||
1028 | 31 | from gi.repository import GObject | ||
1029 | 32 | # pylint: enable=W0404 | ||
1030 | 33 | # pylint: enable=E0611 | ||
1031 | 26 | 34 | ||
1032 | 27 | from dbus.mainloop.glib import DBusGMainLoop | 35 | from dbus.mainloop.glib import DBusGMainLoop |
1033 | 28 | from dbus.service import method, signal | 36 | from dbus.service import method, signal |
1034 | @@ -608,9 +616,9 @@ | |||
1035 | 608 | 616 | ||
1036 | 609 | 617 | ||
1037 | 610 | def run_mainloop(loop=None): | 618 | def run_mainloop(loop=None): |
1039 | 611 | """Run the gobject main loop.""" | 619 | """Run the GObject main loop.""" |
1040 | 612 | if loop is None: | 620 | if loop is None: |
1042 | 613 | loop = gobject.MainLoop() | 621 | loop = GObject.MainLoop() |
1043 | 614 | loop.run() | 622 | loop.run() |
1044 | 615 | 623 | ||
1045 | 616 | 624 | ||
1046 | @@ -643,7 +651,7 @@ | |||
1047 | 643 | """Hook the DBus listeners and start the main loop.""" | 651 | """Hook the DBus listeners and start the main loop.""" |
1048 | 644 | init_mainloop() | 652 | init_mainloop() |
1049 | 645 | if register_service(): | 653 | if register_service(): |
1051 | 646 | loop = gobject.MainLoop() | 654 | loop = GObject.MainLoop() |
1052 | 647 | publish_backend(shutdown_func=loop.quit) | 655 | publish_backend(shutdown_func=loop.quit) |
1053 | 648 | run_mainloop(loop=loop) | 656 | run_mainloop(loop=loop) |
1054 | 649 | else: | 657 | else: |
1055 | 650 | 658 | ||
1056 | === modified file 'ubuntuone/controlpanel/dbustests/test_dbus_service.py' | |||
1057 | --- ubuntuone/controlpanel/dbustests/test_dbus_service.py 2011-07-22 21:26:48 +0000 | |||
1058 | +++ ubuntuone/controlpanel/dbustests/test_dbus_service.py 2011-08-25 19:40:18 +0000 | |||
1059 | @@ -107,7 +107,7 @@ | |||
1060 | 107 | rs() | 107 | rs() |
1061 | 108 | self.mocker.result(True) | 108 | self.mocker.result(True) |
1062 | 109 | 109 | ||
1064 | 110 | mainloop = "ubuntuone.controlpanel.dbus_service.gobject.MainLoop" | 110 | mainloop = "ubuntuone.controlpanel.dbus_service.GObject.MainLoop" |
1065 | 111 | mainloop = self.mocker.replace(mainloop) | 111 | mainloop = self.mocker.replace(mainloop) |
1066 | 112 | mainloop() | 112 | mainloop() |
1067 | 113 | loop = self.mocker.mock() | 113 | loop = self.mocker.mock() |
1068 | 114 | 114 | ||
1069 | === modified file 'ubuntuone/controlpanel/dbustests/test_sd_client/test_linux.py' | |||
1070 | --- ubuntuone/controlpanel/dbustests/test_sd_client/test_linux.py 2011-07-22 21:26:48 +0000 | |||
1071 | +++ ubuntuone/controlpanel/dbustests/test_sd_client/test_linux.py 2011-08-25 19:40:18 +0000 | |||
1072 | @@ -82,7 +82,8 @@ | |||
1073 | 82 | 82 | ||
1074 | 83 | def test_set_status_changed_handler(self): | 83 | def test_set_status_changed_handler(self): |
1075 | 84 | """A proper callback can be connected to StatusChanged signal.""" | 84 | """A proper callback can be connected to StatusChanged signal.""" |
1077 | 85 | _, sig = sd_client.set_status_changed_handler(self._set_called) | 85 | client = sd_client.SyncDaemonClient() |
1078 | 86 | _, sig = client.set_status_changed_handler(self._set_called) | ||
1079 | 86 | 87 | ||
1080 | 87 | self.assertEqual(sig._handler, self._set_called) | 88 | self.assertEqual(sig._handler, self._set_called) |
1081 | 88 | self.assertEqual(sig._member, 'StatusChanged') | 89 | self.assertEqual(sig._member, 'StatusChanged') |
1082 | 89 | 90 | ||
1083 | === modified file 'ubuntuone/controlpanel/gui/gtk/gui.py' | |||
1084 | --- ubuntuone/controlpanel/gui/gtk/gui.py 2011-07-22 21:26:48 +0000 | |||
1085 | +++ ubuntuone/controlpanel/gui/gtk/gui.py 2011-08-25 19:40:18 +0000 | |||
1086 | @@ -28,17 +28,14 @@ | |||
1087 | 28 | import dbus | 28 | import dbus |
1088 | 29 | import gtk | 29 | import gtk |
1089 | 30 | import gobject | 30 | import gobject |
1090 | 31 | import ubuntu_sso | ||
1091 | 32 | 31 | ||
1092 | 33 | from dbus.mainloop.glib import DBusGMainLoop | 32 | from dbus.mainloop.glib import DBusGMainLoop |
1093 | 34 | from ubuntu_sso import networkstate | 33 | from ubuntu_sso import networkstate |
1094 | 35 | from ubuntu_sso.credentials import (TC_URL_KEY, HELP_TEXT_KEY, WINDOW_ID_KEY, | ||
1095 | 36 | PING_URL_KEY) | ||
1096 | 37 | # No name 'clientdefs' in module 'ubuntuone' | ||
1097 | 38 | # pylint: disable=E0611,F0401 | 34 | # pylint: disable=E0611,F0401 |
1101 | 39 | from gi.repository import GLib | 35 | from ubuntuone.platform.credentials import ( |
1102 | 40 | from ubuntuone.clientdefs import (APP_NAME as U1_APP_NAME, TC_URL as U1_TC_URL, | 36 | APP_NAME as U1_APP_NAME, |
1103 | 41 | PING_URL as U1_PING_URL, DESCRIPTION as U1_DESCRIPTION) | 37 | CredentialsManagementTool, |
1104 | 38 | ) | ||
1105 | 42 | # pylint: enable=E0611,F0401 | 39 | # pylint: enable=E0611,F0401 |
1106 | 43 | 40 | ||
1107 | 44 | # Wildcard import ubuntuone.controlpanel.gui | 41 | # Wildcard import ubuntuone.controlpanel.gui |
1108 | @@ -123,21 +120,6 @@ | |||
1109 | 123 | gtk.main() | 120 | gtk.main() |
1110 | 124 | 121 | ||
1111 | 125 | 122 | ||
1112 | 126 | def filter_by_app_name(f): | ||
1113 | 127 | """Excecute 'f' filtering by app_name.""" | ||
1114 | 128 | |||
1115 | 129 | @wraps(f) | ||
1116 | 130 | def filter_by_app_name_inner(instance, app_name, *args, **kwargs): | ||
1117 | 131 | """Execute 'f' only if 'app_name' matches 'U1_APP_NAME'.""" | ||
1118 | 132 | if app_name == U1_APP_NAME: | ||
1119 | 133 | return f(instance, app_name, *args, **kwargs) | ||
1120 | 134 | else: | ||
1121 | 135 | logger.info('%s: ignoring call since received app_name '\ | ||
1122 | 136 | '"%s" (expected "%s")', | ||
1123 | 137 | f.__name__, app_name, U1_APP_NAME) | ||
1124 | 138 | return filter_by_app_name_inner | ||
1125 | 139 | |||
1126 | 140 | |||
1127 | 141 | def on_size_allocate(widget, allocation, label): | 123 | def on_size_allocate(widget, allocation, label): |
1128 | 142 | """Resize labels according to who 'widget' is being resized.""" | 124 | """Resize labels according to who 'widget' is being resized.""" |
1129 | 143 | label.set_size_request(allocation.width - 2, -1) | 125 | label.set_size_request(allocation.width - 2, -1) |
1130 | @@ -188,10 +170,6 @@ | |||
1131 | 188 | 170 | ||
1132 | 189 | logger.debug('%s: started.', self.__class__.__name__) | 171 | logger.debug('%s: started.', self.__class__.__name__) |
1133 | 190 | 172 | ||
1134 | 191 | def humanize(self, int_bytes): | ||
1135 | 192 | """Return a human readble string of 'int_bytes'.""" | ||
1136 | 193 | return GLib.format_size_for_display(int_bytes) | ||
1137 | 194 | |||
1138 | 195 | def _set_warning(self, message, label): | 173 | def _set_warning(self, message, label): |
1139 | 196 | """Set 'message' as warning in 'label'.""" | 174 | """Set 'message' as warning in 'label'.""" |
1140 | 197 | label.set_markup(WARNING_MARKUP % message) | 175 | label.set_markup(WARNING_MARKUP % message) |
1141 | @@ -272,23 +250,9 @@ | |||
1142 | 272 | 250 | ||
1143 | 273 | def __init__(self, main_window): | 251 | def __init__(self, main_window): |
1144 | 274 | GreyableBin.__init__(self) | 252 | GreyableBin.__init__(self) |
1160 | 275 | 253 | creds_backend = CredentialsManagementTool() | |
1146 | 276 | sso_backend = None | ||
1147 | 277 | bus = dbus.SessionBus() | ||
1148 | 278 | try: | ||
1149 | 279 | obj = bus.get_object(ubuntu_sso.DBUS_BUS_NAME, | ||
1150 | 280 | ubuntu_sso.DBUS_CREDENTIALS_PATH, | ||
1151 | 281 | follow_name_owner_changes=True) | ||
1152 | 282 | iface = ubuntu_sso.DBUS_CREDENTIALS_IFACE | ||
1153 | 283 | sso_backend = dbus.Interface(obj, dbus_interface=iface) | ||
1154 | 284 | except dbus.exceptions.DBusException: | ||
1155 | 285 | logger.exception('Can not connect to DBus at %r', | ||
1156 | 286 | (ubuntu_sso.DBUS_BUS_NAME, | ||
1157 | 287 | ubuntu_sso.DBUS_CREDENTIALS_PATH)) | ||
1158 | 288 | raise | ||
1159 | 289 | |||
1161 | 290 | ControlPanelMixin.__init__(self, filename='overview.ui', | 254 | ControlPanelMixin.__init__(self, filename='overview.ui', |
1163 | 291 | backend_instance=sso_backend) | 255 | backend_instance=creds_backend) |
1164 | 292 | self.add(self.itself) | 256 | self.add(self.itself) |
1165 | 293 | self.banner.set_from_file(get_data_file(OVERVIEW_BANNER)) | 257 | self.banner.set_from_file(get_data_file(OVERVIEW_BANNER)) |
1166 | 294 | self.files_icon.set_from_file(get_data_file(FILES_ICON)) | 258 | self.files_icon.set_from_file(get_data_file(FILES_ICON)) |
1167 | @@ -305,15 +269,6 @@ | |||
1168 | 305 | self._credentials_are_new = False | 269 | self._credentials_are_new = False |
1169 | 306 | self.show() | 270 | self.show() |
1170 | 307 | 271 | ||
1171 | 308 | self.backend.connect_to_signal('CredentialsFound', | ||
1172 | 309 | self.on_credentials_found) | ||
1173 | 310 | self.backend.connect_to_signal('CredentialsNotFound', | ||
1174 | 311 | self.on_credentials_not_found) | ||
1175 | 312 | self.backend.connect_to_signal('CredentialsError', | ||
1176 | 313 | self.on_credentials_error) | ||
1177 | 314 | self.backend.connect_to_signal('AuthorizationDenied', | ||
1178 | 315 | self.on_authorization_denied) | ||
1179 | 316 | |||
1180 | 317 | kw = dict(result_cb=self.on_network_state_changed) | 272 | kw = dict(result_cb=self.on_network_state_changed) |
1181 | 318 | self.network_manager_state = networkstate.NetworkManagerState(**kw) | 273 | self.network_manager_state = networkstate.NetworkManagerState(**kw) |
1182 | 319 | self.network_manager_state.find_online_state() | 274 | self.network_manager_state.find_online_state() |
1183 | @@ -323,6 +278,14 @@ | |||
1184 | 323 | ControlPanelMixin._set_warning(self, message, | 278 | ControlPanelMixin._set_warning(self, message, |
1185 | 324 | label=self.warning_label) | 279 | label=self.warning_label) |
1186 | 325 | 280 | ||
1187 | 281 | def _window_xid(self): | ||
1188 | 282 | """Return settings for credentials backend.""" | ||
1189 | 283 | if self.main_window.window is not None: | ||
1190 | 284 | settings = {'window_id': str(self.main_window.window.xid)} | ||
1191 | 285 | else: | ||
1192 | 286 | settings = {} | ||
1193 | 287 | return settings | ||
1194 | 288 | |||
1195 | 326 | def set_property(self, prop_name, new_value): | 289 | def set_property(self, prop_name, new_value): |
1196 | 327 | """Override 'set_property' to disable buttons if prop is 'greyed'.""" | 290 | """Override 'set_property' to disable buttons if prop is 'greyed'.""" |
1197 | 328 | if prop_name == 'greyed': | 291 | if prop_name == 'greyed': |
1198 | @@ -342,21 +305,17 @@ | |||
1199 | 342 | 305 | ||
1200 | 343 | def on_join_now_button_clicked(self, *a, **kw): | 306 | def on_join_now_button_clicked(self, *a, **kw): |
1201 | 344 | """User wants to join now.""" | 307 | """User wants to join now.""" |
1207 | 345 | settings = {TC_URL_KEY: U1_TC_URL, HELP_TEXT_KEY: U1_DESCRIPTION, | 308 | d = self.backend.register(**self._window_xid()) |
1208 | 346 | WINDOW_ID_KEY: str(self.main_window.window.xid), | 309 | d.addCallback(self.on_credentials_result) |
1209 | 347 | PING_URL_KEY: U1_PING_URL} | 310 | d.addErrback(self.on_credentials_error) |
1205 | 348 | self.backend.register(U1_APP_NAME, settings, | ||
1206 | 349 | reply_handler=NO_OP, error_handler=error_handler) | ||
1210 | 350 | self.set_property('greyed', True) | 311 | self.set_property('greyed', True) |
1211 | 351 | self.warning_label.set_text('') | 312 | self.warning_label.set_text('') |
1212 | 352 | 313 | ||
1213 | 353 | def on_connect_button_clicked(self, *a, **kw): | 314 | def on_connect_button_clicked(self, *a, **kw): |
1214 | 354 | """User wants to connect now.""" | 315 | """User wants to connect now.""" |
1220 | 355 | settings = {TC_URL_KEY: U1_TC_URL, HELP_TEXT_KEY: U1_DESCRIPTION, | 316 | d = self.backend.login(**self._window_xid()) |
1221 | 356 | WINDOW_ID_KEY: str(self.main_window.window.xid), | 317 | d.addCallback(self.on_credentials_result) |
1222 | 357 | PING_URL_KEY: U1_PING_URL} | 318 | d.addErrback(self.on_credentials_error) |
1218 | 358 | self.backend.login(U1_APP_NAME, settings, | ||
1219 | 359 | reply_handler=NO_OP, error_handler=error_handler) | ||
1223 | 360 | self.set_property('greyed', True) | 319 | self.set_property('greyed', True) |
1224 | 361 | self.warning_label.set_text('') | 320 | self.warning_label.set_text('') |
1225 | 362 | 321 | ||
1226 | @@ -364,31 +323,42 @@ | |||
1227 | 364 | """User wants to learn more.""" | 323 | """User wants to learn more.""" |
1228 | 365 | uri_hook(self.learn_more_button, LEARN_MORE_LINK) | 324 | uri_hook(self.learn_more_button, LEARN_MORE_LINK) |
1229 | 366 | 325 | ||
1231 | 367 | @filter_by_app_name | 326 | def on_credentials_result(self, result): |
1232 | 327 | """Process the credentials response. | ||
1233 | 328 | |||
1234 | 329 | If 'result' is a non empty dict, they were found. | ||
1235 | 330 | If 'result' is an empty dict, they were not found. | ||
1236 | 331 | If 'result' is None, the user cancelled the process. | ||
1237 | 332 | |||
1238 | 333 | """ | ||
1239 | 334 | if result is None: | ||
1240 | 335 | self.on_authorization_denied() | ||
1241 | 336 | elif result == {}: | ||
1242 | 337 | self.on_credentials_not_found() | ||
1243 | 338 | else: | ||
1244 | 339 | self.on_credentials_found(result) | ||
1245 | 340 | |||
1246 | 368 | @log_call(logger.info, with_args=False) | 341 | @log_call(logger.info, with_args=False) |
1249 | 369 | def on_credentials_found(self, app_name, credentials): | 342 | def on_credentials_found(self, credentials): |
1250 | 370 | """SSO backend notifies of credentials found.""" | 343 | """Credentials backend notifies of credentials found.""" |
1251 | 371 | self.set_property('greyed', False) | 344 | self.set_property('greyed', False) |
1252 | 372 | self.emit('credentials-found', self._credentials_are_new, credentials) | 345 | self.emit('credentials-found', self._credentials_are_new, credentials) |
1253 | 373 | 346 | ||
1254 | 374 | @filter_by_app_name | ||
1255 | 375 | @log_call(logger.info) | 347 | @log_call(logger.info) |
1258 | 376 | def on_credentials_not_found(self, app_name): | 348 | def on_credentials_not_found(self): |
1259 | 377 | """SSO backend notifies of credentials not found.""" | 349 | """Creds backend notifies of credentials not found.""" |
1260 | 378 | self._credentials_are_new = True | 350 | self._credentials_are_new = True |
1261 | 379 | self.set_property('greyed', False) | 351 | self.set_property('greyed', False) |
1262 | 380 | 352 | ||
1263 | 381 | @filter_by_app_name | ||
1264 | 382 | @log_call(logger.error) | 353 | @log_call(logger.error) |
1267 | 383 | def on_credentials_error(self, app_name, error_dict): | 354 | def on_credentials_error(self, error_dict): |
1268 | 384 | """SSO backend notifies of an error when fetching credentials.""" | 355 | """Creds backend notifies of an error when fetching credentials.""" |
1269 | 385 | self.set_property('greyed', False) | 356 | self.set_property('greyed', False) |
1270 | 386 | self._set_warning(CREDENTIALS_ERROR) | 357 | self._set_warning(CREDENTIALS_ERROR) |
1271 | 387 | 358 | ||
1272 | 388 | @filter_by_app_name | ||
1273 | 389 | @log_call(logger.info) | 359 | @log_call(logger.info) |
1276 | 390 | def on_authorization_denied(self, app_name): | 360 | def on_authorization_denied(self): |
1277 | 391 | """SSO backend notifies that user refused auth for 'app_name'.""" | 361 | """Creds backend notifies that user refused auth for 'app_name'.""" |
1278 | 392 | self.set_property('greyed', False) | 362 | self.set_property('greyed', False) |
1279 | 393 | 363 | ||
1280 | 394 | @log_call(logger.info) | 364 | @log_call(logger.info) |
1281 | @@ -402,8 +372,9 @@ | |||
1282 | 402 | else: | 372 | else: |
1283 | 403 | self.set_sensitive(True) | 373 | self.set_sensitive(True) |
1284 | 404 | self.warning_label.set_text(msg) | 374 | self.warning_label.set_text(msg) |
1287 | 405 | self.backend.find_credentials(U1_APP_NAME, {}, | 375 | d = self.backend.find_credentials() |
1288 | 406 | reply_handler=NO_OP, error_handler=error_handler) | 376 | d.addCallback(self.on_credentials_result) |
1289 | 377 | d.addErrback(self.on_credentials_error) | ||
1290 | 407 | 378 | ||
1291 | 408 | 379 | ||
1292 | 409 | class DashboardPanel(UbuntuOneBin, ControlPanelMixin): | 380 | class DashboardPanel(UbuntuOneBin, ControlPanelMixin): |
1293 | @@ -520,7 +491,7 @@ | |||
1294 | 520 | scroll_to_cell = True | 491 | scroll_to_cell = True |
1295 | 521 | else: | 492 | else: |
1296 | 522 | free_bytes_str = self.FREE_SPACE | 493 | free_bytes_str = self.FREE_SPACE |
1298 | 523 | free_bytes_args = {'free_space': self.humanize(free_bytes)} | 494 | free_bytes_args = {'free_space': humanize(free_bytes)} |
1299 | 524 | free_bytes = free_bytes_str % free_bytes_args | 495 | free_bytes = free_bytes_str % free_bytes_args |
1300 | 525 | 496 | ||
1301 | 526 | row = (self.ROW_HEADER % (name, free_bytes), | 497 | row = (self.ROW_HEADER % (name, free_bytes), |
1302 | @@ -1542,7 +1513,7 @@ | |||
1303 | 1542 | """Backend notifies of account info.""" | 1513 | """Backend notifies of account info.""" |
1304 | 1543 | used = int(info['quota_used']) | 1514 | used = int(info['quota_used']) |
1305 | 1544 | total = int(info['quota_total']) | 1515 | total = int(info['quota_total']) |
1307 | 1545 | data = {'used': self.humanize(used), 'total': self.humanize(total), | 1516 | data = {'used': humanize(used), 'total': humanize(total), |
1308 | 1546 | 'percentage': (used / total) * 100} | 1517 | 'percentage': (used / total) * 100} |
1309 | 1547 | self._update_quota(QUOTA_LABEL % data, data) | 1518 | self._update_quota(QUOTA_LABEL % data, data) |
1310 | 1548 | 1519 | ||
1311 | 1549 | 1520 | ||
1312 | === modified file 'ubuntuone/controlpanel/gui/gtk/tests/__init__.py' | |||
1313 | --- ubuntuone/controlpanel/gui/gtk/tests/__init__.py 2011-07-22 21:26:48 +0000 | |||
1314 | +++ ubuntuone/controlpanel/gui/gtk/tests/__init__.py 2011-08-25 19:40:18 +0000 | |||
1315 | @@ -22,6 +22,7 @@ | |||
1316 | 22 | 22 | ||
1317 | 23 | from collections import defaultdict | 23 | from collections import defaultdict |
1318 | 24 | 24 | ||
1319 | 25 | from twisted.internet import defer | ||
1320 | 25 | from ubuntuone.devtools.handlers import MementoHandler | 26 | from ubuntuone.devtools.handlers import MementoHandler |
1321 | 26 | 27 | ||
1322 | 27 | from ubuntuone.controlpanel.gui.gtk import gui | 28 | from ubuntuone.controlpanel.gui.gtk import gui |
1323 | @@ -83,14 +84,12 @@ | |||
1324 | 83 | self._signals[signal].append(handler) | 84 | self._signals[signal].append(handler) |
1325 | 84 | 85 | ||
1326 | 85 | 86 | ||
1329 | 86 | class FakedSSOBackend(FakedDBusBackend): | 87 | class FakedCredentialsBackend(FakedObject): |
1330 | 87 | """Fake a SSO Backend, act as a dbus.Interface.""" | 88 | """Fake a credentials backend.""" |
1331 | 88 | 89 | ||
1332 | 89 | bus_name = gui.ubuntu_sso.DBUS_BUS_NAME | ||
1333 | 90 | object_path = gui.ubuntu_sso.DBUS_CREDENTIALS_PATH | ||
1334 | 91 | iface = gui.ubuntu_sso.DBUS_CREDENTIALS_IFACE | ||
1335 | 92 | exposed_methods = ['find_credentials', 'clear_credentials', | 90 | exposed_methods = ['find_credentials', 'clear_credentials', |
1336 | 93 | 'login', 'register'] | 91 | 'login', 'register'] |
1337 | 92 | next_result = defer.succeed(None) | ||
1338 | 94 | 93 | ||
1339 | 95 | 94 | ||
1340 | 96 | class FakedControlPanelBackend(FakedDBusBackend): | 95 | class FakedControlPanelBackend(FakedDBusBackend): |
1341 | @@ -135,8 +134,6 @@ | |||
1342 | 135 | if dbus_interface == gui.DBUS_PREFERENCES_IFACE: | 134 | if dbus_interface == gui.DBUS_PREFERENCES_IFACE: |
1343 | 136 | return FakedControlPanelBackend(obj, dbus_interface, | 135 | return FakedControlPanelBackend(obj, dbus_interface, |
1344 | 137 | *args, **kwargs) | 136 | *args, **kwargs) |
1345 | 138 | if dbus_interface == gui.ubuntu_sso.DBUS_CREDENTIALS_IFACE: | ||
1346 | 139 | return FakedSSOBackend(obj, dbus_interface, *args, **kwargs) | ||
1347 | 140 | if dbus_interface == gui.DBUS_IFACE_GUI: | 137 | if dbus_interface == gui.DBUS_IFACE_GUI: |
1348 | 141 | return FakeControlPanelBackend( | 138 | return FakeControlPanelBackend( |
1349 | 142 | obj, dbus_interface, *args, **kwargs) | 139 | obj, dbus_interface, *args, **kwargs) |
1350 | @@ -188,9 +185,11 @@ | |||
1351 | 188 | # pylint: disable=E1102 | 185 | # pylint: disable=E1102 |
1352 | 189 | klass = None | 186 | klass = None |
1353 | 190 | kwargs = {} | 187 | kwargs = {} |
1354 | 188 | backend_is_dbus = True | ||
1355 | 191 | 189 | ||
1356 | 192 | def setUp(self): | 190 | def setUp(self): |
1357 | 193 | super(BaseTestCase, self).setUp() | 191 | super(BaseTestCase, self).setUp() |
1358 | 192 | self.patch(gui, 'CredentialsManagementTool', FakedCredentialsBackend) | ||
1359 | 194 | self.patch(gui.os.path, 'expanduser', | 193 | self.patch(gui.os.path, 'expanduser', |
1360 | 195 | lambda path: path.replace('~', USER_HOME)) | 194 | lambda path: path.replace('~', USER_HOME)) |
1361 | 196 | self.patch(gui.gtk, 'main', lambda: None) | 195 | self.patch(gui.gtk, 'main', lambda: None) |
1362 | @@ -221,14 +220,13 @@ | |||
1363 | 221 | pb = gui.gtk.gdk.pixbuf_new_from_file(gui.get_data_file(filename)) | 220 | pb = gui.gtk.gdk.pixbuf_new_from_file(gui.get_data_file(filename)) |
1364 | 222 | self.assertEqual(image.get_pixbuf().get_pixels(), pb.get_pixels()) | 221 | self.assertEqual(image.get_pixbuf().get_pixels(), pb.get_pixels()) |
1365 | 223 | 222 | ||
1367 | 224 | def assert_backend_called(self, method_name, args, backend=None): | 223 | def assert_backend_called(self, method_name, *args, **kwargs): |
1368 | 225 | """Check that the control panel backend 'method_name' was called.""" | 224 | """Check that the control panel backend 'method_name' was called.""" |
1375 | 226 | if backend is None: | 225 | if self.backend_is_dbus: |
1376 | 227 | backend = self.ui.backend | 226 | kwargs = {'reply_handler': gui.NO_OP, |
1377 | 228 | self.assertIn(method_name, backend._called) | 227 | 'error_handler': gui.error_handler} |
1378 | 229 | kwargs = {'reply_handler': gui.NO_OP, | 228 | self.assertIn(method_name, self.ui.backend._called) |
1379 | 230 | 'error_handler': gui.error_handler} | 229 | self.assertEqual(self.ui.backend._called[method_name], (args, kwargs)) |
1374 | 231 | self.assertEqual(backend._called[method_name], (args, kwargs)) | ||
1380 | 232 | 230 | ||
1381 | 233 | def assert_warning_correct(self, warning, text): | 231 | def assert_warning_correct(self, warning, text): |
1382 | 234 | """Check that 'warning' is visible, showing 'text'.""" | 232 | """Check that 'warning' is visible, showing 'text'.""" |
1383 | 235 | 233 | ||
1384 | === modified file 'ubuntuone/controlpanel/gui/gtk/tests/test_gui.py' | |||
1385 | --- ubuntuone/controlpanel/gui/gtk/tests/test_gui.py 2011-07-22 21:26:48 +0000 | |||
1386 | +++ ubuntuone/controlpanel/gui/gtk/tests/test_gui.py 2011-08-25 19:40:18 +0000 | |||
1387 | @@ -42,6 +42,7 @@ | |||
1388 | 42 | ) | 42 | ) |
1389 | 43 | from ubuntuone.controlpanel.gui.gtk.tests.test_package_manager import ( | 43 | from ubuntuone.controlpanel.gui.gtk.tests.test_package_manager import ( |
1390 | 44 | SUCCESS, FAILURE) | 44 | SUCCESS, FAILURE) |
1391 | 45 | from ubuntuone.controlpanel.gui import humanize | ||
1392 | 45 | 46 | ||
1393 | 46 | 47 | ||
1394 | 47 | # Attribute 'yyy' defined outside __init__, access to a protected member | 48 | # Attribute 'yyy' defined outside __init__, access to a protected member |
1395 | @@ -159,7 +160,7 @@ | |||
1396 | 159 | self.ui.backend._called.pop('volumes_info', None) | 160 | self.ui.backend._called.pop('volumes_info', None) |
1397 | 160 | self.ui.load() | 161 | self.ui.load() |
1398 | 161 | 162 | ||
1400 | 162 | self.assert_backend_called('volumes_info', ()) | 163 | self.assert_backend_called('volumes_info') |
1401 | 163 | 164 | ||
1402 | 164 | def test_is_processing_after_load(self): | 165 | def test_is_processing_after_load(self): |
1403 | 165 | """The ui is processing when contents are load.""" | 166 | """The ui is processing when contents are load.""" |
1404 | @@ -196,7 +197,7 @@ | |||
1405 | 196 | treeiter = self.ui.volumes_store.get_iter_root() | 197 | treeiter = self.ui.volumes_store.get_iter_root() |
1406 | 197 | for name, free_bytes, volumes in FAKE_VOLUMES_INFO: | 198 | for name, free_bytes, volumes in FAKE_VOLUMES_INFO: |
1407 | 198 | name = "%s's" % name if name else gui.MY_FOLDERS | 199 | name = "%s's" % name if name else gui.MY_FOLDERS |
1409 | 199 | free_bytes = self.ui.humanize(int(free_bytes)) | 200 | free_bytes = humanize(int(free_bytes)) |
1410 | 200 | header = (name, self.ui.FREE_SPACE % {'free_space': free_bytes}) | 201 | header = (name, self.ui.FREE_SPACE % {'free_space': free_bytes}) |
1411 | 201 | 202 | ||
1412 | 202 | # check parent row | 203 | # check parent row |
1413 | @@ -277,7 +278,7 @@ | |||
1414 | 277 | treeiter = self.ui.volumes_store.get_iter_root() | 278 | treeiter = self.ui.volumes_store.get_iter_root() |
1415 | 278 | for name, free_bytes, volumes in FAKE_VOLUMES_NO_FREE_SPACE_INFO: | 279 | for name, free_bytes, volumes in FAKE_VOLUMES_NO_FREE_SPACE_INFO: |
1416 | 279 | name = "%s's" % name if name else gui.MY_FOLDERS | 280 | name = "%s's" % name if name else gui.MY_FOLDERS |
1418 | 280 | free_bytes = self.ui.humanize(int(free_bytes)) | 281 | free_bytes = humanize(int(free_bytes)) |
1419 | 281 | free_bytes = self.ui.NO_FREE_SPACE % {'free_space': free_bytes} | 282 | free_bytes = self.ui.NO_FREE_SPACE % {'free_space': free_bytes} |
1420 | 282 | 283 | ||
1421 | 283 | # check parent row | 284 | # check parent row |
1422 | @@ -440,7 +441,7 @@ | |||
1423 | 440 | subscribed = gui.bool_str(not bool(volume['subscribed'])) | 441 | subscribed = gui.bool_str(not bool(volume['subscribed'])) |
1424 | 441 | # backend was called | 442 | # backend was called |
1425 | 442 | self.assert_backend_called('change_volume_settings', | 443 | self.assert_backend_called('change_volume_settings', |
1427 | 443 | (fid, {'subscribed': subscribed})) | 444 | fid, {'subscribed': subscribed}) |
1428 | 444 | # store was updated | 445 | # store was updated |
1429 | 445 | it = self.ui.volumes_store.get_iter(path) | 446 | it = self.ui.volumes_store.get_iter(path) |
1430 | 446 | value = self.ui.volumes_store.get_value(it, 1) | 447 | value = self.ui.volumes_store.get_value(it, 1) |
1431 | @@ -572,7 +573,7 @@ | |||
1432 | 572 | """Changing throttling settings updates the backend properly.""" | 573 | """Changing throttling settings updates the backend properly.""" |
1433 | 573 | expected = self.ui.__dict__ | 574 | expected = self.ui.__dict__ |
1434 | 574 | self.assert_backend_called('change_device_settings', | 575 | self.assert_backend_called('change_device_settings', |
1436 | 575 | (self.ui.id, expected)) | 576 | self.ui.id, expected) |
1437 | 576 | self.assertEqual(self.ui.warning_label.get_text(), '') | 577 | self.assertEqual(self.ui.warning_label.get_text(), '') |
1438 | 577 | 578 | ||
1439 | 578 | limit_enabled = self.ui.throttling_limits.get_sensitive() | 579 | limit_enabled = self.ui.throttling_limits.get_sensitive() |
1440 | @@ -806,7 +807,7 @@ | |||
1441 | 806 | self.ui.is_local = False | 807 | self.ui.is_local = False |
1442 | 807 | self.ui.remove.clicked() | 808 | self.ui.remove.clicked() |
1443 | 808 | 809 | ||
1445 | 809 | self.assert_backend_called('remove_device', (self.ui.id,)) | 810 | self.assert_backend_called('remove_device', self.ui.id) |
1446 | 810 | self.assertFalse(self.ui.get_sensitive(), | 811 | self.assertFalse(self.ui.get_sensitive(), |
1447 | 811 | 'Must be disabled while removing.') | 812 | 'Must be disabled while removing.') |
1448 | 812 | 813 | ||
1449 | @@ -936,7 +937,7 @@ | |||
1450 | 936 | self.ui.backend._called.pop('devices_info', None) | 937 | self.ui.backend._called.pop('devices_info', None) |
1451 | 937 | self.ui.load() | 938 | self.ui.load() |
1452 | 938 | 939 | ||
1454 | 939 | self.assert_backend_called('devices_info', ()) | 940 | self.assert_backend_called('devices_info') |
1455 | 940 | 941 | ||
1456 | 941 | def test_is_processing_after_load(self): | 942 | def test_is_processing_after_load(self): |
1457 | 942 | """The ui is processing when contents are load.""" | 943 | """The ui is processing when contents are load.""" |
1458 | @@ -1246,7 +1247,7 @@ | |||
1459 | 1246 | 1247 | ||
1460 | 1247 | def test_file_sync_status_is_requested(self): | 1248 | def test_file_sync_status_is_requested(self): |
1461 | 1248 | """The file sync status is requested to the backend.""" | 1249 | """The file sync status is requested to the backend.""" |
1463 | 1249 | self.assert_backend_called('file_sync_status', ()) | 1250 | self.assert_backend_called('file_sync_status') |
1464 | 1250 | 1251 | ||
1465 | 1251 | def test_is_disabled(self): | 1252 | def test_is_disabled(self): |
1466 | 1252 | """Until file sync status is given, the widget is disabled.""" | 1253 | """Until file sync status is given, the widget is disabled.""" |
1467 | @@ -1273,10 +1274,10 @@ | |||
1468 | 1273 | assert self.ui.button.get_active() | 1274 | assert self.ui.button.get_active() |
1469 | 1274 | 1275 | ||
1470 | 1275 | self.ui.button.set_active(not self.ui.button.get_active()) | 1276 | self.ui.button.set_active(not self.ui.button.get_active()) |
1472 | 1276 | self.assert_backend_called('disable_files', ()) | 1277 | self.assert_backend_called('disable_files') |
1473 | 1277 | 1278 | ||
1474 | 1278 | self.ui.button.set_active(not self.ui.button.get_active()) | 1279 | self.ui.button.set_active(not self.ui.button.get_active()) |
1476 | 1279 | self.assert_backend_called('enable_files', ()) | 1280 | self.assert_backend_called('enable_files') |
1477 | 1280 | 1281 | ||
1478 | 1281 | def test_on_file_sync_enabled(self): | 1282 | def test_on_file_sync_enabled(self): |
1479 | 1282 | """When file sync is enabled, the button is active.""" | 1283 | """When file sync is enabled, the button is active.""" |
1480 | @@ -1330,7 +1331,7 @@ | |||
1481 | 1330 | 1331 | ||
1482 | 1331 | args = (self.service_id, | 1332 | args = (self.service_id, |
1483 | 1332 | {'enabled': gui.bool_str(self.ui.button.get_active())}) | 1333 | {'enabled': gui.bool_str(self.ui.button.get_active())}) |
1485 | 1333 | self.assert_backend_called('change_replication_settings', args) | 1334 | self.assert_backend_called('change_replication_settings', *args) |
1486 | 1334 | 1335 | ||
1487 | 1335 | def test_dependency(self): | 1336 | def test_dependency(self): |
1488 | 1336 | """The dependency box is None.""" | 1337 | """The dependency box is None.""" |
1489 | @@ -1543,7 +1544,7 @@ | |||
1490 | 1543 | self.ui.load_replications() | 1544 | self.ui.load_replications() |
1491 | 1544 | 1545 | ||
1492 | 1545 | self.assertTrue(self.ui.message.active) | 1546 | self.assertTrue(self.ui.message.active) |
1494 | 1546 | self.assert_backend_called('replications_info', ()) | 1547 | self.assert_backend_called('replications_info') |
1495 | 1547 | 1548 | ||
1496 | 1548 | 1549 | ||
1497 | 1549 | class ServicesWithDesktopcouchTestCase(ServicesTestCase): | 1550 | class ServicesWithDesktopcouchTestCase(ServicesTestCase): |
1498 | @@ -1750,7 +1751,7 @@ | |||
1499 | 1750 | def test_file_sync_status_is_requested_on_load(self): | 1751 | def test_file_sync_status_is_requested_on_load(self): |
1500 | 1751 | """The file sync status is requested to the backend.""" | 1752 | """The file sync status is requested to the backend.""" |
1501 | 1752 | self.ui.load() | 1753 | self.ui.load() |
1503 | 1753 | self.assert_backend_called('file_sync_status', ()) | 1754 | self.assert_backend_called('file_sync_status') |
1504 | 1754 | 1755 | ||
1505 | 1755 | def test_on_file_sync_status_disabled(self): | 1756 | def test_on_file_sync_status_disabled(self): |
1506 | 1756 | """The file sync is disabled. | 1757 | """The file sync is disabled. |
1507 | @@ -1862,43 +1863,43 @@ | |||
1508 | 1862 | self.ui.backend._called.clear() | 1863 | self.ui.backend._called.clear() |
1509 | 1863 | self.ui.on_files_start_error({'error_msg': 'error msg'}) | 1864 | self.ui.on_files_start_error({'error_msg': 'error msg'}) |
1510 | 1864 | 1865 | ||
1512 | 1865 | self.assert_backend_called('file_sync_status', ()) | 1866 | self.assert_backend_called('file_sync_status') |
1513 | 1866 | 1867 | ||
1514 | 1867 | def test_on_connect_clicked(self): | 1868 | def test_on_connect_clicked(self): |
1515 | 1868 | """User requested connection.""" | 1869 | """User requested connection.""" |
1516 | 1869 | self.ui.on_connect_clicked(self.ui.button) | 1870 | self.ui.on_connect_clicked(self.ui.button) |
1517 | 1870 | 1871 | ||
1519 | 1871 | self.assert_backend_called('connect_files', ()) | 1872 | self.assert_backend_called('connect_files') |
1520 | 1872 | 1873 | ||
1521 | 1873 | def test_on_disconnect_clicked(self): | 1874 | def test_on_disconnect_clicked(self): |
1522 | 1874 | """User requested disconnection.""" | 1875 | """User requested disconnection.""" |
1523 | 1875 | self.ui.on_disconnect_clicked(self.ui.button) | 1876 | self.ui.on_disconnect_clicked(self.ui.button) |
1524 | 1876 | 1877 | ||
1526 | 1877 | self.assert_backend_called('disconnect_files', ()) | 1878 | self.assert_backend_called('disconnect_files') |
1527 | 1878 | 1879 | ||
1528 | 1879 | def test_on_enable_clicked(self): | 1880 | def test_on_enable_clicked(self): |
1529 | 1880 | """User requested enable the service.""" | 1881 | """User requested enable the service.""" |
1530 | 1881 | self.ui.on_enable_clicked(self.ui.button) | 1882 | self.ui.on_enable_clicked(self.ui.button) |
1531 | 1882 | 1883 | ||
1533 | 1883 | self.assert_backend_called('enable_files', ()) | 1884 | self.assert_backend_called('enable_files') |
1534 | 1884 | 1885 | ||
1535 | 1885 | def test_on_restart_clicked(self): | 1886 | def test_on_restart_clicked(self): |
1536 | 1886 | """User requested restart the service.""" | 1887 | """User requested restart the service.""" |
1537 | 1887 | self.ui.on_restart_clicked(self.ui.button) | 1888 | self.ui.on_restart_clicked(self.ui.button) |
1538 | 1888 | 1889 | ||
1540 | 1889 | self.assert_backend_called('restart_files', ()) | 1890 | self.assert_backend_called('restart_files') |
1541 | 1890 | 1891 | ||
1542 | 1891 | def test_on_start_clicked(self): | 1892 | def test_on_start_clicked(self): |
1543 | 1892 | """User requested start the service.""" | 1893 | """User requested start the service.""" |
1544 | 1893 | self.ui.on_start_clicked(self.ui.button) | 1894 | self.ui.on_start_clicked(self.ui.button) |
1545 | 1894 | 1895 | ||
1547 | 1895 | self.assert_backend_called('start_files', ()) | 1896 | self.assert_backend_called('start_files') |
1548 | 1896 | 1897 | ||
1549 | 1897 | def test_on_stop_clicked(self): | 1898 | def test_on_stop_clicked(self): |
1550 | 1898 | """User requested stop the service.""" | 1899 | """User requested stop the service.""" |
1551 | 1899 | self.ui.on_stop_clicked(self.ui.button) | 1900 | self.ui.on_stop_clicked(self.ui.button) |
1552 | 1900 | 1901 | ||
1554 | 1901 | self.assert_backend_called('stop_files', ()) | 1902 | self.assert_backend_called('stop_files') |
1555 | 1902 | 1903 | ||
1556 | 1903 | 1904 | ||
1557 | 1904 | class ManagementPanelTestCase(ControlPanelMixinTestCase): | 1905 | class ManagementPanelTestCase(ControlPanelMixinTestCase): |
1558 | @@ -1912,8 +1913,8 @@ | |||
1559 | 1912 | used = int(info['quota_used']) | 1913 | used = int(info['quota_used']) |
1560 | 1913 | total = int(info['quota_total']) | 1914 | total = int(info['quota_total']) |
1561 | 1914 | percentage = round((used / total) * 100, 2) | 1915 | percentage = round((used / total) * 100, 2) |
1564 | 1915 | expected = {'used': self.ui.humanize(used), | 1916 | expected = {'used': humanize(used), |
1565 | 1916 | 'total': self.ui.humanize(total), | 1917 | 'total': humanize(total), |
1566 | 1917 | 'percentage': percentage} | 1918 | 'percentage': percentage} |
1567 | 1918 | msg = gui.QUOTA_LABEL % expected | 1919 | msg = gui.QUOTA_LABEL % expected |
1568 | 1919 | self.assertEqual(self.ui.quota_label.get_text(), msg) | 1920 | self.assertEqual(self.ui.quota_label.get_text(), msg) |
1569 | @@ -1992,7 +1993,7 @@ | |||
1570 | 1992 | def test_account_info_is_requested_on_load(self): | 1993 | def test_account_info_is_requested_on_load(self): |
1571 | 1993 | """The account info is requested to the backend.""" | 1994 | """The account info is requested to the backend.""" |
1572 | 1994 | self.ui.load() | 1995 | self.ui.load() |
1574 | 1995 | self.assert_backend_called('account_info', ()) | 1996 | self.assert_backend_called('account_info') |
1575 | 1996 | 1997 | ||
1576 | 1997 | def test_file_sync_status_info_is_requested_on_load(self): | 1998 | def test_file_sync_status_info_is_requested_on_load(self): |
1577 | 1998 | """The file sync status info is requested to the backend.""" | 1999 | """The file sync status info is requested to the backend.""" |
1578 | 1999 | 2000 | ||
1579 | === modified file 'ubuntuone/controlpanel/gui/gtk/tests/test_gui_basic.py' | |||
1580 | --- ubuntuone/controlpanel/gui/gtk/tests/test_gui_basic.py 2011-07-22 21:26:48 +0000 | |||
1581 | +++ ubuntuone/controlpanel/gui/gtk/tests/test_gui_basic.py 2011-08-25 19:40:18 +0000 | |||
1582 | @@ -20,9 +20,14 @@ | |||
1583 | 20 | 20 | ||
1584 | 21 | from __future__ import division | 21 | from __future__ import division |
1585 | 22 | 22 | ||
1586 | 23 | from twisted.internet import defer | ||
1587 | 24 | from twisted.python.failure import Failure | ||
1588 | 23 | 25 | ||
1589 | 24 | from ubuntuone.controlpanel.gui.gtk import gui | 26 | from ubuntuone.controlpanel.gui.gtk import gui |
1591 | 25 | from ubuntuone.controlpanel.gui.gtk.tests import BaseTestCase, FakedSSOBackend | 27 | from ubuntuone.controlpanel.gui.gtk.tests import ( |
1592 | 28 | BaseTestCase, | ||
1593 | 29 | FakedCredentialsBackend, | ||
1594 | 30 | ) | ||
1595 | 26 | from ubuntuone.controlpanel.tests import TOKEN | 31 | from ubuntuone.controlpanel.tests import TOKEN |
1596 | 27 | 32 | ||
1597 | 28 | from ubuntuone.devtools.testcase import skipIf | 33 | from ubuntuone.devtools.testcase import skipIf |
1598 | @@ -287,7 +292,7 @@ | |||
1599 | 287 | """On 'credentials-found' signal, ask syncdaemon to connect.""" | 292 | """On 'credentials-found' signal, ask syncdaemon to connect.""" |
1600 | 288 | # credentials are new | 293 | # credentials are new |
1601 | 289 | self.ui.overview.emit('credentials-found', True, object()) | 294 | self.ui.overview.emit('credentials-found', True, object()) |
1603 | 290 | self.assert_backend_called('connect_files', ()) | 295 | self.assert_backend_called('connect_files') |
1604 | 291 | 296 | ||
1605 | 292 | def test_local_device_removed_shows_overview_panel(self): | 297 | def test_local_device_removed_shows_overview_panel(self): |
1606 | 293 | """On 'local-device-removed' signal, the overview panel is shown.""" | 298 | """On 'local-device-removed' signal, the overview panel is shown.""" |
1607 | @@ -306,7 +311,7 @@ | |||
1608 | 306 | def test_backend_is_shutdown_on_close(self): | 311 | def test_backend_is_shutdown_on_close(self): |
1609 | 307 | """When the control panel is closed, the backend is shutdown.""" | 312 | """When the control panel is closed, the backend is shutdown.""" |
1610 | 308 | self.ui.emit('destroy') | 313 | self.ui.emit('destroy') |
1612 | 309 | self.assert_backend_called('shutdown', ()) | 314 | self.assert_backend_called('shutdown') |
1613 | 310 | 315 | ||
1614 | 311 | 316 | ||
1615 | 312 | class UbuntuOneBinTestCase(BaseTestCase): | 317 | class UbuntuOneBinTestCase(BaseTestCase): |
1616 | @@ -437,6 +442,11 @@ | |||
1617 | 437 | klass = gui.OverviewPanel | 442 | klass = gui.OverviewPanel |
1618 | 438 | kwargs = {'main_window': gui.gtk.Window()} | 443 | kwargs = {'main_window': gui.gtk.Window()} |
1619 | 439 | ui_filename = 'overview.ui' | 444 | ui_filename = 'overview.ui' |
1620 | 445 | backend_is_dbus = False | ||
1621 | 446 | |||
1622 | 447 | def setUp(self): | ||
1623 | 448 | super(OverwiewPanelTestCase, self).setUp() | ||
1624 | 449 | gui.gtk.link_button_set_uri_hook(lambda *a: None) | ||
1625 | 440 | 450 | ||
1626 | 441 | def test_is_a_greyable_bin(self): | 451 | def test_is_a_greyable_bin(self): |
1627 | 442 | """Inherits from GreyableBin.""" | 452 | """Inherits from GreyableBin.""" |
1628 | @@ -450,20 +460,102 @@ | |||
1629 | 450 | """The 'join_now' button is the default widget.""" | 460 | """The 'join_now' button is the default widget.""" |
1630 | 451 | self.assertTrue(self.ui.join_now_button.get_property('can-default')) | 461 | self.assertTrue(self.ui.join_now_button.get_property('can-default')) |
1631 | 452 | 462 | ||
1646 | 453 | def test_sso_backend(self): | 463 | def test_backend(self): |
1647 | 454 | """Has a correct SSO backend.""" | 464 | """Has a correct backend.""" |
1648 | 455 | self.assertIsInstance(self.ui.backend, FakedSSOBackend) | 465 | self.assertIsInstance(self.ui.backend, FakedCredentialsBackend) |
1649 | 456 | 466 | ||
1650 | 457 | def test_sso_backend_signals(self): | 467 | |
1651 | 458 | """The proper signals are connected to the backend.""" | 468 | class OverwiewPanelBackendCallbacksTestCase(OverwiewPanelTestCase): |
1652 | 459 | self.assertEqual(self.ui.backend._signals['CredentialsFound'], | 469 | """Proper callbacks are chained to the credentials backend methods.""" |
1653 | 460 | [self.ui.on_credentials_found]) | 470 | |
1654 | 461 | self.assertEqual(self.ui.backend._signals['CredentialsNotFound'], | 471 | failure = Exception() |
1655 | 462 | [self.ui.on_credentials_not_found]) | 472 | |
1656 | 463 | self.assertEqual(self.ui.backend._signals['CredentialsError'], | 473 | def test_find_credentials_fired_with_credentials(self): |
1657 | 464 | [self.ui.on_credentials_error]) | 474 | """Test that on_credentials_found is called.""" |
1658 | 465 | self.assertEqual(self.ui.backend._signals['AuthorizationDenied'], | 475 | self.ui.backend.next_result = defer.succeed(TOKEN) |
1659 | 466 | [self.ui.on_authorization_denied]) | 476 | self.patch(self.ui, 'on_credentials_found', self._set_called) |
1660 | 477 | |||
1661 | 478 | self.ui.on_network_state_changed(gui.networkstate.ONLINE) | ||
1662 | 479 | |||
1663 | 480 | self.assertEqual(self._called, ((TOKEN,), {})) | ||
1664 | 481 | |||
1665 | 482 | def test_find_credentials_fired_without_credentials(self): | ||
1666 | 483 | """Test that on_credentials_not_found is called.""" | ||
1667 | 484 | self.ui.backend.next_result = defer.succeed({}) | ||
1668 | 485 | self.patch(self.ui, 'on_credentials_not_found', self._set_called) | ||
1669 | 486 | |||
1670 | 487 | self.ui.on_network_state_changed(gui.networkstate.ONLINE) | ||
1671 | 488 | |||
1672 | 489 | self.assertEqual(self._called, ((), {})) | ||
1673 | 490 | |||
1674 | 491 | def test_find_credentials_errback(self): | ||
1675 | 492 | """Test that on_credentials_error is called.""" | ||
1676 | 493 | self.ui.backend.next_result = defer.fail(self.failure) | ||
1677 | 494 | self.patch(self.ui, 'on_credentials_error', self._set_called) | ||
1678 | 495 | |||
1679 | 496 | self.ui.on_network_state_changed(gui.networkstate.ONLINE) | ||
1680 | 497 | |||
1681 | 498 | failure = self._called[0][0] | ||
1682 | 499 | self.assertIsInstance(failure, Failure) | ||
1683 | 500 | self.assertEqual(failure.value, self.failure) | ||
1684 | 501 | |||
1685 | 502 | def test_register_fired_with_credentials(self): | ||
1686 | 503 | """Test that on_credentials_found is called.""" | ||
1687 | 504 | self.ui.backend.next_result = defer.succeed(TOKEN) | ||
1688 | 505 | self.patch(self.ui, 'on_credentials_found', self._set_called) | ||
1689 | 506 | |||
1690 | 507 | self.ui.join_now_button.clicked() | ||
1691 | 508 | |||
1692 | 509 | self.assertEqual(self._called, ((TOKEN,), {})) | ||
1693 | 510 | |||
1694 | 511 | def test_register_fired_with_credentials_none(self): | ||
1695 | 512 | """Test that on_authorization_denied is called.""" | ||
1696 | 513 | self.ui.backend.next_result = defer.succeed(None) | ||
1697 | 514 | self.patch(self.ui, 'on_authorization_denied', self._set_called) | ||
1698 | 515 | |||
1699 | 516 | self.ui.join_now_button.clicked() | ||
1700 | 517 | |||
1701 | 518 | self.assertEqual(self._called, ((), {})) | ||
1702 | 519 | |||
1703 | 520 | def test_register_errback(self): | ||
1704 | 521 | """Test that on_credentials_error is called.""" | ||
1705 | 522 | self.ui.backend.next_result = defer.fail(self.failure) | ||
1706 | 523 | self.patch(self.ui, 'on_credentials_error', self._set_called) | ||
1707 | 524 | |||
1708 | 525 | self.ui.join_now_button.clicked() | ||
1709 | 526 | |||
1710 | 527 | failure = self._called[0][0] | ||
1711 | 528 | self.assertIsInstance(failure, Failure) | ||
1712 | 529 | self.assertEqual(failure.value, self.failure) | ||
1713 | 530 | |||
1714 | 531 | def test_login_fired_with_credentials(self): | ||
1715 | 532 | """Test that on_credentials_found is called.""" | ||
1716 | 533 | self.ui.backend.next_result = defer.succeed(TOKEN) | ||
1717 | 534 | self.patch(self.ui, 'on_credentials_found', self._set_called) | ||
1718 | 535 | |||
1719 | 536 | self.ui.connect_button.clicked() | ||
1720 | 537 | |||
1721 | 538 | self.assertEqual(self._called, ((TOKEN,), {})) | ||
1722 | 539 | |||
1723 | 540 | def test_login_fired_with_credentials_none(self): | ||
1724 | 541 | """Test that on_authorization_denied is called.""" | ||
1725 | 542 | self.ui.backend.next_result = defer.succeed(None) | ||
1726 | 543 | self.patch(self.ui, 'on_authorization_denied', self._set_called) | ||
1727 | 544 | |||
1728 | 545 | self.ui.connect_button.clicked() | ||
1729 | 546 | |||
1730 | 547 | self.assertEqual(self._called, ((), {})) | ||
1731 | 548 | |||
1732 | 549 | def test_login_errback(self): | ||
1733 | 550 | """Test that on_credentials_error is called.""" | ||
1734 | 551 | self.ui.backend.next_result = defer.fail(self.failure) | ||
1735 | 552 | self.patch(self.ui, 'on_credentials_error', self._set_called) | ||
1736 | 553 | |||
1737 | 554 | self.ui.connect_button.clicked() | ||
1738 | 555 | |||
1739 | 556 | failure = self._called[0][0] | ||
1740 | 557 | self.assertIsInstance(failure, Failure) | ||
1741 | 558 | self.assertEqual(failure.value, self.failure) | ||
1742 | 467 | 559 | ||
1743 | 468 | 560 | ||
1744 | 469 | class OverwiewNetworkStatePanelTestCase(OverwiewPanelTestCase): | 561 | class OverwiewNetworkStatePanelTestCase(OverwiewPanelTestCase): |
1745 | @@ -514,13 +606,13 @@ | |||
1746 | 514 | def test_find_credentials_is_called(self): | 606 | def test_find_credentials_is_called(self): |
1747 | 515 | """Credentials are asked to SSO backend.""" | 607 | """Credentials are asked to SSO backend.""" |
1748 | 516 | self.assertFalse(self.ui._credentials_are_new) | 608 | self.assertFalse(self.ui._credentials_are_new) |
1750 | 517 | self.assert_backend_called('find_credentials', (gui.U1_APP_NAME, {})) | 609 | self.assert_backend_called('find_credentials') |
1751 | 518 | 610 | ||
1752 | 519 | def test_on_credentials_found(self): | 611 | def test_on_credentials_found(self): |
1753 | 520 | """Callback 'on_credentials_found' is correct.""" | 612 | """Callback 'on_credentials_found' is correct.""" |
1754 | 521 | self.ui.connect('credentials-found', self._set_called) | 613 | self.ui.connect('credentials-found', self._set_called) |
1755 | 522 | 614 | ||
1757 | 523 | self.ui.on_credentials_found(gui.U1_APP_NAME, TOKEN) | 615 | self.ui.on_credentials_found(TOKEN) |
1758 | 524 | 616 | ||
1759 | 525 | self.assertFalse(self.ui.get_property('greyed'), 'Must not be greyed.') | 617 | self.assertFalse(self.ui.get_property('greyed'), 'Must not be greyed.') |
1760 | 526 | # assume credentials were in local keyring | 618 | # assume credentials were in local keyring |
1761 | @@ -531,9 +623,9 @@ | |||
1762 | 531 | self.ui.connect('credentials-found', self._set_called) | 623 | self.ui.connect('credentials-found', self._set_called) |
1763 | 532 | 624 | ||
1764 | 533 | # credentials weren't in the system | 625 | # credentials weren't in the system |
1766 | 534 | self.ui.on_credentials_not_found(gui.U1_APP_NAME) | 626 | self.ui.on_credentials_not_found() |
1767 | 535 | # now they are! | 627 | # now they are! |
1769 | 536 | self.ui.on_credentials_found(gui.U1_APP_NAME, TOKEN) | 628 | self.ui.on_credentials_found(TOKEN) |
1770 | 537 | 629 | ||
1771 | 538 | self.assertFalse(self.ui.get_property('greyed'), 'Must not be greyed.') | 630 | self.assertFalse(self.ui.get_property('greyed'), 'Must not be greyed.') |
1772 | 539 | # assume credentials were not in local keyring | 631 | # assume credentials were not in local keyring |
1773 | @@ -541,70 +633,31 @@ | |||
1774 | 541 | 633 | ||
1775 | 542 | def test_on_credentials_not_found(self): | 634 | def test_on_credentials_not_found(self): |
1776 | 543 | """Callback 'on_credentials_not_found' is correct.""" | 635 | """Callback 'on_credentials_not_found' is correct.""" |
1778 | 544 | self.ui.on_credentials_not_found(gui.U1_APP_NAME) | 636 | self.ui.on_credentials_not_found() |
1779 | 545 | self.assertTrue(self.ui.get_visible()) | 637 | self.assertTrue(self.ui.get_visible()) |
1780 | 546 | self.assertTrue(self.ui._credentials_are_new) | 638 | self.assertTrue(self.ui._credentials_are_new) |
1781 | 547 | 639 | ||
1782 | 548 | def test_on_credentials_error(self): | 640 | def test_on_credentials_error(self): |
1783 | 549 | """Callback 'on_credentials_error' is correct.""" | 641 | """Callback 'on_credentials_error' is correct.""" |
1785 | 550 | self.ui.on_credentials_error(gui.U1_APP_NAME, {}) | 642 | self.ui.on_credentials_error({}) |
1786 | 551 | self.assertTrue(self.ui.get_visible()) | 643 | self.assertTrue(self.ui.get_visible()) |
1787 | 552 | self.assert_warning_correct(self.ui.warning_label, | 644 | self.assert_warning_correct(self.ui.warning_label, |
1788 | 553 | gui.CREDENTIALS_ERROR) | 645 | gui.CREDENTIALS_ERROR) |
1789 | 554 | 646 | ||
1790 | 555 | def test_on_authorization_denied(self): | 647 | def test_on_authorization_denied(self): |
1791 | 556 | """Callback 'on_authorization_denied' is correct.""" | 648 | """Callback 'on_authorization_denied' is correct.""" |
1793 | 557 | self.ui.on_authorization_denied(gui.U1_APP_NAME) | 649 | self.ui.on_authorization_denied() |
1794 | 558 | self.assertTrue(self.ui.get_visible()) | 650 | self.assertTrue(self.ui.get_visible()) |
1795 | 559 | self.assertFalse(self.ui.get_property('greyed'), 'Must not be greyed.') | 651 | self.assertFalse(self.ui.get_property('greyed'), 'Must not be greyed.') |
1796 | 560 | self.assertEqual(self.ui.warning_label.get_text(), '') | 652 | self.assertEqual(self.ui.warning_label.get_text(), '') |
1797 | 561 | 653 | ||
1798 | 562 | 654 | ||
1799 | 563 | class OverwiewPanelAppNameMismatchTestCase(OverwiewPanelTestCase): | ||
1800 | 564 | """The test suite for the overview panel when the app_name won't match.""" | ||
1801 | 565 | |||
1802 | 566 | NOT_U1_APP = 'Not ' + gui.U1_APP_NAME | ||
1803 | 567 | |||
1804 | 568 | def test_filter_by_app_name(self): | ||
1805 | 569 | """The filter_by_app_name decorator is correct.""" | ||
1806 | 570 | f = gui.filter_by_app_name(self._set_called) | ||
1807 | 571 | f(self.ui, self.NOT_U1_APP) | ||
1808 | 572 | self.assertFalse(self._called) | ||
1809 | 573 | self.assertTrue(self.memento.check_info('ignoring', self.NOT_U1_APP)) | ||
1810 | 574 | |||
1811 | 575 | args = ('test', object()) | ||
1812 | 576 | kwargs = {'really': 'AWESOME'} | ||
1813 | 577 | f(self.ui, gui.U1_APP_NAME, *args, **kwargs) | ||
1814 | 578 | self.assertEqual(self._called, | ||
1815 | 579 | ((self.ui, gui.U1_APP_NAME,) + args, kwargs)) | ||
1816 | 580 | |||
1817 | 581 | def test_on_credentials_found(self): | ||
1818 | 582 | """Callback 'on_credentials_found' is not executed.""" | ||
1819 | 583 | self.assert_function_decorated(gui.filter_by_app_name, | ||
1820 | 584 | self.ui.on_credentials_found) | ||
1821 | 585 | |||
1822 | 586 | def test_on_credentials_not_found(self): | ||
1823 | 587 | """Callback 'on_credentials_not_found' is not executed.""" | ||
1824 | 588 | self.assert_function_decorated(gui.filter_by_app_name, | ||
1825 | 589 | self.ui.on_credentials_not_found) | ||
1826 | 590 | |||
1827 | 591 | def test_on_credentials_error(self): | ||
1828 | 592 | """Callback 'on_credentials_error' is not executed.""" | ||
1829 | 593 | self.assert_function_decorated(gui.filter_by_app_name, | ||
1830 | 594 | self.ui.on_credentials_error) | ||
1831 | 595 | |||
1832 | 596 | def test_on_authorization_denied(self): | ||
1833 | 597 | """Callback 'on_authorization_denied' is not executed.""" | ||
1834 | 598 | self.assert_function_decorated(gui.filter_by_app_name, | ||
1835 | 599 | self.ui.on_authorization_denied) | ||
1836 | 600 | |||
1837 | 601 | |||
1838 | 602 | class OverwiewPanelNoCredsTestCase(OverwiewPanelTestCase): | 655 | class OverwiewPanelNoCredsTestCase(OverwiewPanelTestCase): |
1839 | 603 | """The test suite for the overview panel when no credentials are found.""" | 656 | """The test suite for the overview panel when no credentials are found.""" |
1840 | 604 | 657 | ||
1841 | 605 | def setUp(self): | 658 | def setUp(self): |
1842 | 606 | super(OverwiewPanelNoCredsTestCase, self).setUp() | 659 | super(OverwiewPanelNoCredsTestCase, self).setUp() |
1844 | 607 | self.ui.on_credentials_not_found(gui.U1_APP_NAME) | 660 | self.ui.on_credentials_not_found() |
1845 | 608 | 661 | ||
1846 | 609 | def test_startup_visibility(self): | 662 | def test_startup_visibility(self): |
1847 | 610 | """The widget is visible at startup.""" | 663 | """The widget is visible at startup.""" |
1848 | @@ -631,12 +684,8 @@ | |||
1849 | 631 | self.ui.join_now_button.clicked() | 684 | self.ui.join_now_button.clicked() |
1850 | 632 | 685 | ||
1851 | 633 | window_id = self.kwargs['main_window'].window.xid | 686 | window_id = self.kwargs['main_window'].window.xid |
1858 | 634 | args = (gui.U1_APP_NAME, | 687 | kwargs = {'window_id': str(window_id)} |
1859 | 635 | {gui.TC_URL_KEY: gui.U1_TC_URL, | 688 | self.assert_backend_called('register', **kwargs) |
1854 | 636 | gui.HELP_TEXT_KEY: gui.U1_DESCRIPTION, | ||
1855 | 637 | gui.WINDOW_ID_KEY: str(window_id), | ||
1856 | 638 | gui.PING_URL_KEY: gui.U1_PING_URL}) | ||
1857 | 639 | self.assert_backend_called('register', args) | ||
1860 | 640 | 689 | ||
1861 | 641 | def test_connect_button_clicked(self): | 690 | def test_connect_button_clicked(self): |
1862 | 642 | """Test the 'join now' button callback.""" | 691 | """Test the 'join now' button callback.""" |
1863 | @@ -646,12 +695,8 @@ | |||
1864 | 646 | self.ui.connect_button.clicked() | 695 | self.ui.connect_button.clicked() |
1865 | 647 | 696 | ||
1866 | 648 | window_id = self.kwargs['main_window'].window.xid | 697 | window_id = self.kwargs['main_window'].window.xid |
1873 | 649 | args = (gui.U1_APP_NAME, | 698 | kwargs = {'window_id': str(window_id)} |
1874 | 650 | {gui.TC_URL_KEY: gui.U1_TC_URL, | 699 | self.assert_backend_called('login', **kwargs) |
1869 | 651 | gui.HELP_TEXT_KEY: gui.U1_DESCRIPTION, | ||
1870 | 652 | gui.WINDOW_ID_KEY: str(window_id), | ||
1871 | 653 | gui.PING_URL_KEY: gui.U1_PING_URL}) | ||
1872 | 654 | self.assert_backend_called('login', args) | ||
1875 | 655 | 700 | ||
1876 | 656 | def test_join_now_button_clicked_set_greyed(self): | 701 | def test_join_now_button_clicked_set_greyed(self): |
1877 | 657 | """Clicking on 'join_now' self is greyed.""" | 702 | """Clicking on 'join_now' self is greyed.""" |
1878 | @@ -660,7 +705,7 @@ | |||
1879 | 660 | 705 | ||
1880 | 661 | def test_join_now_button_clicked_removes_warning(self): | 706 | def test_join_now_button_clicked_removes_warning(self): |
1881 | 662 | """Clicking on 'join_now' the warnings are removed.""" | 707 | """Clicking on 'join_now' the warnings are removed.""" |
1883 | 663 | self.ui.on_authorization_denied(gui.U1_APP_NAME) # show warning | 708 | self.ui.on_authorization_denied() # show warning |
1884 | 664 | self.ui.join_now_button.clicked() | 709 | self.ui.join_now_button.clicked() |
1885 | 665 | 710 | ||
1886 | 666 | self.assertEqual(self.ui.warning_label.get_text(), '') | 711 | self.assertEqual(self.ui.warning_label.get_text(), '') |
1887 | @@ -672,7 +717,7 @@ | |||
1888 | 672 | 717 | ||
1889 | 673 | def test_connect_button_clicked_removes_warning(self): | 718 | def test_connect_button_clicked_removes_warning(self): |
1890 | 674 | """Clicking on 'connect' the warnings are removed.""" | 719 | """Clicking on 'connect' the warnings are removed.""" |
1892 | 675 | self.ui.on_authorization_denied(gui.U1_APP_NAME) # show warning | 720 | self.ui.on_authorization_denied() # show warning |
1893 | 676 | self.ui.connect_button.clicked() | 721 | self.ui.connect_button.clicked() |
1894 | 677 | 722 | ||
1895 | 678 | self.assertEqual(self.ui.warning_label.get_text(), '') | 723 | self.assertEqual(self.ui.warning_label.get_text(), '') |
1896 | @@ -688,21 +733,21 @@ | |||
1897 | 688 | def test_on_credentials_not_found_unset_greyed(self): | 733 | def test_on_credentials_not_found_unset_greyed(self): |
1898 | 689 | """Callback 'on_credentials_not_found' unsets the 'greyed' prop.""" | 734 | """Callback 'on_credentials_not_found' unsets the 'greyed' prop.""" |
1899 | 690 | self.ui.connect_button.clicked() | 735 | self.ui.connect_button.clicked() |
1901 | 691 | self.ui.on_credentials_not_found(gui.U1_APP_NAME) | 736 | self.ui.on_credentials_not_found() |
1902 | 692 | 737 | ||
1903 | 693 | self.assertFalse(self.ui.get_property('greyed'), 'Must not be greyed.') | 738 | self.assertFalse(self.ui.get_property('greyed'), 'Must not be greyed.') |
1904 | 694 | 739 | ||
1905 | 695 | def test_on_credentials_error_unset_greyed(self): | 740 | def test_on_credentials_error_unset_greyed(self): |
1906 | 696 | """Callback 'on_credentials_error' unsets the 'greyed' prop.""" | 741 | """Callback 'on_credentials_error' unsets the 'greyed' prop.""" |
1907 | 697 | self.ui.connect_button.clicked() | 742 | self.ui.connect_button.clicked() |
1909 | 698 | self.ui.on_credentials_error(gui.U1_APP_NAME, {}) | 743 | self.ui.on_credentials_error({}) |
1910 | 699 | 744 | ||
1911 | 700 | self.assertFalse(self.ui.get_property('greyed'), 'Must not be greyed.') | 745 | self.assertFalse(self.ui.get_property('greyed'), 'Must not be greyed.') |
1912 | 701 | 746 | ||
1913 | 702 | def test_on_authorization_denied_unset_greyed(self): | 747 | def test_on_authorization_denied_unset_greyed(self): |
1914 | 703 | """Callback 'on_authorization_denied' unsets the 'greyed' prop.""" | 748 | """Callback 'on_authorization_denied' unsets the 'greyed' prop.""" |
1915 | 704 | self.ui.connect_button.clicked() | 749 | self.ui.connect_button.clicked() |
1917 | 705 | self.ui.on_authorization_denied(gui.U1_APP_NAME) | 750 | self.ui.on_authorization_denied() |
1918 | 706 | 751 | ||
1919 | 707 | self.assertFalse(self.ui.get_property('greyed'), 'Must not be greyed.') | 752 | self.assertFalse(self.ui.get_property('greyed'), 'Must not be greyed.') |
1920 | 708 | 753 | ||
1921 | 709 | 754 | ||
1922 | === modified file 'ubuntuone/controlpanel/gui/qt/filesyncstatus.py' | |||
1923 | --- ubuntuone/controlpanel/gui/qt/filesyncstatus.py 2011-07-22 21:26:48 +0000 | |||
1924 | +++ ubuntuone/controlpanel/gui/qt/filesyncstatus.py 2011-08-25 19:40:18 +0000 | |||
1925 | @@ -165,6 +165,14 @@ | |||
1926 | 165 | self.ui.sync_status_button.setText(action) | 165 | self.ui.sync_status_button.setText(action) |
1927 | 166 | self.ui.sync_status_button.setEnabled(True) | 166 | self.ui.sync_status_button.setEnabled(True) |
1928 | 167 | self.ui.sync_status_button.show() | 167 | self.ui.sync_status_button.show() |
1929 | 168 | if status_key == backend.FILE_SYNC_DISCONNECTED: | ||
1930 | 169 | self.ui.sync_status_button.setProperty("secondary", False) | ||
1931 | 170 | else: | ||
1932 | 171 | self.ui.sync_status_button.setProperty("secondary", True) | ||
1933 | 172 | self.ui.sync_status_button.style().unpolish( | ||
1934 | 173 | self.ui.sync_status_button) | ||
1935 | 174 | self.ui.sync_status_button.style().polish( | ||
1936 | 175 | self.ui.sync_status_button) | ||
1937 | 168 | else: | 176 | else: |
1938 | 169 | self.ui.sync_status_button.hide() | 177 | self.ui.sync_status_button.hide() |
1939 | 170 | 178 | ||
1940 | 171 | 179 | ||
1941 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/test_filesyncstatus.py' | |||
1942 | --- ubuntuone/controlpanel/gui/qt/tests/test_filesyncstatus.py 2011-07-22 21:26:48 +0000 | |||
1943 | +++ ubuntuone/controlpanel/gui/qt/tests/test_filesyncstatus.py 2011-08-25 19:40:18 +0000 | |||
1944 | @@ -65,10 +65,22 @@ | |||
1945 | 65 | 65 | ||
1946 | 66 | self.assertTrue(self.ui.ui.sync_status_button.isEnabled()) | 66 | self.assertTrue(self.ui.ui.sync_status_button.isEnabled()) |
1947 | 67 | self.assertEqual(self.ui.ui.sync_status_button.text(), action) | 67 | self.assertEqual(self.ui.ui.sync_status_button.text(), action) |
1948 | 68 | if action == gui.FILE_SYNC_DISCONNECTED: | ||
1949 | 69 | self.assertFalse( | ||
1950 | 70 | self.ui.ui.sync_status_button.property("secondary")) | ||
1951 | 71 | else: | ||
1952 | 72 | self.assertTrue( | ||
1953 | 73 | self.ui.ui.sync_status_button.property("secondary")) | ||
1954 | 68 | 74 | ||
1955 | 69 | self.ui.ui.sync_status_button.click() | 75 | self.ui.ui.sync_status_button.click() |
1956 | 70 | self.assertFalse(self.ui.ui.sync_status_button.isEnabled()) | 76 | self.assertFalse(self.ui.ui.sync_status_button.isEnabled()) |
1957 | 71 | self.assert_backend_called(callback) | 77 | self.assert_backend_called(callback) |
1958 | 78 | if action == gui.FILE_SYNC_DISCONNECTED: | ||
1959 | 79 | self.assertFalse( | ||
1960 | 80 | self.ui.ui.sync_status_button.property("secondary")) | ||
1961 | 81 | else: | ||
1962 | 82 | self.assertTrue( | ||
1963 | 83 | self.ui.ui.sync_status_button.property("secondary")) | ||
1964 | 72 | 84 | ||
1965 | 73 | if tooltip is not None: | 85 | if tooltip is not None: |
1966 | 74 | self.assertEqual(self.ui.ui.sync_status_button.toolTip(), tooltip) | 86 | self.assertEqual(self.ui.ui.sync_status_button.toolTip(), tooltip) |
1967 | 75 | 87 | ||
1968 | === modified file 'ubuntuone/controlpanel/gui/qt/ui/account_ui.py' | |||
1969 | --- ubuntuone/controlpanel/gui/qt/ui/account_ui.py 2011-08-12 19:12:08 +0000 | |||
1970 | +++ ubuntuone/controlpanel/gui/qt/ui/account_ui.py 2011-08-25 19:40:18 +0000 | |||
1971 | @@ -2,7 +2,7 @@ | |||
1972 | 2 | 2 | ||
1973 | 3 | # Form implementation generated from reading ui file 'data/qt/account.ui' | 3 | # Form implementation generated from reading ui file 'data/qt/account.ui' |
1974 | 4 | # | 4 | # |
1976 | 5 | # Created: Fri Aug 12 15:07:18 2011 | 5 | # Created: Thu Aug 25 15:26:50 2011 |
1977 | 6 | # by: PyQt4 UI code generator 4.8.3 | 6 | # by: PyQt4 UI code generator 4.8.3 |
1978 | 7 | # | 7 | # |
1979 | 8 | # WARNING! All changes made in this file will be lost! | 8 | # WARNING! All changes made in this file will be lost! |
1980 | @@ -27,7 +27,7 @@ | |||
1981 | 27 | self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2")) | 27 | self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2")) |
1982 | 28 | self.edit_profile_button = GoToWebButton(Form) | 28 | self.edit_profile_button = GoToWebButton(Form) |
1983 | 29 | self.edit_profile_button.setObjectName(_fromUtf8("edit_profile_button")) | 29 | self.edit_profile_button.setObjectName(_fromUtf8("edit_profile_button")) |
1985 | 30 | self.gridLayout_2.addWidget(self.edit_profile_button, 2, 2, 1, 1) | 30 | self.gridLayout_2.addWidget(self.edit_profile_button, 0, 2, 1, 1) |
1986 | 31 | self.services = QtGui.QGroupBox(Form) | 31 | self.services = QtGui.QGroupBox(Form) |
1987 | 32 | self.services.setObjectName(_fromUtf8("services")) | 32 | self.services.setObjectName(_fromUtf8("services")) |
1988 | 33 | self.verticalLayout_3 = QtGui.QVBoxLayout(self.services) | 33 | self.verticalLayout_3 = QtGui.QVBoxLayout(self.services) |
1989 | @@ -62,7 +62,7 @@ | |||
1990 | 62 | self.gridLayout_2.addWidget(self.profile_info, 0, 0, 1, 1) | 62 | self.gridLayout_2.addWidget(self.profile_info, 0, 0, 1, 1) |
1991 | 63 | self.edit_services_button = GoToWebButton(Form) | 63 | self.edit_services_button = GoToWebButton(Form) |
1992 | 64 | self.edit_services_button.setObjectName(_fromUtf8("edit_services_button")) | 64 | self.edit_services_button.setObjectName(_fromUtf8("edit_services_button")) |
1994 | 65 | self.gridLayout_2.addWidget(self.edit_services_button, 0, 2, 1, 1) | 65 | self.gridLayout_2.addWidget(self.edit_services_button, 2, 2, 1, 1) |
1995 | 66 | spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) | 66 | spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) |
1996 | 67 | self.gridLayout_2.addItem(spacerItem, 0, 3, 1, 1) | 67 | self.gridLayout_2.addItem(spacerItem, 0, 3, 1, 1) |
1997 | 68 | spacerItem1 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) | 68 | spacerItem1 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) |
1998 | 69 | 69 | ||
1999 | === modified file 'ubuntuone/controlpanel/gui/qt/ui/controlpanel_ui.py' | |||
2000 | --- ubuntuone/controlpanel/gui/qt/ui/controlpanel_ui.py 2011-08-12 19:12:08 +0000 | |||
2001 | +++ ubuntuone/controlpanel/gui/qt/ui/controlpanel_ui.py 2011-08-25 19:40:18 +0000 | |||
2002 | @@ -2,7 +2,7 @@ | |||
2003 | 2 | 2 | ||
2004 | 3 | # Form implementation generated from reading ui file 'data/qt/controlpanel.ui' | 3 | # Form implementation generated from reading ui file 'data/qt/controlpanel.ui' |
2005 | 4 | # | 4 | # |
2007 | 5 | # Created: Fri Aug 12 15:07:18 2011 | 5 | # Created: Thu Aug 25 15:26:50 2011 |
2008 | 6 | # by: PyQt4 UI code generator 4.8.3 | 6 | # by: PyQt4 UI code generator 4.8.3 |
2009 | 7 | # | 7 | # |
2010 | 8 | # WARNING! All changes made in this file will be lost! | 8 | # WARNING! All changes made in this file will be lost! |
2011 | @@ -18,7 +18,7 @@ | |||
2012 | 18 | class Ui_Form(object): | 18 | class Ui_Form(object): |
2013 | 19 | def setupUi(self, Form): | 19 | def setupUi(self, Form): |
2014 | 20 | Form.setObjectName(_fromUtf8("Form")) | 20 | Form.setObjectName(_fromUtf8("Form")) |
2016 | 21 | Form.resize(387, 203) | 21 | Form.resize(367, 142) |
2017 | 22 | sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) | 22 | sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) |
2018 | 23 | sizePolicy.setHorizontalStretch(0) | 23 | sizePolicy.setHorizontalStretch(0) |
2019 | 24 | sizePolicy.setVerticalStretch(0) | 24 | sizePolicy.setVerticalStretch(0) |
2020 | @@ -133,10 +133,16 @@ | |||
2021 | 133 | self.tab_widget.addTab(self.account_tab, _fromUtf8("")) | 133 | self.tab_widget.addTab(self.account_tab, _fromUtf8("")) |
2022 | 134 | self.verticalLayout.addWidget(self.tab_widget) | 134 | self.verticalLayout.addWidget(self.tab_widget) |
2023 | 135 | self.frame_footer = QtGui.QFrame(Form) | 135 | self.frame_footer = QtGui.QFrame(Form) |
2024 | 136 | sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) | ||
2025 | 137 | sizePolicy.setHorizontalStretch(0) | ||
2026 | 138 | sizePolicy.setVerticalStretch(0) | ||
2027 | 139 | sizePolicy.setHeightForWidth(self.frame_footer.sizePolicy().hasHeightForWidth()) | ||
2028 | 140 | self.frame_footer.setSizePolicy(sizePolicy) | ||
2029 | 141 | self.frame_footer.setMaximumSize(QtCore.QSize(16777215, 30)) | ||
2030 | 136 | self.frame_footer.setObjectName(_fromUtf8("frame_footer")) | 142 | self.frame_footer.setObjectName(_fromUtf8("frame_footer")) |
2031 | 137 | self.horizontalLayout = QtGui.QHBoxLayout(self.frame_footer) | 143 | self.horizontalLayout = QtGui.QHBoxLayout(self.frame_footer) |
2032 | 138 | self.horizontalLayout.setSpacing(5) | 144 | self.horizontalLayout.setSpacing(5) |
2034 | 139 | self.horizontalLayout.setContentsMargins(3, 0, 3, 3) | 145 | self.horizontalLayout.setMargin(0) |
2035 | 140 | self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout")) | 146 | self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout")) |
2036 | 141 | self.help_button = GoToWebButton(self.frame_footer) | 147 | self.help_button = GoToWebButton(self.frame_footer) |
2037 | 142 | self.help_button.setObjectName(_fromUtf8("help_button")) | 148 | self.help_button.setObjectName(_fromUtf8("help_button")) |
2038 | @@ -149,24 +155,30 @@ | |||
2039 | 149 | self.follow_us_label.setFont(font) | 155 | self.follow_us_label.setFont(font) |
2040 | 150 | self.follow_us_label.setObjectName(_fromUtf8("follow_us_label")) | 156 | self.follow_us_label.setObjectName(_fromUtf8("follow_us_label")) |
2041 | 151 | self.horizontalLayout.addWidget(self.follow_us_label) | 157 | self.horizontalLayout.addWidget(self.follow_us_label) |
2043 | 152 | self.twitter_button = QtGui.QToolButton(self.frame_footer) | 158 | self.twitter_button = QtGui.QPushButton(self.frame_footer) |
2044 | 159 | sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) | ||
2045 | 160 | sizePolicy.setHorizontalStretch(0) | ||
2046 | 161 | sizePolicy.setVerticalStretch(0) | ||
2047 | 162 | sizePolicy.setHeightForWidth(self.twitter_button.sizePolicy().hasHeightForWidth()) | ||
2048 | 163 | self.twitter_button.setSizePolicy(sizePolicy) | ||
2049 | 164 | self.twitter_button.setMaximumSize(QtCore.QSize(16, 16)) | ||
2050 | 153 | self.twitter_button.setCursor(QtCore.Qt.PointingHandCursor) | 165 | self.twitter_button.setCursor(QtCore.Qt.PointingHandCursor) |
2051 | 154 | self.twitter_button.setStyleSheet(_fromUtf8("border: 0;")) | ||
2052 | 155 | self.twitter_button.setText(_fromUtf8("")) | ||
2053 | 156 | icon = QtGui.QIcon() | 166 | icon = QtGui.QIcon() |
2054 | 157 | icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/twitter.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) | 167 | icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/twitter.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) |
2055 | 158 | self.twitter_button.setIcon(icon) | 168 | self.twitter_button.setIcon(icon) |
2056 | 159 | self.twitter_button.setIconSize(QtCore.QSize(22, 22)) | ||
2057 | 160 | self.twitter_button.setObjectName(_fromUtf8("twitter_button")) | 169 | self.twitter_button.setObjectName(_fromUtf8("twitter_button")) |
2058 | 161 | self.horizontalLayout.addWidget(self.twitter_button) | 170 | self.horizontalLayout.addWidget(self.twitter_button) |
2060 | 162 | self.facebook_button = QtGui.QToolButton(self.frame_footer) | 171 | self.facebook_button = QtGui.QPushButton(self.frame_footer) |
2061 | 172 | sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) | ||
2062 | 173 | sizePolicy.setHorizontalStretch(0) | ||
2063 | 174 | sizePolicy.setVerticalStretch(0) | ||
2064 | 175 | sizePolicy.setHeightForWidth(self.facebook_button.sizePolicy().hasHeightForWidth()) | ||
2065 | 176 | self.facebook_button.setSizePolicy(sizePolicy) | ||
2066 | 177 | self.facebook_button.setMaximumSize(QtCore.QSize(16, 16)) | ||
2067 | 163 | self.facebook_button.setCursor(QtCore.Qt.PointingHandCursor) | 178 | self.facebook_button.setCursor(QtCore.Qt.PointingHandCursor) |
2068 | 164 | self.facebook_button.setStyleSheet(_fromUtf8("border: 0;")) | ||
2069 | 165 | self.facebook_button.setText(_fromUtf8("")) | ||
2070 | 166 | icon1 = QtGui.QIcon() | 179 | icon1 = QtGui.QIcon() |
2071 | 167 | icon1.addPixmap(QtGui.QPixmap(_fromUtf8(":/facebook.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) | 180 | icon1.addPixmap(QtGui.QPixmap(_fromUtf8(":/facebook.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) |
2072 | 168 | self.facebook_button.setIcon(icon1) | 181 | self.facebook_button.setIcon(icon1) |
2073 | 169 | self.facebook_button.setIconSize(QtCore.QSize(22, 22)) | ||
2074 | 170 | self.facebook_button.setObjectName(_fromUtf8("facebook_button")) | 182 | self.facebook_button.setObjectName(_fromUtf8("facebook_button")) |
2075 | 171 | self.horizontalLayout.addWidget(self.facebook_button) | 183 | self.horizontalLayout.addWidget(self.facebook_button) |
2076 | 172 | self.verticalLayout.addWidget(self.frame_footer) | 184 | self.verticalLayout.addWidget(self.frame_footer) |
2077 | @@ -182,7 +194,7 @@ | |||
2078 | 182 | self.get_more_space_button.setText(_('Get more storage')) | 194 | self.get_more_space_button.setText(_('Get more storage')) |
2079 | 183 | self.tab_widget.setTabText(self.tab_widget.indexOf(self.folders_tab), _('Folders')) | 195 | self.tab_widget.setTabText(self.tab_widget.indexOf(self.folders_tab), _('Folders')) |
2080 | 184 | self.tab_widget.setTabText(self.tab_widget.indexOf(self.devices_tab), _('Devices')) | 196 | self.tab_widget.setTabText(self.tab_widget.indexOf(self.devices_tab), _('Devices')) |
2082 | 185 | self.tab_widget.setTabText(self.tab_widget.indexOf(self.preferences_tab), _('Preferences')) | 197 | self.tab_widget.setTabText(self.tab_widget.indexOf(self.preferences_tab), _('Settings')) |
2083 | 186 | self.tab_widget.setTabText(self.tab_widget.indexOf(self.account_tab), _('Account information')) | 198 | self.tab_widget.setTabText(self.tab_widget.indexOf(self.account_tab), _('Account information')) |
2084 | 187 | self.help_button.setText(_('Get help online')) | 199 | self.help_button.setText(_('Get help online')) |
2085 | 188 | self.follow_us_label.setText(_('Talk to us')) | 200 | self.follow_us_label.setText(_('Talk to us')) |
2086 | 189 | 201 | ||
2087 | === modified file 'ubuntuone/controlpanel/gui/qt/ui/device_ui.py' | |||
2088 | --- ubuntuone/controlpanel/gui/qt/ui/device_ui.py 2011-08-12 19:12:08 +0000 | |||
2089 | +++ ubuntuone/controlpanel/gui/qt/ui/device_ui.py 2011-08-25 19:40:18 +0000 | |||
2090 | @@ -2,7 +2,7 @@ | |||
2091 | 2 | 2 | ||
2092 | 3 | # Form implementation generated from reading ui file 'data/qt/device.ui' | 3 | # Form implementation generated from reading ui file 'data/qt/device.ui' |
2093 | 4 | # | 4 | # |
2095 | 5 | # Created: Fri Aug 12 15:07:18 2011 | 5 | # Created: Thu Aug 25 15:26:50 2011 |
2096 | 6 | # by: PyQt4 UI code generator 4.8.3 | 6 | # by: PyQt4 UI code generator 4.8.3 |
2097 | 7 | # | 7 | # |
2098 | 8 | # WARNING! All changes made in this file will be lost! | 8 | # WARNING! All changes made in this file will be lost! |
2099 | @@ -32,6 +32,7 @@ | |||
2100 | 32 | spacerItem = QtGui.QSpacerItem(217, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) | 32 | spacerItem = QtGui.QSpacerItem(217, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) |
2101 | 33 | self.horizontalLayout.addItem(spacerItem) | 33 | self.horizontalLayout.addItem(spacerItem) |
2102 | 34 | self.remove_device_button = QtGui.QPushButton(Form) | 34 | self.remove_device_button = QtGui.QPushButton(Form) |
2103 | 35 | self.remove_device_button.setProperty(_fromUtf8("secondary"), True) | ||
2104 | 35 | self.remove_device_button.setObjectName(_fromUtf8("remove_device_button")) | 36 | self.remove_device_button.setObjectName(_fromUtf8("remove_device_button")) |
2105 | 36 | self.horizontalLayout.addWidget(self.remove_device_button) | 37 | self.horizontalLayout.addWidget(self.remove_device_button) |
2106 | 37 | 38 | ||
2107 | 38 | 39 | ||
2108 | === modified file 'ubuntuone/controlpanel/gui/qt/ui/devices_ui.py' | |||
2109 | --- ubuntuone/controlpanel/gui/qt/ui/devices_ui.py 2011-08-12 19:12:08 +0000 | |||
2110 | +++ ubuntuone/controlpanel/gui/qt/ui/devices_ui.py 2011-08-25 19:40:18 +0000 | |||
2111 | @@ -2,7 +2,7 @@ | |||
2112 | 2 | 2 | ||
2113 | 3 | # Form implementation generated from reading ui file 'data/qt/devices.ui' | 3 | # Form implementation generated from reading ui file 'data/qt/devices.ui' |
2114 | 4 | # | 4 | # |
2116 | 5 | # Created: Fri Aug 12 15:07:18 2011 | 5 | # Created: Thu Aug 25 15:26:50 2011 |
2117 | 6 | # by: PyQt4 UI code generator 4.8.3 | 6 | # by: PyQt4 UI code generator 4.8.3 |
2118 | 7 | # | 7 | # |
2119 | 8 | # WARNING! All changes made in this file will be lost! | 8 | # WARNING! All changes made in this file will be lost! |
2120 | 9 | 9 | ||
2121 | === modified file 'ubuntuone/controlpanel/gui/qt/ui/filesyncstatus_ui.py' | |||
2122 | --- ubuntuone/controlpanel/gui/qt/ui/filesyncstatus_ui.py 2011-08-12 19:12:08 +0000 | |||
2123 | +++ ubuntuone/controlpanel/gui/qt/ui/filesyncstatus_ui.py 2011-08-25 19:40:18 +0000 | |||
2124 | @@ -2,7 +2,7 @@ | |||
2125 | 2 | 2 | ||
2126 | 3 | # Form implementation generated from reading ui file 'data/qt/filesyncstatus.ui' | 3 | # Form implementation generated from reading ui file 'data/qt/filesyncstatus.ui' |
2127 | 4 | # | 4 | # |
2129 | 5 | # Created: Fri Aug 12 15:07:18 2011 | 5 | # Created: Thu Aug 25 15:26:50 2011 |
2130 | 6 | # by: PyQt4 UI code generator 4.8.3 | 6 | # by: PyQt4 UI code generator 4.8.3 |
2131 | 7 | # | 7 | # |
2132 | 8 | # WARNING! All changes made in this file will be lost! | 8 | # WARNING! All changes made in this file will be lost! |
2133 | @@ -35,6 +35,7 @@ | |||
2134 | 35 | self.horizontalLayout.addWidget(self.sync_status_label) | 35 | self.horizontalLayout.addWidget(self.sync_status_label) |
2135 | 36 | self.verticalLayout.addLayout(self.horizontalLayout) | 36 | self.verticalLayout.addLayout(self.horizontalLayout) |
2136 | 37 | self.sync_status_button = QtGui.QPushButton(Form) | 37 | self.sync_status_button = QtGui.QPushButton(Form) |
2137 | 38 | self.sync_status_button.setProperty(_fromUtf8("secondary"), True) | ||
2138 | 38 | self.sync_status_button.setObjectName(_fromUtf8("sync_status_button")) | 39 | self.sync_status_button.setObjectName(_fromUtf8("sync_status_button")) |
2139 | 39 | self.verticalLayout.addWidget(self.sync_status_button) | 40 | self.verticalLayout.addWidget(self.sync_status_button) |
2140 | 40 | self.sync_status_label.setBuddy(self.sync_status_button) | 41 | self.sync_status_label.setBuddy(self.sync_status_button) |
2141 | 41 | 42 | ||
2142 | === modified file 'ubuntuone/controlpanel/gui/qt/ui/folders_ui.py' | |||
2143 | --- ubuntuone/controlpanel/gui/qt/ui/folders_ui.py 2011-08-12 19:12:08 +0000 | |||
2144 | +++ ubuntuone/controlpanel/gui/qt/ui/folders_ui.py 2011-08-25 19:40:18 +0000 | |||
2145 | @@ -2,7 +2,7 @@ | |||
2146 | 2 | 2 | ||
2147 | 3 | # Form implementation generated from reading ui file 'data/qt/folders.ui' | 3 | # Form implementation generated from reading ui file 'data/qt/folders.ui' |
2148 | 4 | # | 4 | # |
2150 | 5 | # Created: Fri Aug 12 15:07:18 2011 | 5 | # Created: Thu Aug 25 15:26:50 2011 |
2151 | 6 | # by: PyQt4 UI code generator 4.8.3 | 6 | # by: PyQt4 UI code generator 4.8.3 |
2152 | 7 | # | 7 | # |
2153 | 8 | # WARNING! All changes made in this file will be lost! | 8 | # WARNING! All changes made in this file will be lost! |
2154 | @@ -20,7 +20,6 @@ | |||
2155 | 20 | Form.setObjectName(_fromUtf8("Form")) | 20 | Form.setObjectName(_fromUtf8("Form")) |
2156 | 21 | Form.resize(345, 279) | 21 | Form.resize(345, 279) |
2157 | 22 | Form.setWindowTitle(_fromUtf8("Form")) | 22 | Form.setWindowTitle(_fromUtf8("Form")) |
2158 | 23 | Form.setStyleSheet(_fromUtf8("padding: 0px;")) | ||
2159 | 24 | self.verticalLayout = QtGui.QVBoxLayout(Form) | 23 | self.verticalLayout = QtGui.QVBoxLayout(Form) |
2160 | 25 | self.verticalLayout.setSpacing(0) | 24 | self.verticalLayout.setSpacing(0) |
2161 | 26 | self.verticalLayout.setMargin(0) | 25 | self.verticalLayout.setMargin(0) |
2162 | @@ -32,7 +31,7 @@ | |||
2163 | 32 | self.horizontalLayout_2.setMargin(3) | 31 | self.horizontalLayout_2.setMargin(3) |
2164 | 33 | self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2")) | 32 | self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2")) |
2165 | 34 | self.share_publish_button = GoToWebButton(self.frame_top) | 33 | self.share_publish_button = GoToWebButton(self.frame_top) |
2167 | 35 | sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) | 34 | sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed) |
2168 | 36 | sizePolicy.setHorizontalStretch(0) | 35 | sizePolicy.setHorizontalStretch(0) |
2169 | 37 | sizePolicy.setVerticalStretch(0) | 36 | sizePolicy.setVerticalStretch(0) |
2170 | 38 | sizePolicy.setHeightForWidth(self.share_publish_button.sizePolicy().hasHeightForWidth()) | 37 | sizePolicy.setHeightForWidth(self.share_publish_button.sizePolicy().hasHeightForWidth()) |
2171 | @@ -66,7 +65,7 @@ | |||
2172 | 66 | spacerItem1 = QtGui.QSpacerItem(53, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) | 65 | spacerItem1 = QtGui.QSpacerItem(53, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) |
2173 | 67 | self.horizontalLayout.addItem(spacerItem1) | 66 | self.horizontalLayout.addItem(spacerItem1) |
2174 | 68 | self.add_folder_button = AddFolderButton(self.frame_bottom) | 67 | self.add_folder_button = AddFolderButton(self.frame_bottom) |
2176 | 69 | sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) | 68 | sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed) |
2177 | 70 | sizePolicy.setHorizontalStretch(0) | 69 | sizePolicy.setHorizontalStretch(0) |
2178 | 71 | sizePolicy.setVerticalStretch(0) | 70 | sizePolicy.setVerticalStretch(0) |
2179 | 72 | sizePolicy.setHeightForWidth(self.add_folder_button.sizePolicy().hasHeightForWidth()) | 71 | sizePolicy.setHeightForWidth(self.add_folder_button.sizePolicy().hasHeightForWidth()) |
2180 | 73 | 72 | ||
2181 | === modified file 'ubuntuone/controlpanel/gui/qt/ui/images_rc.py' | |||
2182 | --- ubuntuone/controlpanel/gui/qt/ui/images_rc.py 2011-08-12 19:12:08 +0000 | |||
2183 | +++ ubuntuone/controlpanel/gui/qt/ui/images_rc.py 2011-08-25 19:40:18 +0000 | |||
2184 | @@ -2,7 +2,7 @@ | |||
2185 | 2 | 2 | ||
2186 | 3 | # Resource object code | 3 | # Resource object code |
2187 | 4 | # | 4 | # |
2189 | 5 | # Created: Fri Aug 12 15:07:18 2011 | 5 | # Created: Thu Aug 25 15:26:50 2011 |
2190 | 6 | # by: The Resource Compiler for PyQt (Qt v4.7.2) | 6 | # by: The Resource Compiler for PyQt (Qt v4.7.2) |
2191 | 7 | # | 7 | # |
2192 | 8 | # WARNING! All changes made in this file will be lost! | 8 | # WARNING! All changes made in this file will be lost! |
2193 | @@ -307,90 +307,84 @@ | |||
2194 | 307 | \xf8\xb9\x66\x02\x5d\x38\x49\x38\xe7\x8e\x81\x63\xe0\x88\x7f\x33\ | 307 | \xf8\xb9\x66\x02\x5d\x38\x49\x38\xe7\x8e\x81\x63\xe0\x88\x7f\x33\ |
2195 | 308 | \x0f\xac\x24\xad\x7e\x03\xdb\x11\x28\xad\xbd\x6a\x0e\xf8\x00\x00\ | 308 | \x0f\xac\x24\xad\x7e\x03\xdb\x11\x28\xad\xbd\x6a\x0e\xf8\x00\x00\ |
2196 | 309 | \x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ | 309 | \x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ |
2281 | 310 | \x00\x00\x05\x1d\ | 310 | \x00\x00\x02\x50\ |
2282 | 311 | \x89\ | 311 | \x89\ |
2283 | 312 | \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ | 312 | \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ |
2284 | 313 | \x00\x00\x20\x00\x00\x00\x20\x08\x06\x00\x00\x00\x73\x7a\x7a\xf4\ | 313 | \x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\ |
2285 | 314 | \x00\x00\x04\xe4\x49\x44\x41\x54\x78\xda\xbd\x97\xd9\x4f\xdc\x55\ | 314 | \x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\ |
2286 | 315 | \x14\xc7\xfd\x37\x7c\xb1\x16\xda\x29\x05\x5a\xa8\xec\x20\x52\x95\ | 315 | \x01\x00\x9a\x9c\x18\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\ |
2287 | 316 | \xae\x94\x62\x23\x89\x21\x46\x4d\x7c\x33\xbe\xa8\x2f\x8d\x7d\xe9\ | 316 | \x74\x77\x61\x72\x65\x00\x41\x64\x6f\x62\x65\x20\x49\x6d\x61\x67\ |
2288 | 317 | \x43\xe3\xd2\x5a\x6b\x95\x61\x93\xd2\x05\x81\xd6\x16\x0a\x96\x75\ | 317 | \x65\x52\x65\x61\x64\x79\x71\xc9\x65\x3c\x00\x00\x01\xdd\x49\x44\ |
2289 | 318 | \x98\x8d\x6d\xa6\x82\x0c\xdb\x0c\xfb\xb0\x15\x04\xa4\x44\x91\x52\ | 318 | \x41\x54\x78\xda\x94\x53\xbb\x6e\x13\x41\x14\x3d\x33\x3b\x5e\x7b\ |
2290 | 319 | \xa9\x9d\xb1\xc7\x73\x6e\x38\xbf\xfb\x63\x7e\x3f\x48\xe0\xa1\x93\ | 319 | \x63\x3b\x0f\x04\x29\x42\x91\x2d\x03\x55\x0a\xa4\xd4\x28\xe9\x23\ |
2291 | 320 | \x7c\x72\x96\x7b\xee\xf9\x7e\x73\x5b\xc8\xf0\x82\xf8\xa4\x9e\x8e\ | 320 | \x37\x94\xf9\x01\xc4\x27\x50\x52\xd2\x13\x41\xc3\x17\xa4\xa3\xa3\ |
2292 | 321 | \x44\x0a\x11\xfb\x73\xa2\x90\x34\xd5\xe2\xf6\xac\x32\xe7\xfc\xd9\ | 321 | \xa0\x41\xe9\x40\x02\x04\x54\xd9\x14\x11\x49\x94\x28\xb1\x1d\xef\ |
2293 | 322 | \xae\x59\xff\x97\x9e\x05\x38\xd7\x37\xaf\x0b\x9e\xe9\xc6\x2f\xdc\ | 322 | \x63\x66\x76\x86\x3b\xb3\x8e\xbd\x11\x44\x8a\xef\xea\xee\xce\xeb\ |
2294 | 323 | \x7f\xa8\x67\x36\xbd\x77\xb6\x7b\xd6\x4f\x5a\xa4\x29\xb4\xc9\x4d\ | 323 | \x9c\x3d\xf7\xcc\x8c\x78\xf9\xf1\xcb\xfa\x72\xb7\xbb\x77\xbf\xd3\ |
2295 | 324 | \x66\x89\x63\xee\xb4\x6b\x06\xde\x77\x3c\x80\x93\x36\x2f\xa4\x5b\ | 324 | \x8e\xe7\x5b\x11\xee\x12\x83\x3c\xc3\xd9\xd5\x28\x39\x1d\x0e\x7b\ |
2296 | 325 | \xd7\xf3\x56\xd3\x04\xa3\xf4\x32\xec\xe3\x9c\xeb\xcd\xeb\xf6\x4e\ | 325 | \x78\xfd\xf9\xd7\xc1\xd1\x95\xb2\xca\xd8\x99\xd2\x61\x1c\x56\x74\ |
2297 | 326 | \x21\xef\xb6\x4c\xc0\x99\xae\x39\xc8\x2c\x69\x9b\x13\x2f\x41\x4e\ | 326 | \x9a\x61\xcc\x60\xf1\x67\x24\x31\x4b\x08\xc6\xb0\x18\xb5\x62\x11\ |
2298 | 327 | \x3e\x75\x4e\xf8\xb3\x9a\xc6\x21\xc3\x36\x0e\x27\xcc\xa3\x1c\x35\ | 327 | \x70\x86\x81\xd4\x44\x51\x0f\x36\xfe\xda\x5b\x09\x98\x9f\xb5\x10\ |
2299 | 328 | \x04\x9c\x73\x4e\x6c\x32\xe3\xd5\x9c\x67\xb5\x4c\x02\x69\x92\xb6\ | 328 | \xb9\x92\xc8\x4b\x33\x99\x48\x8b\x12\xcf\xde\x7e\xf5\xed\x0f\x2f\ |
2300 | 329 | \x30\xf0\xc9\xaf\x53\x70\xd2\xe2\x85\xb4\xc6\x51\x38\x6e\x1a\x16\ | 329 | \x9e\x80\xd4\xde\x4a\xe2\xb0\x22\x97\x0a\xb2\x46\x50\x12\x40\xdb\ |
2301 | 330 | \xa4\x63\x4d\xf1\x94\x65\x04\xd2\xee\x76\x43\x98\xd1\x02\xa1\xd9\ | 330 | \x4a\x81\xf5\xe0\x29\x01\xd5\x8e\x3a\x9f\xc3\x8a\x42\x2b\xa8\xb2\ |
2302 | 331 | \x66\x38\x5e\xee\x82\x4c\xdb\x18\x9f\xe3\x9d\x11\xca\x05\x69\xa6\ | 331 | \x9c\x0c\x46\x21\x47\x2b\x6c\xf8\xf6\xf6\xee\xb7\xc9\x78\xbb\xc9\ |
2303 | 332 | \x11\xea\x31\xdc\xa3\xa8\x46\x68\x7d\xd6\x31\x0d\x8a\x81\x8f\x9d\ | 332 | \xf1\x7e\x67\xed\xc6\xcf\x1c\xd6\x13\x48\x33\x25\x68\x18\x06\xd1\ |
2304 | 333 | \x53\x70\xb4\x7e\x48\x18\x60\xb8\x7e\xbb\xb2\x07\x2a\xfa\x67\x60\ | 333 | \x14\xff\x9a\x16\x06\x30\xa4\xa0\xbe\xb6\x22\x50\x9a\xea\x04\xb4\ |
2305 | 334 | \xf9\x89\x4f\x50\x8e\x79\x66\x55\x2f\x9d\x33\x3c\xaf\xad\x79\xa7\ | 334 | \xa9\x98\xa3\xc0\xc2\x34\x2b\x05\xaf\x36\x57\xb0\xba\x34\x25\xbb\ |
2306 | 335 | \x69\x14\x8e\x35\x0c\x53\x8d\xc6\x46\x44\xfc\xc8\x31\x29\x0d\x7c\ | 335 | \x24\xc9\x76\x5c\x83\xe0\x1c\x0e\xcb\x25\xb1\x38\xa3\x24\x11\xb8\ |
2307 | 336 | \xd8\xe4\x15\x03\x87\x6b\x07\x38\x32\x42\x3c\xf0\x53\xee\x99\x81\ | 336 | \x54\xd6\x60\x79\x29\xf2\x24\xef\xbe\xf7\xd1\x2f\x2c\x39\x5e\x3d\ |
2308 | 337 | \x23\xb5\x83\x3c\xab\x81\xf7\x30\xb2\x96\xa0\xa6\x34\xf0\x9e\x7d\ | 337 | \x6a\xbc\xc6\xa5\xc7\x78\x05\xa5\xae\x3a\xe3\xda\xce\x33\x89\xde\ |
2309 | 338 | \x0c\x8e\xd4\x0d\x09\x52\xab\xfb\x45\x64\x36\xf8\xd0\x9c\x06\xd5\ | 338 | \xda\x02\x76\x7f\x0c\x70\x90\x59\x3c\xff\x74\xee\xc7\x3b\x0d\x8e\ |
2310 | 339 | \x3d\xae\x39\x47\x13\xeb\xcf\x50\x53\x1a\xc8\x6c\x18\x84\xc3\x35\ | 339 | \x37\x4f\xef\xd1\x79\xc9\x7d\x3f\x74\x0a\x08\xcb\x0b\xad\xfd\x7e\ |
2311 | 340 | \x03\xf0\xe6\x2f\x6e\x38\x84\x87\x9c\x13\xbe\x67\xa0\x07\x9f\xd3\ | 340 | \x4a\x32\xd2\x65\x46\xfd\xf5\x07\x0c\x3b\x8f\x17\x30\xdf\x0e\xc1\ |
2312 | 341 | \x2c\x83\xb5\x47\x90\x7a\xcf\x13\xd0\x77\x6b\x72\xd4\x94\x06\x32\ | 341 | \x49\x89\xcf\x50\x78\xf9\xd7\xeb\x1c\xc6\x61\x85\x7b\xb9\x90\x66\ |
2313 | 342 | \xea\x07\xe9\x12\xd2\x0f\xaf\x57\xf6\x11\x94\x0b\x56\xff\x03\x5d\ | 342 | \xea\xee\x71\x9a\xe3\xd1\x62\x80\xad\x87\x9d\x1b\x46\x26\xc3\x11\ |
2314 | 343 | \x76\x7e\x53\x0b\x3b\x2e\x08\x30\xaf\x13\xb5\xba\x97\x52\xec\x84\ | 343 | \x79\x65\x6b\x26\x12\x81\xab\x63\x90\x66\x08\x18\x47\xaa\x6b\x0e\ |
2315 | 344 | \x34\x7c\x7a\xda\xc1\xbb\xd5\x1a\x27\x6a\xfa\xa5\x81\x43\x55\x7d\ | 344 | \x53\x49\xfd\x42\xfd\xf7\x00\xcd\x89\xc0\x63\x2a\x0f\xb4\x4e\xf6\ |
2316 | 345 | \x90\x52\xd1\x0b\x6f\x54\xb9\xd7\xf0\x28\xf5\x23\x3f\x6c\x8b\x7b\ | 345 | \x93\x24\xde\x88\x57\x11\x77\xe7\xee\x74\x0f\x2e\xd2\x14\xfb\xc9\ |
2317 | 346 | \xc3\xf3\x90\x76\xb3\x83\x77\x11\x28\xec\x56\x72\xd4\x94\x06\x0e\ | 346 | \xa1\x53\x90\x08\x5b\x96\xbd\xdf\xc7\x27\x7b\x3f\x4f\x4e\xe3\x59\ |
2318 | 347 | \xde\xed\x83\xe4\x3b\xdd\x0c\x0e\xf4\x00\xf7\x96\x7c\xb0\x6d\x2a\ | 347 | \x2e\x13\xb7\x36\xa1\x1d\xef\xfd\x15\x60\x00\xe8\x15\x51\x25\x42\ |
2319 | 348 | \x87\xe6\x69\x0f\xc3\x3b\x39\x97\x06\x52\xca\x7b\x81\x79\xf5\xe7\ | 348 | \x1c\xe5\x09\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ |
2320 | 349 | \x2e\x46\xd4\x8b\x4f\x61\xdb\xfc\xed\x03\xde\xab\xb7\x5f\x1a\x48\ | 349 | \x00\x00\x02\x50\ |
2321 | 350 | \xbc\xd9\x09\x4c\xf2\xed\x6e\x85\xa4\x5b\x2e\x98\xff\x17\xb6\xc5\ | 350 | \x89\ |
2322 | 351 | \x9f\x28\xde\x3c\xbd\x44\x7b\xe4\x5e\x99\xa3\x01\x97\x34\x10\x5f\ | 351 | \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ |
2323 | 352 | \xda\x01\x04\x1d\x92\x68\x12\xc7\x5b\x9d\x30\xf3\x04\x74\x79\xfa\ | 352 | \x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\ |
2324 | 353 | \x6c\x73\xec\xd3\x7f\x41\xea\x1d\x17\xed\x5d\xdb\xa5\xe4\x8c\x34\ | 353 | \x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\ |
2325 | 354 | \x90\x50\xd6\x09\xb1\x3f\xb5\x03\x45\xce\xb9\x9e\x5c\x05\x3d\x34\ | 354 | \x01\x00\x9a\x9c\x18\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\ |
2326 | 355 | \x73\xaa\x1c\x85\x7e\xe3\x5d\x7a\x73\x8c\x34\x10\x57\xd2\x01\xd1\ | 355 | \x74\x77\x61\x72\x65\x00\x41\x64\x6f\x62\x65\x20\x49\x6d\x61\x67\ |
2327 | 356 | \x37\xee\x0b\x28\x67\xa8\xf6\xfe\x03\xba\xf0\xbc\x44\xde\xe5\x3c\ | 356 | \x65\x52\x65\x61\x64\x79\x71\xc9\x65\x3c\x00\x00\x01\xdd\x49\x44\ |
2328 | 357 | \xa6\x58\xb3\x4f\x9d\x4b\x03\xb1\xc5\xed\x40\x44\x5d\x73\x8a\xa8\ | 357 | \x41\x54\x78\xda\x94\x53\xbb\x6e\x13\x41\x14\x3d\x33\x3b\x5e\x7b\ |
2329 | 358 | \x66\x0c\xc5\x86\x1e\x6b\x39\x76\xdb\xa5\xb9\xc3\xb9\x6e\x2d\x7b\ | 358 | \x63\x3b\x0f\x04\x29\x42\x91\x2d\x03\x55\x0a\xa4\xd4\x28\xe9\x23\ |
2330 | 359 | \xdc\x97\x06\x0e\x14\xb5\x01\x11\x75\xd5\x01\x9c\x47\x5f\xbf\x2f\ | 359 | \x37\x94\xf9\x01\xc4\x27\x50\x52\xd2\x13\x41\xc3\x17\xa4\xa3\xa3\ |
2331 | 360 | \xa2\x79\x6a\x09\x3c\x2b\xa0\x21\xbd\xd8\x01\x47\xcb\xda\x21\x09\ | 360 | \xa0\x41\xe9\x40\x02\x04\x54\xd9\x14\x11\x49\x94\x28\xb1\x1d\xef\ |
2332 | 361 | \x9f\x52\x7d\x47\xe2\xe4\x1d\x0c\x6b\xf0\x8c\x34\xf0\xca\x55\x27\ | 361 | \x63\x66\x76\x86\x3b\xb3\x8e\xbd\x11\x44\x8a\xef\xea\xee\xce\xeb\ |
2333 | 362 | \xa8\x89\x28\x6c\x55\xf2\xd2\xfe\x39\xe8\x7d\x04\x1a\x9c\x8b\x3e\ | 362 | \x9c\x3d\xf7\xcc\x8c\x78\xf9\xf1\xcb\xfa\x72\xb7\xbb\x77\xbf\xd3\ |
2334 | 363 | \xf8\xa0\xc2\x05\xbb\xce\x57\xc3\x8b\xe7\xaa\xd6\xa8\x54\xf2\x98\ | 363 | \x8e\xe7\x5b\x11\xee\x12\x83\x3c\xc3\xd9\xd5\x28\x39\x1d\x0e\x7b\ |
2335 | 364 | \x5c\x2b\xc4\x5d\x73\xa8\x77\x71\xce\x51\x1a\x88\xbc\xd2\x06\x91\ | 364 | \x78\xfd\xf9\xd7\xc1\xd1\x95\xb2\xca\xd8\x99\xd2\x61\x1c\x56\x74\ |
2336 | 365 | \x57\x5a\x61\x5f\x41\xb3\x80\x6a\x82\xf2\x77\xf0\xbb\xc0\x30\x3e\ | 365 | \x9a\x61\xcc\x60\xf1\x67\x24\x31\x4b\x08\xc6\xb0\x18\xb5\x62\x11\ |
2337 | 366 | \xb9\x6b\x79\x6b\xe4\xf4\xcc\x42\x7c\x9e\x95\x77\x29\xec\xc7\x9d\ | 366 | \x70\x86\x81\xd4\x44\x51\x0f\x36\xfe\xda\x5b\x09\x98\x9f\xb5\x10\ |
2338 | 367 | \x08\xed\x96\x06\xf6\xff\xd8\x02\x44\x58\x9e\x5d\xc4\xf0\x7c\x3b\ | 367 | \xb9\x92\xc8\x4b\x33\x99\x48\x8b\x12\xcf\xde\x7e\xf5\xed\x0f\x2f\ |
2339 | 368 | \xd7\x82\x86\xb1\x45\x70\xe3\xb3\x77\x2e\x6f\x8d\xeb\x03\x0f\x71\ | 368 | \x9e\x80\xd4\xde\x4a\xe2\xb0\x22\x97\x0a\xb2\x46\x50\x12\x40\xdb\ |
2340 | 369 | \x4f\x33\x84\xe3\x0e\xde\xad\xd6\x92\x2f\x80\x8d\xd0\x1c\x1b\xec\ | 369 | \x4a\x81\xf5\xe0\x29\x01\xd5\x8e\x3a\x9f\xc3\x8a\x42\x2b\xa8\xb2\ |
2341 | 370 | \xcb\x6f\x86\x30\x8c\xa1\x01\x24\xe2\xbf\x5b\xcf\xc2\x0a\xbe\xc4\ | 370 | \x9c\x0c\x46\x21\x47\x2b\x6c\xf8\xf6\xf6\xee\xb7\xc9\x78\xbb\xc9\ |
2342 | 371 | \xd6\x0c\x0c\xac\x00\xed\xe3\xdd\x02\xce\x51\x53\x1a\x88\xc2\xe7\ | 371 | \xf1\x7e\x67\xed\xc6\xcf\x1c\xd6\x13\x48\x33\x25\x68\x18\x06\xd1\ |
2343 | 372 | \xd8\x6b\xb4\xc0\xde\x6c\x0b\x84\xe7\xda\x09\x1c\xb4\x52\x14\xbd\ | 372 | \x14\xff\x9a\x16\x06\x30\xa4\xa0\xbe\xb6\x22\x50\x9a\xea\x04\xb4\ |
2344 | 373 | \x30\x8c\x09\x45\xad\x50\x3f\xf6\x50\xfc\x8e\x1f\x5f\xc5\xe5\x9b\ | 373 | \xa9\x98\xa3\xc0\xc2\x34\x2b\x05\xaf\x36\x57\xb0\xba\x34\x25\xbb\ |
2345 | 374 | \x9b\x11\x66\xdb\x66\x96\xf8\x3e\x45\xde\x27\x88\xcc\xb5\x49\x03\ | 374 | \x24\xc9\x76\x5c\x83\xe0\x1c\x0e\xcb\x25\xb1\x38\xa3\x24\x11\xb8\ |
2346 | 375 | \xd1\x68\x20\x04\x9b\x7b\xbe\x37\x13\x22\x0f\x35\xda\xd4\x3d\xaa\ | 375 | \x54\xd6\x60\x79\x29\xf2\x24\xef\xbe\xf7\xd1\x2f\x2c\x39\x5e\x3d\ |
2347 | 376 | \x45\x4c\xbd\xe1\x84\xa2\xae\x07\xd0\x8a\xbf\xe9\x1e\xfb\x61\x43\ | 376 | \x6a\xbc\xc6\xa5\xc7\x78\x05\xa5\xae\x3a\xe3\xda\xce\x33\x89\xde\ |
2348 | 377 | \xea\xbc\x0b\x10\x9d\x8f\x82\x46\xab\xb8\xcb\xf7\x99\x03\x6a\x03\ | 377 | \xda\x02\x76\x7f\x0c\x70\x90\x59\x3c\xff\x74\xee\xc7\x3b\x0d\x8e\ |
2349 | 378 | \x31\x05\x4d\xb0\xfb\x3b\x93\x42\xc8\x0f\x16\x42\xd3\xe3\x68\xc0\ | 378 | \x37\x4f\xef\xd1\x79\xc9\x7d\x3f\x74\x0a\x08\xcb\x0b\xad\xfd\x7e\ |
2350 | 379 | \x05\x5c\x6f\x00\x8a\x34\xf2\xbc\xee\xbe\xa8\x5c\xab\xca\x00\x16\ | 379 | \x4a\x32\xd2\x65\x46\xfd\xf5\x07\x0c\x3b\x8f\x17\x30\xdf\x0e\xc1\ |
2351 | 380 | \xbb\xbe\xad\x87\x3d\x97\x1b\x15\x0c\x97\x4d\xdc\xa3\xc8\x35\x81\ | 380 | \x49\x89\xcf\x50\x78\xf9\xd7\xeb\x1c\xc6\x61\x85\x7b\xb9\x90\x66\ |
2352 | 381 | \x0b\x1a\x44\x5f\xd6\xf2\x4c\x75\x47\xce\x5c\x92\xbb\x79\x26\x46\ | 381 | \xea\xee\x71\x9a\xe3\xd1\x62\x80\xad\x87\x9d\x1b\x46\x26\xc3\x11\ |
2353 | 382 | \x6d\x20\x0e\x8b\x60\xfc\x56\x13\x14\xc0\xee\x4b\x26\x08\xba\x28\ | 382 | \x79\x65\x6b\x26\x12\x81\xab\x63\x90\x66\x08\x18\x47\xaa\x6b\x0e\ |
2354 | 383 | \xeb\x60\x12\xc3\x1e\x42\xf5\x66\x91\x73\xcd\x5d\xca\x0d\x18\x13\ | 383 | \x53\x49\xfd\x42\xfd\xf7\x00\xcd\x89\xc0\x63\x2a\x0f\xb4\x4e\xf6\ |
2355 | 384 | \x0a\x54\x3f\x05\xb1\xc6\x46\x9f\x01\x85\x5e\x3e\x5f\x03\xc1\x17\ | 384 | \x93\x24\xde\x88\x57\x11\x77\xe7\xee\x74\x0f\x2e\xd2\x14\xfb\xc9\ |
2356 | 385 | \xeb\x75\xa1\x33\x26\x48\x53\x8b\xbb\x0c\x7d\x35\x53\xdf\xd1\xdc\ | 385 | \xa1\x53\x90\x08\x5b\x96\xbd\xdf\xc7\x27\x7b\x3f\x4f\x4e\xe3\x59\ |
2357 | 386 | \x0f\x41\x33\xf1\x46\x8b\x8f\x0d\x14\x1a\x3e\x2f\xfd\x3d\x31\x0f\ | 386 | \x2e\x13\xb7\x36\xa1\x1d\xef\xfd\x15\x60\x00\xe8\x15\x51\x25\x42\ |
2358 | 387 | \xff\xa3\xe0\x53\xee\xbc\x50\x27\x78\xe9\xab\x6a\x06\x2f\xd5\x8a\ | 387 | \x1c\xe5\x09\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ |
2275 | 388 | \xc8\x67\x3b\xbe\xae\xe1\x9a\xa2\x44\xce\x68\x72\x51\xe3\x1e\xd2\ | ||
2276 | 389 | \x20\x2d\xd2\xe4\x3f\xcd\x22\xc8\x89\xe1\x0c\x9a\xc8\x36\xf9\x0f\ | ||
2277 | 390 | \xe2\xd3\xbc\x96\x67\x01\x8a\x0c\xf7\x38\xea\x91\x92\x6f\xe5\x99\ | ||
2278 | 391 | \x80\x68\x5b\xd7\x4b\xce\x31\xfb\x49\x8b\x34\x85\x36\x00\xb0\x89\ | ||
2279 | 392 | \xe7\xfd\xe7\x79\x04\x69\xff\x0f\xc3\x78\xed\x1a\xcc\x42\xc6\x50\ | ||
2280 | 393 | \x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\ | ||
2359 | 394 | \x00\x00\x01\x27\ | 388 | \x00\x00\x01\x27\ |
2360 | 395 | \x89\ | 389 | \x89\ |
2361 | 396 | \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ | 390 | \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ |
2362 | @@ -412,308 +406,329 @@ | |||
2363 | 412 | \x04\xc3\x06\xd0\xb4\xf6\x1c\xaa\xf8\x39\x94\x8f\x12\xe1\x00\x01\ | 406 | \x04\xc3\x06\xd0\xb4\xf6\x1c\xaa\xf8\x39\x94\x8f\x12\xe1\x00\x01\ |
2364 | 413 | \x06\x00\x00\x4e\x7e\x7b\x48\x93\x95\x27\x00\x00\x00\x00\x49\x45\ | 407 | \x06\x00\x00\x4e\x7e\x7b\x48\x93\x95\x27\x00\x00\x00\x00\x49\x45\ |
2365 | 414 | \x4e\x44\xae\x42\x60\x82\ | 408 | \x4e\x44\xae\x42\x60\x82\ |
2367 | 415 | \x00\x00\x12\xb1\ | 409 | \x00\x00\x14\x10\ |
2368 | 416 | \x51\ | 410 | \x51\ |
2369 | 417 | \x4d\x61\x69\x6e\x57\x69\x6e\x64\x6f\x77\x20\x7b\x0a\x20\x20\x20\ | 411 | \x4d\x61\x69\x6e\x57\x69\x6e\x64\x6f\x77\x20\x7b\x0a\x20\x20\x20\ |
2370 | 418 | \x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x2d\x63\x6f\x6c\x6f\ | 412 | \x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x2d\x63\x6f\x6c\x6f\ |
2371 | 419 | \x72\x3a\x20\x23\x64\x64\x34\x38\x31\x34\x3b\x0a\x7d\x0a\x0a\x51\ | 413 | \x72\x3a\x20\x23\x64\x64\x34\x38\x31\x34\x3b\x0a\x7d\x0a\x0a\x51\ |
2372 | 420 | \x57\x69\x64\x67\x65\x74\x20\x7b\x0a\x20\x20\x20\x20\x66\x6f\x6e\ | 414 | \x57\x69\x64\x67\x65\x74\x20\x7b\x0a\x20\x20\x20\x20\x66\x6f\x6e\ |
2373 | 421 | \x74\x2d\x66\x61\x6d\x69\x6c\x79\x3a\x20\x22\x55\x62\x75\x6e\x74\ | 415 | \x74\x2d\x66\x61\x6d\x69\x6c\x79\x3a\x20\x22\x55\x62\x75\x6e\x74\ |
2422 | 422 | \x75\x22\x3b\x0a\x7d\x0a\x0a\x51\x46\x72\x61\x6d\x65\x20\x7b\x0a\ | 416 | \x75\x22\x3b\x0a\x20\x20\x20\x20\x66\x6f\x6e\x74\x2d\x73\x69\x7a\ |
2423 | 423 | \x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x3a\x20\x6e\x6f\x6e\x65\ | 417 | \x65\x3a\x20\x31\x33\x70\x78\x3b\x0a\x20\x20\x20\x20\x63\x6f\x6c\ |
2424 | 424 | \x3b\x0a\x7d\x0a\x0a\x51\x46\x72\x61\x6d\x65\x23\x66\x72\x61\x6d\ | 418 | \x6f\x72\x3a\x20\x23\x33\x33\x33\x33\x33\x33\x3b\x0a\x7d\x0a\x0a\ |
2425 | 425 | \x65\x5f\x68\x65\x61\x64\x65\x72\x20\x7b\x0a\x20\x20\x20\x20\x62\ | 419 | \x51\x46\x72\x61\x6d\x65\x20\x7b\x0a\x20\x20\x20\x20\x62\x6f\x72\ |
2426 | 426 | \x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x20\x23\x66\x66\x66\x66\ | 420 | \x64\x65\x72\x3a\x20\x6e\x6f\x6e\x65\x3b\x0a\x7d\x0a\x0a\x51\x46\ |
2427 | 427 | \x66\x66\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x72\ | 421 | \x72\x61\x6d\x65\x23\x66\x72\x61\x6d\x65\x5f\x68\x65\x61\x64\x65\ |
2428 | 428 | \x61\x64\x69\x75\x73\x3a\x20\x35\x70\x78\x3b\x0a\x20\x20\x20\x20\ | 422 | \x72\x20\x7b\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\ |
2429 | 429 | \x62\x6f\x72\x64\x65\x72\x2d\x73\x74\x79\x6c\x65\x3a\x20\x73\x6f\ | 423 | \x6e\x64\x3a\x20\x23\x66\x66\x66\x66\x66\x66\x3b\x0a\x20\x20\x20\ |
2382 | 430 | \x6c\x69\x64\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\ | ||
2383 | 431 | \x63\x6f\x6c\x6f\x72\x3a\x20\x23\x39\x33\x39\x33\x38\x39\x3b\x0a\ | ||
2384 | 432 | \x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x77\x69\x64\x74\x68\ | ||
2385 | 433 | \x3a\x20\x31\x70\x78\x3b\x0a\x20\x20\x20\x20\x6d\x69\x6e\x2d\x68\ | ||
2386 | 434 | \x65\x69\x67\x68\x74\x3a\x20\x39\x30\x70\x78\x3b\x0a\x7d\x0a\x0a\ | ||
2387 | 435 | \x51\x46\x72\x61\x6d\x65\x23\x66\x72\x61\x6d\x65\x5f\x67\x72\x65\ | ||
2388 | 436 | \x65\x74\x69\x6e\x67\x20\x7b\x0a\x20\x20\x20\x20\x6d\x61\x72\x67\ | ||
2389 | 437 | \x69\x6e\x20\x30\x70\x78\x3b\x0a\x20\x20\x20\x20\x70\x61\x64\x64\ | ||
2390 | 438 | \x69\x6e\x67\x2d\x6c\x65\x66\x74\x3a\x20\x31\x35\x70\x78\x3b\x0a\ | ||
2391 | 439 | \x20\x20\x20\x20\x70\x61\x64\x64\x69\x6e\x67\x2d\x74\x6f\x70\x3a\ | ||
2392 | 440 | \x20\x31\x30\x70\x78\x3b\x0a\x20\x20\x20\x20\x70\x61\x64\x64\x69\ | ||
2393 | 441 | \x6e\x67\x2d\x72\x69\x67\x68\x74\x3a\x20\x31\x30\x70\x78\x3b\x0a\ | ||
2394 | 442 | \x20\x20\x20\x20\x70\x61\x64\x64\x69\x6e\x67\x2d\x62\x6f\x74\x74\ | ||
2395 | 443 | \x6f\x6d\x3a\x20\x31\x30\x70\x78\x3b\x0a\x7d\x0a\x0a\x51\x46\x72\ | ||
2396 | 444 | \x61\x6d\x65\x23\x66\x72\x61\x6d\x65\x5f\x73\x74\x61\x74\x75\x73\ | ||
2397 | 445 | \x2c\x0a\x51\x46\x72\x61\x6d\x65\x23\x66\x72\x61\x6d\x65\x5f\x73\ | ||
2398 | 446 | \x74\x6f\x72\x61\x67\x65\x20\x7b\x0a\x20\x20\x20\x20\x62\x6f\x72\ | ||
2399 | 447 | \x64\x65\x72\x2d\x73\x74\x79\x6c\x65\x3a\x20\x64\x6f\x74\x74\x65\ | ||
2400 | 448 | \x64\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x63\x6f\ | ||
2401 | 449 | \x6c\x6f\x72\x3a\x20\x23\x39\x33\x39\x33\x38\x39\x3b\x0a\x20\x20\ | ||
2402 | 450 | \x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x6c\x65\x66\x74\x2d\x77\x69\ | ||
2403 | 451 | \x64\x74\x68\x3a\x20\x31\x70\x78\x3b\x0a\x20\x20\x20\x20\x70\x61\ | ||
2404 | 452 | \x64\x64\x69\x6e\x67\x3a\x20\x31\x30\x70\x78\x3b\x0a\x20\x20\x20\ | ||
2405 | 453 | \x20\x6d\x69\x6e\x2d\x77\x69\x64\x74\x68\x3a\x20\x34\x30\x70\x78\ | ||
2406 | 454 | \x3b\x0a\x7d\x0a\x0a\x51\x46\x72\x61\x6d\x65\x23\x61\x63\x63\x6f\ | ||
2407 | 455 | \x75\x6e\x74\x5f\x73\x65\x70\x61\x72\x61\x74\x6f\x72\x20\x7b\x0a\ | ||
2408 | 456 | \x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x73\x74\x79\x6c\x65\ | ||
2409 | 457 | \x3a\x20\x64\x6f\x74\x74\x65\x64\x3b\x0a\x20\x20\x20\x20\x62\x6f\ | ||
2410 | 458 | \x72\x64\x65\x72\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x39\x33\x39\ | ||
2411 | 459 | \x33\x38\x39\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\ | ||
2412 | 460 | \x62\x6f\x74\x74\x6f\x6d\x2d\x77\x69\x64\x74\x68\x3a\x20\x31\x70\ | ||
2413 | 461 | \x78\x3b\x0a\x7d\x0a\x0a\x51\x50\x75\x73\x68\x42\x75\x74\x74\x6f\ | ||
2414 | 462 | \x6e\x5b\x65\x6e\x61\x62\x6c\x65\x64\x3d\x22\x74\x72\x75\x65\x22\ | ||
2415 | 463 | \x5d\x20\x7b\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\ | ||
2416 | 464 | \x6e\x64\x3a\x20\x71\x6c\x69\x6e\x65\x61\x72\x67\x72\x61\x64\x69\ | ||
2417 | 465 | \x65\x6e\x74\x28\x78\x31\x3a\x20\x30\x2c\x20\x79\x31\x3a\x20\x30\ | ||
2418 | 466 | \x2c\x20\x78\x32\x3a\x20\x30\x2c\x20\x79\x32\x3a\x20\x31\x2c\x0a\ | ||
2419 | 467 | \x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x6f\x70\x3a\x20\x30\x20\ | ||
2420 | 468 | \x23\x66\x65\x63\x66\x63\x32\x2c\x20\x73\x74\x6f\x70\x3a\x20\x31\ | ||
2421 | 469 | \x2e\x30\x20\x23\x65\x34\x34\x65\x31\x39\x29\x3b\x0a\x20\x20\x20\ | ||
2430 | 470 | \x20\x62\x6f\x72\x64\x65\x72\x2d\x72\x61\x64\x69\x75\x73\x3a\x20\ | 424 | \x20\x62\x6f\x72\x64\x65\x72\x2d\x72\x61\x64\x69\x75\x73\x3a\x20\ |
2431 | 471 | \x35\x70\x78\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\ | 425 | \x35\x70\x78\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\ |
2432 | 472 | \x73\x74\x79\x6c\x65\x3a\x20\x73\x6f\x6c\x69\x64\x3b\x0a\x20\x20\ | 426 | \x73\x74\x79\x6c\x65\x3a\x20\x73\x6f\x6c\x69\x64\x3b\x0a\x20\x20\ |
2441 | 473 | \x20\x20\x70\x61\x64\x64\x69\x6e\x67\x3a\x20\x36\x70\x78\x3b\x0a\ | 427 | \x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\ |
2442 | 474 | \x20\x20\x20\x20\x63\x6f\x6c\x6f\x72\x3a\x20\x77\x68\x69\x74\x65\ | 428 | \x23\x39\x33\x39\x33\x38\x39\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\ |
2443 | 475 | \x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x63\x6f\x6c\ | 429 | \x64\x65\x72\x2d\x77\x69\x64\x74\x68\x3a\x20\x31\x70\x78\x3b\x0a\ |
2444 | 476 | \x6f\x72\x3a\x20\x23\x39\x33\x39\x33\x38\x39\x3b\x0a\x20\x20\x20\ | 430 | \x20\x20\x20\x20\x6d\x69\x6e\x2d\x68\x65\x69\x67\x68\x74\x3a\x20\ |
2445 | 477 | \x20\x62\x6f\x72\x64\x65\x72\x2d\x77\x69\x64\x74\x68\x3a\x20\x31\ | 431 | \x39\x30\x70\x78\x3b\x0a\x7d\x0a\x0a\x51\x46\x72\x61\x6d\x65\x23\ |
2446 | 478 | \x70\x78\x3b\x0a\x20\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3a\x20\ | 432 | \x66\x72\x61\x6d\x65\x5f\x67\x72\x65\x65\x74\x69\x6e\x67\x20\x7b\ |
2447 | 479 | \x31\x34\x70\x78\x3b\x0a\x7d\x0a\x0a\x51\x50\x75\x73\x68\x42\x75\ | 433 | \x0a\x20\x20\x20\x20\x6d\x61\x72\x67\x69\x6e\x20\x30\x70\x78\x3b\ |
2448 | 480 | \x74\x74\x6f\x6e\x3a\x68\x6f\x76\x65\x72\x5b\x65\x6e\x61\x62\x6c\ | 434 | \x0a\x20\x20\x20\x20\x70\x61\x64\x64\x69\x6e\x67\x2d\x6c\x65\x66\ |
2449 | 435 | \x74\x3a\x20\x31\x35\x70\x78\x3b\x0a\x20\x20\x20\x20\x70\x61\x64\ | ||
2450 | 436 | \x64\x69\x6e\x67\x2d\x74\x6f\x70\x3a\x20\x31\x30\x70\x78\x3b\x0a\ | ||
2451 | 437 | \x20\x20\x20\x20\x70\x61\x64\x64\x69\x6e\x67\x2d\x72\x69\x67\x68\ | ||
2452 | 438 | \x74\x3a\x20\x31\x30\x70\x78\x3b\x0a\x20\x20\x20\x20\x70\x61\x64\ | ||
2453 | 439 | \x64\x69\x6e\x67\x2d\x62\x6f\x74\x74\x6f\x6d\x3a\x20\x31\x30\x70\ | ||
2454 | 440 | \x78\x3b\x0a\x7d\x0a\x0a\x51\x46\x72\x61\x6d\x65\x23\x66\x72\x61\ | ||
2455 | 441 | \x6d\x65\x5f\x73\x74\x61\x74\x75\x73\x2c\x0a\x51\x46\x72\x61\x6d\ | ||
2456 | 442 | \x65\x23\x66\x72\x61\x6d\x65\x5f\x73\x74\x6f\x72\x61\x67\x65\x20\ | ||
2457 | 443 | \x7b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x73\x74\x79\ | ||
2458 | 444 | \x6c\x65\x3a\x20\x64\x6f\x74\x74\x65\x64\x3b\x0a\x20\x20\x20\x20\ | ||
2459 | 445 | \x62\x6f\x72\x64\x65\x72\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x39\ | ||
2460 | 446 | \x33\x39\x33\x38\x39\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\ | ||
2461 | 447 | \x72\x2d\x6c\x65\x66\x74\x2d\x77\x69\x64\x74\x68\x3a\x20\x31\x70\ | ||
2462 | 448 | \x78\x3b\x0a\x20\x20\x20\x20\x70\x61\x64\x64\x69\x6e\x67\x3a\x20\ | ||
2463 | 449 | \x31\x30\x70\x78\x3b\x0a\x20\x20\x20\x20\x6d\x69\x6e\x2d\x77\x69\ | ||
2464 | 450 | \x64\x74\x68\x3a\x20\x34\x30\x70\x78\x3b\x0a\x7d\x0a\x0a\x51\x46\ | ||
2465 | 451 | \x72\x61\x6d\x65\x23\x61\x63\x63\x6f\x75\x6e\x74\x5f\x73\x65\x70\ | ||
2466 | 452 | \x61\x72\x61\x74\x6f\x72\x20\x7b\x0a\x20\x20\x20\x20\x62\x6f\x72\ | ||
2467 | 453 | \x64\x65\x72\x2d\x73\x74\x79\x6c\x65\x3a\x20\x64\x6f\x74\x74\x65\ | ||
2468 | 454 | \x64\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x63\x6f\ | ||
2469 | 455 | \x6c\x6f\x72\x3a\x20\x23\x39\x33\x39\x33\x38\x39\x3b\x0a\x20\x20\ | ||
2470 | 456 | \x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x62\x6f\x74\x74\x6f\x6d\x2d\ | ||
2471 | 457 | \x77\x69\x64\x74\x68\x3a\x20\x31\x70\x78\x3b\x0a\x7d\x0a\x0a\x51\ | ||
2472 | 458 | \x46\x72\x61\x6d\x65\x23\x66\x72\x6d\x5f\x62\x6f\x78\x20\x7b\x20\ | ||
2473 | 459 | \x2f\x2a\x54\x68\x65\x20\x4c\x6f\x61\x64\x69\x6e\x67\x20\x4f\x76\ | ||
2474 | 460 | \x65\x72\x6c\x61\x79\x20\x66\x72\x61\x6d\x65\x2e\x2a\x2f\x0a\x20\ | ||
2475 | 461 | \x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x20\x23\ | ||
2476 | 462 | \x66\x66\x66\x66\x66\x66\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\ | ||
2477 | 463 | \x65\x72\x2d\x72\x61\x64\x69\x75\x73\x3a\x20\x35\x70\x78\x3b\x0a\ | ||
2478 | 464 | \x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x73\x74\x79\x6c\x65\ | ||
2479 | 465 | \x3a\x20\x73\x6f\x6c\x69\x64\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\ | ||
2480 | 466 | \x64\x65\x72\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x39\x33\x39\x33\ | ||
2481 | 467 | \x38\x39\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x77\ | ||
2482 | 468 | \x69\x64\x74\x68\x3a\x20\x31\x70\x78\x3b\x0a\x20\x20\x20\x20\x63\ | ||
2483 | 469 | \x6f\x6c\x6f\x72\x3a\x20\x77\x68\x69\x74\x65\x3b\x0a\x20\x20\x20\ | ||
2484 | 470 | \x20\x6d\x69\x6e\x2d\x68\x65\x69\x67\x68\x74\x3a\x20\x31\x30\x30\ | ||
2485 | 471 | \x70\x78\x3b\x0a\x7d\x0a\x0a\x51\x46\x72\x61\x6d\x65\x23\x66\x72\ | ||
2486 | 472 | \x6d\x5f\x62\x6f\x78\x20\x3e\x20\x51\x4c\x61\x62\x65\x6c\x20\x7b\ | ||
2487 | 473 | \x0a\x20\x20\x20\x20\x66\x6f\x6e\x74\x2d\x73\x69\x7a\x65\x3a\x20\ | ||
2488 | 474 | \x32\x34\x70\x78\x3b\x0a\x7d\x0a\x0a\x51\x50\x75\x73\x68\x42\x75\ | ||
2489 | 475 | \x74\x74\x6f\x6e\x20\x7b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\ | ||
2490 | 476 | \x72\x2d\x72\x61\x64\x69\x75\x73\x3a\x20\x35\x70\x78\x3b\x0a\x20\ | ||
2491 | 477 | \x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x73\x74\x79\x6c\x65\x3a\ | ||
2492 | 478 | \x20\x73\x6f\x6c\x69\x64\x3b\x0a\x20\x20\x20\x20\x70\x61\x64\x64\ | ||
2493 | 479 | \x69\x6e\x67\x3a\x20\x36\x70\x78\x3b\x0a\x20\x20\x20\x20\x70\x61\ | ||
2494 | 480 | \x64\x64\x69\x6e\x67\x2d\x6c\x65\x66\x74\x3a\x20\x32\x30\x70\x78\ | ||
2495 | 481 | \x3b\x0a\x20\x20\x20\x20\x70\x61\x64\x64\x69\x6e\x67\x2d\x72\x69\ | ||
2496 | 482 | \x67\x68\x74\x3a\x20\x32\x30\x70\x78\x3b\x0a\x20\x20\x20\x20\x62\ | ||
2497 | 483 | \x6f\x72\x64\x65\x72\x2d\x77\x69\x64\x74\x68\x3a\x20\x31\x70\x78\ | ||
2498 | 484 | \x3b\x0a\x7d\x0a\x0a\x51\x50\x75\x73\x68\x42\x75\x74\x74\x6f\x6e\ | ||
2499 | 485 | \x5b\x65\x6e\x61\x62\x6c\x65\x64\x3d\x22\x74\x72\x75\x65\x22\x5d\ | ||
2500 | 486 | \x20\x7b\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\ | ||
2501 | 487 | \x64\x3a\x20\x71\x6c\x69\x6e\x65\x61\x72\x67\x72\x61\x64\x69\x65\ | ||
2502 | 488 | \x6e\x74\x28\x78\x31\x3a\x20\x30\x2c\x20\x79\x31\x3a\x20\x30\x2c\ | ||
2503 | 489 | \x20\x78\x32\x3a\x20\x30\x2c\x20\x79\x32\x3a\x20\x31\x2c\x0a\x20\ | ||
2504 | 490 | \x20\x20\x20\x20\x20\x20\x20\x73\x74\x6f\x70\x3a\x20\x30\x20\x23\ | ||
2505 | 491 | \x66\x65\x39\x65\x38\x34\x2c\x73\x74\x6f\x70\x3a\x20\x31\x2e\x30\ | ||
2506 | 492 | \x20\x23\x64\x64\x34\x38\x31\x34\x29\x3b\x0a\x20\x20\x20\x20\x63\ | ||
2507 | 493 | \x6f\x6c\x6f\x72\x3a\x20\x77\x68\x69\x74\x65\x3b\x0a\x20\x20\x20\ | ||
2508 | 494 | \x20\x62\x6f\x72\x64\x65\x72\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\ | ||
2509 | 495 | \x39\x39\x39\x39\x39\x39\x3b\x0a\x7d\x0a\x0a\x51\x50\x75\x73\x68\ | ||
2510 | 496 | \x42\x75\x74\x74\x6f\x6e\x3a\x68\x6f\x76\x65\x72\x5b\x65\x6e\x61\ | ||
2511 | 497 | \x62\x6c\x65\x64\x3d\x22\x74\x72\x75\x65\x22\x5d\x20\x7b\x0a\x20\ | ||
2512 | 498 | \x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x20\x71\ | ||
2513 | 499 | \x6c\x69\x6e\x65\x61\x72\x67\x72\x61\x64\x69\x65\x6e\x74\x28\x78\ | ||
2514 | 500 | \x31\x3a\x20\x30\x2c\x20\x79\x31\x3a\x20\x30\x2c\x20\x78\x32\x3a\ | ||
2515 | 501 | \x20\x30\x2c\x20\x79\x32\x3a\x20\x31\x2c\x0a\x20\x20\x20\x20\x20\ | ||
2516 | 502 | \x20\x20\x20\x73\x74\x6f\x70\x3a\x20\x30\x20\x23\x66\x66\x62\x31\ | ||
2517 | 503 | \x39\x63\x2c\x73\x74\x6f\x70\x3a\x20\x31\x2e\x30\x20\x23\x64\x64\ | ||
2518 | 504 | \x34\x38\x31\x34\x29\x3b\x0a\x20\x20\x20\x20\x63\x6f\x6c\x6f\x72\ | ||
2519 | 505 | \x3a\x20\x77\x68\x69\x74\x65\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\ | ||
2520 | 506 | \x64\x65\x72\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x39\x39\x39\x39\ | ||
2521 | 507 | \x39\x39\x3b\x0a\x7d\x0a\x0a\x51\x50\x75\x73\x68\x42\x75\x74\x74\ | ||
2522 | 508 | \x6f\x6e\x3a\x70\x72\x65\x73\x73\x65\x64\x5b\x65\x6e\x61\x62\x6c\ | ||
2523 | 481 | \x65\x64\x3d\x22\x74\x72\x75\x65\x22\x5d\x20\x7b\x0a\x20\x20\x20\ | 509 | \x65\x64\x3d\x22\x74\x72\x75\x65\x22\x5d\x20\x7b\x0a\x20\x20\x20\ |
2524 | 482 | \x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x20\x71\x6c\x69\ | 510 | \x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x20\x71\x6c\x69\ |
2525 | 483 | \x6e\x65\x61\x72\x67\x72\x61\x64\x69\x65\x6e\x74\x28\x78\x31\x3a\ | 511 | \x6e\x65\x61\x72\x67\x72\x61\x64\x69\x65\x6e\x74\x28\x78\x31\x3a\ |
2526 | 484 | \x20\x30\x2c\x20\x79\x31\x3a\x20\x30\x2c\x20\x78\x32\x3a\x20\x30\ | 512 | \x20\x30\x2c\x20\x79\x31\x3a\x20\x30\x2c\x20\x78\x32\x3a\x20\x30\ |
2527 | 485 | \x2c\x20\x79\x32\x3a\x20\x31\x2c\x0a\x20\x20\x20\x20\x20\x20\x20\ | 513 | \x2c\x20\x79\x32\x3a\x20\x31\x2c\x0a\x20\x20\x20\x20\x20\x20\x20\ |
2542 | 486 | \x20\x73\x74\x6f\x70\x3a\x20\x30\x20\x23\x66\x65\x64\x61\x64\x31\ | 514 | \x20\x73\x74\x6f\x70\x3a\x20\x30\x20\x23\x62\x39\x33\x66\x31\x34\ |
2543 | 487 | \x2c\x73\x74\x6f\x70\x3a\x20\x31\x2e\x30\x20\x23\x65\x34\x37\x61\ | 515 | \x2c\x73\x74\x6f\x70\x3a\x20\x31\x2e\x30\x20\x23\x64\x64\x34\x38\ |
2544 | 488 | \x35\x35\x29\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\ | 516 | \x31\x34\x29\x3b\x0a\x20\x20\x20\x20\x63\x6f\x6c\x6f\x72\x3a\x20\ |
2545 | 489 | \x72\x61\x64\x69\x75\x73\x3a\x20\x35\x70\x78\x3b\x0a\x20\x20\x20\ | 517 | \x77\x68\x69\x74\x65\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\ |
2546 | 490 | \x20\x62\x6f\x72\x64\x65\x72\x2d\x73\x74\x79\x6c\x65\x3a\x20\x73\ | 518 | \x72\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x39\x39\x39\x39\x39\x39\ |
2547 | 491 | \x6f\x6c\x69\x64\x3b\x0a\x20\x20\x20\x20\x70\x61\x64\x64\x69\x6e\ | 519 | \x3b\x0a\x7d\x0a\x0a\x51\x50\x75\x73\x68\x42\x75\x74\x74\x6f\x6e\ |
2548 | 492 | \x67\x3a\x20\x36\x70\x78\x3b\x0a\x20\x20\x20\x20\x63\x6f\x6c\x6f\ | 520 | \x5b\x73\x65\x63\x6f\x6e\x64\x61\x72\x79\x3d\x22\x74\x72\x75\x65\ |
2549 | 493 | \x72\x3a\x20\x77\x68\x69\x74\x65\x3b\x0a\x20\x20\x20\x20\x62\x6f\ | 521 | \x22\x5d\x20\x7b\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\ |
2550 | 494 | \x72\x64\x65\x72\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x39\x33\x39\ | 522 | \x75\x6e\x64\x3a\x20\x71\x6c\x69\x6e\x65\x61\x72\x67\x72\x61\x64\ |
2551 | 495 | \x33\x38\x39\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\ | 523 | \x69\x65\x6e\x74\x28\x78\x31\x3a\x20\x30\x2c\x20\x79\x31\x3a\x20\ |
2552 | 496 | \x77\x69\x64\x74\x68\x3a\x20\x31\x70\x78\x3b\x0a\x20\x20\x20\x20\ | 524 | \x30\x2c\x20\x78\x32\x3a\x20\x30\x2c\x20\x79\x32\x3a\x20\x31\x2c\ |
2553 | 497 | \x68\x65\x69\x67\x68\x74\x3a\x20\x31\x32\x70\x78\x3b\x0a\x7d\x0a\ | 525 | \x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x6f\x70\x3a\x20\x30\ |
2554 | 498 | \x0a\x51\x50\x75\x73\x68\x42\x75\x74\x74\x6f\x6e\x3a\x70\x72\x65\ | 526 | \x20\x23\x66\x66\x66\x66\x66\x66\x2c\x73\x74\x6f\x70\x3a\x20\x31\ |
2555 | 499 | \x73\x73\x65\x64\x5b\x65\x6e\x61\x62\x6c\x65\x64\x3d\x22\x74\x72\ | 527 | \x2e\x30\x20\x23\x65\x36\x65\x36\x65\x36\x29\x3b\x0a\x20\x20\x20\ |
2556 | 528 | \x20\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x33\x33\x33\x33\x33\x33\x3b\ | ||
2557 | 529 | \x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x63\x6f\x6c\x6f\ | ||
2558 | 530 | \x72\x3a\x20\x23\x39\x39\x39\x39\x39\x39\x3b\x0a\x7d\x0a\x0a\x51\ | ||
2559 | 531 | \x50\x75\x73\x68\x42\x75\x74\x74\x6f\x6e\x3a\x68\x6f\x76\x65\x72\ | ||
2560 | 532 | \x5b\x73\x65\x63\x6f\x6e\x64\x61\x72\x79\x3d\x22\x74\x72\x75\x65\ | ||
2561 | 533 | \x22\x5d\x20\x7b\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\ | ||
2562 | 534 | \x75\x6e\x64\x3a\x20\x71\x6c\x69\x6e\x65\x61\x72\x67\x72\x61\x64\ | ||
2563 | 535 | \x69\x65\x6e\x74\x28\x78\x31\x3a\x20\x30\x2c\x20\x79\x31\x3a\x20\ | ||
2564 | 536 | \x30\x2c\x20\x78\x32\x3a\x20\x30\x2c\x20\x79\x32\x3a\x20\x31\x2c\ | ||
2565 | 537 | \x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x6f\x70\x3a\x20\x30\ | ||
2566 | 538 | \x20\x23\x66\x66\x66\x66\x66\x66\x2c\x73\x74\x6f\x70\x3a\x20\x31\ | ||
2567 | 539 | \x2e\x30\x20\x23\x65\x64\x65\x64\x65\x64\x29\x3b\x0a\x20\x20\x20\ | ||
2568 | 540 | \x20\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x33\x33\x33\x33\x33\x33\x3b\ | ||
2569 | 541 | \x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x63\x6f\x6c\x6f\ | ||
2570 | 542 | \x72\x3a\x20\x23\x39\x39\x39\x39\x39\x39\x3b\x0a\x7d\x0a\x0a\x51\ | ||
2571 | 543 | \x50\x75\x73\x68\x42\x75\x74\x74\x6f\x6e\x3a\x70\x72\x65\x73\x73\ | ||
2572 | 544 | \x65\x64\x5b\x73\x65\x63\x6f\x6e\x64\x61\x72\x79\x3d\x22\x74\x72\ | ||
2573 | 500 | \x75\x65\x22\x5d\x20\x7b\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\ | 545 | \x75\x65\x22\x5d\x20\x7b\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\ |
2574 | 501 | \x72\x6f\x75\x6e\x64\x3a\x20\x71\x6c\x69\x6e\x65\x61\x72\x67\x72\ | 546 | \x72\x6f\x75\x6e\x64\x3a\x20\x71\x6c\x69\x6e\x65\x61\x72\x67\x72\ |
2575 | 502 | \x61\x64\x69\x65\x6e\x74\x28\x78\x31\x3a\x20\x30\x2c\x20\x79\x31\ | 547 | \x61\x64\x69\x65\x6e\x74\x28\x78\x31\x3a\x20\x30\x2c\x20\x79\x31\ |
2576 | 503 | \x3a\x20\x30\x2c\x20\x78\x32\x3a\x20\x30\x2c\x20\x79\x32\x3a\x20\ | 548 | \x3a\x20\x30\x2c\x20\x78\x32\x3a\x20\x30\x2c\x20\x79\x32\x3a\x20\ |
2577 | 504 | \x31\x2c\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x6f\x70\x3a\ | 549 | \x31\x2c\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x6f\x70\x3a\ |
2630 | 505 | \x20\x30\x20\x23\x65\x34\x34\x65\x31\x39\x2c\x73\x74\x6f\x70\x3a\ | 550 | \x20\x30\x20\x23\x64\x39\x64\x39\x64\x39\x2c\x73\x74\x6f\x70\x3a\ |
2631 | 506 | \x20\x31\x2e\x30\x20\x23\x66\x65\x63\x66\x63\x32\x29\x3b\x0a\x20\ | 551 | \x20\x31\x2e\x30\x20\x23\x66\x65\x66\x65\x66\x65\x29\x3b\x0a\x20\ |
2632 | 507 | \x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x72\x61\x64\x69\x75\x73\ | 552 | \x20\x20\x20\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x33\x33\x33\x33\x33\ |
2633 | 508 | \x3a\x20\x35\x70\x78\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\ | 553 | \x33\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x63\x6f\ |
2634 | 509 | \x72\x2d\x73\x74\x79\x6c\x65\x3a\x20\x73\x6f\x6c\x69\x64\x3b\x0a\ | 554 | \x6c\x6f\x72\x3a\x20\x23\x39\x39\x39\x39\x39\x39\x3b\x0a\x7d\x0a\ |
2635 | 510 | \x20\x20\x20\x20\x70\x61\x64\x64\x69\x6e\x67\x3a\x20\x36\x70\x78\ | 555 | \x0a\x51\x50\x75\x73\x68\x42\x75\x74\x74\x6f\x6e\x5b\x65\x6e\x61\ |
2636 | 511 | \x3b\x0a\x20\x20\x20\x20\x63\x6f\x6c\x6f\x72\x3a\x20\x77\x68\x69\ | 556 | \x62\x6c\x65\x64\x3d\x22\x66\x61\x6c\x73\x65\x22\x5d\x20\x7b\x0a\ |
2585 | 512 | \x74\x65\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x63\ | ||
2586 | 513 | \x6f\x6c\x6f\x72\x3a\x20\x23\x39\x33\x39\x33\x38\x39\x3b\x0a\x20\ | ||
2587 | 514 | \x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x77\x69\x64\x74\x68\x3a\ | ||
2588 | 515 | \x20\x31\x70\x78\x3b\x0a\x20\x20\x20\x20\x68\x65\x69\x67\x68\x74\ | ||
2589 | 516 | \x3a\x20\x31\x32\x70\x78\x3b\x0a\x7d\x0a\x0a\x51\x50\x75\x73\x68\ | ||
2590 | 517 | \x42\x75\x74\x74\x6f\x6e\x5b\x65\x6e\x61\x62\x6c\x65\x64\x3d\x22\ | ||
2591 | 518 | \x66\x61\x6c\x73\x65\x22\x5d\x20\x7b\x0a\x20\x20\x20\x20\x62\x61\ | ||
2592 | 519 | \x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x20\x71\x6c\x69\x6e\x65\x61\ | ||
2593 | 520 | \x72\x67\x72\x61\x64\x69\x65\x6e\x74\x28\x78\x31\x3a\x20\x30\x2c\ | ||
2594 | 521 | \x20\x79\x31\x3a\x20\x30\x2c\x20\x78\x32\x3a\x20\x30\x2c\x20\x79\ | ||
2595 | 522 | \x32\x3a\x20\x31\x2c\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\ | ||
2596 | 523 | \x6f\x70\x3a\x20\x30\x20\x23\x65\x61\x65\x61\x65\x61\x2c\x20\x73\ | ||
2597 | 524 | \x74\x6f\x70\x3a\x20\x31\x2e\x30\x20\x23\x63\x61\x63\x61\x63\x61\ | ||
2598 | 525 | \x29\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x72\x61\ | ||
2599 | 526 | \x64\x69\x75\x73\x3a\x20\x35\x70\x78\x3b\x0a\x20\x20\x20\x20\x62\ | ||
2600 | 527 | \x6f\x72\x64\x65\x72\x2d\x73\x74\x79\x6c\x65\x3a\x20\x73\x6f\x6c\ | ||
2601 | 528 | \x69\x64\x3b\x0a\x20\x20\x20\x20\x70\x61\x64\x64\x69\x6e\x67\x3a\ | ||
2602 | 529 | \x20\x36\x70\x78\x3b\x0a\x20\x20\x20\x20\x63\x6f\x6c\x6f\x72\x3a\ | ||
2603 | 530 | \x20\x23\x35\x39\x35\x39\x35\x39\x3b\x0a\x20\x20\x20\x20\x62\x6f\ | ||
2604 | 531 | \x72\x64\x65\x72\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x39\x33\x39\ | ||
2605 | 532 | \x33\x38\x39\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\ | ||
2606 | 533 | \x77\x69\x64\x74\x68\x3a\x20\x31\x70\x78\x3b\x0a\x20\x20\x20\x20\ | ||
2607 | 534 | \x68\x65\x69\x67\x68\x74\x3a\x20\x31\x32\x70\x78\x3b\x0a\x7d\x0a\ | ||
2608 | 535 | \x0a\x51\x50\x75\x73\x68\x42\x75\x74\x74\x6f\x6e\x23\x68\x65\x6c\ | ||
2609 | 536 | \x70\x5f\x62\x75\x74\x74\x6f\x6e\x20\x7b\x0a\x20\x20\x20\x20\x62\ | ||
2610 | 537 | \x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x20\x74\x72\x61\x6e\x73\ | ||
2611 | 538 | \x70\x61\x72\x65\x6e\x74\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\ | ||
2612 | 539 | \x65\x72\x3a\x20\x6e\x6f\x6e\x65\x3b\x0a\x20\x20\x20\x20\x63\x6f\ | ||
2613 | 540 | \x6c\x6f\x72\x3a\x20\x77\x68\x69\x74\x65\x3b\x0a\x20\x20\x20\x20\ | ||
2614 | 541 | \x68\x65\x69\x67\x68\x74\x3a\x20\x32\x30\x70\x78\x3b\x0a\x20\x20\ | ||
2615 | 542 | \x20\x20\x74\x65\x78\x74\x2d\x64\x65\x63\x6f\x72\x61\x74\x69\x6f\ | ||
2616 | 543 | \x6e\x3a\x20\x75\x6e\x64\x65\x72\x6c\x69\x6e\x65\x3b\x0a\x20\x20\ | ||
2617 | 544 | \x20\x20\x70\x61\x64\x64\x69\x6e\x67\x3a\x20\x30\x70\x78\x3b\x0a\ | ||
2618 | 545 | \x7d\x0a\x0a\x51\x50\x75\x73\x68\x42\x75\x74\x74\x6f\x6e\x23\x65\ | ||
2619 | 546 | \x78\x70\x6c\x6f\x72\x65\x5f\x66\x6f\x6c\x64\x65\x72\x5f\x62\x75\ | ||
2620 | 547 | \x74\x74\x6f\x6e\x20\x7b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\ | ||
2621 | 548 | \x72\x3a\x20\x6e\x6f\x6e\x65\x3b\x0a\x20\x20\x20\x20\x62\x61\x63\ | ||
2622 | 549 | \x6b\x67\x72\x6f\x75\x6e\x64\x3a\x20\x6e\x6f\x6e\x65\x3b\x0a\x20\ | ||
2623 | 550 | \x20\x20\x20\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x35\x39\x35\x39\x35\ | ||
2624 | 551 | \x39\x3b\x0a\x7d\x0a\x0a\x51\x50\x75\x73\x68\x42\x75\x74\x74\x6f\ | ||
2625 | 552 | \x6e\x23\x61\x64\x64\x5f\x66\x6f\x6c\x64\x65\x72\x5f\x62\x75\x74\ | ||
2626 | 553 | \x74\x6f\x6e\x20\x7b\x0a\x20\x20\x20\x20\x70\x61\x64\x64\x69\x6e\ | ||
2627 | 554 | \x67\x3a\x20\x35\x70\x78\x3b\x0a\x7d\x0a\x0a\x47\x6f\x54\x6f\x57\ | ||
2628 | 555 | \x65\x62\x42\x75\x74\x74\x6f\x6e\x23\x73\x68\x61\x72\x65\x5f\x70\ | ||
2629 | 556 | \x75\x62\x6c\x69\x73\x68\x5f\x62\x75\x74\x74\x6f\x6e\x20\x7b\x0a\ | ||
2637 | 557 | \x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x20\ | 557 | \x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x20\ |
2697 | 558 | \x74\x72\x61\x6e\x73\x70\x61\x72\x65\x6e\x74\x3b\x0a\x20\x20\x20\ | 558 | \x71\x6c\x69\x6e\x65\x61\x72\x67\x72\x61\x64\x69\x65\x6e\x74\x28\ |
2698 | 559 | \x20\x62\x6f\x72\x64\x65\x72\x3a\x20\x6e\x6f\x6e\x65\x3b\x0a\x20\ | 559 | \x78\x31\x3a\x20\x30\x2c\x20\x79\x31\x3a\x20\x30\x2c\x20\x78\x32\ |
2699 | 560 | \x20\x20\x20\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x64\x64\x34\x38\x31\ | 560 | \x3a\x20\x30\x2c\x20\x79\x32\x3a\x20\x31\x2c\x0a\x20\x20\x20\x20\ |
2700 | 561 | \x34\x3b\x0a\x20\x20\x20\x20\x74\x65\x78\x74\x2d\x64\x65\x63\x6f\ | 561 | \x20\x20\x20\x20\x73\x74\x6f\x70\x3a\x20\x30\x20\x23\x65\x61\x65\ |
2701 | 562 | \x72\x61\x74\x69\x6f\x6e\x3a\x20\x75\x6e\x64\x65\x72\x6c\x69\x6e\ | 562 | \x61\x65\x61\x2c\x20\x73\x74\x6f\x70\x3a\x20\x31\x2e\x30\x20\x23\ |
2702 | 563 | \x65\x3b\x0a\x7d\x0a\x0a\x51\x54\x61\x62\x42\x61\x72\x3a\x3a\x74\ | 563 | \x63\x61\x63\x61\x63\x61\x29\x3b\x0a\x20\x20\x20\x20\x63\x6f\x6c\ |
2703 | 564 | \x61\x62\x20\x7b\x0a\x20\x20\x20\x20\x68\x65\x69\x67\x68\x74\x3a\ | 564 | \x6f\x72\x3a\x20\x23\x35\x39\x35\x39\x35\x39\x3b\x0a\x20\x20\x20\ |
2704 | 565 | \x20\x31\x35\x70\x78\x3b\x0a\x20\x20\x20\x20\x63\x6f\x6c\x6f\x72\ | 565 | \x20\x62\x6f\x72\x64\x65\x72\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\ |
2705 | 566 | \x3a\x20\x23\x33\x33\x33\x33\x33\x33\x3b\x0a\x20\x20\x20\x20\x62\ | 566 | \x39\x33\x39\x33\x38\x39\x3b\x0a\x7d\x0a\x0a\x51\x50\x75\x73\x68\ |
2706 | 567 | \x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x2d\x63\x6f\x6c\x6f\x72\x3a\ | 567 | \x42\x75\x74\x74\x6f\x6e\x23\x68\x65\x6c\x70\x5f\x62\x75\x74\x74\ |
2707 | 568 | \x20\x23\x65\x34\x65\x30\x64\x64\x3b\x0a\x20\x20\x20\x20\x62\x6f\ | 568 | \x6f\x6e\x20\x7b\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\ |
2708 | 569 | \x72\x64\x65\x72\x2d\x74\x6f\x70\x2d\x6c\x65\x66\x74\x2d\x72\x61\ | 569 | \x75\x6e\x64\x3a\x20\x74\x72\x61\x6e\x73\x70\x61\x72\x65\x6e\x74\ |
2709 | 570 | \x64\x69\x75\x73\x3a\x20\x35\x70\x78\x3b\x0a\x20\x20\x20\x20\x62\ | 570 | \x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x3a\x20\x6e\x6f\ |
2710 | 571 | \x6f\x72\x64\x65\x72\x2d\x74\x6f\x70\x2d\x72\x69\x67\x68\x74\x2d\ | 571 | \x6e\x65\x3b\x0a\x20\x20\x20\x20\x63\x6f\x6c\x6f\x72\x3a\x20\x77\ |
2711 | 572 | \x72\x61\x64\x69\x75\x73\x3a\x20\x35\x70\x78\x3b\x0a\x20\x20\x20\ | 572 | \x68\x69\x74\x65\x3b\x0a\x20\x20\x20\x20\x74\x65\x78\x74\x2d\x64\ |
2712 | 573 | \x20\x62\x6f\x72\x64\x65\x72\x2d\x73\x74\x79\x6c\x65\x3a\x20\x73\ | 573 | \x65\x63\x6f\x72\x61\x74\x69\x6f\x6e\x3a\x20\x75\x6e\x64\x65\x72\ |
2713 | 574 | \x6f\x6c\x69\x64\x3b\x0a\x20\x20\x20\x20\x70\x61\x64\x64\x69\x6e\ | 574 | \x6c\x69\x6e\x65\x3b\x0a\x20\x20\x20\x20\x70\x61\x64\x64\x69\x6e\ |
2714 | 575 | \x67\x3a\x20\x31\x32\x70\x78\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\ | 575 | \x67\x3a\x20\x30\x70\x78\x3b\x0a\x7d\x0a\x0a\x51\x50\x75\x73\x68\ |
2715 | 576 | \x64\x65\x72\x2d\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\ | 576 | \x42\x75\x74\x74\x6f\x6e\x23\x65\x78\x70\x6c\x6f\x72\x65\x5f\x66\ |
2716 | 577 | \x39\x33\x39\x33\x38\x39\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\ | 577 | \x6f\x6c\x64\x65\x72\x5f\x62\x75\x74\x74\x6f\x6e\x20\x7b\x0a\x20\ |
2717 | 578 | \x65\x72\x2d\x72\x69\x67\x68\x74\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\ | 578 | \x20\x20\x20\x62\x6f\x72\x64\x65\x72\x3a\x20\x6e\x6f\x6e\x65\x3b\ |
2718 | 579 | \x23\x39\x33\x39\x33\x38\x39\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\ | 579 | \x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\ |
2719 | 580 | \x64\x65\x72\x2d\x6c\x65\x66\x74\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\ | 580 | \x20\x6e\x6f\x6e\x65\x3b\x0a\x20\x20\x20\x20\x63\x6f\x6c\x6f\x72\ |
2720 | 581 | \x77\x68\x69\x74\x65\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\ | 581 | \x3a\x20\x23\x35\x39\x35\x39\x35\x39\x3b\x0a\x20\x20\x20\x20\x70\ |
2721 | 582 | \x72\x2d\x62\x6f\x74\x74\x6f\x6d\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\ | 582 | \x61\x64\x64\x69\x6e\x67\x2d\x6c\x65\x66\x74\x3a\x20\x31\x30\x70\ |
2722 | 583 | \x23\x39\x33\x39\x33\x38\x39\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\ | 583 | \x78\x3b\x0a\x20\x20\x20\x20\x70\x61\x64\x64\x69\x6e\x67\x2d\x72\ |
2723 | 584 | \x64\x65\x72\x2d\x77\x69\x64\x74\x68\x3a\x20\x31\x70\x78\x3b\x0a\ | 584 | \x69\x67\x68\x74\x3a\x20\x31\x30\x70\x78\x3b\x0a\x7d\x0a\x0a\x51\ |
2724 | 585 | \x7d\x0a\x0a\x51\x54\x61\x62\x42\x61\x72\x3a\x3a\x74\x61\x62\x3a\ | 585 | \x50\x75\x73\x68\x42\x75\x74\x74\x6f\x6e\x23\x74\x77\x69\x74\x74\ |
2725 | 586 | \x73\x65\x6c\x65\x63\x74\x65\x64\x20\x7b\x0a\x20\x20\x20\x20\x62\ | 586 | \x65\x72\x5f\x62\x75\x74\x74\x6f\x6e\x2c\x0a\x51\x50\x75\x73\x68\ |
2726 | 587 | \x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x2d\x63\x6f\x6c\x6f\x72\x3a\ | 587 | \x42\x75\x74\x74\x6f\x6e\x23\x66\x61\x63\x65\x62\x6f\x6f\x6b\x5f\ |
2727 | 588 | \x20\x77\x68\x69\x74\x65\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\ | 588 | \x62\x75\x74\x74\x6f\x6e\x20\x7b\x0a\x20\x20\x20\x20\x62\x6f\x72\ |
2728 | 589 | \x65\x72\x2d\x74\x6f\x70\x2d\x6c\x65\x66\x74\x2d\x72\x61\x64\x69\ | 589 | \x64\x65\x72\x3a\x20\x6e\x6f\x6e\x65\x3b\x0a\x7d\x0a\x0a\x47\x6f\ |
2729 | 590 | \x75\x73\x3a\x20\x35\x70\x78\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\ | 590 | \x54\x6f\x57\x65\x62\x42\x75\x74\x74\x6f\x6e\x23\x73\x68\x61\x72\ |
2730 | 591 | \x64\x65\x72\x2d\x74\x6f\x70\x2d\x72\x69\x67\x68\x74\x2d\x72\x61\ | 591 | \x65\x5f\x70\x75\x62\x6c\x69\x73\x68\x5f\x62\x75\x74\x74\x6f\x6e\ |
2731 | 592 | \x64\x69\x75\x73\x3a\x20\x35\x70\x78\x3b\x0a\x20\x20\x20\x20\x62\ | 592 | \x20\x7b\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\ |
2732 | 593 | \x6f\x72\x64\x65\x72\x2d\x73\x74\x79\x6c\x65\x3a\x20\x73\x6f\x6c\ | 593 | \x64\x3a\x20\x74\x72\x61\x6e\x73\x70\x61\x72\x65\x6e\x74\x3b\x0a\ |
2733 | 594 | \x69\x64\x3b\x0a\x20\x20\x20\x20\x70\x61\x64\x64\x69\x6e\x67\x3a\ | 594 | \x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x3a\x20\x6e\x6f\x6e\x65\ |
2734 | 595 | \x20\x31\x32\x70\x78\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\ | 595 | \x3b\x0a\x20\x20\x20\x20\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x64\x64\ |
2735 | 596 | \x72\x2d\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x39\x33\ | 596 | \x34\x38\x31\x34\x3b\x0a\x20\x20\x20\x20\x74\x65\x78\x74\x2d\x64\ |
2736 | 597 | \x39\x33\x38\x39\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\ | 597 | \x65\x63\x6f\x72\x61\x74\x69\x6f\x6e\x3a\x20\x75\x6e\x64\x65\x72\ |
2737 | 598 | \x2d\x72\x69\x67\x68\x74\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x39\ | 598 | \x6c\x69\x6e\x65\x3b\x0a\x7d\x0a\x0a\x51\x54\x61\x62\x42\x61\x72\ |
2738 | 599 | \x33\x39\x33\x38\x39\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\ | 599 | \x3a\x3a\x74\x61\x62\x20\x7b\x0a\x20\x20\x20\x20\x68\x65\x69\x67\ |
2739 | 600 | \x72\x2d\x6c\x65\x66\x74\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x77\x68\ | 600 | \x68\x74\x3a\x20\x31\x35\x70\x78\x3b\x0a\x20\x20\x20\x20\x63\x6f\ |
2740 | 601 | \x69\x74\x65\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\ | 601 | \x6c\x6f\x72\x3a\x20\x23\x33\x33\x33\x33\x33\x33\x3b\x0a\x20\x20\ |
2741 | 602 | \x62\x6f\x74\x74\x6f\x6d\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x77\x68\ | 602 | \x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x2d\x63\x6f\x6c\ |
2742 | 603 | \x69\x74\x65\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\ | 603 | \x6f\x72\x3a\x20\x23\x65\x34\x65\x30\x64\x64\x3b\x0a\x20\x20\x20\ |
2743 | 604 | \x77\x69\x64\x74\x68\x3a\x20\x31\x70\x78\x3b\x0a\x7d\x0a\x0a\x51\ | 604 | \x20\x62\x6f\x72\x64\x65\x72\x2d\x74\x6f\x70\x2d\x6c\x65\x66\x74\ |
2744 | 605 | \x54\x61\x62\x42\x61\x72\x3a\x3a\x74\x61\x62\x3a\x66\x69\x72\x73\ | 605 | \x2d\x72\x61\x64\x69\x75\x73\x3a\x20\x35\x70\x78\x3b\x0a\x20\x20\ |
2745 | 606 | \x74\x3a\x21\x73\x65\x6c\x65\x63\x74\x65\x64\x20\x7b\x0a\x20\x20\ | 606 | \x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x74\x6f\x70\x2d\x72\x69\x67\ |
2746 | 607 | \x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x6c\x65\x66\x74\x2d\x63\x6f\ | 607 | \x68\x74\x2d\x72\x61\x64\x69\x75\x73\x3a\x20\x35\x70\x78\x3b\x0a\ |
2747 | 608 | \x6c\x6f\x72\x3a\x20\x23\x39\x33\x39\x33\x38\x39\x3b\x0a\x20\x20\ | 608 | \x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x73\x74\x79\x6c\x65\ |
2748 | 609 | \x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x6c\x65\x66\x74\x2d\x63\x6f\ | 609 | \x3a\x20\x73\x6f\x6c\x69\x64\x3b\x0a\x20\x20\x20\x20\x70\x61\x64\ |
2749 | 610 | \x6c\x6f\x72\x3a\x20\x23\x39\x33\x39\x33\x38\x39\x3b\x0a\x7d\x0a\ | 610 | \x64\x69\x6e\x67\x3a\x20\x31\x32\x70\x78\x3b\x0a\x20\x20\x20\x20\ |
2750 | 611 | \x0a\x51\x54\x61\x62\x42\x61\x72\x3a\x3a\x74\x61\x62\x3a\x66\x69\ | 611 | \x62\x6f\x72\x64\x65\x72\x2d\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\ |
2751 | 612 | \x72\x73\x74\x3a\x73\x65\x6c\x65\x63\x74\x65\x64\x20\x7b\x0a\x20\ | 612 | \x3a\x20\x23\x39\x33\x39\x33\x38\x39\x3b\x0a\x20\x20\x20\x20\x62\ |
2752 | 613 | \x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x6c\x65\x66\x74\x2d\x63\ | 613 | \x6f\x72\x64\x65\x72\x2d\x72\x69\x67\x68\x74\x2d\x63\x6f\x6c\x6f\ |
2753 | 614 | \x6f\x6c\x6f\x72\x3a\x20\x23\x39\x33\x39\x33\x38\x39\x3b\x0a\x7d\ | 614 | \x72\x3a\x20\x23\x39\x33\x39\x33\x38\x39\x3b\x0a\x20\x20\x20\x20\ |
2754 | 615 | \x0a\x0a\x51\x54\x61\x62\x42\x61\x72\x3a\x3a\x74\x61\x62\x3a\x6d\ | 615 | \x62\x6f\x72\x64\x65\x72\x2d\x6c\x65\x66\x74\x2d\x63\x6f\x6c\x6f\ |
2755 | 616 | \x69\x64\x64\x6c\x65\x3a\x21\x73\x65\x6c\x65\x63\x74\x65\x64\x20\ | 616 | \x72\x3a\x20\x77\x68\x69\x74\x65\x3b\x0a\x20\x20\x20\x20\x62\x6f\ |
2756 | 617 | \x72\x64\x65\x72\x2d\x62\x6f\x74\x74\x6f\x6d\x2d\x63\x6f\x6c\x6f\ | ||
2757 | 618 | \x72\x3a\x20\x23\x39\x33\x39\x33\x38\x39\x3b\x0a\x20\x20\x20\x20\ | ||
2758 | 619 | \x62\x6f\x72\x64\x65\x72\x2d\x77\x69\x64\x74\x68\x3a\x20\x31\x70\ | ||
2759 | 620 | \x78\x3b\x0a\x7d\x0a\x0a\x51\x54\x61\x62\x42\x61\x72\x3a\x3a\x74\ | ||
2760 | 621 | \x61\x62\x3a\x73\x65\x6c\x65\x63\x74\x65\x64\x20\x7b\x0a\x20\x20\ | ||
2761 | 622 | \x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x2d\x63\x6f\x6c\ | ||
2762 | 623 | \x6f\x72\x3a\x20\x77\x68\x69\x74\x65\x3b\x0a\x20\x20\x20\x20\x62\ | ||
2763 | 624 | \x6f\x72\x64\x65\x72\x2d\x74\x6f\x70\x2d\x6c\x65\x66\x74\x2d\x72\ | ||
2764 | 625 | \x61\x64\x69\x75\x73\x3a\x20\x35\x70\x78\x3b\x0a\x20\x20\x20\x20\ | ||
2765 | 626 | \x62\x6f\x72\x64\x65\x72\x2d\x74\x6f\x70\x2d\x72\x69\x67\x68\x74\ | ||
2766 | 627 | \x2d\x72\x61\x64\x69\x75\x73\x3a\x20\x35\x70\x78\x3b\x0a\x20\x20\ | ||
2767 | 628 | \x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x73\x74\x79\x6c\x65\x3a\x20\ | ||
2768 | 629 | \x73\x6f\x6c\x69\x64\x3b\x0a\x20\x20\x20\x20\x70\x61\x64\x64\x69\ | ||
2769 | 630 | \x6e\x67\x3a\x20\x31\x32\x70\x78\x3b\x0a\x20\x20\x20\x20\x62\x6f\ | ||
2770 | 631 | \x72\x64\x65\x72\x2d\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\ | ||
2771 | 632 | \x23\x39\x33\x39\x33\x38\x39\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\ | ||
2772 | 633 | \x64\x65\x72\x2d\x72\x69\x67\x68\x74\x2d\x63\x6f\x6c\x6f\x72\x3a\ | ||
2773 | 634 | \x20\x23\x39\x33\x39\x33\x38\x39\x3b\x0a\x20\x20\x20\x20\x62\x6f\ | ||
2774 | 635 | \x72\x64\x65\x72\x2d\x6c\x65\x66\x74\x2d\x63\x6f\x6c\x6f\x72\x3a\ | ||
2775 | 636 | \x20\x77\x68\x69\x74\x65\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\ | ||
2776 | 637 | \x65\x72\x2d\x62\x6f\x74\x74\x6f\x6d\x2d\x63\x6f\x6c\x6f\x72\x3a\ | ||
2777 | 638 | \x20\x77\x68\x69\x74\x65\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\ | ||
2778 | 639 | \x65\x72\x2d\x77\x69\x64\x74\x68\x3a\x20\x31\x70\x78\x3b\x0a\x7d\ | ||
2779 | 640 | \x0a\x0a\x51\x54\x61\x62\x42\x61\x72\x3a\x3a\x74\x61\x62\x3a\x66\ | ||
2780 | 641 | \x69\x72\x73\x74\x3a\x21\x73\x65\x6c\x65\x63\x74\x65\x64\x20\x7b\ | ||
2781 | 642 | \x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x6c\x65\x66\x74\ | ||
2782 | 643 | \x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x39\x33\x39\x33\x38\x39\x3b\ | ||
2783 | 644 | \x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x6c\x65\x66\x74\ | ||
2784 | 645 | \x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x39\x33\x39\x33\x38\x39\x3b\ | ||
2785 | 646 | \x0a\x7d\x0a\x0a\x51\x54\x61\x62\x42\x61\x72\x3a\x3a\x74\x61\x62\ | ||
2786 | 647 | \x3a\x66\x69\x72\x73\x74\x3a\x73\x65\x6c\x65\x63\x74\x65\x64\x20\ | ||
2787 | 617 | \x7b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x6c\x65\x66\ | 648 | \x7b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x6c\x65\x66\ |
2789 | 618 | \x74\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x65\x34\x65\x30\x64\x64\ | 649 | \x74\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x39\x33\x39\x33\x38\x39\ |
2790 | 619 | \x3b\x0a\x7d\x0a\x0a\x51\x54\x61\x62\x42\x61\x72\x3a\x3a\x74\x61\ | 650 | \x3b\x0a\x7d\x0a\x0a\x51\x54\x61\x62\x42\x61\x72\x3a\x3a\x74\x61\ |
2808 | 620 | \x62\x3a\x68\x6f\x76\x65\x72\x20\x7b\x0a\x20\x20\x20\x20\x62\x61\ | 651 | \x62\x3a\x6d\x69\x64\x64\x6c\x65\x3a\x21\x73\x65\x6c\x65\x63\x74\ |
2809 | 621 | \x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x20\x71\x6c\x69\x6e\x65\x61\ | 652 | \x65\x64\x20\x7b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\ |
2810 | 622 | \x72\x67\x72\x61\x64\x69\x65\x6e\x74\x28\x78\x31\x3a\x20\x30\x2c\ | 653 | \x6c\x65\x66\x74\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x65\x34\x65\ |
2811 | 623 | \x20\x79\x31\x3a\x20\x30\x2c\x20\x78\x32\x3a\x20\x30\x2c\x20\x79\ | 654 | \x30\x64\x64\x3b\x0a\x7d\x0a\x0a\x51\x54\x61\x62\x42\x61\x72\x3a\ |
2812 | 624 | \x32\x3a\x20\x31\x2c\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\ | 655 | \x3a\x74\x61\x62\x3a\x68\x6f\x76\x65\x72\x20\x7b\x0a\x20\x20\x20\ |
2813 | 625 | \x6f\x70\x3a\x20\x30\x20\x23\x66\x61\x66\x61\x66\x61\x2c\x20\x73\ | 656 | \x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x20\x23\x66\x36\ |
2814 | 626 | \x74\x6f\x70\x3a\x20\x30\x2e\x34\x20\x23\x66\x34\x66\x34\x66\x34\ | 657 | \x66\x36\x66\x36\x3b\x0a\x20\x20\x20\x20\x74\x65\x78\x74\x2d\x64\ |
2815 | 627 | \x2c\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x74\x6f\x70\x3a\x20\ | 658 | \x65\x63\x6f\x72\x61\x74\x69\x6f\x6e\x3a\x20\x75\x6e\x64\x65\x72\ |
2816 | 628 | \x30\x2e\x35\x20\x23\x65\x37\x65\x37\x65\x37\x2c\x20\x73\x74\x6f\ | 659 | \x6c\x69\x6e\x65\x3b\x0a\x7d\x0a\x0a\x51\x54\x61\x62\x42\x61\x72\ |
2817 | 629 | \x70\x3a\x20\x31\x2e\x30\x20\x23\x66\x61\x66\x61\x66\x61\x29\x3b\ | 660 | \x3a\x3a\x74\x61\x62\x3a\x6c\x61\x73\x74\x3a\x21\x73\x65\x6c\x65\ |
2818 | 630 | \x0a\x20\x20\x20\x20\x74\x65\x78\x74\x2d\x64\x65\x63\x6f\x72\x61\ | 661 | \x63\x74\x65\x64\x20\x7b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\ |
2819 | 631 | \x74\x69\x6f\x6e\x3a\x20\x75\x6e\x64\x65\x72\x6c\x69\x6e\x65\x3b\ | 662 | \x72\x2d\x6c\x65\x66\x74\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x65\ |
2820 | 632 | \x0a\x7d\x0a\x0a\x51\x54\x61\x62\x42\x61\x72\x3a\x3a\x74\x61\x62\ | 663 | \x34\x65\x30\x64\x64\x3b\x0a\x7d\x0a\x0a\x51\x54\x61\x62\x57\x69\ |
2821 | 633 | \x3a\x6c\x61\x73\x74\x3a\x21\x73\x65\x6c\x65\x63\x74\x65\x64\x20\ | 664 | \x64\x67\x65\x74\x20\x7b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\ |
2822 | 634 | \x7b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x6c\x65\x66\ | 665 | \x72\x2d\x62\x6f\x74\x74\x6f\x6d\x2d\x6c\x65\x66\x74\x2d\x72\x61\ |
2823 | 635 | \x74\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x65\x34\x65\x30\x64\x64\ | 666 | \x64\x69\x75\x73\x3a\x20\x35\x70\x78\x3b\x0a\x20\x20\x20\x20\x62\ |
2824 | 636 | \x3b\x0a\x7d\x0a\x0a\x51\x54\x61\x62\x57\x69\x64\x67\x65\x74\x20\ | 667 | \x6f\x72\x64\x65\x72\x2d\x62\x6f\x74\x74\x6f\x6d\x2d\x72\x69\x67\ |
2825 | 668 | \x68\x74\x2d\x72\x61\x64\x69\x75\x73\x3a\x20\x35\x70\x78\x3b\x0a\ | ||
2826 | 669 | \x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x73\x74\x79\x6c\x65\ | ||
2827 | 670 | \x3a\x20\x73\x6f\x6c\x69\x64\x3b\x0a\x20\x20\x20\x20\x70\x61\x64\ | ||
2828 | 671 | \x64\x69\x6e\x67\x3a\x20\x31\x30\x70\x78\x3b\x0a\x7d\x0a\x0a\x51\ | ||
2829 | 672 | \x54\x61\x62\x57\x69\x64\x67\x65\x74\x3a\x3a\x70\x61\x6e\x65\x20\ | ||
2830 | 637 | \x7b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x62\x6f\x74\ | 673 | \x7b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x62\x6f\x74\ |
2831 | 638 | \x74\x6f\x6d\x2d\x6c\x65\x66\x74\x2d\x72\x61\x64\x69\x75\x73\x3a\ | 674 | \x74\x6f\x6d\x2d\x6c\x65\x66\x74\x2d\x72\x61\x64\x69\x75\x73\x3a\ |
2832 | 639 | \x20\x35\x70\x78\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\ | 675 | \x20\x35\x70\x78\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\ |
2833 | 640 | \x2d\x62\x6f\x74\x74\x6f\x6d\x2d\x72\x69\x67\x68\x74\x2d\x72\x61\ | 676 | \x2d\x62\x6f\x74\x74\x6f\x6d\x2d\x72\x69\x67\x68\x74\x2d\x72\x61\ |
2834 | 641 | \x64\x69\x75\x73\x3a\x20\x35\x70\x78\x3b\x0a\x20\x20\x20\x20\x62\ | 677 | \x64\x69\x75\x73\x3a\x20\x35\x70\x78\x3b\x0a\x20\x20\x20\x20\x62\ |
2910 | 642 | \x6f\x72\x64\x65\x72\x2d\x73\x74\x79\x6c\x65\x3a\x20\x73\x6f\x6c\ | 678 | \x6f\x72\x64\x65\x72\x2d\x74\x6f\x70\x2d\x72\x69\x67\x68\x74\x2d\ |
2911 | 643 | \x69\x64\x3b\x0a\x20\x20\x20\x20\x70\x61\x64\x64\x69\x6e\x67\x3a\ | 679 | \x72\x61\x64\x69\x75\x73\x3a\x20\x35\x70\x78\x3b\x0a\x20\x20\x20\ |
2912 | 644 | \x20\x31\x30\x70\x78\x3b\x0a\x7d\x0a\x0a\x51\x54\x61\x62\x57\x69\ | 680 | \x20\x62\x6f\x72\x64\x65\x72\x2d\x73\x74\x79\x6c\x65\x3a\x20\x73\ |
2913 | 645 | \x64\x67\x65\x74\x3a\x3a\x70\x61\x6e\x65\x20\x7b\x0a\x20\x20\x20\ | 681 | \x6f\x6c\x69\x64\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\ |
2914 | 646 | \x20\x62\x6f\x72\x64\x65\x72\x2d\x62\x6f\x74\x74\x6f\x6d\x2d\x6c\ | 682 | \x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x39\x33\x39\x33\x38\x39\x3b\ |
2915 | 647 | \x65\x66\x74\x2d\x72\x61\x64\x69\x75\x73\x3a\x20\x35\x70\x78\x3b\ | 683 | \x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x77\x69\x64\x74\ |
2916 | 648 | \x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x62\x6f\x74\x74\ | 684 | \x68\x3a\x20\x31\x70\x78\x3b\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\ |
2917 | 649 | \x6f\x6d\x2d\x72\x69\x67\x68\x74\x2d\x72\x61\x64\x69\x75\x73\x3a\ | 685 | \x67\x72\x6f\x75\x6e\x64\x3a\x20\x77\x68\x69\x74\x65\x3b\x0a\x20\ |
2918 | 650 | \x20\x35\x70\x78\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\ | 686 | \x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x74\x6f\x70\x3a\x20\x32\ |
2919 | 651 | \x2d\x74\x6f\x70\x2d\x72\x69\x67\x68\x74\x2d\x72\x61\x64\x69\x75\ | 687 | \x70\x78\x20\x73\x6f\x6c\x69\x64\x20\x77\x68\x69\x74\x65\x3b\x0a\ |
2920 | 652 | \x73\x3a\x20\x35\x70\x78\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\ | 688 | \x7d\x0a\x0a\x51\x47\x72\x6f\x75\x70\x42\x6f\x78\x20\x7b\x0a\x20\ |
2921 | 653 | \x65\x72\x2d\x73\x74\x79\x6c\x65\x3a\x20\x73\x6f\x6c\x69\x64\x3b\ | 689 | \x20\x20\x20\x70\x61\x64\x64\x69\x6e\x67\x2d\x74\x6f\x70\x3a\x20\ |
2922 | 654 | \x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x63\x6f\x6c\x6f\ | 690 | \x33\x30\x70\x78\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\ |
2923 | 655 | \x72\x3a\x20\x23\x39\x33\x39\x33\x38\x39\x3b\x0a\x20\x20\x20\x20\ | 691 | \x3a\x20\x6e\x6f\x6e\x65\x3b\x0a\x20\x20\x20\x20\x6d\x61\x72\x67\ |
2924 | 656 | \x62\x6f\x72\x64\x65\x72\x2d\x77\x69\x64\x74\x68\x3a\x20\x31\x70\ | 692 | \x69\x6e\x2d\x74\x6f\x70\x3a\x20\x31\x65\x78\x3b\x0a\x7d\x0a\x0a\ |
2925 | 657 | \x78\x3b\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\ | 693 | \x51\x47\x72\x6f\x75\x70\x42\x6f\x78\x3a\x3a\x74\x69\x74\x6c\x65\ |
2926 | 658 | \x64\x3a\x20\x77\x68\x69\x74\x65\x3b\x0a\x20\x20\x20\x20\x62\x6f\ | 694 | \x20\x7b\x0a\x20\x20\x20\x20\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x33\ |
2927 | 659 | \x72\x64\x65\x72\x2d\x74\x6f\x70\x3a\x20\x32\x70\x78\x20\x73\x6f\ | 695 | \x33\x33\x33\x33\x33\x3b\x0a\x20\x20\x20\x20\x66\x6f\x6e\x74\x3a\ |
2928 | 660 | \x6c\x69\x64\x20\x77\x68\x69\x74\x65\x3b\x0a\x7d\x0a\x0a\x51\x47\ | 696 | \x20\x62\x6f\x6c\x64\x20\x31\x35\x70\x78\x3b\x0a\x7d\x0a\x0a\x51\ |
2929 | 661 | \x72\x6f\x75\x70\x42\x6f\x78\x20\x7b\x0a\x20\x20\x20\x20\x70\x61\ | 697 | \x47\x72\x6f\x75\x70\x42\x6f\x78\x23\x70\x72\x6f\x66\x69\x6c\x65\ |
2930 | 662 | \x64\x64\x69\x6e\x67\x2d\x74\x6f\x70\x3a\x20\x33\x30\x70\x78\x3b\ | 698 | \x2c\x0a\x51\x47\x72\x6f\x75\x70\x42\x6f\x78\x23\x73\x65\x72\x76\ |
2931 | 663 | \x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x3a\x20\x6e\x6f\x6e\ | 699 | \x69\x63\x65\x73\x20\x7b\x0a\x20\x20\x20\x20\x70\x61\x64\x64\x69\ |
2932 | 664 | \x65\x3b\x0a\x20\x20\x20\x20\x6d\x61\x72\x67\x69\x6e\x2d\x74\x6f\ | 700 | \x6e\x67\x2d\x6c\x65\x66\x74\x3a\x20\x35\x70\x78\x3b\x0a\x7d\x0a\ |
2933 | 665 | \x70\x3a\x20\x31\x65\x78\x3b\x0a\x7d\x0a\x0a\x51\x47\x72\x6f\x75\ | 701 | \x0a\x51\x4c\x69\x73\x74\x57\x69\x64\x67\x65\x74\x20\x7b\x0a\x20\ |
2934 | 666 | \x70\x42\x6f\x78\x3a\x3a\x74\x69\x74\x6c\x65\x20\x7b\x0a\x20\x20\ | 702 | \x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x20\x23\ |
2935 | 667 | \x20\x20\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x33\x33\x33\x33\x33\x33\ | 703 | \x66\x37\x66\x36\x66\x35\x3b\x0a\x20\x20\x20\x20\x61\x6c\x74\x65\ |
2936 | 668 | \x3b\x0a\x20\x20\x20\x20\x66\x6f\x6e\x74\x3a\x20\x62\x6f\x6c\x64\ | 704 | \x72\x6e\x61\x74\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\ |
2937 | 669 | \x20\x31\x35\x70\x78\x3b\x0a\x7d\x0a\x0a\x51\x47\x72\x6f\x75\x70\ | 705 | \x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x65\x66\x65\x64\x65\x63\x3b\ |
2938 | 670 | \x42\x6f\x78\x23\x70\x72\x6f\x66\x69\x6c\x65\x2c\x0a\x51\x47\x72\ | 706 | \x0a\x7d\x0a\x0a\x51\x4c\x69\x73\x74\x57\x69\x64\x67\x65\x74\x23\ |
2939 | 671 | \x6f\x75\x70\x42\x6f\x78\x23\x73\x65\x72\x76\x69\x63\x65\x73\x20\ | 707 | \x6c\x69\x73\x74\x5f\x64\x65\x76\x69\x63\x65\x73\x3a\x3a\x69\x74\ |
2940 | 672 | \x7b\x0a\x20\x20\x20\x20\x70\x61\x64\x64\x69\x6e\x67\x2d\x6c\x65\ | 708 | \x65\x6d\x20\x7b\x0a\x20\x20\x20\x20\x6d\x69\x6e\x2d\x68\x65\x69\ |
2941 | 673 | \x66\x74\x3a\x20\x35\x70\x78\x3b\x0a\x7d\x0a\x0a\x51\x4c\x69\x73\ | 709 | \x67\x68\x74\x3a\x20\x34\x38\x70\x78\x3b\x0a\x7d\x0a\x0a\x51\x4c\ |
2942 | 674 | \x74\x57\x69\x64\x67\x65\x74\x20\x7b\x0a\x20\x20\x20\x20\x62\x61\ | 710 | \x61\x62\x65\x6c\x23\x6f\x74\x68\x65\x72\x5f\x64\x65\x76\x69\x63\ |
2943 | 675 | \x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x20\x23\x66\x37\x66\x36\x66\ | 711 | \x65\x73\x5f\x6c\x61\x62\x65\x6c\x20\x7b\x0a\x20\x20\x20\x20\x66\ |
2944 | 676 | \x35\x3b\x0a\x20\x20\x20\x20\x61\x6c\x74\x65\x72\x6e\x61\x74\x65\ | 712 | \x6f\x6e\x74\x3a\x20\x62\x6f\x6c\x64\x20\x31\x36\x70\x78\x3b\x0a\ |
2945 | 677 | \x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x2d\x63\x6f\x6c\x6f\ | 713 | \x7d\x0a\x0a\x51\x4c\x61\x62\x65\x6c\x23\x70\x65\x72\x63\x65\x6e\ |
2946 | 678 | \x72\x3a\x20\x23\x65\x66\x65\x64\x65\x63\x3b\x0a\x7d\x0a\x0a\x51\ | 714 | \x74\x61\x67\x65\x5f\x75\x73\x61\x67\x65\x5f\x6c\x61\x62\x65\x6c\ |
2947 | 679 | \x4c\x69\x73\x74\x57\x69\x64\x67\x65\x74\x23\x6c\x69\x73\x74\x5f\ | 715 | \x20\x7b\x0a\x20\x20\x20\x20\x6d\x61\x72\x67\x69\x6e\x2d\x74\x6f\ |
2948 | 680 | \x64\x65\x76\x69\x63\x65\x73\x3a\x3a\x69\x74\x65\x6d\x20\x7b\x0a\ | 716 | \x70\x3a\x20\x2d\x34\x70\x78\x3b\x0a\x7d\x0a\x0a\x51\x4c\x61\x62\ |
2949 | 681 | \x20\x20\x20\x20\x6d\x69\x6e\x2d\x68\x65\x69\x67\x68\x74\x3a\x20\ | 717 | \x65\x6c\x23\x66\x6f\x6c\x6c\x6f\x77\x5f\x75\x73\x5f\x6c\x61\x62\ |
2950 | 682 | \x34\x38\x70\x78\x3b\x0a\x7d\x0a\x0a\x51\x4c\x61\x62\x65\x6c\x23\ | 718 | \x65\x6c\x20\x7b\x0a\x20\x20\x20\x20\x63\x6f\x6c\x6f\x72\x3a\x20\ |
2951 | 683 | \x6f\x74\x68\x65\x72\x5f\x64\x65\x76\x69\x63\x65\x73\x5f\x6c\x61\ | 719 | \x77\x68\x69\x74\x65\x3b\x0a\x7d\x0a\x0a\x51\x41\x62\x73\x74\x72\ |
2952 | 684 | \x62\x65\x6c\x20\x7b\x0a\x20\x20\x20\x20\x66\x6f\x6e\x74\x3a\x20\ | 720 | \x61\x63\x74\x49\x74\x65\x6d\x56\x69\x65\x77\x20\x7b\x0a\x20\x20\ |
2953 | 685 | \x62\x6f\x6c\x64\x20\x31\x36\x70\x78\x3b\x0a\x7d\x0a\x0a\x51\x4c\ | 721 | \x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x73\x74\x79\x6c\x65\x3a\x20\ |
2954 | 686 | \x61\x62\x65\x6c\x23\x70\x65\x72\x63\x65\x6e\x74\x61\x67\x65\x5f\ | 722 | \x73\x6f\x6c\x69\x64\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\ |
2955 | 687 | \x75\x73\x61\x67\x65\x5f\x6c\x61\x62\x65\x6c\x20\x7b\x0a\x20\x20\ | 723 | \x72\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x38\x39\x38\x39\x38\x39\ |
2956 | 688 | \x20\x20\x6d\x61\x72\x67\x69\x6e\x2d\x74\x6f\x70\x3a\x20\x2d\x34\ | 724 | \x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x74\x6f\x70\ |
2957 | 689 | \x70\x78\x3b\x0a\x7d\x0a\x0a\x51\x4c\x61\x62\x65\x6c\x23\x66\x6f\ | 725 | \x2d\x77\x69\x64\x74\x68\x3a\x20\x31\x70\x78\x3b\x0a\x20\x20\x20\ |
2958 | 690 | \x6c\x6c\x6f\x77\x5f\x75\x73\x5f\x6c\x61\x62\x65\x6c\x20\x7b\x0a\ | 726 | \x20\x62\x6f\x72\x64\x65\x72\x2d\x62\x6f\x74\x74\x6f\x6d\x2d\x77\ |
2959 | 691 | \x20\x20\x20\x20\x63\x6f\x6c\x6f\x72\x3a\x20\x77\x68\x69\x74\x65\ | 727 | \x69\x64\x74\x68\x3a\x20\x31\x70\x78\x3b\x0a\x20\x20\x20\x20\x61\ |
2960 | 692 | \x3b\x0a\x7d\x0a\x0a\x51\x46\x72\x61\x6d\x65\x23\x66\x72\x6d\x5f\ | 728 | \x6c\x74\x65\x72\x6e\x61\x74\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\ |
2961 | 693 | \x62\x6f\x78\x20\x7b\x20\x2f\x2a\x20\x74\x68\x65\x20\x6c\x6f\x61\ | 729 | \x75\x6e\x64\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x66\x37\x66\x36\ |
2962 | 694 | \x64\x69\x6e\x67\x6f\x76\x65\x72\x6c\x61\x79\x20\x66\x72\x61\x6d\ | 730 | \x66\x35\x3b\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\ |
2963 | 695 | \x65\x20\x2a\x2f\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\ | 731 | \x6e\x64\x3a\x20\x23\x65\x66\x65\x64\x65\x63\x3b\x0a\x7d\x0a\ |
2889 | 696 | \x75\x6e\x64\x3a\x20\x23\x66\x66\x66\x66\x66\x66\x3b\x0a\x20\x20\ | ||
2890 | 697 | \x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x72\x61\x64\x69\x75\x73\x3a\ | ||
2891 | 698 | \x20\x35\x70\x78\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\ | ||
2892 | 699 | \x2d\x73\x74\x79\x6c\x65\x3a\x20\x73\x6f\x6c\x69\x64\x3b\x0a\x20\ | ||
2893 | 700 | \x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x63\x6f\x6c\x6f\x72\x3a\ | ||
2894 | 701 | \x20\x23\x39\x33\x39\x33\x38\x39\x3b\x0a\x20\x20\x20\x20\x62\x6f\ | ||
2895 | 702 | \x72\x64\x65\x72\x2d\x77\x69\x64\x74\x68\x3a\x20\x31\x70\x78\x3b\ | ||
2896 | 703 | \x0a\x20\x20\x20\x20\x63\x6f\x6c\x6f\x72\x3a\x20\x77\x68\x69\x74\ | ||
2897 | 704 | \x65\x3b\x0a\x20\x20\x20\x20\x6d\x69\x6e\x2d\x68\x65\x69\x67\x68\ | ||
2898 | 705 | \x74\x3a\x20\x31\x30\x30\x70\x78\x3b\x0a\x7d\x0a\x0a\x51\x41\x62\ | ||
2899 | 706 | \x73\x74\x72\x61\x63\x74\x49\x74\x65\x6d\x56\x69\x65\x77\x20\x7b\ | ||
2900 | 707 | \x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x73\x74\x79\x6c\ | ||
2901 | 708 | \x65\x3a\x20\x73\x6f\x6c\x69\x64\x3b\x0a\x20\x20\x20\x20\x62\x6f\ | ||
2902 | 709 | \x72\x64\x65\x72\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x33\x33\x33\ | ||
2903 | 710 | \x33\x33\x33\x3b\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\ | ||
2904 | 711 | \x77\x69\x64\x74\x68\x3a\x20\x31\x70\x78\x3b\x0a\x20\x20\x20\x20\ | ||
2905 | 712 | \x61\x6c\x74\x65\x72\x6e\x61\x74\x65\x2d\x62\x61\x63\x6b\x67\x72\ | ||
2906 | 713 | \x6f\x75\x6e\x64\x2d\x63\x6f\x6c\x6f\x72\x3a\x20\x23\x65\x66\x65\ | ||
2907 | 714 | \x64\x65\x63\x3b\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\ | ||
2908 | 715 | \x75\x6e\x64\x3a\x20\x23\x66\x37\x66\x36\x66\x35\x3b\x0a\x7d\x0a\ | ||
2909 | 716 | \ | ||
2964 | 717 | \x00\x00\x02\x6f\ | 732 | \x00\x00\x02\x6f\ |
2965 | 718 | \x89\ | 733 | \x89\ |
2966 | 719 | \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ | 734 | \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ |
2967 | @@ -23296,85 +23311,80 @@ | |||
2968 | 23296 | \xee\xee\xee\x93\x74\xd0\xf8\xf8\x78\xff\xac\x9e\xfb\xdf\x96\xbf\ | 23311 | \xee\xee\xee\x93\x74\xd0\xf8\xf8\x78\xff\xac\x9e\xfb\xdf\x96\xbf\ |
2969 | 23297 | \x02\x0c\x00\x57\x70\xa3\x5d\x63\x1a\xb1\xc1\x00\x00\x00\x00\x49\ | 23312 | \x02\x0c\x00\x57\x70\xa3\x5d\x63\x1a\xb1\xc1\x00\x00\x00\x00\x49\ |
2970 | 23298 | \x45\x4e\x44\xae\x42\x60\x82\ | 23313 | \x45\x4e\x44\xae\x42\x60\x82\ |
3050 | 23299 | \x00\x00\x04\xc5\ | 23314 | \x00\x00\x02\x2a\ |
3051 | 23300 | \x89\ | 23315 | \x89\ |
3052 | 23301 | \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ | 23316 | \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ |
3053 | 23302 | \x00\x00\x20\x00\x00\x00\x20\x08\x06\x00\x00\x00\x73\x7a\x7a\xf4\ | 23317 | \x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\ |
3054 | 23303 | \x00\x00\x04\x8c\x49\x44\x41\x54\x78\xda\xbd\x97\xfb\x53\xd4\x65\ | 23318 | \x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\ |
3055 | 23304 | \x14\xc6\xf9\x17\xfa\x4b\x6c\xa6\xdf\xba\x89\x9a\x19\x65\x99\x95\ | 23319 | \x01\x00\x9a\x9c\x18\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\ |
3056 | 23305 | \x20\x97\xbd\x21\xec\x02\x8a\x28\x77\x58\x60\xc1\x26\xe9\x66\x4a\ | 23320 | \x74\x77\x61\x72\x65\x00\x41\x64\x6f\x62\x65\x20\x49\x6d\x61\x67\ |
3057 | 23306 | \xa5\x21\x2c\xe2\x28\xb0\x0b\xbb\x2c\x2c\x94\x94\x46\x54\xde\xa6\ | 23321 | \x65\x52\x65\x61\x64\x79\x71\xc9\x65\x3c\x00\x00\x01\xb7\x49\x44\ |
3058 | 23307 | \x71\x72\xaa\xd1\x9a\x32\xa6\xa6\x7b\x43\x22\x0a\x22\x5e\xb6\xd3\ | 23322 | \x41\x54\x78\xda\x94\x93\x4d\x2f\x03\x41\x18\xc7\x9f\x5d\xd3\xdd\ |
3059 | 23308 | \x7b\x5e\xe6\xd9\xf7\xec\xee\x77\x1b\x7e\x92\x99\xcf\x9c\x73\x9e\ | 23323 | \xb6\x0e\x5e\x83\x34\xc1\x88\x38\x38\x78\x8d\x44\x38\x38\x78\xb9\ |
3060 | 23309 | \xf7\x5c\x1e\x96\x1f\x80\x0c\xfe\x7a\xe0\xa1\xba\x07\x15\xdd\x8a\ | 23324 | \x8a\xc6\x55\x22\x1c\x5c\xc4\x37\x70\xf3\x2d\x48\x70\x90\x38\x96\ |
3061 | 23310 | \xa9\xfb\x44\x37\xdf\x94\xc7\xa7\x8a\x9a\x22\x33\x7b\xbb\xce\xc4\ | 23325 | \xc4\x89\xe8\xcd\x57\xd0\x92\x58\x2b\x95\x4a\x43\xd5\x5b\xed\xdb\ |
3062 | 23311 | \xf6\xf5\x9e\xa7\xd7\x7b\xce\x5a\x82\xb7\xe4\xf8\xe6\x11\xcc\x40\ | 23326 | \xec\xac\x99\xd9\x54\xad\x96\xf0\x5c\x9e\xcc\xf3\x3c\xff\xdf\xfc\ |
3063 | 23312 | \x4b\x3f\xd7\xde\x7d\x36\xc6\xb7\xf8\xa6\x36\xc1\x6e\x0a\x1b\x87\ | 23327 | \x67\x76\x47\x1a\x9b\x5b\x1f\x0c\x87\xa3\x09\x35\x1c\xc1\x8a\xa2\ |
3064 | 23313 | \x67\xf6\x1c\xfc\x8c\x2a\x5f\x3d\x49\x1e\xdf\xfb\xe4\x6e\x19\x37\ | 23328 | \xc2\x5f\xc2\xb6\x2d\xb0\x4c\x43\x37\xcd\xf7\x38\x52\xd5\x48\x62\ |
3065 | 23314 | \xf8\xc6\xa9\xb4\xed\x04\xe0\x5a\x53\xd2\xfa\x01\x7a\x64\x2f\x47\ | 23329 | \x76\x7a\x1c\x77\xb7\xb7\x82\x24\x49\x7f\x02\x78\x9e\x07\x57\x99\ |
3066 | 23315 | \xdd\x27\x75\x68\x65\x8a\x8a\xf6\x09\x7a\xb9\xf3\x73\xe2\x9b\x7c\ | 23330 | \x1c\x3e\x3c\x39\x4b\x20\x14\x52\x70\xbe\x60\x41\x4a\x4f\xc3\x7f\ |
3067 | 23316 | \x3b\x83\x9d\x78\xdf\xfe\x24\x56\xbe\x77\x82\x3c\x6a\x69\x51\xcb\ | 23331 | \xa2\xa5\x2e\x0a\x21\x25\x8c\x11\x80\x0c\xe9\x4c\x1e\x5c\xea\xfd\ |
3068 | 23317 | \x18\x62\x0a\x9e\xb6\x84\x77\xe4\x8c\xec\x91\xd1\x32\xdf\xd9\xfe\ | 23332 | \x0b\xf0\xf8\x62\x30\x27\x00\x88\x50\x0a\x96\xe3\xfe\x38\x38\x39\ |
3069 | 23318 | \x21\x79\x0f\x4c\xc6\xf8\xf6\xb2\x81\x8e\x49\x72\xb7\x8e\xd3\xb6\ | 23333 | \xda\x05\xcb\xf3\xc3\x50\x1b\x51\xc4\x3a\xbe\xb6\x2f\x32\x61\x12\ |
3070 | 23319 | \xe6\x28\x15\x36\x8d\x6a\x8a\x7d\xe3\x32\x4f\x5b\xf3\x0c\x6a\x47\ | 23334 | \xae\x45\xae\xeb\xb2\x05\xfd\x11\xf0\x55\xec\x0b\xcb\xb3\x5c\xcb\ |
3071 | 23320 | \x7d\x98\x36\x97\xf9\x29\xcb\xd5\x41\x1b\x1c\xfb\xe9\x29\xa7\x89\ | 23335 | \x00\xf4\x57\x40\x49\xbc\xba\x71\x04\xda\x6d\x21\xd0\xe3\x5a\xe1\ |
3072 | 23321 | \xfc\x0e\xf8\x56\xf3\x3b\x53\x14\x37\x50\xbf\x7f\x92\x9c\x8d\x23\ | 23336 | \x80\x1f\x86\xdb\xf9\x2d\x2e\x6f\x1e\x02\x6b\x24\xcb\x65\x07\x8a\ |
3073 | 23322 | \x6a\xd9\x18\x88\xd7\x2e\xef\xe8\x72\x6c\x1c\xd5\x9a\xd6\x9b\xf4\ | 23337 | \x2c\x81\xe9\x04\x01\xc9\xed\xa5\xcf\x4f\xc6\xe3\x78\x6b\xd1\xbf\ |
3074 | 23323 | \xbb\x06\x7d\xb6\xda\x10\xd9\xab\x7b\xe9\xe4\xe9\xcb\x34\x7f\x73\ | 23338 | \x93\xe5\x1d\x91\xa3\xa8\xa6\xe4\x80\x82\x2a\x68\x41\x80\xe3\x38\ |
3075 | 23324 | \x89\x92\xbe\x30\xaf\x4c\x47\x75\xac\xdb\x77\xca\x18\xd8\xad\x7e\ | 23339 | \x55\x9d\x94\xe6\x4a\x1a\x44\x98\x0d\x85\xd1\xec\x6f\x80\x89\xa5\ |
3076 | 23325 | \x2e\x85\xde\xa8\xfa\x0e\x22\x88\x20\x9d\x9e\xa2\xb9\xbd\x41\x9a\ | 23340 | \x5d\x91\x4f\x37\x17\x44\x9e\x5a\xd9\x0b\xf4\xb9\x86\x6b\x91\x69\ |
3077 | 23326 | \x9b\xbf\x45\xf7\x62\xff\x5a\xc2\xbd\x12\x75\xd3\x18\x28\x7f\xe5\ | 23341 | \x19\x0c\x6b\x40\xb1\xf8\x52\x75\x47\x87\xf8\x4e\x2a\xfa\xf5\x21\ |
3078 | 23327 | \x04\x39\x1a\x46\x34\x05\xb5\x61\xe4\x29\x1a\x72\xbb\x3a\xc8\x51\ | 23342 | \xe0\x5a\xd4\xd8\xde\x09\xb8\x7f\x08\x0a\xcd\x4f\xd5\x01\x0e\x11\ |
3079 | 23328 | \x12\x9a\xb8\x48\xb7\xef\xc6\xd2\xc2\x33\x72\x87\xba\x69\x0c\x78\ | 23343 | \xb9\x63\x60\x24\x50\xc7\xb1\x7a\xb8\x36\x18\x80\x58\x36\xb8\x66\ |
3080 | 23329 | \x7c\x51\xdd\x90\x5f\x13\x52\x1f\xe5\x30\xf2\x15\xc1\xbd\xcc\xe5\ | 23344 | \x11\xa2\x1e\x85\x7c\xd1\xaa\x00\x10\xe2\x03\x8c\x37\xe3\xb3\xd6\ |
3081 | 23330 | \x2b\x7f\xd2\xe2\xd2\xbd\xb4\xa0\x0f\x33\xee\x96\xa8\x31\x50\xd4\ | 23345 | \x54\xab\x0a\x0d\xe5\x77\x50\x03\x54\xbf\xbb\xcf\xe1\xbe\x58\x8c\ |
3082 | 23331 | \x14\x55\xae\x86\x35\xb9\x55\x43\x0c\x6a\x35\x10\x96\x1a\x62\x4a\ | 23346 | \xfd\xdb\x0d\x15\x00\x55\xf5\x5f\xe8\x4c\x6f\x5b\xd9\x15\x7b\x8d\ |
3083 | 23332 | \xef\xc2\xe2\xdd\x04\x3e\x3a\xf3\x23\x15\xb7\x8c\xe9\x37\x20\xe7\ | 23347 | \x5a\x36\x0b\x12\xb1\x75\x44\x8d\xe7\xf8\x85\xa6\x25\x52\x9a\x8e\ |
3084 | 23333 | \x5c\x8d\x11\x63\x20\xaf\x7a\x90\xb2\x77\x07\x28\xb7\x7a\x08\xa4\ | 23348 | \xab\x1d\xa1\xa7\x35\x27\xf2\x41\xf2\x3c\x50\x97\xd9\xc6\x9e\xf9\ |
3085 | 23334 | \xab\x11\x53\xb8\xbe\x70\x27\x01\x47\x43\x58\xce\x6a\xb6\x56\x0d\ | 23349 | \x1a\xff\x10\x60\x00\x7c\x3b\xda\x5b\x6c\x8a\x7e\xa0\x00\x00\x00\ |
3086 | 23335 | \xc6\x73\x75\xd3\x18\xc8\xa9\x1c\xa4\x97\x2a\x06\xe2\x64\xef\x0a\ | 23350 | \x00\x49\x45\x4e\x44\xae\x42\x60\x82\ |
3087 | 23336 | \x92\xd4\x38\x67\x64\xbe\xa5\x22\x80\x5a\xc7\xd9\x1b\x77\x24\xe8\ | 23351 | \x00\x00\x02\x2a\ |
3088 | 23337 | \x03\x16\x3b\x84\x81\x2d\xbb\x02\x04\x5e\x28\xef\x03\xa8\xd5\xb1\ | 23352 | \x89\ |
3089 | 23338 | \x81\x84\x77\xe4\x99\xb9\x6f\x68\x56\xe7\xbc\x46\x33\xd7\x6e\x4b\ | 23353 | \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ |
3090 | 23339 | \x58\xe3\x37\x60\xb5\xdf\x18\x78\x7e\xfb\x71\x02\x2f\xee\x1c\x88\ | 23354 | \x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\ |
3091 | 23340 | \xb3\x79\x47\x1f\x34\xe4\xa8\x75\xfc\xeb\xea\xd2\x4a\xc1\x4e\xcc\ | 23355 | \x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\ |
3092 | 23341 | \x2b\x03\xfd\xc6\xc0\x73\xa5\xc7\x48\xa1\x1e\xfb\xd4\xa1\x7e\xc4\ | 23356 | \x01\x00\x9a\x9c\x18\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\ |
3093 | 23342 | \x04\x36\x95\x1d\xe7\x1e\xd4\x3a\xff\x7d\xe6\xd6\x8a\xf8\xf8\xfc\ | 23357 | \x74\x77\x61\x72\x65\x00\x41\x64\x6f\x62\x65\x20\x49\x6d\x61\x67\ |
3094 | 23343 | \x34\x66\xc4\x4e\x61\x60\x93\x72\xb5\xb1\xe4\x28\x71\x44\xce\xc4\ | 23358 | \x65\x52\x65\x61\x64\x79\x71\xc9\x65\x3c\x00\x00\x01\xb7\x49\x44\ |
3095 | 23344 | \xf5\xb2\x63\x96\x6f\xbf\xfe\xbd\xb8\x22\x4e\x9d\x9b\x96\xfb\x80\ | 23359 | \x41\x54\x78\xda\x94\x93\x4d\x2f\x03\x41\x18\xc7\x9f\x5d\xd3\xdd\ |
3096 | 23345 | \x31\xf0\xac\x72\xf6\xb4\xbb\x57\xc3\x39\x40\x8d\xb7\xe4\xfa\xe7\ | 23360 | \xb6\x0e\x5e\x83\x34\xc1\x88\x38\x38\x78\x8d\x44\x38\x38\x78\xb9\ |
3097 | 23346 | \x3f\x6e\xae\x88\x43\x81\x0b\x72\x1f\x72\x63\x60\xa3\xe7\x28\x31\ | 23361 | \x8a\xc6\x55\x22\x1c\x5c\xc4\x37\x70\xf3\x2d\x48\x70\x90\x38\x96\ |
3098 | 23347 | \x59\x45\x3d\x1c\x01\x34\x19\xd3\xe6\xd3\xbf\x2d\x48\xfe\x6f\x1f\ | 23362 | \xc4\x89\xe8\xcd\x57\xd0\x92\x58\x2b\x95\x4a\x43\xd5\x5b\xed\xdb\ |
3099 | 23348 | \x74\x63\xe0\xc9\x42\x3f\x31\x1b\xb6\xf5\x10\xf2\xac\xe2\x5e\xe4\ | 23363 | \xec\xac\x99\xd9\x54\xad\x96\xf0\x5c\x9e\xcc\xf3\x3c\xff\xdf\xfc\ |
3100 | 23349 | \x96\x35\x34\xe8\x3f\xfc\x32\x2f\x51\x47\x8e\x24\xcf\xe0\x06\xe6\ | 23364 | \x67\x76\x47\x1a\x9b\x5b\x1f\x0c\x87\xa3\x09\x35\x1c\xc1\x8a\xa2\ |
3101 | 23350 | \x8c\x01\x16\x25\x4f\x38\xbb\x64\x8e\x88\x05\x96\xef\xdf\xfd\x74\ | 23365 | \xc2\x5f\xc2\xb6\x2d\xb0\x4c\x43\x37\xcd\xf7\x38\x52\xd5\x48\x62\ |
3102 | 23351 | \x43\xc2\x3a\x90\xbd\x32\x1a\x03\xeb\x5d\x7e\x5a\xef\xf4\xd3\x5a\ | 23366 | \x76\x7a\x1c\x77\xb7\xb7\x82\x24\x49\x7f\x02\x78\x9e\x07\x57\x99\ |
3103 | 23352 | \xfb\x61\x0d\xd7\x0c\x72\x51\x5b\x46\xe6\xd2\xf4\x75\x89\xd5\x3c\ | 23367 | \x1c\x3e\x3c\x39\x4b\x20\x14\x52\x70\xbe\x60\x41\x4a\x4f\xc3\x7f\ |
3104 | 23353 | \x34\x60\x0c\xac\x73\x74\x11\x93\x59\xf0\x9e\x8e\x6b\x0a\x3a\x51\ | 23368 | \xa2\xa5\x2e\x0a\x21\x25\x8c\x11\x80\x0c\xe9\x4c\x1e\x5c\xea\xfd\ |
3105 | 23354 | \xa7\x65\x9d\xdd\xf4\x33\x5f\x5f\x99\x93\xe0\x0d\x7d\xa8\x01\xd7\ | 23369 | \x0b\xf0\xf8\x62\x30\x27\x00\x88\x50\x0a\x96\xe3\xfe\x38\x38\x39\ |
3106 | 23355 | \xd2\xc0\x61\x7a\x3c\xef\x20\xad\xb1\x75\x72\x94\x40\xd7\xc8\x9e\ | 23370 | \xda\x05\xcb\xf3\xc3\x50\x1b\x51\xc4\x3a\xbe\xb6\x2f\x32\x61\x12\ |
3107 | 23356 | \xcc\xfc\x43\x1a\xd4\x17\xbf\x9f\x93\xa0\x37\xed\x0e\x75\xd3\x18\ | 23371 | \xae\x45\xae\xeb\xb2\x05\xfd\x11\xf0\x55\xec\x0b\xcb\xb3\x5c\xcb\ |
3108 | 23357 | \x58\x6b\x7b\x97\x1e\xc9\x7e\x8b\x1e\x56\x3c\x96\xdb\xa1\x79\x34\ | 23372 | \x00\xf4\x57\x40\x49\xbc\xba\x71\x04\xda\x6d\x21\xd0\xe3\x5a\xe1\ |
3109 | 23358 | \xe7\x80\x8e\xd0\x00\x34\x44\xe4\x17\xbe\xbd\x26\x91\xbd\x96\x33\ | 23373 | \x80\x1f\x86\xdb\xf9\x2d\x2e\x6f\x1e\x02\x6b\x24\xcb\x65\x07\x8a\ |
3110 | 23359 | \xab\xf3\x3a\x8c\x81\x12\xdf\x08\x39\xeb\x87\xc8\x51\x37\xc8\xe8\ | 23374 | \x2c\x81\xe9\x04\x01\xc9\xed\xa5\xcf\x4f\xc6\xe3\x78\x6b\xd1\xbf\ |
3111 | 23360 | \xbc\xb0\x31\x2c\x35\x5d\x23\xba\x94\x8e\x1a\x7c\x71\x69\x56\xa2\ | 23375 | \x93\xe5\x1d\x91\xa3\xa8\xa6\xe4\x80\x82\x2a\x68\x41\x80\xe3\x38\ |
3112 | 23361 | \x7a\x42\x5a\x77\x35\x84\xb8\x37\xa5\xbf\xb8\x29\x9c\x68\xc0\x5e\ | 23376 | \x55\x9d\x94\xe6\x4a\x1a\x44\x98\x0d\x85\xd1\xec\x6f\x80\x89\xa5\ |
3113 | 23362 | \x1b\x04\x3c\xc4\xa4\x68\x88\x6c\x0c\x35\x38\xf7\xcd\x55\x09\xf7\ | 23377 | \x5d\x91\x4f\x37\x17\x44\x9e\x5a\xd9\x0b\xf4\xb9\x86\x6b\x91\x69\ |
3114 | 23363 | \xa0\xdf\x72\x9f\x5b\x1a\x70\x37\x87\xa9\xa0\x26\x40\x0e\x35\x04\ | 23378 | \x19\x0c\x6b\x40\xb1\xf8\x52\x75\x47\x87\xf8\x4e\x2a\xfa\xf5\x21\ |
3115 | 23364 | \xd8\x25\x34\x8e\xf6\xe5\x5a\x63\x53\x0b\xa0\xe3\xed\xf4\x57\xff\ | 23379 | \xe0\x5a\xd4\xd8\xde\x09\xb8\x7f\x08\x0a\xcd\x4f\xd5\x01\x0e\x11\ |
3116 | 23365 | \x48\xe4\x2c\xf2\x84\x9a\x6f\x9a\x3f\xc9\xd8\x40\xf5\x00\xe5\x57\ | 23380 | \xb9\x63\x60\x24\x50\xc7\xb1\x7a\xb8\x36\x18\x80\x58\x36\xb8\x66\ |
3117 | 23366 | \x25\xa0\x9c\x0e\x26\xd4\xb6\xea\xa0\xd6\xa0\xcb\xf8\xe9\x97\x33\ | 23381 | \x11\xa2\x1e\x85\x7c\xd1\xaa\x00\x10\xe2\x03\x8c\x37\xe3\xb3\xd6\ |
3118 | 23367 | \x92\xe4\x59\xb5\x3f\x00\x4d\x7f\x73\xa5\xbe\x88\xf8\x04\xbc\xe1\ | 23382 | \x54\xab\x0a\x0d\xe5\x77\x50\x03\x54\xbf\xbb\xcf\xe1\xbe\x58\x8c\ |
3119 | 23368 | \x18\x7f\x2c\x79\x7c\x44\x35\x59\xc1\x6f\xc0\x56\x93\x5c\x07\x13\ | 23383 | \xfd\xdb\x0d\x15\x00\x55\xf5\x5f\xe8\x4c\x6f\x5b\xd9\x15\x7b\x8d\ |
3120 | 23369 | \xea\x7c\x75\x4c\xcc\x20\x07\xca\x40\x90\x3c\xcd\xc3\x31\x18\xe8\ | 23384 | \x5a\x36\x0b\x12\xb1\x75\x44\x8d\xe7\xf8\x85\xa6\x25\x52\x9a\x8e\ |
3121 | 23370 | \x7e\xc6\xed\x9f\x2d\x6d\x1b\x25\x67\xc3\x10\xe5\xab\x65\xcc\xd6\ | 23385 | \xab\x1d\xa1\xa7\x35\x27\xf2\x41\xf2\x3c\x50\x97\xd9\xc6\x9e\xf9\ |
3122 | 23371 | \xca\x7e\xa0\x86\x02\x3a\xe2\x2d\x57\x2d\x41\x2d\xfa\x64\x8f\xcc\ | 23386 | \x1a\xff\x10\x60\x00\x7c\x3b\xda\x5b\x6c\x8a\x7e\xa0\x00\x00\x00\ |
3123 | 23372 | \xc5\x5b\x40\xdf\xe0\x5b\x7c\x13\xff\x9a\xad\xd2\xbf\x11\x3d\xfe\ | 23387 | \x00\x49\x45\x4e\x44\xae\x42\x60\x82\ |
3045 | 23373 | \xd9\xe2\xe6\x50\x6c\xc7\x9e\x28\x95\xb6\x46\x88\x23\x80\x86\x68\ | ||
3046 | 23374 | \x45\x59\xdb\x88\xe9\x11\x71\xbb\x3a\x26\xb5\x12\x5f\x24\xc6\xb7\ | ||
3047 | 23375 | \xf8\x26\xdf\xce\x20\x22\x98\xb8\xdf\xff\x9e\xaf\xe2\xdb\xff\x01\ | ||
3048 | 23376 | \x95\x7c\xeb\x7f\xbd\xd5\xeb\x77\x00\x00\x00\x00\x49\x45\x4e\x44\ | ||
3049 | 23377 | \xae\x42\x60\x82\ | ||
3124 | 23378 | \x00\x00\x01\x68\ | 23388 | \x00\x00\x01\x68\ |
3125 | 23379 | \x89\ | 23389 | \x89\ |
3126 | 23380 | \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ | 23390 | \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ |
3127 | @@ -23468,21 +23478,23 @@ | |||
3128 | 23468 | " | 23478 | " |
3129 | 23469 | 23479 | ||
3130 | 23470 | qt_resource_struct = "\ | 23480 | qt_resource_struct = "\ |
3133 | 23471 | \x00\x00\x00\x00\x00\x02\x00\x00\x00\x0e\x00\x00\x00\x01\ | 23481 | \x00\x00\x00\x00\x00\x02\x00\x00\x00\x10\x00\x00\x00\x01\ |
3134 | 23472 | \x00\x00\x01\xf0\x00\x00\x00\x00\x00\x01\x00\x05\xb2\x73\ | 23482 | \x00\x00\x01\xf0\x00\x00\x00\x00\x00\x01\x00\x05\xb2\xec\ |
3135 | 23473 | \x00\x00\x00\x96\x00\x00\x00\x00\x00\x01\x00\x00\x0c\xe5\ | 23483 | \x00\x00\x00\x96\x00\x00\x00\x00\x00\x01\x00\x00\x0c\xe5\ |
3137 | 23474 | \x00\x00\x01\x3e\x00\x00\x00\x00\x00\x01\x00\x00\x17\xfe\ | 23484 | \x00\x00\x01\x3e\x00\x00\x00\x00\x00\x01\x00\x00\x17\x85\ |
3138 | 23475 | \x00\x00\x00\x7e\x00\x00\x00\x00\x00\x01\x00\x00\x09\xc8\ | 23485 | \x00\x00\x00\x7e\x00\x00\x00\x00\x00\x01\x00\x00\x09\xc8\ |
3140 | 23476 | \x00\x00\x01\xb4\x00\x00\x00\x00\x00\x01\x00\x05\xaa\x1e\ | 23486 | \x00\x00\x01\xb4\x00\x00\x00\x00\x00\x01\x00\x05\xab\x04\ |
3141 | 23477 | \x00\x00\x00\x4a\x00\x00\x00\x00\x00\x01\x00\x00\x04\x92\ | 23487 | \x00\x00\x00\x4a\x00\x00\x00\x00\x00\x01\x00\x00\x04\x92\ |
3142 | 23478 | \x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ | 23488 | \x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ |
3143 | 23479 | \x00\x00\x00\xee\x00\x00\x00\x00\x00\x01\x00\x00\x11\xb2\ | 23489 | \x00\x00\x00\xee\x00\x00\x00\x00\x00\x01\x00\x00\x11\xb2\ |
3144 | 23490 | \x00\x00\x00\xee\x00\x00\x00\x00\x00\x01\x00\x00\x14\x06\ | ||
3145 | 23480 | \x00\x00\x00\x30\x00\x00\x00\x00\x00\x01\x00\x00\x01\xd5\ | 23491 | \x00\x00\x00\x30\x00\x00\x00\x00\x00\x01\x00\x00\x01\xd5\ |
3146 | 23481 | \x00\x00\x00\xd4\x00\x00\x00\x00\x00\x01\x00\x00\x0f\x83\ | 23492 | \x00\x00\x00\xd4\x00\x00\x00\x00\x00\x01\x00\x00\x0f\x83\ |
3151 | 23482 | \x00\x00\x01\x0a\x00\x00\x00\x00\x00\x01\x00\x00\x16\xd3\ | 23493 | \x00\x00\x01\x0a\x00\x00\x00\x00\x00\x01\x00\x00\x16\x5a\ |
3152 | 23483 | \x00\x00\x01\xd2\x00\x00\x00\x00\x00\x01\x00\x05\xad\xaa\ | 23494 | \x00\x00\x01\xd2\x00\x00\x00\x00\x00\x01\x00\x05\xb0\xbe\ |
3153 | 23484 | \x00\x00\x01\x5e\x00\x00\x00\x00\x00\x01\x00\x00\x2a\xb3\ | 23495 | \x00\x00\x01\xd2\x00\x00\x00\x00\x00\x01\x00\x05\xae\x90\ |
3154 | 23485 | \x00\x00\x01\x96\x00\x00\x00\x00\x00\x01\x00\x00\x2d\x26\ | 23496 | \x00\x00\x01\x5e\x00\x00\x00\x00\x00\x01\x00\x00\x2b\x99\ |
3155 | 23497 | \x00\x00\x01\x96\x00\x00\x00\x00\x00\x01\x00\x00\x2e\x0c\ | ||
3156 | 23486 | " | 23498 | " |
3157 | 23487 | 23499 | ||
3158 | 23488 | def qInitResources(): | 23500 | def qInitResources(): |
3159 | 23489 | 23501 | ||
3160 | === modified file 'ubuntuone/controlpanel/gui/qt/ui/loadingoverlay_ui.py' | |||
3161 | --- ubuntuone/controlpanel/gui/qt/ui/loadingoverlay_ui.py 2011-08-12 19:12:08 +0000 | |||
3162 | +++ ubuntuone/controlpanel/gui/qt/ui/loadingoverlay_ui.py 2011-08-25 19:40:18 +0000 | |||
3163 | @@ -2,7 +2,7 @@ | |||
3164 | 2 | 2 | ||
3165 | 3 | # Form implementation generated from reading ui file 'data/qt/loadingoverlay.ui' | 3 | # Form implementation generated from reading ui file 'data/qt/loadingoverlay.ui' |
3166 | 4 | # | 4 | # |
3168 | 5 | # Created: Fri Aug 12 15:07:18 2011 | 5 | # Created: Thu Aug 25 15:26:50 2011 |
3169 | 6 | # by: PyQt4 UI code generator 4.8.3 | 6 | # by: PyQt4 UI code generator 4.8.3 |
3170 | 7 | # | 7 | # |
3171 | 8 | # WARNING! All changes made in this file will be lost! | 8 | # WARNING! All changes made in this file will be lost! |
3172 | 9 | 9 | ||
3173 | === modified file 'ubuntuone/controlpanel/gui/qt/ui/mainwindow_ui.py' | |||
3174 | --- ubuntuone/controlpanel/gui/qt/ui/mainwindow_ui.py 2011-08-12 19:12:08 +0000 | |||
3175 | +++ ubuntuone/controlpanel/gui/qt/ui/mainwindow_ui.py 2011-08-25 19:40:18 +0000 | |||
3176 | @@ -2,7 +2,7 @@ | |||
3177 | 2 | 2 | ||
3178 | 3 | # Form implementation generated from reading ui file 'data/qt/mainwindow.ui' | 3 | # Form implementation generated from reading ui file 'data/qt/mainwindow.ui' |
3179 | 4 | # | 4 | # |
3181 | 5 | # Created: Fri Aug 12 15:07:18 2011 | 5 | # Created: Thu Aug 25 15:26:50 2011 |
3182 | 6 | # by: PyQt4 UI code generator 4.8.3 | 6 | # by: PyQt4 UI code generator 4.8.3 |
3183 | 7 | # | 7 | # |
3184 | 8 | # WARNING! All changes made in this file will be lost! | 8 | # WARNING! All changes made in this file will be lost! |
3185 | @@ -48,7 +48,7 @@ | |||
3186 | 48 | QtCore.QMetaObject.connectSlotsByName(MainWindow) | 48 | QtCore.QMetaObject.connectSlotsByName(MainWindow) |
3187 | 49 | 49 | ||
3188 | 50 | def retranslateUi(self, MainWindow): | 50 | def retranslateUi(self, MainWindow): |
3190 | 51 | MainWindow.setWindowTitle(_('Ubuntu One Control Panel')) | 51 | MainWindow.setWindowTitle(_('Ubuntu One')) |
3191 | 52 | 52 | ||
3192 | 53 | from ubuntuone.controlpanel.gui.qt.controlpanel import ControlPanel | 53 | from ubuntuone.controlpanel.gui.qt.controlpanel import ControlPanel |
3193 | 54 | import images_rc | 54 | import images_rc |
3194 | 55 | 55 | ||
3195 | === modified file 'ubuntuone/controlpanel/gui/qt/ui/preferences_ui.py' | |||
3196 | --- ubuntuone/controlpanel/gui/qt/ui/preferences_ui.py 2011-08-12 19:12:08 +0000 | |||
3197 | +++ ubuntuone/controlpanel/gui/qt/ui/preferences_ui.py 2011-08-25 19:40:18 +0000 | |||
3198 | @@ -2,7 +2,7 @@ | |||
3199 | 2 | 2 | ||
3200 | 3 | # Form implementation generated from reading ui file 'data/qt/preferences.ui' | 3 | # Form implementation generated from reading ui file 'data/qt/preferences.ui' |
3201 | 4 | # | 4 | # |
3203 | 5 | # Created: Fri Aug 12 15:07:18 2011 | 5 | # Created: Thu Aug 25 15:26:50 2011 |
3204 | 6 | # by: PyQt4 UI code generator 4.8.3 | 6 | # by: PyQt4 UI code generator 4.8.3 |
3205 | 7 | # | 7 | # |
3206 | 8 | # WARNING! All changes made in this file will be lost! | 8 | # WARNING! All changes made in this file will be lost! |
3207 | @@ -90,6 +90,7 @@ | |||
3208 | 90 | self.apply_changes_button.setObjectName(_fromUtf8("apply_changes_button")) | 90 | self.apply_changes_button.setObjectName(_fromUtf8("apply_changes_button")) |
3209 | 91 | self.horizontalLayout.addWidget(self.apply_changes_button) | 91 | self.horizontalLayout.addWidget(self.apply_changes_button) |
3210 | 92 | self.restore_defaults_button = QtGui.QPushButton(Form) | 92 | self.restore_defaults_button = QtGui.QPushButton(Form) |
3211 | 93 | self.restore_defaults_button.setProperty(_fromUtf8("secondary"), True) | ||
3212 | 93 | self.restore_defaults_button.setObjectName(_fromUtf8("restore_defaults_button")) | 94 | self.restore_defaults_button.setObjectName(_fromUtf8("restore_defaults_button")) |
3213 | 94 | self.horizontalLayout.addWidget(self.restore_defaults_button) | 95 | self.horizontalLayout.addWidget(self.restore_defaults_button) |
3214 | 95 | self.verticalLayout.addLayout(self.horizontalLayout) | 96 | self.verticalLayout.addLayout(self.horizontalLayout) |
3215 | @@ -98,7 +99,7 @@ | |||
3216 | 98 | QtCore.QMetaObject.connectSlotsByName(Form) | 99 | QtCore.QMetaObject.connectSlotsByName(Form) |
3217 | 99 | 100 | ||
3218 | 100 | def retranslateUi(self, Form): | 101 | def retranslateUi(self, Form): |
3220 | 101 | self.bandwidth_settings.setTitle(_('Bandwidth settings')) | 102 | self.bandwidth_settings.setTitle(_('Bandwidth Settings')) |
3221 | 102 | self.limit_uploads_checkbox.setText(_('Limit upload speed to')) | 103 | self.limit_uploads_checkbox.setText(_('Limit upload speed to')) |
3222 | 103 | self.kbps_label_1.setText(_('Kilobits per second')) | 104 | self.kbps_label_1.setText(_('Kilobits per second')) |
3223 | 104 | self.limit_downloads_checkbox.setText(_('Limit download speed to')) | 105 | self.limit_downloads_checkbox.setText(_('Limit download speed to')) |
3224 | 105 | 106 | ||
3225 | === modified file 'ubuntuone/controlpanel/login_client.py' | |||
3226 | --- ubuntuone/controlpanel/login_client.py 2011-07-22 21:26:48 +0000 | |||
3227 | +++ ubuntuone/controlpanel/login_client.py 2011-08-25 19:40:18 +0000 | |||
3228 | @@ -18,14 +18,15 @@ | |||
3229 | 18 | 18 | ||
3230 | 19 | """Client to access Ubuntu One credentials.""" | 19 | """Client to access Ubuntu One credentials.""" |
3231 | 20 | 20 | ||
3232 | 21 | # pylint: disable=E0611, F0401 | ||
3233 | 22 | from ubuntuone.platform.credentials import CredentialsManagementTool | ||
3234 | 23 | # pylint: enable=E0611, F0401 | ||
3235 | 24 | |||
3236 | 21 | 25 | ||
3237 | 22 | def get_sso_proxy(): | 26 | def get_sso_proxy(): |
3238 | 23 | """Return a login client.""" | 27 | """Return a login client.""" |
3244 | 24 | # No name 'credentials' in module 'ubuntuone.platform' | 28 | result = CredentialsManagementTool() |
3245 | 25 | # Reimport 'credentials' (imported line 22) | 29 | return result |
3241 | 26 | # pylint: disable=E0611,W0404 | ||
3242 | 27 | from ubuntuone.platform import credentials | ||
3243 | 28 | return credentials.CredentialsManagementTool() | ||
3246 | 29 | 30 | ||
3247 | 30 | 31 | ||
3248 | 31 | def get_credentials(): | 32 | def get_credentials(): |
3249 | @@ -38,3 +39,15 @@ | |||
3250 | 38 | """Clear the credentials for Ubuntu One.""" | 39 | """Clear the credentials for Ubuntu One.""" |
3251 | 39 | proxy = get_sso_proxy() | 40 | proxy = get_sso_proxy() |
3252 | 40 | return proxy.clear_credentials() | 41 | return proxy.clear_credentials() |
3253 | 42 | |||
3254 | 43 | |||
3255 | 44 | def login(*args, **kwargs): | ||
3256 | 45 | """Get the credentials for Ubuntu One offering the user to login.""" | ||
3257 | 46 | proxy = get_sso_proxy() | ||
3258 | 47 | return proxy.login(*args, **kwargs) | ||
3259 | 48 | |||
3260 | 49 | |||
3261 | 50 | def register(*args, **kwargs): | ||
3262 | 51 | """Get the credentials for Ubuntu One offering the user to register.""" | ||
3263 | 52 | proxy = get_sso_proxy() | ||
3264 | 53 | return proxy.register(*args, **kwargs) | ||
3265 | 41 | 54 | ||
3266 | === modified file 'ubuntuone/controlpanel/sd_client/__init__.py' | |||
3267 | --- ubuntuone/controlpanel/sd_client/__init__.py 2011-07-22 21:26:48 +0000 | |||
3268 | +++ ubuntuone/controlpanel/sd_client/__init__.py 2011-08-25 19:40:18 +0000 | |||
3269 | @@ -21,221 +21,186 @@ | |||
3270 | 21 | import sys | 21 | import sys |
3271 | 22 | import warnings | 22 | import warnings |
3272 | 23 | 23 | ||
3273 | 24 | # pylint: disable=E0611 | ||
3274 | 25 | from ubuntuone.platform import tools | ||
3275 | 26 | # pylint: enable=E0611 | ||
3276 | 24 | from ubuntuone.controlpanel.logger import setup_logging | 27 | from ubuntuone.controlpanel.logger import setup_logging |
3277 | 25 | 28 | ||
3278 | 26 | # pylint: disable=W0611 | ||
3279 | 27 | |||
3280 | 28 | 29 | ||
3281 | 29 | logger = setup_logging('sd_client') | 30 | logger = setup_logging('sd_client') |
3282 | 30 | 31 | ||
3283 | 31 | 32 | ||
3492 | 32 | def get_syncdaemon_tool(): | 33 | class SyncDaemonClient(object): |
3493 | 33 | """Get a proxy for the SyncDaemonTool.""" | 34 | """An abstraction to SyncDaemonTool.""" |
3494 | 34 | # Reimport 'SyncDaemonTool' | 35 | |
3495 | 35 | # No name 'tools' in module 'ubuntuone.platform' | 36 | def __init__(self): |
3496 | 36 | # pylint: disable=W0404, E0611 | 37 | """Get a proxy for the SyncDaemonTool.""" |
3497 | 37 | from ubuntuone.platform import tools | 38 | self.status_changed_handler = None |
3498 | 38 | proxy = tools.SyncDaemonTool() | 39 | self.proxy = tools.SyncDaemonTool() |
3499 | 39 | return proxy | 40 | |
3500 | 40 | 41 | def get_throttling_limits(self): | |
3501 | 41 | 42 | """Get the speed limits from the syncdaemon.""" | |
3502 | 42 | def get_throttling_limits(): | 43 | return self.proxy.get_throttling_limits() |
3503 | 43 | """Get the speed limits from the syncdaemon.""" | 44 | |
3504 | 44 | return get_syncdaemon_tool().get_throttling_limits() | 45 | def set_throttling_limits(self, limits): |
3505 | 45 | 46 | """Set the speed limits on the syncdaemon.""" | |
3506 | 46 | 47 | dload = int(limits["download"]) | |
3507 | 47 | def set_throttling_limits(limits): | 48 | uload = int(limits["upload"]) |
3508 | 48 | """Set the speed limits on the syncdaemon.""" | 49 | return self.proxy.set_throttling_limits(dload, uload) |
3509 | 49 | dload = int(limits["download"]) | 50 | |
3510 | 50 | uload = int(limits["upload"]) | 51 | def bandwidth_throttling_enabled(self): |
3511 | 51 | return get_syncdaemon_tool().set_throttling_limits(dload, uload) | 52 | """Get the state of throttling in the syncdaemon.""" |
3512 | 52 | 53 | return self.proxy.is_throttling_enabled() | |
3513 | 53 | 54 | ||
3514 | 54 | def bandwidth_throttling_enabled(): | 55 | def enable_bandwidth_throttling(self): |
3515 | 55 | """Get the state of throttling in the syncdaemon.""" | 56 | """Enable the speed limits in the syncdaemon.""" |
3516 | 56 | return get_syncdaemon_tool().is_throttling_enabled() | 57 | return self.proxy.enable_throttling(True) |
3517 | 57 | 58 | ||
3518 | 58 | 59 | def disable_bandwidth_throttling(self): | |
3519 | 59 | def enable_bandwidth_throttling(): | 60 | """Disable the speed limits in the syncdaemon.""" |
3520 | 60 | """Enable the speed limits in the syncdaemon.""" | 61 | return self.proxy.enable_throttling(False) |
3521 | 61 | return get_syncdaemon_tool().enable_throttling(True) | 62 | |
3522 | 62 | 63 | def autoconnect_enabled(self): | |
3523 | 63 | 64 | """Get the state of autoconnect in the syncdaemon.""" | |
3524 | 64 | def disable_bandwidth_throttling(): | 65 | return self.proxy.is_autoconnect_enabled() |
3525 | 65 | """Disable the speed limits in the syncdaemon.""" | 66 | |
3526 | 66 | return get_syncdaemon_tool().enable_throttling(False) | 67 | def enable_autoconnect(self): |
3527 | 67 | 68 | """Enable autoconnect in the syncdaemon.""" | |
3528 | 68 | 69 | return self.proxy.enable_autoconnect(True) | |
3529 | 69 | def autoconnect_enabled(): | 70 | |
3530 | 70 | """Get the state of autoconnect in the syncdaemon.""" | 71 | def disable_autoconnect(self): |
3531 | 71 | return get_syncdaemon_tool().is_autoconnect_enabled() | 72 | """Disable autoconnect in the syncdaemon.""" |
3532 | 72 | 73 | return self.proxy.enable_autoconnect(False) | |
3533 | 73 | 74 | ||
3534 | 74 | def enable_autoconnect(): | 75 | def show_all_notifications_enabled(self): |
3535 | 75 | """Enable autoconnect in the syncdaemon.""" | 76 | """Get the state of show_all_notifications in the syncdaemon.""" |
3536 | 76 | return get_syncdaemon_tool().enable_autoconnect(True) | 77 | return self.proxy.is_show_all_notifications_enabled() |
3537 | 77 | 78 | ||
3538 | 78 | 79 | def enable_show_all_notifications(self): | |
3539 | 79 | def disable_autoconnect(): | 80 | """Enable show_all_notifications in the syncdaemon.""" |
3540 | 80 | """Disable autoconnect in the syncdaemon.""" | 81 | return self.proxy.enable_show_all_notifications(True) |
3541 | 81 | return get_syncdaemon_tool().enable_autoconnect(False) | 82 | |
3542 | 82 | 83 | def disable_show_all_notifications(self): | |
3543 | 83 | 84 | """Disable show_all_notifications in the syncdaemon.""" | |
3544 | 84 | def show_all_notifications_enabled(): | 85 | return self.proxy.enable_show_all_notifications(False) |
3545 | 85 | """Get the state of show_all_notifications in the syncdaemon.""" | 86 | |
3546 | 86 | return get_syncdaemon_tool().is_show_all_notifications_enabled() | 87 | def share_autosubscribe_enabled(self): |
3547 | 87 | 88 | """Get the state of share_autosubscribe in the syncdaemon.""" | |
3548 | 88 | 89 | return self.proxy.is_share_autosubscribe_enabled() | |
3549 | 89 | def enable_show_all_notifications(): | 90 | |
3550 | 90 | """Enable show_all_notifications in the syncdaemon.""" | 91 | def enable_share_autosubscribe(self): |
3551 | 91 | return get_syncdaemon_tool().enable_show_all_notifications(True) | 92 | """Enable share_autosubscribe in the syncdaemon.""" |
3552 | 92 | 93 | return self.proxy.enable_share_autosubscribe(True) | |
3553 | 93 | 94 | ||
3554 | 94 | def disable_show_all_notifications(): | 95 | def disable_share_autosubscribe(self): |
3555 | 95 | """Disable show_all_notifications in the syncdaemon.""" | 96 | """Disable share_autosubscribe in the syncdaemon.""" |
3556 | 96 | return get_syncdaemon_tool().enable_show_all_notifications(False) | 97 | return self.proxy.enable_share_autosubscribe(False) |
3557 | 97 | 98 | ||
3558 | 98 | 99 | def udf_autosubscribe_enabled(self): | |
3559 | 99 | def share_autosubscribe_enabled(): | 100 | """Get the state of udf_autosubscribe in the syncdaemon.""" |
3560 | 100 | """Get the state of share_autosubscribe in the syncdaemon.""" | 101 | return self.proxy.is_udf_autosubscribe_enabled() |
3561 | 101 | return get_syncdaemon_tool().is_share_autosubscribe_enabled() | 102 | |
3562 | 102 | 103 | def enable_udf_autosubscribe(self): | |
3563 | 103 | 104 | """Enable udf_autosubscribe in the syncdaemon.""" | |
3564 | 104 | def enable_share_autosubscribe(): | 105 | return self.proxy.enable_udf_autosubscribe(True) |
3565 | 105 | """Enable share_autosubscribe in the syncdaemon.""" | 106 | |
3566 | 106 | return get_syncdaemon_tool().enable_share_autosubscribe(True) | 107 | def disable_udf_autosubscribe(self): |
3567 | 107 | 108 | """Disable udf_autosubscribe in the syncdaemon.""" | |
3568 | 108 | 109 | return self.proxy.enable_udf_autosubscribe(False) | |
3569 | 109 | def disable_share_autosubscribe(): | 110 | |
3570 | 110 | """Disable share_autosubscribe in the syncdaemon.""" | 111 | def get_root_dir(self): |
3571 | 111 | return get_syncdaemon_tool().enable_share_autosubscribe(False) | 112 | """Retrieve the root information from syncdaemon.""" |
3572 | 112 | 113 | return self.proxy.get_root_dir() | |
3573 | 113 | 114 | ||
3574 | 114 | def udf_autosubscribe_enabled(): | 115 | def get_shares_dir(self): |
3575 | 115 | """Get the state of udf_autosubscribe in the syncdaemon.""" | 116 | """Retrieve the shares information from syncdaemon.""" |
3576 | 116 | return get_syncdaemon_tool().is_udf_autosubscribe_enabled() | 117 | return self.proxy.get_shares_dir() |
3577 | 117 | 118 | ||
3578 | 118 | 119 | def get_shares_dir_link(self): | |
3579 | 119 | def enable_udf_autosubscribe(): | 120 | """Retrieve the shares information from syncdaemon.""" |
3580 | 120 | """Enable udf_autosubscribe in the syncdaemon.""" | 121 | return self.proxy.get_shares_dir_link() |
3581 | 121 | return get_syncdaemon_tool().enable_udf_autosubscribe(True) | 122 | |
3582 | 122 | 123 | def get_folders(self): | |
3583 | 123 | 124 | """Retrieve the folders information from syncdaemon.""" | |
3584 | 124 | def disable_udf_autosubscribe(): | 125 | return self.proxy.get_folders() |
3585 | 125 | """Disable udf_autosubscribe in the syncdaemon.""" | 126 | |
3586 | 126 | return get_syncdaemon_tool().enable_udf_autosubscribe(False) | 127 | def create_folder(self, path): |
3587 | 127 | 128 | """Create a new folder through syncdaemon.""" | |
3588 | 128 | 129 | return self.proxy.create_folder(path) | |
3589 | 129 | def get_root_dir(): | 130 | |
3590 | 130 | """Retrieve the root information from syncdaemon.""" | 131 | def subscribe_folder(self, folder_id): |
3591 | 131 | return get_syncdaemon_tool().get_root_dir() | 132 | """Subscribe to 'folder_id'.""" |
3592 | 132 | 133 | return self.proxy.subscribe_folder(folder_id) | |
3593 | 133 | 134 | ||
3594 | 134 | def get_shares_dir(): | 135 | def unsubscribe_folder(self, folder_id): |
3595 | 135 | """Retrieve the shares information from syncdaemon.""" | 136 | """Unsubscribe 'folder_id'.""" |
3596 | 136 | return get_syncdaemon_tool().get_shares_dir() | 137 | return self.proxy.unsubscribe_folder(folder_id) |
3597 | 137 | 138 | ||
3598 | 138 | 139 | def get_shares(self): | |
3599 | 139 | def get_shares_dir_link(): | 140 | """Retrieve the shares information from syncdaemon.""" |
3600 | 140 | """Retrieve the shares information from syncdaemon.""" | 141 | return self.proxy.get_shares() |
3601 | 141 | return get_syncdaemon_tool().get_shares_dir_link() | 142 | |
3602 | 142 | 143 | def subscribe_share(self, share_id): | |
3603 | 143 | 144 | """Subscribe to 'share_id'.""" | |
3604 | 144 | def get_folders(): | 145 | return self.proxy.subscribe_share(share_id) |
3605 | 145 | """Retrieve the folders information from syncdaemon.""" | 146 | |
3606 | 146 | return get_syncdaemon_tool().get_folders() | 147 | def unsubscribe_share(self, share_id): |
3607 | 147 | 148 | """Unsubscribe 'share_id'.""" | |
3608 | 148 | 149 | return self.proxy.unsubscribe_share(share_id) | |
3609 | 149 | def create_folder(path): | 150 | |
3610 | 150 | """Create a new folder through syncdaemon.""" | 151 | def get_current_status(self): |
3611 | 151 | return get_syncdaemon_tool().create_folder(path) | 152 | """Retrieve the current status from syncdaemon.""" |
3612 | 152 | 153 | return self.proxy.get_status() | |
3613 | 153 | 154 | ||
3614 | 154 | def subscribe_folder(folder_id): | 155 | def file_sync_enabled(self): |
3615 | 155 | """Subscribe to 'folder_id'.""" | 156 | """Get if file sync service is enabled.""" |
3616 | 156 | return get_syncdaemon_tool().subscribe_folder(folder_id) | 157 | return self.proxy.is_files_sync_enabled() |
3617 | 157 | 158 | ||
3618 | 158 | 159 | def enable_file_sync(self): | |
3619 | 159 | def unsubscribe_folder(folder_id): | 160 | """Enable the file sync service.""" |
3620 | 160 | """Unsubscribe 'folder_id'.""" | 161 | return self.proxy.enable_files_sync(True) |
3621 | 161 | return get_syncdaemon_tool().unsubscribe_folder(folder_id) | 162 | |
3622 | 162 | 163 | def disable_file_sync(self): | |
3623 | 163 | 164 | """Enable the file sync service.""" | |
3624 | 164 | def get_shares(): | 165 | return self.proxy.enable_files_sync(False) |
3625 | 165 | """Retrieve the shares information from syncdaemon.""" | 166 | |
3626 | 166 | return get_syncdaemon_tool().get_shares() | 167 | def files_sync_enabled(self): |
3627 | 167 | 168 | """Get if file sync service is enabled.""" | |
3628 | 168 | 169 | warnings.warn('use file_sync_enabled instead', DeprecationWarning) | |
3629 | 169 | def subscribe_share(share_id): | 170 | return self.file_sync_enabled() |
3630 | 170 | """Subscribe to 'share_id'.""" | 171 | |
3631 | 171 | return get_syncdaemon_tool().subscribe_share(share_id) | 172 | def set_files_sync_enabled(self, enabled): |
3632 | 172 | 173 | """Set the file sync service to be 'enabled'.""" | |
3633 | 173 | 174 | warnings.warn('use {enable/disable}_file_sync instead', | |
3634 | 174 | def unsubscribe_share(share_id): | 175 | DeprecationWarning) |
3635 | 175 | """Unsubscribe 'share_id'.""" | 176 | if enabled: |
3636 | 176 | return get_syncdaemon_tool().unsubscribe_share(share_id) | 177 | return self.enable_file_sync() |
3637 | 177 | 178 | else: | |
3638 | 178 | 179 | return self.disable_file_sync() | |
3639 | 179 | def get_current_status(): | 180 | |
3640 | 180 | """Retrieve the current status from syncdaemon.""" | 181 | def connect_file_sync(self): |
3641 | 181 | return get_syncdaemon_tool().get_status() | 182 | """Connect the file sync service.""" |
3642 | 182 | 183 | return self.proxy.connect() | |
3643 | 183 | 184 | ||
3644 | 184 | def file_sync_enabled(): | 185 | def disconnect_file_sync(self): |
3645 | 185 | """Get if file sync service is enabled.""" | 186 | """Disconnect the file sync service.""" |
3646 | 186 | return get_syncdaemon_tool().is_files_sync_enabled() | 187 | return self.proxy.disconnect() |
3647 | 187 | 188 | ||
3648 | 188 | 189 | def start_file_sync(self): | |
3649 | 189 | def enable_file_sync(): | 190 | """Start the file sync service.""" |
3650 | 190 | """Enable the file sync service.""" | 191 | return self.proxy.start() |
3651 | 191 | return get_syncdaemon_tool().enable_files_sync(True) | 192 | |
3652 | 192 | 193 | def stop_file_sync(self): | |
3653 | 193 | 194 | """Stop the file sync service.""" | |
3654 | 194 | def disable_file_sync(): | 195 | return self.proxy.quit() |
3655 | 195 | """Enable the file sync service.""" | 196 | |
3656 | 196 | return get_syncdaemon_tool().enable_files_sync(False) | 197 | def set_status_changed_handler(self, handler): |
3449 | 197 | |||
3450 | 198 | |||
3451 | 199 | def files_sync_enabled(): | ||
3452 | 200 | """Get if file sync service is enabled.""" | ||
3453 | 201 | warnings.warn('use file_sync_enabled instead', DeprecationWarning) | ||
3454 | 202 | return file_sync_enabled() | ||
3455 | 203 | |||
3456 | 204 | |||
3457 | 205 | def set_files_sync_enabled(enabled): | ||
3458 | 206 | """Set the file sync service to be 'enabled'.""" | ||
3459 | 207 | warnings.warn('use {enable/disable}_file_sync instead', DeprecationWarning) | ||
3460 | 208 | if enabled: | ||
3461 | 209 | return enable_file_sync() | ||
3462 | 210 | else: | ||
3463 | 211 | return disable_file_sync() | ||
3464 | 212 | |||
3465 | 213 | |||
3466 | 214 | def connect_file_sync(): | ||
3467 | 215 | """Connect the file sync service.""" | ||
3468 | 216 | return get_syncdaemon_tool().connect() | ||
3469 | 217 | |||
3470 | 218 | |||
3471 | 219 | def disconnect_file_sync(): | ||
3472 | 220 | """Disconnect the file sync service.""" | ||
3473 | 221 | return get_syncdaemon_tool().disconnect() | ||
3474 | 222 | |||
3475 | 223 | |||
3476 | 224 | def start_file_sync(): | ||
3477 | 225 | """Start the file sync service.""" | ||
3478 | 226 | return get_syncdaemon_tool().start() | ||
3479 | 227 | |||
3480 | 228 | |||
3481 | 229 | def stop_file_sync(): | ||
3482 | 230 | """Stop the file sync service.""" | ||
3483 | 231 | return get_syncdaemon_tool().quit() | ||
3484 | 232 | |||
3485 | 233 | |||
3486 | 234 | if sys.platform.startswith("linux"): | ||
3487 | 235 | from ubuntuone.controlpanel.sd_client.linux \ | ||
3488 | 236 | import set_status_changed_handler | ||
3489 | 237 | else: | ||
3490 | 238 | |||
3491 | 239 | def set_status_changed_handler(handler): | ||
3657 | 240 | """Set the status handler function.""" | 198 | """Set the status handler function.""" |
3659 | 241 | return get_syncdaemon_tool().set_status_changed_handler(handler) | 199 | self.status_changed_handler = handler |
3660 | 200 | if sys.platform.startswith("linux"): | ||
3661 | 201 | # pylint: disable=W0404 | ||
3662 | 202 | from ubuntuone.controlpanel.sd_client import linux | ||
3663 | 203 | result = linux.set_status_changed_handler(handler) | ||
3664 | 204 | else: | ||
3665 | 205 | result = self.proxy.set_status_changed_handler(handler) | ||
3666 | 206 | return result | ||
3667 | 242 | 207 | ||
3668 | === modified file 'ubuntuone/controlpanel/tests/test_backend.py' | |||
3669 | --- ubuntuone/controlpanel/tests/test_backend.py 2011-07-22 21:26:48 +0000 | |||
3670 | +++ ubuntuone/controlpanel/tests/test_backend.py 2011-08-25 19:40:18 +0000 | |||
3671 | @@ -66,18 +66,33 @@ | |||
3672 | 66 | ) | 66 | ) |
3673 | 67 | 67 | ||
3674 | 68 | 68 | ||
3679 | 69 | # pylint: disable=E1101 | 69 | # pylint: disable=E1101, W0201, W0212 |
3680 | 70 | 70 | ||
3681 | 71 | 71 | ||
3682 | 72 | class MockWebClient(object): | 72 | class CallRecorder(object): |
3683 | 73 | """A class that records every call clients made to it.""" | ||
3684 | 74 | |||
3685 | 75 | def __init__(self): | ||
3686 | 76 | self._called = defaultdict(int) | ||
3687 | 77 | |||
3688 | 78 | def __getattribute__(self, attr_name): | ||
3689 | 79 | """Override to we can record calls to members.""" | ||
3690 | 80 | result = super(CallRecorder, self).__getattribute__(attr_name) | ||
3691 | 81 | if attr_name != '_called': | ||
3692 | 82 | called = super(CallRecorder, self).__getattribute__('_called') | ||
3693 | 83 | called[attr_name] += 1 | ||
3694 | 84 | return result | ||
3695 | 85 | |||
3696 | 86 | |||
3697 | 87 | class MockWebClient(CallRecorder): | ||
3698 | 73 | """A mock webclient.""" | 88 | """A mock webclient.""" |
3699 | 74 | 89 | ||
3700 | 75 | failure = False | ||
3701 | 76 | results = {} | ||
3702 | 77 | |||
3703 | 78 | def __init__(self, get_credentials): | 90 | def __init__(self, get_credentials): |
3704 | 79 | """Initialize this mock instance.""" | 91 | """Initialize this mock instance.""" |
3705 | 92 | super(MockWebClient, self).__init__() | ||
3706 | 80 | self.get_credentials = get_credentials | 93 | self.get_credentials = get_credentials |
3707 | 94 | self.failure = False | ||
3708 | 95 | self.results = {} | ||
3709 | 81 | 96 | ||
3710 | 82 | def call_api(self, method): | 97 | def call_api(self, method): |
3711 | 83 | """Get a given url from the webservice.""" | 98 | """Get a given url from the webservice.""" |
3712 | @@ -90,42 +105,48 @@ | |||
3713 | 90 | return defer.succeed(result) | 105 | return defer.succeed(result) |
3714 | 91 | 106 | ||
3715 | 92 | 107 | ||
3717 | 93 | class MockLoginClient(object): | 108 | class MockLoginClient(CallRecorder): |
3718 | 94 | """A mock login_client module.""" | 109 | """A mock login_client module.""" |
3719 | 95 | 110 | ||
3721 | 96 | creds = TOKEN | 111 | def __init__(self): |
3722 | 112 | """Initialize this mock instance.""" | ||
3723 | 113 | super(MockLoginClient, self).__init__() | ||
3724 | 114 | self.creds = TOKEN | ||
3725 | 97 | 115 | ||
3727 | 98 | def get_credentials(self): | 116 | def find_credentials(self): |
3728 | 99 | """Return the mock credentials.""" | 117 | """Return the mock credentials.""" |
3729 | 100 | return defer.succeed(self.creds) | 118 | return defer.succeed(self.creds) |
3730 | 101 | 119 | ||
3731 | 102 | def clear_credentials(self): | 120 | def clear_credentials(self): |
3732 | 103 | """Clear the mock credentials.""" | 121 | """Clear the mock credentials.""" |
3734 | 104 | MockLoginClient.creds = None | 122 | self.creds = None |
3735 | 105 | return defer.succeed(None) | 123 | return defer.succeed(None) |
3736 | 106 | 124 | ||
3737 | 107 | 125 | ||
3739 | 108 | class MockSDClient(object): | 126 | class MockSDClient(CallRecorder): |
3740 | 109 | """A mock sd_client module.""" | 127 | """A mock sd_client module.""" |
3741 | 110 | 128 | ||
3760 | 111 | throttling = False | 129 | def __init__(self): |
3761 | 112 | show_all_notifications = True | 130 | """Initialize this mock instance.""" |
3762 | 113 | autoconnect = True | 131 | super(MockSDClient, self).__init__() |
3763 | 114 | udf_autosubscribe = False | 132 | self.throttling = False |
3764 | 115 | share_autosubscribe = False | 133 | self.show_all_notifications = True |
3765 | 116 | limits = {"download": -1, "upload": -1} | 134 | self.autoconnect = True |
3766 | 117 | file_sync = True | 135 | self.udf_autosubscribe = False |
3767 | 118 | status = { | 136 | self.share_autosubscribe = False |
3768 | 119 | 'name': 'TEST', 'queues': 'GORGEOUS', 'connection': '', | 137 | self.limits = {"download": -1, "upload": -1} |
3769 | 120 | 'description': 'Some test state, nothing else.', | 138 | self.file_sync = True |
3770 | 121 | 'is_error': '', 'is_connected': 'True', 'is_online': '', | 139 | self.status = { |
3771 | 122 | } | 140 | 'name': 'TEST', 'queues': 'GORGEOUS', 'connection': '', |
3772 | 123 | status_changed_handler = None | 141 | 'description': 'Some test state, nothing else.', |
3773 | 124 | subscribed_folders = [] | 142 | 'is_error': '', 'is_connected': 'True', 'is_online': '', |
3774 | 125 | subscribed_shares = [] | 143 | } |
3775 | 126 | actions = [] | 144 | self.status_changed_handler = None |
3776 | 127 | shares = [] | 145 | self.subscribed_folders = [] |
3777 | 128 | folders = [] | 146 | self.subscribed_shares = [] |
3778 | 147 | self.actions = [] | ||
3779 | 148 | self.shares = [] | ||
3780 | 149 | self.folders = [] | ||
3781 | 129 | 150 | ||
3782 | 130 | def get_throttling_limits(self): | 151 | def get_throttling_limits(self): |
3783 | 131 | """Return the sample speed limits.""" | 152 | """Return the sample speed limits.""" |
3784 | @@ -198,27 +219,27 @@ | |||
3785 | 198 | 219 | ||
3786 | 199 | def files_sync_enabled(self): | 220 | def files_sync_enabled(self): |
3787 | 200 | """Get if file sync service is enabled.""" | 221 | """Get if file sync service is enabled.""" |
3789 | 201 | return MockSDClient.file_sync | 222 | return self.file_sync |
3790 | 202 | 223 | ||
3791 | 203 | def set_files_sync_enabled(self, enabled): | 224 | def set_files_sync_enabled(self, enabled): |
3792 | 204 | """Set the file sync service to be 'enabled'.""" | 225 | """Set the file sync service to be 'enabled'.""" |
3794 | 205 | MockSDClient.file_sync = enabled | 226 | self.file_sync = enabled |
3795 | 206 | 227 | ||
3796 | 207 | def connect_file_sync(self): | 228 | def connect_file_sync(self): |
3797 | 208 | """Connect files service.""" | 229 | """Connect files service.""" |
3799 | 209 | MockSDClient.actions.append('connect') | 230 | self.actions.append('connect') |
3800 | 210 | 231 | ||
3801 | 211 | def disconnect_file_sync(self): | 232 | def disconnect_file_sync(self): |
3802 | 212 | """Disconnect file_sync service.""" | 233 | """Disconnect file_sync service.""" |
3804 | 213 | MockSDClient.actions.append('disconnect') | 234 | self.actions.append('disconnect') |
3805 | 214 | 235 | ||
3806 | 215 | def start_file_sync(self): | 236 | def start_file_sync(self): |
3807 | 216 | """Start the file_sync service.""" | 237 | """Start the file_sync service.""" |
3809 | 217 | MockSDClient.actions.append('start') | 238 | self.actions.append('start') |
3810 | 218 | 239 | ||
3811 | 219 | def stop_file_sync(self): | 240 | def stop_file_sync(self): |
3812 | 220 | """Stop the file_sync service.""" | 241 | """Stop the file_sync service.""" |
3814 | 221 | MockSDClient.actions.append('stop') | 242 | self.actions.append('stop') |
3815 | 222 | 243 | ||
3816 | 223 | def get_root_dir(self): | 244 | def get_root_dir(self): |
3817 | 224 | """Grab the root dir.""" | 245 | """Grab the root dir.""" |
3818 | @@ -234,31 +255,31 @@ | |||
3819 | 234 | 255 | ||
3820 | 235 | def get_folders(self): | 256 | def get_folders(self): |
3821 | 236 | """Grab list of folders.""" | 257 | """Grab list of folders.""" |
3823 | 237 | return MockSDClient.folders | 258 | return self.folders |
3824 | 238 | 259 | ||
3825 | 239 | def subscribe_folder(self, volume_id): | 260 | def subscribe_folder(self, volume_id): |
3826 | 240 | """Subcribe to 'volume_id'.""" | 261 | """Subcribe to 'volume_id'.""" |
3828 | 241 | MockSDClient.subscribed_folders.append(volume_id) | 262 | self.subscribed_folders.append(volume_id) |
3829 | 242 | 263 | ||
3830 | 243 | def unsubscribe_folder(self, volume_id): | 264 | def unsubscribe_folder(self, volume_id): |
3831 | 244 | """Unsubcribe from 'volume_id'.""" | 265 | """Unsubcribe from 'volume_id'.""" |
3833 | 245 | MockSDClient.subscribed_folders.remove(volume_id) | 266 | self.subscribed_folders.remove(volume_id) |
3834 | 246 | 267 | ||
3835 | 247 | def create_folder(self, path): | 268 | def create_folder(self, path): |
3836 | 248 | """Grab list of folders.""" | 269 | """Grab list of folders.""" |
3838 | 249 | MockSDClient.folders.append(path) | 270 | self.folders.append(path) |
3839 | 250 | 271 | ||
3840 | 251 | def get_shares(self): | 272 | def get_shares(self): |
3841 | 252 | """Grab list of shares.""" | 273 | """Grab list of shares.""" |
3843 | 253 | return MockSDClient.shares | 274 | return self.shares |
3844 | 254 | 275 | ||
3845 | 255 | def subscribe_share(self, volume_id): | 276 | def subscribe_share(self, volume_id): |
3846 | 256 | """Subcribe to 'volume_id'.""" | 277 | """Subcribe to 'volume_id'.""" |
3848 | 257 | MockSDClient.subscribed_shares.append(volume_id) | 278 | self.subscribed_shares.append(volume_id) |
3849 | 258 | 279 | ||
3850 | 259 | def unsubscribe_share(self, volume_id): | 280 | def unsubscribe_share(self, volume_id): |
3851 | 260 | """Unsubcribe from 'volume_id'.""" | 281 | """Unsubcribe from 'volume_id'.""" |
3853 | 261 | MockSDClient.subscribed_shares.remove(volume_id) | 282 | self.subscribed_shares.remove(volume_id) |
3854 | 262 | 283 | ||
3855 | 263 | def get_current_status(self): | 284 | def get_current_status(self): |
3856 | 264 | """Grab syncdaemon status.""" | 285 | """Grab syncdaemon status.""" |
3857 | @@ -273,7 +294,7 @@ | |||
3858 | 273 | return SAMPLE_SHARED | 294 | return SAMPLE_SHARED |
3859 | 274 | 295 | ||
3860 | 275 | 296 | ||
3862 | 276 | class MockReplicationClient(object): | 297 | class MockReplicationClient(CallRecorder): |
3863 | 277 | """A mock replication_client module.""" | 298 | """A mock replication_client module.""" |
3864 | 278 | 299 | ||
3865 | 279 | BOOKMARKS = 'awesome' | 300 | BOOKMARKS = 'awesome' |
3866 | @@ -311,21 +332,22 @@ | |||
3867 | 311 | def setUp(self): | 332 | def setUp(self): |
3868 | 312 | super(BackendBasicTestCase, self).setUp() | 333 | super(BackendBasicTestCase, self).setUp() |
3869 | 313 | self.patch(backend, "web_client_factory", MockWebClient) | 334 | self.patch(backend, "web_client_factory", MockWebClient) |
3872 | 314 | self.patch(backend, "login_client", MockLoginClient()) | 335 | self.patch(backend, "CredentialsManagementTool", MockLoginClient) |
3873 | 315 | self.patch(backend, "sd_client", MockSDClient()) | 336 | self.patch(backend.sd_client, "SyncDaemonClient", MockSDClient) |
3874 | 316 | self.patch(backend, "replication_client", MockReplicationClient()) | 337 | self.patch(backend, "replication_client", MockReplicationClient()) |
3875 | 338 | |||
3876 | 317 | self.local_token = DEVICE_TYPE_COMPUTER + TOKEN["token"] | 339 | self.local_token = DEVICE_TYPE_COMPUTER + TOKEN["token"] |
3877 | 318 | self.be = backend.ControlBackend() | 340 | self.be = backend.ControlBackend() |
3878 | 341 | self.be.wc.failure = False | ||
3879 | 319 | 342 | ||
3880 | 320 | self.memento = MementoHandler() | 343 | self.memento = MementoHandler() |
3881 | 321 | backend.logger.addHandler(self.memento) | 344 | backend.logger.addHandler(self.memento) |
3882 | 322 | 345 | ||
3883 | 323 | MockLoginClient.creds = TOKEN | ||
3884 | 324 | MockWebClient.failure = None | ||
3885 | 325 | |||
3886 | 326 | def test_backend_creation(self): | 346 | def test_backend_creation(self): |
3887 | 327 | """The backend instance is successfully created.""" | 347 | """The backend instance is successfully created.""" |
3889 | 328 | self.assertEqual(self.be.wc.__class__, MockWebClient) | 348 | self.assertIsInstance(self.be.wc, MockWebClient) |
3890 | 349 | self.assertIsInstance(self.be.login_client, MockLoginClient) | ||
3891 | 350 | self.assertIsInstance(self.be.sd_client, MockSDClient) | ||
3892 | 329 | 351 | ||
3893 | 330 | @inlineCallbacks | 352 | @inlineCallbacks |
3894 | 331 | def test_get_token(self): | 353 | def test_get_token(self): |
3895 | @@ -361,6 +383,22 @@ | |||
3896 | 361 | self.be.shutdown() | 383 | self.be.shutdown() |
3897 | 362 | # nothing explodes | 384 | # nothing explodes |
3898 | 363 | 385 | ||
3899 | 386 | @inlineCallbacks | ||
3900 | 387 | def test_credentials_are_cached(self): | ||
3901 | 388 | """The credentials are cached.""" | ||
3902 | 389 | creds1 = yield self.be.get_credentials() | ||
3903 | 390 | creds2 = yield self.be.get_credentials() | ||
3904 | 391 | self.assertEqual(creds1, creds2) | ||
3905 | 392 | self.assertEqual(self.be.login_client._called['find_credentials'], 1) | ||
3906 | 393 | |||
3907 | 394 | def test_login_client_is_cached(self): | ||
3908 | 395 | """The login_client instance is cached.""" | ||
3909 | 396 | self.assertIs(self.be.login_client, self.be.login_client) | ||
3910 | 397 | |||
3911 | 398 | def test_sd_client_is_cached(self): | ||
3912 | 399 | """The sd_client instance is cached.""" | ||
3913 | 400 | self.assertIs(self.be.sd_client, self.be.sd_client) | ||
3914 | 401 | |||
3915 | 364 | 402 | ||
3916 | 365 | class BackendAccountTestCase(BackendBasicTestCase): | 403 | class BackendAccountTestCase(BackendBasicTestCase): |
3917 | 366 | """Account tests for the backend.""" | 404 | """Account tests for the backend.""" |
3918 | @@ -384,16 +422,16 @@ | |||
3919 | 384 | @inlineCallbacks | 422 | @inlineCallbacks |
3920 | 385 | def test_account_info_fails(self): | 423 | def test_account_info_fails(self): |
3921 | 386 | """The account_info method exercises its errback.""" | 424 | """The account_info method exercises its errback.""" |
3923 | 387 | MockWebClient.failure = 404 | 425 | self.be.wc.failure = 404 |
3924 | 388 | yield self.assertFailure(self.be.account_info(), | 426 | yield self.assertFailure(self.be.account_info(), |
3925 | 389 | backend.WebClientError) | 427 | backend.WebClientError) |
3926 | 390 | 428 | ||
3927 | 391 | @inlineCallbacks | 429 | @inlineCallbacks |
3928 | 392 | def test_account_info_fails_with_unauthorized(self): | 430 | def test_account_info_fails_with_unauthorized(self): |
3929 | 393 | """The account_info clears the credentials on unauthorized.""" | 431 | """The account_info clears the credentials on unauthorized.""" |
3931 | 394 | MockWebClient.failure = 401 | 432 | self.be.wc.failure = 401 |
3932 | 395 | d = defer.Deferred() | 433 | d = defer.Deferred() |
3934 | 396 | self.patch(backend.login_client, 'clear_credentials', | 434 | self.patch(self.be.login_client, 'clear_credentials', |
3935 | 397 | lambda: d.callback('called')) | 435 | lambda: d.callback('called')) |
3936 | 398 | yield self.assertFailure(self.be.account_info(), | 436 | yield self.assertFailure(self.be.account_info(), |
3937 | 399 | backend.UnauthorizedError) | 437 | backend.UnauthorizedError) |
3938 | @@ -423,7 +461,7 @@ | |||
3939 | 423 | @inlineCallbacks | 461 | @inlineCallbacks |
3940 | 424 | def test_devices_info_with_webclient_error(self): | 462 | def test_devices_info_with_webclient_error(self): |
3941 | 425 | """The devices_info returns local info if webclient error.""" | 463 | """The devices_info returns local info if webclient error.""" |
3943 | 426 | MockWebClient.failure = 404 | 464 | self.be.wc.failure = 404 |
3944 | 427 | result = yield self.be.devices_info() | 465 | result = yield self.be.devices_info() |
3945 | 428 | 466 | ||
3946 | 429 | self.assertEqual(result, [LOCAL_DEVICE]) | 467 | self.assertEqual(result, [LOCAL_DEVICE]) |
3947 | @@ -433,9 +471,9 @@ | |||
3948 | 433 | @inlineCallbacks | 471 | @inlineCallbacks |
3949 | 434 | def test_devices_info_fails_with_unauthorized(self): | 472 | def test_devices_info_fails_with_unauthorized(self): |
3950 | 435 | """The devices_info clears the credentials on unauthorized.""" | 473 | """The devices_info clears the credentials on unauthorized.""" |
3952 | 436 | MockWebClient.failure = 401 | 474 | self.be.wc.failure = 401 |
3953 | 437 | d = defer.Deferred() | 475 | d = defer.Deferred() |
3955 | 438 | self.patch(backend.login_client, 'clear_credentials', | 476 | self.patch(self.be.login_client, 'clear_credentials', |
3956 | 439 | lambda: d.callback('called')) | 477 | lambda: d.callback('called')) |
3957 | 440 | yield self.assertFailure(self.be.devices_info(), | 478 | yield self.assertFailure(self.be.devices_info(), |
3958 | 441 | backend.UnauthorizedError) | 479 | backend.UnauthorizedError) |
3959 | @@ -446,13 +484,14 @@ | |||
3960 | 446 | """The devices_info returns device only info if files is disabled.""" | 484 | """The devices_info returns device only info if files is disabled.""" |
3961 | 447 | yield self.be.disable_files() | 485 | yield self.be.disable_files() |
3962 | 448 | status = yield self.be.file_sync_status() | 486 | status = yield self.be.file_sync_status() |
3964 | 449 | assert status['status'] == backend.FILE_SYNC_DISABLED, status | 487 | assert status['status'] == backend.FILE_SYNC_DISABLED |
3965 | 450 | 488 | ||
3966 | 451 | self.be.wc.results[DEVICES_API] = SAMPLE_DEVICES_JSON | 489 | self.be.wc.results[DEVICES_API] = SAMPLE_DEVICES_JSON |
3967 | 452 | result = yield self.be.devices_info() | 490 | result = yield self.be.devices_info() |
3968 | 453 | 491 | ||
3971 | 454 | expected = EXPECTED_DEVICES_INFO[:] | 492 | expected = [] |
3972 | 455 | for device in expected: | 493 | for device in EXPECTED_DEVICES_INFO: |
3973 | 494 | device = device.copy() | ||
3974 | 456 | device.pop('limit_bandwidth', None) | 495 | device.pop('limit_bandwidth', None) |
3975 | 457 | device.pop(backend.DOWNLOAD_KEY, None) | 496 | device.pop(backend.DOWNLOAD_KEY, None) |
3976 | 458 | device.pop(backend.UPLOAD_KEY, None) | 497 | device.pop(backend.UPLOAD_KEY, None) |
3977 | @@ -461,6 +500,7 @@ | |||
3978 | 461 | device.pop(backend.SHARE_AUTOSUBSCRIBE_KEY, None) | 500 | device.pop(backend.SHARE_AUTOSUBSCRIBE_KEY, None) |
3979 | 462 | device.pop(backend.UDF_AUTOSUBSCRIBE_KEY, None) | 501 | device.pop(backend.UDF_AUTOSUBSCRIBE_KEY, None) |
3980 | 463 | device['configurable'] = False | 502 | device['configurable'] = False |
3981 | 503 | expected.append(device) | ||
3982 | 464 | self.assertEqual(result, expected) | 504 | self.assertEqual(result, expected) |
3983 | 465 | 505 | ||
3984 | 466 | @inlineCallbacks | 506 | @inlineCallbacks |
3985 | @@ -506,7 +546,7 @@ | |||
3986 | 506 | @inlineCallbacks | 546 | @inlineCallbacks |
3987 | 507 | def test_device_names_info_with_webclient_error(self): | 547 | def test_device_names_info_with_webclient_error(self): |
3988 | 508 | """The device_names_info returns local info if webclient error.""" | 548 | """The device_names_info returns local info if webclient error.""" |
3990 | 509 | MockWebClient.failure = 404 | 549 | self.be.wc.failure = 404 |
3991 | 510 | result = yield self.be.device_names_info() | 550 | result = yield self.be.device_names_info() |
3992 | 511 | 551 | ||
3993 | 512 | device = LOCAL_DEVICE.copy() | 552 | device = LOCAL_DEVICE.copy() |
3994 | @@ -525,9 +565,9 @@ | |||
3995 | 525 | @inlineCallbacks | 565 | @inlineCallbacks |
3996 | 526 | def test_device_names_info_fails_with_unauthorized(self): | 566 | def test_device_names_info_fails_with_unauthorized(self): |
3997 | 527 | """The device_names_info clears the credentials on unauthorized.""" | 567 | """The device_names_info clears the credentials on unauthorized.""" |
3999 | 528 | MockWebClient.failure = 401 | 568 | self.be.wc.failure = 401 |
4000 | 529 | d = defer.Deferred() | 569 | d = defer.Deferred() |
4002 | 530 | self.patch(backend.login_client, 'clear_credentials', | 570 | self.patch(self.be.login_client, 'clear_credentials', |
4003 | 531 | lambda: d.callback('called')) | 571 | lambda: d.callback('called')) |
4004 | 532 | yield self.assertFailure(self.be.device_names_info(), | 572 | yield self.assertFailure(self.be.device_names_info(), |
4005 | 533 | backend.UnauthorizedError) | 573 | backend.UnauthorizedError) |
4006 | @@ -565,7 +605,7 @@ | |||
4007 | 565 | result = yield self.be.remove_device(device_id) | 605 | result = yield self.be.remove_device(device_id) |
4008 | 566 | self.assertEqual(result, device_id) | 606 | self.assertEqual(result, device_id) |
4009 | 567 | # credentials were not cleared | 607 | # credentials were not cleared |
4011 | 568 | self.assertEqual(MockLoginClient.creds, TOKEN) | 608 | self.assertEqual(self.be.login_client.creds, TOKEN) |
4012 | 569 | 609 | ||
4013 | 570 | @inlineCallbacks | 610 | @inlineCallbacks |
4014 | 571 | def test_remove_device_clear_credentials_if_local_device(self): | 611 | def test_remove_device_clear_credentials_if_local_device(self): |
4015 | @@ -574,21 +614,21 @@ | |||
4016 | 574 | self.be.wc.results[apiurl] = SAMPLE_DEVICES_JSON | 614 | self.be.wc.results[apiurl] = SAMPLE_DEVICES_JSON |
4017 | 575 | yield self.be.remove_device(self.local_token) | 615 | yield self.be.remove_device(self.local_token) |
4018 | 576 | # credentials were cleared | 616 | # credentials were cleared |
4020 | 577 | self.assertEqual(MockLoginClient.creds, None) | 617 | self.assertEqual(self.be.login_client.creds, None) |
4021 | 578 | 618 | ||
4022 | 579 | @inlineCallbacks | 619 | @inlineCallbacks |
4023 | 580 | def test_remove_device_fails(self): | 620 | def test_remove_device_fails(self): |
4024 | 581 | """The remove_device method fails as expected.""" | 621 | """The remove_device method fails as expected.""" |
4026 | 582 | MockWebClient.failure = 404 | 622 | self.be.wc.failure = 404 |
4027 | 583 | yield self.assertFailure(self.be.remove_device(self.local_token), | 623 | yield self.assertFailure(self.be.remove_device(self.local_token), |
4028 | 584 | backend.WebClientError) | 624 | backend.WebClientError) |
4029 | 585 | 625 | ||
4030 | 586 | @inlineCallbacks | 626 | @inlineCallbacks |
4031 | 587 | def test_remove_device_fails_with_unauthorized(self): | 627 | def test_remove_device_fails_with_unauthorized(self): |
4032 | 588 | """The remove_device clears the credentials on unauthorized.""" | 628 | """The remove_device clears the credentials on unauthorized.""" |
4034 | 589 | MockWebClient.failure = 401 | 629 | self.be.wc.failure = 401 |
4035 | 590 | d = defer.Deferred() | 630 | d = defer.Deferred() |
4037 | 591 | self.patch(backend.login_client, 'clear_credentials', | 631 | self.patch(self.be.login_client, 'clear_credentials', |
4038 | 592 | lambda: d.callback('called')) | 632 | lambda: d.callback('called')) |
4039 | 593 | yield self.assertFailure(self.be.remove_device(self.local_token), | 633 | yield self.assertFailure(self.be.remove_device(self.local_token), |
4040 | 594 | backend.UnauthorizedError) | 634 | backend.UnauthorizedError) |
4041 | @@ -598,6 +638,8 @@ | |||
4042 | 598 | def test_remove_device_does_not_log_device_id(self): | 638 | def test_remove_device_does_not_log_device_id(self): |
4043 | 599 | """The remove_device does not log the device_id.""" | 639 | """The remove_device does not log the device_id.""" |
4044 | 600 | device_id = DEVICE_TYPE_COMPUTER + TOKEN['token'] | 640 | device_id = DEVICE_TYPE_COMPUTER + TOKEN['token'] |
4045 | 641 | apiurl = DEVICE_REMOVE_API % ('computer', TOKEN['token']) | ||
4046 | 642 | self.be.wc.results[apiurl] = SAMPLE_DEVICES_JSON | ||
4047 | 601 | yield self.be.remove_device(device_id) | 643 | yield self.be.remove_device(device_id) |
4048 | 602 | 644 | ||
4049 | 603 | device_id_logged = all(device_id not in r.getMessage() | 645 | device_id_logged = all(device_id not in r.getMessage() |
4050 | @@ -607,57 +649,57 @@ | |||
4051 | 607 | @inlineCallbacks | 649 | @inlineCallbacks |
4052 | 608 | def test_change_show_all_notifications(self): | 650 | def test_change_show_all_notifications(self): |
4053 | 609 | """The device settings are updated.""" | 651 | """The device settings are updated.""" |
4055 | 610 | backend.sd_client.show_all_notifications = False | 652 | self.be.sd_client.show_all_notifications = False |
4056 | 611 | yield self.be.change_device_settings(self.local_token, | 653 | yield self.be.change_device_settings(self.local_token, |
4057 | 612 | {backend.SHOW_ALL_NOTIFICATIONS_KEY: True}) | 654 | {backend.SHOW_ALL_NOTIFICATIONS_KEY: True}) |
4059 | 613 | self.assertEqual(backend.sd_client.show_all_notifications, True) | 655 | self.assertEqual(self.be.sd_client.show_all_notifications, True) |
4060 | 614 | yield self.be.change_device_settings(self.local_token, | 656 | yield self.be.change_device_settings(self.local_token, |
4061 | 615 | {backend.SHOW_ALL_NOTIFICATIONS_KEY: False}) | 657 | {backend.SHOW_ALL_NOTIFICATIONS_KEY: False}) |
4063 | 616 | self.assertEqual(backend.sd_client.show_all_notifications, False) | 658 | self.assertEqual(self.be.sd_client.show_all_notifications, False) |
4064 | 617 | 659 | ||
4065 | 618 | @inlineCallbacks | 660 | @inlineCallbacks |
4066 | 619 | def test_change_limit_bandwidth(self): | 661 | def test_change_limit_bandwidth(self): |
4067 | 620 | """The device settings are updated.""" | 662 | """The device settings are updated.""" |
4069 | 621 | backend.sd_client.throttling = False | 663 | self.be.sd_client.throttling = False |
4070 | 622 | yield self.be.change_device_settings(self.local_token, | 664 | yield self.be.change_device_settings(self.local_token, |
4071 | 623 | {backend.LIMIT_BW_KEY: True}) | 665 | {backend.LIMIT_BW_KEY: True}) |
4073 | 624 | self.assertEqual(backend.sd_client.throttling, True) | 666 | self.assertEqual(self.be.sd_client.throttling, True) |
4074 | 625 | yield self.be.change_device_settings(self.local_token, | 667 | yield self.be.change_device_settings(self.local_token, |
4075 | 626 | {backend.LIMIT_BW_KEY: False}) | 668 | {backend.LIMIT_BW_KEY: False}) |
4077 | 627 | self.assertEqual(backend.sd_client.throttling, False) | 669 | self.assertEqual(self.be.sd_client.throttling, False) |
4078 | 628 | 670 | ||
4079 | 629 | @inlineCallbacks | 671 | @inlineCallbacks |
4080 | 630 | def test_change_upload_speed_limit(self): | 672 | def test_change_upload_speed_limit(self): |
4081 | 631 | """The device settings are updated.""" | 673 | """The device settings are updated.""" |
4083 | 632 | backend.sd_client.limits = {"download": -1, "upload": -1} | 674 | self.be.sd_client.limits = {"download": -1, "upload": -1} |
4084 | 633 | yield self.be.change_device_settings(self.local_token, | 675 | yield self.be.change_device_settings(self.local_token, |
4085 | 634 | {backend.UPLOAD_KEY: 1111}) | 676 | {backend.UPLOAD_KEY: 1111}) |
4088 | 635 | self.assertEqual(backend.sd_client.limits["upload"], 1111) | 677 | self.assertEqual(self.be.sd_client.limits["upload"], 1111) |
4089 | 636 | self.assertEqual(backend.sd_client.limits["download"], -1) | 678 | self.assertEqual(self.be.sd_client.limits["download"], -1) |
4090 | 637 | 679 | ||
4091 | 638 | @inlineCallbacks | 680 | @inlineCallbacks |
4092 | 639 | def test_change_download_speed_limit(self): | 681 | def test_change_download_speed_limit(self): |
4093 | 640 | """The device settings are updated.""" | 682 | """The device settings are updated.""" |
4095 | 641 | backend.sd_client.limits = {"download": -1, "upload": -1} | 683 | self.be.sd_client.limits = {"download": -1, "upload": -1} |
4096 | 642 | yield self.be.change_device_settings(self.local_token, | 684 | yield self.be.change_device_settings(self.local_token, |
4097 | 643 | {backend.DOWNLOAD_KEY: 99}) | 685 | {backend.DOWNLOAD_KEY: 99}) |
4100 | 644 | self.assertEqual(backend.sd_client.limits["upload"], -1) | 686 | self.assertEqual(self.be.sd_client.limits["upload"], -1) |
4101 | 645 | self.assertEqual(backend.sd_client.limits["download"], 99) | 687 | self.assertEqual(self.be.sd_client.limits["download"], 99) |
4102 | 646 | 688 | ||
4103 | 647 | @inlineCallbacks | 689 | @inlineCallbacks |
4104 | 648 | def test_changing_settings_for_wrong_id_has_no_effect(self): | 690 | def test_changing_settings_for_wrong_id_has_no_effect(self): |
4105 | 649 | """If the id is wrong, no settings are changed.""" | 691 | """If the id is wrong, no settings are changed.""" |
4108 | 650 | backend.sd_client.throttling = False | 692 | self.be.sd_client.throttling = False |
4109 | 651 | backend.sd_client.limits = {"download": -1, "upload": -1} | 693 | self.be.sd_client.limits = {"download": -1, "upload": -1} |
4110 | 652 | new_settings = { | 694 | new_settings = { |
4111 | 653 | backend.DOWNLOAD_KEY: 99, | 695 | backend.DOWNLOAD_KEY: 99, |
4112 | 654 | backend.UPLOAD_KEY: 99, | 696 | backend.UPLOAD_KEY: 99, |
4113 | 655 | backend.LIMIT_BW_KEY: True, | 697 | backend.LIMIT_BW_KEY: True, |
4114 | 656 | } | 698 | } |
4115 | 657 | yield self.be.change_device_settings("wrong token!", new_settings) | 699 | yield self.be.change_device_settings("wrong token!", new_settings) |
4119 | 658 | self.assertEqual(backend.sd_client.throttling, False) | 700 | self.assertEqual(self.be.sd_client.throttling, False) |
4120 | 659 | self.assertEqual(backend.sd_client.limits["upload"], -1) | 701 | self.assertEqual(self.be.sd_client.limits["upload"], -1) |
4121 | 660 | self.assertEqual(backend.sd_client.limits["download"], -1) | 702 | self.assertEqual(self.be.sd_client.limits["download"], -1) |
4122 | 661 | 703 | ||
4123 | 662 | @inlineCallbacks | 704 | @inlineCallbacks |
4124 | 663 | def test_changing_settings_does_not_log_device_id(self): | 705 | def test_changing_settings_does_not_log_device_id(self): |
4125 | @@ -674,7 +716,6 @@ | |||
4126 | 674 | """Volumes tests for the backend.""" | 716 | """Volumes tests for the backend.""" |
4127 | 675 | 717 | ||
4128 | 676 | # Access to a protected member of a client class | 718 | # Access to a protected member of a client class |
4129 | 677 | # pylint: disable=W0212 | ||
4130 | 678 | 719 | ||
4131 | 679 | def setUp(self): | 720 | def setUp(self): |
4132 | 680 | super(BackendVolumesTestCase, self).setUp() | 721 | super(BackendVolumesTestCase, self).setUp() |
4133 | @@ -753,8 +794,8 @@ | |||
4134 | 753 | @inlineCallbacks | 794 | @inlineCallbacks |
4135 | 754 | def test_volumes_info(self): | 795 | def test_volumes_info(self): |
4136 | 755 | """The volumes_info method exercises its callback.""" | 796 | """The volumes_info method exercises its callback.""" |
4139 | 756 | self.patch(MockSDClient, 'shares', SAMPLE_SHARES) | 797 | self.patch(self.be.sd_client, 'shares', SAMPLE_SHARES) |
4140 | 757 | self.patch(MockSDClient, 'folders', SAMPLE_FOLDERS) | 798 | self.patch(self.be.sd_client, 'folders', SAMPLE_FOLDERS) |
4141 | 758 | 799 | ||
4142 | 759 | expected = yield self.expected_volumes(SAMPLE_SHARES, SAMPLE_FOLDERS) | 800 | expected = yield self.expected_volumes(SAMPLE_SHARES, SAMPLE_FOLDERS) |
4143 | 760 | result = yield self.be.volumes_info() | 801 | result = yield self.be.volumes_info() |
4144 | @@ -763,16 +804,14 @@ | |||
4145 | 763 | @inlineCallbacks | 804 | @inlineCallbacks |
4146 | 764 | def test_volumes_info_without_storage_info(self): | 805 | def test_volumes_info_without_storage_info(self): |
4147 | 765 | """The volumes_info method exercises its callback.""" | 806 | """The volumes_info method exercises its callback.""" |
4150 | 766 | self.patch(MockSDClient, 'shares', SAMPLE_SHARES) | 807 | self.patch(self.be.sd_client, 'shares', SAMPLE_SHARES) |
4151 | 767 | self.patch(MockSDClient, 'folders', SAMPLE_FOLDERS) | 808 | self.patch(self.be.sd_client, 'folders', SAMPLE_FOLDERS) |
4152 | 768 | 809 | ||
4153 | 769 | expected = yield self.expected_volumes(SAMPLE_SHARES, SAMPLE_FOLDERS, | 810 | expected = yield self.expected_volumes(SAMPLE_SHARES, SAMPLE_FOLDERS, |
4154 | 770 | with_storage_info=False) | 811 | with_storage_info=False) |
4155 | 771 | result = yield self.be.volumes_info(with_storage_info=False) | 812 | result = yield self.be.volumes_info(with_storage_info=False) |
4156 | 772 | self.assertEqual(result, expected) | 813 | self.assertEqual(result, expected) |
4157 | 773 | 814 | ||
4158 | 774 | # pylint: disable=W0212 | ||
4159 | 775 | |||
4160 | 776 | def test_cached_volumes_are_initially_empty(self): | 815 | def test_cached_volumes_are_initially_empty(self): |
4161 | 777 | """The cached volume list is empty.""" | 816 | """The cached volume list is empty.""" |
4162 | 778 | self.assertEqual(self.be._volumes, {}) | 817 | self.assertEqual(self.be._volumes, {}) |
4163 | @@ -780,8 +819,8 @@ | |||
4164 | 780 | @inlineCallbacks | 819 | @inlineCallbacks |
4165 | 781 | def test_volumes_are_cached(self): | 820 | def test_volumes_are_cached(self): |
4166 | 782 | """The volume list is cached.""" | 821 | """The volume list is cached.""" |
4169 | 783 | self.patch(MockSDClient, 'shares', SAMPLE_SHARES) | 822 | self.patch(self.be.sd_client, 'shares', SAMPLE_SHARES) |
4170 | 784 | self.patch(MockSDClient, 'folders', SAMPLE_FOLDERS) | 823 | self.patch(self.be.sd_client, 'folders', SAMPLE_FOLDERS) |
4171 | 785 | 824 | ||
4172 | 786 | expected = {} | 825 | expected = {} |
4173 | 787 | info = yield self.expected_volumes(SAMPLE_SHARES, SAMPLE_FOLDERS) | 826 | info = yield self.expected_volumes(SAMPLE_SHARES, SAMPLE_FOLDERS) |
4174 | @@ -832,8 +871,8 @@ | |||
4175 | 832 | u'volume_id': u'7d130dfe-98b2-4bd5-8708-9eeba9838ac0'}, | 871 | u'volume_id': u'7d130dfe-98b2-4bd5-8708-9eeba9838ac0'}, |
4176 | 833 | ] | 872 | ] |
4177 | 834 | 873 | ||
4180 | 835 | self.patch(MockSDClient, 'shares', read_only_shares) | 874 | self.patch(self.be.sd_client, 'shares', read_only_shares) |
4181 | 836 | self.patch(MockSDClient, 'folders', SAMPLE_FOLDERS) | 875 | self.patch(self.be.sd_client, 'folders', SAMPLE_FOLDERS) |
4182 | 837 | 876 | ||
4183 | 838 | expected = yield self.expected_volumes(read_only_shares, | 877 | expected = yield self.expected_volumes(read_only_shares, |
4184 | 839 | SAMPLE_FOLDERS) | 878 | SAMPLE_FOLDERS) |
4185 | @@ -843,9 +882,9 @@ | |||
4186 | 843 | @inlineCallbacks | 882 | @inlineCallbacks |
4187 | 844 | def test_volumes_info_no_quota_for_root(self): | 883 | def test_volumes_info_no_quota_for_root(self): |
4188 | 845 | """The volumes_info returns info even if quota call fails.""" | 884 | """The volumes_info returns info even if quota call fails.""" |
4192 | 846 | MockWebClient.failure = 500 | 885 | self.be.wc.failure = 500 |
4193 | 847 | self.patch(MockSDClient, 'shares', SAMPLE_SHARES) | 886 | self.patch(self.be.sd_client, 'shares', SAMPLE_SHARES) |
4194 | 848 | self.patch(MockSDClient, 'folders', SAMPLE_FOLDERS) | 887 | self.patch(self.be.sd_client, 'folders', SAMPLE_FOLDERS) |
4195 | 849 | 888 | ||
4196 | 850 | expected = yield self.expected_volumes(SAMPLE_SHARES, SAMPLE_FOLDERS) | 889 | expected = yield self.expected_volumes(SAMPLE_SHARES, SAMPLE_FOLDERS) |
4197 | 851 | result = yield self.be.volumes_info() | 890 | result = yield self.be.volumes_info() |
4198 | @@ -860,9 +899,9 @@ | |||
4199 | 860 | self.be._volumes[fid] = {u'type': self.be.FOLDER_TYPE} | 899 | self.be._volumes[fid] = {u'type': self.be.FOLDER_TYPE} |
4200 | 861 | 900 | ||
4201 | 862 | yield self.be.subscribe_volume(volume_id=fid) | 901 | yield self.be.subscribe_volume(volume_id=fid) |
4203 | 863 | self.addCleanup(lambda: MockSDClient.subscribed_folders.remove(fid)) | 902 | self.addCleanup(self.be.sd_client.subscribed_folders.remove, fid) |
4204 | 864 | 903 | ||
4206 | 865 | self.assertEqual(MockSDClient.subscribed_folders, [fid]) | 904 | self.assertEqual(self.be.sd_client.subscribed_folders, [fid]) |
4207 | 866 | 905 | ||
4208 | 867 | @inlineCallbacks | 906 | @inlineCallbacks |
4209 | 868 | def test_unsubscribe_volume_folder(self): | 907 | def test_unsubscribe_volume_folder(self): |
4210 | @@ -871,11 +910,11 @@ | |||
4211 | 871 | self.be._volumes[fid] = {u'type': self.be.FOLDER_TYPE} | 910 | self.be._volumes[fid] = {u'type': self.be.FOLDER_TYPE} |
4212 | 872 | 911 | ||
4213 | 873 | yield self.be.subscribe_volume(volume_id=fid) | 912 | yield self.be.subscribe_volume(volume_id=fid) |
4215 | 874 | self.assertEqual(MockSDClient.subscribed_folders, [fid]) | 913 | self.assertEqual(self.be.sd_client.subscribed_folders, [fid]) |
4216 | 875 | 914 | ||
4217 | 876 | yield self.be.unsubscribe_volume(volume_id=fid) | 915 | yield self.be.unsubscribe_volume(volume_id=fid) |
4218 | 877 | 916 | ||
4220 | 878 | self.assertEqual(MockSDClient.subscribed_folders, []) | 917 | self.assertEqual(self.be.sd_client.subscribed_folders, []) |
4221 | 879 | 918 | ||
4222 | 880 | @inlineCallbacks | 919 | @inlineCallbacks |
4223 | 881 | def test_subscribe_volume_share(self): | 920 | def test_subscribe_volume_share(self): |
4224 | @@ -884,9 +923,9 @@ | |||
4225 | 884 | self.be._volumes[sid] = {u'type': self.be.SHARE_TYPE} | 923 | self.be._volumes[sid] = {u'type': self.be.SHARE_TYPE} |
4226 | 885 | 924 | ||
4227 | 886 | yield self.be.subscribe_volume(volume_id=sid) | 925 | yield self.be.subscribe_volume(volume_id=sid) |
4229 | 887 | self.addCleanup(lambda: MockSDClient.subscribed_shares.remove(sid)) | 926 | self.addCleanup(self.be.sd_client.subscribed_shares.remove, sid) |
4230 | 888 | 927 | ||
4232 | 889 | self.assertEqual(MockSDClient.subscribed_shares, [sid]) | 928 | self.assertEqual(self.be.sd_client.subscribed_shares, [sid]) |
4233 | 890 | 929 | ||
4234 | 891 | @inlineCallbacks | 930 | @inlineCallbacks |
4235 | 892 | def test_unsubscribe_volume_share(self): | 931 | def test_unsubscribe_volume_share(self): |
4236 | @@ -895,11 +934,11 @@ | |||
4237 | 895 | self.be._volumes[sid] = {u'type': self.be.SHARE_TYPE} | 934 | self.be._volumes[sid] = {u'type': self.be.SHARE_TYPE} |
4238 | 896 | 935 | ||
4239 | 897 | yield self.be.subscribe_volume(volume_id=sid) | 936 | yield self.be.subscribe_volume(volume_id=sid) |
4241 | 898 | self.assertEqual(MockSDClient.subscribed_shares, [sid]) | 937 | self.assertEqual(self.be.sd_client.subscribed_shares, [sid]) |
4242 | 899 | 938 | ||
4243 | 900 | yield self.be.unsubscribe_volume(volume_id=sid) | 939 | yield self.be.unsubscribe_volume(volume_id=sid) |
4244 | 901 | 940 | ||
4246 | 902 | self.assertEqual(MockSDClient.subscribed_shares, []) | 941 | self.assertEqual(self.be.sd_client.subscribed_shares, []) |
4247 | 903 | 942 | ||
4248 | 904 | @inlineCallbacks | 943 | @inlineCallbacks |
4249 | 905 | def test_change_volume_settings_folder(self): | 944 | def test_change_volume_settings_folder(self): |
4250 | @@ -908,10 +947,10 @@ | |||
4251 | 908 | self.be._volumes[fid] = {u'type': self.be.FOLDER_TYPE} | 947 | self.be._volumes[fid] = {u'type': self.be.FOLDER_TYPE} |
4252 | 909 | 948 | ||
4253 | 910 | yield self.be.change_volume_settings(fid, {'subscribed': True}) | 949 | yield self.be.change_volume_settings(fid, {'subscribed': True}) |
4255 | 911 | self.assertEqual(MockSDClient.subscribed_folders, [fid]) | 950 | self.assertEqual(self.be.sd_client.subscribed_folders, [fid]) |
4256 | 912 | 951 | ||
4257 | 913 | yield self.be.change_volume_settings(fid, {'subscribed': False}) | 952 | yield self.be.change_volume_settings(fid, {'subscribed': False}) |
4259 | 914 | self.assertEqual(MockSDClient.subscribed_folders, []) | 953 | self.assertEqual(self.be.sd_client.subscribed_folders, []) |
4260 | 915 | 954 | ||
4261 | 916 | @inlineCallbacks | 955 | @inlineCallbacks |
4262 | 917 | def test_change_volume_settings_share(self): | 956 | def test_change_volume_settings_share(self): |
4263 | @@ -920,17 +959,17 @@ | |||
4264 | 920 | self.be._volumes[sid] = {u'type': self.be.SHARE_TYPE} | 959 | self.be._volumes[sid] = {u'type': self.be.SHARE_TYPE} |
4265 | 921 | 960 | ||
4266 | 922 | yield self.be.change_volume_settings(sid, {'subscribed': True}) | 961 | yield self.be.change_volume_settings(sid, {'subscribed': True}) |
4268 | 923 | self.assertEqual(MockSDClient.subscribed_shares, [sid]) | 962 | self.assertEqual(self.be.sd_client.subscribed_shares, [sid]) |
4269 | 924 | 963 | ||
4270 | 925 | yield self.be.change_volume_settings(sid, {'subscribed': False}) | 964 | yield self.be.change_volume_settings(sid, {'subscribed': False}) |
4272 | 926 | self.assertEqual(MockSDClient.subscribed_shares, []) | 965 | self.assertEqual(self.be.sd_client.subscribed_shares, []) |
4273 | 927 | 966 | ||
4274 | 928 | @inlineCallbacks | 967 | @inlineCallbacks |
4275 | 929 | def test_change_volume_settings_no_setting(self): | 968 | def test_change_volume_settings_no_setting(self): |
4276 | 930 | """The change volume settings does not fail on empty settings.""" | 969 | """The change volume settings does not fail on empty settings.""" |
4277 | 931 | yield self.be.change_volume_settings('test', {}) | 970 | yield self.be.change_volume_settings('test', {}) |
4280 | 932 | self.assertEqual(MockSDClient.subscribed_folders, []) | 971 | self.assertEqual(self.be.sd_client.subscribed_folders, []) |
4281 | 933 | self.assertEqual(MockSDClient.subscribed_shares, []) | 972 | self.assertEqual(self.be.sd_client.subscribed_shares, []) |
4282 | 934 | 973 | ||
4283 | 935 | @inlineCallbacks | 974 | @inlineCallbacks |
4284 | 936 | def test_create_folder(self): | 975 | def test_create_folder(self): |
4285 | @@ -938,7 +977,7 @@ | |||
4286 | 938 | folder_path = os.path.join(USER_HOME, 'Test Me') | 977 | folder_path = os.path.join(USER_HOME, 'Test Me') |
4287 | 939 | yield self.be.create_folder(folder_path=folder_path) | 978 | yield self.be.create_folder(folder_path=folder_path) |
4288 | 940 | 979 | ||
4290 | 941 | self.assertEqual(MockSDClient.folders, [folder_path]) | 980 | self.assertEqual(self.be.sd_client.folders, [folder_path]) |
4291 | 942 | 981 | ||
4292 | 943 | 982 | ||
4293 | 944 | class BackendValidatePathForFolderTestCase(BackendBasicTestCase): | 983 | class BackendValidatePathForFolderTestCase(BackendBasicTestCase): |
4294 | @@ -950,9 +989,9 @@ | |||
4295 | 950 | super(BackendValidatePathForFolderTestCase, self).setUp() | 989 | super(BackendValidatePathForFolderTestCase, self).setUp() |
4296 | 951 | old_home = os.environ['HOME'] | 990 | old_home = os.environ['HOME'] |
4297 | 952 | os.environ['HOME'] = USER_HOME | 991 | os.environ['HOME'] = USER_HOME |
4301 | 953 | self.addCleanup(lambda: os.environ.__setitem__('HOME', old_home)) | 992 | self.addCleanup(os.environ.__setitem__, 'HOME', old_home) |
4302 | 954 | self.patch(MockSDClient, 'shares', SAMPLE_SHARES) | 993 | self.patch(self.be.sd_client, 'shares', SAMPLE_SHARES) |
4303 | 955 | self.patch(MockSDClient, 'folders', SAMPLE_FOLDERS) | 994 | self.patch(self.be.sd_client, 'folders', SAMPLE_FOLDERS) |
4304 | 956 | self.patch(backend, 'is_link', lambda p: False) | 995 | self.patch(backend, 'is_link', lambda p: False) |
4305 | 957 | 996 | ||
4306 | 958 | @defer.inlineCallbacks | 997 | @defer.inlineCallbacks |
4307 | @@ -1040,8 +1079,8 @@ | |||
4308 | 1040 | 1079 | ||
4309 | 1041 | def _build_msg(self): | 1080 | def _build_msg(self): |
4310 | 1042 | """Build expected message regarding file sync status.""" | 1081 | """Build expected message regarding file sync status.""" |
4313 | 1043 | return '%s (%s)' % (MockSDClient.status['description'], | 1082 | return '%s (%s)' % (self.be.sd_client.status['description'], |
4314 | 1044 | MockSDClient.status['name']) | 1083 | self.be.sd_client.status['name']) |
4315 | 1045 | 1084 | ||
4316 | 1046 | @inlineCallbacks | 1085 | @inlineCallbacks |
4317 | 1047 | def assert_correct_status(self, status, msg=None): | 1086 | def assert_correct_status(self, status, msg=None): |
4318 | @@ -1054,14 +1093,14 @@ | |||
4319 | 1054 | @inlineCallbacks | 1093 | @inlineCallbacks |
4320 | 1055 | def test_disabled(self): | 1094 | def test_disabled(self): |
4321 | 1056 | """The syncdaemon status is processed and emitted.""" | 1095 | """The syncdaemon status is processed and emitted.""" |
4323 | 1057 | self.patch(MockSDClient, 'file_sync', False) | 1096 | self.patch(self.be.sd_client, 'file_sync', False) |
4324 | 1058 | yield self.assert_correct_status(FILE_SYNC_DISABLED, msg='') | 1097 | yield self.assert_correct_status(FILE_SYNC_DISABLED, msg='') |
4325 | 1059 | self.assertTrue(self.be.file_sync_disabled) | 1098 | self.assertTrue(self.be.file_sync_disabled) |
4326 | 1060 | 1099 | ||
4327 | 1061 | @inlineCallbacks | 1100 | @inlineCallbacks |
4328 | 1062 | def test_error(self): | 1101 | def test_error(self): |
4329 | 1063 | """The syncdaemon status is processed and emitted.""" | 1102 | """The syncdaemon status is processed and emitted.""" |
4331 | 1064 | MockSDClient.status = { | 1103 | self.be.sd_client.status = { |
4332 | 1065 | 'is_error': 'True', # nothing else matters | 1104 | 'is_error': 'True', # nothing else matters |
4333 | 1066 | 'is_online': '', 'is_connected': '', | 1105 | 'is_online': '', 'is_connected': '', |
4334 | 1067 | 'name': 'AUTH_FAILED', 'connection': '', 'queues': '', | 1106 | 'name': 'AUTH_FAILED', 'connection': '', 'queues': '', |
4335 | @@ -1074,7 +1113,7 @@ | |||
4336 | 1074 | @inlineCallbacks | 1113 | @inlineCallbacks |
4337 | 1075 | def test_starting_when_init_not_user(self): | 1114 | def test_starting_when_init_not_user(self): |
4338 | 1076 | """The syncdaemon status is processed and emitted.""" | 1115 | """The syncdaemon status is processed and emitted.""" |
4340 | 1077 | MockSDClient.status = { | 1116 | self.be.sd_client.status = { |
4341 | 1078 | 'is_error': '', 'is_online': '', 'is_connected': '', | 1117 | 'is_error': '', 'is_online': '', 'is_connected': '', |
4342 | 1079 | 'connection': 'Not User With Network', 'queues': '', | 1118 | 'connection': 'Not User With Network', 'queues': '', |
4343 | 1080 | 'name': 'INIT', 'description': 'something new', | 1119 | 'name': 'INIT', 'description': 'something new', |
4344 | @@ -1085,7 +1124,7 @@ | |||
4345 | 1085 | @inlineCallbacks | 1124 | @inlineCallbacks |
4346 | 1086 | def test_starting_when_init_with_user(self): | 1125 | def test_starting_when_init_with_user(self): |
4347 | 1087 | """The syncdaemon status is processed and emitted.""" | 1126 | """The syncdaemon status is processed and emitted.""" |
4349 | 1088 | MockSDClient.status = { | 1127 | self.be.sd_client.status = { |
4350 | 1089 | 'is_error': '', 'is_online': '', 'is_connected': '', | 1128 | 'is_error': '', 'is_online': '', 'is_connected': '', |
4351 | 1090 | 'connection': 'With User With Network', 'queues': '', | 1129 | 'connection': 'With User With Network', 'queues': '', |
4352 | 1091 | 'name': 'INIT', 'description': 'something new', | 1130 | 'name': 'INIT', 'description': 'something new', |
4353 | @@ -1096,7 +1135,7 @@ | |||
4354 | 1096 | @inlineCallbacks | 1135 | @inlineCallbacks |
4355 | 1097 | def test_starting_when_local_rescan_not_user(self): | 1136 | def test_starting_when_local_rescan_not_user(self): |
4356 | 1098 | """The syncdaemon status is processed and emitted.""" | 1137 | """The syncdaemon status is processed and emitted.""" |
4358 | 1099 | MockSDClient.status = { | 1138 | self.be.sd_client.status = { |
4359 | 1100 | 'is_error': '', 'is_online': '', 'is_connected': '', | 1139 | 'is_error': '', 'is_online': '', 'is_connected': '', |
4360 | 1101 | 'connection': 'Not User With Network', 'queues': '', | 1140 | 'connection': 'Not User With Network', 'queues': '', |
4361 | 1102 | 'name': 'LOCAL_RESCAN', 'description': 'something new', | 1141 | 'name': 'LOCAL_RESCAN', 'description': 'something new', |
4362 | @@ -1107,7 +1146,7 @@ | |||
4363 | 1107 | @inlineCallbacks | 1146 | @inlineCallbacks |
4364 | 1108 | def test_starting_when_local_rescan_with_user(self): | 1147 | def test_starting_when_local_rescan_with_user(self): |
4365 | 1109 | """The syncdaemon status is processed and emitted.""" | 1148 | """The syncdaemon status is processed and emitted.""" |
4367 | 1110 | MockSDClient.status = { | 1149 | self.be.sd_client.status = { |
4368 | 1111 | 'is_error': '', 'is_online': '', 'is_connected': '', | 1150 | 'is_error': '', 'is_online': '', 'is_connected': '', |
4369 | 1112 | 'connection': 'With User With Network', 'queues': '', | 1151 | 'connection': 'With User With Network', 'queues': '', |
4370 | 1113 | 'name': 'LOCAL_RESCAN', 'description': 'something new', | 1152 | 'name': 'LOCAL_RESCAN', 'description': 'something new', |
4371 | @@ -1118,7 +1157,7 @@ | |||
4372 | 1118 | @inlineCallbacks | 1157 | @inlineCallbacks |
4373 | 1119 | def test_starting_when_ready_with_user(self): | 1158 | def test_starting_when_ready_with_user(self): |
4374 | 1120 | """The syncdaemon status is processed and emitted.""" | 1159 | """The syncdaemon status is processed and emitted.""" |
4376 | 1121 | MockSDClient.status = { | 1160 | self.be.sd_client.status = { |
4377 | 1122 | 'is_error': '', 'is_online': '', 'is_connected': '', | 1161 | 'is_error': '', 'is_online': '', 'is_connected': '', |
4378 | 1123 | 'connection': 'With User With Network', 'queues': '', | 1162 | 'connection': 'With User With Network', 'queues': '', |
4379 | 1124 | 'name': 'READY', 'description': 'something nicer', | 1163 | 'name': 'READY', 'description': 'something nicer', |
4380 | @@ -1129,7 +1168,7 @@ | |||
4381 | 1129 | @inlineCallbacks | 1168 | @inlineCallbacks |
4382 | 1130 | def test_disconnected(self): | 1169 | def test_disconnected(self): |
4383 | 1131 | """The syncdaemon status is processed and emitted.""" | 1170 | """The syncdaemon status is processed and emitted.""" |
4385 | 1132 | MockSDClient.status = { | 1171 | self.be.sd_client.status = { |
4386 | 1133 | 'is_error': '', 'is_online': '', 'is_connected': '', | 1172 | 'is_error': '', 'is_online': '', 'is_connected': '', |
4387 | 1134 | 'queues': '', 'description': 'something new', | 1173 | 'queues': '', 'description': 'something new', |
4388 | 1135 | 'connection': 'Not User With Network', # user didn't connect | 1174 | 'connection': 'Not User With Network', # user didn't connect |
4389 | @@ -1143,7 +1182,7 @@ | |||
4390 | 1143 | @inlineCallbacks | 1182 | @inlineCallbacks |
4391 | 1144 | def test_disconnected_when_waiting(self): | 1183 | def test_disconnected_when_waiting(self): |
4392 | 1145 | """The syncdaemon status is processed and emitted.""" | 1184 | """The syncdaemon status is processed and emitted.""" |
4394 | 1146 | MockSDClient.status = { | 1185 | self.be.sd_client.status = { |
4395 | 1147 | 'is_error': '', 'is_online': '', 'is_connected': '', | 1186 | 'is_error': '', 'is_online': '', 'is_connected': '', |
4396 | 1148 | 'connection': 'With User With Network', 'queues': '', | 1187 | 'connection': 'With User With Network', 'queues': '', |
4397 | 1149 | 'name': 'WAITING', 'description': 'what a long wait!', | 1188 | 'name': 'WAITING', 'description': 'what a long wait!', |
4398 | @@ -1156,7 +1195,7 @@ | |||
4399 | 1156 | @inlineCallbacks | 1195 | @inlineCallbacks |
4400 | 1157 | def test_syncing_if_online(self): | 1196 | def test_syncing_if_online(self): |
4401 | 1158 | """The syncdaemon status is processed and emitted.""" | 1197 | """The syncdaemon status is processed and emitted.""" |
4403 | 1159 | MockSDClient.status = { | 1198 | self.be.sd_client.status = { |
4404 | 1160 | 'is_error': '', 'is_online': 'True', 'is_connected': 'True', | 1199 | 'is_error': '', 'is_online': 'True', 'is_connected': 'True', |
4405 | 1161 | 'name': 'QUEUE_MANAGER', 'connection': '', | 1200 | 'name': 'QUEUE_MANAGER', 'connection': '', |
4406 | 1162 | 'queues': 'WORKING_ON_CONTENT', # anything but IDLE | 1201 | 'queues': 'WORKING_ON_CONTENT', # anything but IDLE |
4407 | @@ -1170,7 +1209,7 @@ | |||
4408 | 1170 | @inlineCallbacks | 1209 | @inlineCallbacks |
4409 | 1171 | def test_syncing_even_if_not_online(self): | 1210 | def test_syncing_even_if_not_online(self): |
4410 | 1172 | """The syncdaemon status is processed and emitted.""" | 1211 | """The syncdaemon status is processed and emitted.""" |
4412 | 1173 | MockSDClient.status = { | 1212 | self.be.sd_client.status = { |
4413 | 1174 | 'is_error': '', 'is_online': '', 'is_connected': 'True', | 1213 | 'is_error': '', 'is_online': '', 'is_connected': 'True', |
4414 | 1175 | 'name': 'CHECK_VERSION', 'connection': '', | 1214 | 'name': 'CHECK_VERSION', 'connection': '', |
4415 | 1176 | 'queues': 'WORKING_ON_CONTENT', | 1215 | 'queues': 'WORKING_ON_CONTENT', |
4416 | @@ -1184,7 +1223,7 @@ | |||
4417 | 1184 | @inlineCallbacks | 1223 | @inlineCallbacks |
4418 | 1185 | def test_idle(self): | 1224 | def test_idle(self): |
4419 | 1186 | """The syncdaemon status is processed and emitted.""" | 1225 | """The syncdaemon status is processed and emitted.""" |
4421 | 1187 | MockSDClient.status = { | 1226 | self.be.sd_client.status = { |
4422 | 1188 | 'is_error': '', 'is_online': 'True', 'is_connected': 'True', | 1227 | 'is_error': '', 'is_online': 'True', 'is_connected': 'True', |
4423 | 1189 | 'name': 'QUEUE_MANAGER', 'connection': '', | 1228 | 'name': 'QUEUE_MANAGER', 'connection': '', |
4424 | 1190 | 'queues': 'IDLE', | 1229 | 'queues': 'IDLE', |
4425 | @@ -1198,7 +1237,7 @@ | |||
4426 | 1198 | @inlineCallbacks | 1237 | @inlineCallbacks |
4427 | 1199 | def test_stopped(self): | 1238 | def test_stopped(self): |
4428 | 1200 | """The syncdaemon status is processed and emitted.""" | 1239 | """The syncdaemon status is processed and emitted.""" |
4430 | 1201 | MockSDClient.status = { | 1240 | self.be.sd_client.status = { |
4431 | 1202 | 'is_error': '', 'is_online': '', 'is_connected': '', | 1241 | 'is_error': '', 'is_online': '', 'is_connected': '', |
4432 | 1203 | 'name': 'SHUTDOWN', 'connection': '', | 1242 | 'name': 'SHUTDOWN', 'connection': '', |
4433 | 1204 | 'queues': 'IDLE', | 1243 | 'queues': 'IDLE', |
4434 | @@ -1212,7 +1251,7 @@ | |||
4435 | 1212 | @inlineCallbacks | 1251 | @inlineCallbacks |
4436 | 1213 | def test_unknown(self): | 1252 | def test_unknown(self): |
4437 | 1214 | """The syncdaemon status is processed and emitted.""" | 1253 | """The syncdaemon status is processed and emitted.""" |
4439 | 1215 | MockSDClient.status = { | 1254 | self.be.sd_client.status = status = { |
4440 | 1216 | 'is_error': '', 'is_online': '', 'is_connected': '', | 1255 | 'is_error': '', 'is_online': '', 'is_connected': '', |
4441 | 1217 | 'name': '', 'connection': '', 'queues': '', | 1256 | 'name': '', 'connection': '', 'queues': '', |
4442 | 1218 | 'description': '', | 1257 | 'description': '', |
4443 | @@ -1220,7 +1259,7 @@ | |||
4444 | 1220 | yield self.assert_correct_status(FILE_SYNC_UNKNOWN) | 1259 | yield self.assert_correct_status(FILE_SYNC_UNKNOWN) |
4445 | 1221 | 1260 | ||
4446 | 1222 | has_warning = self.memento.check_warning('file_sync_status: unknown', | 1261 | has_warning = self.memento.check_warning('file_sync_status: unknown', |
4448 | 1223 | repr(MockSDClient.status)) | 1262 | repr(status)) |
4449 | 1224 | self.assertTrue(has_warning) | 1263 | self.assertTrue(has_warning) |
4450 | 1225 | 1264 | ||
4451 | 1226 | # self.be.file_sync_disabled does not change | 1265 | # self.be.file_sync_disabled does not change |
4452 | @@ -1231,10 +1270,8 @@ | |||
4453 | 1231 | self.be.status_changed_handler = self._set_called | 1270 | self.be.status_changed_handler = self._set_called |
4454 | 1232 | status = {'name': 'foo', 'description': 'bar', 'is_error': '', | 1271 | status = {'name': 'foo', 'description': 'bar', 'is_error': '', |
4455 | 1233 | 'is_connected': '', 'is_online': '', 'queues': ''} | 1272 | 'is_connected': '', 'is_online': '', 'queues': ''} |
4457 | 1234 | backend.sd_client.status_changed_handler(status) | 1273 | self.be.sd_client.status_changed_handler(status) |
4458 | 1235 | 1274 | ||
4459 | 1236 | # pylint: disable=W0212 | ||
4460 | 1237 | # Access to a protected member _process_file_sync_status | ||
4461 | 1238 | expected_status = self.be._process_file_sync_status(status) | 1275 | expected_status = self.be._process_file_sync_status(status) |
4462 | 1239 | self.assertEqual(self._called, ((expected_status,), {})) | 1276 | self.assertEqual(self._called, ((expected_status,), {})) |
4463 | 1240 | 1277 | ||
4464 | @@ -1259,7 +1296,7 @@ | |||
4465 | 1259 | 1296 | ||
4466 | 1260 | def setUp(self): | 1297 | def setUp(self): |
4467 | 1261 | super(BackendFileSyncOpsTestCase, self).setUp() | 1298 | super(BackendFileSyncOpsTestCase, self).setUp() |
4469 | 1262 | MockSDClient.actions = [] | 1299 | self.be.sd_client.actions = [] |
4470 | 1263 | 1300 | ||
4471 | 1264 | @inlineCallbacks | 1301 | @inlineCallbacks |
4472 | 1265 | def test_enable_files(self): | 1302 | def test_enable_files(self): |
4473 | @@ -1267,7 +1304,7 @@ | |||
4474 | 1267 | yield self.be.disable_files() | 1304 | yield self.be.disable_files() |
4475 | 1268 | 1305 | ||
4476 | 1269 | yield self.be.enable_files() | 1306 | yield self.be.enable_files() |
4478 | 1270 | self.assertTrue(MockSDClient.file_sync) | 1307 | self.assertTrue(self.be.sd_client.file_sync) |
4479 | 1271 | self.assertFalse(self.be.file_sync_disabled) | 1308 | self.assertFalse(self.be.file_sync_disabled) |
4480 | 1272 | 1309 | ||
4481 | 1273 | @inlineCallbacks | 1310 | @inlineCallbacks |
4482 | @@ -1276,7 +1313,7 @@ | |||
4483 | 1276 | yield self.be.enable_files() | 1313 | yield self.be.enable_files() |
4484 | 1277 | 1314 | ||
4485 | 1278 | yield self.be.disable_files() | 1315 | yield self.be.disable_files() |
4487 | 1279 | self.assertFalse(MockSDClient.file_sync) | 1316 | self.assertFalse(self.be.sd_client.file_sync) |
4488 | 1280 | self.assertTrue(self.be.file_sync_disabled) | 1317 | self.assertTrue(self.be.file_sync_disabled) |
4489 | 1281 | 1318 | ||
4490 | 1282 | @inlineCallbacks | 1319 | @inlineCallbacks |
4491 | @@ -1284,7 +1321,7 @@ | |||
4492 | 1284 | """Connect files service.""" | 1321 | """Connect files service.""" |
4493 | 1285 | yield self.be.connect_files() | 1322 | yield self.be.connect_files() |
4494 | 1286 | 1323 | ||
4496 | 1287 | self.assertEqual(MockSDClient.actions, ['connect']) | 1324 | self.assertEqual(self.be.sd_client.actions, ['connect']) |
4497 | 1288 | self.assertFalse(self.be.file_sync_disabled) | 1325 | self.assertFalse(self.be.file_sync_disabled) |
4498 | 1289 | 1326 | ||
4499 | 1290 | @inlineCallbacks | 1327 | @inlineCallbacks |
4500 | @@ -1292,7 +1329,7 @@ | |||
4501 | 1292 | """Disconnect files service.""" | 1329 | """Disconnect files service.""" |
4502 | 1293 | yield self.be.disconnect_files() | 1330 | yield self.be.disconnect_files() |
4503 | 1294 | 1331 | ||
4505 | 1295 | self.assertEqual(MockSDClient.actions, ['disconnect']) | 1332 | self.assertEqual(self.be.sd_client.actions, ['disconnect']) |
4506 | 1296 | self.assertFalse(self.be.file_sync_disabled) | 1333 | self.assertFalse(self.be.file_sync_disabled) |
4507 | 1297 | 1334 | ||
4508 | 1298 | @inlineCallbacks | 1335 | @inlineCallbacks |
4509 | @@ -1300,7 +1337,7 @@ | |||
4510 | 1300 | """Restart the files service.""" | 1337 | """Restart the files service.""" |
4511 | 1301 | yield self.be.restart_files() | 1338 | yield self.be.restart_files() |
4512 | 1302 | 1339 | ||
4514 | 1303 | self.assertEqual(MockSDClient.actions, ['stop', 'start']) | 1340 | self.assertEqual(self.be.sd_client.actions, ['stop', 'start']) |
4515 | 1304 | self.assertFalse(self.be.file_sync_disabled) | 1341 | self.assertFalse(self.be.file_sync_disabled) |
4516 | 1305 | 1342 | ||
4517 | 1306 | @inlineCallbacks | 1343 | @inlineCallbacks |
4518 | @@ -1308,7 +1345,7 @@ | |||
4519 | 1308 | """Start the files service.""" | 1345 | """Start the files service.""" |
4520 | 1309 | yield self.be.start_files() | 1346 | yield self.be.start_files() |
4521 | 1310 | 1347 | ||
4523 | 1311 | self.assertEqual(MockSDClient.actions, ['start']) | 1348 | self.assertEqual(self.be.sd_client.actions, ['start']) |
4524 | 1312 | self.assertFalse(self.be.file_sync_disabled) | 1349 | self.assertFalse(self.be.file_sync_disabled) |
4525 | 1313 | 1350 | ||
4526 | 1314 | @inlineCallbacks | 1351 | @inlineCallbacks |
4527 | @@ -1316,7 +1353,7 @@ | |||
4528 | 1316 | """Stop the files service.""" | 1353 | """Stop the files service.""" |
4529 | 1317 | yield self.be.stop_files() | 1354 | yield self.be.stop_files() |
4530 | 1318 | 1355 | ||
4532 | 1319 | self.assertEqual(MockSDClient.actions, ['stop']) | 1356 | self.assertEqual(self.be.sd_client.actions, ['stop']) |
4533 | 1320 | self.assertFalse(self.be.file_sync_disabled) | 1357 | self.assertFalse(self.be.file_sync_disabled) |
4534 | 1321 | 1358 | ||
4535 | 1322 | 1359 | ||
4536 | @@ -1348,7 +1385,7 @@ | |||
4537 | 1348 | """The replication settings can be changed.""" | 1385 | """The replication settings can be changed.""" |
4538 | 1349 | rid = '0123-4567' | 1386 | rid = '0123-4567' |
4539 | 1350 | MockReplicationClient.replications.add(rid) | 1387 | MockReplicationClient.replications.add(rid) |
4541 | 1351 | self.addCleanup(lambda: MockReplicationClient.replications.remove(rid)) | 1388 | self.addCleanup(MockReplicationClient.replications.remove, rid) |
4542 | 1352 | 1389 | ||
4543 | 1353 | yield self.be.change_replication_settings(rid, {'enabled': False}) | 1390 | yield self.be.change_replication_settings(rid, {'enabled': False}) |
4544 | 1354 | self.assertIn(rid, MockReplicationClient.exclusions) | 1391 | self.assertIn(rid, MockReplicationClient.exclusions) |
4545 | @@ -1373,7 +1410,7 @@ | |||
4546 | 1373 | """The change replication settings does not fail on empty settings.""" | 1410 | """The change replication settings does not fail on empty settings.""" |
4547 | 1374 | rid = '0123-4567' | 1411 | rid = '0123-4567' |
4548 | 1375 | MockReplicationClient.replications.add(rid) | 1412 | MockReplicationClient.replications.add(rid) |
4550 | 1376 | self.addCleanup(lambda: MockReplicationClient.replications.remove(rid)) | 1413 | self.addCleanup(MockReplicationClient.replications.remove, rid) |
4551 | 1377 | 1414 | ||
4552 | 1378 | prior = MockReplicationClient.exclusions.copy() | 1415 | prior = MockReplicationClient.exclusions.copy() |
4553 | 1379 | yield self.be.change_replication_settings(rid, {}) | 1416 | yield self.be.change_replication_settings(rid, {}) |
4554 | @@ -1398,7 +1435,7 @@ | |||
4555 | 1398 | new_value = not self.default_settings[setting_name] | 1435 | new_value = not self.default_settings[setting_name] |
4556 | 1399 | yield self.be.change_file_sync_settings({setting_name: new_value}) | 1436 | yield self.be.change_file_sync_settings({setting_name: new_value}) |
4557 | 1400 | 1437 | ||
4559 | 1401 | self.assertEqual(getattr(backend.sd_client, setting_name), new_value) | 1438 | self.assertEqual(getattr(self.be.sd_client, setting_name), new_value) |
4560 | 1402 | 1439 | ||
4561 | 1403 | actual = yield self.be.file_sync_settings_info() | 1440 | actual = yield self.be.file_sync_settings_info() |
4562 | 1404 | expected = self.default_settings.copy() | 1441 | expected = self.default_settings.copy() |
4563 | @@ -1408,17 +1445,17 @@ | |||
4564 | 1408 | @inlineCallbacks | 1445 | @inlineCallbacks |
4565 | 1409 | def test_file_sync_settings_info(self): | 1446 | def test_file_sync_settings_info(self): |
4566 | 1410 | """The settings_info method exercises its callback.""" | 1447 | """The settings_info method exercises its callback.""" |
4568 | 1411 | backend.sd_client.limits = {"download": 1000, "upload": 100} | 1448 | self.be.sd_client.limits = {"download": 1000, "upload": 100} |
4569 | 1412 | expected = { | 1449 | expected = { |
4571 | 1413 | backend.AUTOCONNECT_KEY: backend.sd_client.autoconnect, | 1450 | backend.AUTOCONNECT_KEY: self.be.sd_client.autoconnect, |
4572 | 1414 | backend.SHOW_ALL_NOTIFICATIONS_KEY: | 1451 | backend.SHOW_ALL_NOTIFICATIONS_KEY: |
4574 | 1415 | backend.sd_client.show_all_notifications, | 1452 | self.be.sd_client.show_all_notifications, |
4575 | 1416 | backend.SHARE_AUTOSUBSCRIBE_KEY: | 1453 | backend.SHARE_AUTOSUBSCRIBE_KEY: |
4577 | 1417 | backend.sd_client.share_autosubscribe, | 1454 | self.be.sd_client.share_autosubscribe, |
4578 | 1418 | backend.UDF_AUTOSUBSCRIBE_KEY: | 1455 | backend.UDF_AUTOSUBSCRIBE_KEY: |
4582 | 1419 | backend.sd_client.udf_autosubscribe, | 1456 | self.be.sd_client.udf_autosubscribe, |
4583 | 1420 | backend.DOWNLOAD_KEY: backend.sd_client.limits['download'], | 1457 | backend.DOWNLOAD_KEY: self.be.sd_client.limits['download'], |
4584 | 1421 | backend.UPLOAD_KEY: backend.sd_client.limits['upload'], | 1458 | backend.UPLOAD_KEY: self.be.sd_client.limits['upload'], |
4585 | 1422 | } | 1459 | } |
4586 | 1423 | result = yield self.be.file_sync_settings_info() | 1460 | result = yield self.be.file_sync_settings_info() |
4587 | 1424 | self.assertEqual(expected, result) | 1461 | self.assertEqual(expected, result) |
4588 | @@ -1453,8 +1490,8 @@ | |||
4589 | 1453 | setting_name = backend.DOWNLOAD_KEY | 1490 | setting_name = backend.DOWNLOAD_KEY |
4590 | 1454 | yield self.be.change_file_sync_settings({setting_name: new_value}) | 1491 | yield self.be.change_file_sync_settings({setting_name: new_value}) |
4591 | 1455 | 1492 | ||
4594 | 1456 | self.assertEqual(backend.sd_client.throttling, True) | 1493 | self.assertEqual(self.be.sd_client.throttling, True) |
4595 | 1457 | self.assertEqual(backend.sd_client.limits, | 1494 | self.assertEqual(self.be.sd_client.limits, |
4596 | 1458 | {'download': new_value, 'upload': -1}) | 1495 | {'download': new_value, 'upload': -1}) |
4597 | 1459 | 1496 | ||
4598 | 1460 | @inlineCallbacks | 1497 | @inlineCallbacks |
4599 | @@ -1464,8 +1501,8 @@ | |||
4600 | 1464 | setting_name = backend.UPLOAD_KEY | 1501 | setting_name = backend.UPLOAD_KEY |
4601 | 1465 | yield self.be.change_file_sync_settings({setting_name: new_value}) | 1502 | yield self.be.change_file_sync_settings({setting_name: new_value}) |
4602 | 1466 | 1503 | ||
4605 | 1467 | self.assertEqual(backend.sd_client.throttling, True) | 1504 | self.assertEqual(self.be.sd_client.throttling, True) |
4606 | 1468 | self.assertEqual(backend.sd_client.limits, | 1505 | self.assertEqual(self.be.sd_client.limits, |
4607 | 1469 | {'download': -1, 'upload': new_value}) | 1506 | {'download': -1, 'upload': new_value}) |
4608 | 1470 | 1507 | ||
4609 | 1471 | @inlineCallbacks | 1508 | @inlineCallbacks |
4610 | @@ -1486,8 +1523,8 @@ | |||
4611 | 1486 | setting_name = backend.UPLOAD_KEY | 1523 | setting_name = backend.UPLOAD_KEY |
4612 | 1487 | yield self.be.change_file_sync_settings({setting_name: -1}) | 1524 | yield self.be.change_file_sync_settings({setting_name: -1}) |
4613 | 1488 | 1525 | ||
4616 | 1489 | self.assertEqual(backend.sd_client.throttling, False) | 1526 | self.assertEqual(self.be.sd_client.throttling, False) |
4617 | 1490 | self.assertEqual(backend.sd_client.limits, | 1527 | self.assertEqual(self.be.sd_client.limits, |
4618 | 1491 | {'download': -1, 'upload': -1}) | 1528 | {'download': -1, 'upload': -1}) |
4619 | 1492 | 1529 | ||
4620 | 1493 | @inlineCallbacks | 1530 | @inlineCallbacks |
4621 | @@ -1508,8 +1545,8 @@ | |||
4622 | 1508 | setting_name = backend.DOWNLOAD_KEY | 1545 | setting_name = backend.DOWNLOAD_KEY |
4623 | 1509 | yield self.be.change_file_sync_settings({setting_name: -1}) | 1546 | yield self.be.change_file_sync_settings({setting_name: -1}) |
4624 | 1510 | 1547 | ||
4627 | 1511 | self.assertEqual(backend.sd_client.throttling, False) | 1548 | self.assertEqual(self.be.sd_client.throttling, False) |
4628 | 1512 | self.assertEqual(backend.sd_client.limits, | 1549 | self.assertEqual(self.be.sd_client.limits, |
4629 | 1513 | {'download': -1, 'upload': -1}) | 1550 | {'download': -1, 'upload': -1}) |
4630 | 1514 | 1551 | ||
4631 | 1515 | @inlineCallbacks | 1552 | @inlineCallbacks |
4632 | @@ -1528,12 +1565,12 @@ | |||
4633 | 1528 | # the call we want to test | 1565 | # the call we want to test |
4634 | 1529 | yield self.be.restore_file_sync_settings() | 1566 | yield self.be.restore_file_sync_settings() |
4635 | 1530 | 1567 | ||
4642 | 1531 | self.assertEqual(backend.sd_client.autoconnect, True) | 1568 | self.assertEqual(self.be.sd_client.autoconnect, True) |
4643 | 1532 | self.assertEqual(backend.sd_client.show_all_notifications, True) | 1569 | self.assertEqual(self.be.sd_client.show_all_notifications, True) |
4644 | 1533 | self.assertEqual(backend.sd_client.share_autosubscribe, False) | 1570 | self.assertEqual(self.be.sd_client.share_autosubscribe, False) |
4645 | 1534 | self.assertEqual(backend.sd_client.udf_autosubscribe, False) | 1571 | self.assertEqual(self.be.sd_client.udf_autosubscribe, False) |
4646 | 1535 | self.assertEqual(backend.sd_client.throttling, False) | 1572 | self.assertEqual(self.be.sd_client.throttling, False) |
4647 | 1536 | self.assertEqual(backend.sd_client.limits, | 1573 | self.assertEqual(self.be.sd_client.limits, |
4648 | 1537 | {'download': -1, 'upload': -1}) | 1574 | {'download': -1, 'upload': -1}) |
4649 | 1538 | 1575 | ||
4650 | 1539 | result = yield self.be.file_sync_settings_info() | 1576 | result = yield self.be.file_sync_settings_info() |
4651 | 1540 | 1577 | ||
4652 | === modified file 'ubuntuone/controlpanel/tests/test_login_client.py' | |||
4653 | --- ubuntuone/controlpanel/tests/test_login_client.py 2011-07-22 21:26:48 +0000 | |||
4654 | +++ ubuntuone/controlpanel/tests/test_login_client.py 2011-08-25 19:40:18 +0000 | |||
4655 | @@ -19,10 +19,6 @@ | |||
4656 | 19 | """Tests for the service when accessing the login client.""" | 19 | """Tests for the service when accessing the login client.""" |
4657 | 20 | 20 | ||
4658 | 21 | from twisted.internet import defer | 21 | from twisted.internet import defer |
4659 | 22 | # No name 'credentials' in module 'ubuntuone.platform' | ||
4660 | 23 | # pylint: disable=E0611 | ||
4661 | 24 | from ubuntuone.platform import credentials | ||
4662 | 25 | # pylint: enable=E0611 | ||
4663 | 26 | 22 | ||
4664 | 27 | from ubuntuone.controlpanel import login_client | 23 | from ubuntuone.controlpanel import login_client |
4665 | 28 | from ubuntuone.controlpanel.tests import TestCase, TOKEN | 24 | from ubuntuone.controlpanel.tests import TestCase, TOKEN |
4666 | @@ -49,13 +45,23 @@ | |||
4667 | 49 | FakedCredentialsManagementTool.credentials = None | 45 | FakedCredentialsManagementTool.credentials = None |
4668 | 50 | yield | 46 | yield |
4669 | 51 | 47 | ||
4670 | 48 | @defer.inlineCallbacks | ||
4671 | 49 | def login(self): | ||
4672 | 50 | """Create credentials for Ubuntu One by logging in.""" | ||
4673 | 51 | yield defer.succeed(FakedCredentialsManagementTool.credentials) | ||
4674 | 52 | |||
4675 | 53 | @defer.inlineCallbacks | ||
4676 | 54 | def register(self): | ||
4677 | 55 | """Create credentials for Ubuntu One by registering.""" | ||
4678 | 56 | yield defer.succeed(FakedCredentialsManagementTool.credentials) | ||
4679 | 57 | |||
4680 | 52 | 58 | ||
4681 | 53 | class BaseTestCase(TestCase): | 59 | class BaseTestCase(TestCase): |
4682 | 54 | """Base TestCase for the login client methods.""" | 60 | """Base TestCase for the login client methods.""" |
4683 | 55 | 61 | ||
4684 | 56 | def setUp(self): | 62 | def setUp(self): |
4685 | 57 | super(BaseTestCase, self).setUp() | 63 | super(BaseTestCase, self).setUp() |
4687 | 58 | self.patch(credentials, 'CredentialsManagementTool', | 64 | self.patch(login_client, 'CredentialsManagementTool', |
4688 | 59 | FakedCredentialsManagementTool) | 65 | FakedCredentialsManagementTool) |
4689 | 60 | FakedCredentialsManagementTool.credentials = TOKEN | 66 | FakedCredentialsManagementTool.credentials = TOKEN |
4690 | 61 | 67 | ||
4691 | @@ -87,7 +93,7 @@ | |||
4692 | 87 | 93 | ||
4693 | 88 | @defer.inlineCallbacks | 94 | @defer.inlineCallbacks |
4694 | 89 | def test_clear_credentials(self): | 95 | def test_clear_credentials(self): |
4696 | 90 | """The credentials are properly retrieved.""" | 96 | """The credentials are properly cleared.""" |
4697 | 91 | yield login_client.clear_credentials() | 97 | yield login_client.clear_credentials() |
4698 | 92 | self.assertEqual(None, FakedCredentialsManagementTool.credentials) | 98 | self.assertEqual(None, FakedCredentialsManagementTool.credentials) |
4699 | 93 | 99 | ||
4700 | @@ -98,3 +104,39 @@ | |||
4701 | 98 | self.fake_fail) | 104 | self.fake_fail) |
4702 | 99 | yield self.assertFailure(login_client.clear_credentials(), | 105 | yield self.assertFailure(login_client.clear_credentials(), |
4703 | 100 | CustomError) | 106 | CustomError) |
4704 | 107 | |||
4705 | 108 | |||
4706 | 109 | class LoginTestCase(BaseTestCase): | ||
4707 | 110 | """Test for the login method.""" | ||
4708 | 111 | |||
4709 | 112 | @defer.inlineCallbacks | ||
4710 | 113 | def test_login(self): | ||
4711 | 114 | """The credentials are properly retrieved.""" | ||
4712 | 115 | yield login_client.login() | ||
4713 | 116 | self.assertEqual(TOKEN, FakedCredentialsManagementTool.credentials) | ||
4714 | 117 | |||
4715 | 118 | @defer.inlineCallbacks | ||
4716 | 119 | def test_login_throws_an_error(self): | ||
4717 | 120 | """If login fails, the error is propagated.""" | ||
4718 | 121 | self.patch(FakedCredentialsManagementTool, 'login', | ||
4719 | 122 | self.fake_fail) | ||
4720 | 123 | yield self.assertFailure(login_client.login(), | ||
4721 | 124 | CustomError) | ||
4722 | 125 | |||
4723 | 126 | |||
4724 | 127 | class RegisterTestCase(BaseTestCase): | ||
4725 | 128 | """Test for the register method.""" | ||
4726 | 129 | |||
4727 | 130 | @defer.inlineCallbacks | ||
4728 | 131 | def test_register(self): | ||
4729 | 132 | """The credentials are properly retrieved.""" | ||
4730 | 133 | yield login_client.register() | ||
4731 | 134 | self.assertEqual(TOKEN, FakedCredentialsManagementTool.credentials) | ||
4732 | 135 | |||
4733 | 136 | @defer.inlineCallbacks | ||
4734 | 137 | def test_register_throws_an_error(self): | ||
4735 | 138 | """If register fails, the error is propagated.""" | ||
4736 | 139 | self.patch(FakedCredentialsManagementTool, 'register', | ||
4737 | 140 | self.fake_fail) | ||
4738 | 141 | yield self.assertFailure(login_client.register(), | ||
4739 | 142 | CustomError) | ||
4740 | 101 | 143 | ||
4741 | === modified file 'ubuntuone/controlpanel/tests/test_sd_client.py' | |||
4742 | --- ubuntuone/controlpanel/tests/test_sd_client.py 2011-07-22 21:26:48 +0000 | |||
4743 | +++ ubuntuone/controlpanel/tests/test_sd_client.py 2011-08-25 19:40:18 +0000 | |||
4744 | @@ -149,7 +149,7 @@ | |||
4745 | 149 | @inlineCallbacks | 149 | @inlineCallbacks |
4746 | 150 | def get_shares(self): | 150 | def get_shares(self): |
4747 | 151 | """Get the list of shares (accepted or not).""" | 151 | """Get the list of shares (accepted or not).""" |
4749 | 152 | result = yield FakedSyncDaemonTool.shares.values() | 152 | result = yield self.shares.values() |
4750 | 153 | returnValue(sorted(result)) | 153 | returnValue(sorted(result)) |
4751 | 154 | 154 | ||
4752 | 155 | def refresh_shares(self): | 155 | def refresh_shares(self): |
4753 | @@ -169,38 +169,38 @@ | |||
4754 | 169 | if path == '': # simulate an error | 169 | if path == '': # simulate an error |
4755 | 170 | raise CustomError(path) | 170 | raise CustomError(path) |
4756 | 171 | 171 | ||
4758 | 172 | folder = FakedSyncDaemonTool.create_udf(path) | 172 | folder = self.create_udf(path) |
4759 | 173 | return folder | 173 | return folder |
4760 | 174 | 174 | ||
4761 | 175 | def delete_folder(self, folder_id): | 175 | def delete_folder(self, folder_id): |
4762 | 176 | """Delete a user defined folder given its id.""" | 176 | """Delete a user defined folder given its id.""" |
4764 | 177 | if folder_id not in FakedSyncDaemonTool.folders: | 177 | if folder_id not in self.folders: |
4765 | 178 | raise CustomError(folder_id) | 178 | raise CustomError(folder_id) |
4766 | 179 | 179 | ||
4768 | 180 | folder = FakedSyncDaemonTool.folders.pop(folder_id) | 180 | folder = self.folders.pop(folder_id) |
4769 | 181 | return folder | 181 | return folder |
4770 | 182 | 182 | ||
4771 | 183 | @inlineCallbacks | 183 | @inlineCallbacks |
4772 | 184 | def subscribe_folder(self, folder_id): | 184 | def subscribe_folder(self, folder_id): |
4773 | 185 | """Subscribe to a user defined folder given its id.""" | 185 | """Subscribe to a user defined folder given its id.""" |
4775 | 186 | yield FakedSyncDaemonTool._set_folder_attr(folder_id, | 186 | yield self._set_folder_attr(folder_id, |
4776 | 187 | u'subscribed', True) | 187 | u'subscribed', True) |
4777 | 188 | 188 | ||
4778 | 189 | @inlineCallbacks | 189 | @inlineCallbacks |
4779 | 190 | def unsubscribe_folder(self, folder_id): | 190 | def unsubscribe_folder(self, folder_id): |
4780 | 191 | """Unsubscribe from a user defined folder given its id.""" | 191 | """Unsubscribe from a user defined folder given its id.""" |
4782 | 192 | yield FakedSyncDaemonTool._set_folder_attr(folder_id, | 192 | yield self._set_folder_attr(folder_id, |
4783 | 193 | u'subscribed', False) | 193 | u'subscribed', False) |
4784 | 194 | 194 | ||
4785 | 195 | @inlineCallbacks | 195 | @inlineCallbacks |
4786 | 196 | def get_folders(self): | 196 | def get_folders(self): |
4787 | 197 | """Return the list of folders (a list of dicts).""" | 197 | """Return the list of folders (a list of dicts).""" |
4789 | 198 | result = yield FakedSyncDaemonTool.folders.values() | 198 | result = yield self.folders.values() |
4790 | 199 | returnValue(sorted(result)) | 199 | returnValue(sorted(result)) |
4791 | 200 | 200 | ||
4792 | 201 | def get_folder_info(self, path): | 201 | def get_folder_info(self, path): |
4793 | 202 | """Call the get_info method for a UDF path.""" | 202 | """Call the get_info method for a UDF path.""" |
4795 | 203 | for _, content in FakedSyncDaemonTool.folders.iteritems(): | 203 | for _, content in self.folders.iteritems(): |
4796 | 204 | if content['path'] == path: | 204 | if content['path'] == path: |
4797 | 205 | return content | 205 | return content |
4798 | 206 | else: | 206 | else: |
4799 | @@ -322,9 +322,10 @@ | |||
4800 | 322 | def setUp(self): | 322 | def setUp(self): |
4801 | 323 | super(BaseTestCase, self).setUp() | 323 | super(BaseTestCase, self).setUp() |
4802 | 324 | self.patch(tools, 'SyncDaemonTool', FakedSyncDaemonTool) | 324 | self.patch(tools, 'SyncDaemonTool', FakedSyncDaemonTool) |
4806 | 325 | FakedSyncDaemonTool.shares.clear() | 325 | self.sd = sd_client.SyncDaemonClient() |
4807 | 326 | FakedSyncDaemonTool.folders.clear() | 326 | self.sd.proxy.shares.clear() |
4808 | 327 | FakedSyncDaemonTool.called.clear() | 327 | self.sd.proxy.folders.clear() |
4809 | 328 | self.sd.proxy.called.clear() | ||
4810 | 328 | 329 | ||
4811 | 329 | def fake_fail(self, *a): | 330 | def fake_fail(self, *a): |
4812 | 330 | """Fake a failure.""" | 331 | """Fake a failure.""" |
4813 | @@ -337,79 +338,79 @@ | |||
4814 | 337 | @inlineCallbacks | 338 | @inlineCallbacks |
4815 | 338 | def test_throttle_limits_returned(self): | 339 | def test_throttle_limits_returned(self): |
4816 | 339 | """When SD returns the limits, they are handled.""" | 340 | """When SD returns the limits, they are handled.""" |
4819 | 340 | limits = yield sd_client.get_throttling_limits() | 341 | limits = yield self.sd.get_throttling_limits() |
4820 | 341 | self.assertEqual(limits, FakedSyncDaemonTool.settings['limits']) | 342 | self.assertEqual(limits, self.sd.proxy.settings['limits']) |
4821 | 342 | 343 | ||
4822 | 343 | @inlineCallbacks | 344 | @inlineCallbacks |
4823 | 344 | def test_getting_throttle_limits_throws_an_error(self): | 345 | def test_getting_throttle_limits_throws_an_error(self): |
4824 | 345 | """Handle error when getting the limits.""" | 346 | """Handle error when getting the limits.""" |
4826 | 346 | self.patch(FakedSyncDaemonTool, 'get_throttling_limits', | 347 | self.patch(self.sd.proxy, 'get_throttling_limits', |
4827 | 347 | self.fake_fail) | 348 | self.fake_fail) |
4829 | 348 | yield self.assertFailure(sd_client.get_throttling_limits(), | 349 | yield self.assertFailure(self.sd.get_throttling_limits(), |
4830 | 349 | CustomError) | 350 | CustomError) |
4831 | 350 | 351 | ||
4832 | 351 | @inlineCallbacks | 352 | @inlineCallbacks |
4833 | 352 | def test_throttle_limits_set(self): | 353 | def test_throttle_limits_set(self): |
4834 | 353 | """Setting the limits.""" | 354 | """Setting the limits.""" |
4837 | 354 | yield sd_client.set_throttling_limits(SAMPLE_LIMITS) | 355 | yield self.sd.set_throttling_limits(SAMPLE_LIMITS) |
4838 | 355 | actual = sd_client.get_throttling_limits() | 356 | actual = self.sd.get_throttling_limits() |
4839 | 356 | self.assertEqual(actual, SAMPLE_LIMITS) | 357 | self.assertEqual(actual, SAMPLE_LIMITS) |
4840 | 357 | 358 | ||
4841 | 358 | @inlineCallbacks | 359 | @inlineCallbacks |
4842 | 359 | def test_setting_throttle_limits_throws_an_error(self): | 360 | def test_setting_throttle_limits_throws_an_error(self): |
4843 | 360 | """Handle error when setting the limits.""" | 361 | """Handle error when setting the limits.""" |
4845 | 361 | self.patch(FakedSyncDaemonTool, 'set_throttling_limits', | 362 | self.patch(self.sd.proxy, 'set_throttling_limits', |
4846 | 362 | self.fake_fail) | 363 | self.fake_fail) |
4848 | 363 | d = sd_client.set_throttling_limits(SAMPLE_LIMITS) | 364 | d = self.sd.set_throttling_limits(SAMPLE_LIMITS) |
4849 | 364 | yield self.assertFailure(d, CustomError) | 365 | yield self.assertFailure(d, CustomError) |
4850 | 365 | 366 | ||
4851 | 366 | @inlineCallbacks | 367 | @inlineCallbacks |
4852 | 367 | def test_throttle_get(self): | 368 | def test_throttle_get(self): |
4853 | 368 | """Getting the throttling state.""" | 369 | """Getting the throttling state.""" |
4856 | 369 | FakedSyncDaemonTool.settings['throttling_enabled'] = False | 370 | self.sd.proxy.settings['throttling_enabled'] = False |
4857 | 370 | throttling = yield sd_client.bandwidth_throttling_enabled() | 371 | throttling = yield self.sd.bandwidth_throttling_enabled() |
4858 | 371 | self.assertEqual(throttling, False) | 372 | self.assertEqual(throttling, False) |
4859 | 372 | 373 | ||
4862 | 373 | FakedSyncDaemonTool.settings['throttling_enabled'] = True | 374 | self.sd.proxy.settings['throttling_enabled'] = True |
4863 | 374 | throttling = yield sd_client.bandwidth_throttling_enabled() | 375 | throttling = yield self.sd.bandwidth_throttling_enabled() |
4864 | 375 | self.assertEqual(throttling, True) | 376 | self.assertEqual(throttling, True) |
4865 | 376 | 377 | ||
4866 | 377 | @inlineCallbacks | 378 | @inlineCallbacks |
4867 | 378 | def test_throttle_get_throws_an_error(self): | 379 | def test_throttle_get_throws_an_error(self): |
4868 | 379 | """Handle error when getting the throttling state.""" | 380 | """Handle error when getting the throttling state.""" |
4870 | 380 | self.patch(FakedSyncDaemonTool, 'is_throttling_enabled', | 381 | self.patch(self.sd.proxy, 'is_throttling_enabled', |
4871 | 381 | self.fake_fail) | 382 | self.fake_fail) |
4873 | 382 | yield self.assertFailure(sd_client.bandwidth_throttling_enabled(), | 383 | yield self.assertFailure(self.sd.bandwidth_throttling_enabled(), |
4874 | 383 | CustomError) | 384 | CustomError) |
4875 | 384 | 385 | ||
4876 | 385 | @inlineCallbacks | 386 | @inlineCallbacks |
4877 | 386 | def test_throttle_enable(self): | 387 | def test_throttle_enable(self): |
4878 | 387 | """Enabling bw throttling.""" | 388 | """Enabling bw throttling.""" |
4882 | 388 | FakedSyncDaemonTool.settings['throttling_enabled'] = False | 389 | self.sd.proxy.settings['throttling_enabled'] = False |
4883 | 389 | yield sd_client.enable_bandwidth_throttling() | 390 | yield self.sd.enable_bandwidth_throttling() |
4884 | 390 | self.assertTrue(FakedSyncDaemonTool.settings['throttling_enabled']) | 391 | self.assertTrue(self.sd.proxy.settings['throttling_enabled']) |
4885 | 391 | 392 | ||
4886 | 392 | @inlineCallbacks | 393 | @inlineCallbacks |
4887 | 393 | def test_throttle_enable_throws_an_error(self): | 394 | def test_throttle_enable_throws_an_error(self): |
4888 | 394 | """Handle error when enabling throttling.""" | 395 | """Handle error when enabling throttling.""" |
4890 | 395 | self.patch(FakedSyncDaemonTool, 'enable_throttling', | 396 | self.patch(self.sd.proxy, 'enable_throttling', |
4891 | 396 | self.fake_fail) | 397 | self.fake_fail) |
4893 | 397 | yield self.assertFailure(sd_client.enable_bandwidth_throttling(), | 398 | yield self.assertFailure(self.sd.enable_bandwidth_throttling(), |
4894 | 398 | CustomError) | 399 | CustomError) |
4895 | 399 | 400 | ||
4896 | 400 | @inlineCallbacks | 401 | @inlineCallbacks |
4897 | 401 | def test_throttle_disable(self): | 402 | def test_throttle_disable(self): |
4898 | 402 | """Disabling bw throttling.""" | 403 | """Disabling bw throttling.""" |
4902 | 403 | FakedSyncDaemonTool.settings['throttling_enabled'] = True | 404 | self.sd.proxy.settings['throttling_enabled'] = True |
4903 | 404 | yield sd_client.disable_bandwidth_throttling() | 405 | yield self.sd.disable_bandwidth_throttling() |
4904 | 405 | self.assertFalse(FakedSyncDaemonTool.settings['throttling_enabled']) | 406 | self.assertFalse(self.sd.proxy.settings['throttling_enabled']) |
4905 | 406 | 407 | ||
4906 | 407 | @inlineCallbacks | 408 | @inlineCallbacks |
4907 | 408 | def test_throttle_disable_throws_an_error(self): | 409 | def test_throttle_disable_throws_an_error(self): |
4908 | 409 | """Handle error when disabling throttling.""" | 410 | """Handle error when disabling throttling.""" |
4910 | 410 | self.patch(FakedSyncDaemonTool, 'enable_throttling', | 411 | self.patch(self.sd.proxy, 'enable_throttling', |
4911 | 411 | self.fake_fail) | 412 | self.fake_fail) |
4913 | 412 | yield self.assertFailure(sd_client.disable_bandwidth_throttling(), | 413 | yield self.assertFailure(self.sd.disable_bandwidth_throttling(), |
4914 | 413 | CustomError) | 414 | CustomError) |
4915 | 414 | 415 | ||
4916 | 415 | 416 | ||
4917 | @@ -420,53 +421,56 @@ | |||
4918 | 420 | # pylint: disable=E1120 | 421 | # pylint: disable=E1120 |
4919 | 421 | 422 | ||
4920 | 422 | name = 'show_all_notifications' | 423 | name = 'show_all_notifications' |
4924 | 423 | getter = lambda _: sd_client.show_all_notifications_enabled() | 424 | |
4925 | 424 | enabler = lambda _: sd_client.enable_show_all_notifications() | 425 | def setUp(self): |
4926 | 425 | disabler = lambda _: sd_client.disable_show_all_notifications() | 426 | super(NotificationsTestCase, self).setUp() |
4927 | 427 | self.getter = getattr(self.sd, '%s_enabled' % self.name) | ||
4928 | 428 | self.enabler = getattr(self.sd, 'enable_%s' % self.name) | ||
4929 | 429 | self.disabler = getattr(self.sd, 'disable_%s' % self.name) | ||
4930 | 426 | 430 | ||
4931 | 427 | @inlineCallbacks | 431 | @inlineCallbacks |
4932 | 428 | def test_get_value(self): | 432 | def test_get_value(self): |
4933 | 429 | """Getting the show_all_notifications state.""" | 433 | """Getting the show_all_notifications state.""" |
4935 | 430 | FakedSyncDaemonTool.settings[self.name] = False | 434 | self.sd.proxy.settings[self.name] = False |
4936 | 431 | state = yield self.getter() | 435 | state = yield self.getter() |
4937 | 432 | self.assertEqual(state, False) | 436 | self.assertEqual(state, False) |
4939 | 433 | FakedSyncDaemonTool.settings[self.name] = True | 437 | self.sd.proxy.settings[self.name] = True |
4940 | 434 | state = yield self.getter() | 438 | state = yield self.getter() |
4941 | 435 | self.assertEqual(state, True) | 439 | self.assertEqual(state, True) |
4942 | 436 | 440 | ||
4943 | 437 | @inlineCallbacks | 441 | @inlineCallbacks |
4944 | 438 | def test_get_value_throws_an_error(self): | 442 | def test_get_value_throws_an_error(self): |
4945 | 439 | """Handle error when getting the show_all_notifications state.""" | 443 | """Handle error when getting the show_all_notifications state.""" |
4947 | 440 | self.patch(FakedSyncDaemonTool, 'is_%s_enabled' % self.name, | 444 | self.patch(self.sd.proxy, 'is_%s_enabled' % self.name, |
4948 | 441 | self.fake_fail) | 445 | self.fake_fail) |
4949 | 442 | yield self.assertFailure(self.getter(), CustomError) | 446 | yield self.assertFailure(self.getter(), CustomError) |
4950 | 443 | 447 | ||
4951 | 444 | @inlineCallbacks | 448 | @inlineCallbacks |
4952 | 445 | def test_enable(self): | 449 | def test_enable(self): |
4953 | 446 | """Enabling show_all_notifications.""" | 450 | """Enabling show_all_notifications.""" |
4955 | 447 | FakedSyncDaemonTool.settings[self.name] = False | 451 | self.sd.proxy.settings[self.name] = False |
4956 | 448 | yield self.enabler() | 452 | yield self.enabler() |
4958 | 449 | self.assertTrue(FakedSyncDaemonTool.settings[self.name]) | 453 | self.assertTrue(self.sd.proxy.settings[self.name]) |
4959 | 450 | 454 | ||
4960 | 451 | @inlineCallbacks | 455 | @inlineCallbacks |
4961 | 452 | def test_enable_throws_an_error(self): | 456 | def test_enable_throws_an_error(self): |
4962 | 453 | """Handle error when enabling show_all_notifications.""" | 457 | """Handle error when enabling show_all_notifications.""" |
4964 | 454 | self.patch(FakedSyncDaemonTool, 'enable_%s' % self.name, | 458 | self.patch(self.sd.proxy, 'enable_%s' % self.name, |
4965 | 455 | self.fake_fail) | 459 | self.fake_fail) |
4966 | 456 | yield self.assertFailure(self.enabler(), CustomError) | 460 | yield self.assertFailure(self.enabler(), CustomError) |
4967 | 457 | 461 | ||
4968 | 458 | @inlineCallbacks | 462 | @inlineCallbacks |
4969 | 459 | def test_disable(self): | 463 | def test_disable(self): |
4970 | 460 | """Disabling show_all_notifications.""" | 464 | """Disabling show_all_notifications.""" |
4972 | 461 | FakedSyncDaemonTool.settings[self.name] = True | 465 | self.sd.proxy.settings[self.name] = True |
4973 | 462 | yield self.disabler() | 466 | yield self.disabler() |
4975 | 463 | value = FakedSyncDaemonTool.settings[self.name] | 467 | value = self.sd.proxy.settings[self.name] |
4976 | 464 | self.assertFalse(value) | 468 | self.assertFalse(value) |
4977 | 465 | 469 | ||
4978 | 466 | @inlineCallbacks | 470 | @inlineCallbacks |
4979 | 467 | def test_disable_throws_an_error(self): | 471 | def test_disable_throws_an_error(self): |
4980 | 468 | """Handle error when disabling show_all_notifications.""" | 472 | """Handle error when disabling show_all_notifications.""" |
4982 | 469 | self.patch(FakedSyncDaemonTool, 'enable_%s' % self.name, | 473 | self.patch(self.sd.proxy, 'enable_%s' % self.name, |
4983 | 470 | self.fake_fail) | 474 | self.fake_fail) |
4984 | 471 | yield self.assertFailure(self.disabler(), CustomError) | 475 | yield self.assertFailure(self.disabler(), CustomError) |
4985 | 472 | 476 | ||
4986 | @@ -475,27 +479,18 @@ | |||
4987 | 475 | """Test for the autoconnect syncdaemon client methods.""" | 479 | """Test for the autoconnect syncdaemon client methods.""" |
4988 | 476 | 480 | ||
4989 | 477 | name = 'autoconnect' | 481 | name = 'autoconnect' |
4990 | 478 | getter = lambda _: sd_client.autoconnect_enabled() | ||
4991 | 479 | enabler = lambda _: sd_client.enable_autoconnect() | ||
4992 | 480 | disabler = lambda _: sd_client.disable_autoconnect() | ||
4993 | 481 | 482 | ||
4994 | 482 | 483 | ||
4995 | 483 | class ShareAutosubscribeTestCase(NotificationsTestCase): | 484 | class ShareAutosubscribeTestCase(NotificationsTestCase): |
4996 | 484 | """Test for the share_autosubscribe syncdaemon client methods.""" | 485 | """Test for the share_autosubscribe syncdaemon client methods.""" |
4997 | 485 | 486 | ||
4998 | 486 | name = 'share_autosubscribe' | 487 | name = 'share_autosubscribe' |
4999 | 487 | getter = lambda _: sd_client.share_autosubscribe_enabled() | ||
5000 | 488 | enabler = lambda _: sd_client.enable_share_autosubscribe() |
The diff has been truncated for viewing.