def upload(self, dataset_id, source_path, dest_path=None):
upload_result = UploadResult()<EOL>source_path = str(source_path)<EOL>if not dest_path:<EOL><INDENT>dest_path = source_path<EOL><DEDENT>else:<EOL><INDENT>dest_path = str(dest_path)<EOL><DEDENT>if os.path.isdir(source_path):<EOL><INDENT>for path, subdirs, files in os.walk(source_path):<EOL><INDENT>relative_path = os.path.relpath(path, source_path)<EOL>current_dest_prefix = dest_path<EOL>if relative_path is not "<STR_LIT:.>":<EOL><INDENT>current_dest_prefix = os.path.join(current_dest_prefix, relative_path)<EOL><DEDENT>for name in files:<EOL><INDENT>current_dest_path = os.path.join(current_dest_prefix, name)<EOL>current_source_path = os.path.join(path, name)<EOL>try:<EOL><INDENT>if self.upload(dataset_id, current_source_path, current_dest_path).successful():<EOL><INDENT>upload_result.add_success(current_source_path)<EOL><DEDENT>else:<EOL><INDENT>upload_result.add_failure(current_source_path,"<STR_LIT>")<EOL><DEDENT><DEDENT>except (CitrinationClientError, ValueError) as e:<EOL><INDENT>upload_result.add_failure(current_source_path, str(e))<EOL><DEDENT><DEDENT><DEDENT>return upload_result<EOL><DEDENT>elif os.path.isfile(source_path):<EOL><INDENT>file_data = { "<STR_LIT>": str(dest_path), "<STR_LIT>": str(source_path)}<EOL>j = self._get_success_json(self._post_json(routes.upload_to_dataset(dataset_id), data=file_data))<EOL>s3url = _get_s3_presigned_url(j)<EOL>with open(source_path, '<STR_LIT:rb>') as f:<EOL><INDENT>if os.stat(source_path).st_size == <NUM_LIT:0>:<EOL><INDENT>data = "<STR_LIT>"<EOL><DEDENT>else:<EOL><INDENT>data = f<EOL><DEDENT>r = requests.put(s3url, data=data, headers=j["<STR_LIT>"])<EOL>if r.status_code == <NUM_LIT:200>:<EOL><INDENT>data = {'<STR_LIT>': j['<STR_LIT:url>']['<STR_LIT:path>'], '<STR_LIT>': j['<STR_LIT>']}<EOL>self._post_json(routes.update_file(j['<STR_LIT>']), data=data)<EOL>upload_result.add_success(source_path)<EOL>return upload_result<EOL><DEDENT>else:<EOL><INDENT>raise CitrinationClientError("<STR_LIT>".format(source_path))<EOL><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>raise ValueError("<STR_LIT>".format(source_path))<EOL><DEDENT>
Upload a file, specifying source and dest paths a file (acts as the scp command).asdfasdf

:param source_path: The path to the file on the source host asdf
:type source_path: str
:param dest_path: The path to the file where the contents of the upload will be written (on the dest host)
:type dest_path: str
:return: The result of the upload process
:rtype: :class:`UploadResult`