~ubuntu-branches/ubuntu/lucid/ubuntuone-storage-protocol/lucid-security

« back to all changes in this revision

Viewing changes to ubuntuone/storageprotocol/dircontent.py

  • Committer: Bazaar Package Importer
  • Author(s): Rodney Dawes
  • Date: 2009-06-30 12:00:00 UTC
  • Revision ID: james.westby@ubuntu.com-20090630120000-2k2hvba9epf0mfgl
Tags: upstream-0.90.3
ImportĀ upstreamĀ versionĀ 0.90.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# ubuntuone.storageprotocol.dircontent - directory content handling
 
2
#
 
3
# Author: Tim Cole <tim.cole@canonical.com>
 
4
#
 
5
# Copyright 2009 Canonical Ltd.
 
6
#
 
7
# This program is free software: you can redistribute it and/or modify it 
 
8
# under the terms of the GNU Affero General Public License version 3,
 
9
# as published by the Free Software Foundation.
 
10
#
 
11
# This program is distributed in the hope that it will be useful, but 
 
12
# WITHOUT ANY WARRANTY; without even the implied warranties of 
 
13
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
 
14
# PURPOSE.  See the GNU Affero General Public License for more details.
 
15
#
 
16
# You should have received a copy of the GNU Affero General Public License
 
17
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
18
"""
 
19
Standard routines for working with directory content.
 
20
 
 
21
"""
 
22
 
 
23
# DIRECTORY, FILE, and SYMLINK are for re-export
 
24
# pylint: disable-msg=W0611
 
25
from ubuntuone.storageprotocol.dircontent_pb2 import \
 
26
    DirectoryContent, DIRECTORY, FILE, SYMLINK
 
27
 
 
28
def parse_dir_content(stream):
 
29
    """Unserializes directory content from a stream.
 
30
 
 
31
    @param stream: an IO-alike stream object
 
32
    @return: a generator yielding DirEntry objects
 
33
 
 
34
    """
 
35
    raw_content = stream.read()
 
36
    unserialized_content = DirectoryContent()
 
37
    # XXX: what exceptions can protobuf's parser raise?
 
38
    unserialized_content.ParseFromString(raw_content)
 
39
 
 
40
    for entry in unserialized_content.entries:
 
41
        yield DirEntry(name=entry.name, node_type=entry.node_type,
 
42
                       uuid=entry.node)
 
43
 
 
44
def by_utf8_name(entry_a, entry_b):
 
45
    """Compares two entries by the UTF-8 form of their names."""
 
46
    return cmp(entry_a.utf8_name, entry_b.utf8_name)
 
47
 
 
48
def write_dir_content(entries, stream):
 
49
    """Takes a sequence of DirEntry objects, sorts them, and writes
 
50
    the corresponding serialized directory content to the given stream.
 
51
 
 
52
    @param entries: an iterator producing DirEntry objects
 
53
    @param stream: an IO-compatible stream to write to
 
54
 
 
55
    """
 
56
    sorted_entries = sorted(entries, by_utf8_name)
 
57
    for chunk in yield_presorted_dir_content(sorted_entries):
 
58
        stream.write(chunk)
 
59
 
 
60
def yield_presorted_dir_content(sorted_entries):
 
61
    """Takes a presorted sequence of DirEntry objects and yields each
 
62
    chunks of serialized content.
 
63
 
 
64
    @param sorted_entries: a presorted sequence of DirEntry objects
 
65
 
 
66
    """
 
67
 
 
68
    # A series of concatenated DirectoryContent objects is equivalent to
 
69
    # a single DirectoryContent object with fields repeated.  Among other
 
70
    # things, this makes it easy to re-use the same protobuf objects for
 
71
    # each entry that we serialize.
 
72
    content = DirectoryContent()
 
73
    pb_entry = content.entries.add()
 
74
 
 
75
    for entry in sorted_entries:
 
76
        pb_entry.name = entry.name
 
77
        pb_entry.node_type = entry.node_type
 
78
        pb_entry.node = entry.uuid
 
79
        yield content.SerializeToString()
 
80
 
 
81
 
 
82
class DirEntry(object):
 
83
    """An object representing a directory entry.
 
84
 
 
85
    @attr name: the node's name in the directory as a unicode string
 
86
    @attr utf8_name: the node's name encoded in UTF-8
 
87
    @attr node_type: the node's type (one of FILE, DIRECTORY, or SYMLINK)
 
88
    @attr uuid: the node's server-side UUID
 
89
 
 
90
    """
 
91
 
 
92
    def __init__(self, name=None, utf8_name=None, node_type=None, uuid=None):
 
93
        """Initializes a directory entry object.  Providing either the unicode
 
94
        or UTF-8 names will result in both name fields being set.
 
95
 
 
96
        @param name: the node's name in the directory
 
97
        @param utf8_name: the node's name encoded in UTF-8
 
98
        @param node_type: the node's type
 
99
        @param uuid: the node's server-sude UUID
 
100
 
 
101
        """
 
102
        if name is not None:
 
103
            self.name = name
 
104
        elif utf8_name is not None:
 
105
            self.name = utf8_name.decode("utf-8")
 
106
        else:
 
107
            self.name = None
 
108
 
 
109
        if utf8_name is not None:
 
110
            self.utf8_name = utf8_name
 
111
        elif name is not None:
 
112
            self.utf8_name = name.encode("utf-8")
 
113
        else:
 
114
            self.utf8_name = None
 
115
 
 
116
        self.node_type = node_type
 
117
        self.uuid = uuid
 
118
 
 
119
    def __eq__(self, other):
 
120
        if isinstance(other, DirEntry):
 
121
            return self.name == other.name and \
 
122
                   self.utf8_name == other.utf8_name and \
 
123
                   self.node_type == other.node_type and \
 
124
                   self.uuid == other.uuid
 
125
        else:
 
126
            return False