diff --git a/CHANGELOG b/CHANGELOG index 6f1c8d4..436a9ca 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,21 +1,25 @@ -2011-05-31 Randall Degges + * PEP8 Fixes + +2011-05-31 Randall Degges * BUGFIX: Fixing issue that prevented manager.status command from returning proper output. 2007-01-26 Matthew Nicholson - * asterisk/manager.py: Make get_header() functions work like - dict.get(). - * UPGRADE: Updated. + * asterisk/manager.py: Make get_header() functions work like + dict.get(). + * UPGRADE: Updated. 2007-01-16 Matthew Nicholson - * asterisk/manager.py: Fix support for Manager.command(). Patch from - Karl Putland . + * asterisk/manager.py: Fix support for Manager.command(). Patch from + Karl Putland . 2007-01-02 Matthew Nicholson - * asterisk/agi.py (AGI.set_autohangup): Fixed syntax error. + * asterisk/agi.py (AGI.set_autohangup): Fixed syntax error. 2006-11-28 Matthew Nicholson @@ -94,4 +98,3 @@ * ChangeLog: Added. * TODO: Added. * MANIFEST.in: Added ChangeLog and TODO. - diff --git a/asterisk/agi.py b/asterisk/agi.py index d67734a..1ff97bd 100644 --- a/asterisk/agi.py +++ b/asterisk/agi.py @@ -19,34 +19,65 @@ pyvr """ -import sys, pprint, re +import sys +import pprint +import re from types import ListType import signal -DEFAULT_TIMEOUT = 2000 # 2sec timeout used as default for functions that take timeouts -DEFAULT_RECORD = 20000 # 20sec record time +DEFAULT_TIMEOUT = 2000 # 2sec timeout used as default for functions that take timeouts +DEFAULT_RECORD = 20000 # 20sec record time re_code = re.compile(r'(^\d*)\s*(.*)') re_kv = re.compile(r'(?P\w+)=(?P[^\s]+)\s*(?:\((?P.*)\))*') -class AGIException(Exception): pass -class AGIError(AGIException): pass -class AGIUnknownError(AGIError): pass +class AGIException(Exception): + pass -class AGIAppError(AGIError): pass + +class AGIError(AGIException): + pass + + +class AGIUnknownError(AGIError): + pass + + +class AGIAppError(AGIError): + pass # there are several different types of hangups we can detect # they all are derrived from AGIHangup -class AGIHangup(AGIAppError): pass -class AGISIGHUPHangup(AGIHangup): pass -class AGISIGPIPEHangup(AGIHangup): pass -class AGIResultHangup(AGIHangup): pass -class AGIDBError(AGIAppError): pass -class AGIUsageError(AGIError): pass -class AGIInvalidCommand(AGIError): pass +class AGIHangup(AGIAppError): + pass + + +class AGISIGHUPHangup(AGIHangup): + pass + + +class AGISIGPIPEHangup(AGIHangup): + pass + + +class AGIResultHangup(AGIHangup): + pass + + +class AGIDBError(AGIAppError): + pass + + +class AGIUsageError(AGIError): + pass + + +class AGIInvalidCommand(AGIError): + pass + class AGI: """ @@ -73,10 +104,10 @@ class AGI: if line == '': #blank line signals end break - key,data = line.split(':')[0], ':'.join(line.split(':')[1:]) + key, data = line.split(':')[0], ':'.join(line.split(':')[1:]) key = key.strip() data = data.strip() - if key <> '': + if key != '': self.env[key] = data sys.stderr.write('class AGI: self.env = ') sys.stderr.write(pprint.pformat(self.env)) @@ -92,7 +123,7 @@ class AGI: def test_hangup(self): """This function throws AGIHangup if we have recieved a SIGHUP""" if self._got_sighup: - raise AGISIGHUPHangup("Received SIGHUP from Asterisk") + raise AGISIGHUPHangup("Received SIGHUP from Asterisk") def execute(self, command, *args): self.test_hangup() @@ -100,7 +131,7 @@ class AGI: try: self.send_command(command, *args) return self.get_result() - except IOError,e: + except IOError, e: if e.errno == 32: # Broken Pipe * let us go raise AGISIGPIPEHangup("Received SIGPIPE") @@ -110,7 +141,7 @@ class AGI: def send_command(self, command, *args): """Send a command to Asterisk""" command = command.strip() - command = '%s %s' % (command, ' '.join(map(str,args))) + command = '%s %s' % (command, ' '.join(map(str, args))) command = command.strip() if command[-1] != '\n': command += '\n' @@ -121,7 +152,7 @@ class AGI: def get_result(self, stdin=sys.stdin): """Read the result of a command from Asterisk""" code = 0 - result = {'result':('','')} + result = {'result': ('', '')} line = stdin.readline().strip() sys.stderr.write(' RESULT_LINE: %s\n' % line) m = re_code.search(line) @@ -130,7 +161,7 @@ class AGI: code = int(code) if code == 200: - for key,value,data in re_kv.findall(response): + for key, value, data in re_kv.findall(response): result[key] = (value, data) # If user hangs up... we get 'hangup' in the data @@ -226,7 +257,8 @@ class AGI: extension must not be included in the filename. """ escape_digits = self._process_digit_list(escape_digits) - response = self.execute('STREAM FILE', filename, escape_digits, sample_offset) + response = self.execute( + 'STREAM FILE', filename, escape_digits, sample_offset) res = response['result'][0] if res == '0': return '' @@ -265,7 +297,8 @@ class AGI: """ res = self.execute('SEND IMAGE', filename)['result'][0] if res != '0': - raise AGIAppError('Channel falure on channel %s' % self.env.get('agi_channel','UNKNOWN')) + raise AGIAppError('Channel falure on channel %s' % + self.env.get('agi_channel', 'UNKNOWN')) def say_digits(self, digits, escape_digits=''): """agi.say_digits(digits, escape_digits='') --> digit @@ -326,7 +359,8 @@ class AGI: """ characters = self._process_digit_list(characters) escape_digits = self._process_digit_list(escape_digits) - res = self.execute('SAY PHONETIC', characters, escape_digits)['result'][0] + res = self.execute( + 'SAY PHONETIC', characters, escape_digits)['result'][0] if res == '0': return '' else: @@ -372,8 +406,10 @@ class AGI: in seconds since the UNIX Epoch (Jan 1, 1970 00:00:00). """ escape_digits = self._process_digit_list(escape_digits) - if format: format = self._quote(format) - res = self.execute('SAY DATETIME', seconds, escape_digits, format, zone)['result'][0] + if format: + format = self._quote(format) + res = self.execute( + 'SAY DATETIME', seconds, escape_digits, format, zone)['result'][0] if res == '0': return '' else: @@ -401,7 +437,8 @@ class AGI: """ escape_digits = self._process_digit_list(escape_digits) if timeout: - response = self.execute('GET OPTION', filename, escape_digits, timeout) + response = self.execute( + 'GET OPTION', filename, escape_digits, timeout) else: response = self.execute('GET OPTION', filename, escape_digits) @@ -455,7 +492,8 @@ class AGI: exceeding the end of the file """ escape_digits = self._process_digit_list(escape_digits) - res = self.execute('RECORD FILE', self._quote(filename), format, escape_digits, timeout, offset, beep)['result'][0] + res = self.execute('RECORD FILE', self._quote(filename), format, + escape_digits, timeout, offset, beep)['result'][0] try: return chr(int(res)) except: @@ -510,11 +548,11 @@ class AGI: 7 Line is busy """ try: - result = self.execute('CHANNEL STATUS', channel) + result = self.execute('CHANNEL STATUS', channel) except AGIHangup: - raise + raise except AGIAppError: - result = {'result': ('-1','')} + result = {'result': ('-1', '')} return int(result['result'][0]) @@ -530,27 +568,28 @@ class AGI: the variable is not set, an empty string is returned. """ try: - result = self.execute('GET VARIABLE', self._quote(name)) + result = self.execute('GET VARIABLE', self._quote(name)) except AGIResultHangup: - result = {'result': ('1', 'hangup')} + result = {'result': ('1', 'hangup')} res, value = result['result'] return value - def get_full_variable(self, name, channel = None): + def get_full_variable(self, name, channel=None): """Get a channel variable. This function returns the value of the indicated channel variable. If the variable is not set, an empty string is returned. """ try: - if channel: - result = self.execute('GET FULL VARIABLE', self._quote(name), self._quote(channel)) - else: - result = self.execute('GET FULL VARIABLE', self._quote(name)) + if channel: + result = self.execute('GET FULL VARIABLE', + self._quote(name), self._quote(channel)) + else: + result = self.execute('GET FULL VARIABLE', self._quote(name)) except AGIResultHangup: - result = {'result': ('1', 'hangup')} + result = {'result': ('1', 'hangup')} res, value = result['result'] return value @@ -571,10 +610,12 @@ class AGI: """ family = '"%s"' % family key = '"%s"' % key - result = self.execute('DATABASE GET', self._quote(family), self._quote(key)) + result = self.execute( + 'DATABASE GET', self._quote(family), self._quote(key)) res, value = result['result'] if res == '0': - raise AGIDBError('Key not found in database: family=%s, key=%s' % (family, key)) + raise AGIDBError('Key not found in database: family=%s, key=%s' % + (family, key)) elif res == '1': return value else: @@ -585,7 +626,8 @@ class AGI: Adds or updates an entry in the Asterisk database for a given family, key, and value. """ - result = self.execute('DATABASE PUT', self._quote(family), self._quote(key), self._quote(value)) + result = self.execute('DATABASE PUT', self._quote( + family), self._quote(key), self._quote(value)) res, value = result['result'] if res == '0': raise AGIDBError('Unable to put vaule in databale: family=%s, key=%s, value=%s' % (family, key, value)) @@ -595,7 +637,8 @@ class AGI: Deletes an entry in the Asterisk database for a given family and key. """ - result = self.execute('DATABASE DEL', self._quote(family), self._quote(key)) + result = self.execute( + 'DATABASE DEL', self._quote(family), self._quote(key)) res, value = result['result'] if res == '0': raise AGIDBError('Unable to delete from database: family=%s, key=%s' % (family, key)) @@ -605,7 +648,8 @@ class AGI: Deletes a family or specific keytree with in a family in the Asterisk database. """ - result = self.execute('DATABASE DELTREE', self._quote(family), self._quote(key)) + result = self.execute( + 'DATABASE DELTREE', self._quote(family), self._quote(key)) res, value = result['result'] if res == '0': raise AGIDBError('Unable to delete tree from database: family=%s, key=%s' % (family, key)) @@ -616,7 +660,7 @@ class AGI: """ self.execute('NOOP') -if __name__=='__main__': +if __name__ == '__main__': agi = AGI() #agi.appexec('festival','Welcome to Klass Technologies. Thank you for calling.') #agi.appexec('festival','This is a test of the text to speech engine.') @@ -638,11 +682,12 @@ if __name__=='__main__': #agi.appexec('background','demo-congrats') try: - agi.appexec('backgrounder','demo-congrats') + agi.appexec('backgrounder', 'demo-congrats') except AGIAppError: - sys.stderr.write("Handled exception for missing application backgrounder\n") + sys.stderr.write( + "Handled exception for missing application backgrounder\n") - agi.set_variable('foo','bar') + agi.set_variable('foo', 'bar') agi.get_variable('foo') try: @@ -661,6 +706,7 @@ if __name__=='__main__': agi.database_del('foo', 'bar') agi.database_deltree('foo') except AGIDBError: - sys.stderr.write("Handled exception for missing database entry bar:foo\n") + sys.stderr.write( + "Handled exception for missing database entry bar:foo\n") agi.hangup() diff --git a/asterisk/agitb.py b/asterisk/agitb.py index 9eea166..f1fa4d3 100644 --- a/asterisk/agitb.py +++ b/asterisk/agitb.py @@ -36,6 +36,7 @@ import sys __UNDEF__ = [] # a special sentinel object + def lookup(name, frame, locals): """Find the value for a given name in the given environment.""" if name in locals: @@ -44,7 +45,7 @@ def lookup(name, frame, locals): return 'global', frame.f_globals[name] if '__builtins__' in frame.f_globals: builtins = frame.f_globals['__builtins__'] - if type(builtins) is type({}): + if isinstance(builtins, type({})): if name in builtins: return 'builtin', builtins[name] else: @@ -52,12 +53,15 @@ def lookup(name, frame, locals): return 'builtin', getattr(builtins, name) return None, __UNDEF__ + def scanvars(reader, frame, locals): """Scan one logical line of Python and look up values of variables used.""" - import tokenize, keyword + import tokenize + import keyword vars, lasttoken, parent, prefix, value = [], None, None, '', __UNDEF__ for ttype, token, start, end, line in tokenize.generate_tokens(reader): - if ttype == tokenize.NEWLINE: break + if ttype == tokenize.NEWLINE: + break if ttype == tokenize.NAME and token not in keyword.kwlist: if lasttoken == '.': if parent is not __UNDEF__: @@ -77,9 +81,15 @@ def scanvars(reader, frame, locals): def text((etype, evalue, etb), context=5): """Return a plain text document describing a given traceback.""" - import os, types, time, traceback, linecache, inspect, pydoc + import os + import types + import time + import traceback + import linecache + import inspect + import pydoc - if type(etype) is types.ClassType: + if isinstance(etype, types.ClassType): etype = etype.__name__ pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable date = time.ctime(time.time()) @@ -97,13 +107,16 @@ function calls leading up to the error, in the order they occurred. if func != '?': call = 'in ' + func + \ inspect.formatargvalues(args, varargs, varkw, locals, - formatvalue=lambda value: '=' + pydoc.text.repr(value)) + formatvalue=lambda value: '=' + pydoc.text.repr(value)) highlight = {} + def reader(lnum=[lnum]): highlight[lnum[0]] = 1 - try: return linecache.getline(file, lnum[0]) - finally: lnum[0] += 1 + try: + return linecache.getline(file, lnum[0]) + finally: + lnum[0] += 1 vars = scanvars(reader, frame, locals) rows = [' %s %s' % (file, call)] @@ -111,17 +124,21 @@ function calls leading up to the error, in the order they occurred. i = lnum - index for line in lines: num = '%5d ' % i - rows.append(num+line.rstrip()) + rows.append(num + line.rstrip()) i += 1 done, dump = {}, [] for name, where, value in vars: - if name in done: continue + if name in done: + continue done[name] = 1 if value is not __UNDEF__: - if where == 'global': name = 'global ' + name - elif where == 'local': name = name - else: name = where + name.split('.')[-1] + if where == 'global': + name = 'global ' + name + elif where == 'local': + name = name + else: + name = where + name.split('.')[-1] dump.append('%s = %s' % (name, pydoc.text.repr(value))) else: dump.append(name + ' undefined') @@ -130,10 +147,10 @@ function calls leading up to the error, in the order they occurred. frames.append('\n%s\n' % '\n'.join(rows)) exception = ['%s: %s' % (str(etype), str(evalue))] - if type(evalue) is types.InstanceType: + if isinstance(evalue, types.InstanceType): for name in dir(evalue): value = pydoc.text.repr(getattr(evalue, name)) - exception.append('\n%s%s = %s' % (" "*4, name, value)) + exception.append('\n%s%s = %s' % (" " * 4, name, value)) import traceback return head + ''.join(frames) + ''.join(exception) + ''' @@ -144,11 +161,12 @@ the original traceback: %s ''' % ''.join(traceback.format_exception(etype, evalue, etb)) + class Hook: """A hook to replace sys.excepthook that shows tracebacks in HTML.""" def __init__(self, display=1, logdir=None, context=5, file=None, - agi=None): + agi=None): self.display = display # send tracebacks to browser if true self.logdir = logdir # log tracebacks to files if not None self.context = context # number of source code lines per frame @@ -180,7 +198,8 @@ class Hook: self.file.write('A problem occured in a python script\n') if self.logdir is not None: - import os, tempfile + import os + import tempfile (fd, path) = tempfile.mkstemp(suffix='.txt', dir=self.logdir) try: file = os.fdopen(fd, 'w') @@ -197,20 +216,22 @@ class Hook: try: self.file.flush() - except: pass + except: + pass handler = Hook().handle + + def enable(agi=None, display=1, logdir=None, context=5): """Install an exception handler that formats tracebacks as HTML. The optional argument 'display' can be set to 0 to suppress sending the traceback to the browser, and 'logdir' can be set to a directory to cause tracebacks to be written to files there.""" - except_hook = Hook(display=display, logdir=logdir, - context=context, agi=agi) + except_hook = Hook(display=display, logdir=logdir, + context=context, agi=agi) sys.excepthook = except_hook global handler handler = except_hook.handle - diff --git a/asterisk/config.py b/asterisk/config.py index 916f636..4e28bd8 100644 --- a/asterisk/config.py +++ b/asterisk/config.py @@ -28,18 +28,22 @@ This module provides parsing functionality for asterisk config files. import sys -class ParseError(Exception): pass + +class ParseError(Exception): + pass + class Line(object): def __init__(self, line, number): self.line = '' self.comment = '' line = line.strip() # I guess we don't preserve indentation - self.number = number + self.number = number parts = line.split(';') if len(parts) >= 2: self.line = parts[0].strip() - self.comment = ';'.join(parts[1:]) #Just in case the comment contained ';' + self.comment = ';'.join( + parts[1:]) # Just in case the comment contained ';' else: self.line = line @@ -59,12 +63,14 @@ class Category(Line): Line.__init__(self, line, num) if self.line: if (self.line[0] != '[' or self.line[-1] != ']'): - raise ParseError(self.number, "Missing '[' or ']' in category definition") + raise ParseError( + self.number, "Missing '[' or ']' in category definition") self.name = self.line[1:-1] elif name: self.name = name else: - raise Exception("Must provide name or line representing a category") + raise Exception( + "Must provide name or line representing a category") self.items = [] self.comments = [] @@ -106,10 +112,11 @@ class Item(Line): if self.line.strip()[-1] == ']': raise ParseError(self.number, "Category name missing '['") else: - raise ParseError(self.number, "Item must be in name = value pairs") + raise ParseError( + self.number, "Item must be in name = value pairs") if value and value[0] == '>': - self.style = '>' #preserve the style of the original + self.style = '>' # preserve the style of the original value = value[1:].strip() self.name = name.strip() self.value = value @@ -119,6 +126,7 @@ class Item(Line): return '%s =%s %s\t;%s' % (self.name, self.style, self.value, self.comment) return '%s =%s %s' % (self.name, self.style, self.value) + class Config(object): def __init__(self, filename): self.filename = filename @@ -127,8 +135,8 @@ class Config(object): self.categories = [] # load and parse the file - self.load() - self.parse() + self.load() + self.parse() def load(self): self.raw_lines = open(self.filename).readlines() @@ -140,14 +148,15 @@ class Config(object): def parse(self): cat = None - num = 0 + num = 0 for line in self.raw_lines: num += 1 line = line.strip() if not line or line[0] == ';': item = Line(line or '', num) self.lines.append(item) - if cat: cat.comments.append(item) + if cat: + cat.comments.append(item) continue elif line[0] == '[': cat = Category(line, num) @@ -157,6 +166,6 @@ class Config(object): else: item = Item(line, num) self.lines.append(item) - if cat: cat.append(item) + if cat: + cat.append(item) continue - diff --git a/asterisk/manager.py b/asterisk/manager.py index 5bb5b84..00b5206 100644 --- a/asterisk/manager.py +++ b/asterisk/manager.py @@ -52,7 +52,8 @@ Not all manager actions are implmented as of yet, feel free to add them and submit patches. """ -import sys,os +import sys +import os import socket import threading import Queue @@ -63,6 +64,7 @@ from time import sleep EOL = '\r\n' + class ManagerMsg(object): """A manager interface message""" def __init__(self, response): @@ -99,13 +101,13 @@ class ManagerMsg(object): """Parse a manager message""" data = [] - for n, line in enumerate (response): + for n, line in enumerate(response): # all valid header lines end in \r\n - if not line.endswith ('\r\n'): + if not line.endswith('\r\n'): data.extend(response[n:]) break try: - k, v = (x.strip() for x in line.split(':',1)) + k, v = (x.strip() for x in line.split(':', 1)) self.headers[k] = v except ValueError: # invalid header, start of multi-line data response @@ -115,9 +117,9 @@ class ManagerMsg(object): def has_header(self, hname): """Check for a header""" - return self.headers.has_key(hname) + return hname in self.headers - def get_header(self, hname, defval = None): + def get_header(self, hname, defval=None): """Return the specfied header""" return self.headers.get(hname, defval) @@ -143,16 +145,17 @@ class Event(object): # if this is not an event message we have a problem if not message.has_header('Event'): - raise ManagerException('Trying to create event from non event message') + raise ManagerException( + 'Trying to create event from non event message') # get the event name self.name = message.get_header('Event') def has_header(self, hname): """Check for a header""" - return self.headers.has_key(hname) + return hname in self.headers - def get_header(self, hname, defval = None): + def get_header(self, hname, defval=None): """Return the specfied header""" return self.headers.get(hname, defval) @@ -164,7 +167,8 @@ class Event(object): return self.headers['Event'] def get_action_id(self): - return self.headers.get('ActionID',0000) + return self.headers.get('ActionID', 0000) + class Manager(object): def __init__(self): @@ -192,12 +196,12 @@ class Manager(object): # some threads self.message_thread = threading.Thread(target=self.message_loop) - self.event_dispatch_thread = threading.Thread(target=self.event_dispatch) + self.event_dispatch_thread = threading.Thread( + target=self.event_dispatch) self.message_thread.setDaemon(True) self.event_dispatch_thread.setDaemon(True) - def __del__(self): self.close() @@ -241,18 +245,19 @@ class Manager(object): cdict.update(kwargs) # set the action id - if not cdict.has_key('ActionID'): cdict['ActionID'] = '%s-%08x' % (self.hostname, self.next_seq()) + if 'ActionID' not in cdict: + cdict['ActionID'] = '%s-%08x' % (self.hostname, self.next_seq()) clist = [] # generate the command for key, value in cdict.items(): if isinstance(value, list): - for item in value: - item = tuple([key, item]) - clist.append('%s: %s' % item) + for item in value: + item = tuple([key, item]) + clist.append('%s: %s' % item) else: - item = tuple([key, value]) - clist.append('%s: %s' % item) + item = tuple([key, value]) + clist.append('%s: %s' % item) clist.append(EOL) command = EOL.join(clist) @@ -263,7 +268,7 @@ class Manager(object): except socket.error, (errno, reason): raise ManagerSocketException(errno, reason) - self._reswaiting.insert(0,1) + self._reswaiting.insert(0, 1) response = self._response_queue.get() self._reswaiting.pop(0) @@ -285,7 +290,7 @@ class Manager(object): while self._running.isSet() and self._connected.isSet(): try: lines = [] - for line in self._sock : + for line in self._sock: # check to see if this is the greeting line if not self.title and '/' in line and not ':' in line: # store the title of the manager we are connecting to: @@ -293,8 +298,8 @@ class Manager(object): # store the version of the manager we are connecting to: self.version = line.split('/')[1].strip() # fake message header - lines.append ('Response: Generated Header\r\n') - lines.append (line) + lines.append('Response: Generated Header\r\n') + lines.append(line) break # If the line is EOL marker we have a complete message. # Some commands are broken and contain a \n\r\n @@ -302,7 +307,7 @@ class Manager(object): # have such a command where the data ends with the # marker --END COMMAND--, so we ignore embedded # newlines until we see that marker - if line == EOL and not wait_for_marker : + if line == EOL and not wait_for_marker: multiline = False if lines or not self._connected.isSet(): break @@ -321,7 +326,7 @@ class Manager(object): # Response: Follows indicates we should wait for end # marker --END COMMAND-- if not (multiline or status) and line.startswith('Response') and \ - line.split(':', 1)[1].strip() == 'Follows': + line.split(':', 1)[1].strip() == 'Follows': wait_for_marker = True # same when seeing end of multiline response if multiline and line.startswith('--END COMMAND--'): @@ -347,7 +352,6 @@ class Manager(object): self._connected.clear() self._message_queue.put(None) - def register_event(self, event, function): """ Register a callback for the specfied event. @@ -410,7 +414,6 @@ class Manager(object): # wait for our data receiving thread to exit t.join() - def event_dispatch(self): """This thread is responsible for dispatching events""" @@ -427,12 +430,12 @@ class Manager(object): # first build a list of the functions to execute callbacks = (self._event_callbacks.get(ev.name, []) - + self._event_callbacks.get('*', [])) + + self._event_callbacks.get('*', [])) # now execute the functions for callback in callbacks: - if callback(ev, self): - break + if callback(ev, self): + break def connect(self, host, port=5038): """Connect to the manager interface""" @@ -448,9 +451,9 @@ class Manager(object): # create our socket and connect try: _sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - _sock.connect((host,port)) - self._sock = _sock.makefile () - _sock.close () + _sock.connect((host, port)) + self._sock = _sock.makefile() + _sock.close() except socket.error, (errno, reason): raise ManagerSocketException(errno, reason) @@ -493,26 +496,26 @@ class Manager(object): def login(self, username, secret): """Login to the manager, throws ManagerAuthException when login falis""" - cdict = {'Action':'Login'} + cdict = {'Action': 'Login'} cdict['Username'] = username cdict['Secret'] = secret response = self.send_action(cdict) if response.get_header('Response') == 'Error': - raise ManagerAuthException(response.get_header('Message')) + raise ManagerAuthException(response.get_header('Message')) return response def ping(self): """Send a ping action to the manager""" - cdict = {'Action':'Ping'} + cdict = {'Action': 'Ping'} response = self.send_action(cdict) return response def logoff(self): """Logoff from the manager""" - cdict = {'Action':'Logoff'} + cdict = {'Action': 'Logoff'} response = self.send_action(cdict) return response @@ -520,16 +523,16 @@ class Manager(object): def hangup(self, channel): """Hangup the specified channel""" - cdict = {'Action':'Hangup'} + cdict = {'Action': 'Hangup'} cdict['Channel'] = channel response = self.send_action(cdict) return response - def status(self, channel = ''): + def status(self, channel=''): """Get a status message from asterisk""" - cdict = {'Action':'Status'} + cdict = {'Action': 'Status'} cdict['Channel'] = channel response = self.send_action(cdict) @@ -538,12 +541,14 @@ class Manager(object): def redirect(self, channel, exten, priority='1', extra_channel='', context=''): """Redirect a channel""" - cdict = {'Action':'Redirect'} + cdict = {'Action': 'Redirect'} cdict['Channel'] = channel cdict['Exten'] = exten cdict['Priority'] = priority - if context: cdict['Context'] = context - if extra_channel: cdict['ExtraChannel'] = extra_channel + if context: + cdict['Context'] = context + if extra_channel: + cdict['ExtraChannel'] = extra_channel response = self.send_action(cdict) return response @@ -551,19 +556,27 @@ class Manager(object): def originate(self, channel, exten, context='', priority='', timeout='', caller_id='', async=False, account='', variables={}): """Originate a call""" - cdict = {'Action':'Originate'} + cdict = {'Action': 'Originate'} cdict['Channel'] = channel cdict['Exten'] = exten - if context: cdict['Context'] = context - if priority: cdict['Priority'] = priority - if timeout: cdict['Timeout'] = timeout - if caller_id: cdict['CallerID'] = caller_id - if async: cdict['Async'] = 'yes' - if account: cdict['Account'] = account + if context: + cdict['Context'] = context + if priority: + cdict['Priority'] = priority + if timeout: + cdict['Timeout'] = timeout + if caller_id: + cdict['CallerID'] = caller_id + if async: + cdict['Async'] = 'yes' + if account: + cdict['Account'] = account # join dict of vairables together in a string in the form of 'key=val|key=val' # with the latest CVS HEAD this is no longer necessary # if variables: cdict['Variable'] = '|'.join(['='.join((str(key), str(value))) for key, value in variables.items()]) - if variables: cdict['Variable'] = ['='.join((str(key), str(value))) for key, value in variables.items()] + if variables: + cdict['Variable'] = ['='.join( + (str(key), str(value))) for key, value in variables.items()] response = self.send_action(cdict) @@ -572,7 +585,7 @@ class Manager(object): def mailbox_status(self, mailbox): """Get the status of the specfied mailbox""" - cdict = {'Action':'MailboxStatus'} + cdict = {'Action': 'MailboxStatus'} cdict['Mailbox'] = mailbox response = self.send_action(cdict) @@ -581,7 +594,7 @@ class Manager(object): def command(self, command): """Execute a command""" - cdict = {'Action':'Command'} + cdict = {'Action': 'Command'} cdict['Command'] = command response = self.send_action(cdict) @@ -590,16 +603,16 @@ class Manager(object): def extension_state(self, exten, context): """Get the state of an extension""" - cdict = {'Action':'ExtensionState'} + cdict = {'Action': 'ExtensionState'} cdict['Exten'] = exten cdict['Context'] = context response = self.send_action(cdict) return response - def playdtmf (self, channel, digit) : + def playdtmf(self, channel, digit): """Plays a dtmf digit on the specified channel""" - cdict = {'Action':'PlayDTMF'} + cdict = {'Action': 'PlayDTMF'} cdict['Channel'] = channel cdict['Digit'] = digit response = self.send_action(cdict) @@ -609,7 +622,7 @@ class Manager(object): def absolute_timeout(self, channel, timeout): """Set an absolute timeout on a channel""" - cdict = {'Action':'AbsoluteTimeout'} + cdict = {'Action': 'AbsoluteTimeout'} cdict['Channel'] = channel cdict['Timeout'] = timeout response = self.send_action(cdict) @@ -617,25 +630,31 @@ class Manager(object): return response def mailbox_count(self, mailbox): - cdict = {'Action':'MailboxCount'} + cdict = {'Action': 'MailboxCount'} cdict['Mailbox'] = mailbox response = self.send_action(cdict) return response def sippeers(self): - cdict = {'Action' : 'Sippeers'} + cdict = {'Action': 'Sippeers'} response = self.send_action(cdict) return response def sipshowpeer(self, peer): - cdict = {'Action' : 'SIPshowpeer'} + cdict = {'Action': 'SIPshowpeer'} cdict['Peer'] = peer response = self.send_action(cdict) return response -class ManagerException(Exception): pass -class ManagerSocketException(ManagerException): pass -class ManagerAuthException(ManagerException): pass +class ManagerException(Exception): + pass + +class ManagerSocketException(ManagerException): + pass + + +class ManagerAuthException(ManagerException): + pass diff --git a/setup.py b/setup.py index 403fc0e..663c728 100644 --- a/setup.py +++ b/setup.py @@ -6,45 +6,43 @@ from asterisk import __version__ as version description = [] -f = open ('README') +f = open('README') + logo_stripped = False -for line in f : - if not logo_stripped and line.strip () : +for line in f: + if not logo_stripped and line.strip(): continue logo_stripped = True - description.append (line) + description.append(line) -licenses = ( 'Python Software Foundation License' - , 'GNU Library or Lesser General Public License (LGPL)' - ) +licenses = ('Python Software Foundation License', + 'GNU Library or Lesser General Public License (LGPL)') - -setup \ - ( name = 'pyst2' - , version = version - , description = 'A Python Interface to Asterisk' - , long_description = ''.join (description) - , author = 'Karl Putland' - , author_email = 'kputland@users.sourceforge.net' - , maintainer = 'Randall Degges' - , maintainer_email = 'rdegges@gmail.com' - , url = 'http://www.sourceforge.net/projects/pyst/' - , packages = ['asterisk'] - , license = ', '.join (licenses) - , platforms = 'Any' - , classifiers = - [ 'Development Status :: 5 - Production/Stable' - , 'Environment :: Other Environment' - , 'Intended Audience :: Developers' - , 'Intended Audience :: Telecommunications Industry' - , 'Operating System :: OS Independent' - , 'Programming Language :: Python' - , 'Programming Language :: Python :: 2.4' - , 'Programming Language :: Python :: 2.5' - , 'Programming Language :: Python :: 2.6' - , 'Programming Language :: Python :: 2.7' - , 'Topic :: Communications :: Internet Phone' - , 'Topic :: Communications :: Telephony' - , 'Topic :: Software Development :: Libraries :: Python Modules' - ] + ['License :: OSI Approved :: ' + l for l in licenses] - ) +setup( + name='pyst2', + version=version, + description='A Python Interface to Asterisk', + long_description=''.join(description), author='Karl Putland', + author_email='kputland@users.sourceforge.net', + maintainer='Randall Degges', + maintainer_email='rdegges@gmail.com', + url='http://www.sourceforge.net/projects/pyst/', + packages=['asterisk'], + license=', '.join(licenses), + platforms='Any', + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Environment :: Other Environment', + 'Intended Audience :: Developers', + 'Intended Audience :: Telecommunications Industry', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2.4', + 'Programming Language :: Python :: 2.5', + 'Programming Language :: Python :: 2.6', + 'Programming Language :: Python :: 2.7', + 'Topic :: Communications :: Internet Phone', + 'Topic :: Communications :: Telephony', + 'Topic :: Software Development :: Libraries :: Python Modules' + ] + ['License :: OSI Approved :: ' + l for l in licenses] +)