From 992297f2cb2263970d803076840e7057bc9a5fb5 Mon Sep 17 00:00:00 2001 From: Shubham Chaudhary Date: Sat, 13 May 2017 11:16:33 +0530 Subject: [PATCH 1/8] Fix readme and don't allow bad docs to go online --- README.md | 2 ++ requirements-dev.txt | 2 ++ setup.py | 5 ++++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cc47d65..9c6b339 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,10 @@ pip3 install qmon ``` This is how it'll appear in hipchat: + ![hipchat_window](http://i.imgur.com/G1vnPUm.png) Find us: + * [PyPi](https://pypi.python.org/pypi/qmon) diff --git a/requirements-dev.txt b/requirements-dev.txt index 953186b..866d1ff 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -5,3 +5,5 @@ nose2 mock coverage unittest2 + +pypandoc diff --git a/setup.py b/setup.py index 0155e85..6cdc9f5 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,10 @@ def get_long_description(): try: import pypandoc long_description = pypandoc.convert('README.md', 'rst') - except (IOError, ImportError): + with open('README.rst', 'w') as fhan: + fhan.write(long_description) + except (IOError, ImportError) as e: + raise e with open('README.md') as fhan: long_description = fhan.read() return long_description From 2a7d4631f0a7e05b7a2384a9fdc5faab45a2809d Mon Sep 17 00:00:00 2001 From: Shubham Chaudhary Date: Sat, 13 May 2017 11:22:43 +0530 Subject: [PATCH 2/8] Run setup functions only through cli --- setup.py | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/setup.py b/setup.py index 6cdc9f5..3fcda70 100644 --- a/setup.py +++ b/setup.py @@ -27,20 +27,21 @@ def get_long_description(): return long_description -add_keywords = dict( - entry_points={ - 'console_scripts': ['qmon = qmon.main:main'], - }, ) - -setup( - name='QMon', - description='Redis Monitor - monitor number of items and more for any type of redis queue', - version=get_version(), - packages=find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]), - license='GPLv3+', - author='Shubham Chaudhary', - author_email='me@shubhamchaudhary.in', - url='https://github.com/shubhamchaudhary/qmon', - long_description=get_long_description(), - install_requires=get_requirements(), - **add_keywords) +if __name__ == '__main__': + add_keywords = dict( + entry_points={ + 'console_scripts': ['qmon = qmon.main:main'], + }, ) + + setup( + name='QMon', + description='Redis Monitor - monitor number of items and more for any type of redis queue', + version=get_version(), + packages=find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]), + license='GPLv3+', + author='Shubham Chaudhary', + author_email='me@shubhamchaudhary.in', + url='https://github.com/shubhamchaudhary/qmon', + long_description=get_long_description(), + install_requires=get_requirements(), + **add_keywords) From bd5c3a420038d91242bed975957ab78fb79973e2 Mon Sep 17 00:00:00 2001 From: Shubham Chaudhary Date: Sat, 13 May 2017 11:34:20 +0530 Subject: [PATCH 3/8] Add github description at the top in pypi --- setup.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/setup.py b/setup.py index 3fcda70..3599b0d 100644 --- a/setup.py +++ b/setup.py @@ -18,6 +18,12 @@ def get_long_description(): try: import pypandoc long_description = pypandoc.convert('README.md', 'rst') + + readme_note = """\ + .. note:: + For the latest source, discussion, etc, please visit the + `GitHub repository `_\n\n""" + long_description = readme_note + long_description with open('README.rst', 'w') as fhan: fhan.write(long_description) except (IOError, ImportError) as e: From d1a0e1fccfd8fb11e2d9e8920b2616803105219a Mon Sep 17 00:00:00 2001 From: Shubham Chaudhary Date: Tue, 13 Jun 2017 12:29:29 +0530 Subject: [PATCH 4/8] Allow users to specify time and enable stop once empty at will --- qmon/main.py | 14 ++++++++-- qmon/monitor.py | 14 +++++++--- tests/__init__.py | 1 + tests/test_monitor.py | 63 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 tests/__init__.py create mode 100644 tests/test_monitor.py diff --git a/qmon/main.py b/qmon/main.py index 6f8e54a..55022a7 100644 --- a/qmon/main.py +++ b/qmon/main.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +# -*- coding: utf-8 -*- # # main.py - All commandline interactions # This file is a part of QMon. @@ -18,7 +19,6 @@ # You should have received a copy of the GNU General Public License # along with QMon. If not, see . # - from __future__ import print_function import logging @@ -26,6 +26,7 @@ import qmon.monitor from qmon import __version__ +from qmon import monitor def print_version(): @@ -43,6 +44,8 @@ def parse_known_args(): parser.add_argument('--host', required=True, help='Redis host') parser.add_argument('--port', '-p', help='Redis port') parser.add_argument('--room', '-r', help='HipChat Room') + parser.add_argument('--sleep-time', '-t', default=monitor.TIME_GAP_IN_SECONDS, help='Number of seconds to sleep') + parser.add_argument('--stop-once-empty', '-s', action='store_true', help='Stop when no items left in queue') parser.add_argument('-V', '--version', action='store_true', dest='version', @@ -55,7 +58,14 @@ def main(): args, otherthings, parser = parse_known_args() setup_logging() - qmon.monitor.monitor_queue(queue_name=args.queue_name, host=args.host, port=args.port, room=args.room) + qmon.monitor.monitor_queue( + queue_name=args.queue_name, + host=args.host, + port=args.port, + room=args.room, + sleep_time=args.sleep_time, + stop_once_empty=args.stop_once_empty + ) return 0 diff --git a/qmon/monitor.py b/qmon/monitor.py index 15bd4b0..a659bae 100644 --- a/qmon/monitor.py +++ b/qmon/monitor.py @@ -30,9 +30,15 @@ def __should_i_notify_subscribers_now(): return should_notify -def monitor_queue(queue_name, host, port, room): +def monitor_queue(queue_name, host, port, room, sleep_time=TIME_GAP_IN_SECONDS, stop_once_empty=False): + sleep_time = int(sleep_time) + if sleep_time < 1: + raise ValueError('Sleep time too low. Please specify sleep time in seconds.') + if room is None: + raise ValueError('Please specify a valid room name') logger.info('Connecting to hipchat') - hc = hypchat.HypChat(os.environ['HIP_TOKEN']) + hip_token = os.environ['HIP_TOKEN'] # Please specify your token using: export HIP_TOKEN=my_hipchat_token + hc = hypchat.HypChat(hip_token) room = hc.get_room(room) room.notification( @@ -45,7 +51,7 @@ def monitor_queue(queue_name, host, port, room): last_notify_items_length = 0 last_items_length = 0 rd = qmon.status.redis_connection_cached(host, port) - while items_in_queue: + while not stop_once_empty or items_in_queue: items_in_queue = qmon.status.get_items_in_queue(queue_name, redis_conn=rd, default=0) if last_items_length != items_in_queue: message = '{} queue status: {:,d}'.format(queue_name, items_in_queue) @@ -54,7 +60,7 @@ def monitor_queue(queue_name, host, port, room): if notified: last_notify_items_length = items_in_queue last_items_length = items_in_queue - time.sleep(TIME_GAP_IN_SECONDS) + time.sleep(sleep_time) room.notification( 'All done for {queue}.'.format(queue=queue_name), diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/test_monitor.py b/tests/test_monitor.py new file mode 100644 index 0000000..8e5ac34 --- /dev/null +++ b/tests/test_monitor.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +import unittest +from unittest import mock + +from qmon.monitor import monitor_queue + + +@mock.patch('qmon.monitor.time.sleep') +@mock.patch('qmon.monitor.os.environ') +@mock.patch('qmon.monitor.hypchat.HypChat') +@mock.patch('qmon.monitor.qmon.status.get_items_in_queue') +@mock.patch('qmon.monitor.qmon.status.redis_connection_cached') +class TestMonitor(unittest.TestCase): + def setup_mock(self, mock_hypchat, mock_items_in_queue, mock_os, mock_redis, items_in_queue=None): + if not items_in_queue: + items_in_queue = [0] + mock_items_in_queue.side_effect = items_in_queue + redis = mock.MagicMock() + mock_redis.return_value = redis + mock_os.__getitem__.return_value = 'dummy_token' + client = mock.MagicMock() + room = mock.MagicMock() + client.get_room.return_value = room + mock_hypchat.return_value = client + return room + + def test_monitor_queue__no_items__only_start_notification_and_end_notification( + self, mock_redis, mock_items_in_queue, mock_hypchat, mock_os, mock_sleep + ): + room = self.setup_mock(mock_hypchat, mock_items_in_queue, mock_os, mock_redis, items_in_queue=[0]) + + monitor_queue( + 'dummy_queue', + 'dummy_host', + 10, + 'dummy_room', + stop_once_empty=True, + ) + + room.notification.assert_has_calls([ + mock.call('Starting to monitor queue=dummy_queue on port=10', color='yellow', notify=True), + mock.call('All done for dummy_queue.', color='yellow', notify=True), + ]) + self.assertEqual(2, room.notification.call_count) + + def test_monitor_queue__some_items__send_notification( + self, mock_redis, mock_items_in_queue, mock_hypchat, mock_os, mock_sleep + ): + room = self.setup_mock(mock_hypchat, mock_items_in_queue, mock_os, mock_redis, items_in_queue=[30, 0]) + + monitor_queue( + 'dummy_queue', + 'dummy_host', + 10, + 'dummy_room', + stop_once_empty=True, + ) + + room.notification.assert_has_calls([ + mock.call('dummy_queue queue status: 30', color='gray', notify=False), + mock.call('dummy_queue queue status: 0', color='gray', notify=False), + ]) + self.assertEqual(4, room.notification.call_count) From 091f9404aa2f6c35f05b1e2bb7103be7a384eaa0 Mon Sep 17 00:00:00 2001 From: Shubham Chaudhary Date: Tue, 13 Jun 2017 12:40:26 +0530 Subject: [PATCH 5/8] Update version number --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 3599b0d..b1dc8ed 100644 --- a/setup.py +++ b/setup.py @@ -1,11 +1,11 @@ -# coding=utf-8 +# -*- coding: utf-8 -*- from distutils.core import setup from setuptools import find_packages def get_version(): - return '0.1.1' + return '0.2.0' def get_requirements(): @@ -43,7 +43,7 @@ def get_long_description(): name='QMon', description='Redis Monitor - monitor number of items and more for any type of redis queue', version=get_version(), - packages=find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]), + packages=find_packages(exclude=['*.tests', '*.tests.*', 'tests.*', 'tests']), license='GPLv3+', author='Shubham Chaudhary', author_email='me@shubhamchaudhary.in', From 2251d89ffd27fb18e6d96536a50730ff7cac9a15 Mon Sep 17 00:00:00 2001 From: Shubham Chaudhary Date: Tue, 13 Jun 2017 12:41:21 +0530 Subject: [PATCH 6/8] Update pre-commit settings --- .pre-commit-config.yaml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c235a57..0c1a2f0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,13 +1,14 @@ - repo: git@github.com:asottile/reorder_python_imports - sha: v0.3.0 - commit_stage: [commit] + sha: v0.3.2 + commit_stage: + - commit hooks: - id: reorder-python-imports stages: commit_stage - - repo: git://github.com/pre-commit/pre-commit-hooks - sha: v0.6.0 - commit_stage: [commit] + sha: v0.8.0 + commit_stage: + - commit hooks: - id: trailing-whitespace - id: check-ast @@ -15,16 +16,15 @@ - id: check-merge-conflict - id: check-symlinks - id: debug-statements - #- id: detect-aws-credentials - id: detect-private-key - id: double-quote-string-fixer - id: end-of-file-fixer - id: fix-encoding-pragma - id: flake8 stages: commit_stage - - repo: local - push_stage: [push] + push_stage: + - push hooks: - id: check-tox name: Tox Tests From 10191aacd4a8aa380857ec5e3260555c66fbae07 Mon Sep 17 00:00:00 2001 From: Shubham Chaudhary Date: Tue, 13 Jun 2017 12:49:19 +0530 Subject: [PATCH 7/8] Install pandoc in dev environment --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 9b5a6e8..f145696 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,10 @@ matrix: - python: 2.6 - python: 2.7 - python: pypy +addons: + apt: + packages: + - pandoc install: - pip install -r requirements.txt - pip install -r requirements-dev.txt From abbe58bfa03500d960e94e33a73f8470263590ff Mon Sep 17 00:00:00 2001 From: Shubham Chaudhary Date: Tue, 13 Jun 2017 12:56:24 +0530 Subject: [PATCH 8/8] Disable older build matrix --- .travis.yml | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index f145696..de125e6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,18 +1,10 @@ language: python python: - - 2.6 - - 2.7 - - pypy - - 3.2 - 3.3 - 3.4 + - 3.5 + - 3.6 - nightly - - pypy3 -matrix: - allow_failures: - - python: 2.6 - - python: 2.7 - - python: pypy addons: apt: packages: