示例#1
0
	def get_uploaded_tracks(self, user):
		spinner = Halo(text="Fetching uploads")
		spinner.start()			
		tracks = self.client.get("/tracks", id=user.id)
		spinner.stop()
		print("Found {} uploads".format(len(tracks)))
		self.get_multiple_tracks(tracks)          
示例#2
0
	def get_liked_tracks(self):
		spinner = Halo(text="Fetching liked tracks")
		spinner.start()		
		liked_tracks = self.client.get("/resolve", url=self.url + "/likes")
		spinner.stop()
		print("{} liked track(s) found".format(len(liked_tracks)))
		self.get_multiple_tracks(liked_tracks)
示例#3
0
def require(package):
    """ Specifies a package that should be installed.

    By default, this method will use the default package manager of the OS
    (brew for Mac, apt-get for Ubuntu, etc.), but you can override the default
    package by specifying it in the `package_aliases.py` file.

    Args:
        package (str): User-friendly name of package. Most often, this will be
            the same as the actual name of the package in the package manager,
            but some packages will have different names on different systems.
            Use your best judgement to determine what name to use.
    """
    DefaultPackageManager = default_package_managers[get_platform()]
    command = DefaultPackageManager(package)
    if package in package_aliases:
        default = package_aliases[package].get('default', command)
        command = package_aliases[package].get(get_platform(), default)

    if command is None:
        return

    spinner = Halo(
        text="Installing {}".format(package), spinner="dots", placement="right"
    )
    spinner.start()
    successful = command.execute()
    if not successful:
        spinner.fail()
    else:
        spinner.succeed()
示例#4
0
文件: svm.py 项目: techieji/shop
 def load_from_backup(klass, backup='shop', catch=True, snapshot_n=-1):
     answers = prompt([{
         'type': 'confirm',
         'name': 'overwrite',
         'message':
         f'Any files already in this directory will be overwritten. Is that all right?',
         'default': False
     }])
     if not answers['overwrite']: return
     spinner = Halo('Loading snapshot').start()
     klass.load(backup, catch).snapshots[snapshot_n].restore(spinner)
     spinner.start().succeed('Snapshot loaded!')
示例#5
0
    def test_fail(self):
        """Test fail method
        """
        spinner = Halo(stream=self._stream)
        spinner.start('foo')
        spinner.fail()

        output = self._get_test_output()['text']
        pattern = re.compile(r'(✖|×) foo', re.UNICODE)

        self.assertRegexpMatches(output[-1], pattern)
        spinner.stop()
示例#6
0
    def test_warning(self):
        """Test warn method
        """
        spinner = Halo(stream=self._stream)
        spinner.start('foo')
        spinner.warn('Warning!')

        output = self._get_test_output()['text']
        pattern = re.compile(r'(⚠|!!) Warning!', re.UNICODE)

        self.assertRegexpMatches(output[-1], pattern)
        spinner.stop()
示例#7
0
class SpinnerCursor(object):
    def __init__(self, text, spinner):
        """Create a spinner to show execution while waiting for processes"""
        self.spinner = Halo(text=text, spinner=spinner)

    def start(self):
        """start the animation of cursor"""
        self.spinner.start()

    def stop(self):
        """stop the animation of cursor"""
        self.spinner.succeed('End!')
示例#8
0
    def test_succeed_with_new_text(self):
        """Test succeed method with new text
        """
        spinner = Halo(stream=self._stream)
        spinner.start('foo')
        spinner.succeed('bar')

        output = self._get_test_output()['text']
        pattern = re.compile(r'(✔|v) bar', re.UNICODE)

        self.assertRegexpMatches(output[-1], pattern)
        spinner.stop()
示例#9
0
文件: test_halo.py 项目: inxming/halo
    def test_info(self):
        """Test info method
        """
        spinner = Halo(stream=self._stream)
        spinner.start('foo')
        spinner.info()

        output = self._get_test_output()
        pattern = re.compile(r'(ℹ|¡) foo', re.UNICODE)

        self.assertRegexpMatches(output[-1], pattern)
        spinner.stop()
示例#10
0
文件: test_halo.py 项目: inxming/halo
    def test_succeed(self):
        """Test succeed method
        """
        spinner = Halo(stream=self._stream)
        spinner.start('foo')
        spinner.succeed('foo')

        output = self._get_test_output()
        pattern = re.compile(r'(✔|v) foo', re.UNICODE)

        self.assertRegexpMatches(output[-1], pattern)
        spinner.stop()
示例#11
0
def main(ARGS):
    # Load DeepSpeech model
    if os.path.isdir(ARGS.model):
        model_dir = ARGS.model
        ARGS.model = os.path.join(model_dir, 'output_graph.pb')
        ARGS.alphabet = os.path.join(
            model_dir, ARGS.alphabet if ARGS.alphabet else 'alphabet.txt')
        ARGS.lm = os.path.join(model_dir, ARGS.lm)
        ARGS.trie = os.path.join(model_dir, ARGS.trie)

    print('Initializing model...')
    logging.info("ARGS.model: %s", ARGS.model)
    logging.info("ARGS.alphabet: %s", ARGS.alphabet)
    model = deepspeech.Model(ARGS.model, ARGS.n_features, ARGS.n_context,
                             ARGS.alphabet, ARGS.beam_width)
    if ARGS.lm and ARGS.trie:
        logging.info("ARGS.lm: %s", ARGS.lm)
        logging.info("ARGS.trie: %s", ARGS.trie)
        model.enableDecoderWithLM(ARGS.alphabet, ARGS.lm, ARGS.trie,
                                  ARGS.lm_alpha, ARGS.lm_beta)

    # Start audio with VAD
    vad_audio = VADAudio(aggressiveness=ARGS.vad_aggressiveness,
                         device=ARGS.device,
                         input_rate=ARGS.rate)
    print("Listening (ctrl-C to exit)...")
    frames = vad_audio.vad_collector()

    # Stream from microphone to DeepSpeech using VAD
    spinner = None
    if not ARGS.nospinner: spinner = Halo(spinner='line')
    stream_context = model.setupStream()
    wav_data = bytearray()
    for frame in frames:
        if frame is not None:
            if spinner: spinner.start()
            logging.debug("streaming frame")
            model.feedAudioContent(stream_context,
                                   np.frombuffer(frame, np.int16))
            if ARGS.savewav: wav_data.extend(frame)
        else:
            if spinner: spinner.stop()
            logging.debug("end utterence")
            if ARGS.savewav:
                vad_audio.write_wav(
                    os.path.join(
                        ARGS.savewav,
                        datetime.now().strftime(
                            "savewav_%Y-%m-%d_%H-%M-%S_%f.wav")), wav_data)
                wav_data = bytearray()
            text = model.finishStream(stream_context)
            print("Recognized: %s" % text)
            stream_context = model.setupStream()
示例#12
0
    def go(self, _url=None, _params={}):
        # Serialise the final search query
        request = _url + '?' + urllib.urlencode(_params)

        # GitHub conventions...
        request = request.replace('%3A', ':')
        request = request.replace('%2B', '+')

        if self.verbose:
            print('Requesting %s...' % request)

        # Make the request!
        response = requests.get(request,
                                headers={
                                    'Accept':
                                    'application/vnd.github.cloak-preview',
                                    'Authorization':
                                    'token ' + self.args['github_oauth_token']
                                })
        raw_data = response.json()

        # We've probably hit a rate limit
        if 'items' not in raw_data.keys():
            if 'X-RateLimit-Reset' in response.headers:
                reset_at = datetime.fromtimestamp(
                    float(response.headers['X-RateLimit-Reset']))

                # Wait until reset
                diff = (reset_at - datetime.now()).total_seconds()

                if diff > 0:
                    # + 5 for good measure
                    diff = int(diff + 5)
                    countdown_text = 'Waiting %d seconds due to rate limiting...'

                    ratelimit = Halo(text=countdown_text % diff,
                                     spinner='dots')
                    ratelimit.start()

                    for i in range(diff):
                        ratelimit.text = countdown_text % (diff - i)
                        try:
                            time.sleep(1)
                        except IOError:
                            pass

                    ratelimit.stop()

            # Try again?
            response = self.go(_url, _params)

        return response
示例#13
0
def main():
    """
    usage: nrql [-h] [--region {EU,US}] [--env ENV] [--verbose]

    optional arguments:
      -h, --help            show this help message and exit
      --region {EU,US}, --r {EU,US}
                            Pass this flag to set your region (EU or US) By
                            default the region is set to US.
      --env ENV, --e ENV    Environment handler.
      --verbose, --v        Pass this flag if you want the whole response.
        :return:
    """
    style = Style.from_dict({
        "completion-menu.completion": "bg:#008888 #ffffff",
        "completion-menu.completion.current": "bg:#00aaaa #000000",
        "scrollbar.background": "bg:#88aaaa",
        "scrollbar.button": "bg:#222222",
    })
    args = arg_parser()
    nrql = NRQL()
    nrql.verbose = args.verbose
    nrql.region = args.region
    wordlist = load_or_generate()
    nrql_completer = WordCompleter(wordlist, ignore_case=True)
    session = PromptSession(lexer=PygmentsLexer(SqlLexer),
                            completer=nrql_completer,
                            style=style)
    print("Welcome to your data, let's get querying...")
    while True:
        try:
            text = session.prompt("> ")
        except KeyboardInterrupt:
            continue
        except EOFError:
            break
        else:
            if not (text and text.strip()):
                continue
            if text == "quit()":
                sys.exit(0)
            spinner = Halo(spinner="dots")
            spinner.start()
            req = nrql.query(text)
            spinner.stop()
            formatted_json = json.dumps(req, sort_keys=True, indent=4)
            print(
                highlight(
                    str(formatted_json).encode("utf-8"),
                    lexers.JsonLexer(),
                    formatters.TerminalFormatter(),
                ))
示例#14
0
    def print_subreddits(reddit, search_for):
        """
        Print valid and invalid Subreddits.

        Calls previously defined private method:

            PrintSubs._find_subs()

        Parameters
        ----------
        reddit: Reddit object
            Reddit instance created by PRAW API credentials
        search_for: str
            String denoting Subreddits to scrape for

        Returns
        -------
        subs: list
            List of valid Subreddits
        not_subs: list
            List of invalid Subreddits
        """

        check_subs_spinner = Halo(color = "white", text = "Validating Subreddit(s).")
        print()
        check_subs_spinner.start()
        not_subs, subs = PrintSubs._find_subs(reddit, search_for)
        check_subs_spinner.succeed("Finished Subreddit validation.")

        if subs:
            print(Fore.GREEN + Style.BRIGHT + "\nThe following Subreddits were found and will be scraped:")
            print(Fore.GREEN + Style.BRIGHT + "-" * 56)
            print(*subs, sep = "\n")
        if not_subs:
            print(Fore.YELLOW + Style.BRIGHT + "\nThe following Subreddits were not found and will be skipped:")
            print(Fore.YELLOW + Style.BRIGHT + "-" * 60)
            print(*not_subs, sep = "\n")

            logging.warning("Failed to validate the following Subreddits:")
            logging.warning(f"{not_subs}")
            logging.warning("Skipping.")
            logging.info("")

        if not subs:
            logging.critical("ALL SUBREDDITS FAILED VALIDATION.")
            Errors.n_title("Subreddits")
            logging.critical("NO SUBREDDITS LEFT TO SCRAPE.")
            logging.critical("ABORTING URS.\n")
            
            quit()

        return subs
示例#15
0
 def search(self, time_now=datetime.now()):
     """
     This method takes datetime object and searches all the Food trucks that are open at the time that is passed
     as argument. If no value is passed then it takes the current time as default.
     :param time_now: Python datetime object. Default value is current time
     :return: None
     """
     # getting day of the week. this is used to filter the 'dayorder' field in Socrata data
     current_day_order = time_now.isoweekday()
     # formatting time stamp into HH:MM format. this will be used as a filter out food trucks whose start and end
     # time do not contain current timestamp
     time_str = "'{}'".format(time_now.strftime('%H:%M'))
     self.display_message("\nTime is: {}".format(time_now.strftime("%c")))
     try:
         # initialize Halo spinner object to display spinner in console while we fetch data from the SODA API
         spinner = Halo()
         spinner.start("Finding food trucks for you...")
         # here the query is selecting 'applicant', 'location', 'start24', 'end24', 'dayorder', 'dayofweekstr' only
         # it is also filtering the result where 'start24' of the food truck data is less than the current time and
         # 'end24' is greater than equal to current time (start24 <= time_str <= end24). It is also filtering the
         # result by the day of the week by specifying dayorder=current_day_order. And finally it orders the result
         # in ascending order of 'applicant' field which is the name of the Food Truck. I am assuming the 'applicant'
         # field is the name of the Food Truck
         socrata_data = self.api_service.select([
             'applicant', 'location', 'start24', 'end24', 'dayorder',
             'dayofweekstr'
         ]).where(start24__lte=time_str,
                  end24__gte=time_str,
                  dayorder=current_day_order).order_by('applicant').query(
                      self.socrata_dataset_id)
         # stop and clear the spinner from the console to clean it up before printing the final output
         spinner.stop()
         spinner.clear()
         # parse and convert the response JSON into a List of SocrataData model object
         socrata_data_list = parse_obj_as(List[SocrataData], socrata_data)
         # for some Food trucks, there are multiple entries in the result because of different timings in the day
         # I only need any one out of these. As we are getting already filtered result that fit our criteria from the
         # API, I can sure that all these entries are valid. To remove duplicate I am using a python dictionary where
         # the key is a unique combination of 'applicant' and 'location' field. I am using a dictionary instead of
         # hash set because I want maintain the insertion order of the already sorted result. In Python3, sets don't
         # guarantee insertion order but by default a dictionary is ordered in Python 3.
         for data in socrata_data_list:
             self.foodtruck_dataset[(data.applicant, data.location)] = data
         self.total_foodtrucks_open = len(self.foodtruck_dataset)
         # Once I have the dictionary of the dataset, I am updating the PrettyTable rows with the data
         self.__update_ptable()
     except requests.exceptions.HTTPError as ex:
         logging.error(str(ex))
     except:
         traceback.print_exc()
         logging.error(
             "unhandled exception occurred while searching food trucks")
示例#16
0
    def read_dataset(self):
        """
        Method to read image dataset in numpy array for training the model.

        The structure of the data dir at `data_dir_path` should be:
            data
            ├── a
            |   ├── 1.png
            |   ├── 2.png
            |   └── ...
            ├── b
            |   ├── 1.png
            |   ├── 2.png
            |   └── ...
            └── ...

        Sub directory name is the name of the label and contains MNIST format compliant handwritten images
        of the character denoted by that label.
        """

        base_sep_count = self.data_dir_path.count(os.sep)
        features = []
        labels = []

        spinner = Halo(text='Reading', spinner='dots')
        spinner.start()

        for subdir, dirs, files in os.walk(self.data_dir_path, topdown=True):
            # go only 2 levels deep
            if subdir.count(os.sep) - base_sep_count == 1:
                del dirs[:]
                continue

            for filename in files:
                filepath = os.path.join(subdir, filename)

                if imghdr.what(filepath) == 'png':
                    labels.append(
                        [os.path.basename(os.path.dirname(filepath))])

                    name_im = cv2.imread(filename=filepath)
                    name_im = np.dot(name_im[..., :3], [0.299, 0.587, 0.114])
                    name_im = name_im.flatten()

                    features.append(list(name_im))

        spinner.succeed(text='Finished reading')

        features = np.array(features)
        labels = np.array(labels).ravel()

        return features, labels
示例#17
0
def read_screen():
    spinner = Halo(text='Reading screen', spinner='bouncingBar')
    spinner.start()
    screenshot_file = "Screens/to_ocr.png"
    screen_grab(screenshot_file)

    #prepare argparse
    ap = argparse.ArgumentParser(description='HQ_Bot')
    ap.add_argument("-i",
                    "--image",
                    required=False,
                    default=screenshot_file,
                    help="path to input image to be OCR'd")
    ap.add_argument("-p",
                    "--preprocess",
                    type=str,
                    default="thresh",
                    help="type of preprocessing to be done")
    args = vars(ap.parse_args())

    # load the image
    image = cv2.imread(args["image"])
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    if args["preprocess"] == "thresh":
        gray = cv2.threshold(gray, 0, 255,
                             cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
    elif args["preprocess"] == "blur":
        gray = cv2.medianBlur(gray, 3)

    # store grayscale image as a temp file to apply OCR
    filename = "Screens/{}.png".format(os.getpid())
    cv2.imwrite(filename, gray)

    # load the image as a PIL/Pillow image, apply OCR, and then delete the temporary file
    text = pytesseract.image_to_string(Image.open(filename), lang="spa")

    #Uncomment the following block to delete screenshots after read
    '''os.remove(filename)
	os.remove(screenshot_file)'''

    # show the output images
    '''cv2.imshow("Image", image)
	cv2.imshow("Output", gray)
	os.remove(screenshot_file)
	if cv2.waitKey(0):
		cv2.destroyAllWindows()
	print(text)
	'''
    spinner.succeed()
    spinner.stop()
    return text
示例#18
0
 def main(self):
     os.chdir(self.dirname)
     if self.args.top:
         self.get_charted_tracks("top")
         return
     if self.args.new:
         self.get_charted_tracks("trending")
         return
     spinner = Halo(text="Resolving URL")
     spinner.start()
     params = {"url": self.url, "client_id": client_id}
     url = "{}/resolve".format(self.API_V2)
     res = self.session.get(url, params=params)
     if not res.ok:
         print(
             "Could not get a valid response from the SoundCloud API. Please check the API key"
         )
         return
     res = res.json()
     data = resource.Resource(res)
     spinner.stop()
     if isinstance(data, resource.Resource):
         if data.kind == "user":
             print("User profile found")
             folder = validate_name(data.username)
             if not os.path.isdir(folder): os.mkdir(folder)
             os.chdir(os.path.join(os.getcwd(), folder))
             print("Saving in: " + os.getcwd())
             if self.args.all or self.args.likes:
                 self.get_liked_tracks(data)
             if not self.args.likes:
                 self.get_uploaded_tracks(data)
         elif data.kind == "track":
             print("Single track found")
             print("Saving in: " + os.getcwd())
             if self.args.similar:
                 self.get_recommended_tracks(data)
             self.get_single_track(data)
         elif data.kind == "playlist":
             print("Single playlist found.")
             folder = validate_name(data.user["username"])
             if not os.path.isdir(folder):
                 os.mkdir(folder)
             os.chdir(os.path.join(os.getcwd(), str(folder)))
             self.get_playlist(data)
     elif isinstance(data, resource.ResourceList):
         if data[0].kind == "playlist":
             print("%d playlists found" % (len(data)))
             for playlist in data:
                 self.get_playlist(playlist)
         elif data[0].kind == "track":
             self.get_multiple_tracks(data)
示例#19
0
def main1(ARGS, time_limit):
    # Load DeepSpeech model
    #logging.info("ARGS.model: %s", ARGS.model)
    model = deepspeech.Model(ARGS.model)
    if ARGS.scorer:
        #logging.info("ARGS.scorer: %s", ARGS.scorer)
        model.enableExternalScorer(ARGS.scorer)

    # Start audio with VAD
    vad_audio = VADAudio(aggressiveness=ARGS.vad_aggressiveness,
                         device=ARGS.device,
                         input_rate=ARGS.rate,
                         file=ARGS.file)

    frames = vad_audio.vad_collector()

    # Stream from microphone to DeepSpeech using VAD
    spinner = None
    if not ARGS.nospinner:
        spinner = Halo(spinner='line')
    stream_context = model.createStream()
    wav_data = bytearray()
    StartTime = datetime.now()
    flag = 0
    for frame in frames:

        Span = datetime.now() - StartTime
        if Span.seconds > time_limit:
            return 1

        if frame is not None:
            if spinner: spinner.start()
            #logging.debug("streaming frame")
            stream_context.feedAudioContent(np.frombuffer(frame, np.int16))
            if ARGS.savewav: wav_data.extend(frame)
        else:
            if spinner: spinner.stop()
            #logging.debug("end utterence")
            if ARGS.savewav:
                vad_audio.write_wav(
                    os.path.join(
                        ARGS.savewav,
                        datetime.now().strftime(
                            "savewav_%Y-%m-%d_%H-%M-%S_%f.wav")), wav_data)
                wav_data = bytearray()
            text = stream_context.finishStream()
            print(text)

            if check(text) > 0:
                return 0

            stream_context = model.createStream()
示例#20
0
    def upload(self, history_path=None):
        ''' Upload current history '''
        spinner = Halo(text='Uploading ...', spinner='dots')
        spinner.start()

        # Validate token key
        config.check_authorization(spinner, spinner_callback)

        try:
            if config.parser['Auth']['gist_id']:
                gist = config.gist.get_gist(config.parser['Auth']['gist_id'])

                # Set upload date
                config.parser['Upload']['last_date'] = str(int(time.time()))
                config.write()

                gist.edit(files=read_files())

                spinner_callback(spinner,
                                 'Gist ID ({}) updated.'.format(gist.id),
                                 'succeed')
            else:
                description = 'syncshell Gist'
                gist = config.gist.get_user().create_gist(
                    False, read_files(), description)

                # Set upload date
                config.parser['Upload']['last_date'] = str(int(time.time()))
                config.parser['Auth']['gist_id'] = gist.id
                config.write()

                gist.edit(files=read_files())
                spinner_callback(spinner,
                                 'New Gist ID ({}) created.'.format(gist.id),
                                 'succeed')
        except FileNotFoundError as e:
            spinner_callback(spinner, 'Couldn\'t find history file.', 'fail')
            sys.exit(1)
        except KeyError as e:
            spinner_callback(spinner, 'Request\'s data is not valid', 'fail')
            sys.exit(1)
        except UnknownObjectException as e:
            if e.status == 404:
                config.parser['Auth']['gist_id'] = ''
                config.write()

                logger.warn('To create new gist run command again.')

            spinner_callback(spinner, '{} - {}'.format(e.status,
                                                       e.data['message']),
                             'fail')
            sys.exit(1)
示例#21
0
async def original_writeups(link):
    """Get all the information about events along with
       link to original writeups

    :link: A URL to the tasks of a CTF

    :return: Information about the all the task along with URL
             to original writeups in tabulated form
    """
    spinner = Halo(text=colors("Grabing writeups", "32"),
                   spinner='moon',
                   color='green')
    spinner.start()

    info = []
    headers = ['S.no', 'Name', 'Points', 'tags', 'URL']
    soup = await make_soup(link)
    trs = soup.findAll('tr')

    # For getting tasks links
    for ind, tr in enumerate(trs[1:]):
        rated = {}
        gen = tr.text.split('\n')

        # Check if writeup exists or not
        if gen[-1] == str(0):
            tags = ','.join(gen[3:-2])
            info.append([ind, gen[0], gen[1], tags, "No writeups"])
            continue

        url = ROOT_URL + tr.find('a').get('href')
        soup = await make_soup(url)
        trs1 = soup.findAll('tr')

        # For getting "all" the writeups of one task
        for tr1 in trs1[1:]:
            para = soup.findAll('p')
            name = soup.find('h2').text
            point = para[0].text.split(':')[-1].strip()
            tags = para[1].text.split(':')[-1].split('\xa0')
            tags = ', '.join(i for i in tags[:-1])
            rated[tr1.find('a').get('href')] = tr1.find('div').text

        # Get writeup link which has the max rating.
        Link = await original_writeup_link(max(rated, key=rated.get))

        info.append([ind, name, point, tags, Link])

    table = tabulate(info, headers, tablefmt="fancy_grid")

    spinner.succeed("Voila!!")
    return table
示例#22
0
	def get_recommended_tracks(self, track, no_of_tracks=10):
		params = {
			"client_id": secret,
			"limit": no_of_tracks,
			"offset": 0
		}		
		spinner = Halo(text="Fetching tracks similar to {}".format(track.title))
		spinner.start()	
		recommended_tracks_url = "{}/tracks/{}/related".format(self.API_V2, track.id)
		r = self.session.get(recommended_tracks_url, params=params)
		spinner.stop()
		tracks = json.loads(r.text)["collection"]
		self.get_multiple_tracks(tracks)
示例#23
0
def snakeless_spinner(*args, **kwargs):
    spinner = Halo(*args, **kwargs)
    spinner.start()
    try:
        yield spinner
    except CommandFailure as exc:
        spinner.fail(str(exc))
        raise
    except Exception as exc:
        spinner.fail(spinner.text + "\n" + "Unexpected exception.")
        raise
    finally:
        spinner.stop()
示例#24
0
def onlyOneTargetUserName():
    try:
        TITLE = " SEARCH BY USER NAME"
        username = str(input("User Name: "))
        spinner = Halo(text='Loading', spinner='dots')

        prints.titlePrint(TITLE)

        spinner.start()
        open_sources.searchOnAllOpenSourcesByUsername(username)
        spinner.stop()
    except ValueError:
        exceptions.printException(__name__)
示例#25
0
 def create_staff(self):
     spinner = Halo("Creating a staff user")
     spinner.start()
     email = "*****@*****.**"
     User.objects.create_user(
         email=email,
         password=USER_PW,
         first_name="Staff",
         last_name="Staffski",
         is_staff=True,
         phone_number="87654321"
     )
     spinner.succeed("Creating staff user. email: {}, password: {}".format(email, USER_PW))
示例#26
0
	def download(self, survey, datatype):
		spinner = Halo(text='Downloading ' + datatype + ' for ' + survey, spinner='dots')
		spinner.start()
		try:
			url_base = "surveys/selfserve/bb5/" + survey + "/" + datatype
			
			result = api.get(url_base, format="json")
			spinner.succeed('Download complete')
			return result
		except:
			# print("[ERROR] ", sys.exc_info()[0])
			spinner.fail('An error occured')
			raise
示例#27
0
    def test_initial_title_spinner(self):
        """Test Halo with initial title.
        """
        spinner = Halo('bar', stream=self._stream)

        spinner.start()
        time.sleep(1)
        spinner.stop()
        output = self._get_test_output()['text']

        self.assertEqual(output[0], '{} bar'.format(frames[0]))
        self.assertEqual(output[1], '{} bar'.format(frames[1]))
        self.assertEqual(output[2], '{} bar'.format(frames[2]))
示例#28
0
def send_request(API_URI, method="GET"):
    spinner = Halo(text='\t Hold on a second ....', spinner='dots')
    spinner.start()
    try:
        response = requests.get(API_URI, timeout=5)
        resp_json = response.json()
        spinner.stop()
        return resp_json
    except Exception:
        logger.log_error(
            "Request Exception Occured! Please check network connection"
        )
    spinner.stop()
示例#29
0
    def test_basic_spinner(self):
        """Test the basic of basic spinners.
        """
        spinner = Halo(text='foo', spinner='dots', stream=self._stream)

        spinner.start()
        time.sleep(1)
        spinner.stop()
        output = self._get_test_output()['text']

        self.assertEqual(output[0], '{} foo'.format(frames[0]))
        self.assertEqual(output[1], '{} foo'.format(frames[1]))
        self.assertEqual(output[2], '{} foo'.format(frames[2]))
示例#30
0
def main():
    init()  #initialize colorama
    print(Back.BLUE + Fore.RED + " halo spinner example ")
    #create the Halo spinner
    spinner = Halo(text='What is taking so long..',
                   text_color='cyan',
                   color='green')
    #start the spin simulation
    spinner.start()
    #sleep
    time.sleep(5)
    #stop and print the final message
    spinner.stop_and_persist(symbol='✔ '.encode('utf-8'), text='Done!')
def UnzipFiles():
    spinner = Halo(text='Unpacking Data', spinner='dots')
    spinner.start()
    for item in os.listdir('data'):  # loop through items in dir
        if item.endswith('.zip'):  # check for ".zip" extension
            file_name = os.path.abspath('data/' +
                                        item)  # get full path of files
            zip_ref = zipfile.ZipFile(file_name)  # create zipfile object
            zip_ref.extractall('data')  # extract file to dir
            zip_ref.close()  # close file
            #os.remove(file_name) # delete zipped file
    spinner.succeed('Data Unpacked')
    pass
示例#32
0
def audio_main():
    #print('Initializing model...')

    # DeepSpeech parameters
    model_file_path = 'deepspeech-0.9.3-models.pbmm'
    '''https://github.com/mozilla/DeepSpeech/releases/download/v0.9.3/deepspeech-0.9.3-models.pbmm '''
    model = ds.Model(model_file_path)

    scorer_file_path = 'deepspeech-0.9.3-models.scorer'
    """https://github.com/mozilla/DeepSpeech/releases/download/v0.9.3/deepspeech-0.9.3-models.scorer"""
    model.enableExternalScorer(scorer_file_path)

    lm_alpha = 0.75
    lm_beta = 1.85
    model.setScorerAlphaBeta(lm_alpha, lm_beta)

    beam_width = 500
    model.setBeamWidth(beam_width)

    # Start audio with VAD
    vad_audio = VADAudio(aggressiveness=ARGS.vad_aggressiveness,
                         device=ARGS.device,
                         input_rate=ARGS.rate,
                         file=ARGS.file)
    print("Listening (ctrl-C to exit)...")
    frames = vad_audio.vad_collector()

    # Stream from microphone to DeepSpeech using VAD
    spinner = None
    if not ARGS.nospinner:
        spinner = Halo(spinner='line')
    stream_context = model.createStream()
    wav_data = bytearray()
    for frame in frames:
        if frame is not None:
            if spinner: spinner.start()
            logging.debug("streaming frame")
            stream_context.feedAudioContent(np.frombuffer(frame, np.int16))
            if ARGS.savewav: wav_data.extend(frame)
        else:
            if spinner: spinner.stop()
            logging.debug("end utterence")
            if ARGS.savewav:
                vad_audio.write_wav(
                    os.path.join(
                        ARGS.savewav,
                        datetime.now().strftime(
                            "savewav_%Y-%m-%d_%H-%M-%S_%f.wav")), wav_data)
                wav_data = bytearray()
            text = stream_context.finishStream()
            return text
示例#33
0
def run_processing():
    # push code to colab and run the colab start and stop
    try:
        url = input("Enter the url generated in colab: ")
        hostname, port = url.split(":")
        port = int(port)
        key = input("Enter secret key: ")
        passwd = hashlib.sha1(
            hashlib.sha1(key.encode("utf-8")).hexdigest()[:10].encode(
                "utf-8")).hexdigest()[:10]
        vnc_pass = hashlib.sha1(passwd.encode("utf-8")).hexdigest()[:10]
    except Exception as e:
        print("Error: " + str(e))
        exit(1)
    try:
        spinner = Halo(text="Connecting", spinner="dots")
        spinner.start()
        with Connection(host=hostname,
                        port=port,
                        user="******",
                        connect_kwargs={"password": passwd}) as c:
            server = SSHTunnelForwarder(
                (hostname, port),
                ssh_username="******",
                ssh_password=passwd,
                remote_bind_address=('127.0.0.1', 5901),
                local_bind_address=('0.0.0.0', 5901))
            server.start()
            spinner.succeed("Connected")
            sudopass = Responder(
                pattern=r"\[sudo\] password for colab:",
                response=f"{passwd}\n",
            )
            spinner = Halo(text="Setting up Processing3", spinner="dots")
            spinner.start()
            c.run(
                "cd /content && sudo wget https://github.com/processing/processing/releases/download/processing-0270-3.5.4/processing-3.5.4-linux64.tgz && sudo tar xvfz processing-3.5.4-linux64.tgz",
                pty=True,
                watchers=[sudopass],
                hide="out",
            )
            spinner.succeed("Finished setting up Processing3")
            print(
                f"Open up your VNC client and enter {bcolors.WARNING}localhost:5901{bcolors.ENDC}. Password is {bcolors.WARNING}{vnc_pass}{bcolors.ENDC}. Once you're connected, open up Terminal and type this: {bcolors.WARNING}/content/processing-3.5.4/processing{bcolors.ENDC}"
            )
    except Exception as e:
        spinner.fail("Something went wrong when running.")
        print(str(e))
        exit(1)
    _ = input("Press CTRL+C twice to exit.")
    server.stop()
示例#34
0
def run():
    tf.reset_default_graph()

    train_dataset, val_dataset = load_all_datasets()

    handle, training_iterator, validation_iterator, next_element = load_iterators(
        train_dataset, val_dataset)

    training, img, mask, out, merged, upd = model(*next_element)

    saver = tf.train.Saver(max_to_keep=2)

    sess = tf.Session()

    train_writer = tf.summary.FileWriter('./logs/train', sess.graph)
    val_writer = tf.summary.FileWriter('./logs/val', sess.graph)

    sess.run(tf.global_variables_initializer())

    training_handle = sess.run(training_iterator.string_handle())
    validation_handle = sess.run(validation_iterator.string_handle())

    i = 0

    spinner = Halo(text='Training', spinner='dots')
    subprocess.Popen([
        "tensorboard", "--logdir", "./logs", "--port", "6006", "--host",
        "0.0.0.0"
    ])

    spinner.start()
    while True:
        m, _ = sess.run([merged, upd], feed_dict={handle: training_handle})
        train_writer.add_summary(m, i)

        if i % 100 == 0:
            m = sess.run(merged,
                         feed_dict={
                             training: False,
                             handle: validation_handle
                         })
            val_writer.add_summary(m, i)
            val_writer.flush()

        if i % 1000 == 0 and i > 0:
            # Save model
            saver.save(sess, "./models/model.ckpt", global_step=i)

        i += 1

    spinner.stop()
示例#35
0
def main(ARGS):
    # Load DeepSpeech model
    if os.path.isdir(ARGS.model):
        model_dir = ARGS.model
        ARGS.model = os.path.join(model_dir, 'output_graph.pb')
        ARGS.alphabet = os.path.join(model_dir, ARGS.alphabet if ARGS.alphabet else 'alphabet.txt')
        ARGS.lm = os.path.join(model_dir, ARGS.lm)
        ARGS.trie = os.path.join(model_dir, ARGS.trie)

    print('Initializing model...')
    logging.info("ARGS.model: %s", ARGS.model)
    logging.info("ARGS.alphabet: %s", ARGS.alphabet)
    model = deepspeech.Model(ARGS.model, ARGS.n_features, ARGS.n_context, ARGS.alphabet, ARGS.beam_width)
    if ARGS.lm and ARGS.trie:
        logging.info("ARGS.lm: %s", ARGS.lm)
        logging.info("ARGS.trie: %s", ARGS.trie)
        model.enableDecoderWithLM(ARGS.alphabet, ARGS.lm, ARGS.trie, ARGS.lm_alpha, ARGS.lm_beta)

    # Start audio with VAD
    vad_audio = VADAudio(aggressiveness=ARGS.vad_aggressiveness,
                         device=ARGS.device,
                         input_rate=ARGS.rate)
    print("Listening (ctrl-C to exit)...")
    frames = vad_audio.vad_collector()

    # Stream from microphone to DeepSpeech using VAD
    spinner = None
    if not ARGS.nospinner: spinner = Halo(spinner='line')
    stream_context = model.setupStream()
    wav_data = bytearray()
    for frame in frames:
        if frame is not None:
            if spinner: spinner.start()
            logging.debug("streaming frame")
            model.feedAudioContent(stream_context, np.frombuffer(frame, np.int16))
            if ARGS.savewav: wav_data.extend(frame)
        else:
            if spinner: spinner.stop()
            logging.debug("end utterence")
            if ARGS.savewav:
                vad_audio.write_wav(os.path.join(ARGS.savewav, datetime.now().strftime("savewav_%Y-%m-%d_%H-%M-%S_%f.wav")), wav_data)
                wav_data = bytearray()
            text = model.finishStream(stream_context)
            print("Recognized: %s" % text)
            stream_context = model.setupStream()
示例#36
0
	def get_charted_tracks(self, kind, no_of_tracks=10):
		url_params = {
			"limit": no_of_tracks,
			"genre": "soundcloud:genres:" + self.args.genre,
			"kind": kind,
			"client_id": secret
		}
		url = "{}/charts".format(self.API_V2)
		tracks = []
		spinner = Halo(text="Fetching {} {} tracks".format(no_of_tracks, kind))
		spinner.start()
		while len(tracks) < no_of_tracks:
			response = self.session.get(url, params=url_params)
			json_payload = json.loads(response.text)
			tracks += json_payload["collection"]
			url = json_payload["next_href"]
		spinner.stop()
		tracks = map(lambda x: x["track"], tracks[:no_of_tracks])
		self.get_multiple_tracks(tracks)
示例#37
0
def link(src, dest, backup_dir):
    """ Creates a symbolic link at the specified location.

    Args:
        src (str): Path to the file that we want to link to.
        dest (str): Path of the link that will be created.
        backupd_dir (str): Path to directory to backup existing files.
    """
    message = "linking %s" % os.path.basename(src)
    spinner = Halo(text=message, spinner="dots", placement="right")
    spinner.start()
    if os.path.islink(dest):
        os.unlink(dest)

    if os.path.exists(dest):
        _backup(dest, backup_dir)

    os.symlink(src, dest)
    spinner.succeed()
示例#38
0
def configure(namespace, key, *values):
    """ Sets configuration on mac using `defaults` """
    spinner = Halo(
        text="Setting {}".format(key),
        spinner="dots",
        placement="right"
    )
    spinner.start()
    try:
        if namespace:
            sh.defaults("write", namespace, key, *values)
        else:
            sh.defaults("write", key, *values)
        spinner.succeed()
    except sh.ErrorReturnCode as err:
        err_message = "\n\t" + err.stderr.replace("\n", "\n\t")
        logging.error(
            "Error with `defaults write -g %s %s: %s", key, values, err_message
        )
        spinner.fail()
示例#39
0
def default_shell(name):
    """ Sets default shell for the current user. """
    spinner = Halo(
        text="Default shell `{}`".format(name),
        spinner="dots",
        placement="right"
    )
    spinner.start()
    try:
        path = sh.which(name).strip()
        user = sh.whoami().strip()
        with Authentication():
            sh.chsh("-s", path, user)
        spinner.succeed()
    except sh.ErrorReturnCode as err:
        err_message = "\n\t" + err.stderr.replace("\n", "\n\t")
        logging.error(
            "Error changing default shell to %s: %s", name, err_message
        )
        spinner.fail()
示例#40
0
	def main(self):
		os.chdir(self.dirname)
		if self.args.top:
			self.get_charted_tracks("top")
		if self.args.new:
			self.get_charted_tracks("trending")
		spinner = Halo(text="Resolving URL")
		spinner.start()		
		data = self.client.get("/resolve", url=self.url) if self.url else None
		spinner.stop()
		if isinstance(data, resource.Resource):
			if data.kind == "user":
				print("User profile found")
				folder = self.validate_name(data.username)
				if not os.path.isdir(folder): os.mkdir(folder)
				os.chdir(os.path.join(os.getcwd(), folder))
				print("Saving in: " + os.getcwd())
				if self.args.all or self.args.likes:
					self.get_liked_tracks()
				if not self.args.likes:
					self.get_uploaded_tracks(data)
			elif data.kind == "track":
					print("Single track found")
					print("Saving in: " + os.getcwd())
					if self.args.similar:
						self.get_recommended_tracks(data)
					self.get_single_track(data)
			elif data.kind == "playlist":
				print("Single playlist found.")
				folder = self.validate_name(data.user["username"])
				if not os.path.isdir(folder):
					os.mkdir(folder)
				os.chdir(os.path.join(os.getcwd(), str(folder)))
				self.get_playlist(data)
		elif isinstance(data, resource.ResourceList):
			if data[0].kind == "playlist":
				print("%d playlists found" % (len(data)))
				for playlist in data:
					self.get_playlist(playlist)
			elif data[0].kind == "track":
				self.get_multiple_tracks(data)
示例#41
0
def remap_key(src, dest):
    """ Remaps src key to dest key.

    An example of remapping the caps lock key to act like the left control key
    would be to call `remap_key('capslock', 'left-ctrl')

    Args:
        src (str): Key name in keyboard dict. This is the key that will change
            functionality.
        dest (str): Key name in keyboard dict. The key defined in `src` should
            act like this key.
    """
    # TODO (phillip): Right now, these changes do not survive a reboot. I am
    # going to just change this manually in the keyboard settings, but I might
    # be able to figure out how to do it with `defaults`.
    # https://apple.stackexchange.com/questions/141069/updating-modifier-keys-from-the-command-line-takes-no-effect
    spinner = Halo(
        text="Remapping {} to {}".format(src, dest),
        spinner="dots",
        placement="right"
    )
    spinner.start()
    remap_dict = {
        'UserKeyMapping': [
            {
                'HIDKeyboardModifierMappingSrc': keyboard[src],
                'HIDKeyboardModifierMappingDst': keyboard[dest]
            }
        ]
    }
    try:
        sh.hidutil("property", "--set", str(remap_dict).replace("'", '"'))
        spinner.succeed()
    except sh.ErrorReturnCode as err:
        err_message = "\n\t" + err.stderr.replace("\n", "\n\t")
        logging.error(
            "Error with `hidutil property --set %s : %s",
            str(remap_dict),
            err_message
        )
        spinner.fail()
示例#42
0
def curl(src, dest):
    """ Installs `src` to path `dest` """
    spinner = Halo(
        text="curl {}".format(dest),
        spinner="dots",
        placement="right"
    )
    spinner.start()
    if os.path.exists(dest):
        spinner.info("{} already exists".format(dest))
        return

    try:
        sh.curl("-fLo", dest, src)
        spinner.succeed()
    except sh.ErrorReturnCode as err:
        err_message = "\n\t" + err.stderr.replace("\n", "\n\t")
        logging.error(
            "Error downloading file `%s`: %s", src, err_message
        )
        spinner.fail()
示例#43
0
def extract(src, dest):
    """ Extracts the source file in dest """
    spinner = Halo(
        text="extract {}".format(src),
        spinner="dots",
        placement="right"
    )
    spinner.start()
    try:
        # TODO (phillip): This should choose the correct decompression based
        # on the filename where possible.
        with tarfile.open(src, "r:gz") as tar:
            tar.extractall(dest)
        sh.rm(src)
        spinner.succeed()
    except sh.ErrorReturnCode as err:
        err_message = "\n\t" + err.stderr.replace("\n", "\n\t")
        logging.error(
            "Error extracting file `%s`: %s", src, err_message
        )
        spinner.fail()
示例#44
0
def font(name):
    """ Installs fonts using curl.

    Args:
        name (str): The name of the font as defined in `font_library` dictionary.
    """
    spinner = Halo(
        text="Font {}".format(name),
        spinner="dots",
        placement="right"
    )
    spinner.start()
    try:
        library = os.path.join(HOME, "Library/Fonts")
        path = os.path.join(library, name)
        sh.curl("-fLo", path, font_library[name])
        spinner.succeed()
    except sh.ErrorReturnCode as err:
        err_message = "\n\t" + err.stderr.replace("\n", "\n\t")
        logging.error(
            "Error installing font `%s`: %s", name, err_message
        )
        spinner.fail()
示例#45
0
def install_homebrew():
    """ Installs or upgrades homebrew on mac.

    If homebrew is not installed, this command will install it, otherwise
    it will update homebrew to the latest version. Additionally, it will
    offer to upgrade all homebrew packages. Upgrading all packages can take
    a long time, so the user is given the choice to skip the upgrade.
    """
    print("Checking homebrew install")
    if sh.which("brew"):
        spinner = Halo(
            text="Updating homebrew", spinner="dots", placement="right"
        )
        spinner.start()
        sh.brew("update")
        spinner.succeed()
        print(
            "Before using homebrew to install packages, we can upgrade "
            "any outdated packages."
        )
        response = user_input("Run brew upgrade? [y|N] ")
        if response[0].lower() == "y":
            spinner = Halo(
                text="Upgrade brew packages", spinner="dots", placement="right"
            )
            spinner.start()
            sh.brew("upgrade")
            spinner.succeed()
        else:
            print("Skipped brew package upgrades")
    else:
        # TODO (phillip): Currently, this homebrew installation does not work on a fresh
        # computer. It works from the command line, but not when run from the script. I
        # need to figure out what is going on. It could be because user input is needed.
        spinner = Halo(
            text="Installing homebrew", spinner="dots", placement="right"
        )
        spinner.start()
        try:
            script = sh.curl("-fsSL", BREW_GITHUB).stdout
            sh.ruby("-e", script)
            spinner.succeed()
        except sh.ErrorReturnCode:
            logging.error("Unable to install homebrew. Aborting...")
            spinner.fail()
            exit(1)
示例#46
0
import time
from halo import Halo

spinner = Halo(text="Loading")
spinner.start()

time.sleep(2)

spinner.stop()
示例#47
0
def file(path, template_file, load_vars=lambda: {}):
    """ Installs a template file using symlinks.

    If a file already exists at the specified path and it is not a symbolic
    link, then this function will print an error and return. If the file is
    a symlink to the `build` directory of your dotfiles repo, then this will
    check to see if the template has been modified since the file was last
    built.

    Args:
        path (str): Filesystem path where we should install the filled out
            template file.
        template_file (str): The filename of the template to install. The
            file should be located in the $ROOT/templates directory of this
            repository.
        load_vars (func): A function that will be run when the file is built to
            fill in template information. This is passed in as a function so
            that user input is only asked for when the file is built.
    """
    spinner = Halo(text=path, spinner="dots", placement="right")
    spinner.start()
    if os.path.exists(path) and not os.path.islink(path):
        print("Error: {} exists and is not a soft link".format(path))
        spinner.fail()
        return

    try:
        # Load template as a Jinja2 Template
        template_path = os.path.join(
            ROOT, os.path.join("templates", template_file)
        )
        template_mtime = os.path.getmtime(template_path)
        with open(template_path, "r") as template_file:
            template = Template(template_file.read())

        build_path = os.path.join(
            ROOT, os.path.join("build", os.path.basename(path))
        )
        if not os.path.exists(build_path):
            build_mtime = 0
        else:
            build_mtime = os.path.getmtime(build_path)

        # Build the template if the template has been modified since last build
        if template_mtime > build_mtime:
            # TODO (plemons): I should only do this if I actually need user
            # input. Theoretically, the load_vars function could just read
            # from a config file making this unnecessary
            spinner.info("Asking for user input for {}".format(path))
            if not os.path.exists(os.path.dirname(build_path)):
                os.makedirs(os.path.dirname(build_path))
            with open(build_path, 'w') as outfile:
                outfile.write(template.render(**load_vars()))

        path = os.path.expanduser(path)
        dirpath = os.path.dirname(path)
        if not os.path.exists(dirpath):
            os.makedirs(dirpath)
        if os.path.islink(path):
            os.unlink(path)
        os.symlink(build_path, path)
        spinner.succeed()
    except OSError as err:
        print(err)
        spinner.fail()
示例#48
0
class Installer:

    CURSE_URL = 'https://wow.curseforge.com'
    ALT_CURSE_URL = 'https://www.curseforge.com'
    ALT_REGEX = re.compile(r'class="download__link" href="(?P<path>.+)"')

    def __init__(self, conf='conf.json', peggle=False):
        with open(conf, 'r') as f:
            config = json.loads(f.read())
        self.addons_path = Path(config['addons_path'])
        self.addons = config['addons']
        self.peggle = peggle
        self.session = None

        # Runtime
        self.loader = None
        self._done = []
        self._failed = []

    def done(self, addon, error=None):
        if error is not None:
            self._failed.append((addon, error))
        else:
            self._done.append(addon)
        errors = f', {len(self._failed)} errors' if self._failed else ''
        self.loader.text = f'Installing addons... ({len(self._done) + len(self._failed)}/{len(self.addons)}{errors})'

    async def _alt_install_addon(self, addon):
        """
        Retry on standard Curse website.
        """
        url = f'{self.ALT_CURSE_URL}/wow/addons/{addon}/download'
        async with self.session.get(url) as response:
            if response.status != 200:
                self.done(addon, 'not found')
                return
            match = self.ALT_REGEX.search(await response.text())

        if not match:
            self.done(addon, 'regex error /!\\')
            return

        url = f"{self.ALT_CURSE_URL}{match.group('path')}"
        async with self.session.get(url) as response:
            if response.status != 200:
                self.done(addon, 'not found')
                return
            zip_data = await response.read()

        z = zipfile.ZipFile(BytesIO(zip_data))
        z.extractall(self.addons_path)
        self.done(addon)

    async def _install_addon(self, addon):
        """
        Install from new Curse project website.
        """
        url = f'{self.CURSE_URL}/projects/{addon}/files/latest'
        async with self.session.get(url) as response:
            if response.status != 200:
                await self._alt_install_addon(addon)
                return
            zip_data = await response.read()

        z = zipfile.ZipFile(BytesIO(zip_data))
        z.extractall(self.addons_path)
        self.done(addon)

    async def _install_peggle(self):
        """
        Custom installation of the addon 'Peggle'.
        See https://github.com/adamz01h/wow_peggle
        """
        url = 'https://github.com/adamz01h/wow_peggle/archive/master.zip'
        async with self.session.get(url) as response:
            if response.status != 200:
                self.done('Peggle', 'could not retrieve archive from github')
                return
            zip_data = await response.read()

        tmp_path = Path('/tmp/peggle')
        z = zipfile.ZipFile(BytesIO(zip_data))
        z.extractall(tmp_path)
        shutil.move(
            tmp_path / 'wow_peggle-master/Peggle',
            self.addons_path / 'Peggle',
        )
        self.done('Peggle')

    async def install(self):
        tasks = [self._install_addon(addon) for addon in self.addons]
        if self.peggle is True:
            tasks.append(self._install_peggle())
            self.addons.append('Peggle')

        self.loader = Halo(f'Installing addons... (0/{len(tasks)})')
        self.loader.start()

        async with ClientSession() as self.session:
            await asyncio.gather(*tasks)

        self.loader.stop()

        for addon, error in self._failed:
            print(f"Failed to install: '{addon}' ({error})")
        for addon in self._done:
            print(f"Successfully installed: '{addon}'")