diff --git a/ckan/lib/util.py b/ckan/lib/util.py deleted file mode 100644 index 3cf19c348d1..00000000000 --- a/ckan/lib/util.py +++ /dev/null @@ -1,47 +0,0 @@ -# encoding: utf-8 - -'''Shared utility functions for any Python code to use. - -Unlike :py:mod:`ckan.lib.helpers`, the functions in this module are not -available to templates. - -''' -import subprocess - - -# We implement our own check_output() function because -# subprocess.check_output() isn't in Python 2.6. -# This code is copy-pasted from Python 2.7 and adapted to make it work with -# Python 2.6. -# http://hg.python.org/cpython/file/d37f963394aa/Lib/subprocess.py#l544 -def check_output(*popenargs, **kwargs): - r"""Run command with arguments and return its output as a byte string. - - If the exit code was non-zero it raises a CalledProcessError. The - CalledProcessError object will have the return code in the returncode - attribute and output in the output attribute. - - The arguments are the same as for the Popen constructor. Example: - - >>> check_output(["ls", "-l", "/dev/null"]) - 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n' - - The stdout argument is not allowed as it is used internally. - To capture standard error in the result, use stderr=STDOUT. - - >>> check_output(["/bin/sh", "-c", - ... "ls -l non_existent_file ; exit 0"], - ... stderr=STDOUT) - 'ls: non_existent_file: No such file or directory\n' - """ - if 'stdout' in kwargs: - raise ValueError('stdout argument not allowed, it will be overridden.') - process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs) - output, unused_err = process.communicate() - retcode = process.poll() - if retcode: - cmd = kwargs.get("args") - if cmd is None: - cmd = popenargs[0] - raise subprocess.CalledProcessError(retcode, cmd) - return output diff --git a/ckan/model/extension.py b/ckan/model/extension.py index b471534a45a..64c68c8f1fa 100644 --- a/ckan/model/extension.py +++ b/ckan/model/extension.py @@ -4,23 +4,17 @@ Provides bridges between the model and plugin PluginImplementationss """ import logging +from operator import methodcaller from sqlalchemy.orm.interfaces import MapperExtension from sqlalchemy.orm.session import SessionExtension import ckan.plugins as plugins -try: - from operator import methodcaller -except ImportError: - def methodcaller(name, *args, **kwargs): - "Replaces stdlib operator.methodcaller in python <2.6" - def caller(obj): - return getattr(obj, name)(*args, **kwargs) - return caller log = logging.getLogger(__name__) + class ObserverNotifier(object): """ Mixin for hooking into SQLAlchemy @@ -93,7 +87,6 @@ def notify_observers(self, func): for observer in plugins.PluginImplementations(plugins.ISession): func(observer) - def after_begin(self, session, transaction, connection): return self.notify_observers( methodcaller('after_begin', session, transaction, connection) @@ -123,4 +116,3 @@ def after_rollback(self, session): return self.notify_observers( methodcaller('after_rollback', session) ) - diff --git a/ckan/pastertemplates/template/+dot+travis.yml_tmpl b/ckan/pastertemplates/template/+dot+travis.yml_tmpl index 536ae829969..cc4b3d7cd1f 100644 --- a/ckan/pastertemplates/template/+dot+travis.yml_tmpl +++ b/ckan/pastertemplates/template/+dot+travis.yml_tmpl @@ -1,7 +1,6 @@ language: python sudo: required python: - - "2.6" - "2.7" env: PGVERSION=9.1 install: diff --git a/ckan/pastertemplates/template/setup.py_tmpl b/ckan/pastertemplates/template/setup.py_tmpl index 844042b0035..d6dafcc4cd5 100644 --- a/ckan/pastertemplates/template/setup.py_tmpl +++ b/ckan/pastertemplates/template/setup.py_tmpl @@ -43,7 +43,6 @@ setup( # Specify the Python versions you support here. In particular, ensure # that you indicate whether you support Python 2, Python 3 or both. - 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', ], diff --git a/ckan/tests/controllers/test_api.py b/ckan/tests/controllers/test_api.py index 9cab9d2c1dd..5050ddb32aa 100644 --- a/ckan/tests/controllers/test_api.py +++ b/ckan/tests/controllers/test_api.py @@ -7,10 +7,9 @@ import json from routes import url_for -from nose.tools import assert_equal +from nose.tools import assert_equal, assert_in import ckan.tests.helpers as helpers -from ckan.tests.helpers import assert_in from ckan.tests import factories from ckan import model diff --git a/ckan/tests/controllers/test_group.py b/ckan/tests/controllers/test_group.py index bae63cafc45..67e06c92ce9 100644 --- a/ckan/tests/controllers/test_group.py +++ b/ckan/tests/controllers/test_group.py @@ -1,7 +1,7 @@ # encoding: utf-8 from bs4 import BeautifulSoup -from nose.tools import assert_equal, assert_true +from nose.tools import assert_equal, assert_true, assert_in from routes import url_for @@ -9,7 +9,6 @@ import ckan.model as model from ckan.tests import factories -assert_in = helpers.assert_in webtest_submit = helpers.webtest_submit submit_and_follow = helpers.submit_and_follow diff --git a/ckan/tests/controllers/test_organization.py b/ckan/tests/controllers/test_organization.py index b8e038bcf1e..ed8da4a48a8 100644 --- a/ckan/tests/controllers/test_organization.py +++ b/ckan/tests/controllers/test_organization.py @@ -1,12 +1,12 @@ # encoding: utf-8 from bs4 import BeautifulSoup -from nose.tools import assert_equal, assert_true +from nose.tools import assert_equal, assert_true, assert_in from routes import url_for from mock import patch from ckan.tests import factories, helpers -from ckan.tests.helpers import webtest_submit, submit_and_follow, assert_in +from ckan.tests.helpers import webtest_submit, submit_and_follow class TestOrganizationNew(helpers.FunctionalTestBase): diff --git a/ckan/tests/controllers/test_package.py b/ckan/tests/controllers/test_package.py index 9275be446bc..265b13adac7 100644 --- a/ckan/tests/controllers/test_package.py +++ b/ckan/tests/controllers/test_package.py @@ -6,6 +6,7 @@ assert_not_equal, assert_raises, assert_true, + assert_in ) from mock import patch, MagicMock @@ -17,10 +18,8 @@ import ckan.tests.helpers as helpers import ckan.tests.factories as factories -from ckan.tests.helpers import assert_in -assert_in = helpers.assert_in webtest_submit = helpers.webtest_submit submit_and_follow = helpers.submit_and_follow diff --git a/ckan/tests/controllers/test_tags.py b/ckan/tests/controllers/test_tags.py index d8c17933515..77d7e083311 100644 --- a/ckan/tests/controllers/test_tags.py +++ b/ckan/tests/controllers/test_tags.py @@ -3,7 +3,7 @@ import math import string -from nose.tools import assert_equal, assert_true, assert_false +from nose.tools import assert_equal, assert_true, assert_false, assert_in from bs4 import BeautifulSoup from routes import url_for @@ -11,7 +11,6 @@ import ckan.tests.helpers as helpers from ckan.tests import factories -assert_in = helpers.assert_in webtest_submit = helpers.webtest_submit submit_and_follow = helpers.submit_and_follow diff --git a/ckan/tests/helpers.py b/ckan/tests/helpers.py index e43093076f2..7f8a0ff77c5 100644 --- a/ckan/tests/helpers.py +++ b/ckan/tests/helpers.py @@ -22,6 +22,7 @@ import webtest from pylons import config import nose.tools +from nose.tools import assert_in, assert_not_in import mock import ckan.lib.search as search @@ -30,17 +31,6 @@ import ckan.logic as logic -try: - from nose.tools import assert_in, assert_not_in -except ImportError: - # Python 2.6 doesn't have these, so define them here - def assert_in(a, b, msg=None): - assert a in b, msg or '%r was not in %r' % (a, b) - - def assert_not_in(a, b, msg=None): - assert a not in b, msg or '%r was in %r' % (a, b) - - def reset_db(): '''Reset CKAN's database. diff --git a/ckan/tests/legacy/__init__.py b/ckan/tests/legacy/__init__.py index acaafc60b52..fcbf89c7134 100644 --- a/ckan/tests/legacy/__init__.py +++ b/ckan/tests/legacy/__init__.py @@ -355,15 +355,6 @@ def skip_test(*args): def clear_flash(res=None): messages = h._flash.pop_messages() -try: - from nose.tools import assert_in, assert_not_in -except ImportError: - def assert_in(a, b, msg=None): - assert a in b, msg or '%r was not in %r' % (a, b) - def assert_not_in(a, b, msg=None): - assert a not in b, msg or '%r was in %r' % (a, b) - - class StatusCodes: STATUS_200_OK = 200 STATUS_201_CREATED = 201 diff --git a/ckan/tests/legacy/functional/api/test_api.py b/ckan/tests/legacy/functional/api/test_api.py index 7c7a1756008..7f172ed1129 100644 --- a/ckan/tests/legacy/functional/api/test_api.py +++ b/ckan/tests/legacy/functional/api/test_api.py @@ -2,10 +2,10 @@ import json +from nose.tools import assert_in + from ckan.tests.legacy.functional.api.base import * -import ckan.tests.legacy -assert_in = ckan.tests.legacy.assert_in class ApiTestCase(ApiTestCase, ControllerTestCase): diff --git a/ckan/tests/legacy/lib/test_dictization.py b/ckan/tests/legacy/lib/test_dictization.py index 864a22b06c0..6a7cfbf8399 100644 --- a/ckan/tests/legacy/lib/test_dictization.py +++ b/ckan/tests/legacy/lib/test_dictization.py @@ -1,10 +1,10 @@ # encoding: utf-8 -from ckan.tests.legacy import assert_equal, assert_not_in, assert_in +from nose.tools import assert_equal, assert_not_in, assert_in from pprint import pprint, pformat from difflib import unified_diff -import ckan.lib.search as search +import ckan.lib.search as search from ckan.lib.create_test_data import CreateTestData from ckan import model from ckan.lib.dictization import (table_dictize, diff --git a/ckan/tests/legacy/models/test_group.py b/ckan/tests/legacy/models/test_group.py index 9d0e76acd96..a4da7148088 100644 --- a/ckan/tests/legacy/models/test_group.py +++ b/ckan/tests/legacy/models/test_group.py @@ -1,9 +1,12 @@ # encoding: utf-8 -from ckan.tests.legacy import assert_equal, assert_in, assert_not_in, CreateTestData +from nose.tools import assert_in, assert_not_in, assert_equal + +from ckan.tests.legacy import CreateTestData import ckan.model as model + class TestGroup(object): @classmethod diff --git a/ckan/tests/legacy/test_coding_standards.py b/ckan/tests/legacy/test_coding_standards.py index b3c556833d5..b9a5f0d3142 100644 --- a/ckan/tests/legacy/test_coding_standards.py +++ b/ckan/tests/legacy/test_coding_standards.py @@ -488,7 +488,6 @@ class TestPep8(object): 'ckan/model/authz.py', 'ckan/model/dashboard.py', 'ckan/model/domain_object.py', - 'ckan/model/extension.py', 'ckan/model/follower.py', 'ckan/model/group.py', 'ckan/model/group_extra.py', diff --git a/ckan/tests/lib/search/test_index.py b/ckan/tests/lib/search/test_index.py index dd783e6d500..dbee706d983 100644 --- a/ckan/tests/lib/search/test_index.py +++ b/ckan/tests/lib/search/test_index.py @@ -3,17 +3,13 @@ import datetime import hashlib import json -import nose.tools import nose +from nose.tools import assert_equal, assert_in, assert_not_in from pylons import config import ckan.lib.search as search import ckan.tests.helpers as helpers -assert_equal = nose.tools.assert_equal -assert_in = helpers.assert_in -assert_not_in = helpers.assert_not_in - class TestSearchIndex(object): diff --git a/ckan/tests/lib/test_mailer.py b/ckan/tests/lib/test_mailer.py index b45b41b6e47..143be8373b4 100644 --- a/ckan/tests/lib/test_mailer.py +++ b/ckan/tests/lib/test_mailer.py @@ -1,6 +1,6 @@ # encoding: utf-8 -from nose.tools import assert_equal, assert_raises +from nose.tools import assert_equal, assert_raises, assert_in from pylons import config from email.mime.text import MIMEText from email.parser import Parser @@ -16,8 +16,6 @@ import ckan.tests.helpers as helpers import ckan.tests.factories as factories -assert_in = helpers.assert_in - class MailerBase(SmtpServerHarness): diff --git a/ckan/tests/test_coding_standards.py b/ckan/tests/test_coding_standards.py index 8726f277bd3..6010449676d 100644 --- a/ckan/tests/test_coding_standards.py +++ b/ckan/tests/test_coding_standards.py @@ -15,8 +15,6 @@ import re import subprocess -import ckan.lib.util as util - def test_building_the_docs(): '''There should be no warnings or errors when building the Sphinx docs. @@ -28,8 +26,12 @@ def test_building_the_docs(): ''' try: - output = util.check_output( - ['python', 'setup.py', 'build_sphinx', '--all-files', '--fresh-env'], + output = subprocess.check_output( + ['python', + 'setup.py', + 'build_sphinx', + '--all-files', + '--fresh-env'], stderr=subprocess.STDOUT) except subprocess.CalledProcessError as err: assert False, ( diff --git a/ckanext/datapusher/tests/test.py b/ckanext/datapusher/tests/test.py index 2d44c0b14e1..58802fb07ec 100644 --- a/ckanext/datapusher/tests/test.py +++ b/ckanext/datapusher/tests/test.py @@ -4,7 +4,6 @@ import httpretty import httpretty.core import nose -import sys import datetime import pylons @@ -56,19 +55,12 @@ def __getattr__(self, attr): httpretty.core.fakesock.socket = HTTPrettyFix -# avoid hanging tests https://github.com/gabrielfalcao/HTTPretty/issues/34 -if sys.version_info < (2, 7, 0): - import socket - socket.setdefaulttimeout(1) - - class TestDatastoreCreate(tests.WsgiAppCase): sysadmin_user = None normal_user = None @classmethod def setup_class(cls): - wsgiapp = middleware.make_app(config['global_conf'], **config) cls.app = paste.fixture.TestApp(wsgiapp) if not tests.is_datastore_supported(): @@ -84,20 +76,11 @@ def setup_class(cls): set_url_type( model.Package.get('annakarenina').resources, cls.sysadmin_user) - # Httpretty crashes with Solr on Python 2.6, - # skip the tests - if (sys.version_info[0] == 2 and sys.version_info[1] == 6): - raise nose.SkipTest() - @classmethod def teardown_class(cls): rebuild_all_dbs(cls.Session) p.unload('datastore') p.unload('datapusher') - # Reenable Solr indexing - if (sys.version_info[0] == 2 and sys.version_info[1] == 6 - and not p.plugin_loaded('synchronous_search')): - p.load('synchronous_search') def test_create_ckan_resource_in_package(self): package = model.Package.get('annakarenina') diff --git a/ckanext/datastore/tests/test_create.py b/ckanext/datastore/tests/test_create.py index a36340ec82d..8e97355b525 100644 --- a/ckanext/datastore/tests/test_create.py +++ b/ckanext/datastore/tests/test_create.py @@ -22,12 +22,6 @@ from ckanext.datastore.tests.helpers import rebuild_all_dbs, set_url_type -# avoid hanging tests https://github.com/gabrielfalcao/HTTPretty/issues/34 -if sys.version_info < (2, 7, 0): - import socket - socket.setdefaulttimeout(1) - - class TestDatastoreCreateNewTests(object): @classmethod def setup_class(cls): diff --git a/ckanext/example_igroupform/tests/test_controllers.py b/ckanext/example_igroupform/tests/test_controllers.py index b6f03eaf7e6..be598a13aae 100644 --- a/ckanext/example_igroupform/tests/test_controllers.py +++ b/ckanext/example_igroupform/tests/test_controllers.py @@ -1,6 +1,6 @@ # encoding: utf-8 -from nose.tools import assert_equal +from nose.tools import assert_equal, assert_in from routes import url_for import ckan.plugins as plugins @@ -8,7 +8,6 @@ import ckan.model as model from ckan.tests import factories -assert_in = helpers.assert_in webtest_submit = helpers.webtest_submit submit_and_follow = helpers.submit_and_follow diff --git a/ckanext/example_iuploader/test/test_plugin.py b/ckanext/example_iuploader/test/test_plugin.py index f99dc6b15f9..08daf634d21 100644 --- a/ckanext/example_iuploader/test/test_plugin.py +++ b/ckanext/example_iuploader/test/test_plugin.py @@ -6,6 +6,7 @@ from mock import patch from nose.tools import ( assert_equal, + assert_in, assert_is_instance ) from pyfakefs import fake_filesystem @@ -19,7 +20,6 @@ import ckan.tests.helpers as helpers import ckanext.example_iuploader.plugin as plugin -assert_in = helpers.assert_in webtest_submit = helpers.webtest_submit submit_and_follow = helpers.submit_and_follow diff --git a/ckanext/example_theme/custom_emails/tests.py b/ckanext/example_theme/custom_emails/tests.py index 3aaf30e40f4..5c72852d15a 100644 --- a/ckanext/example_theme/custom_emails/tests.py +++ b/ckanext/example_theme/custom_emails/tests.py @@ -11,10 +11,7 @@ from ckan.tests.lib.test_mailer import MailerBase import ckan.tests.helpers as helpers -from nose.tools import assert_equal - - -assert_in = helpers.assert_in +from nose.tools import assert_equal, assert_in class TestExampleCustomEmailsPlugin(MailerBase): diff --git a/ckanext/resourceproxy/tests/test_proxy.py b/ckanext/resourceproxy/tests/test_proxy.py index 28a382ef713..78413da7685 100644 --- a/ckanext/resourceproxy/tests/test_proxy.py +++ b/ckanext/resourceproxy/tests/test_proxy.py @@ -1,6 +1,5 @@ # encoding: utf-8 -import sys import requests import unittest import json @@ -60,20 +59,12 @@ def setup_class(cls): wsgiapp = middleware.make_app(config['global_conf'], **config) cls.app = paste.fixture.TestApp(wsgiapp) create_test_data.CreateTestData.create() - # Httpretty crashes with Solr on Python 2.6, - # skip the tests - if (sys.version_info[0] == 2 and sys.version_info[1] == 6): - raise nose.SkipTest() @classmethod def teardown_class(cls): config.clear() config.update(cls._original_config) model.repo.rebuild_db() - # Reenable Solr indexing - if (sys.version_info[0] == 2 and sys.version_info[1] == 6 - and not p.plugin_loaded('synchronous_search')): - p.load('synchronous_search') def setUp(self): self.url = 'http://www.ckan.org/static/example.json' diff --git a/doc/conf.py b/doc/conf.py index 635dba13f16..3ed57700fbb 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -18,8 +18,6 @@ import os import subprocess -import ckan.lib.util as util - # If your extensions (or modules documented by autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. @@ -126,7 +124,7 @@ def latest_release_tag(): This requires git to be installed. ''' - git_tags = util.check_output( + git_tags = subprocess.check_output( ['git', 'tag', '-l'], stderr=subprocess.STDOUT).split() # FIXME: We could do more careful pattern matching against ckan-X.Y.Z here. diff --git a/doc/contributing/python.rst b/doc/contributing/python.rst index b557dae81ff..58509d4f916 100644 --- a/doc/contributing/python.rst +++ b/doc/contributing/python.rst @@ -74,7 +74,7 @@ Imports Logging ------- -We use `the Python standard library's logging module `_ +We use `the Python standard library's logging module `_ to log messages in CKAN, e.g.:: import logging diff --git a/doc/maintaining/installing/install-from-source.rst b/doc/maintaining/installing/install-from-source.rst index 5dc82468219..f5f895333cf 100644 --- a/doc/maintaining/installing/install-from-source.rst +++ b/doc/maintaining/installing/install-from-source.rst @@ -33,7 +33,7 @@ wiki page for help): ===================== =============================================== Package Description ===================== =============================================== -Python `The Python programming language, v2.6 or 2.7 `_ +Python `The Python programming language, v2.7 `_ |postgres| `The PostgreSQL database system, v8.4 or newer `_ libpq `The C programmer's interface to PostgreSQL `_ pip `A tool for installing and managing Python packages `_