Clean and get setup.py working once and for all.

Fixes:
    README.rst now included
    Double line spacing removed from long_description
    Source package now includes tests, examples, etc using Manifest.in
    README.rst typos fixed
    Added README.rst section on installing dnspython for Python3
    Version bumped to RC2
    Version is now taken from sleekxmpp.version.__version__ without
        having to pull in the entire library
    Added 'test' command for setup.py
    Simplified testall.py
    Docs build cleanly from source package after installation
This commit is contained in:
Lance Stout 2011-08-24 21:54:36 -07:00
parent 2a80824076
commit ede59ab40e
8 changed files with 130 additions and 81 deletions

6
MANIFEST.in Normal file
View file

@ -0,0 +1,6 @@
include README.rst
include LICENSE
include testall.py
recursive-include docs Makefile *.bat *.py *.rst *.css *.ttf *.png
recursive-include examples *.py
recursive-include tests *.py

View file

@ -34,7 +34,8 @@ SleekXMPP's design goals and philosphy are:
Get the Code Get the Code
------------ ------------
.. code-block:: sh
Get the latest stable version from PyPI::
pip install sleekxmpp pip install sleekxmpp
@ -54,6 +55,15 @@ The latest source code for SleekXMPP may be found on `Github
**Develop Releases** **Develop Releases**
- `Latest Develop Version <http://github.com/fritzy/SleekXMPP/zipball/develop>`_ - `Latest Develop Version <http://github.com/fritzy/SleekXMPP/zipball/develop>`_
Installing DNSPython
---------------------
If you are using Python3 and wish to use dnspython, you will have to checkout and
install the ``python3`` branch::
git clone http://github.com/rthalley/dnspython
cd dnspython
git checkout python3
python3 setup.py install
Discussion Discussion
---------- ----------
@ -68,7 +78,6 @@ help with SleekXMPP.
Documentation and Testing Documentation and Testing
------------------------- -------------------------
Documentation can be found both inline in the code, and as a Sphinx project in ``/docs``. Documentation can be found both inline in the code, and as a Sphinx project in ``/docs``.
To generate the Sphinx documentation, follow the commands below. The HTML output will To generate the Sphinx documentation, follow the commands below. The HTML output will
be in ``docs/_build/html``:: be in ``docs/_build/html``::
@ -84,7 +93,6 @@ To run the test suite for SleekXMPP::
The SleekXMPP Boilerplate The SleekXMPP Boilerplate
------------------------- -------------------------
Projects using SleekXMPP tend to follow a basic pattern for setting up client/component Projects using SleekXMPP tend to follow a basic pattern for setting up client/component
connections and configuration. Here is the gist of the boilerplate needed for a SleekXMPP connections and configuration. Here is the gist of the boilerplate needed for a SleekXMPP
based project. See the documetation or examples directory for more detailed archetypes for based project. See the documetation or examples directory for more detailed archetypes for
@ -136,8 +144,10 @@ SleekXMPP projects::
xmpp.register_plugin('xep_0199') # XMPP Ping xmpp.register_plugin('xep_0199') # XMPP Ping
# If you are working with an OpenFire server, you will need # If you are working with an OpenFire server, you will need
# to useuterborg Larsson version: # to use a different SSL version:
# xmppissl_version = ssl.PROTOCOL_SSLv3 #
# import ssl
# xmpp.ssl_version = ssl.PROTOCOL_SSLv3
if xmpp.connect(): if xmpp.connect():
xmpp.process(block=True) xmpp.process(block=True)

View file

@ -4,8 +4,6 @@ clientxmpp
.. module:: sleekxmpp.clientxmpp .. module:: sleekxmpp.clientxmpp
.. autodata:: SRV_SUPPORT
.. autoclass:: ClientXMPP .. autoclass:: ClientXMPP
.. automethod:: connect .. automethod:: connect

21
setup.py Normal file → Executable file
View file

@ -4,16 +4,15 @@
# Copyright (C) 2007-2011 Nathanael C. Fritz # Copyright (C) 2007-2011 Nathanael C. Fritz
# All Rights Reserved # All Rights Reserved
# #
# This software is licensed as described in the README file, # This software is licensed as described in the README.rst and LICENSE
# which you should have received as part of this distribution. # file, which you should have received as part of this distribution.
#
# from ez_setup import use_setuptools
from distutils.core import setup
import sys import sys
from distutils.core import setup, Command
# from ez_setup import use_setuptools
import sleekxmpp from testall import TestCommand
from sleekxmpp.version import __version__
# if 'cygwin' in sys.platform.lower(): # if 'cygwin' in sys.platform.lower():
# min_version = '0.6c6' # min_version = '0.6c6'
# else: # else:
@ -27,10 +26,10 @@ import sleekxmpp
# #
# from setuptools import setup, find_packages, Extension, Feature # from setuptools import setup, find_packages, Extension, Feature
VERSION = sleekxmpp.__version__ VERSION = __version__
DESCRIPTION = 'SleekXMPP is an elegant Python library for XMPP (aka Jabber, Google Talk, etc).' DESCRIPTION = 'SleekXMPP is an elegant Python library for XMPP (aka Jabber, Google Talk, etc).'
with open('README.rst') as readme: with open('README.rst') as readme:
LONG_DESCRIPTION = '\n'.join(readme) LONG_DESCRIPTION = ''.join(readme)
CLASSIFIERS = [ 'Intended Audience :: Developers', CLASSIFIERS = [ 'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License', 'License :: OSI Approved :: MIT License',
@ -93,5 +92,7 @@ setup(
license = 'MIT', license = 'MIT',
platforms = [ 'any' ], platforms = [ 'any' ],
packages = packages, packages = packages,
requires = [ 'tlslite', 'pythondns' ], requires = [ 'dnspython' ],
classifiers = CLASSIFIERS,
cmdclass = {'test': TestCommand}
) )

View file

@ -15,5 +15,4 @@ from sleekxmpp.xmlstream import XMLStream, RestartStream
from sleekxmpp.xmlstream.matcher import * from sleekxmpp.xmlstream.matcher import *
from sleekxmpp.xmlstream.stanzabase import StanzaBase, ET from sleekxmpp.xmlstream.stanzabase import StanzaBase, ET
__version__ = '1.0rc1' from sleekxmpp.version import __version__, __version_info__
__version_info__ = (1, 0, 0, 'rc1', 0)

13
sleekxmpp/version.py Normal file
View file

@ -0,0 +1,13 @@
"""
SleekXMPP: The Sleek XMPP Library
Copyright (C) 2010 Nathanael C. Fritz
This file is part of SleekXMPP.
See the file LICENSE for copying permission.
"""
# We don't want to have to import the entire library
# just to get the version info for setup.py
__version__ = '1.0rc2'
__version_info__ = (1, 0, 0, 'rc2', 0)

117
testall.py Normal file → Executable file
View file

@ -1,70 +1,63 @@
#!/usr/bin/env python #!/usr/bin/env python
import unittest
import logging
import sys
import os import os
import sys
import logging
import unittest
import distutils.core
class testoverall(unittest.TestCase): from glob import glob
from os.path import splitext, basename, join as pjoin, walk
def testModules(self):
"""Testing all modules by compiling them"""
import compileall
import re
if sys.version_info < (3,0):
self.failUnless(compileall.compile_dir('.' + os.sep + 'sleekxmpp', rx=re.compile('/[.]svn'), quiet=True))
else:
self.failUnless(compileall.compile_dir('.' + os.sep + 'sleekxmpp', rx=re.compile('/[.]svn|.*26.*'), quiet=True))
def testTabNanny(self): def run_tests():
"""Invoking the tabnanny""" """
import tabnanny Find and run all tests in the tests/ directory.
self.failIf(tabnanny.check("." + os.sep + 'sleekxmpp'))
#raise "Help!" Excludes live tests (tests/live_*).
"""
testfiles = ['tests.test_overall']
exclude = ['__init__.py', 'test_overall.py']
for t in glob(pjoin('.', 'tests', '*.py')):
if True not in [t.endswith(ex) for ex in exclude]:
if basename(t).startswith('test_'):
testfiles.append('tests.%s' % splitext(basename(t))[0])
suites = []
for file in testfiles:
__import__(file)
suites.append(sys.modules[file].suite)
tests = unittest.TestSuite(suites)
runner = unittest.TextTestRunner(verbosity=2)
# Disable logging output
logging.basicConfig(level=100)
logging.disable(100)
result = runner.run(tests)
return result
# Add a 'test' command for setup.py
class TestCommand(distutils.core.Command):
user_options = [ ]
def initialize_options(self):
self._dir = os.getcwd()
def finalize_options(self):
pass
def run(self):
run_tests()
def disabled_testMethodLength(self):
"""Testing for excessive method lengths"""
import re
dirs = os.walk(sys.path[0] + os.sep + 'sleekxmpp')
offenders = []
for d in dirs:
if not '.svn' in d[0]:
for filename in d[2]:
if filename.endswith('.py') and d[0].find("template%stemplates" % os.sep) == -1:
with open("%s%s%s" % (d[0],os.sep,filename), "r") as fp:
cur = None
methodline = lineno = methodlen = methodindent = 0
for line in fp:
indentlevel = re.compile("^[\t ]*").search(line).end()
line = line.expandtabs()
lineno += 1
if line.strip().startswith("def ") or line.strip().startswith("except") or (line.strip() and methodindent > indentlevel) or (line.strip() and methodindent == indentlevel): #new method found or old one ended
if cur: #existing method needs final evaluation
if methodlen > 50 and not cur.strip().startswith("def setupUi"):
offenders.append("Method '%s' on line %s of %s/%s is longer than 50 lines (%s)" % (cur.strip(),methodline,d[0][len(rootp):],filename,methodlen))
methodlen = 0
cur = line
methodindent = indentlevel
methodline = lineno
if line and cur and not line.strip().startswith("#") and not (cur.strip().startswith("try:") and methodindent == 0): #if we weren't all whitespace and weren't a comment
methodlen += 1
self.failIf(offenders,"\n".join(offenders))
if __name__ == '__main__': if __name__ == '__main__':
logging.basicConfig(level=100) result = run_tests()
logging.disable(100) print("<tests %s ran='%s' errors='%s' fails='%s' success='%s' />" % (
#this doesn't need to be very clean "xmlns='http//andyet.net/protocol/tests'",
alltests = [unittest.TestLoader().loadTestsFromTestCase(testoverall)] result.testsRun, len(result.errors),
rootp = sys.path[0] + os.sep + 'tests' len(result.failures), result.wasSuccessful()))
dirs = os.walk(rootp)
for d in dirs:
if not '.svn' in d[0]:
for filename in d[2]:
if filename.startswith('test_') and filename.endswith('.py'):
modname = ('tests' + "." + filename)[:-3].replace(os.sep,'.')
__import__(modname)
#sys.modules[modname].config = moduleconfig
alltests.append(sys.modules[modname].suite)
alltests_suite = unittest.TestSuite(alltests)
result = unittest.TextTestRunner(verbosity=2).run(alltests_suite)
print("""<tests xmlns='http://andyet.net/protocol/tests' ran='%s' errors='%s' fails='%s' success='%s' />""" % (result.testsRun, len(result.errors), len(result.failures), result.wasSuccessful()))

29
tests/test_overall.py Normal file
View file

@ -0,0 +1,29 @@
import os
import re
import sys
import unittest
import tabnanny
import compileall
class TestOverall(unittest.TestCase):
"""
Test overall package health by compiling and checking
code style.
"""
def testModules(self):
"""Testing all modules by compiling them"""
src = '..%ssleekxmpp' % os.sep
if sys.version_info < (3, 0):
rx = re.compile('/[.]svn')
else:
rx = re.compile('/[.]svn|.*26.*')
self.failUnless(compileall.compile_dir(src, rx=rx, quiet=True))
def testTabNanny(self):
"""Testing that indentation is consistent"""
self.failIf(tabnanny.check('..%ssleekxmpp' % os.sep))
suite = unittest.TestLoader().loadTestsFromTestCase(TestOverall)