예제 #1
0
파일: workspace.py 프로젝트: Numergy/yoda
    def execute(self, args):
        logger = logging.getLogger(__name__)
        if args.workspace_subcommand is None:
            self.parser.print_help()
            return None

        color = Color()
        if (args.workspace_subcommand == "add"):
            ws_name = slashes2dash(args.name)
            self.ws.add(ws_name, args.path)
            logger.info(color.colored(
                "Workspace `%s` successfuly added" % ws_name, "green"))
        elif (args.workspace_subcommand == "remove"):
            ws_name = slashes2dash(args.name)
            self.ws.remove(ws_name)
            logger.info(color.colored(
                "Workspace `%s` successfuly removed" % ws_name, "green"))
        elif (args.workspace_subcommand == "list"):
            table = PrettyTable(["Name", "Path"])
            table.align["Name"] = "l"
            table.align["Path"] = "l"
            for key, ws in sorted(self.ws.list().items()):
                table.add_row([key, ws["path"]])

            logger.info(table)
예제 #2
0
파일: update.py 프로젝트: Numergy/yoda
 def print_update(self, repo_name, repo_path):
     """Print repository update."""
     color = Color()
     self.logger.info(color.colored(
         "=> [%s] %s" % (repo_name, repo_path), "green"))
     try:
         repo = Repository(repo_path)
         repo.update()
     except RepositoryError as e:
         self.logger.error(e)
         pass
     print("\n")
예제 #3
0
파일: status.py 프로젝트: hackolite/yoda
 def print_status(self, repo_name, repo_path):
     """Print repository status."""
     color = Color()
     try:
         repo = Repository(repo_path)
         self.logger.info(color.colored(
             "=> [%s] %s" % (repo_name, repo_path), "green"))
         repo.status()
         self.logger.info("\n")
     except ValueError as e:
         self.logger.error(e)
         pass
예제 #4
0
파일: show.py 프로젝트: hackolite/yoda
    def show_workspace(self, name):
        """Show specific workspace."""
        if not self.workspace.exists(name):
            raise ValueError("Workspace `%s` doesn't exists." % name)

        color = Color()
        workspaces = self.workspace.list()

        self.logger.info("<== %s workspace ==>" % color.colored(name, "green"))
        self.logger.info("\tPath: %s" % workspaces[name]["path"])
        self.logger.info("\tNumber of repositories: %s"
                         % color.colored(
                             len(workspaces[name]["repositories"]),
                             "yellow"))

        repo_colored = color.colored("Repositories", "blue")
        path_colored = color.colored("Path", "blue")
        trepositories = PrettyTable(
            [repo_colored, path_colored, color.colored("+", "blue")])
        trepositories.align[repo_colored] = "l"
        trepositories.align[path_colored] = "l"

        for repo_name in workspaces[name]["repositories"]:
            fullname = "%s/%s" % (name, repo_name)
            fullpath = find_path(fullname, self.config)[fullname]
            try:
                repo = Repository(fullpath)
                repo_scm = repo.get_scm()
            except RepositoryAdapterNotFound:
                repo_scm = None
            trepositories.add_row(
                [color.colored(repo_name, "cyan"), fullpath, repo_scm])

        self.logger.info(trepositories)
예제 #5
0
    def __init__(self, connector, output_directory, subprocess=None):
        """
            Initiliaze Downloader

            Parameters:
                connector: connector to Grooveshark api
                subprocess: spawn new processes
                output_directory: where files will be downloaded
        """
        if subprocess is not None:
            self.subprocess = subprocess
        else:
            import subprocess
            self.subprocess = subprocess

        self.color = Color()

        self.output_directory = output_directory
        self.connector = connector
        self.download_queue = []
        self.download_count = 0
예제 #6
0
파일: workspace.py 프로젝트: Numergy/yoda
    def sync(self, ws_name):
        """Synchronise workspace's repositories."""
        path = self.config["workspaces"][ws_name]["path"]
        repositories = self.config["workspaces"][ws_name]["repositories"]

        logger = logging.getLogger(__name__)
        color = Color()

        for r in os.listdir(path):
            try:
                repo = Repository(os.path.join(path, r))
            except RepositoryError:
                continue
            else:
                repositories[r] = repo.path

        for repo_name, path in repositories.items():
            logger.info(color.colored(
                " - %s" % repo_name, "blue"))

        self.config["workspaces"][ws_name]["repositories"]
        self.config.write()
예제 #7
0
파일: workspace.py 프로젝트: hackolite/yoda
    def sync(self, ws_name):
        """Synchronise workspace's repositories."""
        path = self.config["workspaces"][ws_name]["path"]
        repositories = self.config["workspaces"][ws_name]["repositories"]

        repo_list = {}

        for r in listdir(path):
            try:
                repo = Repository(join(path, r))
            except RepositoryError:
                continue
            else:
                repositories[r] = repo.path
                repo_list[r] = repo.path

        logger = logging.getLogger(__name__)
        color = Color()
        logger.info("Workspace `%s` synchronized" % ws_name)
        logger.info("Added %d repositories:" % len(repo_list))
        for repo_name, path in repo_list.items():
            logger.info(color.colored(
                " - %s" % repo_name, "blue"))
예제 #8
0
    def __init__(self, connector, output_directory, subprocess=None):
        """
            Initiliaze Downloader

            Parameters:
                connector: connector to Grooveshark api
                subprocess: spawn new processes
                output_directory: where files will be downloaded
        """
        if subprocess is not None:
            self.subprocess = subprocess
        else:
            import subprocess
            self.subprocess = subprocess

        self.color = Color()

        self.output_directory = output_directory
        self.connector = connector
        self.download_queue = []
        self.download_count = 0
예제 #9
0
#!/usr/bin/env python

from pycolorizer import Color, InvalidStyleNameError

c = Color()

# highlight('green') == bg('green') == bg_green()
# white() == fg('white')

print(c('Hello World!').white().bold().highlight('blue'))

# Create your own styles
c.set_themes(
    {
        'welcome': ('yellow', 'bg_cyan'),
        'bye': 'blue',
    }
)


print(c('Hello world!').welcome().bold())
print(c('Bye!').bye())

c.add_theme('error', 'red')
try:
    c.add_theme('error&é"&é"&é', 'red')
except InvalidStyleNameError as e:
    print(c('InvalidStyleNameError {}'.format(e)).error())

# Use style tags
text = """
예제 #10
0
class Downloader:
    output_directory = None
    connector = None
    subprocess = None
    download_queue = None
    download_count = None
    max_per_list = 10

    def __init__(self, connector, output_directory, subprocess=None):
        """
            Initiliaze Downloader

            Parameters:
                connector: connector to Grooveshark api
                subprocess: spawn new processes
                output_directory: where files will be downloaded
        """
        if subprocess is not None:
            self.subprocess = subprocess
        else:
            import subprocess
            self.subprocess = subprocess

        self.color = Color()

        self.output_directory = output_directory
        self.connector = connector
        self.download_queue = []
        self.download_count = 0

    def download_playlist(self, playlist_id=None):
        """
            Download Playlist

            Parameters:
                playlist_id: the playlist id
        """
        songs = []
        if (playlist_id is not None):
            plist = self.connector.get_playlist_from_id(playlist_id)
            songs = plist["Songs"] if ("Songs" in plist) else []
        else:
            for playlist in self.download_queue:
                plist = self.connector.get_playlist_from_id(
                    playlist['PlaylistID'])
                songs = songs + plist["Songs"]

        self.download_queue = songs
        self.download()

    def download_song(self, filename, song):
        """
            Download song

            Parameters:
                filename: the filename
                song: dictionary with song informations
        """
        self.color.cprint(("Downloading: %s" % (filename)), "cyan")
        stream_key = self.connector.get_stream_key_from_song_id(song["SongID"])
        if stream_key == []:
            print("Failed to retrieve stream key!")
            return False

        #Run wget to download the song
        wget = "wget --progress=dot --post-data=streamKey=%s" \
            " -O \"%s\" \"http://%s/stream.php\"" % (
                stream_key["streamKey"], filename, stream_key["ip"]
            )
        cmd = wget + " 2>&1 | grep --line-buffered \"%\" |" \
            "sed -u -e \"s,\.,,g\" | awk '{printf(\"\b\b\b\b%4s\", $2)}'"
        process = self.subprocess.Popen(cmd, shell=True)

        try:
            process.wait()
            self.color.cprint("\nDownloaded", "green")
            self.download_count += 1
        except BaseException:
            self.color.cprint("Download cancelled. File deleted.", "red")
            os.remove(filename)
            return False

        return True

    def prepare(self, query, type=None):
        """
            Prepare downloads

            Parameters:
                query: the search query
                type: the search type
                    (types are 'Songs', 'Artists', 'Albums' or 'Playlists')
        """
        result = self.connector.search(query, type)
        self.__display_raw_input(
            result, type, "Press \"n\" for next page, "
            "\"Number id\" to add element in queue, "
            "\"q\" for quit and download: ")

    def __display_raw_input(self, result, type, input_text):
        """
            Display prompt to choose songs, playlist, etc...

            Parameters:
                result: the result from the connector
                type: the search type
                    (types are 'Songs', 'Artists', 'Albums' or 'Playlists')
                input_text: texte for the raw input
        """
        try:
            if type != "Playlists":
                table = PrettyTable(["id", "Album", "Artist", "Song"])
            else:
                table = PrettyTable(["id", "Name", "Author", "NumSongs"])

            for idx, data in enumerate(result):
                key = None
                if (type != "Playlists"):
                    table.add_row([
                        idx, data["AlbumName"].ljust(40), data["ArtistName"],
                        data["SongName"]
                        if "SongName" in data else data["Name"]
                    ])
                else:
                    table.add_row([
                        idx, data["Name"].ljust(40), data["FName"],
                        data["NumSongs"]
                    ])

                is_last = (idx == (len(result) - 1))
                if ((idx != 0 and idx % self.max_per_list == 0) or is_last):

                    print(table.get_string())
                    table.clear_rows()
                    while (key is not False):
                        key = input(input_text)
                        if (key == "q"):
                            raise StopIteration
                        elif (key == "n" and is_last is False):
                            key = False
                        elif (key.isdigit()):
                            key = int(key)
                            if (key >= 0 and key <= len(result)):
                                added_data = result[key]
                                self.download_queue.append(added_data)
                                print("%s added" %
                                      added_data["SongName"] if "SongName" in
                                      added_data else added_data["Name"])
                                continue
        except StopIteration:
            pass
        except Exception as inst:
            print("Unexpected error:", sys.exc_info()[0])
            raise inst

    def download(self):
        """
            Download files
        """
        if (self.download_queue != []):
            for file in self.download_queue:
                filename = (
                    "%s/%s - %s.mp3" %
                    (self.output_directory, file["ArtistName"],
                     file["SongName"] if "SongName" in file else file["Name"]))

                if (os.path.exists(filename) is not True):
                    self.download_song(filename, file)
                else:
                    self.download_count += 1
            return True
        return False

    def has_downloaded(self):
        return False if self.download_count == 0 else True
예제 #11
0
class ColorTest(unittest.TestCase):
    def setUp(self):
        self.color = Color()

    def test_given_string_should_apply_style(self):
        self.assertEqual(
            "\033[31mfoo\033[0m",
            str(self.color('foo').red())
        )

    def test_given_string_should_apply_more_than_one_style(self):
        self.assertEqual(
            "\033[1m\033[97mfoo\033[0m\033[0m",
            str(self.color('foo').white().bold())
        )

    def test_style_name_is_not_case_sensitive(self):
        self.assertEqual(
            "\033[31mfoo\033[0m",
            str(self.color('foo').RED())
        )

    def test_state_is_initialized(self):
        self.assertEqual('foo', str(self.color('foo')))
        self.assertEqual('bar', str(self.color('bar')))

    def test_given_styled_string_should_be_able_to_reused(self):
        self.assertEqual('foo', str(self.color('foo').blue().reset()))

    def test_raise_error_when_style_not_found(self):
        self.assertRaises(
            NoStyleFoundError,
            lambda: self.color.color('foo bar').foo()
        )

    def test_style_can_contain_text(self):
        self.assertEqual(
            str(self.color('foo').blue()),
            self.color().blue('foo')
        )

    def test_shortcut_foreground(self):
        self.assertEqual(
            str(self.color('Hello').blue()),
            str(self.color('Hello').fg('blue'))
        )

    def test_shortcut_background(self):
        self.assertEqual(
            str(self.color('Hello').bg_red()),
            str(self.color('Hello').bg('red'))
        )

    def test_has_highlight_shortcut_for_background(self):
        self.assertEqual(
            str(self.color('Hello').bg_blue()),
            str(self.color('Hello').highlight('blue'))
        )

    def test_should_support_themes(self):
        self.color.set_themes({'error': 'red'})
        self.assertEqual(
            str(self.color('Error...').red()),
            str(self.color('Error...').error())
        )

    def test_thmes_can_override_default_styles(self):
        self.color.set_themes({'white': 'red'})
        self.assertEqual(
            str(self.color('Warning...').red()),
            str(self.color('Warning...').white())
        )

    def test_given_invalid_them_name_should_raise_error(self):
        self.assertRaises(
            InvalidStyleNameError,
            lambda: self.color('foo bar').set_themes({'&é""': "white"})
        )

    def test_given_styled_string_can_be_cleaned(self):
        self.assertEqual(
            'some text',
            str(self.color(str(self.color('some text').red())).clean())
        )

    def test_given_string_with_style_tags_should_be_interpret(self):
        text = 'This is <red>some text</red>'
        self.assertEqual(
            'This is ' + str(self.color('some text').red()),
            str(self.color(text).colorize())
        )

    def test_given_string_with_nested_tags_should_be_interpret(self):
        actual = str(
            self.color('<cyan>Hello <bold>World!</bold></cyan>')
            .colorize()
        )
        expected = str(
            self.color('Hello ' + str(self.color('World!').bold()))
            .cyan()
        )
        self.assertEqual(expected, actual)

    def test_apply(self):
        self.assertEqual(
            str(self.color('foo').blue()),
            str(self.color().apply('blue', 'foo'))
        )

    def test_apply_center(self):
        width = 80
        for text in ('', 'hello', 'hellow world', '✩'):
            current_width = len(
                str(self.color(text).center(width))
            )

            self.assertEqual(width, current_width)
            current_width = len(
                str(
                    self.color(text)
                    .center(width)
                    .bg('blue')
                    .clean()
                )
            )
            self.assertEqual(width, current_width)

    def test_apply_center_multiline(self):
        width = 80
        color = Color()
        text = 'hello' + "\n" + '✩' + "\n" + 'world'
        actual = str(color(text).center(width))
        for line in actual.split("\n"):
            self.assertEqual(width, len(line))

    def test_should_support_256_colors(self):
        self.assertEqual(
            "\033[38;5;3mfoo\033[0m",
            self.color().apply('color[3]', 'foo')
        )
        self.assertEqual(
            "\033[48;5;3mfoo\033[0m",
            self.color().apply('bg_color[3]', 'foo')
        )

    def test_given_invalid_color_number_should_raise_error(self):
        self.assertRaises(
            NoStyleFoundError,
            lambda: self.color().apply('color[-1]', 'foo')
        )

        self.assertRaises(
            NoStyleFoundError,
            lambda: self.color().apply('color[256]', 'foo')
        )

    def test_should_handle_recursion_in_theme_with_list(self):
        self.assertRaises(
            RecursionInThemeError,
            lambda: self.color().set_themes(
                {
                    'green': ['green'],
                }
            )
        )

    def test_should_handle_recursion_in_theme_with_string(self):
        self.assertRaises(
            RecursionInThemeError,
            lambda: self.color().set_themes(
                {
                    'green': 'green',
                }
            )
        )
예제 #12
0
 def setUp(self):
     self.color = Color()
예제 #13
0
class Downloader:
    output_directory = None
    connector = None
    subprocess = None
    download_queue = None
    download_count = None
    max_per_list = 10

    def __init__(self, connector, output_directory, subprocess=None):
        """
            Initiliaze Downloader

            Parameters:
                connector: connector to Grooveshark api
                subprocess: spawn new processes
                output_directory: where files will be downloaded
        """
        if subprocess is not None:
            self.subprocess = subprocess
        else:
            import subprocess
            self.subprocess = subprocess

        self.color = Color()

        self.output_directory = output_directory
        self.connector = connector
        self.download_queue = []
        self.download_count = 0

    def download_playlist(self, playlist_id=None):
        """
            Download Playlist

            Parameters:
                playlist_id: the playlist id
        """
        songs = []
        if (playlist_id is not None):
            plist = self.connector.get_playlist_from_id(playlist_id)
            songs = plist["Songs"] if ("Songs" in plist) else []
        else:
            for playlist in self.download_queue:
                plist = self.connector.get_playlist_from_id(
                    playlist['PlaylistID']
                )
                songs = songs + plist["Songs"]

        self.download_queue = songs
        self.download()

    def download_song(self, filename, song):
        """
            Download song

            Parameters:
                filename: the filename
                song: dictionary with song informations
        """
        self.color.cprint(("Downloading: %s" % (filename)), "cyan")
        stream_key = self.connector.get_stream_key_from_song_id(song["SongID"])
        if stream_key == []:
            print("Failed to retrieve stream key!")
            return False

        #Run wget to download the song
        wget = "wget --progress=dot --post-data=streamKey=%s" \
            " -O \"%s\" \"http://%s/stream.php\"" % (
                stream_key["streamKey"], filename, stream_key["ip"]
            )
        cmd = wget + " 2>&1 | grep --line-buffered \"%\" |" \
            "sed -u -e \"s,\.,,g\" | awk '{printf(\"\b\b\b\b%4s\", $2)}'"
        process = self.subprocess.Popen(cmd, shell=True)

        try:
            process.wait()
            self.color.cprint("\nDownloaded", "green")
            self.download_count += 1
        except BaseException:
            self.color.cprint("Download cancelled. File deleted.", "red")
            os.remove(filename)
            return False

        return True

    def prepare(self, query, type=None):
        """
            Prepare downloads

            Parameters:
                query: the search query
                type: the search type
                    (types are 'Songs', 'Artists', 'Albums' or 'Playlists')
        """
        result = self.connector.search(query, type)
        self.__display_raw_input(
            result,
            type,
            "Press \"n\" for next page, "
            "\"Number id\" to add element in queue, "
            "\"q\" for quit and download: "
        )

    def __display_raw_input(self, result, type, input_text):
        """
            Display prompt to choose songs, playlist, etc...

            Parameters:
                result: the result from the connector
                type: the search type
                    (types are 'Songs', 'Artists', 'Albums' or 'Playlists')
                input_text: texte for the raw input
        """
        try:
            if type != "Playlists":
                table = PrettyTable(["id", "Album", "Artist", "Song"])
            else:
                table = PrettyTable(["id", "Name", "Author", "NumSongs"])

            for idx, data in enumerate(result):
                key = None
                if (type != "Playlists"):
                    table.add_row([
                        idx,
                        data["AlbumName"].ljust(40),
                        data["ArtistName"],
                        data["SongName"]
                        if "SongName" in data else data["Name"]])
                else:
                    table.add_row([
                        idx,
                        data["Name"].ljust(40),
                        data["FName"],
                        data["NumSongs"]])

                is_last = (idx == (len(result) - 1))
                if ((idx != 0 and idx % self.max_per_list == 0) or is_last):

                    print(table.get_string())
                    table.clear_rows()
                    while (key is not False):
                        key = input(input_text)
                        if (key == "q"):
                            raise StopIteration
                        elif (key == "n" and is_last is False):
                            key = False
                        elif (key.isdigit()):
                            key = int(key)
                            if (key >= 0 and key <= len(result)):
                                added_data = result[key]
                                self.download_queue.append(added_data)
                                print(
                                    "%s added" %
                                    added_data["SongName"]
                                    if "SongName" in added_data
                                    else added_data["Name"]
                                )
                                continue
        except StopIteration:
            pass
        except Exception as inst:
            print("Unexpected error:", sys.exc_info()[0])
            raise inst

    def download(self):
        """
            Download files
        """
        if (self.download_queue != []):
            for file in self.download_queue:
                filename = (
                    "%s/%s - %s.mp3" %
                    (
                        self.output_directory,
                        file["ArtistName"],
                        file["SongName"]
                        if "SongName" in file else file["Name"]
                    )
                )

                if (os.path.exists(filename) is not True):
                    self.download_song(filename, file)
                else:
                    self.download_count += 1
            return True
        return False

    def has_downloaded(self):
        return False if self.download_count == 0 else True