Skip to content

Commit

Permalink
#29 covers sharing interface for files, adds return values to upload …
Browse files Browse the repository at this point in the history
…and delete as well
  • Loading branch information
caseneuve committed Jan 16, 2021
1 parent b7498be commit f466508
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 12 deletions.
34 changes: 31 additions & 3 deletions pythonanywhere/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,28 +30,56 @@ def delete(self):
try:
self.api.path_delete(self.path)
logger.info(snakesay(f"{self.path} deleted!"))
return True
except Exception as e:
logger.warning(snakesay(str(e)))
return False

def upload(self, content):
try:
result = self.api.path_post(self.path, content)
except Exception as e:
logger.warning(snakesay(str(e)))
return None
return False

msg = {
200: f"{self.path} successfully updated!",
201: f"Content successfully uploaded to {self.path}!"
}[result]

logger.info(snakesay(msg))
return True

def get_sharing_url(self):
url = self.api.sharing_get(self.path)
if url:
logger.info(snakesay(f"{self.path} is shared at {url}"))
return url
logger.info(snakesay(f"{self.path} has not been shared."))
return ""

def share(self):
pass
try:
code, shared_url = self.api.sharing_post(self.path)
except Exception as e:
logger.warning(snakesay(str(e)))
return ""

msg = {200: "was already", 201: "successfully"}[code]
logger.info(snakesay(f"{self.path} {msg} shared at {shared_url}"))
return shared_url

def unshare(self):
pass
already_shared = self.get_sharing_url()
if already_shared:
result = self.api.sharing_delete(self.path)
if result == 204:
logger.info(snakesay(f"{self.path} is no longer shared!"))
return True
logger.info(snakesay(f"Could not unshare {self.path}... :("))
return False
logger.info(snakesay(f"{self.path} is not being shared, no need to stop sharing..."))
return True

def tree(self):
pass
Expand Down
7 changes: 5 additions & 2 deletions pythonanywhere/files.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@ class PAPath:
def __init__(self, path: str) -> None: ...
def __repr__(self) -> str: ...
def contents(self) -> Union[dict, str]: ...
def delete(self) -> None: ...
def upload(self, content: bytes) -> None: ...
def delete(self) -> bool: ...
def upload(self, content: bytes) -> bool: ...
def get_sharing_url(self) -> str: ...
def share(self) -> str: ...
def unshare(self) -> bool: ...
143 changes: 136 additions & 7 deletions tests/test_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@


@pytest.mark.files
class TestPathRepr(TestFiles):
class TestPAPathRepr(TestFiles):
def test_contains_correct_pythonanywhere_resource_url_for_instantiated_path(self):
path = self.home_dir_path

Expand All @@ -19,7 +19,7 @@ def test_contains_correct_pythonanywhere_resource_url_for_instantiated_path(self


@pytest.mark.files
class TestPathContents(TestFiles):
class TestPAPathContents(TestFiles):
def test_returns_file_contents_as_string_if_path_points_to_a_file(self, mocker):
path = f"{self.home_dir_path}README.txt"
mock_path_get = mocker.patch("pythonanywhere.api.files_api.Files.path_get")
Expand Down Expand Up @@ -49,7 +49,7 @@ def test_raises_when_path_unavailable(self, mocker):


@pytest.mark.files
class TestPathDelete(TestFiles):
class TestPAPathDelete(TestFiles):
def test_informes_about_successful_file_deletion(self, mocker):
mock_delete = mocker.patch("pythonanywhere.api.files_api.Files.path_delete")
mock_delete.return_value.status_code = 204
Expand All @@ -76,7 +76,7 @@ def test_warns_about_failed_deletion(self, mocker):


@pytest.mark.files
class TestPathUpload(TestFiles):
class TestPAPathUpload(TestFiles):
def test_informs_about_successful_upload_of_a_file(self, mocker):
mock_post = mocker.patch("pythonanywhere.api.files_api.Files.path_post")
mock_post.return_value = 201
Expand All @@ -85,11 +85,12 @@ def test_informs_about_successful_upload_of_a_file(self, mocker):
destination_path = "/home/user/"
content = "content".encode()

PAPath(destination_path).upload(content)
result = PAPath(destination_path).upload(content)

assert mock_post.call_args == call(destination_path, content)
assert mock_snake.call_args == call(f"Content successfully uploaded to {destination_path}!")
assert mock_info.call_args == call(mock_snake.return_value)
assert result == True

def test_informs_about_successful_update_of_existing_file_with_provided_stream(self, mocker):
mock_post = mocker.patch("pythonanywhere.api.files_api.Files.path_post")
Expand All @@ -99,11 +100,12 @@ def test_informs_about_successful_update_of_existing_file_with_provided_stream(s
destination_path = "/home/user/"
content = "content".encode()

PAPath(destination_path).upload(content)
result = PAPath(destination_path).upload(content)

assert mock_post.call_args == call(destination_path, content)
assert mock_snake.call_args == call(f"{destination_path} successfully updated!")
assert mock_info.call_args == call(mock_snake.return_value)
assert result == True


def test_warns_when_file_has_not_been_uploaded(self, mocker):
Expand All @@ -115,8 +117,135 @@ def test_warns_when_file_has_not_been_uploaded(self, mocker):
destination_path = "wrong/path"
content = "content".encode()

PAPath(destination_path).upload(content)
result = PAPath(destination_path).upload(content)

assert mock_post.call_args == call(destination_path, content)
assert mock_snake.call_args == call("sth went wrong")
assert mock_warning.call_args == call(mock_snake.return_value)
assert result == False


@pytest.mark.files
class TestPAPathShare(TestFiles):
def test_returns_url_for_shared_file(self, mocker):
mock_sharing_get = mocker.patch("pythonanywhere.api.files_api.Files.sharing_get")
mock_sharing_get.return_value = "url"
mock_snake = mocker.patch("pythonanywhere.files.snakesay")
mock_info = mocker.patch("pythonanywhere.files.logger.info")
query_path = "/pa/path/to/a/file"

result = PAPath(query_path).get_sharing_url()

assert mock_sharing_get.call_args == call(query_path)
assert mock_snake.call_args == call(f"{query_path} is shared at url")
assert mock_info.call_args == call(mock_snake.return_value)
assert result == "url"

def test_returns_empty_string_when_file_not_shared(self, mocker):
mock_sharing_get = mocker.patch("pythonanywhere.api.files_api.Files.sharing_get")
mock_sharing_get.return_value = ""
mock_snake = mocker.patch("pythonanywhere.files.snakesay")
mock_info = mocker.patch("pythonanywhere.files.logger.info")
query_path = "/pa/path/to/a/file"

result = PAPath(query_path).get_sharing_url()

assert mock_sharing_get.call_args == call(query_path)
assert mock_snake.call_args == call(f"{query_path} has not been shared.")
assert mock_info.call_args == call(mock_snake.return_value)
assert result == ""

def test_path_already_shared(self, mocker):
mock_sharing_post = mocker.patch("pythonanywhere.api.files_api.Files.sharing_post")
mock_sharing_post.return_value = (200, "url")
mock_snake = mocker.patch("pythonanywhere.files.snakesay")
mock_info = mocker.patch("pythonanywhere.files.logger.info")
path_to_share = "/pa/path/to/a/file"

result = PAPath(path_to_share).share()

assert mock_sharing_post.call_args == call(path_to_share)
assert mock_snake.call_args == call(f"{path_to_share} was already shared at url")
assert mock_info.call_args == call(mock_snake.return_value)
assert result == "url"

def test_path_successfully_shared(self, mocker):
mock_sharing_post = mocker.patch("pythonanywhere.api.files_api.Files.sharing_post")
mock_sharing_post.return_value = (201, "url")
mock_snake = mocker.patch("pythonanywhere.files.snakesay")
mock_info = mocker.patch("pythonanywhere.files.logger.info")
path_to_share = "/pa/path/to/a/file"

result = PAPath(path_to_share).share()

assert mock_sharing_post.call_args == call(path_to_share)
assert mock_snake.call_args == call(f"{path_to_share} successfully shared at url")
assert mock_info.call_args == call(mock_snake.return_value)
assert result == "url"

def test_warns_if_share_fails(self, mocker):
mock_sharing_post = mocker.patch("pythonanywhere.api.files_api.Files.sharing_post")
mock_sharing_post.side_effect = Exception("failed")
mock_snake = mocker.patch("pythonanywhere.files.snakesay")
mock_warning = mocker.patch("pythonanywhere.files.logger.warning")
path_to_share = "/invalid/path"

result = PAPath(path_to_share).share()

assert mock_sharing_post.call_args == call(path_to_share)
assert mock_snake.call_args == call("failed")
assert mock_warning.call_args == call(mock_snake.return_value)
assert result == ""

def test_path_is_not_shared_so_cannot_be_unshared(self, mocker):
mock_sharing_get = mocker.patch("pythonanywhere.api.files_api.Files.sharing_get")
mock_sharing_get.return_value = ""
mock_sharing_delete = mocker.patch("pythonanywhere.api.files_api.Files.sharing_delete")
mock_snake = mocker.patch("pythonanywhere.files.snakesay")
mock_info = mocker.patch("pythonanywhere.files.logger.info")
path_to_unshare = "/pa/path/to/a/file"

result = PAPath(path_to_unshare).unshare()

assert mock_sharing_get.call_args == call(path_to_unshare)
assert mock_sharing_delete.call_count == 0
assert mock_snake.call_args == call(
f"{path_to_unshare} is not being shared, no need to stop sharing..."
)
assert mock_info.call_args == call(mock_snake.return_value)
assert result == True

def test_path_successfully_unshared(self, mocker):
mock_sharing_get = mocker.patch("pythonanywhere.api.files_api.Files.sharing_get")
mock_sharing_get.return_value = "url"
mock_sharing_delete = mocker.patch("pythonanywhere.api.files_api.Files.sharing_delete")
mock_sharing_delete.return_value = 204
mock_snake = mocker.patch("pythonanywhere.files.snakesay")
mock_info = mocker.patch("pythonanywhere.files.logger.info")
path_to_shared_file = "/pa/path/to/a/file"

result = PAPath(path_to_shared_file).unshare()

assert mock_sharing_get.call_args == call(path_to_shared_file)
assert mock_sharing_delete.call_args == call(path_to_shared_file)
assert mock_snake.call_args == call(f"{path_to_shared_file} is no longer shared!")
assert mock_info.call_args == call(mock_snake.return_value)
assert result == True

def test_warns_if_unshare_not_successful(self, mocker):
mock_sharing_get = mocker.patch("pythonanywhere.api.files_api.Files.sharing_get")
mock_sharing_get.return_value = "url"
mock_sharing_delete = mocker.patch("pythonanywhere.api.files_api.Files.sharing_delete")
mock_sharing_delete.return_value = 999
mock_snake = mocker.patch("pythonanywhere.files.snakesay")
mock_info = mocker.patch("pythonanywhere.files.logger.info")
path_to_shared_file = "/pa/path/to/a/file"

result = PAPath(path_to_shared_file).unshare()

assert mock_sharing_get.call_args == call(path_to_shared_file)
assert mock_sharing_delete.call_args == call(path_to_shared_file)
assert mock_snake.call_args == call(f"Could not unshare {path_to_shared_file}... :(")
assert mock_info.call_args == call(mock_snake.return_value)
assert result == False

0 comments on commit f466508

Please sign in to comment.