Classes refactoring

This commit is contained in:
Marcin Kulik
2012-10-16 00:06:23 +02:00
committed by Marcin Kulik
parent 59e31503da
commit 1dea30c0d7
7 changed files with 184 additions and 159 deletions

View File

@@ -1,155 +1,9 @@
#!/usr/bin/env python #!/usr/bin/env python
import os from cli import CLI
import sys
import getopt
import httplib, urllib
import socket
import glob
import ConfigParser
import uuid
from constants import BASE_DIR, SCRIPT_NAME
from asciicast import AsciiCast
from uploader import Uploader
def check_pending():
num = len(pending_list())
if num > 0:
print 'Warning: %i recorded asciicasts weren\'t uploaded. ' \
'Run "%s upload" to upload them or delete them with "rm -rf %s/*".' \
% (num, SCRIPT_NAME, AsciiCast.QUEUE_DIR)
def upload_pending(api_url):
print 'Uploading pending asciicasts...'
for path in pending_list():
url = Uploader(api_url, path).upload()
if url:
print url
def auth(api_url, user_token):
url = '%s/connect/%s' % (api_url, user_token)
print 'Open following URL in your browser to authenticate and/or claim ' \
'recorded asciicasts:\n\n%s' % url
def pending_list():
return [os.path.dirname(p) for p in glob.glob(AsciiCast.QUEUE_DIR + '/*/*.time')]
def usage():
text = '''usage: %s [-h] [-i] [-y] [-c <command>] [-t <title>] [action]
Asciicast recorder+uploader.
Actions:
rec record asciicast (this is the default when no action given)
upload upload recorded (but not uploaded) asciicasts
auth authenticate and/or claim recorded asciicasts
Optional arguments:
-c command run specified command instead of shell ($SHELL)
-t title specify title of recorded asciicast
-y don't prompt for confirmation
-h, --help show this help message and exit
--version show version information''' % SCRIPT_NAME
print text
def print_version():
print 'asciiio 1.0'
def main(): def main():
'''Parses command-line options and creates asciicast.''' CLI().run()
try:
opts, args = getopt.getopt(sys.argv[1:], 'c:t:ihy', ['help', 'version'])
except getopt.error as msg:
print('%s: %s' % (sys.argv[0], msg))
print('Run "%s --help" for list of available options' % sys.argv[0])
sys.exit(2)
action = 'rec'
if len(args) > 1:
print('Too many arguments')
print('Run "%s --help" for list of available options' % sys.argv[0])
sys.exit(2)
elif len(args) == 1:
action = args[0]
config = ConfigParser.RawConfigParser()
config.add_section('user')
config.add_section('api')
config.add_section('record')
cfg_file = os.path.expanduser('~/.ascii.io/config')
try:
config.read(cfg_file)
except ConfigParser.ParsingError:
print('Config file %s contains syntax errors' % cfg_file)
sys.exit(2)
try:
user_token = config.get('user', 'token')
except ConfigParser.NoOptionError:
user_token = str(uuid.uuid1())
config.set('user', 'token', user_token)
try:
record_input = config.getboolean('record', 'input')
except ConfigParser.NoOptionError:
record_input = False
try:
api_url = config.get('api', 'url')
except ConfigParser.NoOptionError:
api_url = 'http://ascii.io'
if not os.path.isdir(BASE_DIR):
os.mkdir(BASE_DIR)
if not os.path.exists(cfg_file):
with open(cfg_file, 'wb') as configfile:
config.write(configfile)
api_url = os.environ.get('ASCII_IO_API_URL', api_url)
command = None
title = None
always_yes = False
for opt, arg in opts:
if opt in ('-h', '--help'):
usage()
sys.exit(0)
elif opt == '--version':
print_version()
sys.exit(0)
elif opt == '-c':
command = arg.split()
elif opt == '-t':
title = arg
elif opt == '-i':
record_input = True
elif opt == '-y':
always_yes = True
if action == 'rec':
check_pending()
if not AsciiCast(api_url, user_token, command, title, record_input, always_yes).create():
sys.exit(1)
elif action == 'upload':
upload_pending(api_url)
elif action == 'auth':
auth(api_url, user_token)
else:
print('Unknown action: %s' % action)
print('Run "%s --help" for list of available options' % sys.argv[0])
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@@ -5,22 +5,23 @@ import subprocess
import json import json
import shutil import shutil
from constants import SCRIPT_NAME, BASE_DIR from constants import BASE_DIR
from pty_recorder import PtyRecorder from pty_recorder import PtyRecorder
from uploader import Uploader from uploader import Uploader
class AsciiCast(object): class AsciiCast(object):
QUEUE_DIR = BASE_DIR + "/queue" QUEUE_DIR = BASE_DIR + "/queue"
def __init__(self, api_url, user_token, command, title, record_input, always_yes): def __init__(self, config, options):
self.api_url = api_url self.config = config
self.user_token = user_token self.api_url = config.api_url()
self.user_token = config.user_token()
self.path = AsciiCast.QUEUE_DIR + "/%i" % int(time.time()) self.path = AsciiCast.QUEUE_DIR + "/%i" % int(time.time())
self.command = command self.command = options.command
self.title = title self.title = options.title
self.record_input = record_input self.record_input = options.record_input
self.always_yes = options.always_yes
self.duration = None self.duration = None
self.always_yes = always_yes
def create(self): def create(self):
self._record() self._record()
@@ -85,7 +86,7 @@ class AsciiCast(object):
return process.communicate()[0].strip() return process.communicate()[0].strip()
def _upload(self): def _upload(self):
url = Uploader(self.api_url, self.path).upload() url = Uploader(self.config, self.path).upload()
if url: if url:
print url print url
return True return True

66
src/cli.py Normal file
View File

@@ -0,0 +1,66 @@
import os
import sys
import glob
import help_text
from config import Config
from options import Options
from constants import SCRIPT_NAME
from asciicast import AsciiCast
from uploader import Uploader
class CLI:
'''Parses command-line options and xxxxxxxxxxxxxxxxx.'''
def run(self):
self.config = Config()
self.options = Options(sys.argv)
action = self.options.action
if action == 'rec':
self.check_pending()
self.record()
elif action == 'upload':
self.upload_pending()
elif action == 'auth':
self.auth()
elif action == 'help':
self.usage()
elif action == 'version':
self.print_version()
else:
print('Unknown action: %s' % action)
print('Run "%s --help" for list of available options' % sys.argv[0])
def record(self):
if not AsciiCast(self.config, self.options).create():
sys.exit(1)
def auth(self):
url = '%s/connect/%s' % (self.config.api_url(), self.config.user_token())
print 'Open following URL in your browser to authenticate and/or claim ' \
'recorded asciicasts:\n\n%s' % url
def check_pending(self):
num = len(self.pending_list())
if num > 0:
print 'Warning: %i recorded asciicasts weren\'t uploaded. ' \
'Run "%s upload" to upload them or delete them with "rm -rf %s/*".' \
% (num, SCRIPT_NAME, AsciiCast.QUEUE_DIR)
def upload_pending(self):
print 'Uploading pending asciicasts...'
for path in self.pending_list():
url = Uploader(self.config, path).upload()
if url:
print url
def pending_list(self):
return [os.path.dirname(p) for p in glob.glob(AsciiCast.QUEUE_DIR + '/*/*.time')]
def print_version(self):
print 'asciiio 1.0'
def usage(self):
print help_text.TEXT

46
src/config.py Normal file
View File

@@ -0,0 +1,46 @@
import os
import ConfigParser
import uuid
class Config:
def __init__(self):
self.config_filename = os.path.expanduser('~/.ascii.io/config')
config = ConfigParser.RawConfigParser()
config.add_section('user')
config.add_section('api')
config.add_section('record')
try:
config.read(self.config_filename)
except ConfigParser.ParsingError:
print('Config file %s contains syntax errors' % self.config_filename)
sys.exit(2)
self.config = config
# if not os.path.isdir(BASE_DIR):
# os.mkdir(BASE_DIR)
def api_url(self):
try:
api_url = self.config.get('api', 'url')
except ConfigParser.NoOptionError:
api_url = 'http://ascii.io'
api_url = os.environ.get('ASCII_IO_API_URL', api_url)
return api_url
def user_token(self):
try:
user_token = self.config.get('user', 'token')
except ConfigParser.NoOptionError:
user_token = str(uuid.uuid1())
self.config.set('user', 'token', user_token)
with open(self.config_filename, 'wb') as configfile:
self.config.write(configfile)
return user_token

17
src/help_text.py Normal file
View File

@@ -0,0 +1,17 @@
from constants import SCRIPT_NAME
TEXT = '''usage: %s [-h] [-i] [-y] [-c <command>] [-t <title>] [action]
Asciicast recorder+uploader.
Actions:
rec record asciicast (this is the default when no action given)
upload upload recorded (but not uploaded) asciicasts
auth authenticate and/or claim recorded asciicasts
Optional arguments:
-c command run specified command instead of shell ($SHELL)
-t title specify title of recorded asciicast
-y don't prompt for confirmation
-h, --help show this help message and exit
--version show version information''' % SCRIPT_NAME

41
src/options.py Normal file
View File

@@ -0,0 +1,41 @@
import sys
import getopt
class Options:
def __init__(self, argv):
self.action = None
self.command = None
self.title = None
self.record_input = False
self.always_yes = False
try:
opts, args = getopt.getopt(argv[1:], 'c:t:ihy', ['help', 'version'])
except getopt.error as msg:
print('%s: %s' % (argv[0], msg))
print('Run "%s --help" for list of available options' % argv[0])
sys.exit(2)
if len(args) == 0:
self.action = 'rec'
elif len(args) == 1:
self.action = args[0]
elif len(args) > 1:
print('Too many arguments')
print('Run "%s --help" for list of available options' % argv[0])
sys.exit(2)
for opt, arg in opts:
if opt in ('-h', '--help'):
self.action = 'help'
elif opt == '--version':
self.action = 'version'
elif opt == '-c':
self.command = arg.split()
elif opt == '-t':
self.title = arg
elif opt == '-i':
self.record_input = True
elif opt == '-y':
self.always_yes = True

View File

@@ -8,8 +8,8 @@ class Uploader(object):
Uploads recorded script to website using HTTP based API. Uploads recorded script to website using HTTP based API.
''' '''
def __init__(self, api_url, path): def __init__(self, config, path):
self.api_url = api_url self.api_url = config.api_url()
self.path = path self.path = path
def upload(self): def upload(self):