portfoliome /
foil
| 1 | import io |
||
|
0 ignored issues
–
show
|
|||
| 2 | import os |
||
| 3 | import tempfile |
||
| 4 | import unittest |
||
| 5 | from unittest import mock |
||
| 6 | from urllib.parse import urljoin |
||
| 7 | |||
| 8 | from foil.ftp import (parse_line, ftp_walk, ftp_listing_paths, ListingType, |
||
| 9 | FTP_URL_TEMPLATE, download_ftp_url) |
||
| 10 | |||
| 11 | |||
| 12 | FILE_CONTENT = b'mock_content' |
||
| 13 | |||
| 14 | MOCK_FTP_CONFIG = { |
||
| 15 | 'user': 'fake_user', |
||
| 16 | 'password': 'fake_password', |
||
| 17 | 'host': 'host', |
||
| 18 | 'port': 21 |
||
| 19 | } |
||
| 20 | |||
| 21 | |||
| 22 | def mock_directory_line(name): |
||
| 23 | return 'drwxr-xr-x 4 ftsclient ftsclient 60 Dec 11 10:03 {}'.format(name) |
||
| 24 | |||
| 25 | |||
| 26 | def mock_file_line(name): |
||
| 27 | return '-rw-r--r-- 1 bd_mgr online 3661980 Mar 30 02:13 {}'.format(name) |
||
| 28 | |||
| 29 | |||
| 30 | def mock_ftp_walk(): |
||
| 31 | return iter([('/root', ['directory1', 'directory2'], ['file1']), |
||
| 32 | ('/root/directory1', ['subdirectory'], []), |
||
| 33 | ('/root/directory1/subdirectory', [], ['file1', 'file2']), |
||
| 34 | ('/root/directory2', [], [])]) |
||
| 35 | |||
| 36 | |||
| 37 | class MockFTPConnection: |
||
|
0 ignored issues
–
show
This class should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. Loading history...
|
|||
| 38 | FTP_DIR_TREE = { |
||
| 39 | '/root': [mock_directory_line('directory1'), |
||
| 40 | mock_directory_line('directory2'), |
||
| 41 | mock_file_line('file1')], |
||
| 42 | '/root/directory1': [mock_directory_line('subdirectory')], |
||
| 43 | '/root/directory1/subdirectory': [mock_file_line('file1'), |
||
| 44 | mock_file_line('file2')], |
||
| 45 | '/root/directory2': ['totals']} |
||
| 46 | |||
| 47 | BINARY_DATA = {'file1': b'abc', 'file2': b'123'} |
||
| 48 | |||
| 49 | def dir(self, path, callback): |
||
| 50 | listings = self.FTP_DIR_TREE[path] |
||
| 51 | for listing in listings: |
||
| 52 | callback(listing) |
||
| 53 | |||
| 54 | def retrbinary(self, path, callback): |
||
| 55 | file = path.rpartition(' ')[-1] |
||
| 56 | callback(self.BINARY_DATA[file]) |
||
| 57 | |||
| 58 | |||
| 59 | def mock_url_open(url): |
||
|
0 ignored issues
–
show
|
|||
| 60 | return io.BytesIO(FILE_CONTENT) |
||
| 61 | |||
| 62 | |||
| 63 | class TestListingTraversal(unittest.TestCase): |
||
| 64 | def setUp(self): |
||
| 65 | self.conn = MockFTPConnection() |
||
| 66 | self.root = '/root' |
||
| 67 | |||
| 68 | def test_ftp_walk(self): |
||
| 69 | expected = list(mock_ftp_walk()) |
||
| 70 | result = list(ftp_walk(self.conn, rootpath=self.root)) |
||
| 71 | |||
| 72 | self.assertEqual(expected, result) |
||
| 73 | |||
| 74 | def test_ftp_listing_paths(self): |
||
| 75 | expected = set(['/root/file1', |
||
| 76 | '/root/directory1/subdirectory/file1', |
||
| 77 | '/root/directory1/subdirectory/file2']) |
||
| 78 | result = set(ftp_listing_paths(self.conn, self.root)) |
||
| 79 | |||
| 80 | self.assertEqual(expected, result) |
||
| 81 | |||
| 82 | |||
| 83 | class TestParseListingLines(unittest.TestCase): |
||
| 84 | def test_parse_directory(self): |
||
| 85 | directory_name = 'photos' |
||
| 86 | entry = mock_directory_line(directory_name) |
||
| 87 | |||
| 88 | expected = (ListingType.directory, directory_name) |
||
| 89 | result = parse_line(entry) |
||
| 90 | self.assertEqual(expected, result) |
||
| 91 | |||
| 92 | def test_parse_file(self): |
||
| 93 | filename = 'katies_photo_album.zip' |
||
| 94 | entry = mock_file_line(filename) |
||
| 95 | |||
| 96 | expected = (ListingType.file, filename) |
||
| 97 | result = parse_line(entry) |
||
| 98 | self.assertEqual(expected, result) |
||
| 99 | |||
| 100 | |||
| 101 | class TestFtpFileTransfer(unittest.TestCase): |
||
| 102 | |||
| 103 | def setUp(self): |
||
| 104 | self.filename = 'makeme.zip' |
||
| 105 | self.ftp_url = FTP_URL_TEMPLATE.format_map(MOCK_FTP_CONFIG) |
||
| 106 | self.source_uri = urljoin(self.ftp_url, 'some_dir/some_file.zip') |
||
| 107 | |||
| 108 | @mock.patch('foil.ftp.urllib.request.urlopen') |
||
| 109 | def test_create_target_directory(self, mock_urlopen): |
||
| 110 | mock_urlopen.side_effect = mock_url_open |
||
| 111 | |||
| 112 | with tempfile.TemporaryDirectory(prefix='ftp_trans_') as temp_directory: |
||
| 113 | target_uri = os.path.join(temp_directory, 'some_dir', self.filename) |
||
| 114 | |||
| 115 | download_ftp_url(self.source_uri, target_uri) |
||
| 116 | |||
| 117 | with open(target_uri, 'rb') as result_file: |
||
| 118 | result = result_file.read() |
||
| 119 | |||
| 120 | self.assertEqual(FILE_CONTENT, result) |
||
| 121 | |||
| 122 | if os.path.exists(temp_directory): |
||
| 123 | os.unlink(temp_directory) |
||
| 124 |
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.