From df0dc740d509d8ed22a85bf0a0bed8ea7742f3fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Bryon?= Date: Fri, 10 May 2013 21:02:13 +0200 Subject: [PATCH 1/3] Moved some general-purpose (not specific to Django) material to hospital project. --- .../django_doctor_demo/simple/healthchecks.py | 4 +- doctor/__init__.py | 2 - doctor/views.py | 106 +----------------- etc/buildout.cfg | 1 + setup.py | 1 + 5 files changed, 7 insertions(+), 107 deletions(-) diff --git a/demo/django_doctor_demo/simple/healthchecks.py b/demo/django_doctor_demo/simple/healthchecks.py index 34ac01f..7c1d490 100644 --- a/demo/django_doctor_demo/simple/healthchecks.py +++ b/demo/django_doctor_demo/simple/healthchecks.py @@ -1,9 +1,9 @@ # -*- coding: utf-8 -*- """Health checks.""" -import doctor +from hospital import HealthCheck -class FakeHealthCheck(doctor.HealthCheck): +class FakeHealthCheck(HealthCheck): """Check that health checks are captured.""" def test_success(self): """Successful healthcheck is captured and passes.""" diff --git a/doctor/__init__.py b/doctor/__init__.py index 505e600..756c4d3 100644 --- a/doctor/__init__.py +++ b/doctor/__init__.py @@ -1,7 +1,5 @@ # -*- coding: utf-8 -*- """Django health check and test-that-it-works application.""" -# Import API shortcuts. -from doctor.healthchecks import HealthCheck #: django-doctor version information, as a tuple. diff --git a/doctor/views.py b/doctor/views.py index bf7c617..7aabf63 100644 --- a/doctor/views.py +++ b/doctor/views.py @@ -14,6 +14,8 @@ from django.views.decorators.cache import never_cache from django.views.generic import TemplateView +from hospital.loading import HealthCheckLoader + from doctor.conf import TEMPLATE_CONTEXT from doctor.services import load_service_classes from doctor.utils import cleanse_dictionary @@ -122,108 +124,6 @@ def force_server_error(request): return HttpResponse('This should never show up.', content_type='text/plain') -class HealthCheckLoader(unittest.TestLoader): - """Encapsulate HealthCheck loading. - - This is a special TestLoader which makes sure instances are actually - health checks. - - .. warning:: - - Since this loader can be called with arguments provided by users (GET - requests), **we have to make sure user input is safe**. - As an example, we can't accept to load health checks from any callable, - because this callable could be anything. - - """ - def is_health_check(self, value): - """Return True if ``value`` is an health check. - - Proxy to :py:attr:`` - Tests ``is_healthcheck`` attribute of ``value``. - - """ - - try: - return value.is_healthcheck - except AttributeError: - return False - - def filter_suite(self, suite): - """Return copy of TestSuite where only health checks remain.""" - if isinstance(suite, unittest.TestSuite): - suite_copy = self.suiteClass() - for sub in suite: - if isinstance(sub, unittest.TestSuite): - suite_copy.addTest(self.filter_suite(sub)) - else: - if self.is_health_check(sub): - suite_copy.addTest(sub) - elif self.is_health_check(suite): - suite_copy = suite.copy() - return suite_copy - - def loadTestsFromModule(self, module): - suite_tree = super(HealthCheckLoader, self).loadTestsFromModule(module) - return self.filter_suite(suite_tree) - - def loadTestsFromName(self, name, module=None): - """Same as unittest.TestLoader.loadTestsFromName, but restricted - to health test objects, i.e. no callable allowed.""" - parts = name.split('.') - if module: - parts.insert(0, module) - name = '.'.join(parts) - # First, retrieve a module. - module_obj = None - path_parts = [] - while parts: - latest_part = parts.pop(0) - path_parts.append(latest_part) - path = '.'.join(path_parts) - try: - imported_obj = __import__(path, globals(), locals(), [], -1) - except ImportError as module_exception: - if not module_obj: - raise module_exception - else: - path_parts.pop() # Last part is not a module. - path = '.'.join(path_parts) - break - else: - if not module_obj: - module_obj = imported_obj - else: - module_obj = getattr(module_obj, latest_part) - # We got ``module_obj`` for ``path``. - # Let's retrieve members. - parts = name[len(path):].lstrip('.') - if not parts: - return self.loadTestsFromModule(module_obj) - else: - parts = parts.split('.') - class_name = parts[0] - try: - class_obj = getattr(module_obj, class_name) - except AttributeError as class_exception: - raise ImportError("Couldn't load '%s'" % name) - if not self.is_health_check(class_obj): - raise ImportError("'%s' is not a health check" % name) - try: - method_name = parts[1] - except IndexError: - return self.loadTestsFromTestCase(class_obj) - else: - try: - method_obj = getattr(class_obj, method_name) - except AttributeError: - raise AttributeError("'%s' is not a health check method" % name) - return unittest.TestSuite([class_obj(method_name)]) - - def loadTestsFromNames(self, names, module=None): - raise NotImplementedError() - - class HealthCheckView(TemplateView): """Load a health check, run it and return result.""" #: Name of the health_check argument captured in urlpatterns. @@ -268,7 +168,7 @@ def del_health_check(self): health_check = property(get_health_check, set_health_check, del_health_check, - """:py:class:`doctor.HealthCheck` instance.""") + """:py:class:`hospital.HealthCheck` instance.""") def get_health_check_result(self): """Getter for health_check_result, runs tests when first requested.""" diff --git a/etc/buildout.cfg b/etc/buildout.cfg index 4940a2d..574a09d 100644 --- a/etc/buildout.cfg +++ b/etc/buildout.cfg @@ -20,6 +20,7 @@ use-dependency-links = false develop = ${buildout:directory}/ ${buildout:directory}/demo/ + ${buildout:directory}/../hospital parts = django-doctor directories diff --git a/setup.py b/setup.py index 2b1e3c2..89a04d5 100644 --- a/setup.py +++ b/setup.py @@ -19,6 +19,7 @@ url='https://github.com/funkbit/django-doctor', include_package_data=True, packages=['doctor', 'doctor.services', 'doctor.management', 'doctor.management.commands'], + install_requires=['hospital'], tests_require=['django>=1.4,<1.5'], license='BSD', classifiers = ( From d2c047a8654cca0a470a03fd9e1c60078424dda8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Bryon?= Date: Sat, 11 May 2013 11:46:38 +0200 Subject: [PATCH 2/3] Using public release of hospital. --- etc/buildout.cfg | 1 - 1 file changed, 1 deletion(-) diff --git a/etc/buildout.cfg b/etc/buildout.cfg index 574a09d..4940a2d 100644 --- a/etc/buildout.cfg +++ b/etc/buildout.cfg @@ -20,7 +20,6 @@ use-dependency-links = false develop = ${buildout:directory}/ ${buildout:directory}/demo/ - ${buildout:directory}/../hospital parts = django-doctor directories From 7225e53e3042747207efc7403a1849a614067772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Bryon?= Date: Sat, 11 May 2013 11:54:09 +0200 Subject: [PATCH 3/3] Using crate.io to as Python package index for development environment. --- etc/buildout.cfg | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/etc/buildout.cfg b/etc/buildout.cfg index 4940a2d..5d9466b 100644 --- a/etc/buildout.cfg +++ b/etc/buildout.cfg @@ -12,9 +12,11 @@ installed = lib/buildout/.installed.cfg parts-directory = lib/buildout/parts # Package index, mirrors, allowed hosts and dependency links. Those options # control locations where buildout looks for packages. -index = http://f.pypi.python.org/simple +index = https://simple.crate.io find-links = -allow-hosts = *.python.org +allow-hosts = + *.crate.io + packages.crate-cdn.com use-dependency-links = false # Development. develop = @@ -67,3 +69,4 @@ z3c.recipe.scripts = 1.0.1 zc.recipe.egg = 1.3.2 zest.releaser = 3.43 django-nose = 1.1 +hospital = 0.1