Merge lp:~facundo/magicicada-protocol/publicfiles into lp:magicicada-protocol

Proposed by Facundo Batista on 2016-11-07
Status: Merged
Approved by: Natalia Bidart on 2016-11-26
Approved revision: 170
Merged at revision: 169
Proposed branch: lp:~facundo/magicicada-protocol/publicfiles
Merge into: lp:magicicada-protocol
Diff against target: 715 lines (+406/-59)
5 files modified
tests/test_client.py (+182/-49)
tests/test_public_file_info.py (+74/-0)
ubuntuone/storageprotocol/client.py (+71/-8)
ubuntuone/storageprotocol/protocol.proto (+24/-2)
ubuntuone/storageprotocol/public_file_info.py (+55/-0)
To merge this branch: bzr merge lp:~facundo/magicicada-protocol/publicfiles
Reviewer Review Type Date Requested Status
Natalia Bidart 2016-11-07 Approve on 2016-11-26
Review via email: mp+310154@code.launchpad.net

Commit message

Protocol infrastructure to support public files change and listing.

Description of the change

Protocol infrastructure to support public files change and listing.

To post a comment you must log in.
Facundo Batista (facundo) wrote :

Comments addressed

170. By Facundo Batista on 2016-11-15

Import order.

Natalia Bidart (nataliabidart) wrote :

LGTM Thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'tests/test_client.py'
2--- tests/test_client.py 2016-09-19 02:00:32 +0000
3+++ tests/test_client.py 2016-11-15 23:38:26 +0000
4@@ -1,6 +1,7 @@
5 # -*- coding: utf-8 -*-
6-#
7-# Copyright (C) 2009-2015 Canonical Ltd.
8+
9+# Copyright 2009-2015 Canonical Ltd.
10+# Copyright 2016 Chicharreros (https://launchpad.net/~chicharreros)
11 #
12 # This program is free software: you can redistribute it and/or modify it
13 # under the terms of the GNU Affero General Public License version 3,
14@@ -26,6 +27,7 @@
15 # do not wish to do so, delete this exception statement from your
16 # version. If you delete this exception statement from all source
17 # files in the program, then also delete it here.
18+
19 """Tests for the protocol client."""
20
21 import StringIO
22@@ -42,8 +44,20 @@
23
24 from ubuntuone.storageprotocol import protocol_pb2, sharersp, delta, request
25 from ubuntuone.storageprotocol.client import (
26- StorageClient, CreateUDF, ListVolumes, DeleteVolume, GetDelta, Unlink,
27- Authenticate, MakeFile, MakeDir, PutContent, Move, BytesMessageProducer,
28+ Authenticate,
29+ BytesMessageProducer,
30+ ChangePublicAccess,
31+ CreateUDF,
32+ DeleteVolume,
33+ GetDelta,
34+ ListPublicFiles,
35+ ListVolumes,
36+ MakeDir,
37+ MakeFile,
38+ Move,
39+ PutContent,
40+ StorageClient,
41+ Unlink,
42 )
43
44 from ubuntuone.storageprotocol import volumes
45@@ -61,6 +75,7 @@
46 NODE = uuid.UUID('FEDCBA98-7654-3211-2345-6789ABCDEF12')
47 USER = u'Dude'
48 GENERATION = 999
49+PUBLIC_URL = "http://magicicada/someid"
50
51
52 class FakedError(Exception):
53@@ -308,7 +323,7 @@
54 self.client.set_share_change_callback(a_callback)
55 self.assertTrue(self.client._share_change_callback is a_callback)
56 self.client.handle_NOTIFY_SHARE(proto_msg)
57- self.assertEquals(self.share_notif.share_id, share_resp.share_id)
58+ self.assertEqual(self.share_notif.share_id, share_resp.share_id)
59
60 def test_share_delete_callback(self):
61 """Test share_delete callback usage."""
62@@ -329,7 +344,7 @@
63 self.client.set_share_delete_callback(a_callback)
64 self.assertTrue(self.client._share_delete_callback is a_callback)
65 self.client.handle_SHARE_DELETED(proto_msg)
66- self.assertEquals(self.deleted_share_id, share_id)
67+ self.assertEqual(self.deleted_share_id, share_id)
68
69 def test_share_answer_callback(self):
70 """Test share_answer callback usage."""
71@@ -351,8 +366,8 @@
72 self.client.set_share_answer_callback(a_callback)
73 self.assertTrue(self.client._share_answer_callback is a_callback)
74 self.client.handle_SHARE_ACCEPTED(proto_msg)
75- self.assertEquals(self.answer[0], share_id)
76- self.assertEquals(self.answer[1], "Yes")
77+ self.assertEqual(self.answer[0], share_id)
78+ self.assertEqual(self.answer[1], "Yes")
79
80 def test_handle_volume_new_generation_uuid(self):
81 """Test handle_VOLUME_NEW_GENERATION with an uuid id."""
82@@ -415,7 +430,7 @@
83 root = volumes.RootVolume.from_msg(message.volume_created.root)
84
85 self.client.handle_VOLUME_CREATED(message)
86- self.assertEquals(root, self.volume)
87+ self.assertEqual(root, self.volume)
88
89 def test_handle_udf_created_passes_a_udf(self):
90 """Test handle_VOLUME_CREATED parameter passing."""
91@@ -431,7 +446,7 @@
92 udf = volumes.UDFVolume.from_msg(message.volume_created.udf)
93
94 self.client.handle_VOLUME_CREATED(message)
95- self.assertEquals(udf, self.volume)
96+ self.assertEqual(udf, self.volume)
97
98 def test_handle_share_created_passes_a_share(self):
99 """Test handle_VOLUME_CREATED parameter passing."""
100@@ -447,7 +462,7 @@
101 share = volumes.ShareVolume.from_msg(message.volume_created.share)
102
103 self.client.handle_VOLUME_CREATED(message)
104- self.assertEquals(share, self.volume)
105+ self.assertEqual(share, self.volume)
106
107 def test_handle_volume_created_if_callback_is_none(self):
108 """Test handle_VOLUME_CREATED if callback is none."""
109@@ -478,7 +493,7 @@
110 message.volume_deleted.volume = str(VOLUME)
111 self.client.handle_VOLUME_DELETED(message)
112
113- self.assertEquals(VOLUME, self.volume)
114+ self.assertEqual(VOLUME, self.volume)
115
116 def test_handle_volume_deleted_if_none(self):
117 """Test handle_VOLUME_DELETED if callback is none."""
118@@ -515,8 +530,8 @@
119
120 def test_init(self):
121 """Test request creation."""
122- self.assertEquals(PATH, self.request.path)
123- self.assertEquals(NAME, self.request.name)
124+ self.assertEqual(PATH, self.request.path)
125+ self.assertEqual(NAME, self.request.name)
126 self.assertTrue(self.request.volume_id is None)
127 self.assertTrue(self.request.node_id is None)
128
129@@ -524,11 +539,11 @@
130 """Test request start."""
131 self.request.start()
132
133- self.assertEquals(1, len(self.request.protocol.messages))
134+ self.assertEqual(1, len(self.request.protocol.messages))
135 actual_msg, = self.request.protocol.messages
136- self.assertEquals(protocol_pb2.Message.CREATE_UDF, actual_msg.type)
137- self.assertEquals(self.request.path, actual_msg.create_udf.path)
138- self.assertEquals(self.request.name, actual_msg.create_udf.name)
139+ self.assertEqual(protocol_pb2.Message.CREATE_UDF, actual_msg.type)
140+ self.assertEqual(self.request.path, actual_msg.create_udf.path)
141+ self.assertEqual(self.request.name, actual_msg.create_udf.name)
142
143 def test_process_message_error(self):
144 """Test request processMessage on error."""
145@@ -544,8 +559,8 @@
146 message.volume_created.udf.node = str(NODE)
147 self.request.processMessage(message)
148
149- self.assertEquals(str(VOLUME), self.request.volume_id, 'volume set')
150- self.assertEquals(str(NODE), self.request.node_id, 'node set')
151+ self.assertEqual(str(VOLUME), self.request.volume_id, 'volume set')
152+ self.assertEqual(str(NODE), self.request.node_id, 'node set')
153 self.assertTrue(self.done_called, 'done() was called')
154
155
156@@ -566,15 +581,15 @@
157
158 def test_init(self):
159 """Test request creation."""
160- self.assertEquals([], self.request.volumes)
161+ self.assertEqual([], self.request.volumes)
162
163 def test_start(self):
164 """Test request start."""
165 self.request.start()
166
167- self.assertEquals(1, len(self.request.protocol.messages))
168+ self.assertEqual(1, len(self.request.protocol.messages))
169 actual_msg, = self.request.protocol.messages
170- self.assertEquals(protocol_pb2.Message.LIST_VOLUMES, actual_msg.type)
171+ self.assertEqual(protocol_pb2.Message.LIST_VOLUMES, actual_msg.type)
172
173 def test_process_message_error(self):
174 """Test request processMessage on error."""
175@@ -598,10 +613,9 @@
176 root = volumes.RootVolume.from_msg(message.list_volumes.root)
177 self.request.processMessage(message)
178
179- self.assertEquals(3, len(self.request.volumes),
180- '3 volumes stored')
181- self.assertEquals([udf, share, root], self.request.volumes,
182- 'volumes stored')
183+ self.assertEqual(3, len(self.request.volumes), '3 volumes stored')
184+ self.assertEqual([udf, share, root], self.request.volumes,
185+ 'volumes stored')
186
187 message = protocol_pb2.Message()
188 message.type = protocol_pb2.Message.VOLUMES_END
189@@ -622,7 +636,7 @@
190 self.request.processMessage(message)
191
192 self.request.start()
193- self.assertEquals([], self.request.volumes)
194+ self.assertEqual([], self.request.volumes)
195
196
197 class DeleteVolumeTestCase(RequestTestCase):
198@@ -642,17 +656,17 @@
199
200 def test_init(self):
201 """Test request creation."""
202- self.assertEquals(str(VOLUME), self.request.volume_id)
203+ self.assertEqual(str(VOLUME), self.request.volume_id)
204
205 def test_start(self):
206 """Test request start."""
207 self.request.start()
208
209- self.assertEquals(1, len(self.request.protocol.messages))
210+ self.assertEqual(1, len(self.request.protocol.messages))
211 actual_msg, = self.request.protocol.messages
212- self.assertEquals(protocol_pb2.Message.DELETE_VOLUME, actual_msg.type)
213- self.assertEquals(self.request.volume_id,
214- actual_msg.delete_volume.volume)
215+ self.assertEqual(protocol_pb2.Message.DELETE_VOLUME, actual_msg.type)
216+ self.assertEqual(self.request.volume_id,
217+ actual_msg.delete_volume.volume)
218
219 def test_process_message_error(self):
220 """Test request processMessage on error."""
221@@ -685,17 +699,17 @@
222
223 def test_init(self):
224 """Test request creation."""
225- self.assertEquals(str(SHARE), self.request.share_id)
226+ self.assertEqual(str(SHARE), self.request.share_id)
227
228 def test_start(self):
229 """Test request start."""
230 self.request.start()
231
232- self.assertEquals(1, len(self.request.protocol.messages))
233+ self.assertEqual(1, len(self.request.protocol.messages))
234 actual_msg, = self.request.protocol.messages
235- self.assertEquals(protocol_pb2.Message.GET_DELTA, actual_msg.type)
236- self.assertEquals(self.request.share_id,
237- actual_msg.get_delta.share)
238+ self.assertEqual(protocol_pb2.Message.GET_DELTA, actual_msg.type)
239+ self.assertEqual(self.request.share_id,
240+ actual_msg.get_delta.share)
241
242 def test_process_message_error(self):
243 """Test request processMessage on error."""
244@@ -712,11 +726,11 @@
245 self.request.processMessage(message)
246
247 self.assertTrue(self.done_called, 'done() was called')
248- self.assertEquals(self.request.end_generation,
249- message.delta_end.generation)
250- self.assertEquals(self.request.full, message.delta_end.full)
251- self.assertEquals(self.request.free_bytes,
252- message.delta_end.free_bytes)
253+ self.assertEqual(self.request.end_generation,
254+ message.delta_end.generation)
255+ self.assertEqual(self.request.full, message.delta_end.full)
256+ self.assertEqual(self.request.free_bytes,
257+ message.delta_end.free_bytes)
258
259 def test_process_message_content(self):
260 """Test request processMessage for content."""
261@@ -748,11 +762,11 @@
262 self.request.done = was_called(self, 'done_called')
263 self.request.start()
264
265- self.assertEquals(1, len(self.request.protocol.messages))
266+ self.assertEqual(1, len(self.request.protocol.messages))
267 actual_msg, = self.request.protocol.messages
268- self.assertEquals(protocol_pb2.Message.GET_DELTA, actual_msg.type)
269- self.assertEquals(self.request.share_id,
270- actual_msg.get_delta.share)
271+ self.assertEqual(protocol_pb2.Message.GET_DELTA, actual_msg.type)
272+ self.assertEqual(self.request.share_id,
273+ actual_msg.get_delta.share)
274
275
276 class TestAuth(RequestTestCase):
277@@ -958,5 +972,124 @@
278 return d
279
280
281-if __name__ == '__main__':
282- unittest.main()
283+class ChangePublicAccessTestCase(RequestTestCase):
284+ """Test cases for ChangePublicAccess op."""
285+
286+ request_class = ChangePublicAccess
287+
288+ @defer.inlineCallbacks
289+ def setUp(self):
290+ """Initialize testing protocol."""
291+ yield super(ChangePublicAccessTestCase, self).setUp()
292+ self.protocol = FakedProtocol()
293+ self.request = self.request_class(
294+ self.protocol, share_id=SHARE, node_id=NODE, is_public=True)
295+ self.request.error = faked_error
296+ self.done_called = False
297+ self.request.done = was_called(self, 'done_called')
298+
299+ def test_init(self):
300+ """Test request creation."""
301+ self.assertEqual(self.request.share_id, str(SHARE))
302+ self.assertEqual(self.request.node_id, str(NODE))
303+ self.assertTrue(self.request.is_public)
304+
305+ def test_start(self):
306+ """Test request start."""
307+ self.request.start()
308+
309+ self.assertEqual(1, len(self.request.protocol.messages))
310+ actual_msg, = self.request.protocol.messages
311+ self.assertEqual(actual_msg.type,
312+ protocol_pb2.Message.CHANGE_PUBLIC_ACCESS)
313+ self.assertEqual(actual_msg.change_public_access.share,
314+ self.request.share_id)
315+ self.assertEqual(actual_msg.change_public_access.node,
316+ self.request.node_id)
317+ self.assertTrue(actual_msg.change_public_access.is_public)
318+
319+ def test_process_message_error(self):
320+ """Test request processMessage on error."""
321+ message = protocol_pb2.Message()
322+ self.assertRaises(FakedError, self.request.processMessage, message)
323+ self.assertIsNone(self.request.public_url)
324+
325+ def test_process_message_ok(self):
326+ """Test request processMessage on sucess."""
327+ message = protocol_pb2.Message()
328+ message.type = protocol_pb2.Message.OK
329+ message.public_url = PUBLIC_URL
330+ self.request.processMessage(message)
331+
332+ self.assertTrue(self.done_called, 'done() was called')
333+ self.assertIsNotNone(self.request.public_url)
334+
335+
336+class ListPublicFilesTestCase(RequestTestCase):
337+ """Test cases for ListPublicFiles op."""
338+
339+ request_class = ListPublicFiles
340+
341+ @defer.inlineCallbacks
342+ def setUp(self):
343+ """Initialize testing protocol."""
344+ yield super(ListPublicFilesTestCase, self).setUp()
345+ self.protocol = FakedProtocol()
346+ self.request = self.request_class(self.protocol)
347+ self.request.error = faked_error
348+ self.done_called = False
349+ self.request.done = was_called(self, 'done_called')
350+
351+ def test_start(self):
352+ """Test request start."""
353+ self.request.start()
354+
355+ self.assertEqual(1, len(self.request.protocol.messages))
356+ actual_msg, = self.request.protocol.messages
357+ self.assertEqual(actual_msg.type,
358+ protocol_pb2.Message.LIST_PUBLIC_FILES)
359+
360+ def test_process_message_error(self):
361+ """Test request processMessage on error."""
362+ message = protocol_pb2.Message()
363+ self.assertRaises(FakedError, self.request.processMessage, message)
364+ self.assertEqual(self.request.public_files, [])
365+
366+ def test_process_message_ok(self):
367+ """Test request processMessage on sucess."""
368+ # send two nodes
369+ message = protocol_pb2.Message()
370+ message.type = protocol_pb2.Message.PUBLIC_FILE_INFO
371+ message.public_file_info.share = 'share_id'
372+ message.public_file_info.node = 'node_id_1'
373+ message.public_file_info.is_public = True
374+ message.public_file_info.public_url = "test url 123"
375+ self.request.processMessage(message)
376+
377+ message = protocol_pb2.Message()
378+ message.type = protocol_pb2.Message.PUBLIC_FILE_INFO
379+ message.public_file_info.share = 'share_id'
380+ message.public_file_info.node = 'node_id_2'
381+ message.public_file_info.is_public = True
382+ message.public_file_info.public_url = "test url 456"
383+ self.request.processMessage(message)
384+
385+ # finish
386+ message = protocol_pb2.Message()
387+ message.type = protocol_pb2.Message.PUBLIC_FILE_INFO_END
388+ self.request.processMessage(message)
389+
390+ # check
391+ self.assertTrue(self.done_called, 'done() was called')
392+ node1, node2 = self.request.public_files
393+ print("NNNNNNNNNNNNO 1", node1)
394+
395+ self.assertEqual(node1.share_id, 'share_id')
396+ self.assertEqual(node1.node_id, 'node_id_1')
397+ self.assertEqual(node1.is_public, True)
398+ self.assertEqual(node1.public_url, 'test url 123')
399+
400+ self.assertEqual(node2.share_id, 'share_id')
401+ self.assertEqual(node2.node_id, 'node_id_2')
402+ self.assertEqual(node2.is_public, True)
403+ self.assertEqual(node2.public_url, 'test url 456')
404
405=== added file 'tests/test_public_file_info.py'
406--- tests/test_public_file_info.py 1970-01-01 00:00:00 +0000
407+++ tests/test_public_file_info.py 2016-11-15 23:38:26 +0000
408@@ -0,0 +1,74 @@
409+# -*- coding: utf-8 -*-
410+
411+# Copyright 2016 Chicharreros (https://launchpad.net/~chicharreros)
412+#
413+# This program is free software: you can redistribute it and/or modify it
414+# under the terms of the GNU Affero General Public License version 3,
415+# as published by the Free Software Foundation.
416+#
417+# This program is distributed in the hope that it will be useful, but
418+# WITHOUT ANY WARRANTY; without even the implied warranties of
419+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
420+# PURPOSE. See the GNU Affero General Public License for more details.
421+#
422+# You should have received a copy of the GNU Affero General Public License
423+# along with this program. If not, see <http://www.gnu.org/licenses/>.
424+#
425+# In addition, as a special exception, the copyright holders give
426+# permission to link the code of portions of this program with the
427+# OpenSSL library under certain conditions as described in each
428+# individual source file, and distribute linked combinations
429+# including the two.
430+# You must obey the GNU General Public License in all respects
431+# for all of the code used other than OpenSSL. If you modify
432+# file(s) with this exception, you may extend this exception to your
433+# version of the file(s), but you are not obligated to do so. If you
434+# do not wish to do so, delete this exception statement from your
435+# version. If you delete this exception statement from all source
436+# files in the program, then also delete it here.
437+
438+"""Tests for generation node data type."""
439+
440+import unittest
441+
442+from ubuntuone.storageprotocol import protocol_pb2, public_file_info, request
443+
444+SHARE = "share_id"
445+NODE = "node_id"
446+PUBLIC_URL = "test public url"
447+
448+
449+def get_message():
450+ """Returns a PUBLIC_FILE_INFO message with sample data in the fields."""
451+ message = protocol_pb2.Message()
452+ message.type = protocol_pb2.Message.PUBLIC_FILE_INFO
453+ message.public_file_info.share = str(SHARE)
454+ message.public_file_info.node = str(NODE)
455+ message.public_file_info.is_public = True
456+ message.public_file_info.public_url = PUBLIC_URL
457+ return message
458+
459+
460+class DeltaTestCase(unittest.TestCase):
461+ """Check Delta data type."""
462+
463+ def test_correct_attributes(self):
464+ """Assert over attribute correctness."""
465+ m = public_file_info.PublicFileInfo.from_message(get_message())
466+ self.assertEqual(m.share_id, SHARE)
467+ self.assertEqual(m.node_id, NODE)
468+ self.assertEqual(m.is_public, True)
469+ self.assertEqual(m.public_url, PUBLIC_URL)
470+
471+ def test_is_equal(self):
472+ """Test object equality."""
473+ m = public_file_info.PublicFileInfo.from_message(get_message())
474+ m2 = public_file_info.PublicFileInfo.from_message(get_message())
475+ self.assertEqual(m, m2)
476+
477+ def test_root_share_id(self):
478+ """Test that DeltaInfo.from_message works with request.ROOT."""
479+ msg = get_message()
480+ msg.public_file_info.share = request.ROOT
481+ m = public_file_info.PublicFileInfo.from_message(msg)
482+ self.assertEqual(m.share_id, request.ROOT)
483
484=== modified file 'ubuntuone/storageprotocol/client.py'
485--- ubuntuone/storageprotocol/client.py 2016-10-11 19:01:04 +0000
486+++ ubuntuone/storageprotocol/client.py 2016-11-15 23:38:26 +0000
487@@ -1,12 +1,5 @@
488-# ubuntuone.storageprotocol.client - the storage protocol client
489-#
490-# Author: Lucio Torre <lucio.torre@canonical.com>
491-# Author: Natalia B. Bidart <natalia.bidart@canonical.com>
492-# Author: Guillermo Gonzalez <guillermo.gonzalez@canonical.com>
493-# Author: Facundo Batista <facundo@canonical.com>
494-# Author: Alejandro J. Cura <alecu@canonical.com>
495-#
496 # Copyright 2009-2015 Canonical Ltd.
497+# Copyright 2016 Chicharreros (https://launchpad.net/~chicharreros)
498 #
499 # This program is free software: you can redistribute it and/or modify it
500 # under the terms of the GNU Affero General Public License version 3,
501@@ -32,6 +25,7 @@
502 # do not wish to do so, delete this exception statement from your
503 # version. If you delete this exception statement from all source
504 # files in the program, then also delete it here.
505+
506 """The storage protocol client."""
507
508 import logging
509@@ -47,6 +41,7 @@
510 from ubuntuone.storageprotocol import (
511 delta,
512 protocol_pb2,
513+ public_file_info,
514 request,
515 sharersp,
516 volumes,
517@@ -538,6 +533,18 @@
518 p.start()
519 return p.deferred
520
521+ def change_public_access(self, share_id, node_id, is_public):
522+ """Change the public access of a file."""
523+ p = ChangePublicAccess(self, share_id, node_id, is_public)
524+ p.start()
525+ return p.deferred
526+
527+ def list_public_files(self):
528+ """List the public files."""
529+ p = ListPublicFiles(self)
530+ p.start()
531+ return p.deferred
532+
533 def delete_volume(self, volume_id):
534 """Delete 'volume' on the server, removing the associated tree.
535
536@@ -961,6 +968,62 @@
537 self._default_process_message(message)
538
539
540+class ChangePublicAccess(request.Request):
541+ """Change the public access of a file."""
542+
543+ __slots__ = ('share_id', 'node_id', 'is_public', 'public_url')
544+
545+ def __init__(self, protocol, share_id, node_id, is_public):
546+ request.Request.__init__(self, protocol)
547+ self.public_url = None
548+
549+ self.share_id = str(share_id)
550+ self.node_id = str(node_id)
551+ self.is_public = is_public
552+
553+ def _start(self):
554+ message = protocol_pb2.Message()
555+ message.type = protocol_pb2.Message.CHANGE_PUBLIC_ACCESS
556+ message.change_public_access.share = self.share_id
557+ message.change_public_access.node = self.node_id
558+ message.change_public_access.is_public = self.is_public
559+ self.sendMessage(message)
560+
561+ def processMessage(self, message):
562+ if message.type == protocol_pb2.Message.OK:
563+ self.public_url = message.public_url
564+ self.done()
565+ else:
566+ self._default_process_message(message)
567+
568+
569+class ListPublicFiles(request.Request):
570+ """List all the public files for an user."""
571+
572+ __slots__ = ('public_files',)
573+
574+ def __init__(self, protocol):
575+ """List volumes."""
576+ request.Request.__init__(self, protocol)
577+ self.public_files = []
578+
579+ def _start(self):
580+ """Send the LIST_PUBLIC_FILES message to the server."""
581+ message = protocol_pb2.Message()
582+ message.type = protocol_pb2.Message.LIST_PUBLIC_FILES
583+ self.sendMessage(message)
584+
585+ def processMessage(self, message):
586+ """Process the answer from the server."""
587+ if message.type == protocol_pb2.Message.PUBLIC_FILE_INFO:
588+ info = public_file_info.PublicFileInfo.from_message(message)
589+ self.public_files.append(info)
590+ elif message.type == protocol_pb2.Message.PUBLIC_FILE_INFO_END:
591+ self.done()
592+ else:
593+ self._default_process_message(message)
594+
595+
596 class Move(request.Request):
597 """Move a node.
598
599
600=== modified file 'ubuntuone/storageprotocol/protocol.proto'
601--- ubuntuone/storageprotocol/protocol.proto 2012-03-29 20:28:09 +0000
602+++ ubuntuone/storageprotocol/protocol.proto 2016-11-15 23:38:26 +0000
603@@ -1,7 +1,6 @@
604 /*
605- ubuntuone.storageprotocol.protocol_pb2 - storage protocol
606-
607 Copyright 2009-2012 Canonical Ltd.
608+ Copyright 2016 Chicharreros (https://launchpad.net/~chicharreros)
609
610 This program is free software: you can redistribute it and/or modify it
611 under the terms of the GNU Affero General Public License version 3,
612@@ -97,6 +96,11 @@
613 GET_DELTA = 51; // ask for a delta
614 DELTA_INFO = 52; // a row of the delta
615 DELTA_END = 53; // marks the end of a delta
616+
617+ CHANGE_PUBLIC_ACCESS = 55; // change the public access of a file
618+ PUBLIC_FILE_INFO = 56; // information for a public file
619+ PUBLIC_FILE_INFO_END = 57; // marks the end of a bunch of public file infos
620+ LIST_PUBLIC_FILES = 58; // get the list of public files for the user
621 }
622
623 required MessageType type = 2; // The type of the message contained
624@@ -159,6 +163,11 @@
625 optional GetDelta get_delta = 38;
626 optional DeltaInfo delta_info = 39;
627 optional DeltaEnd delta_end = 40;
628+
629+ // public files
630+ optional ChangePublicAccess change_public_access = 45;
631+ optional bytes public_url = 46;
632+ optional PublicFileInfo public_file_info = 47;
633 }
634
635 message Error {
636@@ -481,6 +490,19 @@
637 optional uint64 free_bytes = 3; // this will be just a hint if full == False
638 }
639
640+message ChangePublicAccess {
641+ optional bytes share = 1;
642+ optional bytes node = 2;
643+ optional bool is_public = 3;
644+}
645+
646+message PublicFileInfo {
647+ optional bytes share = 1;
648+ optional bytes node = 2;
649+ optional bool is_public = 3;
650+ optional bytes public_url = 4;
651+}
652+
653 /*
654 == changes ==
655
656
657=== added file 'ubuntuone/storageprotocol/public_file_info.py'
658--- ubuntuone/storageprotocol/public_file_info.py 1970-01-01 00:00:00 +0000
659+++ ubuntuone/storageprotocol/public_file_info.py 2016-11-15 23:38:26 +0000
660@@ -0,0 +1,55 @@
661+# Copyright 2016 Chicharreros (https://launchpad.net/~chicharreros)
662+#
663+# This program is free software: you can redistribute it and/or modify it
664+# under the terms of the GNU Affero General Public License version 3,
665+# as published by the Free Software Foundation.
666+#
667+# This program is distributed in the hope that it will be useful, but
668+# WITHOUT ANY WARRANTY; without even the implied warranties of
669+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
670+# PURPOSE. See the GNU Affero General Public License for more details.
671+#
672+# You should have received a copy of the GNU Affero General Public License
673+# along with this program. If not, see <http://www.gnu.org/licenses/>.
674+#
675+# In addition, as a special exception, the copyright holders give
676+# permission to link the code of portions of this program with the
677+# OpenSSL library under certain conditions as described in each
678+# individual source file, and distribute linked combinations
679+# including the two.
680+# You must obey the GNU General Public License in all respects
681+# for all of the code used other than OpenSSL. If you modify
682+# file(s) with this exception, you may extend this exception to your
683+# version of the file(s), but you are not obligated to do so. If you
684+# do not wish to do so, delete this exception statement from your
685+# version. If you delete this exception statement from all source
686+# files in the program, then also delete it here.
687+
688+"""Wrapper class for public file information."""
689+
690+
691+class PublicFileInfo(object):
692+ """Hold the public file object information."""
693+
694+ def __init__(self, share_id, node_id, is_public, public_url):
695+ self.share_id = share_id
696+ self.node_id = node_id
697+ self.is_public = is_public
698+ self.public_url = public_url
699+
700+ @classmethod
701+ def from_message(cls, message):
702+ """Creates the object using the information from a message."""
703+ info = message.public_file_info
704+ result = cls(
705+ share_id=info.share,
706+ node_id=info.node,
707+ is_public=info.is_public,
708+ public_url=info.public_url)
709+ return result
710+
711+ def __eq__(self, other):
712+ if not isinstance(other, self.__class__):
713+ return False
714+
715+ return self.__dict__ == other.__dict__

Subscribers

People subscribed via source and target branches

to all changes: