文件操作 - container.py
返回文件管理
返回主菜单
删除本文件
文件: /usr/lib/python2.7/site-packages/cloudfiles/container.py
编辑文件内容
""" container operations Containers are storage compartments where you put your data (objects). A container is similar to a directory or folder on a conventional filesystem with the exception that they exist in a flat namespace, you can not create containers inside of containers. See COPYING for license information. """ from storage_object import Object, ObjectResults from errors import ResponseError, InvalidContainerName, InvalidObjectName, \ ContainerNotPublic, CDNNotEnabled from utils import requires_name import consts from fjson import json_loads # Because HTTPResponse objects *have* to have read() called on them # before they can be used again ... # pylint: disable-msg=W0612 class Container(object): """ Container object and Object instance factory. If your account has the feature enabled, containers can be publically shared over a global content delivery network. @ivar name: the container's name (generally treated as read-only) @type name: str @ivar object_count: the number of objects in this container (cached) @type object_count: number @ivar size_used: the sum of the sizes of all objects in this container (cached) @type size_used: number @ivar cdn_ttl: the time-to-live of the CDN's public cache of this container (cached, use make_public to alter) @type cdn_ttl: number @ivar cdn_log_retention: retention of the logs in the container. @type cdn_log_retention: bool @undocumented: _fetch_cdn_data @undocumented: _list_objects_raw """ def __set_name(self, name): # slashes make for invalid names if isinstance(name, (str, unicode)) and \ ('/' in name or len(name) > consts.container_name_limit): raise InvalidContainerName(name) self._name = name name = property(fget=lambda self: self._name, fset=__set_name, doc="the name of the container (read-only)") def __init__(self, connection=None, name=None, count=None, size=None, metadata=None): """ Containers will rarely if ever need to be instantiated directly by the user. Instead, use the L{create_container<Connection.create_container>}, L{get_container<Connection.get_container>}, L{list_containers<Connection.list_containers>} and other methods on a valid Connection object. """ self._name = None self.name = name self.conn = connection self.object_count = count self.size_used = size self.metadata = metadata self.cdn_uri = None self.cdn_ssl_uri = None self.cdn_streaming_uri = None self.cdn_ttl = None self.cdn_log_retention = None if self.metadata == None: self.metadata = {} if connection.cdn_enabled: self._fetch_cdn_data() @requires_name(InvalidContainerName) def update_metadata(self, metadata): """ Update Container Metadata >>> metadata = {'x-container-meta-foo' : 'bar'} >>> container.update_metadata(metadata) @param metadata: A dictionary containing metadata. @type metadata: dict """ response = self.conn.make_request('POST', [self.name], hdrs=metadata) response.read() if (response.status < 200) or (response.status > 299): raise ResponseError(response.status, response.reason) def enable_static_web(self, index=None, listings=None, error=None, listings_css=None): """ Enable static web for this Container >>> container.enable_static_web('index.html', 'error.html', True, 'style.css') @param index: The name of the index landing page @type index : str @param listings: A boolean value to enable listing. @type error: bool @param listings_css: The file to be used when applying CSS to the listing. @type listings_css: str @param error: The suffix to be used for 404 and 401 error pages. @type error: str """ metadata = {'X-Container-Meta-Web-Index' : '', 'X-Container-Meta-Web-Listings' : '', 'X-Container-Meta-Web-Error' : '', 'X-Container-Meta-Web-Listings-CSS' : ''} if index is not None: metadata['X-Container-Meta-Web-Index'] = index if listings is not None: metadata['X-Container-Meta-Web-Listings'] = str(listings) if error is not None: metadata['X-Container-Meta-Web-Error'] = error if listings_css is not None: metadata['X-Container-Meta-Web-Listings-CSS'] = listings_css self.update_metadata(metadata) def disable_static_web(self): """ Disable static web for this Container >>> container.disable_static_web() """ self.enable_static_web() def enable_object_versioning(self, container_name): """ Enable object versioning on this container >>> container.enable_object_versioning('container_i_want_versions_to_go_to') @param container_url: The container where versions will be stored @type container_name: str """ self.update_metadata({'X-Versions-Location' : container_name}) def disable_object_versioning(self): """ Disable object versioning on this container >>> container.disable_object_versioning() """ self.update_metadata({'X-Versions-Location' : ''}) @requires_name(InvalidContainerName) def _fetch_cdn_data(self): """ Fetch the object's CDN data from the CDN service """ response = self.conn.cdn_request('HEAD', [self.name]) if response.status >= 200 and response.status < 300: for hdr in response.getheaders(): if hdr[0].lower() == 'x-cdn-uri': self.cdn_uri = hdr[1] if hdr[0].lower() == 'x-ttl': self.cdn_ttl = int(hdr[1]) if hdr[0].lower() == 'x-cdn-ssl-uri': self.cdn_ssl_uri = hdr[1] if hdr[0].lower() == 'x-cdn-streaming-uri': self.cdn_streaming_uri = hdr[1] if hdr[0].lower() == 'x-log-retention': self.cdn_log_retention = hdr[1] == "True" and True or False @requires_name(InvalidContainerName) def make_public(self, ttl=consts.default_cdn_ttl): """ Either publishes the current container to the CDN or updates its CDN attributes. Requires CDN be enabled on the account. >>> container.make_public(ttl=604800) # expire in 1 week @param ttl: cache duration in seconds of the CDN server @type ttl: number """ if not self.conn.cdn_enabled: raise CDNNotEnabled() if self.cdn_uri: request_method = 'POST' else: request_method = 'PUT' hdrs = {'X-TTL': str(ttl), 'X-CDN-Enabled': 'True'} response = self.conn.cdn_request(request_method, \ [self.name], hdrs=hdrs) if (response.status < 200) or (response.status >= 300): raise ResponseError(response.status, response.reason) self.cdn_ttl = ttl for hdr in response.getheaders(): if hdr[0].lower() == 'x-cdn-uri': self.cdn_uri = hdr[1] if hdr[0].lower() == 'x-cdn-ssl-uri': self.cdn_ssl_uri = hdr[1] @requires_name(InvalidContainerName) def make_private(self): """ Disables CDN access to this container. It may continue to be available until its TTL expires. >>> container.make_private() """ if not self.conn.cdn_enabled: raise CDNNotEnabled() hdrs = {'X-CDN-Enabled': 'False'} self.cdn_uri = None response = self.conn.cdn_request('POST', [self.name], hdrs=hdrs) if (response.status < 200) or (response.status >= 300): raise ResponseError(response.status, response.reason) @requires_name(InvalidContainerName) def purge_from_cdn(self, email=None): """ Purge Edge cache for all object inside of this container. You will be notified by email if one is provided when the job completes. >>> container.purge_from_cdn("user@dmain.com") or >>> container.purge_from_cdn("user@domain.com,user2@domain.com") or >>> container.purge_from_cdn() @param email: A Valid email address @type email: str """ if not self.conn.cdn_enabled: raise CDNNotEnabled() if email: hdrs = {"X-Purge-Email": email} response = self.conn.cdn_request('DELETE', [self.name], hdrs=hdrs) else: response = self.conn.cdn_request('DELETE', [self.name]) if (response.status < 200) or (response.status >= 300): raise ResponseError(response.status, response.reason) @requires_name(InvalidContainerName) def log_retention(self, log_retention=consts.cdn_log_retention): """ Enable CDN log retention on the container. If enabled logs will be periodically (at unpredictable intervals) compressed and uploaded to a ".CDN_ACCESS_LOGS" container in the form of "container_name/YYYY/MM/DD/HH/XXXX.gz". Requires CDN be enabled on the account. >>> container.log_retention(True) @param log_retention: Enable or disable logs retention. @type log_retention: bool """ if not self.conn.cdn_enabled: raise CDNNotEnabled() hdrs = {'X-Log-Retention': log_retention} response = self.conn.cdn_request('POST', [self.name], hdrs=hdrs) if (response.status < 200) or (response.status >= 300): raise ResponseError(response.status, response.reason) self.cdn_log_retention = log_retention def is_public(self): """ Returns a boolean indicating whether or not this container is publically accessible via the CDN. >>> container.is_public() False >>> container.make_public() >>> container.is_public() True @rtype: bool @return: whether or not this container is published to the CDN """ if not self.conn.cdn_enabled: raise CDNNotEnabled() return self.cdn_uri is not None @requires_name(InvalidContainerName) def public_uri(self): """ Return the URI for this container, if it is publically accessible via the CDN. >>> connection['container1'].public_uri() 'http://c00061.cdn.cloudfiles.rackspacecloud.com' @rtype: str @return: the public URI for this container """ if not self.is_public(): raise ContainerNotPublic() return self.cdn_uri @requires_name(InvalidContainerName) def public_ssl_uri(self): """ Return the SSL URI for this container, if it is publically accessible via the CDN. >>> connection['container1'].public_ssl_uri() 'https://c61.ssl.cf0.rackcdn.com' @rtype: str @return: the public SSL URI for this container """ if not self.is_public(): raise ContainerNotPublic() return self.cdn_ssl_uri @requires_name(InvalidContainerName) def public_streaming_uri(self): """ Return the Streaming URI for this container, if it is publically accessible via the CDN. >>> connection['container1'].public_ssl_uri() 'https://c61.stream.rackcdn.com' @rtype: str @return: the public Streaming URI for this container """ if not self.is_public(): raise ContainerNotPublic() return self.cdn_streaming_uri @requires_name(InvalidContainerName) def create_object(self, object_name): """ Return an L{Object} instance, creating it if necessary. When passed the name of an existing object, this method will return an instance of that object, otherwise it will create a new one. >>> container.create_object('new_object') <cloudfiles.storage_object.Object object at 0xb778366c> >>> obj = container.create_object('new_object') >>> obj.name 'new_object' @type object_name: str @param object_name: the name of the object to create @rtype: L{Object} @return: an object representing the newly created storage object """ return Object(self, object_name) @requires_name(InvalidContainerName) def get_objects(self, prefix=None, limit=None, marker=None, path=None, delimiter=None, **parms): """ Return a result set of all Objects in the Container. Keyword arguments are treated as HTTP query parameters and can be used to limit the result set (see the API documentation). >>> container.get_objects(limit=2) ObjectResults: 2 objects >>> for obj in container.get_objects(): ... print obj.name new_object old_object @param prefix: filter the results using this prefix @type prefix: str @param limit: return the first "limit" objects found @type limit: int @param marker: return objects whose names are greater than "marker" @type marker: str @param path: return all objects in "path" @type path: str @param delimiter: use this character as a delimiter for subdirectories @type delimiter: char @rtype: L{ObjectResults} @return: an iterable collection of all storage objects in the container """ return ObjectResults(self, self.list_objects_info( prefix, limit, marker, path, delimiter, **parms)) @requires_name(InvalidContainerName) def get_object(self, object_name): """ Return an L{Object} instance for an existing storage object. If an object with a name matching object_name does not exist then a L{NoSuchObject} exception is raised. >>> obj = container.get_object('old_object') >>> obj.name 'old_object' @param object_name: the name of the object to retrieve @type object_name: str @rtype: L{Object} @return: an Object representing the storage object requested """ return Object(self, object_name, force_exists=True) @requires_name(InvalidContainerName) def list_objects_info(self, prefix=None, limit=None, marker=None, path=None, delimiter=None, **parms): """ Return information about all objects in the Container. Keyword arguments are treated as HTTP query parameters and can be used limit the result set (see the API documentation). >>> conn['container1'].list_objects_info(limit=2) [{u'bytes': 4820, u'content_type': u'application/octet-stream', u'hash': u'db8b55400b91ce34d800e126e37886f8', u'last_modified': u'2008-11-05T00:56:00.406565', u'name': u'new_object'}, {u'bytes': 1896, u'content_type': u'application/octet-stream', u'hash': u'1b49df63db7bc97cd2a10e391e102d4b', u'last_modified': u'2008-11-05T00:56:27.508729', u'name': u'old_object'}] @param prefix: filter the results using this prefix @type prefix: str @param limit: return the first "limit" objects found @type limit: int @param marker: return objects with names greater than "marker" @type marker: str @param path: return all objects in "path" @type path: str @param delimiter: use this character as a delimiter for subdirectories @type delimiter: char @rtype: list({"name":"...", "hash":..., "size":..., "type":...}) @return: a list of all container info as dictionaries with the keys "name", "hash", "size", and "type" """ parms['format'] = 'json' resp = self._list_objects_raw( prefix, limit, marker, path, delimiter, **parms) return json_loads(resp) @requires_name(InvalidContainerName) def list_objects(self, prefix=None, limit=None, marker=None, path=None, delimiter=None, **parms): """ Return names of all L{Object}s in the L{Container}. Keyword arguments are treated as HTTP query parameters and can be used to limit the result set (see the API documentation). >>> container.list_objects() ['new_object', 'old_object'] @param prefix: filter the results using this prefix @type prefix: str @param limit: return the first "limit" objects found @type limit: int @param marker: return objects with names greater than "marker" @type marker: str @param path: return all objects in "path" @type path: str @param delimiter: use this character as a delimiter for subdirectories @type delimiter: char @rtype: list(str) @return: a list of all container names """ resp = self._list_objects_raw(prefix=prefix, limit=limit, marker=marker, path=path, delimiter=delimiter, **parms) return resp.splitlines() @requires_name(InvalidContainerName) def _list_objects_raw(self, prefix=None, limit=None, marker=None, path=None, delimiter=None, **parms): """ Returns a chunk list of storage object info. """ if prefix: parms['prefix'] = prefix if limit: parms['limit'] = limit if marker: parms['marker'] = marker if delimiter: parms['delimiter'] = delimiter if not path is None: parms['path'] = path # empty strings are valid response = self.conn.make_request('GET', [self.name], parms=parms) if (response.status < 200) or (response.status > 299): response.read() raise ResponseError(response.status, response.reason) return response.read() def __getitem__(self, key): return self.get_object(key) def __str__(self): return self.name @requires_name(InvalidContainerName) def delete_object(self, object_name): """ Permanently remove a storage object. >>> container.list_objects() ['new_object', 'old_object'] >>> container.delete_object('old_object') >>> container.list_objects() ['new_object'] @param object_name: the name of the object to retrieve @type object_name: str """ if isinstance(object_name, Object): object_name = object_name.name if not object_name: raise InvalidObjectName(object_name) response = self.conn.make_request('DELETE', [self.name, object_name]) if (response.status < 200) or (response.status > 299): response.read() raise ResponseError(response.status, response.reason) response.read() class ContainerResults(object): """ An iterable results set object for Containers. This class implements dictionary- and list-like interfaces. """ def __init__(self, conn, containers=list()): self._containers = containers self._names = [k['name'] for k in containers] self.conn = conn def __getitem__(self, key): return Container(self.conn, self._containers[key]['name'], self._containers[key]['count'], self._containers[key]['bytes']) def __getslice__(self, i, j): return [Container(self.conn, k['name'], k['count'], \ k['size']) for k in self._containers[i:j]] def __contains__(self, item): return item in self._names def __repr__(self): return 'ContainerResults: %s containers' % len(self._containers) __str__ = __repr__ def __len__(self): return len(self._containers) def index(self, value, *args): """ returns an integer for the first index of value """ return self._names.index(value, *args) def count(self, value): """ returns the number of occurrences of value """ return self._names.count(value) # vim:set ai sw=4 ts=4 tw=0 expandtab:
修改文件时间
将文件时间修改为当前时间的前一年
删除文件