Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python 3 #12

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/workflows/pythontest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: Python Test

on:
push:
branches:
- '**'
pull_request:
branches: [ master ]

jobs:
build:

runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.5, 3.6, 3.7, 3.8]

steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e git+https://github.com/DomAmato/smpp.pdu.git@master#egg=smpp.pdu
pip install -r requirements.txt
pip install service_identity
- name: Lint
run: |
pip install pylint
pylint -rn --errors-only ./smpp
- name: Test
env:
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
run: |
pip install coveralls mock
coverage run --source=smpp -m twisted.trial tests
coveralls
11 changes: 0 additions & 11 deletions .travis.yml

This file was deleted.

2 changes: 1 addition & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1 +1 @@
include README.markdown
include README.md
7 changes: 6 additions & 1 deletion README.markdown → README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# smpp.twisted

[![Test](https://github.com/DomAmato/smpp.twisted/workflows/Python%20Test/badge.svg)](https://github.com/DomAmato/smpp.twisted/actions)
[![Coverage Status](https://coveralls.io/repos/github/DomAmato/smpp.twisted/badge.svg?branch=master)](https://coveralls.io/github/DomAmato/smpp.twisted?branch=master)

SMPP 3.4 client built on Twisted

http://www.nowsms.com/discus/messages/1/24856.html
Expand All @@ -9,7 +14,7 @@ Example
from smpp.twisted.client import SMPPClientTransceiver, SMPPClientService
from smpp.twisted.config import SMPPClientConfig

class SMPP(object):
class SMPP:

def __init__(self, config=None):
if config is None:
Expand Down
1 change: 0 additions & 1 deletion dev_requirements.txt

This file was deleted.

File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from smpp.twisted.client import SMPPClientTransceiver, SMPPClientService
from smpp.twisted.config import SMPPClientConfig

class SMPP(object):
class SMPP:

def __init__(self, config=None):
if config is None:
Expand Down
7 changes: 4 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
twisted
enum
pyOpenSSL
Twisted~=20.3.0
pyOpenSSL~=19.1.0
# cant install from other projects
# smpp.pdu @ git+https://github.com/DomAmato/smpp.pdu.git@master
smpp.pdu
25 changes: 14 additions & 11 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,33 @@
import os
from setuptools import setup, find_packages

def parse_requirements(filename):
"""load requirements from a pip requirements file"""
lineiter = (line.strip() for line in open(filename))
return [line for line in lineiter if line and (not line.startswith("#") and not line.startswith('-'))]

def read(fname):
return open(os.path.join(os.path.dirname(__file__), fname)).read()

from setuptools import setup, find_packages
setup(
name = "smpp.twisted",
version = "0.4",
author = "Roger Hoover",
author_email = "roger.hoover@gmail.com",
description = "SMPP 3.4 client built on Twisted",
license = 'Apache License 2.0',
packages = find_packages(),
long_description=read('README.markdown'),
packages = find_packages(exclude=["tests"]),
long_description=read('README.md'),
keywords = "smpp twisted",
url = "https://github.com/mozes/smpp.twisted",
py_modules=["smpp.twisted"],
include_package_data = True,
package_data={'smpp.twisted': ['README.markdown']},
package_data={'smpp.twisted': ['README.md']},
zip_safe = False,
install_requires = [
'twisted',
'enum',
'pyOpenSSL',
'smpp.pdu',
],
install_requires = parse_requirements('requirements.txt'),
tests_require = [
'mock',
],
test_suite = 'smpp.twisted.tests',
classifiers=[
"Development Status :: 5 - Production/Stable",
"Framework :: Twisted",
Expand All @@ -38,6 +36,11 @@ def read(fname):
"License :: OSI Approved :: Apache Software License",
"Intended Audience :: Developers",
"Programming Language :: Python",
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
"Topic :: Software Development :: Libraries :: Python Modules",
],
)
Expand Down
2 changes: 1 addition & 1 deletion smpp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
See the License for the specific language governing permissions and
limitations under the License.
"""
__import__('pkg_resources').declare_namespace(__name__)
__path__ = __import__('pkgutil').extend_path(__path__, __name__)
49 changes: 26 additions & 23 deletions smpp/twisted/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from OpenSSL import SSL
from twisted.internet.protocol import ClientFactory
from twisted.internet import defer, reactor, ssl
from twisted.application import service
from twisted.application.service import Service
from smpp.twisted.protocol import SMPPClientProtocol, DataHandlerResponse

LOG_CATEGORY="smpp.twisted.client"
Expand All @@ -30,16 +30,17 @@ def __init__(self, config):
self.config = config
self.buildProtocolDeferred = defer.Deferred()
self.log = logging.getLogger(LOG_CATEGORY)

def getConfig(self):
return self.config

def buildProtocol(self, addr):
p = ClientFactory.buildProtocol(self, addr)
#This is a sneaky way of passing the protocol instance back to the caller
#pylint: disable=no-member
reactor.callLater(0, self.buildProtocolDeferred.callback, p)
return p

def clientConnectionFailed(self, connector, reason):
"""Connection failed
"""
Expand All @@ -50,17 +51,17 @@ class CtxFactory(ssl.ClientContextFactory):

def __init__(self, config):
self.smppConfig = config

def getContext(self):
self.method = SSL.SSLv23_METHOD
ctx = ssl.ClientContextFactory.getContext(self)
if self.smppConfig.SSLCertificateFile:
ctx.use_certificate_file(self.smppConfig.SSLCertificateFile)
return ctx

class SMPPClientBase(object):
class SMPPClientBase:
msgHandler = None

def __init__(self, config):
self.config = config
self.log = logging.getLogger(LOG_CATEGORY)
Expand All @@ -71,44 +72,46 @@ def connect(self):
factory = SMPPClientFactory(self.config)
if self.config.useSSL:
self.log.warning('Establishing SSL connection to %s:%d' % (self.config.host, self.config.port))
#pylint: disable=no-member
reactor.connectSSL(self.config.host, self.config.port, factory, CtxFactory(self.config))
else:
self.log.warning('Establishing TCP connection to %s:%d' % (self.config.host, self.config.port))
reactor.connectTCP(self.config.host, self.config.port, factory)
#pylint: disable=no-member
reactor.connectTCP(self.config.host, self.config.port, factory)
return factory.buildProtocolDeferred.addCallback(self.onConnect)

def onConnect(self, smpp):
self.smpp = smpp
if self.msgHandler is not None:
smpp.setDataRequestHandler(self.msgHandler)
return smpp

def connectAndBind(self):
self.bindDeferred = defer.Deferred()
self.connect().addCallback(self.doBind).addErrback(self.bindDeferred.errback)
return self.bindDeferred

def doBind(self, smpp):
self.bind(smpp).addCallback(self.bound).addErrback(self.bindFailed, smpp)
return smpp

def bind(self, smpp):
raise NotImplementedError()

#If bind fails, don't errback until we're disconnected
def bindFailed(self, error, smpp):
smpp.getDisconnectedDeferred().addCallback(lambda result: self.bindDeferred.errback(error))

def bound(self, result):
self.bindDeferred.callback(result.smpp)

class SMPPClientTransmitter(SMPPClientBase):

def bind(self, smpp):
return smpp.bindAsTransmitter()

class SMPPClientReceiver(SMPPClientBase):

def __init__(self, config, msgHandler):
SMPPClientBase.__init__(self, config)
self.msgHandler = msgHandler
Expand All @@ -123,31 +126,31 @@ def bind(self, smpp):

#TODO - move this to mozes code base since
# the service support in Twisted is so crappy
class SMPPClientService(service.Service):
class SMPPClientService(Service):

def __init__(self, smppClient):
self.client = smppClient
self.stopDeferred = defer.Deferred()
self.log = logging.getLogger(LOG_CATEGORY)

def getStopDeferred(self):
return self.stopDeferred

@defer.inlineCallbacks
def startService(self):
service.Service.startService(self)
Service.startService(self)
bindDeferred = self.client.connectAndBind()
bindDeferred.addErrback(self.handleStartError)
smpp = yield bindDeferred
smpp.getDisconnectedDeferred().chainDeferred(self.stopDeferred)
defer.returnValue(smpp)

def handleStartError(self, error):
self.stopDeferred.errback(error)
return error

def stopService(self):
service.Service.stopService(self)
Service.stopService(self)
if self.client.smpp:
self.log.info("Stopping SMPP Client")
return self.client.smpp.unbindAndDisconnect()
Expand Down
17 changes: 8 additions & 9 deletions smpp/twisted/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,33 @@
See the License for the specific language governing permissions and
limitations under the License.
"""
class SMPPConfig(object):


class SMPPConfig:

def __init__(self, **kwargs):
self.sessionInitTimerSecs = kwargs.get('sessionInitTimerSecs', 30)
self.enquireLinkTimerSecs = kwargs.get('enquireLinkTimerSecs', 10)
self.inactivityTimerSecs = kwargs.get('inactivityTimerSecs', 120)
self.responseTimerSecs = kwargs.get('responseTimerSecs', 60)
self.pduReadTimerSecs = kwargs.get('pduReadTimerSecs', 10)


class SMPPClientConfig(SMPPConfig):

def __init__(self, **kwargs):
super(SMPPClientConfig, self).__init__(**kwargs)
self.port = kwargs['port']
self.host = kwargs['host']
self.port = kwargs['port']
self.username = kwargs['username']
self.password = kwargs['password']
self.systemType = kwargs.get('systemType', '')
self.useSSL = kwargs.get('useSSL', False)
self.SSLCertificateFile = kwargs.get('SSLCertificateFile', None)
self.addressRange = kwargs.get('addressRange', None)
self.addressTon = kwargs.get('addressTon', None)
self.addressNpi = kwargs.get('addressNpi', None)
self.addressNpi = kwargs.get('addressNpi', None)

class SMPPServerConfig(SMPPConfig):

def __init__(self, **kwargs):
"""
@param systems: A dict of data representing the available
Expand All @@ -50,5 +50,4 @@ def __init__(self, **kwargs):
"""
super(SMPPServerConfig, self).__init__(**kwargs)
self.systems = kwargs.get('systems', {})
self.msgHandler = kwargs['msgHandler']

self.msgHandler = kwargs['msgHandler']
Loading