diff --git a/pypln/api.py b/pypln/api.py index 6eb4068..76961b0 100644 --- a/pypln/api.py +++ b/pypln/api.py @@ -128,6 +128,22 @@ def properties(self): "{}. The response was: '{}'".format(response.status_code, response.text)) + def delete(self): + ''' + Deletes the document. Be very careful, since this operation is + irreversible. + + Returns True if the Document was successfully deleted, raises + RuntimeError otherwise. + ''' + result = self.session.delete(self.url) + if result.status_code == 204: + return True + else: + raise RuntimeError("Document deletion failed with status " + "{}. The response was: '{}'".format(result.status_code, + result.text)) + class Corpus(object): '''Class that represents a Corpus in PyPLN''' @@ -140,6 +156,9 @@ def __init__(self, session, *args, **kwargs): ''' self.session = session for key, value in kwargs.items(): + if key == 'documents': + value = map(lambda d: Document(session=self.session, **d), + value) setattr(self, key, value) splited_url = urlsplit(self.url) @@ -209,6 +228,22 @@ def add_documents(self, documents): return result, errors + def delete(self): + ''' + Deletes the corpus. Be very careful, since this operation is + irreversible. + + Returns True if the Corpus was successfully deleted, raises + RuntimeError otherwise. + ''' + result = self.session.delete(self.url) + if result.status_code == 204: + return True + else: + raise RuntimeError("Corpus deletion failed with status " + "{}. The response was: '{}'".format(result.status_code, + result.text)) + class PyPLN(object): """ Class to connect to PyPLN's API and execute some actions diff --git a/tests/test_pypln.py b/tests/test_pypln.py index 5d6efa3..d9987f3 100644 --- a/tests/test_pypln.py +++ b/tests/test_pypln.py @@ -379,6 +379,72 @@ def test_adding_multiple_documents_returns_an_error(self, mocked_add_document): self.assertEqual(result[1][0][0], expected[1][0][0]) self.assertIsInstance(expected[1][0][1], RuntimeError) + @patch("requests.Session.delete") + def test_delete_corpus(self, mocked_delete): + mocked_delete.return_value.status_code = 204 + + corpus = Corpus(session=self.session, **self.example_json) + result = corpus.delete() + + mocked_delete.assert_called_with(self.example_json['url']) + self.assertTrue(result) + + @patch("requests.Session.delete") + def test_corpus_deletion_fails(self, mocked_delete): + mocked_delete.return_value.status_code = 403 + + session = requests.Session() + session.auth = ('wrong_user', 'my_precious') + corpus = Corpus(session=session, **self.example_json) + + with self.assertRaises(RuntimeError): + corpus.delete() + + def test_get_all_documents(self): + example_document_2 = { + 'owner': 'user', + 'corpus': 'http://pypln.example.com/corpora/42/', + 'size': 43, + 'properties': 'http://pypln.example.com/documents/124/properties', + 'url': 'http://pypln.example.com/documents/124/', + 'blob': '/test_2.txt', + 'uploaded_at': '2013-10-25T17:00:01.000Z', + } + + expected_documents = [ + Document(session=self.session, **self.example_document), + Document(session=self.session, **example_document_2) + ] + + self.example_json['documents'] = [self.example_document, + example_document_2] + + corpus = Corpus(session=self.session, **self.example_json) + + for document in corpus.documents: + self.assertIsInstance(document, Document) + + retrieved_document_1 = corpus.documents[0] + retrieved_document_2 = corpus.documents[1] + + for key, value in self.example_document.items(): + # `properties` is a method on `Document` class, so replacing with + # `properties_url` to test each key/value + if key == 'properties': + key = 'properties_url' + self.assertEqual(value, getattr(retrieved_document_1, key)) + + for key, value in example_document_2.items(): + # `properties` is a method on `Document` class, so replacing with + # `properties_url` to test each key/value + if key == 'properties': + key = 'properties_url' + self.assertEqual(value, getattr(retrieved_document_2, key)) + + # Document objects should link `session` object from the Corpus + self.assertIs(retrieved_document_1.session, corpus.session) + self.assertIs(retrieved_document_2.session, corpus.session) + class DocumentTest(unittest.TestCase): @@ -582,3 +648,24 @@ def test_download_wordcloud(self, mocked_get): handle.write.assert_called_once_with(png.decode('ascii')) mocked_get.assert_called_with(self.example_json['properties'] + 'wordcloud') + + @patch("requests.Session.delete") + def test_delete_document(self, mocked_delete): + mocked_delete.return_value.status_code = 204 + + document = Document(session=self.session, **self.example_json) + result = document.delete() + + mocked_delete.assert_called_with(self.example_json['url']) + self.assertTrue(result) + + @patch("requests.Session.delete") + def test_document_deletion_fails(self, mocked_delete): + mocked_delete.return_value.status_code = 403 + + session = requests.Session() + session.auth = ('wrong_user', 'my_precious') + document = Document(session=session, **self.example_json) + + with self.assertRaises(RuntimeError): + document.delete()