Merge lp:~barry/lazr.smtptest/lp1096475 into lp:lazr.smtptest

Proposed by Barry Warsaw
Status: Merged
Merged at revision: 64
Proposed branch: lp:~barry/lazr.smtptest/lp1096475
Merge into: lp:lazr.smtptest
Diff against target: 2051 lines (+780/-881)
28 files modified
HACKING.rst (+17/-3)
MANIFEST.in (+2/-3)
README.rst (+3/-3)
_bootstrap/COPYRIGHT.txt (+0/-9)
_bootstrap/LICENSE.txt (+0/-54)
_bootstrap/bootstrap.py (+0/-77)
buildout-templates/bin/lint.sh.in (+0/-4)
buildout.cfg (+0/-47)
distribute_setup.py (+546/-0)
ez_setup.py (+0/-241)
lazr/__init__.py (+12/-8)
lazr/smtptest/NEWS.rst (+10/-0)
lazr/smtptest/README.rst (+1/-1)
lazr/smtptest/README_fixture.py (+27/-0)
lazr/smtptest/__init__.py (+1/-1)
lazr/smtptest/controller.py (+9/-3)
lazr/smtptest/docs/fixture.py (+34/-0)
lazr/smtptest/docs/queue.rst (+14/-9)
lazr/smtptest/docs/queue_fixture.py (+27/-0)
lazr/smtptest/docs/usage.rst (+17/-11)
lazr/smtptest/docs/usage_fixture.py (+27/-0)
lazr/smtptest/server.py (+10/-7)
lazr/smtptest/tests/__init__.py (+0/-16)
lazr/smtptest/version.txt (+1/-1)
pylint.rc (+0/-310)
setup.cfg (+8/-0)
setup.py (+14/-21)
src/lazr/smtptest/tests/test_docs.py (+0/-52)
To merge this branch: bzr merge lp:~barry/lazr.smtptest/lp1096475
Reviewer Review Type Date Requested Status
Curtis Hovey (community) code Approve
Gary Poster Pending
Review via email: mp+142024@code.launchpad.net

Description of the change

Ported to Python 3. This should now work on 3.3, 3.2, 2.7, and 2.6

I did a bunch of other cleanups, which may or may not be controversial, but makes things much simpler for me.

* Removed the dependency on zc.buildout. I didn't really feel this was buying us much and more standard Python tools like virtualenv and distribute do just fine.

* Moved the lazr directory up one. `src` wasn't buying us much.

* Ported the test suite to nosetests. See HACKING.rst for details.

* Ported to distribute.

* Yes, renamed all documentation to .rst files for better editor support (i.e. rst-mode)

* Updated copyright years.

* Got rid of pylint. Too many false positives to be useful (should be pretty pyflakes clean though).

* Under Python 3.3, use PEP 420 style namespace package for `lazr`.

To post a comment you must log in.
Revision history for this message
Barry Warsaw (barry) wrote :

Oh yeah, bumped the version number to 2.0

I'll happily do a PyPI release once this lands.

lp:~barry/lazr.smtptest/lp1096475 updated
72. By Barry Warsaw

Update the manifest.

Revision history for this message
Curtis Hovey (sinzui) wrote :

Thank you Barry.

This looks good for merge and release.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== renamed file 'HACKING.txt' => 'HACKING.rst'
2--- HACKING.txt 2009-06-22 22:40:16 +0000
3+++ HACKING.rst 2013-01-07 01:00:29 +0000
4@@ -13,8 +13,6 @@
5 You should have received a copy of the GNU Lesser General Public License
6 along with lazr.smtptest. If not, see <http://www.gnu.org/licenses/>.
7
8-This project uses zc.buildout for development.
9-
10 ============
11 Introduction
12 ============
13@@ -26,7 +24,7 @@
14
15
16 Getting help
17-------------
18+============
19
20 If you find bugs in this package, you can report them here:
21
22@@ -39,3 +37,19 @@
23 or send a message to:
24
25 lazr-users@lists.launchpad.net
26+
27+
28+Running the tests
29+=================
30+
31+The tests suite requires nose_ and is compatible with both Python 2 and
32+Python 3. To run the full test suite::
33+
34+ $ python setup.py nosetests
35+
36+Where ``python`` is the Python executable to use for the tests. E.g. this
37+might be ``python3`` for Python 3, or the Python executable from a
38+virtualenv_.
39+
40+.. _nose: https://nose.readthedocs.org/en/latest/
41+.. _virtualenv: http://www.virtualenv.org/en/latest/
42
43=== modified file 'MANIFEST.in'
44--- MANIFEST.in 2009-06-22 22:40:16 +0000
45+++ MANIFEST.in 2013-01-07 01:00:29 +0000
46@@ -1,4 +1,3 @@
47 include *.py *.rc *.txt
48-recursive-include src *.txt
49-exclude MANIFEST.in buildout.cfg bootstrap.py .bzrignore
50-prune _bootstrap
51+recursive-include *.txt
52+exclude MANIFEST.in .bzrignore
53
54=== renamed file 'README.txt' => 'README.rst'
55--- README.txt 2009-06-23 00:27:13 +0000
56+++ README.rst 2013-01-07 01:00:29 +0000
57@@ -7,9 +7,9 @@
58 under the terms of the GNU Lesser General Public License as published by
59 the Free Software Foundation, version 3 of the License.
60
61- lazr.smtptest is distributed in the hope that it will be useful, but WITHOUT
62- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
63- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
64+ lazr.smtptest is distributed in the hope that it will be useful, but
65+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
66+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
67 License for more details.
68
69 You should have received a copy of the GNU Lesser General Public License
70
71=== removed directory '_bootstrap'
72=== removed file '_bootstrap/COPYRIGHT.txt'
73--- _bootstrap/COPYRIGHT.txt 2009-03-23 19:12:50 +0000
74+++ _bootstrap/COPYRIGHT.txt 1970-01-01 00:00:00 +0000
75@@ -1,9 +0,0 @@
76-Copyright (c) 2004-2009 Zope Corporation and Contributors.
77-All Rights Reserved.
78-
79-This software is subject to the provisions of the Zope Public License,
80-Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
81-THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
82-WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
83-WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
84-FOR A PARTICULAR PURPOSE.
85
86=== removed file '_bootstrap/LICENSE.txt'
87--- _bootstrap/LICENSE.txt 2009-03-23 19:12:50 +0000
88+++ _bootstrap/LICENSE.txt 1970-01-01 00:00:00 +0000
89@@ -1,54 +0,0 @@
90-Zope Public License (ZPL) Version 2.1
91--------------------------------------
92-
93-A copyright notice accompanies this license document that
94-identifies the copyright holders.
95-
96-This license has been certified as open source. It has also
97-been designated as GPL compatible by the Free Software
98-Foundation (FSF).
99-
100-Redistribution and use in source and binary forms, with or
101-without modification, are permitted provided that the
102-following conditions are met:
103-
104-1. Redistributions in source code must retain the
105- accompanying copyright notice, this list of conditions,
106- and the following disclaimer.
107-
108-2. Redistributions in binary form must reproduce the accompanying
109- copyright notice, this list of conditions, and the
110- following disclaimer in the documentation and/or other
111- materials provided with the distribution.
112-
113-3. Names of the copyright holders must not be used to
114- endorse or promote products derived from this software
115- without prior written permission from the copyright
116- holders.
117-
118-4. The right to distribute this software or to use it for
119- any purpose does not give you the right to use
120- Servicemarks (sm) or Trademarks (tm) of the copyright
121- holders. Use of them is covered by separate agreement
122- with the copyright holders.
123-
124-5. If any files are modified, you must cause the modified
125- files to carry prominent notices stating that you changed
126- the files and the date of any change.
127-
128-Disclaimer
129-
130- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS''
131- AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
132- NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
133- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
134- NO EVENT SHALL THE COPYRIGHT HOLDERS BE
135- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
136- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
137- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
138- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
139- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
140- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
141- OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
142- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
143- DAMAGE.
144\ No newline at end of file
145
146=== removed file '_bootstrap/bootstrap.py'
147--- _bootstrap/bootstrap.py 2009-03-23 19:12:50 +0000
148+++ _bootstrap/bootstrap.py 1970-01-01 00:00:00 +0000
149@@ -1,77 +0,0 @@
150-##############################################################################
151-#
152-# Copyright (c) 2006 Zope Corporation and Contributors.
153-# All Rights Reserved.
154-#
155-# This software is subject to the provisions of the Zope Public License,
156-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
157-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
158-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
159-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
160-# FOR A PARTICULAR PURPOSE.
161-#
162-##############################################################################
163-"""Bootstrap a buildout-based project
164-
165-Simply run this script in a directory containing a buildout.cfg.
166-The script accepts buildout command-line options, so you can
167-use the -c option to specify an alternate configuration file.
168-
169-$Id$
170-"""
171-
172-import os, shutil, sys, tempfile, urllib2
173-
174-tmpeggs = tempfile.mkdtemp()
175-
176-is_jython = sys.platform.startswith('java')
177-
178-try:
179- import pkg_resources
180-except ImportError:
181- ez = {}
182- exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
183- ).read() in ez
184- ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
185-
186- import pkg_resources
187-
188-if sys.platform == 'win32':
189- def quote(c):
190- if ' ' in c:
191- return '"%s"' % c # work around spawn lamosity on windows
192- else:
193- return c
194-else:
195- def quote (c):
196- return c
197-
198-cmd = 'from setuptools.command.easy_install import main; main()'
199-ws = pkg_resources.working_set
200-
201-if is_jython:
202- import subprocess
203-
204- assert subprocess.Popen([sys.executable] + ['-c', quote(cmd), '-mqNxd',
205- quote(tmpeggs), 'zc.buildout'],
206- env=dict(os.environ,
207- PYTHONPATH=
208- ws.find(pkg_resources.Requirement.parse('setuptools')).location
209- ),
210- ).wait() == 0
211-
212-else:
213- assert os.spawnle(
214- os.P_WAIT, sys.executable, quote (sys.executable),
215- '-c', quote (cmd), '-mqNxd', quote (tmpeggs), 'zc.buildout',
216- dict(os.environ,
217- PYTHONPATH=
218- ws.find(pkg_resources.Requirement.parse('setuptools')).location
219- ),
220- ) == 0
221-
222-ws.add_entry(tmpeggs)
223-ws.require('zc.buildout')
224-import zc.buildout.buildout
225-zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
226-shutil.rmtree(tmpeggs)
227
228=== removed symlink 'bootstrap.py'
229=== target was u'_bootstrap/bootstrap.py'
230=== removed directory 'buildout-templates'
231=== removed directory 'buildout-templates/bin'
232=== removed file 'buildout-templates/bin/lint.sh.in'
233--- buildout-templates/bin/lint.sh.in 2009-06-22 22:40:16 +0000
234+++ buildout-templates/bin/lint.sh.in 1970-01-01 00:00:00 +0000
235@@ -1,4 +0,0 @@
236-#! /bin/bash
237-
238-export PYTHONPATH=${os-paths}
239-bin/pylint ${package} --rcfile=pylint.rc
240
241=== removed file 'buildout.cfg'
242--- buildout.cfg 2009-06-22 22:40:16 +0000
243+++ buildout.cfg 1970-01-01 00:00:00 +0000
244@@ -1,47 +0,0 @@
245-[buildout]
246-parts =
247- interpreter
248- test
249- docs
250- tags
251- filetemplates
252- pylint
253-unzip = true
254-
255-develop = .
256-
257-[test]
258-recipe = zc.recipe.testrunner
259-eggs = lazr.smtptest
260-defaults = '--tests-pattern ^tests --exit-with-status --suite-name additional_tests'.split()
261-
262-[docs]
263-recipe = z3c.recipe.sphinxdoc
264-eggs = lazr.smtptest [docs]
265-index-doc = README
266-default.css =
267-layout.html =
268-
269-[interpreter]
270-recipe = zc.recipe.egg
271-interpreter = py
272-eggs = lazr.smtptest
273- docutils
274-
275-[tags]
276-recipe = z3c.recipe.tag:tags
277-eggs = lazr.smtptest
278-
279-[filetemplates]
280-recipe = z3c.recipe.filetemplate
281-source-directory = buildout-templates
282-package = lazr.smtptest
283-eggs = lazr.smtptest
284-
285-[pylint]
286-recipe = zc.recipe.egg
287-eggs =
288- logilab.pylintinstaller
289- pylint==0.15.2
290-entry-points = pylint=pylint.lint:Run
291-arguments = sys.argv[1:]
292
293=== added file 'distribute_setup.py'
294--- distribute_setup.py 1970-01-01 00:00:00 +0000
295+++ distribute_setup.py 2013-01-07 01:00:29 +0000
296@@ -0,0 +1,546 @@
297+#!python
298+"""Bootstrap distribute installation
299+
300+If you want to use setuptools in your package's setup.py, just include this
301+file in the same directory with it, and add this to the top of your setup.py::
302+
303+ from distribute_setup import use_setuptools
304+ use_setuptools()
305+
306+If you want to require a specific version of setuptools, set a download
307+mirror, or use an alternate download directory, you can do so by supplying
308+the appropriate options to ``use_setuptools()``.
309+
310+This file can also be run as a script to install or upgrade setuptools.
311+"""
312+import os
313+import shutil
314+import sys
315+import time
316+import fnmatch
317+import tempfile
318+import tarfile
319+import optparse
320+
321+from distutils import log
322+
323+try:
324+ from site import USER_SITE
325+except ImportError:
326+ USER_SITE = None
327+
328+try:
329+ import subprocess
330+
331+ def _python_cmd(*args):
332+ args = (sys.executable,) + args
333+ return subprocess.call(args) == 0
334+
335+except ImportError:
336+ # will be used for python 2.3
337+ def _python_cmd(*args):
338+ args = (sys.executable,) + args
339+ # quoting arguments if windows
340+ if sys.platform == 'win32':
341+ def quote(arg):
342+ if ' ' in arg:
343+ return '"%s"' % arg
344+ return arg
345+ args = [quote(arg) for arg in args]
346+ return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
347+
348+DEFAULT_VERSION = "0.6.34"
349+DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
350+SETUPTOOLS_FAKED_VERSION = "0.6c11"
351+
352+SETUPTOOLS_PKG_INFO = """\
353+Metadata-Version: 1.0
354+Name: setuptools
355+Version: %s
356+Summary: xxxx
357+Home-page: xxx
358+Author: xxx
359+Author-email: xxx
360+License: xxx
361+Description: xxx
362+""" % SETUPTOOLS_FAKED_VERSION
363+
364+
365+def _install(tarball, install_args=()):
366+ # extracting the tarball
367+ tmpdir = tempfile.mkdtemp()
368+ log.warn('Extracting in %s', tmpdir)
369+ old_wd = os.getcwd()
370+ try:
371+ os.chdir(tmpdir)
372+ tar = tarfile.open(tarball)
373+ _extractall(tar)
374+ tar.close()
375+
376+ # going in the directory
377+ subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
378+ os.chdir(subdir)
379+ log.warn('Now working in %s', subdir)
380+
381+ # installing
382+ log.warn('Installing Distribute')
383+ if not _python_cmd('setup.py', 'install', *install_args):
384+ log.warn('Something went wrong during the installation.')
385+ log.warn('See the error message above.')
386+ # exitcode will be 2
387+ return 2
388+ finally:
389+ os.chdir(old_wd)
390+ shutil.rmtree(tmpdir)
391+
392+
393+def _build_egg(egg, tarball, to_dir):
394+ # extracting the tarball
395+ tmpdir = tempfile.mkdtemp()
396+ log.warn('Extracting in %s', tmpdir)
397+ old_wd = os.getcwd()
398+ try:
399+ os.chdir(tmpdir)
400+ tar = tarfile.open(tarball)
401+ _extractall(tar)
402+ tar.close()
403+
404+ # going in the directory
405+ subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
406+ os.chdir(subdir)
407+ log.warn('Now working in %s', subdir)
408+
409+ # building an egg
410+ log.warn('Building a Distribute egg in %s', to_dir)
411+ _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
412+
413+ finally:
414+ os.chdir(old_wd)
415+ shutil.rmtree(tmpdir)
416+ # returning the result
417+ log.warn(egg)
418+ if not os.path.exists(egg):
419+ raise IOError('Could not build the egg.')
420+
421+
422+def _do_download(version, download_base, to_dir, download_delay):
423+ egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg'
424+ % (version, sys.version_info[0], sys.version_info[1]))
425+ if not os.path.exists(egg):
426+ tarball = download_setuptools(version, download_base,
427+ to_dir, download_delay)
428+ _build_egg(egg, tarball, to_dir)
429+ sys.path.insert(0, egg)
430+ import setuptools
431+ setuptools.bootstrap_install_from = egg
432+
433+
434+def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
435+ to_dir=os.curdir, download_delay=15, no_fake=True):
436+ # making sure we use the absolute path
437+ to_dir = os.path.abspath(to_dir)
438+ was_imported = 'pkg_resources' in sys.modules or \
439+ 'setuptools' in sys.modules
440+ try:
441+ try:
442+ import pkg_resources
443+ if not hasattr(pkg_resources, '_distribute'):
444+ if not no_fake:
445+ _fake_setuptools()
446+ raise ImportError
447+ except ImportError:
448+ return _do_download(version, download_base, to_dir, download_delay)
449+ try:
450+ pkg_resources.require("distribute>=" + version)
451+ return
452+ except pkg_resources.VersionConflict:
453+ e = sys.exc_info()[1]
454+ if was_imported:
455+ sys.stderr.write(
456+ "The required version of distribute (>=%s) is not available,\n"
457+ "and can't be installed while this script is running. Please\n"
458+ "install a more recent version first, using\n"
459+ "'easy_install -U distribute'."
460+ "\n\n(Currently using %r)\n" % (version, e.args[0]))
461+ sys.exit(2)
462+ else:
463+ del pkg_resources, sys.modules['pkg_resources'] # reload ok
464+ return _do_download(version, download_base, to_dir,
465+ download_delay)
466+ except pkg_resources.DistributionNotFound:
467+ return _do_download(version, download_base, to_dir,
468+ download_delay)
469+ finally:
470+ if not no_fake:
471+ _create_fake_setuptools_pkg_info(to_dir)
472+
473+
474+def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
475+ to_dir=os.curdir, delay=15):
476+ """Download distribute from a specified location and return its filename
477+
478+ `version` should be a valid distribute version number that is available
479+ as an egg for download under the `download_base` URL (which should end
480+ with a '/'). `to_dir` is the directory where the egg will be downloaded.
481+ `delay` is the number of seconds to pause before an actual download
482+ attempt.
483+ """
484+ # making sure we use the absolute path
485+ to_dir = os.path.abspath(to_dir)
486+ try:
487+ from urllib.request import urlopen
488+ except ImportError:
489+ from urllib2 import urlopen
490+ tgz_name = "distribute-%s.tar.gz" % version
491+ url = download_base + tgz_name
492+ saveto = os.path.join(to_dir, tgz_name)
493+ src = dst = None
494+ if not os.path.exists(saveto): # Avoid repeated downloads
495+ try:
496+ log.warn("Downloading %s", url)
497+ src = urlopen(url)
498+ # Read/write all in one block, so we don't create a corrupt file
499+ # if the download is interrupted.
500+ data = src.read()
501+ dst = open(saveto, "wb")
502+ dst.write(data)
503+ finally:
504+ if src:
505+ src.close()
506+ if dst:
507+ dst.close()
508+ return os.path.realpath(saveto)
509+
510+
511+def _no_sandbox(function):
512+ def __no_sandbox(*args, **kw):
513+ try:
514+ from setuptools.sandbox import DirectorySandbox
515+ if not hasattr(DirectorySandbox, '_old'):
516+ def violation(*args):
517+ pass
518+ DirectorySandbox._old = DirectorySandbox._violation
519+ DirectorySandbox._violation = violation
520+ patched = True
521+ else:
522+ patched = False
523+ except ImportError:
524+ patched = False
525+
526+ try:
527+ return function(*args, **kw)
528+ finally:
529+ if patched:
530+ DirectorySandbox._violation = DirectorySandbox._old
531+ del DirectorySandbox._old
532+
533+ return __no_sandbox
534+
535+
536+def _patch_file(path, content):
537+ """Will backup the file then patch it"""
538+ f = open(path)
539+ existing_content = f.read()
540+ f.close()
541+ if existing_content == content:
542+ # already patched
543+ log.warn('Already patched.')
544+ return False
545+ log.warn('Patching...')
546+ _rename_path(path)
547+ f = open(path, 'w')
548+ try:
549+ f.write(content)
550+ finally:
551+ f.close()
552+ return True
553+
554+_patch_file = _no_sandbox(_patch_file)
555+
556+
557+def _same_content(path, content):
558+ f = open(path)
559+ existing_content = f.read()
560+ f.close()
561+ return existing_content == content
562+
563+
564+def _rename_path(path):
565+ new_name = path + '.OLD.%s' % time.time()
566+ log.warn('Renaming %s to %s', path, new_name)
567+ os.rename(path, new_name)
568+ return new_name
569+
570+
571+def _remove_flat_installation(placeholder):
572+ if not os.path.isdir(placeholder):
573+ log.warn('Unkown installation at %s', placeholder)
574+ return False
575+ found = False
576+ for file in os.listdir(placeholder):
577+ if fnmatch.fnmatch(file, 'setuptools*.egg-info'):
578+ found = True
579+ break
580+ if not found:
581+ log.warn('Could not locate setuptools*.egg-info')
582+ return
583+
584+ log.warn('Moving elements out of the way...')
585+ pkg_info = os.path.join(placeholder, file)
586+ if os.path.isdir(pkg_info):
587+ patched = _patch_egg_dir(pkg_info)
588+ else:
589+ patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO)
590+
591+ if not patched:
592+ log.warn('%s already patched.', pkg_info)
593+ return False
594+ # now let's move the files out of the way
595+ for element in ('setuptools', 'pkg_resources.py', 'site.py'):
596+ element = os.path.join(placeholder, element)
597+ if os.path.exists(element):
598+ _rename_path(element)
599+ else:
600+ log.warn('Could not find the %s element of the '
601+ 'Setuptools distribution', element)
602+ return True
603+
604+_remove_flat_installation = _no_sandbox(_remove_flat_installation)
605+
606+
607+def _after_install(dist):
608+ log.warn('After install bootstrap.')
609+ placeholder = dist.get_command_obj('install').install_purelib
610+ _create_fake_setuptools_pkg_info(placeholder)
611+
612+
613+def _create_fake_setuptools_pkg_info(placeholder):
614+ if not placeholder or not os.path.exists(placeholder):
615+ log.warn('Could not find the install location')
616+ return
617+ pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1])
618+ setuptools_file = 'setuptools-%s-py%s.egg-info' % \
619+ (SETUPTOOLS_FAKED_VERSION, pyver)
620+ pkg_info = os.path.join(placeholder, setuptools_file)
621+ if os.path.exists(pkg_info):
622+ log.warn('%s already exists', pkg_info)
623+ return
624+
625+ log.warn('Creating %s', pkg_info)
626+ try:
627+ f = open(pkg_info, 'w')
628+ except EnvironmentError:
629+ log.warn("Don't have permissions to write %s, skipping", pkg_info)
630+ return
631+ try:
632+ f.write(SETUPTOOLS_PKG_INFO)
633+ finally:
634+ f.close()
635+
636+ pth_file = os.path.join(placeholder, 'setuptools.pth')
637+ log.warn('Creating %s', pth_file)
638+ f = open(pth_file, 'w')
639+ try:
640+ f.write(os.path.join(os.curdir, setuptools_file))
641+ finally:
642+ f.close()
643+
644+_create_fake_setuptools_pkg_info = _no_sandbox(
645+ _create_fake_setuptools_pkg_info
646+)
647+
648+
649+def _patch_egg_dir(path):
650+ # let's check if it's already patched
651+ pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
652+ if os.path.exists(pkg_info):
653+ if _same_content(pkg_info, SETUPTOOLS_PKG_INFO):
654+ log.warn('%s already patched.', pkg_info)
655+ return False
656+ _rename_path(path)
657+ os.mkdir(path)
658+ os.mkdir(os.path.join(path, 'EGG-INFO'))
659+ pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
660+ f = open(pkg_info, 'w')
661+ try:
662+ f.write(SETUPTOOLS_PKG_INFO)
663+ finally:
664+ f.close()
665+ return True
666+
667+_patch_egg_dir = _no_sandbox(_patch_egg_dir)
668+
669+
670+def _before_install():
671+ log.warn('Before install bootstrap.')
672+ _fake_setuptools()
673+
674+
675+def _under_prefix(location):
676+ if 'install' not in sys.argv:
677+ return True
678+ args = sys.argv[sys.argv.index('install') + 1:]
679+ for index, arg in enumerate(args):
680+ for option in ('--root', '--prefix'):
681+ if arg.startswith('%s=' % option):
682+ top_dir = arg.split('root=')[-1]
683+ return location.startswith(top_dir)
684+ elif arg == option:
685+ if len(args) > index:
686+ top_dir = args[index + 1]
687+ return location.startswith(top_dir)
688+ if arg == '--user' and USER_SITE is not None:
689+ return location.startswith(USER_SITE)
690+ return True
691+
692+
693+def _fake_setuptools():
694+ log.warn('Scanning installed packages')
695+ try:
696+ import pkg_resources
697+ except ImportError:
698+ # we're cool
699+ log.warn('Setuptools or Distribute does not seem to be installed.')
700+ return
701+ ws = pkg_resources.working_set
702+ try:
703+ setuptools_dist = ws.find(
704+ pkg_resources.Requirement.parse('setuptools', replacement=False)
705+ )
706+ except TypeError:
707+ # old distribute API
708+ setuptools_dist = ws.find(
709+ pkg_resources.Requirement.parse('setuptools')
710+ )
711+
712+ if setuptools_dist is None:
713+ log.warn('No setuptools distribution found')
714+ return
715+ # detecting if it was already faked
716+ setuptools_location = setuptools_dist.location
717+ log.warn('Setuptools installation detected at %s', setuptools_location)
718+
719+ # if --root or --preix was provided, and if
720+ # setuptools is not located in them, we don't patch it
721+ if not _under_prefix(setuptools_location):
722+ log.warn('Not patching, --root or --prefix is installing Distribute'
723+ ' in another location')
724+ return
725+
726+ # let's see if its an egg
727+ if not setuptools_location.endswith('.egg'):
728+ log.warn('Non-egg installation')
729+ res = _remove_flat_installation(setuptools_location)
730+ if not res:
731+ return
732+ else:
733+ log.warn('Egg installation')
734+ pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO')
735+ if (os.path.exists(pkg_info) and
736+ _same_content(pkg_info, SETUPTOOLS_PKG_INFO)):
737+ log.warn('Already patched.')
738+ return
739+ log.warn('Patching...')
740+ # let's create a fake egg replacing setuptools one
741+ res = _patch_egg_dir(setuptools_location)
742+ if not res:
743+ return
744+ log.warn('Patching complete.')
745+ _relaunch()
746+
747+
748+def _relaunch():
749+ log.warn('Relaunching...')
750+ # we have to relaunch the process
751+ # pip marker to avoid a relaunch bug
752+ _cmd1 = ['-c', 'install', '--single-version-externally-managed']
753+ _cmd2 = ['-c', 'install', '--record']
754+ if sys.argv[:3] == _cmd1 or sys.argv[:3] == _cmd2:
755+ sys.argv[0] = 'setup.py'
756+ args = [sys.executable] + sys.argv
757+ sys.exit(subprocess.call(args))
758+
759+
760+def _extractall(self, path=".", members=None):
761+ """Extract all members from the archive to the current working
762+ directory and set owner, modification time and permissions on
763+ directories afterwards. `path' specifies a different directory
764+ to extract to. `members' is optional and must be a subset of the
765+ list returned by getmembers().
766+ """
767+ import copy
768+ import operator
769+ from tarfile import ExtractError
770+ directories = []
771+
772+ if members is None:
773+ members = self
774+
775+ for tarinfo in members:
776+ if tarinfo.isdir():
777+ # Extract directories with a safe mode.
778+ directories.append(tarinfo)
779+ tarinfo = copy.copy(tarinfo)
780+ tarinfo.mode = 448 # decimal for oct 0700
781+ self.extract(tarinfo, path)
782+
783+ # Reverse sort directories.
784+ if sys.version_info < (2, 4):
785+ def sorter(dir1, dir2):
786+ return cmp(dir1.name, dir2.name)
787+ directories.sort(sorter)
788+ directories.reverse()
789+ else:
790+ directories.sort(key=operator.attrgetter('name'), reverse=True)
791+
792+ # Set correct owner, mtime and filemode on directories.
793+ for tarinfo in directories:
794+ dirpath = os.path.join(path, tarinfo.name)
795+ try:
796+ self.chown(tarinfo, dirpath)
797+ self.utime(tarinfo, dirpath)
798+ self.chmod(tarinfo, dirpath)
799+ except ExtractError:
800+ e = sys.exc_info()[1]
801+ if self.errorlevel > 1:
802+ raise
803+ else:
804+ self._dbg(1, "tarfile: %s" % e)
805+
806+
807+def _build_install_args(options):
808+ """
809+ Build the arguments to 'python setup.py install' on the distribute package
810+ """
811+ install_args = []
812+ if options.user_install:
813+ if sys.version_info < (2, 6):
814+ log.warn("--user requires Python 2.6 or later")
815+ raise SystemExit(1)
816+ install_args.append('--user')
817+ return install_args
818+
819+def _parse_args():
820+ """
821+ Parse the command line for options
822+ """
823+ parser = optparse.OptionParser()
824+ parser.add_option(
825+ '--user', dest='user_install', action='store_true', default=False,
826+ help='install in user site package (requires Python 2.6 or later)')
827+ parser.add_option(
828+ '--download-base', dest='download_base', metavar="URL",
829+ default=DEFAULT_URL,
830+ help='alternative URL from where to download the distribute package')
831+ options, args = parser.parse_args()
832+ # positional arguments are ignored
833+ return options
834+
835+def main(version=DEFAULT_VERSION):
836+ """Install or upgrade setuptools and EasyInstall"""
837+ options = _parse_args()
838+ tarball = download_setuptools(download_base=options.download_base)
839+ return _install(tarball, _build_install_args(options))
840+
841+if __name__ == '__main__':
842+ sys.exit(main())
843
844=== removed file 'ez_setup.py'
845--- ez_setup.py 2009-03-16 15:17:16 +0000
846+++ ez_setup.py 1970-01-01 00:00:00 +0000
847@@ -1,241 +0,0 @@
848-#!python
849-"""Bootstrap setuptools installation
850-
851-If you want to use setuptools in your package's setup.py, just include this
852-file in the same directory with it, and add this to the top of your setup.py::
853-
854- from ez_setup import use_setuptools
855- use_setuptools()
856-
857-If you want to require a specific version of setuptools, set a download
858-mirror, or use an alternate download directory, you can do so by supplying
859-the appropriate options to ``use_setuptools()``.
860-
861-This file can also be run as a script to install or upgrade setuptools.
862-"""
863-import sys
864-DEFAULT_VERSION = "0.6c8"
865-DEFAULT_URL = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3]
866-
867-md5_data = {
868- 'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca',
869- 'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb',
870- 'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b',
871- 'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a',
872- 'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618',
873- 'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac',
874- 'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5',
875- 'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4',
876- 'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c',
877- 'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b',
878- 'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27',
879- 'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277',
880- 'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa',
881- 'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e',
882- 'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e',
883- 'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f',
884- 'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2',
885- 'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc',
886- 'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167',
887- 'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64',
888- 'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d',
889- 'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20',
890- 'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab',
891- 'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53',
892- 'setuptools-0.6c7-py2.3.egg': '209fdf9adc3a615e5115b725658e13e2',
893- 'setuptools-0.6c7-py2.4.egg': '5a8f954807d46a0fb67cf1f26c55a82e',
894- 'setuptools-0.6c7-py2.5.egg': '45d2ad28f9750e7434111fde831e8372',
895- 'setuptools-0.6c8-py2.3.egg': '50759d29b349db8cfd807ba8303f1902',
896- 'setuptools-0.6c8-py2.4.egg': 'cba38d74f7d483c06e9daa6070cce6de',
897- 'setuptools-0.6c8-py2.5.egg': '1721747ee329dc150590a58b3e1ac95b',
898-}
899-
900-import sys, os
901-
902-def _validate_md5(egg_name, data):
903- if egg_name in md5_data:
904- from md5 import md5
905- digest = md5(data).hexdigest()
906- if digest != md5_data[egg_name]:
907- print >>sys.stderr, (
908- "md5 validation of %s failed! (Possible download problem?)"
909- % egg_name
910- )
911- sys.exit(2)
912- return data
913-
914-
915-def use_setuptools(
916- version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
917- download_delay=15, min_version=None
918-):
919- """Automatically find/download setuptools and make it available on sys.path
920-
921- `version` should be a valid setuptools version number that is available
922- as an egg for download under the `download_base` URL (which should end with
923- a '/'). `to_dir` is the directory where setuptools will be downloaded, if
924- it is not already available. If `download_delay` is specified, it should
925- be the number of seconds that will be paused before initiating a download,
926- should one be required. If an older version of setuptools is installed,
927- this routine will print a message to ``sys.stderr`` and raise SystemExit in
928- an attempt to abort the calling script.
929- """
930- # Work around a hack in the ez_setup.py file from simplejson==1.7.3.
931- if min_version:
932- version = min_version
933-
934- was_imported = 'pkg_resources' in sys.modules or 'setuptools' in sys.modules
935- def do_download():
936- egg = download_setuptools(version, download_base, to_dir, download_delay)
937- sys.path.insert(0, egg)
938- import setuptools; setuptools.bootstrap_install_from = egg
939- try:
940- import pkg_resources
941- except ImportError:
942- return do_download()
943- try:
944- pkg_resources.require("setuptools>="+version); return
945- except pkg_resources.VersionConflict, e:
946- if was_imported:
947- print >>sys.stderr, (
948- "The required version of setuptools (>=%s) is not available, and\n"
949- "can't be installed while this script is running. Please install\n"
950- " a more recent version first, using 'easy_install -U setuptools'."
951- "\n\n(Currently using %r)"
952- ) % (version, e.args[0])
953- sys.exit(2)
954- else:
955- del pkg_resources, sys.modules['pkg_resources'] # reload ok
956- return do_download()
957- except pkg_resources.DistributionNotFound:
958- return do_download()
959-
960-def download_setuptools(
961- version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
962- delay = 15
963-):
964- """Download setuptools from a specified location and return its filename
965-
966- `version` should be a valid setuptools version number that is available
967- as an egg for download under the `download_base` URL (which should end
968- with a '/'). `to_dir` is the directory where the egg will be downloaded.
969- `delay` is the number of seconds to pause before an actual download attempt.
970- """
971- import urllib2, shutil
972- egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3])
973- url = download_base + egg_name
974- saveto = os.path.join(to_dir, egg_name)
975- src = dst = None
976- if not os.path.exists(saveto): # Avoid repeated downloads
977- try:
978- from distutils import log
979- if delay:
980- log.warn("""
981----------------------------------------------------------------------------
982-This script requires setuptools version %s to run (even to display
983-help). I will attempt to download it for you (from
984-%s), but
985-you may need to enable firewall access for this script first.
986-I will start the download in %d seconds.
987-
988-(Note: if this machine does not have network access, please obtain the file
989-
990- %s
991-
992-and place it in this directory before rerunning this script.)
993----------------------------------------------------------------------------""",
994- version, download_base, delay, url
995- ); from time import sleep; sleep(delay)
996- log.warn("Downloading %s", url)
997- src = urllib2.urlopen(url)
998- # Read/write all in one block, so we don't create a corrupt file
999- # if the download is interrupted.
1000- data = _validate_md5(egg_name, src.read())
1001- dst = open(saveto,"wb"); dst.write(data)
1002- finally:
1003- if src: src.close()
1004- if dst: dst.close()
1005- return os.path.realpath(saveto)
1006-
1007-def main(argv, version=DEFAULT_VERSION):
1008- """Install or upgrade setuptools and EasyInstall"""
1009- try:
1010- import setuptools
1011- except ImportError:
1012- egg = None
1013- try:
1014- egg = download_setuptools(version, delay=0)
1015- sys.path.insert(0,egg)
1016- from setuptools.command.easy_install import main
1017- return main(list(argv)+[egg]) # we're done here
1018- finally:
1019- if egg and os.path.exists(egg):
1020- os.unlink(egg)
1021- else:
1022- if setuptools.__version__ == '0.0.1':
1023- print >>sys.stderr, (
1024- "You have an obsolete version of setuptools installed. Please\n"
1025- "remove it from your system entirely before rerunning this script."
1026- )
1027- sys.exit(2)
1028-
1029- req = "setuptools>="+version
1030- import pkg_resources
1031- try:
1032- pkg_resources.require(req)
1033- except pkg_resources.VersionConflict:
1034- try:
1035- from setuptools.command.easy_install import main
1036- except ImportError:
1037- from easy_install import main
1038- main(list(argv)+[download_setuptools(delay=0)])
1039- sys.exit(0) # try to force an exit
1040- else:
1041- if argv:
1042- from setuptools.command.easy_install import main
1043- main(argv)
1044- else:
1045- print "Setuptools version",version,"or greater has been installed."
1046- print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
1047-
1048-def update_md5(filenames):
1049- """Update our built-in md5 registry"""
1050-
1051- import re
1052- from md5 import md5
1053-
1054- for name in filenames:
1055- base = os.path.basename(name)
1056- f = open(name,'rb')
1057- md5_data[base] = md5(f.read()).hexdigest()
1058- f.close()
1059-
1060- data = [" %r: %r,\n" % it for it in md5_data.items()]
1061- data.sort()
1062- repl = "".join(data)
1063-
1064- import inspect
1065- srcfile = inspect.getsourcefile(sys.modules[__name__])
1066- f = open(srcfile, 'rb'); src = f.read(); f.close()
1067-
1068- match = re.search("\nmd5_data = {\n([^}]+)}", src)
1069- if not match:
1070- print >>sys.stderr, "Internal error!"
1071- sys.exit(2)
1072-
1073- src = src[:match.start(1)] + repl + src[match.end(1):]
1074- f = open(srcfile,'w')
1075- f.write(src)
1076- f.close()
1077-
1078-
1079-if __name__=='__main__':
1080- if len(sys.argv)>2 and sys.argv[1]=='--md5update':
1081- update_md5(sys.argv[2:])
1082- else:
1083- main(sys.argv[1:])
1084-
1085-
1086-
1087-
1088-
1089
1090=== renamed directory 'src/lazr' => 'lazr'
1091=== modified file 'lazr/__init__.py'
1092--- src/lazr/__init__.py 2009-06-09 03:00:20 +0000
1093+++ lazr/__init__.py 2013-01-07 01:00:29 +0000
1094@@ -1,4 +1,4 @@
1095-# Copyright 2009 Canonical Ltd. All rights reserved.
1096+# Copyright 2009-2013 Canonical Ltd. All rights reserved.
1097 #
1098 # This file is part of lazr.smtptest.
1099 #
1100@@ -14,10 +14,14 @@
1101 # You should have received a copy of the GNU Lesser General Public License
1102 # along with lazr.smtptest. If not, see <http://www.gnu.org/licenses/>.
1103
1104-# this is a namespace package
1105-try:
1106- import pkg_resources
1107- pkg_resources.declare_namespace(__name__)
1108-except ImportError:
1109- import pkgutil
1110- __path__ = pkgutil.extend_path(__path__, __name__)
1111+# This is a namespace package, however under >= Python 3.3, let it be a true
1112+# namespace package (i.e. this cruft isn't necessary).
1113+import sys
1114+
1115+if sys.hexversion < 0x30300f0:
1116+ try:
1117+ import pkg_resources
1118+ pkg_resources.declare_namespace(__name__)
1119+ except ImportError:
1120+ import pkgutil
1121+ __path__ = pkgutil.extend_path(__path__, __name__)
1122
1123=== renamed file 'src/lazr/smtptest/NEWS.txt' => 'lazr/smtptest/NEWS.rst'
1124--- src/lazr/smtptest/NEWS.txt 2011-07-06 21:06:55 +0000
1125+++ lazr/smtptest/NEWS.rst 2013-01-07 01:00:29 +0000
1126@@ -2,6 +2,16 @@
1127 NEWS for lazr.smtptest
1128 ======================
1129
1130+2.0 (2013-01-05)
1131+================
1132+
1133+- Ported to Python 3. Now support Python 2.6, 2.7, 3.2, and 3.3.
1134+
1135+- Removed the dependency on zc.buildout.
1136+
1137+- Use nose for testing.
1138+
1139+
1140 1.3 (2011-06-07)
1141 ================
1142
1143
1144=== renamed file 'src/lazr/smtptest/README.txt' => 'lazr/smtptest/README.rst'
1145--- src/lazr/smtptest/README.txt 2009-06-23 00:29:31 +0000
1146+++ lazr/smtptest/README.rst 2013-01-07 01:00:29 +0000
1147@@ -36,7 +36,7 @@
1148 The lazr.smtptest package is importable, and has a version number.
1149
1150 >>> import lazr.smtptest
1151- >>> print 'VERSION:', lazr.smtptest.__version__
1152+ >>> print('VERSION:', lazr.smtptest.__version__)
1153 VERSION: ...
1154
1155 More information
1156
1157=== added file 'lazr/smtptest/README_fixture.py'
1158--- lazr/smtptest/README_fixture.py 1970-01-01 00:00:00 +0000
1159+++ lazr/smtptest/README_fixture.py 2013-01-07 01:00:29 +0000
1160@@ -0,0 +1,27 @@
1161+# Copyright 2009-2013 Canonical Ltd. All rights reserved.
1162+#
1163+# This file is part of lazr.smtptest
1164+#
1165+# lazr.smtptest is free software: you can redistribute it and/or modify it
1166+# under the terms of the GNU Lesser General Public License as published by
1167+# the Free Software Foundation, version 3 of the License.
1168+#
1169+# lazr.smtptest is distributed in the hope that it will be useful, but WITHOUT
1170+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1171+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
1172+# License for more details.
1173+#
1174+# You should have received a copy of the GNU Lesser General Public License
1175+# along with lazr.smtptest. If not, see <http://www.gnu.org/licenses/>.
1176+
1177+"""Doctest fixtures for running under nose."""
1178+
1179+from __future__ import absolute_import, print_function, unicode_literals
1180+
1181+__metaclass__ = type
1182+__all__ = [
1183+ 'globs',
1184+ ]
1185+
1186+
1187+from lazr.smtptest.docs.fixture import globs
1188
1189=== modified file 'lazr/smtptest/__init__.py'
1190--- src/lazr/smtptest/__init__.py 2009-09-04 19:06:38 +0000
1191+++ lazr/smtptest/__init__.py 2013-01-07 01:00:29 +0000
1192@@ -1,4 +1,4 @@
1193-# Copyright 2009 Canonical Ltd. All rights reserved.
1194+# Copyright 2009-2013 Canonical Ltd. All rights reserved.
1195 #
1196 # This file is part of lazr.smtptest
1197 #
1198
1199=== modified file 'lazr/smtptest/controller.py'
1200--- src/lazr/smtptest/controller.py 2009-06-30 00:40:38 +0000
1201+++ lazr/smtptest/controller.py 2013-01-07 01:00:29 +0000
1202@@ -1,4 +1,4 @@
1203-# Copyright 2009 Canonical Ltd. All rights reserved.
1204+# Copyright 2009-2013 Canonical Ltd. All rights reserved.
1205 #
1206 # This file is part of lazr.smtptest
1207 #
1208@@ -16,6 +16,9 @@
1209
1210 """The SMTP test controller."""
1211
1212+from __future__ import absolute_import, print_function, unicode_literals
1213+
1214+
1215 __metaclass__ = type
1216 __all__ = [
1217 'Controller',
1218@@ -27,12 +30,15 @@
1219 import smtplib
1220 import threading
1221
1222-from Queue import Empty, Queue
1223+try:
1224+ from queue import Empty, Queue
1225+except ImportError:
1226+ # Python 2
1227+ from Queue import Empty, Queue
1228
1229 from lazr.smtptest.server import QueueServer
1230
1231
1232-# pylint: disable-msg=C0103
1233 log = logging.getLogger('lazr.smtptest')
1234
1235
1236
1237=== added file 'lazr/smtptest/docs/fixture.py'
1238--- lazr/smtptest/docs/fixture.py 1970-01-01 00:00:00 +0000
1239+++ lazr/smtptest/docs/fixture.py 2013-01-07 01:00:29 +0000
1240@@ -0,0 +1,34 @@
1241+# Copyright 2009-2013 Canonical Ltd. All rights reserved.
1242+#
1243+# This file is part of lazr.smtptest
1244+#
1245+# lazr.smtptest is free software: you can redistribute it and/or modify it
1246+# under the terms of the GNU Lesser General Public License as published by
1247+# the Free Software Foundation, version 3 of the License.
1248+#
1249+# lazr.smtptest is distributed in the hope that it will be useful, but WITHOUT
1250+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1251+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
1252+# License for more details.
1253+#
1254+# You should have received a copy of the GNU Lesser General Public License
1255+# along with lazr.smtptest. If not, see <http://www.gnu.org/licenses/>.
1256+
1257+"""Doctest fixtures for running under nose."""
1258+
1259+from __future__ import absolute_import, print_function, unicode_literals
1260+
1261+__metaclass__ = type
1262+__all__ = [
1263+ 'globs',
1264+ ]
1265+
1266+
1267+def globs(globs):
1268+ """Set up globals for doctests."""
1269+ # Enable future statements to make Python 2 act more like Python 3.
1270+ globs['absolute_import'] = absolute_import
1271+ globs['print_function'] = print_function
1272+ globs['unicode_literals'] = unicode_literals
1273+ # Provide a convenient way to clean things up at the end of the test.
1274+ return globs
1275
1276=== renamed file 'src/lazr/smtptest/docs/queue.txt' => 'lazr/smtptest/docs/queue.rst'
1277--- src/lazr/smtptest/docs/queue.txt 2009-06-30 00:40:38 +0000
1278+++ lazr/smtptest/docs/queue.rst 2013-01-07 01:00:29 +0000
1279@@ -13,7 +13,11 @@
1280
1281 First, you need a queue.
1282
1283- >>> from Queue import Queue
1284+ >>> try:
1285+ ... from queue import Empty, Queue
1286+ ... except ImportError:
1287+ ... # Python 2
1288+ ... from Queue import Empty, Queue
1289 >>> queue = Queue()
1290
1291 Then you need a server.
1292@@ -34,8 +38,9 @@
1293
1294 >>> import smtplib
1295 >>> smtpd = smtplib.SMTP()
1296- >>> smtpd.connect('localhost', 9025)
1297- (220, '... Python SMTP proxy version ...')
1298+ >>> code, helo = smtpd.connect('localhost', 9025)
1299+ >>> print(code, str(helo))
1300+ 220 ... Python SMTP proxy version ...
1301
1302 >>> smtpd.sendmail('iperson@example.com', ['jperson@example.com'], """\
1303 ... From: Irie Person <iperson@example.com>
1304@@ -69,13 +74,12 @@
1305
1306 All of these messages are available in the queue.
1307
1308- >>> from Queue import Empty
1309 >>> while True:
1310 ... try:
1311 ... message = queue.get_nowait()
1312 ... except Empty:
1313 ... break
1314- ... print message['message-id']
1315+ ... print(message['message-id'])
1316 <elephant>
1317 <falcon>
1318 <goat>
1319@@ -95,8 +99,9 @@
1320 >>> controller.start()
1321
1322 >>> smtpd = smtplib.SMTP()
1323- >>> smtpd.connect('localhost', 9025)
1324- (220, '... Python SMTP proxy version ...')
1325+ >>> code, helo = smtpd.connect('localhost', 9025)
1326+ >>> print(code, str(helo))
1327+ 220 ... Python SMTP proxy version ...
1328
1329 We now have an SMTP server that we can send some messages to.
1330
1331@@ -133,7 +138,7 @@
1332 And we can dump out all the messages from the controller.
1333
1334 >>> for message in controller:
1335- ... print message['message-id']
1336+ ... print(message['message-id'])
1337 <horse>
1338 <iguana>
1339 <jackel>
1340@@ -151,7 +156,7 @@
1341 {}
1342
1343 >>> for message in controller:
1344- ... print message['message-id']
1345+ ... print(message['message-id'])
1346 <kangaroo>
1347
1348
1349
1350=== added file 'lazr/smtptest/docs/queue_fixture.py'
1351--- lazr/smtptest/docs/queue_fixture.py 1970-01-01 00:00:00 +0000
1352+++ lazr/smtptest/docs/queue_fixture.py 2013-01-07 01:00:29 +0000
1353@@ -0,0 +1,27 @@
1354+# Copyright 2009-2013 Canonical Ltd. All rights reserved.
1355+#
1356+# This file is part of lazr.smtptest
1357+#
1358+# lazr.smtptest is free software: you can redistribute it and/or modify it
1359+# under the terms of the GNU Lesser General Public License as published by
1360+# the Free Software Foundation, version 3 of the License.
1361+#
1362+# lazr.smtptest is distributed in the hope that it will be useful, but WITHOUT
1363+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1364+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
1365+# License for more details.
1366+#
1367+# You should have received a copy of the GNU Lesser General Public License
1368+# along with lazr.smtptest. If not, see <http://www.gnu.org/licenses/>.
1369+
1370+"""Doctest fixtures for running under nose."""
1371+
1372+from __future__ import absolute_import, print_function, unicode_literals
1373+
1374+__metaclass__ = type
1375+__all__ = [
1376+ 'globs',
1377+ ]
1378+
1379+
1380+from lazr.smtptest.docs.fixture import globs
1381
1382=== renamed file 'src/lazr/smtptest/docs/usage.txt' => 'lazr/smtptest/docs/usage.rst'
1383--- src/lazr/smtptest/docs/usage.txt 2009-06-18 05:12:56 +0000
1384+++ lazr/smtptest/docs/usage.rst 2013-01-07 01:00:29 +0000
1385@@ -15,7 +15,11 @@
1386 message. For example, you might want to pass the message between the threads
1387 via a Queue.
1388
1389- >>> from Queue import Queue
1390+ >>> try:
1391+ ... from queue import Queue
1392+ ... except ImportError:
1393+ ... # Python 2
1394+ ... from Queue import Queue
1395 >>> queue = Queue()
1396
1397 >>> class MyServer(Server):
1398@@ -32,8 +36,9 @@
1399
1400 >>> from smtplib import SMTP
1401 >>> smtpd = SMTP()
1402- >>> smtpd.connect('localhost', 9025)
1403- (220, '... Python SMTP proxy version ...')
1404+ >>> code, helo = smtpd.connect('localhost', 9025)
1405+ >>> print(code, str(helo))
1406+ 220 ... Python SMTP proxy version ...
1407
1408 ...and send it a message.
1409
1410@@ -50,7 +55,7 @@
1411 Now print the message that the server has just received.
1412
1413 >>> message = queue.get()
1414- >>> print message.as_string()
1415+ >>> print(message.as_string())
1416 From: Abby Person <aperson@example.com>
1417 To: Bart Person <bperson@example.com>
1418 Subject: A test
1419@@ -71,9 +76,9 @@
1420 >>> import socket
1421 >>> try:
1422 ... smtpd.connect('localhost', 9025)
1423- ... except socket.error, error:
1424- ... errno, message = error
1425- ... print message
1426+ ... except socket.error as error:
1427+ ... errno, message = error.args
1428+ ... print(message)
1429 Connection refused
1430
1431
1432@@ -109,8 +114,9 @@
1433 Now we can send a couple of messages to the server.
1434
1435 >>> smtpd = SMTP()
1436- >>> smtpd.connect('localhost', 9025)
1437- (220, '... Python SMTP proxy version ...')
1438+ >>> code, helo = smtpd.connect('localhost', 9025)
1439+ >>> print(code, str(helo))
1440+ 220 ... Python SMTP proxy version ...
1441
1442 >>> smtpd.sendmail('cperson@example.com', ['dperson@example.com'], """\
1443 ... From: Cris Person <cperson@example.com>
1444@@ -146,7 +152,7 @@
1445
1446 >>> for message_id in sorted(message['message-id']
1447 ... for message in mailbox.Maildir(mailbox_dir)):
1448- ... print message_id
1449+ ... print(message_id)
1450 <badger>
1451 <cougar>
1452 <dingo>
1453@@ -155,7 +161,7 @@
1454
1455 >>> for message_id in sorted(message['message-id']
1456 ... for message in mailbox.Maildir(mailbox_dir)):
1457- ... print message_id
1458+ ... print(message_id)
1459 <badger>
1460 <cougar>
1461 <dingo>
1462
1463=== added file 'lazr/smtptest/docs/usage_fixture.py'
1464--- lazr/smtptest/docs/usage_fixture.py 1970-01-01 00:00:00 +0000
1465+++ lazr/smtptest/docs/usage_fixture.py 2013-01-07 01:00:29 +0000
1466@@ -0,0 +1,27 @@
1467+# Copyright 2009-2013 Canonical Ltd. All rights reserved.
1468+#
1469+# This file is part of lazr.smtptest
1470+#
1471+# lazr.smtptest is free software: you can redistribute it and/or modify it
1472+# under the terms of the GNU Lesser General Public License as published by
1473+# the Free Software Foundation, version 3 of the License.
1474+#
1475+# lazr.smtptest is distributed in the hope that it will be useful, but WITHOUT
1476+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1477+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
1478+# License for more details.
1479+#
1480+# You should have received a copy of the GNU Lesser General Public License
1481+# along with lazr.smtptest. If not, see <http://www.gnu.org/licenses/>.
1482+
1483+"""Doctest fixtures for running under nose."""
1484+
1485+from __future__ import absolute_import, print_function, unicode_literals
1486+
1487+__metaclass__ = type
1488+__all__ = [
1489+ 'globs',
1490+ ]
1491+
1492+
1493+from lazr.smtptest.docs.fixture import globs
1494
1495=== modified file 'lazr/smtptest/server.py'
1496--- src/lazr/smtptest/server.py 2011-07-06 21:06:55 +0000
1497+++ lazr/smtptest/server.py 2013-01-07 01:00:29 +0000
1498@@ -1,4 +1,4 @@
1499-# Copyright 2009 Canonical Ltd. All rights reserved.
1500+# Copyright 2009-2013 Canonical Ltd. All rights reserved.
1501 #
1502 # This file is part of lazr.smtptest
1503 #
1504@@ -16,6 +16,9 @@
1505
1506 """The SMTP test server."""
1507
1508+from __future__ import absolute_import, print_function, unicode_literals
1509+
1510+
1511 __metaclass__ = type
1512 __all__ = [
1513 'QueueServer',
1514@@ -28,12 +31,16 @@
1515 import logging
1516 import asyncore
1517
1518-from Queue import Empty
1519+try:
1520+ from queue import Empty
1521+except ImportError:
1522+ # Python 2
1523+ from Queue import Empty
1524+
1525 from email import message_from_string
1526
1527
1528 COMMASPACE = ', '
1529-# pylint: disable-msg=C0103
1530 log = logging.getLogger('lazr.smtptest')
1531
1532
1533@@ -44,7 +51,6 @@
1534 self._server = server
1535 smtpd.SMTPChannel.__init__(self, server, connection, address)
1536
1537- # pylint: disable-msg=W0613
1538 def smtp_EXIT(self, argument):
1539 """EXIT - a new SMTP command to cleanly stop the server."""
1540 self.push('250 Ok')
1541@@ -61,7 +67,6 @@
1542 # asynchat/asyncore doesn't do it.
1543 try:
1544 return smtpd.SMTPChannel.send(self, data)
1545- # pylint: disable-msg=W0704
1546 except socket.error:
1547 # Nothing here can affect the outcome.
1548 pass
1549@@ -123,7 +128,6 @@
1550 log.info('[SMTPServer] processed message: %s',
1551 message.get('message-id', 'n/a'))
1552
1553- # pylint: disable-msg=R0201
1554 def start(self):
1555 """Start the asyncore loop."""
1556 log.info('[SMTPServer] starting asyncore loop')
1557@@ -134,7 +138,6 @@
1558 asyncore.close_all(map=self.socket_map)
1559 self.close()
1560
1561- # pylint: disable-msg=R0201
1562 def reset(self):
1563 """Do whatever you need to do on a reset."""
1564 log.info('[SMTPServer] reset')
1565
1566=== modified file 'lazr/smtptest/tests/__init__.py'
1567--- src/lazr/smtptest/tests/__init__.py 2009-06-09 03:00:20 +0000
1568+++ lazr/smtptest/tests/__init__.py 2013-01-07 01:00:29 +0000
1569@@ -1,16 +0,0 @@
1570-# Copyright 2009 Canonical Ltd. All rights reserved.
1571-#
1572-# This file is part of lazr.smtptest
1573-#
1574-# lazr.smtptest is free software: you can redistribute it and/or modify it
1575-# under the terms of the GNU Lesser General Public License as published by
1576-# the Free Software Foundation, version 3 of the License.
1577-#
1578-# lazr.smtptest is distributed in the hope that it will be useful, but WITHOUT
1579-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1580-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
1581-# License for more details.
1582-#
1583-# You should have received a copy of the GNU Lesser General Public License
1584-# along with lazr.smtptest. If not, see <http://www.gnu.org/licenses/>.
1585-"The lazr.smtptest tests."
1586
1587=== modified file 'lazr/smtptest/version.txt'
1588--- src/lazr/smtptest/version.txt 2011-07-06 21:06:55 +0000
1589+++ lazr/smtptest/version.txt 2013-01-07 01:00:29 +0000
1590@@ -1,1 +1,1 @@
1591-1.3
1592+2.0
1593
1594=== removed file 'pylint.rc'
1595--- pylint.rc 2009-06-17 02:41:00 +0000
1596+++ pylint.rc 1970-01-01 00:00:00 +0000
1597@@ -1,310 +0,0 @@
1598-# lint Python modules using external checkers.
1599-#
1600-# This is the main checker controlling the other ones and the reports
1601-# generation. It is itself both a raw checker and an astng checker in order
1602-# to:
1603-# * handle message activation / deactivation at the module level
1604-# * handle some basic but necessary stats'data (number of classes, methods...)
1605-#
1606-[MASTER]
1607-
1608-# Specify a configuration file.
1609-#rcfile=
1610-
1611-# Python code to execute, usually for sys.path manipulation such as
1612-# pygtk.require().
1613-#init-hook=
1614-
1615-# Profiled execution.
1616-profile=no
1617-
1618-# Add <file or directory> to the black list. It should be a base name, not a
1619-# path. You may set this option multiple times.
1620-ignore=CVS
1621-
1622-# Pickle collected data for later comparisons.
1623-persistent=no
1624-
1625-# Set the cache size for astng objects.
1626-cache-size=500
1627-
1628-# List of plugins (as comma separated values of python modules names) to load,
1629-# usually to register additional checkers.
1630-load-plugins=
1631-
1632-
1633-[MESSAGES CONTROL]
1634-
1635-# Enable only checker(s) with the given id(s). This option conflicts with the
1636-# disable-checker option
1637-#enable-checker=
1638-
1639-# Enable all checker(s) except those with the given id(s). This option
1640-# conflicts with the enable-checker option
1641-#disable-checker=
1642-
1643-# Enable all messages in the listed categories.
1644-#enable-msg-cat=
1645-
1646-# Disable all messages in the listed categories.
1647-#disable-msg-cat=
1648-
1649-# Enable the message(s) with the given id(s).
1650-#enable-msg=
1651-
1652-# Disable the message(s) with the given id(s).
1653-# I0011: *Locally disabling %s*
1654-disable-msg=I0011
1655-
1656-
1657-[REPORTS]
1658-
1659-# Set the output format. Available formats are text, parseable, colorized, msvs
1660-# (visual studio) and html
1661-output-format=parseable
1662-
1663-# Include message's id in output
1664-include-ids=yes
1665-
1666-# Put messages in a separate file for each module / package specified on the
1667-# command line instead of printing them on stdout. Reports (if any) will be
1668-# written in a file name "pylint_global.[txt|html]".
1669-files-output=no
1670-
1671-# Tells wether to display a full report or only the messages
1672-reports=no
1673-
1674-# Python expression which should return a note less than 10 (10 is the highest
1675-# note). You have access to the variables errors warning, statement which
1676-# respectivly contain the number of errors / warnings messages and the total
1677-# number of statements analyzed. This is used by the global evaluation report
1678-# (R0004).
1679-evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
1680-
1681-# Add a comment according to your evaluation note. This is used by the global
1682-# evaluation report (R0004).
1683-comment=no
1684-
1685-# Enable the report(s) with the given id(s).
1686-#enable-report=
1687-
1688-# Disable the report(s) with the given id(s).
1689-#disable-report=
1690-
1691-
1692-# checks for :
1693-# * doc strings
1694-# * modules / classes / functions / methods / arguments / variables name
1695-# * number of arguments, local variables, branchs, returns and statements in
1696-# functions, methods
1697-# * required module attributes
1698-# * dangerous default values as arguments
1699-# * redefinition of function / method / class
1700-# * uses of the global statement
1701-#
1702-[BASIC]
1703-
1704-# Required attributes for module, separated by a comma
1705-required-attributes=
1706-
1707-# Regular expression which should only match functions or classes name which do
1708-# not require a docstring
1709-no-docstring-rgx=__.*__
1710-
1711-# Regular expression which should only match correct module names
1712-module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
1713-
1714-# Regular expression which should only match correct module level names
1715-const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
1716-
1717-# Regular expression which should only match correct class names
1718-class-rgx=[A-Z_][a-zA-Z0-9]+$
1719-
1720-# Regular expression which should only match correct function names
1721-function-rgx=[a-z_][a-z0-9_]{2,30}$
1722-
1723-# Regular expression which should only match correct method names
1724-method-rgx=[a-z_][a-z0-9_]{2,30}$
1725-
1726-# Regular expression which should only match correct instance attribute names
1727-attr-rgx=[a-z_][a-z0-9_]{2,30}$
1728-
1729-# Regular expression which should only match correct argument names
1730-argument-rgx=[a-z_][a-z0-9_]{2,30}$
1731-
1732-# Regular expression which should only match correct variable names
1733-variable-rgx=[a-z_][a-z0-9_]{2,30}$
1734-
1735-# Regular expression which should only match correct list comprehension /
1736-# generator expression variable names
1737-inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
1738-
1739-# Good variable names which should always be accepted, separated by a comma
1740-good-names=i,j,k,ex,Run,_
1741-
1742-# Bad variable names which should always be refused, separated by a comma
1743-bad-names=foo,bar,baz,toto,tutu,tata
1744-
1745-# List of builtins function names that should not be used, separated by a comma
1746-bad-functions=map,filter,apply,input
1747-
1748-
1749-# try to find bugs in the code using type inference
1750-#
1751-[TYPECHECK]
1752-
1753-# Tells wether missing members accessed in mixin class should be ignored. A
1754-# mixin class is detected if its name ends with "mixin" (case insensitive).
1755-ignore-mixin-members=yes
1756-
1757-# List of classes names for which member attributes should not be checked
1758-# (useful for classes with attributes dynamicaly set).
1759-ignored-classes=SQLObject
1760-
1761-# When zope mode is activated, add a predefined set of Zope acquired attributes
1762-# to generated-members.
1763-zope=no
1764-
1765-# List of members which are set dynamically and missed by pylint inference
1766-# system, and so shouldn't trigger E0201 when accessed.
1767-generated-members=REQUEST,acl_users,aq_parent
1768-
1769-
1770-# checks for
1771-# * unused variables / imports
1772-# * undefined variables
1773-# * redefinition of variable from builtins or from an outer scope
1774-# * use of variable before assigment
1775-#
1776-[VARIABLES]
1777-
1778-# Tells wether we should check for unused import in __init__ files.
1779-init-import=no
1780-
1781-# A regular expression matching names used for dummy variables (i.e. not used).
1782-dummy-variables-rgx=_|dummy
1783-
1784-# List of additional names supposed to be defined in builtins. Remember that
1785-# you should avoid to define new builtins when possible.
1786-additional-builtins=
1787-
1788-
1789-# checks for :
1790-# * methods without self as first argument
1791-# * overridden methods signature
1792-# * access only to existant members via self
1793-# * attributes not defined in the __init__ method
1794-# * supported interfaces implementation
1795-# * unreachable code
1796-#
1797-[CLASSES]
1798-
1799-# List of interface methods to ignore, separated by a comma. This is used for
1800-# instance to not check methods defines in Zope's Interface base class.
1801-ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
1802-
1803-# List of method names used to declare (i.e. assign) instance attributes.
1804-defining-attr-methods=__init__,__new__,setUp
1805-
1806-
1807-# checks for sign of poor/misdesign:
1808-# * number of methods, attributes, local variables...
1809-# * size, complexity of functions, methods
1810-#
1811-[DESIGN]
1812-
1813-# Maximum number of arguments for function / method
1814-max-args=5
1815-
1816-# Maximum number of locals for function / method body
1817-max-locals=15
1818-
1819-# Maximum number of return / yield for function / method body
1820-max-returns=6
1821-
1822-# Maximum number of branch for function / method body
1823-max-branchs=12
1824-
1825-# Maximum number of statements in function / method body
1826-max-statements=50
1827-
1828-# Maximum number of parents for a class (see R0901).
1829-max-parents=7
1830-
1831-# Maximum number of attributes for a class (see R0902).
1832-max-attributes=7
1833-
1834-# Minimum number of public methods for a class (see R0903).
1835-min-public-methods=2
1836-
1837-# Maximum number of public methods for a class (see R0904).
1838-max-public-methods=50
1839-
1840-
1841-# checks for
1842-# * external modules dependencies
1843-# * relative / wildcard imports
1844-# * cyclic imports
1845-# * uses of deprecated modules
1846-#
1847-[IMPORTS]
1848-
1849-# Deprecated modules which should not be used, separated by a comma
1850-deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
1851-
1852-# Create a graph of every (i.e. internal and external) dependencies in the
1853-# given file (report R0402 must not be disabled)
1854-import-graph=
1855-
1856-# Create a graph of external dependencies in the given file (report R0402 must
1857-# not be disabled)
1858-ext-import-graph=
1859-
1860-# Create a graph of internal dependencies in the given file (report R0402 must
1861-# not be disabled)
1862-int-import-graph=
1863-
1864-
1865-# checks for :
1866-# * unauthorized constructions
1867-# * strict indentation
1868-# * line length
1869-# * use of <> instead of !=
1870-#
1871-[FORMAT]
1872-
1873-# Maximum number of characters on a single line.
1874-max-line-length=80
1875-
1876-# Maximum number of lines in a module
1877-max-module-lines=1000
1878-
1879-# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
1880-# tab).
1881-indent-string=' '
1882-
1883-
1884-# checks for:
1885-# * warning notes in the code like FIXME, XXX
1886-# * PEP 263: source code with non ascii character but no encoding declaration
1887-#
1888-[MISCELLANEOUS]
1889-
1890-# List of note tags to take in consideration, separated by a comma.
1891-notes=FIXME,XXX,TODO
1892-
1893-
1894-# checks for similarities and duplicated code. This computation may be
1895-# memory / CPU intensive, so you should disable it if you experiments some
1896-# problems.
1897-#
1898-[SIMILARITIES]
1899-
1900-# Minimum lines number of a similarity.
1901-min-similarity-lines=4
1902-
1903-# Ignore comments when computing similarities.
1904-ignore-comments=yes
1905-
1906-# Ignore docstrings when computing similarities.
1907-ignore-docstrings=yes
1908
1909=== added file 'setup.cfg'
1910--- setup.cfg 1970-01-01 00:00:00 +0000
1911+++ setup.cfg 2013-01-07 01:00:29 +0000
1912@@ -0,0 +1,8 @@
1913+[nosetests]
1914+verbosity=3
1915+with-coverage=1
1916+with-doctest=1
1917+doctest-extension=.rst
1918+doctest-options=+ELLIPSIS,+NORMALIZE_WHITESPACE,+REPORT_NDIFF
1919+doctest-fixtures=_fixture
1920+cover-package=lazr.smtptest
1921
1922=== modified file 'setup.py'
1923--- setup.py 2009-09-04 19:06:38 +0000
1924+++ setup.py 2013-01-07 01:00:29 +0000
1925@@ -1,6 +1,4 @@
1926-#!/usr/bin/env python
1927-
1928-# Copyright 2009 Canonical Ltd. All rights reserved.
1929+# Copyright 2009-2013 Canonical Ltd. All rights reserved.
1930 #
1931 # This file is part of lazr.smtptest
1932 #
1933@@ -16,10 +14,9 @@
1934 # You should have received a copy of the GNU Lesser General Public License
1935 # along with lazr.smtptest. If not, see <http://www.gnu.org/licenses/>.
1936
1937-import ez_setup
1938-ez_setup.use_setuptools()
1939+import distribute_setup
1940+distribute_setup.use_setuptools()
1941
1942-import sys
1943 from setuptools import setup, find_packages
1944
1945 # generic helpers primarily for the long_description
1946@@ -36,22 +33,21 @@
1947 return '\n'.join(res)
1948 # end generic helpers
1949
1950-__version__ = open("src/lazr/smtptest/version.txt").read().strip()
1951+__version__ = open("lazr/smtptest/version.txt").read().strip()
1952
1953 setup(
1954 name='lazr.smtptest',
1955 version=__version__,
1956 namespace_packages=['lazr'],
1957- packages=find_packages('src'),
1958- package_dir={'':'src'},
1959+ packages=find_packages(),
1960 include_package_data=True,
1961 zip_safe=False,
1962 maintainer='LAZR Developers',
1963 maintainer_email='lazr-developers@lists.launchpad.net',
1964- description=open('README.txt').readline().strip(),
1965+ description=open('README.rst').readline().strip(),
1966 long_description=generate(
1967- 'src/lazr/smtptest/README.txt',
1968- 'src/lazr/smtptest/NEWS.txt'),
1969+ 'lazr/smtptest/README.rst',
1970+ 'lazr/smtptest/NEWS.rst'),
1971 license='LGPL v3',
1972 install_requires=[
1973 'setuptools',
1974@@ -64,13 +60,10 @@
1975 "Intended Audience :: Developers",
1976 "License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
1977 "Operating System :: OS Independent",
1978- "Programming Language :: Python"],
1979- extras_require=dict(
1980- docs=['Sphinx',
1981- 'z3c.recipe.sphinxdoc']
1982- ),
1983- # This does not play nicely with buildout because it downloads but does
1984- # not cache the package.
1985- #setup_requires=['eggtestinfo', 'setuptools_bzr'],
1986- test_suite='lazr.smtptest.tests',
1987+ 'Programming Language :: Python',
1988+ 'Programming Language :: Python :: 2.6',
1989+ 'Programming Language :: Python :: 2.7',
1990+ 'Programming Language :: Python :: 3',
1991+ ],
1992+ test_suite='nose.collector',
1993 )
1994
1995=== removed directory 'src'
1996=== removed file 'src/lazr/smtptest/tests/test_docs.py'
1997--- src/lazr/smtptest/tests/test_docs.py 2009-06-17 02:41:00 +0000
1998+++ src/lazr/smtptest/tests/test_docs.py 1970-01-01 00:00:00 +0000
1999@@ -1,52 +0,0 @@
2000-# Copyright 2009 Canonical Ltd. All rights reserved.
2001-#
2002-# This file is part of lazr.smtptest
2003-#
2004-# lazr.smtptest is free software: you can redistribute it and/or modify it
2005-# under the terms of the GNU Lesser General Public License as published by
2006-# the Free Software Foundation, version 3 of the License.
2007-#
2008-# lazr.smtptest is distributed in the hope that it will be useful, but WITHOUT
2009-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2010-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
2011-# License for more details.
2012-#
2013-# You should have received a copy of the GNU Lesser General Public License
2014-# along with lazr.smtptest. If not, see <http://www.gnu.org/licenses/>.
2015-"Test harness for doctests."
2016-
2017-# pylint: disable-msg=E0611,W0142
2018-
2019-__metaclass__ = type
2020-__all__ = [
2021- 'additional_tests',
2022- ]
2023-
2024-import atexit
2025-import doctest
2026-import os
2027-# pylint: disable-msg=F0401
2028-from pkg_resources import (
2029- resource_filename, resource_exists, resource_listdir, cleanup_resources)
2030-import unittest
2031-
2032-DOCTEST_FLAGS = (
2033- doctest.ELLIPSIS |
2034- doctest.NORMALIZE_WHITESPACE |
2035- doctest.REPORT_NDIFF)
2036-
2037-
2038-def additional_tests():
2039- "Run the doc tests (README.txt and docs/*, if any exist)"
2040- doctest_files = [
2041- os.path.abspath(resource_filename('lazr.smtptest', 'README.txt'))]
2042- if resource_exists('lazr.smtptest', 'docs'):
2043- for name in resource_listdir('lazr.smtptest', 'docs'):
2044- if name.endswith('.txt'):
2045- doctest_files.append(
2046- os.path.abspath(
2047- resource_filename('lazr.smtptest', 'docs/%s' % name)))
2048- kwargs = dict(module_relative=False, optionflags=DOCTEST_FLAGS)
2049- atexit.register(cleanup_resources)
2050- return unittest.TestSuite((
2051- doctest.DocFileSuite(*doctest_files, **kwargs)))

Subscribers

People subscribed via source and target branches

to all changes: