def display_list_of_questions(questions): print() num = 1 for q in questions: creation_date = (datetime.utcfromtimestamp(q["creation_date"]) + timedelta(hours=load_config()["timezone"]) ).strftime('%Y-%m-%d %H:%M:%S') if q.get("human_datetime", False): date_to_display = q["human_datetime"] else: date_to_display = creation_date new_flag_ui = "" if q["new_flag"]: new_flag_ui = "[new] " print( fg256("yellow", num) + ": " + fg256("lightcoral", new_flag_ui) + fg256("lightgreen", q["title"])) print( fg256( "lightyellow", " {}, {}, score {}, answer_count {}".format( q["tags"], date_to_display, q["score"], q["answer_count"]))) if SHOW_LINK_TO_QUESTION: print(fg256("grey", " {}".format(q["link"]))) print() num = num + 1
def show_step3_features(): ''' Show the selected features ''' (url_mention, TM, E, cat_folds, cat2url, performance_aggregator, DF) = setup() for cat_idx, (cat, folds) in enumerate(cat_folds.items()): train_idx, test_idx = folds[0] S = get(cat2url[cat], train_idx) clue_obj = TextualClueObject(S, url_mention, TM) tmo = clue_obj.tmo features = clue_obj.features c = defaultdict(int) for e, feat in features.iteritems(): feat, bad_idx = remove_unigrams(feat, tmo, df_lim=args.df_lim, df_obj=DF) feat = remove_bigrams(feat, bad_idx) for f in feat: c[f] += 1 # if e[1] > len(features) * 2.0 / 4.0 common_feat = sorted(c.iteritems(), key=lambda x: x[1], reverse=True)[:20] total = float(len(S)) if len(common_feat) == 0: print 'Diverse:', '%-35s' % cat[:35], fg256('red', '|||'), else: print 'Common: ', '%-35s' % cat[:35], fg256('red', '|||'), for e in common_feat: print fg256(color((1 - e[1] / total) / 1.2), tmo[[e[0]]][0]), print import pdb pdb.set_trace()
def insert_colour(matchstring: str, regex: RETYPE, extra_str=None) -> str: """ Given some string and a regex, color the match inside that string :param matchstring: :param regex: :param extra_str: :return: """ if extra_str is None: replace_str = str(color.fg256("yellow", r"\g<0>")) else: replace_str = str(color.fg256("yellow", r"(\g<0> -> {})".format(extra_str))) return re.sub("^[ \t]+", "", re.sub(regex, replace_str, matchstring))
def insert_colour(matchstring: str, regex: RETYPE, extra_str=None) -> str: """ Given some string and a regex, color the match inside that string :param matchstring: :param regex: :param extra_str: :return: """ if extra_str is None: replace_str = str(color.fg256("yellow", r"\g<0>")) else: replace_str = str( color.fg256("yellow", r"(\g<0> -> {})".format(extra_str))) return re.sub("^[ \t]+", "", re.sub(regex, replace_str, matchstring))
def color(c, x): "Colorize numbers in [0,1] based on value; darker means smaller value." a, b = 238, 255 # 232, 255 w = b - a offset = x * w offset = int(round(offset)) return str(fg256(a + offset, c)).encode('utf8')
def delete_questions(params=None): if len(params) == 0: #store.Connection().set_list_of_questions_for_tag( # ActiveSession().last_used_tag, # ActiveSession().remain_questions() #) # TODO: optimize for question in ActiveSession().active_questions: relation_store.delete_question(relation_store.Connection(), question) print(fg256("grey", "delete by {} (remain={})".format(ActiveSession().last_used_tag, len(ActiveSession().remain_questions())))) print() else: if helpers.represents_int(params[1:]): tag_num = int(params[1:]) for tag_dict in ActiveSession().current_tags: if tag_dict["num"] == tag_num: relation_store.delete_questions_by_category(relation_store.Connection(), tag_dict["tag"]) # store.Connection().remove_questions_for_tag(tag_dict["tag"]) else: #store.Connection().remove_by_tag(params[1:]) relation_store.delete_questions_by_category(relation_store.Connection(), params[1:]) print()
def color(c, x): "Colorize numbers in [0,1] based on value; darker means smaller value." a, b = 238, 255 # 232, 255 w = b - a offset = x*w offset = int(round(offset)) return str(fg256(a + offset, c)).encode('utf8')
def say_hello(): print() print("Welcome to Stackify") print( fg256( "grey", " f - fetch, ls - list, s[ tag/num] - show, d - delete, del - delete last seen" ))
def color01(x, fmt='%.10f'): "Colorize numbers in [0,1] based on value; darker means smaller value." if not (0 <= x <= 1 + 1e-10): return red % fmt % x a, b = 238, 255 # 232, 255 w = b - a offset = x * w offset = int(round(offset)) return color.fg256(a + offset, fmt % x)
def color01(x, fmt='%.10f'): "Colorize numbers in [0,1] based on value; darker means smaller value." if not (0 <= x <= 1 + 1e-10): return red % fmt % x a, b = 238, 255 # 232, 255 w = b - a offset = x*w offset = int(round(offset)) return color.fg256(a + offset, fmt % x)
def ls(data_to_display): print() for element in data_to_display: color = "lightgreen" if not element["hidden"] else "red" print( fg256( color, "{}: {} ({} / {})".format(element["num"], element["tag"], element["new_count"], element["count"])))
def plot(x, y, distribution, function, color): term_x, term_y = get_terminal_size() s = script(distribution, function) for i, j in zip(x, y): s += '%f %f\n' % (i, j) master, slave = pty.openpty() gnuplot = subprocess.Popen( ["gnuplot", "-p"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) output = gnuplot.communicate(bytes(s, 'utf-8'))[0] plot_color = bytes(str(fg256(color, '*')), 'utf-8') with_color = output.replace( b'*', plot_color, ) sys.stdout.buffer.write(with_color)
def fetch(from_time: int, sites: List[str] = None) -> List: print() print("fetching data...") now = int(time.time()) result = [] sites = SITES if sites is None else [] total_pages = 0 quota_remain = 0 for site in sites: questions, pages, quota = _fetch_one_site(site=site, from_time=from_time) result = result + questions total_pages += pages quota_remain = quota print( fg256( "grey", "synced pages = {}; remain_quota = {})".format( total_pages, quota_remain))) config.set_value("last-sync", now) return result
def print_worker( start_time: float, worker_count: int, output: mp.Queue, final_queue: mp.Queue, pipemode: bool, editmode: bool, ) -> None: file_count = 0 found_count = 0 exit_count = 0 line_count = 0 file_list = [] while True: statement = output.get() if statement[0] == "EXIT": exit_count += 1 line_count += statement[1] file_count += statement[2] found_count += statement[3] if exit_count == worker_count: break else: if len(statement) == 4: filename, linenum, matched, line = statement replace = None else: filename, linenum, matched, line, replace = statement final_queue.put(filename, linenum) if pipemode: print("{} {} {}".format(filename, linenum, matched)) else: print("{}:{}\n\t{}".format( filename, color.fg256("#00ff00", linenum), insert_colour(matched, line, extra_str=replace), )) file_list.append((statement[1], statement[0])) final_queue.put("EXIT") if not pipemode: print(("---------------\n" "Files Searched: {:,}\n" "Files Matched: {:,}\n" "Lines Searched: {:,}\n" "Duration: {:.3f}").format(file_count, found_count, line_count, time.time() - start_time)) if editmode: files_to_edit = ["+{} {}".format(num, name) for num, name in file_list] call_args = [_ for _ in files_to_edit[0].split(" ")] orientation = 0 for f in files_to_edit[1:]: call_args.append('+"{} {}"'.format("sp" if orientation else "vsp", f)) orientation ^= 1 if len(call_args) > 10: print( color.red( "Cowardly only accepting the first 10 files for editing")) call_string = "{} {}".format(EDITOR, " ".join(call_args[:10])) subprocess.call(call_string, shell=True)
class CliFormatter(string.Formatter): """ Extends string.Formatter to provide some bells and whistles: Tabular Data - `{foo:table}`: tabular_data = [('foo-header', 'bar-header'), ('row1, col1', 'row1, col2)'] # and so on... formatter.format('Here is a table\n{totally_tabular:table}', totally_tabular=tabular_data) ANSI Style Markup - `{foo:bold}`: formatter.format('{good:256_bright_green}, {bad:256_bright_red}', good="Awesome!", bad="Oh no!") Format raw text without an explicit value: formatter.format('{Awesome!:256_bright_green}, {Oh no!:256_bright_red}') # normally would raise a KeyError Auto de-dent - dedent=True (default): multiline_string = ''' Normally this would be printed with the leading/trailing \\n and spaces. You could call textwrap.dedent() on the resulting string but the formatter handles it for you. ''' formatter.format('No indention:\n{}', multiline_string) # dedent=true by default formatter.format('Indention:\n{}', multiline_string, dedent=False) """ STYLES = { 'bold': lambda text: color.bold(text), 'italic': lambda text: color.italic(text), 'strike': lambda text: color.strike(text), 'underline': lambda text: color.underline(text), '256_bright_green': lambda text: color.bold(color.fg256('#00FF00', text)), '256_green': lambda text: color.bold(color.fg256('#00FF00', text)), '256_light_green': lambda text: color.fg256('#99ff00', text), '256_bright_yellow': lambda text: color.bold(color.fg256('#ffdd00', text)), '256_yellow': lambda text: color.fg256('#ffdd00', text), '256_light_yellow': lambda text: color.fg256('#ffff00', text), '256_bright_red': lambda text: color.bold(color.fg256('#ff0000', text)), '256_red': lambda text: color.bold(color.fg256('#ff0000', text)), '256_light_red': lambda text: color.fg256('#ff5500', text), } def __init__(self): super(CliFormatter, self).__init__() self.indent_level = 0 self.dedent = True def format(self, *args, **kwargs): """ You can use 'dedent' to have the formatter de-indent the final string for you which is nice when you are using heredoc style strings that preserve white space in a multiline string. :param args: :param kwargs: :return: """ if 'dedent' in kwargs: self.dedent = kwargs['dedent'] del kwargs['dedent'] formatted = super(CliFormatter, self).format(*args, **kwargs) if self.dedent: formatted = textwrap.dedent(formatted).strip('\n') self.dedent = True self.indent_level = 0 return formatted def vformat(self, format_string, args, kwargs): """ Need to keep track of the indent level incase we generate new rows of text, e.g. a Table, so the indention level of the generated row matches :param format_string: :param args: :param kwargs: :return: """ if isinstance(format_string, str): self.indent_level = len(format_string) - len(format_string.lstrip()) - 1 return super(CliFormatter, self).vformat(format_string, args, kwargs) def get_value(self, key, args, kwargs): """ Normally a key without a matching value would raise an error, but I want to be able to stylize plain text without having to make a variable and stick it in a map, e.g. formatter.format('{This is a string:bold}') instead of formatter.format('{placehold:bold}', {'placeholder': 'This is a string'}) :param key: :param args: :param kwargs: :return: """ try: return super(CliFormatter, self).get_value(key, args, kwargs) except (IndexError, KeyError) as e: return key def format_field(self, value, format_spec): if format_spec == 'table' or format_spec == 'table_no_header': header = format_spec == 'table' return tabulate(value, first_row_header=header, indent_level=self.indent_level) elif format_spec in CliFormatter.STYLES: stylized = CliFormatter.STYLES[format_spec](value) return str(stylized) else: return super(CliFormatter, self).format_field(value, format_spec)
def colour(max, i): out = "%02d" % i value = i * (len(colours) / max) return str(fg256("#000", bg256(colours[value], out)))
def print_worker( start_time: float, worker_count: int, output: mp.Queue, final_queue: mp.Queue, pipemode: bool, editmode: bool, ) -> None: file_count = 0 found_count = 0 exit_count = 0 line_count = 0 file_list = [] while True: statement = output.get() if statement[0] == "EXIT": exit_count += 1 line_count += statement[1] file_count += statement[2] found_count += statement[3] if exit_count == worker_count: break else: if len(statement) == 4: filename, linenum, matched, line = statement replace = None else: filename, linenum, matched, line, replace = statement final_queue.put(filename, linenum) if pipemode: print("{} {} {}".format(filename, linenum, matched)) else: print( "{}:{}\n\t{}".format( filename, color.fg256("#00ff00", linenum), insert_colour(matched, line, extra_str=replace), ) ) file_list.append((statement[1], statement[0])) final_queue.put("EXIT") if not pipemode: print( ( "---------------\n" "Files Searched: {:,}\n" "Files Matched: {:,}\n" "Lines Searched: {:,}\n" "Duration: {:.3f}" ).format(file_count, found_count, line_count, time.time() - start_time) ) if editmode: files_to_edit = ["+{} {}".format(num, name) for num, name in file_list] call_args = [_ for _ in files_to_edit[0].split(" ")] orientation = 0 for f in files_to_edit[1:]: call_args.append('+"{} {}"'.format("sp" if orientation else "vsp", f)) orientation ^= 1 if len(call_args) > 10: print(color.red("Cowardly only accepting the first 10 files for editing")) call_string = "{} {}".format(EDITOR, " ".join(call_args[:10])) subprocess.call(call_string, shell=True)
def summary_for_new_questions(summary: Dict): print() print(fg256("grey", "found new questions:")) for tag, cnt in summary.items(): print(fg256("grey", " {}: {}".format(tag, cnt)))
import sys import os import config from fabulous.color import green, red, fg256 if sys.argv[1] == "open": os.system("picocom /dev/{} -b 115200".format(config.TTY_HANDLER)) elif sys.argv[1] == "deploy": print( fg256( "#e67e22", """ If it hangs on 'Connected to esp8266': - Be sure you are not connected in other session to TTY. If so, disconnect and try it again! - Otherwise, press CTRL-C, reset the NodeMCU by pressing the button on the board and try it again! """)) with open('uconfig.py', 'w') as f: f.write(f'DWEET_THING = "{config.DWEET_THING}"{os.linesep}') f.write(f'WIFI_SSID = "{config.WIFI_SSID}"{os.linesep}') f.write(f'WIFI_PASSWORD = "******"{os.linesep}') files = ";".join(f"put {file}" for file in config.FILES_TO_DEPLOY) error = os.system("mpfshell -n -c 'open {}; {}'".format( config.TTY_HANDLER, files)) if error: print(red("Deploy failed!")) else: print(green("All files were deployed successfully!!")) else: print("⚠️ Unknown option!")
#!/usr/bin/env python """base16 colour theme requires 256-colour support. """ from fabulous import color as col from themelog.themes.base16 import pal messagefmt = { None: '{asctime} {module} {levelname} {msg}'.format( asctime=col.fg256(pal['base03'], '{r.asctime}'), module=col.fg256(pal['base03.5'], '{r.module}'), levelname=col.fg256(pal['base0C'], '{r.levelname}'), msg=col.fg256(pal['base02'], '{r.msg}'), ), 'INFO': '{asctime} {module} {levelname} {msg}'.format( asctime=col.fg256(pal['base03'], '{r.asctime}'), module=col.fg256(pal['base03.5'], '{r.module}'), levelname=col.fg256(pal['base0B'], '{r.levelname}'), # levelname=col.fg256(pal['base06'], '{r.levelname}'), msg=col.fg256(pal['base02'], '{r.msg}'), ), 'WARNING': '{asctime} {module} {levelname} {msg}'.format( asctime=col.fg256(pal['base03'], '{r.asctime}'), module=col.fg256(pal['base03.5'], '{r.module}'), levelname=col.fg256(pal['base0A'], '{r.levelname}'), msg=col.fg256(pal['base02'], '{r.msg}'), ), 'ERROR': '{asctime} {module} {levelname} {msg}'.format( asctime=col.fg256(pal['base03'], '{r.asctime}'),
def alert_unclassified(questions: List[Dict]): for q in questions: if q["first"] == "none": print(fg256('gray', "{}: {}".format(q["site"], q["tags"])))
pal = { '39m': '#0d1926', '40m': '#161616', '41m': '#a45f1a', '42m': '#1aa45f', '43m': '#5fa41a', '44m': '#5f1aa4', '45m': '#a41a5f', '46m': '#1a5fa4', '47m': '#dfdfdf', } messagefmt = { None: '{asctime} {module} {levelname} {msg}'.format( asctime=col.fg256(pal['44m'], '{r.asctime}'), module=col.fg256(pal['44m'], '{r.module}'), levelname=col.fg256(pal['44m'], '{r.levelname}'), msg=col.fg256(pal['44m'], '{r.msg}'), ), 'INFO': '{asctime} {module} {levelname} {msg}'.format( asctime=col.fg256(pal['43m'], '{r.asctime}'), module=col.fg256(pal['43m'], '{r.module}'), levelname=col.fg256(pal['43m'], '{r.levelname}'), msg=col.fg256(pal['43m'], '{r.msg}'), ), 'WARNING': '{asctime} {module} {levelname} {msg}'.format( asctime=col.fg256(pal['41m'], '{r.asctime}'), module=col.fg256(pal['41m'], '{r.module}'), levelname=col.fg256(pal['41m'], '{r.levelname}'), msg=col.fg256(pal['41m'], '{r.msg}'),