mirror of https://github.com/Yomguithereal/fog.git
Better CLI
This commit is contained in:
parent
28fed6bba2
commit
4ce43bca77
|
@ -6,42 +6,90 @@
|
||||||
# a CSV file.
|
# a CSV file.
|
||||||
#
|
#
|
||||||
import csv
|
import csv
|
||||||
from collections import defaultdict
|
import re
|
||||||
|
from collections import Counter
|
||||||
from fog.cli.ui.cluster import ClusteringUI
|
from datetime import datetime
|
||||||
|
from timeit import default_timer as timer
|
||||||
|
|
||||||
from fog.clustering import (
|
from fog.clustering import (
|
||||||
key_collision
|
key_collision
|
||||||
)
|
)
|
||||||
from fog.key import fingerprint
|
from fog.key import fingerprint
|
||||||
|
|
||||||
|
|
||||||
def fingerprint_collision(data):
|
|
||||||
clusters = key_collision(data, key=fingerprint)
|
|
||||||
|
|
||||||
return list(clusters)
|
|
||||||
|
|
||||||
|
|
||||||
CLUSTERING_ROUTINES = {
|
CLUSTERING_ROUTINES = {
|
||||||
'fingerprint_collision': {
|
'fingerprint_collision': {
|
||||||
'name': 'Fingerpint collision',
|
'name': 'Fingerpint collision',
|
||||||
'fn': fingerprint_collision
|
'fn': key_collision,
|
||||||
|
'args': {
|
||||||
|
'key': fingerprint
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def escape_quote(string):
|
||||||
|
return string.replace('\'', '\\\'')
|
||||||
|
|
||||||
|
|
||||||
|
def print_toml_report(meta, values, clusters):
|
||||||
|
print('[info]')
|
||||||
|
print('date = %s' % meta['date'].isoformat().split('.')[0])
|
||||||
|
print('algorithm = \'%s\'' % meta['algorithm'])
|
||||||
|
print()
|
||||||
|
print('[stats]')
|
||||||
|
print('lines = %i' % meta['lines'])
|
||||||
|
print('nb_distinct_values = %i' % len(values))
|
||||||
|
print('nb_clusters = %i' % len(clusters))
|
||||||
|
print('took = %2f' % meta['took'])
|
||||||
|
print()
|
||||||
|
|
||||||
|
for i, cluster in enumerate(clusters):
|
||||||
|
print('[[cluster]]')
|
||||||
|
print('id = %i' % i)
|
||||||
|
print('nb_values = %i' % len(cluster))
|
||||||
|
|
||||||
|
# Sorting by affected rows
|
||||||
|
sorted_values = sorted(cluster, key=lambda v: values[v], reverse=True)
|
||||||
|
max_length = len(max(cluster, key=len))
|
||||||
|
|
||||||
|
print('harmonized = \'%s\'' % escape_quote(sorted_values[0]))
|
||||||
|
print('values = [')
|
||||||
|
for value in sorted_values:
|
||||||
|
print(' [\'%s\',%s %i],' % (
|
||||||
|
escape_quote(value),
|
||||||
|
' ' * (max_length - len(value)),
|
||||||
|
values[value]
|
||||||
|
))
|
||||||
|
|
||||||
|
print(']')
|
||||||
|
|
||||||
|
print('harmonize = false')
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
def cluster_action(namespace):
|
def cluster_action(namespace):
|
||||||
routine = CLUSTERING_ROUTINES[namespace.algorithm]
|
routine = CLUSTERING_ROUTINES[namespace.algorithm]
|
||||||
|
|
||||||
|
lines = 0
|
||||||
with open(namespace.file, 'r') as f:
|
with open(namespace.file, 'r') as f:
|
||||||
reader = csv.DictReader(f)
|
reader = csv.DictReader(f)
|
||||||
|
|
||||||
rows = defaultdict(list)
|
values = Counter()
|
||||||
|
|
||||||
for line in reader:
|
for line in reader:
|
||||||
rows[line[namespace.column]].append(line)
|
lines += 1
|
||||||
|
values[line[namespace.column]] += 1
|
||||||
|
|
||||||
clusters = routine['fn'](rows.keys())
|
start = timer()
|
||||||
|
clusters = routine['fn'](values.keys(), **routine['args'])
|
||||||
|
end = timer() - start
|
||||||
|
|
||||||
ui = ClusteringUI(rows, clusters)
|
meta = {
|
||||||
ui.run()
|
'algorithm': namespace.algorithm,
|
||||||
|
'took': end,
|
||||||
|
'date': datetime.now(),
|
||||||
|
'lines': lines
|
||||||
|
}
|
||||||
|
|
||||||
|
print_toml_report(meta, values, list(clusters))
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
# =============================================================================
|
|
||||||
# Fog Cluster CLI Action UI
|
|
||||||
# =============================================================================
|
|
||||||
#
|
|
||||||
# Urwid UI for the cluster action.
|
|
||||||
#
|
|
||||||
import signal
|
|
||||||
from urwid import (
|
|
||||||
Columns,
|
|
||||||
ExitMainLoop,
|
|
||||||
Filler,
|
|
||||||
LineBox,
|
|
||||||
ListBox,
|
|
||||||
MainLoop,
|
|
||||||
Padding,
|
|
||||||
SimpleFocusListWalker,
|
|
||||||
Text
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def exit(*args):
|
|
||||||
raise ExitMainLoop()
|
|
||||||
|
|
||||||
|
|
||||||
class ClusteringUI(object):
|
|
||||||
def __init__(self, rows, clusters):
|
|
||||||
|
|
||||||
# Composing the UI
|
|
||||||
body = SimpleFocusListWalker([Text(str(cluster)) for cluster in clusters])
|
|
||||||
clusters_list_box = ListBox(body)
|
|
||||||
|
|
||||||
left_box = Padding(clusters_list_box, left=1, right=1)
|
|
||||||
right_box = Padding(Text('Some other thing'), left=1, right=1)
|
|
||||||
|
|
||||||
left_column = LineBox(left_box, title='Fog Clustering', title_align='left')
|
|
||||||
right_colum = LineBox(Filler(right_box, 'top'), title='Stats', title_align='left')
|
|
||||||
|
|
||||||
columns = Columns([('weight', 0.7, left_column), ('weight', 0.3, right_colum)])
|
|
||||||
|
|
||||||
# Loop
|
|
||||||
self.loop = MainLoop(columns, unhandled_input=self.unhandled_input)
|
|
||||||
|
|
||||||
# Handling signals
|
|
||||||
signal.signal(signal.SIGINT, exit)
|
|
||||||
signal.signal(signal.SIGTERM, exit)
|
|
||||||
|
|
||||||
# Properties
|
|
||||||
self.rows = rows
|
|
||||||
self.clusters = clusters
|
|
||||||
self.current_cluster = 0
|
|
||||||
|
|
||||||
# Activable components
|
|
||||||
self.left_box = left_box
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
self.loop.run()
|
|
||||||
|
|
||||||
def unhandled_input(self, key):
|
|
||||||
if key in ('q', 'Q', 'esc'):
|
|
||||||
raise ExitMainLoop()
|
|
Loading…
Reference in New Issue