# Path: foil/ftp.py
# def parse_line(line: str, char_index=0) -> Tuple[ListingType, str]:
#     """Parse FTP directory listing into (type, filename)."""
# 
#     entry_name = str.rpartition(line, ' ')[-1]
#     entry_type = LISTING_FLAG_MAP.get(line[char_index], ListingType.other)
#     return entry_type, entry_name
# 
# def ftp_walk(ftpconn: FTP, rootpath=''):
#     """Recursively traverse an ftp directory to discovery directory listing."""
# 
#     current_directory = rootpath
# 
#     try:
#         directories, files = directory_listing(ftpconn, current_directory)
#     except ftplib.error_perm:
#         return
# 
#     # Yield before recursion
#     yield current_directory, directories, files
# 
#     # Recurse into sub-directories
#     for name in directories:
#         new_path = os.path.join(current_directory, name)
# 
#         for entry in ftp_walk(ftpconn, rootpath=new_path):
#             yield entry
#     else:
#         return
# 
# def ftp_listing_paths(ftpconn: FTP, root: str) -> Iterable[str]:
#     """Generate the full file paths from a root path."""
# 
#     for current_path, dirs, files in ftp_walk(ftpconn, root):
#         yield from (os.path.join(current_path, file) for file in files)
# 
# class ListingType(Enum):
#     directory = DIRECTORY_FLAG
#     file = FILE_FLAG
#     link = LINK_FLAG
#     other = ''
# 
# FTP_URL_TEMPLATE = 'ftp://{user}:{password}@{host}:{port}'
# 
# def download_ftp_url(source_url, target_uri, buffer_size=8192):
#     """Uses urllib. thread safe?"""
# 
#     ensure_file_directory(target_uri)
# 
#     with urllib.request.urlopen(source_url) as source_file:
#         with open(target_uri, 'wb') as target_file:
#             shutil.copyfileobj(source_file, target_file, buffer_size)


import io
import os
import tempfile
import unittest
from unittest import mock
from urllib.parse import urljoin
from foil.ftp import (parse_line, ftp_walk, ftp_listing_paths, ListingType,
                      FTP_URL_TEMPLATE, download_ftp_url)
        self.root = '/root'

    def test_ftp_walk(self):
        expected = list(mock_ftp_walk())
        result = list(ftp_walk(self.conn, rootpath=self.root))

        self.assertEqual(expected, result)

    def test_ftp_listing_paths(self):
        expected = set(['/root/file1',
                        '/root/directory1/subdirectory/file1',
                        '/root/directory1/subdirectory/file2'])
        result = set(ftp_listing_paths(self.conn, self.root))

        self.assertEqual(expected, result)


class TestParseListingLines(unittest.TestCase):
    def test_parse_directory(self):
        directory_name = 'photos'
        entry = mock_directory_line(directory_name)

        expected = (ListingType.directory, directory_name)
        result = parse_line(entry)
        self.assertEqual(expected, result)

    def test_parse_file(self):
        filename = 'katies_photo_album.zip'
        entry = mock_file_line(filename)


# Path: foil/ftp.py
# def parse_line(line: str, char_index=0) -> Tuple[ListingType, str]:
#     """Parse FTP directory listing into (type, filename)."""
# 
#     entry_name = str.rpartition(line, ' ')[-1]
#     entry_type = LISTING_FLAG_MAP.get(line[char_index], ListingType.other)
#     return entry_type, entry_name
# 
# def ftp_walk(ftpconn: FTP, rootpath=''):
#     """Recursively traverse an ftp directory to discovery directory listing."""
# 
#     current_directory = rootpath
# 
#     try:
#         directories, files = directory_listing(ftpconn, current_directory)
#     except ftplib.error_perm:
#         return
# 
#     # Yield before recursion
#     yield current_directory, directories, files
# 
#     # Recurse into sub-directories
#     for name in directories:
#         new_path = os.path.join(current_directory, name)
# 
#         for entry in ftp_walk(ftpconn, rootpath=new_path):
#             yield entry
#     else:
#         return
# 
# def ftp_listing_paths(ftpconn: FTP, root: str) -> Iterable[str]:
#     """Generate the full file paths from a root path."""
# 
#     for current_path, dirs, files in ftp_walk(ftpconn, root):
#         yield from (os.path.join(current_path, file) for file in files)
# 
# class ListingType(Enum):
#     directory = DIRECTORY_FLAG
#     file = FILE_FLAG
#     link = LINK_FLAG
#     other = ''
# 
# FTP_URL_TEMPLATE = 'ftp://{user}:{password}@{host}:{port}'
# 
# def download_ftp_url(source_url, target_uri, buffer_size=8192):
#     """Uses urllib. thread safe?"""
# 
#     ensure_file_directory(target_uri)
# 
#     with urllib.request.urlopen(source_url) as source_file:
#         with open(target_uri, 'wb') as target_file:
#             shutil.copyfileobj(source_file, target_file, buffer_size)


# Path: tests/test_ftp.py
import io
import os
import tempfile
import unittest
from unittest import mock
from urllib.parse import urljoin
from foil.ftp import (parse_line, ftp_walk, ftp_listing_paths, ListingType,
                      FTP_URL_TEMPLATE, download_ftp_url)

        self.root = '/root'

    def test_ftp_walk(self):
        expected = list(mock_ftp_walk())
        result = list(ftp_walk(self.conn, rootpath=self.root))

        self.assertEqual(expected, result)

    def test_ftp_listing_paths(self):
        expected = set(['/root/file1',
                        '/root/directory1/subdirectory/file1',
                        '/root/directory1/subdirectory/file2'])
        result = set(ftp_listing_paths(self.conn, self.root))

        self.assertEqual(expected, result)


class TestParseListingLines(unittest.TestCase):
    def test_parse_directory(self):
        directory_name = 'photos'
        entry = mock_directory_line(directory_name)

        expected = (ListingType.directory, directory_name)
        result = parse_line(entry)
        self.assertEqual(expected, result)

    def test_parse_file(self):
        filename = 'katies_photo_album.zip'
        entry = mock_file_line(filename)


        expected = (ListingType.file, filename)