From: Orakaro Date: Sun, 3 Aug 2014 14:04:49 +0000 (+0900) Subject: Process to Thread, Goodbye SQLAlchemy X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=99b52f5fc1557f18f7d6593ccfa36f130139b4b7;p=rainbowstream.git Process to Thread, Goodbye SQLAlchemy --- diff --git a/docs/conf.py b/docs/conf.py index 061ff74..7b5ea21 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -12,9 +12,6 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys -import os - # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. @@ -51,9 +48,9 @@ copyright = u'2014, Vu Nhat Minh' # built documents. # # The short X.Y version. -version = '0.5.9' +version = '0.6.0' # The full version, including alpha/beta/rc tags. -release = '0.5.9' +release = '0.6.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/rainbowstream/db.py b/rainbowstream/db.py deleted file mode 100644 index e9f2ccc..0000000 --- a/rainbowstream/db.py +++ /dev/null @@ -1,155 +0,0 @@ -import os -from sqlalchemy import create_engine -from sqlalchemy.orm import sessionmaker -from sqlalchemy.pool import StaticPool -from .table_def import * - - -class RainbowDB(): - - engine = None - - def __init__(self): - """ - Init DB - """ - if os.path.isfile('rainbow.db'): - os.system('rm -rf rainbow.db') - init_db() - self.engine = create_engine('sqlite:///rainbow.db', echo=False, connect_args={'check_same_thread':False}, poolclass=StaticPool) - - def tweet_store(self, tweet_id): - """ - Store tweet id - """ - Session = sessionmaker(bind=self.engine) - session = Session() - t = Tweet(tweet_id) - session.add(t) - session.commit() - - def rainbow_to_tweet_query(self, rid): - """ - Query base of rainbow id - """ - Session = sessionmaker(bind=self.engine) - session = Session() - res = session.query(Tweet).filter_by(rainbow_id=rid).all() - return res - - def tweet_to_rainbow_query(self, tid): - """ - Query base of tweet id - """ - Session = sessionmaker(bind=self.engine) - session = Session() - res = session.query(Tweet).filter_by(tweet_id=tid).all() - return res - - def message_store(self, message_id): - """ - Store message id - """ - Session = sessionmaker(bind=self.engine) - session = Session() - m = Message(message_id) - session.add(m) - session.commit() - - def rainbow_to_message_query(self, rid): - """ - Query base of rainbow id - """ - Session = sessionmaker(bind=self.engine) - session = Session() - res = session.query(Message).filter_by(rainbow_id=rid).all() - return res - - def message_to_rainbow_query(self, mid): - """ - Query base of message id - """ - Session = sessionmaker(bind=self.engine) - session = Session() - res = session.query(Message).filter_by(message_id=mid).all() - return res - - def theme_store(self, theme_name): - """ - Store theme - """ - Session = sessionmaker(bind=self.engine) - session = Session() - th = Theme(theme_name) - session.add(th) - session.commit() - - def theme_update(self, theme_name): - """ - Update theme - """ - Session = sessionmaker(bind=self.engine) - session = Session() - res = session.query(Theme).all() - for r in res: - r.theme_name = theme_name - session.commit() - - def theme_query(self): - """ - Query theme - """ - Session = sessionmaker(bind=self.engine) - session = Session() - res = session.query(Theme).all() - return res - - def semaphore_store(self, lock, pause): - """ - Store semaphore lock - """ - Session = sessionmaker(bind=self.engine) - session = Session() - th = Semaphore(lock, pause) - session.add(th) - session.commit() - - def semaphore_update_lock(self, lock): - """ - Update semaphore lock - """ - Session = sessionmaker(bind=self.engine) - session = Session() - res = session.query(Semaphore).all() - for r in res: - r.lock = lock - session.commit() - - def semaphore_update_pause(self, pause): - """ - Update semaphore pause - """ - Session = sessionmaker(bind=self.engine) - session = Session() - res = session.query(Semaphore).all() - for r in res: - r.pause = pause - session.commit() - - def semaphore_query_lock(self): - """ - Query semaphore lock - """ - Session = sessionmaker(bind=self.engine) - session = Session() - res = session.query(Semaphore).all() - return res[0].lock - - def semaphore_query_pause(self): - """ - Query semaphore pause - """ - Session = sessionmaker(bind=self.engine) - session = Session() - res = session.query(Semaphore).all() - return res[0].pause diff --git a/rainbowstream/draw.py b/rainbowstream/draw.py index 78c3a26..d9afe06 100644 --- a/rainbowstream/draw.py +++ b/rainbowstream/draw.py @@ -12,12 +12,10 @@ from dateutil import parser from .c_image import * from .colors import * from .config import * -from .db import * from .py3patch import * - -db = RainbowDB() -g = {} +# Draw global variables +dg = {} def init_cycle(): @@ -35,8 +33,8 @@ def start_cycle(): """ Notify from rainbow """ - g['cyc'] = init_cycle() - g['cache'] = {} + dg['cyc'] = init_cycle() + dg['cache'] = {} def order_rainbow(s): @@ -69,9 +67,9 @@ def Memoize(func): """ @wraps(func) def wrapper(*args): - if args not in g['cache']: - g['cache'][args] = func(*args) - return g['cache'][args] + if args not in dg['cache']: + dg['cache'][args] = func(*args) + return dg['cache'][args] return wrapper @@ -80,7 +78,7 @@ def cycle_color(s): """ Cycle the colors_shuffle """ - return next(g['cyc'])(s) + return next(dg['cyc'])(s) def ascii_art(text): @@ -89,7 +87,7 @@ def ascii_art(text): """ fi = figlet_format(text, font='doom') print('\n'.join( - [next(g['cyc'])(i) for i in fi.split('\n')] + [next(dg['cyc'])(i) for i in fi.split('\n')] )) @@ -117,24 +115,23 @@ def validate_theme(theme): return theme in themes -def reload_theme(current_config): +def reload_theme(value, prev): """ Check current theme and update if necessary """ - exists = db.theme_query() - themes = [t.theme_name for t in exists] - if current_config != themes[0]: + if value != prev: config = os.path.dirname( - __file__) + '/colorset/' + current_config + '.json' + __file__) + '/colorset/' + value + '.json' # Load new config data = load_config(config) if data: for d in data: c[d] = data[d] - # Restart color cycle and update db/config + # Restart color cycle and update config start_cycle() - db.theme_update(current_config) - set_config('THEME', current_config) + set_config('THEME', value) + return value + return prev def color_func(func_name): @@ -151,16 +148,15 @@ def draw(t, keyword=None, check_semaphore=False, fil=[], ig=[]): Draw the rainbow """ - # Check the semaphore lock (stream process only) + # Check the semaphore pause and lock (stream process only) if check_semaphore: - if db.semaphore_query_pause(): + if c['pause']: return - while db.semaphore_query_lock(): + while c['lock']: time.sleep(0.5) - # Check config and theme + # Check config check_config() - reload_theme(c['THEME']) # Retrieve tweet tid = t['id'] @@ -217,11 +213,11 @@ def draw(t, keyword=None, check_semaphore=False, fil=[], ig=[]): return # Get rainbow id - res = db.tweet_to_rainbow_query(tid) - if not res: - db.tweet_store(tid) - res = db.tweet_to_rainbow_query(tid) - rid = res[0].rainbow_id + if tid not in c['tweet_dict']: + c['tweet_dict'].append(tid) + rid = len(c['tweet_dict']) - 1 + else: + rid = c['tweet_dict'].index(tid) # Format info name = cycle_color(name) @@ -309,11 +305,11 @@ def print_message(m, check_semaphore=False): Print direct message """ - # Check the semaphore lock (stream process only) + # Check the semaphore pause and lock (stream process only) if check_semaphore: - if db.semaphore_query_pause(): + if c['pause']: return - while db.semaphore_query_lock(): + while c['lock']: time.sleep(0.5) # Retrieve message @@ -333,11 +329,11 @@ def print_message(m, check_semaphore=False): clock = date.strftime(clock_format) # Get rainbow id - res = db.message_to_rainbow_query(mid) - if not res: - db.message_store(mid) - res = db.message_to_rainbow_query(mid) - rid = res[0].rainbow_id + if mid not in c['message_dict']: + c['message_dict'].append(mid) + rid = len(c['message_dict']) - 1 + else: + rid = c['message_dict'].index(mid) # Draw sender_name = cycle_color(sender_name) @@ -479,22 +475,22 @@ def print_list(group): """ Display a list """ - for g in group: + for grp in group: # Format - name = g['full_name'] + name = grp['full_name'] name = color_func(c['GROUP']['name'])(name + ' : ') - member = str(g['member_count']) + member = str(grp['member_count']) member = color_func(c['GROUP']['member'])(member + ' member') - subscriber = str(g['subscriber_count']) + subscriber = str(grp['subscriber_count']) subscriber = color_func( c['GROUP']['subscriber'])( subscriber + ' subscriber') - description = g['description'].strip() + description = grp['description'].strip() description = color_func(c['GROUP']['description'])(description) - mode = g['mode'] + mode = grp['mode'] mode = color_func(c['GROUP']['mode'])('Type: ' + mode) - created_at = g['created_at'] + created_at = grp['created_at'] date = parser.parse(created_at) date = date - datetime.timedelta(seconds=time.timezone) clock = date.strftime('%Y/%m/%d %H:%M:%S') diff --git a/rainbowstream/rainbow.py b/rainbowstream/rainbow.py index 0a02ea2..6077347 100644 --- a/rainbowstream/rainbow.py +++ b/rainbowstream/rainbow.py @@ -1,8 +1,6 @@ """ Colorful user's timeline stream """ -from multiprocessing import Process - import os import os.path import sys @@ -24,18 +22,13 @@ from .colors import * from .config import * from .consumer import * from .interactive import * -from .db import * from .c_image import * from .py3patch import * # Global values g = {} -# Database -db = RainbowDB() - # Lock for streams - StreamLock = threading.Lock() # Commands @@ -164,9 +157,13 @@ def init(args): files = os.listdir(os.path.dirname(__file__) + '/colorset') themes = [f.split('.')[0] for f in files if f.split('.')[-1] == 'json'] g['themes'] = themes - db.theme_store(c['THEME']) + g['prev_theme'] = c['THEME'] # Semaphore init - db.semaphore_store(False, False) + c['lock'] = False + c['pause'] = False + # Init tweet dict and message dict + c['tweet_dict'] = [] + c['message_dict'] = [] # Image on term c['IMAGE_ON_TERM'] = args.image_on_term @@ -321,7 +318,7 @@ def retweet(): except: printNicely(red('Sorry I can\'t understand.')) return - tid = db.rainbow_to_tweet_query(id)[0].tweet_id + tid = c['tweet_dict'][id] t.statuses.retweet(id=tid, include_entities=False, trim_user=True) @@ -335,7 +332,7 @@ def quote(): except: printNicely(red('Sorry I can\'t understand.')) return - tid = db.rainbow_to_tweet_query(id)[0].tweet_id + tid = c['tweet_dict'][id] tweet = t.statuses.show(id=tid) screen_name = tweet['user']['screen_name'] text = tweet['text'] @@ -363,7 +360,7 @@ def allretweet(): except: printNicely(red('Sorry I can\'t understand.')) return - tid = db.rainbow_to_tweet_query(id)[0].tweet_id + tid = c['tweet_dict'][id] # Get display num if exist try: num = int(g['stuff'].split()[1]) @@ -389,7 +386,7 @@ def favorite(): except: printNicely(red('Sorry I can\'t understand.')) return - tid = db.rainbow_to_tweet_query(id)[0].tweet_id + tid = c['tweet_dict'][id] t.favorites.create(_id=tid, include_entities=False) printNicely(green('Favorited.')) draw(t.statuses.show(id=tid)) @@ -406,7 +403,7 @@ def reply(): except: printNicely(red('Sorry I can\'t understand.')) return - tid = db.rainbow_to_tweet_query(id)[0].tweet_id + tid = c['tweet_dict'][id] user = t.statuses.show(id=tid)['user']['screen_name'] status = ' '.join(g['stuff'].split()[1:]) status = '@' + user + ' ' + status.decode('utf-8') @@ -419,11 +416,11 @@ def delete(): """ t = Twitter(auth=authen()) try: - rid = int(g['stuff'].split()[0]) + id = int(g['stuff'].split()[0]) except: printNicely(red('Sorry I can\'t understand.')) return - tid = db.rainbow_to_tweet_query(rid)[0].tweet_id + tid = c['tweet_dict'][id] t.statuses.destroy(id=tid) printNicely(green('Okay it\'s gone.')) @@ -438,7 +435,7 @@ def unfavorite(): except: printNicely(red('Sorry I can\'t understand.')) return - tid = db.rainbow_to_tweet_query(id)[0].tweet_id + tid = c['tweet_dict'][id] t.favorites.destroy(_id=tid) printNicely(green('Okay it\'s unfavorited.')) draw(t.statuses.show(id=tid)) @@ -492,7 +489,7 @@ def show(): if target != 'image': return id = int(g['stuff'].split()[1]) - tid = db.rainbow_to_tweet_query(id)[0].tweet_id + tid = c['tweet_dict'][id] tweet = t.statuses.show(id=tid) media = tweet['entities']['media'] for m in media: @@ -511,7 +508,7 @@ def urlopen(): try: if not g['stuff'].isdigit(): return - tid = db.rainbow_to_tweet_query(g['stuff'])[0].tweet_id + tid = c['tweet_dict'][g['stuff']] tweet = t.statuses.show(id=tid) link_ary = [ u for u in tweet['text'].split() if u.startswith('http://')] @@ -639,10 +636,10 @@ def trash(): """ t = Twitter(auth=authen()) try: - rid = int(g['stuff'].split()[0]) + id = int(g['stuff'].split()[0]) except: printNicely(red('Sorry I can\'t understand.')) - mid = db.rainbow_to_message_query(rid)[0].message_id + mid = c['message_dict'][id] t.direct_messages.destroy(id=mid) printNicely(green('Message deleted.')) @@ -1140,7 +1137,7 @@ def config(): set_config(key, value) # Apply theme immediately if key == 'THEME': - reload_theme(value) + c['THEME'] = reload_theme(value,c['THEME']) g['decorated_name'] = lambda x: color_func( c['DECORATED_NAME'])( '[' + x + ']: ') @@ -1170,13 +1167,14 @@ def theme(): # Change theme try: # Load new theme - reload_theme(g['stuff']) + c['THEME'] = reload_theme(g['stuff'],c['THEME']) # Redefine decorated_name g['decorated_name'] = lambda x: color_func( c['DECORATED_NAME'])( '[' + x + ']: ') printNicely(green('Theme changed.')) - except: + except Exception as e: + print e printNicely(red('No such theme exists.')) @@ -1444,7 +1442,7 @@ def pause(): """ Pause stream display """ - db.semaphore_update_pause(True) + c['pause'] = True printNicely(green('Stream is paused')) @@ -1452,7 +1450,7 @@ def replay(): """ Replay stream """ - db.semaphore_update_pause(False) + c['pause'] = False printNicely(green('Stream is running back now')) @@ -1469,7 +1467,6 @@ def quit(): """ try: save_history() - os.system('rm -rf rainbow.db') printNicely(green('See you next time :)')) except: pass @@ -1610,6 +1607,8 @@ def listen(): read_history() reset() while True: + # Prompt redraw is needed when user is typing + # raw_input if g['prefix']: line = raw_input(g['decorated_name'](c['PREFIX'])) else: @@ -1619,20 +1618,21 @@ def listen(): except: cmd = '' g['cmd'] = cmd + # Prompt redraw not need when raw_input done try: # Lock the semaphore - db.semaphore_update_lock(True) + c['lock'] = True # Save cmd to global variable and call process g['stuff'] = ' '.join(line.split()[1:]) # Process the command process(cmd)() # Not re-display - if cmd in ['t', 'rt', 'rep']: + if cmd in ['switch', 't', 'rt', 'rep']: g['prefix'] = False else: g['prefix'] = True # Release the semaphore lock - db.semaphore_update_lock(False) + c['lock'] = False except Exception: printNicely(red('OMG something is wrong with Twitter right now.')) @@ -1677,7 +1677,7 @@ def stream(domain, args, name='Rainbow Stream'): StreamLock.acquire() g['stream_stop'] = False for tweet in tweet_iter: - if(g['stream_stop'] == True): + if(g['stream_stop']): StreamLock.release() break if tweet is None: @@ -1696,8 +1696,6 @@ def stream(domain, args, name='Rainbow Stream'): fil=args.filter, ig=args.ignore, ) - sys.stdout.write(g['decorated_name'](c['PREFIX']) + readline.get_line_buffer()) - sys.stdout.flush() elif tweet.get('direct_message'): print_message(tweet['direct_message'], check_semaphore=True) except TwitterHTTPError: @@ -1720,7 +1718,6 @@ def fly(): magenta("We have maximum connection problem with twitter'stream API right now :(")) printNicely(magenta("Let's try again later.")) save_history() - os.system('rm -rf rainbow.db') sys.exit() # Spawn stream thread th = threading.Thread(target=stream, args=(c['USER_DOMAIN'], args, g['original_name'])) diff --git a/rainbowstream/table_def.py b/rainbowstream/table_def.py deleted file mode 100644 index 03ceb5a..0000000 --- a/rainbowstream/table_def.py +++ /dev/null @@ -1,55 +0,0 @@ -from sqlalchemy import * -from sqlalchemy.ext.declarative import declarative_base - -engine = create_engine('sqlite:///rainbow.db', echo=False) -Base = declarative_base() - - -class Tweet(Base): - - __tablename__ = "tweet" - - rainbow_id = Column(Integer, primary_key=True) - tweet_id = Column(Integer) - - def __init__(self, tweet_id): - self.tweet_id = tweet_id - - -class Message(Base): - - __tablename__ = "message" - - rainbow_id = Column(Integer, primary_key=True) - message_id = Column(Integer) - - def __init__(self, message_id): - self.message_id = message_id - - -class Theme(Base): - - __tablename__ = "theme" - - theme_id = Column(Integer, primary_key=True) - theme_name = Column(String(20)) - - def __init__(self, theme_name): - self.theme_name = theme_name - - -class Semaphore(Base): - - __tablename__ = "semaphore" - - semaphore_id = Column(Integer, primary_key=True) - lock = Column(Boolean) - pause = Column(Boolean) - - def __init__(self, lock, pause): - self.lock = lock - self.pause = pause - - -def init_db(): - Base.metadata.create_all(engine) diff --git a/setup.py b/setup.py index 64e50e0..9e5b65e 100644 --- a/setup.py +++ b/setup.py @@ -4,14 +4,13 @@ import os.path import sys # Bumped version -version = '0.5.9' +version = '0.6.0' # Require install_requires = [ "python-dateutil", "requests", "pyfiglet", - "SQLAlchemy", "twitter", "Pillow", ]