From 5979a423311f74a397a325879a0f00b44be77905 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Wed, 3 Sep 2014 19:18:49 -0400 Subject: [PATCH 1/7] Bump development version number --- CHANGES.md | 5 +++++ doorstop/__init__.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 56702e138..93e6c1c66 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,11 @@ Changelog ========= +0.8.1 (dev) +----------- + +- TBD + 0.8 (2014/08/28) ---------------- diff --git a/doorstop/__init__.py b/doorstop/__init__.py index 617f8bac7..efa962fa6 100644 --- a/doorstop/__init__.py +++ b/doorstop/__init__.py @@ -1,7 +1,7 @@ """Package for doorstop.""" __project__ = 'Doorstop' -__version__ = '0.8' +__version__ = '0.8.1-dev' CLI = 'doorstop' GUI = 'doorstop-gui' From 37d260a270580351ecb70551e9f83e5636514801 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Wed, 3 Sep 2014 23:09:31 -0400 Subject: [PATCH 2/7] Add start of integration tests for next number I still need to determine a way to run the server in the background. --- doorstop/server/test/test_all.py | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/doorstop/server/test/test_all.py b/doorstop/server/test/test_all.py index 1195aea0b..27d777572 100644 --- a/doorstop/server/test/test_all.py +++ b/doorstop/server/test/test_all.py @@ -1 +1,36 @@ """Integration tests for the doorstop.web package.""" + +import unittest +from unittest.mock import patch +from multiprocessing import Process + +from doorstop.server import main +from doorstop.server import check, get_next_number + + +# @unittest.skipUnless(os.getenv(ENV), REASON) +@patch('doorstop.settings.SERVER_HOST', 'localhost') +class TestServer(unittest.TestCase): + + """Integration tests for the client/server feature.""" + + def setUp(self): + self.process = Process(target=main.main) + self.process.start() + + def tearDown(self): + self.process.terminate() + + def test_check(self): + """Verify the server can be checked.""" + self.assertTrue(self.process.is_alive()) + check() + + def test_get_next_number(self): + """Verify the next number can be requested from the server.""" + self.assertTrue(self.process.is_alive()) + number = get_next_number('req') + number2 = get_next_number('req') + self.assertIsNot(None, number) + self.assertIsNot(None, number2) + self.assertGreater(number, number2) From 30bb66d2e3d535fb8b299d1e3ed21b216499956e Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Thu, 4 Sep 2014 13:18:05 -0400 Subject: [PATCH 3/7] Add integration tests for next number One test is still failing --- doorstop/cli/test/__init__.py | 8 ++++-- doorstop/server/main.py | 4 ++- doorstop/server/test/__init__.py | 2 +- doorstop/server/test/test_all.py | 40 +++++++++++++++++++---------- doorstop/server/test/test_client.py | 4 +-- doorstop/server/test/test_server.py | 8 +++--- doorstop/server/utilities.py | 18 ++++++++++++- 7 files changed, 59 insertions(+), 25 deletions(-) diff --git a/doorstop/cli/test/__init__.py b/doorstop/cli/test/__init__.py index e5a8b97f3..acd73a3f3 100644 --- a/doorstop/cli/test/__init__.py +++ b/doorstop/cli/test/__init__.py @@ -33,7 +33,9 @@ def setUp(self): settings.CACHE_ITEMS, settings.CACHE_PATHS, settings.WARN_ALL, - settings.ERROR_ALL) + settings.ERROR_ALL, + settings.SERVER_HOST, + settings.SERVER_PORT) def tearDown(self): (settings.REFORMAT, @@ -49,4 +51,6 @@ def tearDown(self): settings.CACHE_ITEMS, settings.CACHE_PATHS, settings.WARN_ALL, - settings.ERROR_ALL) = self.backup + settings.ERROR_ALL, + settings.SERVER_HOST, + settings.SERVER_PORT) = self.backup diff --git a/doorstop/server/main.py b/doorstop/server/main.py index 5069c1e53..8792060e8 100644 --- a/doorstop/server/main.py +++ b/doorstop/server/main.py @@ -18,6 +18,7 @@ log = common.logger(__name__) +app = utilities.StripPathMiddleware(bottle.app()) tree = None # set in `run`, read in the route functions numbers = defaultdict(int) # cache of next document numbers @@ -68,7 +69,8 @@ def run(args, cwd, _): if args.launch: url = utilities.build_url(host=host, port=port) webbrowser.open(url) - bottle.run(host=host, port=port, debug=args.debug, reloader=args.debug) + bottle.run(app=app, host=host, port=port, + debug=args.debug, reloader=args.debug) @get('/') diff --git a/doorstop/server/test/__init__.py b/doorstop/server/test/__init__.py index dfa98c2f1..8cce51fdc 100644 --- a/doorstop/server/test/__init__.py +++ b/doorstop/server/test/__init__.py @@ -1,4 +1,4 @@ -"""Package for the doorstop.web tests.""" +"""Package for the doorstop.server tests.""" ENV = 'TEST_INTEGRATION' # environment variable to enable integration tests REASON = "'{0}' variable not set".format(ENV) diff --git a/doorstop/server/test/test_all.py b/doorstop/server/test/test_all.py index 27d777572..623256ca8 100644 --- a/doorstop/server/test/test_all.py +++ b/doorstop/server/test/test_all.py @@ -1,36 +1,48 @@ -"""Integration tests for the doorstop.web package.""" +"""Integration tests for the doorstop.server package.""" +import os +import time import unittest from unittest.mock import patch from multiprocessing import Process +import logging +from doorstop import server from doorstop.server import main -from doorstop.server import check, get_next_number +from doorstop import settings +from doorstop.server.test import ENV, REASON -# @unittest.skipUnless(os.getenv(ENV), REASON) + +@unittest.skipUnless(os.getenv(ENV), REASON) @patch('doorstop.settings.SERVER_HOST', 'localhost') class TestServer(unittest.TestCase): """Integration tests for the client/server feature.""" - def setUp(self): - self.process = Process(target=main.main) - self.process.start() - - def tearDown(self): - self.process.terminate() + @classmethod + def setUpClass(cls): + assert settings.SERVER_PORT == 7867 + cls.process = Process(target=main.main, kwargs={'args': []}) + cls.process.start() + logging.info("delaying for the server to initialize...") + time.sleep(3) + assert cls.process.is_alive() + + @classmethod + def tearDownClass(cls): + cls.process.terminate() + logging.info("delaying for the server to shutdown...") + time.sleep(1) def test_check(self): """Verify the server can be checked.""" - self.assertTrue(self.process.is_alive()) - check() + server.check() def test_get_next_number(self): """Verify the next number can be requested from the server.""" - self.assertTrue(self.process.is_alive()) - number = get_next_number('req') - number2 = get_next_number('req') + number = server.get_next_number('req') + number2 = server.get_next_number('req') self.assertIsNot(None, number) self.assertIsNot(None, number2) self.assertGreater(number, number2) diff --git a/doorstop/server/test/test_client.py b/doorstop/server/test/test_client.py index c57f8895b..b28fc55ea 100644 --- a/doorstop/server/test/test_client.py +++ b/doorstop/server/test/test_client.py @@ -1,4 +1,4 @@ -"""Unit tests for the doorstop.web.client package.""" +"""Unit tests for the doorstop.server.client module.""" import unittest from unittest.mock import patch, Mock @@ -12,7 +12,7 @@ @patch('doorstop.settings.SERVER_PORT', 8080) class TestModule(unittest.TestCase): - """Unit tests for the doorstop.web.client module.""" + """Unit tests for the doorstop.server.client module.""" @patch('doorstop.settings.SERVER_HOST', '1.2.3.4') def test_exists(self): diff --git a/doorstop/server/test/test_server.py b/doorstop/server/test/test_server.py index 6648be680..1d6af7fdc 100644 --- a/doorstop/server/test/test_server.py +++ b/doorstop/server/test/test_server.py @@ -1,4 +1,4 @@ -"""Unit tests for the doorstop.web.server package.""" +"""Unit tests for the doorstop.server.main module.""" import unittest from unittest.mock import patch, Mock, MagicMock @@ -40,7 +40,7 @@ def setUp(self): class TestModule(BaseTestCase): - """Unit tests for the doorstop.web.server module.""" + """Unit tests for the doorstop.server.main module.""" @patch('doorstop.server.main.build') @patch('bottle.run') @@ -64,7 +64,7 @@ def test_main_debug(self, mock_run, mock_open, mock_build): class TestRoutesHTML(BaseTestCase): - """Unit tests for the doorstop.web.server module HTML responses.""" + """Unit tests for the doorstop.server.main module HTML responses.""" def test_get_index(self): """Verify `/` works (HTML).""" @@ -122,7 +122,7 @@ def test_post_numbers(self): @patch('doorstop.server.utilities.json_response', Mock(return_value=True)) class TestRoutesJSON(BaseTestCase): - """Unit tests for the doorstop.web.server module JSON responses.""" + """Unit tests for the doorstop.server.main module JSON responses.""" def test_get_documents(self): """Verify `/documents` works (JSON).""" diff --git a/doorstop/server/utilities.py b/doorstop/server/utilities.py index e0c2a6c4a..e6d8e065c 100644 --- a/doorstop/server/utilities.py +++ b/doorstop/server/utilities.py @@ -1,12 +1,28 @@ -"""Shared functions for the `doorstop.web` package.""" +"""Shared functions for the `doorstop.server` package.""" +from doorstop import common from doorstop import settings +log = common.logger(__name__) + + +class StripPathMiddleware(object): # pylint: disable=R0903 + + """WSGI middleware that strips trailing slashes from all URLs.""" + + def __init__(self, app): + self.app = app + + def __call__(self, e, h): # pragma: no cover (integration test) + e['PATH_INFO'] = e['PATH_INFO'].rstrip('/') + return self.app(e, h) + def build_url(host=None, port=None, path=None): """Build the server's URL with optional path.""" host = host or settings.SERVER_HOST port = port or settings.SERVER_PORT + log.debug("building URL: {} + {} + {}".format(host, port, path)) if not host: return None url = 'http://{}'.format(host) From a0093f898adfe75758fd2cbaf0baaea020026ebe Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Thu, 4 Sep 2014 13:55:45 -0400 Subject: [PATCH 4/7] Fix failing test --- doorstop/server/main.py | 2 +- doorstop/server/test/test_all.py | 9 ++++----- doorstop/server/test/test_server.py | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/doorstop/server/main.py b/doorstop/server/main.py index 8792060e8..7a71dfb06 100644 --- a/doorstop/server/main.py +++ b/doorstop/server/main.py @@ -161,7 +161,7 @@ def get_attr(prefix, uid, name): def post_numbers(prefix): """Create the next number in a document.""" document = tree.find_document(prefix) - number = max(document.next, numbers[prefix]) + number = max(document.next_number, numbers[prefix]) numbers[prefix] = number + 1 if utilities.json_response(request): data = {'next': number} diff --git a/doorstop/server/test/test_all.py b/doorstop/server/test/test_all.py index 623256ca8..3f005c1b3 100644 --- a/doorstop/server/test/test_all.py +++ b/doorstop/server/test/test_all.py @@ -22,7 +22,6 @@ class TestServer(unittest.TestCase): @classmethod def setUpClass(cls): - assert settings.SERVER_PORT == 7867 cls.process = Process(target=main.main, kwargs={'args': []}) cls.process.start() logging.info("delaying for the server to initialize...") @@ -35,14 +34,14 @@ def tearDownClass(cls): logging.info("delaying for the server to shutdown...") time.sleep(1) - def test_check(self): + def test_check(self): # pylint: disable=R0201 """Verify the server can be checked.""" server.check() def test_get_next_number(self): """Verify the next number can be requested from the server.""" - number = server.get_next_number('req') + number1 = server.get_next_number('req') number2 = server.get_next_number('req') - self.assertIsNot(None, number) + self.assertIsNot(None, number1) self.assertIsNot(None, number2) - self.assertGreater(number, number2) + self.assertLess(number1, number2) diff --git a/doorstop/server/test/test_server.py b/doorstop/server/test/test_server.py index 1d6af7fdc..ddd8c3461 100644 --- a/doorstop/server/test/test_server.py +++ b/doorstop/server/test/test_server.py @@ -22,7 +22,7 @@ class BaseTestCase(unittest.TestCase): mock_document = MagicMock() mock_document.__iter__.return_value = [mock_item, mock_item2] mock_document.prefix = 'PREFIX' - mock_document.next = 42 + mock_document.next_number = 42 mock_document.find_item = Mock(return_value=mock_item) mock_document2 = Mock() From b23ba177f784dace395e2c1c03fa53bc17d2c35a Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Thu, 4 Sep 2014 14:10:17 -0400 Subject: [PATCH 5/7] Pylint cleanup --- doorstop/server/test/test_all.py | 1 - doorstop/server/test/test_client.py | 4 ++-- doorstop/server/test/test_server.py | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/doorstop/server/test/test_all.py b/doorstop/server/test/test_all.py index 3f005c1b3..a59dad218 100644 --- a/doorstop/server/test/test_all.py +++ b/doorstop/server/test/test_all.py @@ -9,7 +9,6 @@ from doorstop import server from doorstop.server import main -from doorstop import settings from doorstop.server.test import ENV, REASON diff --git a/doorstop/server/test/test_client.py b/doorstop/server/test/test_client.py index b28fc55ea..8c6c3cfe5 100644 --- a/doorstop/server/test/test_client.py +++ b/doorstop/server/test/test_client.py @@ -63,7 +63,7 @@ def test_exists_unknown(self): self.assertFalse(exists) @patch('doorstop.settings.SERVER_HOST', '1.2.3.4') - def test_check(self): + def test_check(self): # pylint: disable=R0201 """Verify the client can check a server.""" with patch('doorstop.server.client.exists', Mock(return_value=True)): client.check() @@ -81,7 +81,7 @@ def test_check_unknown(self): self.assertRaises(DoorstopError, client.check) @patch('doorstop.settings.SERVER_HOST', None) - def test_check_disabled(self): + def test_check_disabled(self): # pylint: disable=R0201 """Verify the client can check a disabled server.""" with patch('doorstop.server.client.exists', Mock(return_value=False)): client.check() diff --git a/doorstop/server/test/test_server.py b/doorstop/server/test/test_server.py index ddd8c3461..0db901d6d 100644 --- a/doorstop/server/test/test_server.py +++ b/doorstop/server/test/test_server.py @@ -77,7 +77,7 @@ def test_get_documents(self): text = server.get_documents() self.assertEqual("PREFIX
PREFIX2", text) - def test_get_document(self): + def test_get_document(self): # pylint: disable=R0201 """Verify `/document/PREFIX` works (HTML).""" for line in server.get_document('prefix'): print(line) @@ -87,7 +87,7 @@ def test_get_items(self): text = server.get_items('prefix') self.assertEqual("UID
UID2", text) - def test_get_item(self): + def test_get_item(self): # pylint: disable=R0201 """Verify `/document/PREFIX/items/UID` works (HTML).""" for line in server.get_item('prefix', 'uid'): print(line) From cd0dc8d8e88dfa8bc13ad59d8e3bda75707d0062 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Thu, 4 Sep 2014 18:40:44 -0400 Subject: [PATCH 6/7] Update CHANGES --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 93e6c1c66..0c0b4d329 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,7 +4,7 @@ Changelog 0.8.1 (dev) ----------- -- TBD +- Fixed a bug requesting new item numbers from the server. 0.8 (2014/08/28) ---------------- From 4500eb5d5cfe2874d55093f8c457e080357b5760 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Thu, 4 Sep 2014 18:43:28 -0400 Subject: [PATCH 7/7] Bump release version number --- CHANGES.md | 4 ++-- doorstop/__init__.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 0c0b4d329..fc452981a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,8 +1,8 @@ Changelog ========= -0.8.1 (dev) ------------ +0.8.1 (2014/09/04) +------------------ - Fixed a bug requesting new item numbers from the server. diff --git a/doorstop/__init__.py b/doorstop/__init__.py index efa962fa6..5d70f25e7 100644 --- a/doorstop/__init__.py +++ b/doorstop/__init__.py @@ -1,7 +1,7 @@ """Package for doorstop.""" __project__ = 'Doorstop' -__version__ = '0.8.1-dev' +__version__ = '0.8.1' CLI = 'doorstop' GUI = 'doorstop-gui'