def mkdir(self, name, parent=None, by_name=False, share=0): """Create a directory if it does not exists and return its id """ self._check() if not parent: parent = self.ROOT_ID elif by_name: parent = self._convert_to_id(parent, False) params = urllib.urlencode( { "action": "create_folder", "api_key": self._api_key, "auth_token": self._auth_token, "parent_id": encode(parent), "name": encode(name), "share": share, } ) logger.debug("mkdir params: {}".format(params)) response = urllib.urlopen(self.REST_URL, params) tree = self._parse_response(response) folder = map_element(tree.find("folder")) self._log_response(folder) return folder
def download_file(self, file_id, localdir=None, by_name=False, block_size=65536): """Download the file with the given id to a local directory Refer: http://developers.box.com/docs/#files-download-a-file """ self._check() if by_name: file_id = self._convert_to_id(file_id, True) url = self.DOWNLOAD_URL.format(encode(file_id)) logger.debug("download url: {}".format(url)) stream = self._request(url, None, {}, None, False) meta = stream.info() name = self._get_filename(meta) size = int(meta.getheaders("Content-Length")[0]) logger.debug("filename: {} with size: {}".format(name, size)) localdir = encode(localdir or ".") with open(os.path.join(localdir, name), 'wb') as f: while True: buf = stream.read(block_size) if not buf: break f.write(buf)
def download_file(self, file_id, localdir=None, by_name=False, block_size=65536): """Download the file with the given id to a local directory""" self._check() if by_name: file_id = self._convert_to_id(file_id, True) url = self.DOWNLOAD_URL.format(self._auth_token, encode(file_id)) logger.debug("download url: {}".format(url)) stream = urllib2.urlopen(url) status = stream.getcode() if status / 100 != 2: logger.error("bad status: {}".format(status)) raise StatusError(status) meta = stream.info() name = self._get_filename(meta) size = int(meta.getheaders("Content-Length")[0]) logger.debug("filename: {} with size: {}".format(name, size)) localdir = encode(localdir or ".") with open(os.path.join(localdir, name), 'wb') as f: while True: buffer = stream.read(block_size) if not buffer: break f.write(buffer)
def _rename(self, is_file, id_, new_name, by_name): self._check() if by_name: id_ = self._convert_to_id(id_, is_file) params = urllib.urlencode({ 'action': "rename", 'api_key': self._api_key, 'auth_token': self._auth_token, 'target': "file" if is_file else "folder", 'target_id': encode(id_), 'new_name': encode(new_name)}) logger.debug("rename params: {}".format(params)) response = urllib.urlopen(self.REST_URL, params) tree = self._parse_response(response) self._log_response(tree)
def get_file_info(self, file_id, is_file=True, by_name=False): """Get file/folder's detailed information Refer: http://developers.box.com/docs/#files-get http://developers.box.com/docs/#folders-get-information-about-a-folder """ self._check() if is_file: type_ = "file" else: type_ = "folder" if by_name: file_id = self._convert_to_id(file_id, is_file) url = "{}{}s/{}".format(self.BASE_URL, type_, encode(file_id)) try: return self._request(url) except FileNotFoundError: logger.error(u"cannot find a {} with id: {}".format( type_, file_id)) raise except MethodNotALLowedError: try: int(file_id) except ValueError: logger.error(u"id({}) is ill-formed".format(file_id)) raise ParameterError() raise
def list(self, folder_id=None, extra_params=None, by_name=False): """List files under the given folder""" self._check() if not extra_params: extra_params = [self.ONELEVEL, self.NOZIP, self.SIMPLE] if not folder_id: folder_id = self.ROOT_ID elif by_name: folder_id = self._convert_to_id(folder_id, False) params = urllib.urlencode( { "action": "get_account_tree", "api_key": self._api_key, "auth_token": self._auth_token, "folder_id": encode(folder_id), } ) params += "&" extra_param_list = [("params[]", param) for param in extra_params] params += urllib.urlencode(extra_param_list) logger.debug("list params: {}".format(params)) response = urllib.urlopen(self.REST_URL, params) tree = self._parse_response(response) if self.NOZIP in extra_params: folder = tree.find("tree/folder") else: zipped = tree.findtext("tree") folder = self._unzip_node(zipped) self._log_response(folder) return folder
def list(self, folder_id=None, extra_params=None, by_name=False): """List files under the given folder""" self._check() if not extra_params: extra_params = [self.ONELEVEL, self.NOZIP, self.SIMPLE] if not folder_id: folder_id = self.ROOT_ID elif by_name: folder_id = self._convert_to_id(folder_id, False) params = urllib.urlencode({ 'action': "get_account_tree", 'api_key': self._api_key, 'auth_token': self._auth_token, 'folder_id': encode(folder_id)}) params += "&" extra_param_list = [('params[]', param) for param in extra_params] params += urllib.urlencode(extra_param_list) logger.debug("list params: {}".format(params)) response = urllib.urlopen(self.REST_URL, params) tree = self._parse_response(response) if self.NOZIP in extra_params: folder = tree.find('tree/folder') else: zipped = tree.findtext("tree") folder = self._unzip_node(zipped) self._log_response(folder) return folder
def _move(self, is_file, target, new_folder, by_name): self._check() if by_name: target = self._convert_to_id(target, is_file) new_folder = self._convert_to_id(new_folder, False) params = urllib.urlencode({ 'action': "move", 'api_key': self._api_key, 'auth_token': self._auth_token, 'target': "file" if is_file else "folder", 'target_id': encode(target), 'destination_id': encode(new_folder)}) logger.debug("move params: {}".format(params)) response = urllib.urlopen(self.REST_URL, params) tree = self._parse_response(response) self._log_response(tree)
def _rename(self, is_file, id_, new_name, by_name): try: return self._update_info(is_file, id_, {"name": encode(new_name)}, by_name) except FileConflictionError: logger.error(u"{} {} already exists".format( "File" if is_file else "Folder", new_name)) raise
def download_file(self, file_id, localdir=None, by_name=False): """Download the file with the given id to a local directory""" self._check() if by_name: file_id = self._convert_to_id(file_id, True) url = self.DOWNLOAD_URL.format(self._auth_token, encode(file_id)) logger.debug("download url: {}".format(url)) http = httplib2.Http() response, content = http.request(url, 'GET') logger.debug("response: {}".format(response)) status = response.status if status / 100 != 2: logger.error("bad status: {}".format(status)) raise StatusError(status) name = self._get_filename(response) logger.debug("filename: {}".format(name)) localdir = encode(localdir) file(os.path.join(localdir or ".", name), 'wb').write(content)
def _upload_file(self, upload_file, parent, precheck): remote_id = None if precheck is True: remote_id = self._check_file_on_server(upload_file, parent) if remote_id is True: logger.debug(u"skip uploading file: {}".format(upload_file)) return elif precheck: remote_id = precheck url = self.UPLOAD_URL.format(("/" + remote_id) if remote_id else "") logger.debug(u"uploading {} to {}".format(upload_file, parent)) # Register the streaming http handlers with urllib2 register_openers() upload_file = encode(upload_file) # add "If-Match: ETAG_OF_ORIGINAL" for file's new version? datagen, headers = multipart_encode({ 'filename': open(upload_file), 'parent_id': parent }) class DataWrapper(object): """Fix filename encoding problem""" def __init__(self, filename, datagen, headers): header_data = [] while True: data = datagen.next() if BoxApi.FILENAME_PATTERN.search(data): length = int(headers['Content-Length']) - len(data) filename = os.path.basename(filename) data = BoxApi.FILENAME_PATTERN.sub( "\g<1>" + filename + "\\3", data) headers['Content-Length'] = str(length + len(data)) header_data.insert(0, data) break else: header_data.insert(0, data) self.datagen = datagen self.header_data = header_data def __iter__(self): return self def next(self): if self.header_data: return self.header_data.pop() else: return self.datagen.next() datagen = DataWrapper(upload_file, datagen, headers) return self._request(url, datagen, headers)
def download_file(self, file_id, localdir=None, by_name=False): """Download the file with the given id to a local directory""" self._check() if by_name: file_id = self._convert_to_id(file_id, True) url = self.DOWNLOAD_URL.format(self._auth_token, encode(file_id)) logger.debug("download url: {}".format(url)) http = httplib2.Http() response, content = http.request(url, "GET") logger.debug("response: {}".format(response)) status = response.status if status / 100 != 2: logger.error("bad status: {}".format(status)) raise StatusError(status) name = self._get_filename(response) logger.debug("filename: {}".format(name)) localdir = encode(localdir) file(os.path.join(localdir or ".", name), "wb").write(content)
def _move(self, is_file, target, new_folder, by_name): if by_name: new_folder = self._convert_to_id(new_folder, False) try: return self._update_info(is_file, target, {"parent": { "id": encode(new_folder) }}, by_name) except RequestError: # e.g. move to descendent logger.error(u"{} {} cannot move to {}".format( "File" if is_file else "Folder", target, new_folder)) raise
def mkdir(self, name, parent=None, by_name=False): """Create a directory if it does not exists. Raise `FileConflictionError` if it already exists. Refer: http://developers.box.com/docs/#folders-create-a-new-folder """ self._check() if not parent: parent = self.ROOT_ID elif by_name: parent = self._convert_to_id(parent, False) url = "{}folders".format(self.BASE_URL) data = {"parent": {"id": encode(parent)}, "name": encode(name)} try: return self._request(url, json.dumps(data)) except FileConflictionError as e: logger.warn(u"directory {} already exists".format(name)) e.args = (encode(name), parent) raise
def mkdir(self, name, parent=None, by_name=False, share=0): """Create a directory if it does not exists and return its id """ self._check() if not parent: parent = self.ROOT_ID elif by_name: parent = self._convert_to_id(parent, False) params = urllib.urlencode({ 'action': "create_folder", 'api_key': self._api_key, 'auth_token': self._auth_token, 'parent_id': encode(parent), 'name': encode(name), 'share': share}) logger.debug("mkdir params: {}".format(params)) response = urllib.urlopen(self.REST_URL, params) tree = self._parse_response(response) folder = map_element(tree.find('folder')) self._log_response(folder) return folder
def list(self, folder_id=None, extra_params=None, by_name=False): """List files under the given folder. Refer: http://developers.box.com/docs/#folders-retrieve-a-folders-items """ self._check() if not extra_params: extra_params = [self.ONELEVEL, self.SIMPLE] if not folder_id: folder_id = self.ROOT_ID elif by_name: folder_id = self._convert_to_id(folder_id, False) url = "{}folders/{}/items".format(self.BASE_URL, encode(folder_id)) return self._request(url)
def get_file_info(self, file_id, by_name=False): """Get file detailed information""" self._check() if by_name: file_id = self._convert_to_id(file_id, True) params = urllib.urlencode({ 'action': "get_file_info", 'api_key': self._api_key, 'auth_token': self._auth_token, 'file_id': encode(file_id)}) logger.debug("get_file_info params: {}".format(params)) response = urllib.urlopen(self.REST_URL, params) tree = self._parse_response(response) info = map_element(tree.find('info')) self._log_response(info) return info
def _remove(self, is_file, id_, by_name): self._check() if by_name: id_ = self._convert_to_id(id_, is_file) params = urllib.urlencode( { "action": "delete", "api_key": self._api_key, "auth_token": self._auth_token, "target": "file" if is_file else "folder", "target_id": encode(id_), } ) logger.debug("delete params: {}".format(params)) response = urllib.urlopen(self.REST_URL, params) tree = self._parse_response(response) self._log_response(tree)
def _upload_file(self, upload_file, parent, precheck): if precheck and self._check_file_on_server(upload_file, parent): logger.debug(u"skip uploading file: {}".format(upload_file)) return logger.debug(u"uploading {} to {}".format(upload_file, parent)) url = self.UPLOAD_URL.format(self._auth_token, parent) logger.debug(u"upload url: {}".format(url)) # Register the streaming http handlers with urllib2 register_openers() upload_file = encode(upload_file) datagen, headers = multipart_encode({'file': open(upload_file)}) class DataWrapper(object): """Fix filename encoding problem""" def __init__(self, filename, datagen, headers): data = datagen.next() length = int(headers['Content-Length']) - len(data) filename = os.path.basename(filename) data = BoxApi.FILENAME_PATTERN.sub( "\g<1>" + filename + "\\3", data) headers['Content-Length'] = str(length + len(data)) self.datagen = datagen self.header_data = data def __iter__(self): return self def next(self): if self.header_data: data = self.header_data self.header_data = None return data else: return self.datagen.next() datagen = DataWrapper(upload_file, datagen, headers) request = urllib2.Request(url, datagen, headers) response = urllib2.urlopen(request) tree = self._parse_response(response) self._log_response(tree)
def __str__(self): return encode(unicode(self))