From 5efe3f4593d3e8b4f50768d457e7ffa52d199366 Mon Sep 17 00:00:00 2001 From: Timur Tuchkovenko Date: Wed, 8 Oct 2014 00:49:54 +0600 Subject: [PATCH] minor rewrite for Python 3 support. Some other fixes in corresponding files. --- .gitignore | 10 ++++- CHANGELOG | 30 ++++++++++--- Makefile | 2 +- README.rst | 92 ++++++++++++++++++++++----------------- asterisk/__init__.py | 2 +- asterisk/agi.py | 5 +-- asterisk/agitb.py | 3 +- asterisk/config.py | 8 ++-- asterisk/manager.py | 33 +++++++------- examples/show_channels.py | 16 +++---- setup.py | 4 ++ 11 files changed, 122 insertions(+), 83 deletions(-) diff --git a/.gitignore b/.gitignore index 751af4b..924e52e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ # Temporary files. -*.pyc -*.swp +*.py[cod] +*.sw? *~ .coverage @@ -10,5 +10,11 @@ build _build *.egg-info +# Python-related stuff +env/ +.env/ +venv/ +__pycache__/ + # Auto-generated files. MANIFEST diff --git a/CHANGELOG b/CHANGELOG index 436a9ca..09f49b4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,21 @@ +2014-10-08 Timur Tuchkovenko + * UPGRADE: initial Python 3 support. Now pyst2 requires + Python 'six' module. Some minor changes in other files. + +2014-09-14 Sp1tF1r3 + * asterisk/manager.py: added action 'Reload' for Asterisk Manager + Interface (AMI). + +2013-12-03 Ludovic Gasc + * examples/agi_script.py: added example script to explain AGI + functionality. + * README: renamed to REAMDE.rst for Github's Markdown support. + * setup.py: minor changes. + +2012-11-12 Arezqui Belaid + * asterisk/manager.py: minor empty line enhancements. + * examples/show_channels.py: added example script to show information via + Asterisk Manager Interface (AMI). 2012-11-11 Arezqui Belaid * PEP8 Fixes @@ -8,18 +26,18 @@ 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 diff --git a/Makefile b/Makefile index aaf5793..00ce12f 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ VERSION=$(VERSIONPY) LASTRELEASE:=$(shell ../svntools/lastrelease -n) USERNAME=schlatterbeck -PROJECT=pyst +PROJECT=pyst2 PACKAGE=${PROJECT} CHANGES=changes NOTES=notes diff --git a/README.rst b/README.rst index eae2adb..399915a 100644 --- a/README.rst +++ b/README.rst @@ -1,21 +1,43 @@ -pyst: A Python Interface to Asterisk +pyst2: A Python Interface to Asterisk ==================================== -Pyst consists of a set of interfaces and libraries to allow programming of +Pyst2 consists of a set of interfaces and libraries to allow programming of Asterisk from python. The library currently supports AGI, AMI, and the parsing of Asterisk configuration files. The library also includes debugging facilities for AGI. -Download from `Sourceforge project page`_. +This project has been forked from pyst (http://sf.net/projects/pyst/) because +it was impossible for me to contact the project maintainer (after several +attempts), and I'd like to bring the project up-to-date, fix bugs, and make +it more usable overall. -.. _`Sourceforge project page`: http://sourceforge.net/projects/pyst/ +My immediate plans include adding full documentation, re-writing some +of the core routines, adding a test suite, and accepting pull requests. + +If you are one of the current maintainers, and would like to take over the +fork, please contact me: rdegges@gmail.com, so we can get that setup! + +Requirements +------------ + +1. six + +Installation +------------ + +Download from `Github project page`_. + +.. _`Github project page`: https://github.com/rdegges/pyst2 Installation is the standard python install:: - tar xvf pyst.tar.gz - cd pyst + git clone https://github.com/rdegges/pyst2.git + cd pyst2 python setup.py install --prefix=/usr/local +Documentation +------------- + Documentation is currently only in python docstrings, you can use pythons built-in help facility:: @@ -35,23 +57,14 @@ directly on the host where Asterisk is running. Since Asterisk doesn't run on windows platforms (and probably never will) the agi part of the package can only be run on Asterisk platforms. -.. note:: - This project has been forked because it was impossible for me to contact - the project maintainer (after several attempts), and I'd like to bring the - project up-to-date, fix bugs, and make it more usable overall. - - My plans immediate plans include adding full documentation, re-writing some - of the core routines, adding a test suite, and accepting pull requests. - - If you are one of the current maintainers, and would like to take over the - fork, please contact me: rdegges@gmail.com, so we can get that setup! - Credits ------- Thanks to Karl Putland for writing the original package. Thanks to Matthew Nicholson for maintaining the package for some years and for handing over maintenance when he was no longer interested. +Thanks to Randall Degges for maintaining this for and accepting +pull requests. Things to do for pyst --------------------- @@ -59,9 +72,8 @@ Things to do for pyst This is the original changelog merged into the readme file. I'm not so sure I really want to change all these things (in particular the threaded implementation looks good to me). I will maintain a section -summarizing the changes in this README, the ChangeLog won't be -maintained any longer. Detailed changes will be available in the version -control tool (currently svn). +summarizing the changes in this README. Detailed changes will be +available in the version control tool (currently git). * ChangeLog: The ChangeLog needs to be updated from the monotone logs. @@ -82,28 +94,28 @@ control tool (currently svn). Matthew Nicholson writes on the mailinglist (note that I'm not sure I'll do this, I'm currently satisfied with the threaded implementation): - For pyst 0.3 I am planning to clean up the manager.py. There are - several know issues with the code. No one has actually reported these - as problems, but I have personally had trouble with these. Currently - manager.py runs in several threads, the main program thread, a thread to - read from the network, and an event distribution thread. This causes - problems with non thread safe code such as the MySQLdb libraries. This - design also causes problems when an event handler throws an exception - that causes the event processing thread to terminate. + For pyst 0.3 I am planning to clean up the manager.py. There are + several know issues with the code. No one has actually reported these + as problems, but I have personally had trouble with these. Currently + manager.py runs in several threads, the main program thread, a thread to + read from the network, and an event distribution thread. This causes + problems with non thread safe code such as the MySQLdb libraries. This + design also causes problems when an event handler throws an exception + that causes the event processing thread to terminate. - The second problem is with the way actions are sent. Each action has a - specific function associated with it in the manager object that takes - all possible arguments that may ever be passed to that action. This - makes the api somewhat rigid and the Manager object cluttered. + The second problem is with the way actions are sent. Each action has a + specific function associated with it in the manager object that takes + all possible arguments that may ever be passed to that action. This + makes the api somewhat rigid and the Manager object cluttered. - To solve these problems I am basically going to copy the design of my - Astxx manager library (written in c++) and make it more python like. - Each action will be a different object with certain methods to handle - various tasks, with one function in the actual Manager class to send the - action. This will make the Manager class much smaller and much more - flexible. The current code will be consolidated into a single threaded - design with hooks to have the library process events and such. These - hooks will be called from the host application's main loop. + To solve these problems I am basically going to copy the design of my + Astxx manager library (written in c++) and make it more python like. + Each action will be a different object with certain methods to handle + various tasks, with one function in the actual Manager class to send the + action. This will make the Manager class much smaller and much more + flexible. The current code will be consolidated into a single threaded + design with hooks to have the library process events and such. These + hooks will be called from the host application's main loop. Upgrading from older versions diff --git a/asterisk/__init__.py b/asterisk/__init__.py index 847f0b2..510678b 100644 --- a/asterisk/__init__.py +++ b/asterisk/__init__.py @@ -11,4 +11,4 @@ manager - a module for interacting with the asterisk manager interface """ __all__ = ['agi', 'agitb', 'config', 'manager'] -__version__ = '0.4' +__version__ = '0.4.1' diff --git a/asterisk/agi.py b/asterisk/agi.py index 1ff97bd..8065cde 100644 --- a/asterisk/agi.py +++ b/asterisk/agi.py @@ -22,7 +22,6 @@ pyvr 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 @@ -131,7 +130,7 @@ class AGI: try: self.send_command(command, *args) return self.get_result() - except IOError, e: + except IOError as e: if e.errno == 32: # Broken Pipe * let us go raise AGISIGPIPEHangup("Received SIGPIPE") @@ -188,7 +187,7 @@ class AGI: raise AGIUnknownError(code, 'Unhandled code or undefined response') def _process_digit_list(self, digits): - if type(digits) == ListType: + if type(digits) is list: digits = ''.join(map(str, digits)) return self._quote(digits) diff --git a/asterisk/agitb.py b/asterisk/agitb.py index f1fa4d3..a712194 100644 --- a/asterisk/agitb.py +++ b/asterisk/agitb.py @@ -79,7 +79,7 @@ def scanvars(reader, frame, locals): return vars -def text((etype, evalue, etb), context=5): +def text(eparams, context=5): """Return a plain text document describing a given traceback.""" import os import types @@ -89,6 +89,7 @@ def text((etype, evalue, etb), context=5): import inspect import pydoc + etype, evalue, etb = eparams if isinstance(etype, types.ClassType): etype = etype.__name__ pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable diff --git a/asterisk/config.py b/asterisk/config.py index 4e28bd8..b86a9ae 100644 --- a/asterisk/config.py +++ b/asterisk/config.py @@ -11,11 +11,11 @@ This module provides parsing functionality for asterisk config files. # load and parse the config file try: config = asterisk.config.Config('/etc/asterisk/extensions.conf') - except asterisk.config.ParseError, (line, reason): - print "Parse Error line: %s: %s" % (line, reason) + except asterisk.config.ParseError as e: + print "Parse Error line: %s: %s" % (e.line, e.strerror) sys.exit(1) - except IOError, reason: - print "Error opening file: %s" % reason + except IOError as e: + print "Error opening file: %s" % e.strerror sys.exit(1) # print our parsed output diff --git a/asterisk/manager.py b/asterisk/manager.py index 2546931..8eefcb0 100644 --- a/asterisk/manager.py +++ b/asterisk/manager.py @@ -32,14 +32,14 @@ This module provides a Python API for interfacing with the asterisk manager. response = manager.status() manager.logoff() - except asterisk.manager.ManagerSocketException, (errno, reason): - print "Error connecting to the manager: %s" % reason + except asterisk.manager.ManagerSocketException as e: + print "Error connecting to the manager: %s" % e.strerror sys.exit(1) - except asterisk.manager.ManagerAuthException, reason: - print "Error logging in to the manager: %s" % reason + except asterisk.manager.ManagerAuthException as e: + print "Error logging in to the manager: %s" % e.strerror sys.exit(1) - except asterisk.manager.ManagerException, reason: - print "Error: %s" % reason + except asterisk.manager.ManagerException as e: + print "Error: %s" % e.strerror sys.exit(1) finally: @@ -56,9 +56,8 @@ import sys import os import socket import threading -import Queue +from six.moves import queue import re -from cStringIO import StringIO from types import * from time import sleep @@ -181,9 +180,9 @@ class Manager(object): self.hostname = socket.gethostname() # our queues - self._message_queue = Queue.Queue() - self._response_queue = Queue.Queue() - self._event_queue = Queue.Queue() + self._message_queue = queue.Queue() + self._response_queue = queue.Queue() + self._event_queue = queue.Queue() # callbacks for events self._event_callbacks = {} @@ -265,8 +264,8 @@ class Manager(object): try: self._sock.write(command) self._sock.flush() - except socket.error, (errno, reason): - raise ManagerSocketException(errno, reason) + except socket.error as e: + raise ManagerSocketException(e.errno, e.strerror) self._reswaiting.insert(0, 1) response = self._response_queue.get() @@ -410,7 +409,7 @@ class Manager(object): elif message.has_header('Response'): self._response_queue.put(message) else: - print 'No clue what we got\n%s' % message.data + print('No clue what we got\n%s' % message.data) finally: # wait for our data receiving thread to exit t.join() @@ -445,7 +444,7 @@ class Manager(object): raise ManagerException('Already connected to manager') # make sure host is a string - assert type(host) in StringTypes + assert type(host) is str port = int(port) # make sure port is an int @@ -455,8 +454,8 @@ class Manager(object): _sock.connect((host, port)) self._sock = _sock.makefile() _sock.close() - except socket.error, (errno, reason): - raise ManagerSocketException(errno, reason) + except socket.error as e: + raise ManagerSocketException(e.errno, e.strerror) # we are connected and running self._connected.set() diff --git a/examples/show_channels.py b/examples/show_channels.py index c769d6d..b562f52 100644 --- a/examples/show_channels.py +++ b/examples/show_channels.py @@ -14,20 +14,20 @@ try: # get a status report response = manager.status() - print response + print(response) response = manager.command('core show channels concise') - print response.data + print(response.data) manager.logoff() - except asterisk.manager.ManagerSocketException, (errno, reason): - print "Error connecting to the manager: %s" % reason + except asterisk.manager.ManagerSocketException as e: + print "Error connecting to the manager: %s" % e.strerror sys.exit(1) - except asterisk.manager.ManagerAuthException, reason: - print "Error logging in to the manager: %s" % reason + except asterisk.manager.ManagerAuthException as e: + print "Error logging in to the manager: %s" % e.strerror sys.exit(1) - except asterisk.manager.ManagerException, reason: - print "Error: %s" % reason + except asterisk.manager.ManagerException as e: + print "Error: %s" % e.strerror sys.exit(1) finally: diff --git a/setup.py b/setup.py index 8401acc..46cae39 100755 --- a/setup.py +++ b/setup.py @@ -41,6 +41,10 @@ setup( 'Programming Language :: Python :: 2.5', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.2', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', 'Topic :: Communications :: Internet Phone', 'Topic :: Communications :: Telephony', 'Topic :: Software Development :: Libraries :: Python Modules'