Skip to content

Commit

Permalink
minor rewrite for Python 3 support. Some other fixes in corresponding…
Browse files Browse the repository at this point in the history
… files.
  • Loading branch information
eill committed Oct 8, 2014
1 parent 6bd0cc9 commit 5efe3f4
Show file tree
Hide file tree
Showing 11 changed files with 124 additions and 85 deletions.
10 changes: 8 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Temporary files.
*.pyc
*.swp
*.py[cod]
*.sw?
*~
.coverage

Expand All @@ -10,5 +10,11 @@ build
_build
*.egg-info

# Python-related stuff
env/
.env/
venv/
__pycache__/

# Auto-generated files.
MANIFEST
30 changes: 24 additions & 6 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
2014-10-08 Timur Tuchkovenko <[email protected]>
* UPGRADE: initial Python 3 support. Now pyst2 requires
Python 'six' module. Some minor changes in other files.

2014-09-14 Sp1tF1r3 <https://github.com/Sp1tF1r3>
* asterisk/manager.py: added action 'Reload' for Asterisk Manager
Interface (AMI).

2013-12-03 Ludovic Gasc <[email protected]>
* 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 <[email protected]>
* 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 <[email protected]>
* PEP8 Fixes
Expand All @@ -8,18 +26,18 @@

2007-01-26 Matthew Nicholson <[email protected]>

* 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 <[email protected]>

* asterisk/manager.py: Fix support for Manager.command(). Patch from
Karl Putland <[email protected]>.
* asterisk/manager.py: Fix support for Manager.command(). Patch from
Karl Putland <[email protected]>.

2007-01-02 Matthew Nicholson <[email protected]>

* asterisk/agi.py (AGI.set_autohangup): Fixed syntax error.
* asterisk/agi.py (AGI.set_autohangup): Fixed syntax error.

2006-11-28 Matthew Nicholson <[email protected]>

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ VERSION=$(VERSIONPY)
LASTRELEASE:=$(shell ../svntools/lastrelease -n)

USERNAME=schlatterbeck
PROJECT=pyst
PROJECT=pyst2
PACKAGE=${PROJECT}
CHANGES=changes
NOTES=notes
Expand Down
96 changes: 54 additions & 42 deletions README.rst
Original file line number Diff line number Diff line change
@@ -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: [email protected], 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::

Expand All @@ -35,33 +57,23 @@ 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: [email protected], 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
---------------------

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.
Expand All @@ -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.

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.
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.

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
Expand Down
2 changes: 1 addition & 1 deletion asterisk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@
"""

__all__ = ['agi', 'agitb', 'config', 'manager']
__version__ = '0.4'
__version__ = '0.4.1'
5 changes: 2 additions & 3 deletions asterisk/agi.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
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
Expand Down Expand Up @@ -131,7 +130,7 @@ def execute(self, command, *args):
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")
Expand Down Expand Up @@ -188,7 +187,7 @@ def get_result(self, stdin=sys.stdin):
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)

Expand Down
3 changes: 2 additions & 1 deletion asterisk/agitb.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
8 changes: 4 additions & 4 deletions asterisk/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
# 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
Expand Down
33 changes: 16 additions & 17 deletions asterisk/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ def handle_event(event, 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:
Expand All @@ -56,9 +56,8 @@ def handle_event(event, manager):
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

Expand Down Expand Up @@ -181,9 +180,9 @@ def __init__(self):
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 = {}
Expand Down Expand Up @@ -265,8 +264,8 @@ def send_action(self, cdict={}, **kwargs):
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()
Expand Down Expand Up @@ -410,7 +409,7 @@ def message_loop(self):
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()
Expand Down Expand Up @@ -445,7 +444,7 @@ def connect(self, host, port=5038):
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

Expand All @@ -455,8 +454,8 @@ def connect(self, host, port=5038):
_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()
Expand Down
16 changes: 8 additions & 8 deletions examples/show_channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@

# 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:
Expand Down
Loading

0 comments on commit 5efe3f4

Please sign in to comment.