diff --git a/.travis.yml b/.travis.yml index 9f5df90..e1549f2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,4 +4,4 @@ python: # command to install dependencies install: pip install -r requirements.txt --use-mirrors # command to run tests -script: nosetests +script: utils/pre-commit.txt diff --git a/debian/changelog b/debian/changelog index 8c4f9ba..a734731 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,5 @@ -tonicdnscli (0.9-1) unstable; urgency=low +tonicdnscli (0.10-1) unstable; urgency=low * Initial release (Closes: #679426) - -- Kouhei Maeda Thu, 13 Sep 2012 15:20:15 +0900 + -- Kouhei Maeda Mon, 01 Apr 2013 16:50:28 +0900 diff --git a/debian/control b/debian/control index db2066f..b23b6c7 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: tonicdnscli Section: python Priority: optional Maintainer: Kouhei Maeda -Build-Depends: debhelper (>= 8.0.0), python-all, python-setuptools, python-nose, python-minimock, pep8, python-mock +Build-Depends: debhelper (>= 8.0.0), python-all, python-setuptools, python-pytest, python-minimock, pep8, python-mock Standards-Version: 3.9.3 X-Python-Version: 2.7 Homepage: https://github.com/mkouhei/tonicdnscli diff --git a/debian/rules b/debian/rules index 7f60ffc..95a7af4 100755 --- a/debian/rules +++ b/debian/rules @@ -14,9 +14,9 @@ override_dh_auto_test: set -e; \ - PYTHONPATH=$(CURDIR)/src nosetests -d + py.test -v $(CURDIR)/_build override_dh_install: dh_install - rm -rf $(CURDIR)/debian/python-tonicdnscli/usr/share/pyshared/tonicdnscli/tests - rm -rf $(CURDIR)/debian/python-tonicdnscli/usr/lib/python2.7/dist-packages/tonicdnscli/tests \ No newline at end of file + find $(CURDIR)/debian/python-tonicdnscli -name "*pyc" -delete + find $(CURDIR)/debian/python-tonicdnscli -type d -a -empty -delete diff --git a/docs/HISTORY.rst b/docs/HISTORY.rst index 5810ffd..2ceecd5 100644 --- a/docs/HISTORY.rst +++ b/docs/HISTORY.rst @@ -1,6 +1,12 @@ History ------- +0.10 (2013-04-01) +^^^^^^^^^^^^^^^^^ + +* Change format of pretty print +* move test directory + 0.9 (2012-09-13) ^^^^^^^^^^^^^^^^ diff --git a/docs/README.rst b/docs/README.rst index b1c1297..742b564 100644 --- a/docs/README.rst +++ b/docs/README.rst @@ -88,11 +88,12 @@ Retrieve all zones Get all zones and print.:: $ tonicdnscli get -u tonicusername -P - ============================================================================== - name type notified_serial - ============================================================================== - example.org MASTER 2012052201 - example.net MASTER 2012060502 + +-------------+--------+-----------------+ + | name | type | notified_serial | + +-------------+--------+-----------------+ + | example.org | MASTER | 2012052201 | + | example.net | MASTER | 2012060502 | + +-------------+--------+-----------------+ Retrieve records @@ -101,20 +102,20 @@ Retrieve records Get records of specific zone and print.:: $ tonicdnscli get -s ns.example.org -d example.org -u tonicusername -P - domain: example.org - serial: 2012042403 - DNS : MASTER - ============================================================================== - name type content ttl prio - ============================================================================== - example.org SOA - > ns.example.org hostmaster.example.org 2012042403 86400 - example.org NS ns.example.org 86400 - example.org NS ns2.example.org 86400 - ns.example.org A 192.168.0.100 86400 - ns2.example.org A 192.168.0.101 86400 - www.example.org A 192.168.0.1 86400 - ============================================================================== + zone: example.org + SOA record: ns.example.org hostmaster.example.org 2012042403 + ttl: 86400 + change date: 1341314161 + example.org + +------+------+-----------------+-------+------+-------------+ + | name | type | content | ttl | prio | change date | + +------+------+-----------------+-------+------+-------------+ + | | NS | ns.example.org | 86400 | - | - | + | | NS | ns2.example.org | 86400 | - | - | + | ns. | A | 192.168.0.100 | 86400 | - | - | + | ns2. | A | 192.168.0.101 | 86400 | - | - | + | www. | A | 192.168.0.1 | 86400 | - | - | + +------+------+-----------------+-------+------+-------------+ Create single record @@ -253,9 +254,9 @@ Firstly copy pre-commit hook script.:: $ cp -f utils/pre-commit.txt .git/hooks/pre-commit -Next install python2.7 later, and nosetests. Below in Debian GNU/Linux Sid system,:: +Next install python2.7 later, and py.test. Below in Debian GNU/Linux Sid system,:: - $ sudo apt-get install python python-nose + $ sudo apt-get install python python-pytest Then checkout 'devel' branch for development, commit your changes. Before pull request, execute git rebase. diff --git a/requirements.txt b/requirements.txt index f2f5330..cd01c7a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -pep8==1.2 +pep8==1.4 minimock diff --git a/setup.py b/setup.py index 951ce99..9696d64 100755 --- a/setup.py +++ b/setup.py @@ -1,7 +1,6 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ - Copyright (C) 2012 Kouhei Maeda + Copyright (C) 2012, 2013 Kouhei Maeda This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -56,14 +55,14 @@ install_requires=requires, extras_require=dict( test=[ - 'Nose', + 'pytest', 'pep8', 'unittest', 'minimock', ], ), - test_suite='nose.collector', - tests_require=['Nose','pep8','minimock'], + test_suite='tests', + tests_require=['pytest','pep8','minimock'], entry_points=""" [console_scripts] tonicdnscli = tonicdnscli.command:main diff --git a/src/tonicdnscli/tests/__init__.py b/src/tests/__init__.py similarity index 100% rename from src/tonicdnscli/tests/__init__.py rename to src/tests/__init__.py diff --git a/src/tonicdnscli/tests/test__init__.py b/src/tests/test__init__.py similarity index 78% rename from src/tonicdnscli/tests/test__init__.py rename to src/tests/test__init__.py index 298ce9a..29f585c 100644 --- a/src/tonicdnscli/tests/test__init__.py +++ b/src/tests/test__init__.py @@ -1,10 +1,12 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ Tests of __init__.py """ import unittest +import sys +import os.path +sys.path.append(os.path.abspath('src')) import tonicdnscli @@ -12,7 +14,3 @@ class InitTests(unittest.TestCase): def test_version_defined(self): actual_version = tonicdnscli.__version__ self.assertTrue(actual_version) - - -if __name__ == '__main__': - unittest.main() diff --git a/src/tests/test_command.py b/src/tests/test_command.py new file mode 100644 index 0000000..deed509 --- /dev/null +++ b/src/tests/test_command.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- + +""" +Tests of command.py +""" +import unittest +import sys +import os.path +sys.path.append(os.path.abspath('src')) +import tonicdnscli.command as c +import test_vars as v + + +class commandTests(unittest.TestCase): + def setUp(self): + import os.path + self.maxDiff = None + self.domain = 'example.org' + self.cu_records = [{'records': v.dicts1}] + self.r_records = [{'name': 'example.org', + 'records': self.cu_records[0].get('records')}] + self.record = ['test3.example.org A 10.10.20.10 3600'] + self.d_cu_record = [{'records': [{'name': 'test3.example.org', + 'type': 'A', + 'content': '10.10.20.10', + 'ttl': 3600}]}] + self.d_r_record = [{'name': self.domain, + 'records': [{'name': 'test3.example.org', + 'type': 'A', + 'content': '10.10.20.10', + 'ttl': 3600}]}] + sample0 = os.path.dirname(__file__) + \ + '/../../../examples/example.org.txt' + sample1 = os.path.dirname(__file__) + '/../../examples/example.org.txt' + if os.path.isfile(sample0): + self.sample = sample0 + elif os.path.isfile(sample1): + self.sample = sample1 + + def test_check_infile(self): + self.assertEquals(self.domain, c.check_infile(self.sample)) + + def test_set_json(self): + self.assertEquals(self.cu_records, + c.set_json(self.domain, True, filename=self.sample)) + self.assertEquals(self.r_records, + c.set_json(self.domain, False, filename=self.sample)) + self.assertEquals(self.d_cu_record, + c.set_json(self.domain, True, record=self.record)) + self.assertEquals(self.d_r_record, + c.set_json(self.domain, False, record=self.record)) diff --git a/src/tests/test_connect.py b/src/tests/test_connect.py new file mode 100644 index 0000000..509ea11 --- /dev/null +++ b/src/tests/test_connect.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- + +""" +Tests of connect.py +""" +import unittest +from minimock import mock, Mock, restore +import sys +if sys.version_info > (2, 6) and sys.version_info < (2, 8): + import StringIO as io +elif sys.version_info > (3, 0): + import io as io +if sys.version_info > (2, 6) and sys.version_info < (2, 8): + import urllib2 as urllib +elif sys.version_info > (3, 0): + import urllib.request as urllib +import os.path +sys.path.append(os.path.abspath('src')) +import tonicdnscli.connect as conn +import test_vars as v + + +class connectTests(unittest.TestCase): + def setUp(self): + self.datajson = v.datajson + + self.datadict = v.datadict + + urllib.build_opener = Mock( + 'build_opener', + returns=Mock( + 'opener', + open=Mock( + 'opener.open', + returns=Mock( + 'opener.open', + read=Mock( + 'opener.open.read', + returns=self.datajson))))) + + self.uri = v.uri + self.token = v.token + self.data = '' + + def tearDown(self): + restore() + + def test_tonicdns_client(self): + dumpout = io.StringIO() + ostdout = sys.stdout + sys.stdout = dumpout + uri = self.uri + '/zone/example.org' + conn.tonicdns_client(uri, + 'GET', self.token, self.data) + sys.stdout = ostdout + dumpout.seek(0) + self.assert_(dumpout.getvalue()) + + def test_print_formatted(self): + dumpout = io.StringIO() + ostdout = sys.stdout + sys.stdout = dumpout + conn.print_formatted(self.datadict) + sys.stdout = ostdout + dumpout.seek(0) + self.assert_(dumpout.getvalue()) diff --git a/src/tests/test_converter.py b/src/tests/test_converter.py new file mode 100644 index 0000000..b1a6e86 --- /dev/null +++ b/src/tests/test_converter.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- + +""" +Tests of converter.py +""" +import unittest +import sys +import os.path +sys.path.append(os.path.abspath('src')) +from tonicdnscli.converter import JSONConverter +import test_vars as v + + +class JSONConvertTests(unittest.TestCase): + + def setUp(self): + sample0 = os.path.dirname(__file__) + \ + '/../../../examples/example.org.txt' + sample1 = os.path.dirname(__file__) + '/../../examples/example.org.txt' + if os.path.isfile(sample0): + self.sample = sample0 + elif os.path.isfile(sample1): + self.sample = sample1 + + def test__init__(self): + o = JSONConverter('example.org') + self.assertEquals('example.org', o.domain) + self.assertEquals(0, o.split_index) + self.assertListEqual([], o.records) + self.assertListEqual([], o.separated_list) + self.assertFalse(o.delta) + + def test_read_records(self): + o = JSONConverter('example.org') + o.read_records(v.str2.splitlines()) + self.assertListEqual(v.dicts1, o.records) + + def test_check_key(self): + o = JSONConverter('example.org') + self.assertEquals("test0.example.org", o.check_key(v.line1, 0)) + self.assertEquals("A", o.check_key(v.line1, 1)) + self.assertEquals("10.10.10.10", o.check_key(v.line1, 2)) + self.assertEquals("86400", o.check_key(v.line1, 3)) + self.assertFalse(o.check_key(v.line1, 4)) + self.assertEquals("0", o.check_key(v.line2, 4)) + self.assertFalse(o.check_key(v.line2, 5)) + self.assertEquals("10.10.11.10", o.check_key(v.line3, 2)) + + def test_generate_records(self): + o = JSONConverter('example.org') + o.generate_records(v.line1) + self.assertListEqual(v.list3, o.records) + o2 = JSONConverter('example.org') + o2.generate_records(v.line2) + self.assertListEqual(v.list4, o2.records) + + def test_generata_data(self): + o1 = JSONConverter('example.org') + o1.generata_data(True) + self.assertListEqual([{'records': []}], o1.dict_records) + o2 = JSONConverter('example.org') + o2.generata_data(False) + self.assertListEqual([{'records': [], 'name': 'example.org'}], + o2.dict_records) + + def test_separate_input_file(self): + import os.path + o = JSONConverter('example.org') + with open(self.sample, 'r') as f: + o.separate_input_file(f) + self.maxDiff = None + self.assertListEqual([v.str1], o.separated_list) + o2 = JSONConverter('example.org') + o2.delta = 3 + with open(self.sample, 'r') as f2: + o2.separate_input_file(f2) + self.assertListEqual(v.str_l, o2.separated_list) + + def test_get_soa(self): + o = JSONConverter('exmaple.org') + self.assertEquals(v.new_soa, + o.get_soa(v.older_cur_soa, v.content)) + self.assertNotEquals(v.new_soa, + o.get_soa(v.today_cur_soa, v.content)) diff --git a/src/tests/test_pep8.py b/src/tests/test_pep8.py new file mode 100644 index 0000000..32f0b82 --- /dev/null +++ b/src/tests/test_pep8.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +import sys +import os +import pep8 +CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) +BASE_DIR = os.path.dirname(CURRENT_DIR) + + +def test_pep8(): + arglist = [['statistics', True], + ['show-source', True], + ['repeat', True], + ['exclude', ['gen-py', 'GAuth.py', + 'ttypes.py', 'constants.py']], + ['paths', [BASE_DIR]]] + + pep8style = pep8.StyleGuide(arglist, parse_argv=False, config_file=True) + options = pep8style.options + if options.doctest: + import doctest + fail_d, done_d = doctest.testmod(report=False, verbose=options.verbose) + fail_s, done_s = selftest(options) + count_failed = fail_s + fail_d + if not options.quiet: + count_passed = done_d + done_s - count_failed + print("%d passed and %d failed." % (count_passed, count_failed)) + print("Test failed." if count_failed else "Test passed.") + if count_failed: + sys.exit(1) + if options.testsuite: + init_tests(pep8style) + report = pep8style.check_files() + if options.statistics: + report.print_statistics() + if options.benchmark: + report.print_benchmark() + if options.testsuite and not options.quiet: + report.print_results() + if report.total_errors: + if options.count: + sys.stderr.write(str(report.total_errors) + '\n') + sys.exit(1) + + # reporting errors (additional summary) + errors = report.get_count('E') + warnings = report.get_count('W') + message = 'pep8: %d errors / %d warnings' % (errors, warnings) + print message + assert report.total_errors == 0, message diff --git a/src/tonicdnscli/tests/test_processing.py b/src/tests/test_processing.py similarity index 56% rename from src/tonicdnscli/tests/test_processing.py rename to src/tests/test_processing.py index 10c5c3b..5888143 100644 --- a/src/tonicdnscli/tests/test_processing.py +++ b/src/tests/test_processing.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ @@ -10,6 +9,8 @@ import StringIO as io elif sys.version_info > (3, 0): import io as io +import os.path +sys.path.append(os.path.abspath('src')) from mock import Mock import tonicdnscli.connect as conn import tonicdnscli.processing as p @@ -22,42 +23,42 @@ def setUp(self): self.identifier = 'example_org' self.token = 'efb9fc406a15bf9bdc60f52b36c14bcc6a1fd041' self.list0 = [{'content': '10.10.10.10', 'name': 'test0.example.org', - 'ttl': 86400, 'type': 'A'}, - {'content': '10.10.10.11', 'name': 'test1.example.org', - 'ttl': 86400, 'type': 'A'}, - {'content': '10.10.10.12', 'name': 'test2.example.org', - 'ttl': 86400, 'type': 'A'}, - {'content': 'mx2.example.org', 'name': 'example.org', - 'priority': 10, 'ttl': 86400, 'type': 'MX'}, - {'content': '10.10.11.10', 'name': 'mx.example.org', - 'ttl': 3600, 'type': 'A'}, - {'content': '10.10.11.10', 'name': 'mx2.example.org', - 'ttl': 3600, 'type': 'A'}] + 'ttl': 86400, 'type': 'A'}, + {'content': '10.10.10.11', 'name': 'test1.example.org', + 'ttl': 86400, 'type': 'A'}, + {'content': '10.10.10.12', 'name': 'test2.example.org', + 'ttl': 86400, 'type': 'A'}, + {'content': 'mx2.example.org', 'name': 'example.org', + 'priority': 10, 'ttl': 86400, 'type': 'MX'}, + {'content': '10.10.11.10', 'name': 'mx.example.org', + 'ttl': 3600, 'type': 'A'}, + {'content': '10.10.11.10', 'name': 'mx2.example.org', + 'ttl': 3600, 'type': 'A'}] self.dict0 = {'records': self.list0} self.dict1 = {'name': self.domain, 'records': self.list0} self.dict2 = {'identifier': self.identifier, 'description': 'example', - 'entries': [ - {'name': self.domain, - 'type': 'SOA', - 'content': 'ns.example.org hostmaster.example.org \ -2012020501 3600 900 86400 3600', - 'ttl': 86400}, - {'name': self.domain, - 'type': 'NS', - 'content': 'ns' + self.domain, - 'ttl': 86400}, - {'name': self.domain, - 'type': 'A', - 'content': '10.0.0.100', - 'ttl': 86400}, - {'name': self.domain, - 'type': 'MX', - 'content': 'mx.' + self.domain, - 'ttl': 86400, - 'priority': 10}, - ]} + 'entries': [{'name': self.domain, + 'type': 'SOA', + 'content': 'ns.example.org ' + 'hostmaster.example.org ' + '2012020501 3600 900 86400 3600', + 'ttl': 86400}, + {'name': self.domain, + 'type': 'NS', + 'content': 'ns' + self.domain, + 'ttl': 86400}, + {'name': self.domain, + 'type': 'A', + 'content': '10.0.0.100', + 'ttl': 86400}, + {'name': self.domain, + 'type': 'MX', + 'content': 'mx.' + self.domain, + 'ttl': 86400, + 'priority': 10}, + ]} def test_create_records(self): conn.tonicdns_client = Mock(return_value='true') @@ -90,7 +91,7 @@ def test_create_template(self): sys.stdout = dumpout print(conn.tonicdns_client()) p.create_template(self.server, self.token, - self.identifier, self.dict2) + self.identifier, self.dict2) sys.stdout = ostdout dumpout.seek(0) dumpout.getvalue() @@ -103,11 +104,8 @@ def test_delete_template(self): sys.stdout = dumpout print(conn.tonicdns_client()) p.delete_template(self.server, self.token, - self.identifier) + self.identifier) sys.stdout = ostdout dumpout.seek(0) dumpout.getvalue() self.assertEquals('true\n', dumpout.getvalue()) - -if __name__ == '__main__': - unittest.main() diff --git a/src/tests/test_utils.py b/src/tests/test_utils.py new file mode 100644 index 0000000..92a8865 --- /dev/null +++ b/src/tests/test_utils.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- + +""" +Tests of utils.py +""" +import unittest +import sys +import os.path +sys.path.append(os.path.abspath('src')) +import test_vars as v +import tonicdnscli.utils as u + + +class connectTests(unittest.TestCase): + def setUp(self): + + self.datajson = v.datajson + self.datadict = v.datadict + + def test_print_inline(self): + pass + + def test_error(self): + pass + + def test_get_columns_width(self): + pass + + def test_generate_row_s(self): + pass + + def test_get_row_s(self): + pass + + def test_print_header(self): + pass + + def test_print_bottom(self): + pass + + def test_pretty_print(self): + pass + + def test_pretty_print_zones(self): + pass + + def test_pretty_print_domain(self): + pass diff --git a/src/tests/test_vars.py b/src/tests/test_vars.py new file mode 100644 index 0000000..50e9657 --- /dev/null +++ b/src/tests/test_vars.py @@ -0,0 +1,103 @@ +# -*- coding: utf-8 -*- +""" +variable for tests +""" +from datetime import date + + +datajson = ( + '{"name": "example.org", "type": "MASTER",' + '"notified_serial": "2012042701", ' + '"records": [{"name": "example.org", "type": "SOA", "content": ' + '"ns.example.org hostmaster.example.org 2012020501 ' + '3600 900 86400 3600", "ttl": "86400", "priority": null, ' + '"change_date": "1328449038"},' + '{"name": "example.org", "type": "NS", ' + '"content": "ns.example.org", "ttl": "86400", "priority": null, ' + '"change_date":"1328449038"}]}') + +datadict = {"name": "example.org", "type": "MASTER", + "notified_serial": "2012042701", + "records": [ + {"name": "example.org", "type": "SOA", + "content": "ns.example.org hostmaster.example.org " + "2012020501 3600 900 86400 3600", + "ttl": "86400", "priority": False, + "change_date": "1328449038"}, + {"name": "example.org", "type": "NS", + "content": "ns.example.org", + "ttl": "86400", "priority": False, + "change_date": "1328449038"}]} + +uri = 'https://ns.example.org' +token = 'efb9fc406a15bf9bdc60f52b36c14bcc6a1fd041' + +str_l = ['test0.example.org A 10.10.10.10 86400\n' + 'test1.example.org A 10.10.10.11 86400\n' + 'test2.example.org A 10.10.10.12 86400\n', + 'example.org MX mx.example.org 86400 0\n' + 'example.org MX mx2.example.org 86400 10\n' + 'mx.example.org A 10.10.11.10 3600\n', + 'mx2.example.org A\t\t10.10.11.10 3600\n'] + +str1 = (str_l[0] + str_l[1] + str_l[2]) + +str2 = ('# name type content ttl priority\n' + str1) + +list3 = [{'name': 'test0.example.org', 'type': 'A', + 'content': '10.10.10.10', 'ttl': 86400}] + +list4 = [{'name': 'example.org', 'type': 'MX', + 'content': 'mx.example.org', 'ttl': 86400, 'priority': 0}] + +dicts1 = [{'content': '10.10.10.10', 'name': 'test0.example.org', + 'ttl': 86400, 'type': 'A'}, + {'content': '10.10.10.11', 'name': 'test1.example.org', + 'ttl': 86400, 'type': 'A'}, + {'content': '10.10.10.12', 'name': 'test2.example.org', + 'ttl': 86400, 'type': 'A'}, + {'content': 'mx.example.org', 'name': 'example.org', + 'priority': 0, 'ttl': 86400, 'type': 'MX'}, + {'content': 'mx2.example.org', 'name': 'example.org', + 'priority': 10, 'ttl': 86400, 'type': 'MX'}, + {'content': '10.10.11.10', 'name': 'mx.example.org', + 'ttl': 3600, 'type': 'A'}, + {'content': '10.10.11.10', 'name': 'mx2.example.org', + 'ttl': 3600, 'type': 'A'}] + +line1 = "test0.example.org A 10.10.10.10 86400" +line2 = "example.org MX mx.example.org 86400 0" +line3 = "mx2.example.org A\t\t10.10.11.10 3600" + +older_cur_soa = { + 'name': 'example.org', + 'type': 'SOA', + 'content': 'ns.example.org postmaster.example.org 2012040501', + 'ttl': 86400, + 'priority': None} + +today = date.strftime(date.today(), '%Y%m%d') + +today_cur_soa = { + 'name': 'example.org', + 'type': 'SOA', + 'content': 'ns.example.org postmaster.example.org ' + today + '01', + 'ttl': 86400, + 'priority': None} + +new_soa = { + 'name': 'example.org', + 'type': 'SOA', + 'content': 'ns.example.org postmaster.example.org ' + + today + '01 3600 900 86400 3600', + 'ttl': 86400, + 'priority': None} + +content = { + 'domain': 'example.org', + 'mname': 'ns.example.org', + 'rname': 'postmaster.example.org', + 'refresh': 3600, + 'retry': 900, + 'expire': 86400, + 'minimum': 3600} diff --git a/src/tonicdnscli/__init__.py b/src/tonicdnscli/__init__.py index 8413c07..8e803bb 100644 --- a/src/tonicdnscli/__init__.py +++ b/src/tonicdnscli/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ - Copyright (C) 2012 Kouhei Maeda + Copyright (C) 2012, 2013 Kouhei Maeda This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,5 +16,5 @@ along with this program. If not, see . """ -__version__ = '0.9' +__version__ = '0.10' __timeout__ = 5 diff --git a/src/tonicdnscli/command.py b/src/tonicdnscli/command.py index 5551c50..42ece48 100644 --- a/src/tonicdnscli/command.py +++ b/src/tonicdnscli/command.py @@ -1,7 +1,6 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ - Copyright (C) 2012 Kouhei Maeda + Copyright (C) 2012, 2013 Kouhei Maeda This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -181,8 +180,8 @@ def create(args): # for PUT HTTP method action = True - if (args.__dict__.get('domain') and args.__dict__.get('name') - and args.__dict__.get('rtype') and args.__dict__.get('content')): + if ((args.__dict__.get('domain') and args.__dict__.get('name') + and args.__dict__.get('rtype') and args.__dict__.get('content'))): # for create sub-command domain = args.domain @@ -219,8 +218,8 @@ def delete(args): # for DELETE HTTP method action = False - if (args.__dict__.get('domain') and args.__dict__.get('name') - and args.__dict__.get('rtype') and args.__dict__.get('content')): + if ((args.__dict__.get('domain') and args.__dict__.get('name') + and args.__dict__.get('rtype') and args.__dict__.get('content'))): # for delete sub-command domain = args.domain @@ -257,10 +256,10 @@ def update(args): Firstly call delete(), then create(). """ # Check specifying some new values - if (not args.__dict__.get('new_type') and - not args.__dict__.get('new_content') and - not args.__dict__.get('new_ttl') and - not args.__dict__.get('new_priority')): + if ((not args.__dict__.get('new_type') and + not args.__dict__.get('new_content') and + not args.__dict__.get('new_ttl') and + not args.__dict__.get('new_priority'))): utils.error("Not update any values.") args.__dict__['search'] = (args.__dict__.get('name') + ',' + @@ -441,11 +440,11 @@ def set_option(prs, keyword, required=False): if keyword == 'infile': prs.add_argument('infile', action='store', - help='pre-converted text file') + help='pre-converted text file') if keyword == 'domain': prs.add_argument('--domain', action='store', required=True, - help='create record with specify domain') + help='create record with specify domain') prs.add_argument('--name', action='store', required=True, help='specify with domain option') prs.add_argument('--rtype', action='store', required=True, @@ -453,9 +452,10 @@ def set_option(prs, keyword, required=False): prs.add_argument('--content', action='store', required=True, help='specify with domain option') prs.add_argument('--ttl', action='store', default='3600', - help='specify with domain option, default 3600') + help='specify with domain option, default 3600') prs.add_argument('--priority', action='store', default=False, - help='specify with domain and rtype options as MX|SRV') + help='specify with domain and ' + 'rtype options as MX|SRV') if keyword == 'update': prs.add_argument('--new-type', action='store', @@ -519,7 +519,7 @@ def parse_options(): prs = argparse.ArgumentParser(description='usage') prs.add_argument('-v', '--version', action='version', - version=__version__) + version=__version__) if os.environ.get('HOME'): config_file = os.environ.get('HOME') + '/.tdclirc' if os.path.isfile(config_file): @@ -579,7 +579,7 @@ def parse_show(prs): prs: parser object of argparse """ prs_show = prs.add_parser('show', - help='show converted JSON') + help='show converted JSON') set_option(prs_show, 'infile') prs_show.set_defaults(func=show) @@ -722,7 +722,7 @@ def parse_update_soa(prs, conn): """ prs_soa = prs.add_parser('soa', help='update SOA record') prs_soa.add_argument('--domain', action='store', required=True, - help='specify domain FQDN') + help='specify domain FQDN') prs_soa.add_argument('--mname', action='store', help='specify MNAME of SOA record') prs_soa.add_argument('--rname', action='store', @@ -751,7 +751,7 @@ def parse_create_zone(prs, conn): prs_zone_create.add_argument( '--domain', action='store', required=True, help='specify zone') prs_zone_create.add_argument('--dnsaddr', action='store', required=True, - help='specify IP address of DNS master') + help='specify IP address of DNS master') group_zone_create = prs_zone_create.add_mutually_exclusive_group() group_zone_create.add_argument('-S', action='store_true', help='create zone to SLAVE') diff --git a/src/tonicdnscli/connect.py b/src/tonicdnscli/connect.py index 944e936..e2478af 100644 --- a/src/tonicdnscli/connect.py +++ b/src/tonicdnscli/connect.py @@ -1,7 +1,6 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ - Copyright (C) 2012 Kouhei Maeda + Copyright (C) 2012, 2013 Kouhei Maeda This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -44,8 +43,7 @@ def get_token(username, password, server): authinfo = { "username": username, "password": password, - "local_user": username - } + "local_user": username} token = tonicdns_client(uri, method, token, data=authinfo) @@ -182,19 +180,26 @@ def response(uri, method, res, token='', keyword='', if len(uri.split('/')) == 5: # when specify template identfier - print_formatted(datas) + #print_formatted(datas) + utils.pretty_print(datas) else: # when get all templates for data in datas: - print_formatted(data) + #print_formatted(data) + utils.pretty_print(datas) else: # 'get' subcommand if raw_flag: return datas else: - print_formatted(datas) + #print_formatted(datas) + if len(uri.split('zone/')) > 1: + domain = uri.split('zone/')[1] + else: + domain = '' + utils.pretty_print(datas, keyword, domain) else: # response non JSON data @@ -231,18 +236,18 @@ def search_record(datas, keyword): if key_name and key_type: if key_content: - if (record['name'].find(key_name) > -1 and - record['type'] == key_type and - record['content'].find(key_content) > -1): + if ((record['name'].find(key_name) > -1 and + record['type'] == key_type and + record['content'].find(key_content) > -1)): result.append(record) else: - if (record['name'].find(key_name) > -1 and - record['type'] == key_type): + if ((record['name'].find(key_name) > -1 and + record['type'] == key_type)): result.append(record) - elif (record['name'].find(keyword) >= 0 or - record['content'].find(keyword) >= 0 or - record['type'] == keyword): + elif ((record['name'].find(keyword) >= 0 or + record['content'].find(keyword) >= 0 or + record['type'] == keyword)): result.append(record) return result diff --git a/src/tonicdnscli/converter.py b/src/tonicdnscli/converter.py index 7fa0643..217e51b 100644 --- a/src/tonicdnscli/converter.py +++ b/src/tonicdnscli/converter.py @@ -1,7 +1,6 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ - Copyright (C) 2012 Kouhei Maeda + Copyright (C) 2012, 2013 Kouhei Maeda This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -57,12 +56,10 @@ def generate_records(self, line): "name": self.check_key(line, 0), "type": self.check_key(line, 1), "content": self.check_key(line, 2), - "ttl": int(self.check_key(line, 3)) - } + "ttl": int(self.check_key(line, 3))} if self.check_key(line, 4): d.update( - {"priority": int(self.check_key(line, 4))} - ) + {"priority": int(self.check_key(line, 4))}) self.records.append(d) def generate_template(self, domain, ipaddr, desc): @@ -70,24 +67,22 @@ def generate_template(self, domain, ipaddr, desc): serial = date.strftime(date.today(), '%Y%m%d') + '01' ns = 'ns.' + domain soa = (ns + ' hostmaster.' + domain + - ' ' + serial + ' ' + self.refresh + ' ' + self.retry + - ' ' + self.expire + ' ' + str(self.ttl)) + ' ' + serial + ' ' + self.refresh + ' ' + self.retry + + ' ' + self.expire + ' ' + str(self.ttl)) self.record = { - 'identifier': domain.replace('.', '_'), - 'description': desc, - 'entries': [ + 'identifier': domain.replace('.', '_'), + 'description': desc, + 'entries': [ self.record(domain, 'SOA', soa), self.record(domain, 'NS', ns), - self.record(ns, 'A', ipaddr) - ]} + self.record(ns, 'A', ipaddr)]} def record(self, name, rtype, content): record_d = { 'name': name, 'type': rtype, 'content': content, - 'ttl': self.ttl - } + 'ttl': self.ttl} return record_d def generate_zone(self, domain, template, dtype, master=None): @@ -97,10 +92,7 @@ def generate_zone(self, domain, template, dtype, master=None): "name": domain, "type": dtype, "master": master, - "templates": [ - {"identifier": template} - ] - } + "templates": [{"identifier": template}]} def check_key(self, key, index): import re @@ -172,6 +164,7 @@ def get_soa(self, record, content): serial = str(int(cur_serial) + 1) new_record['content'] = (mname + ' ' + rname + ' ' + - serial + ' ' + self.refresh + ' ' + self.retry + ' ' + - self.expire + ' ' + str(self.ttl)) + serial + ' ' + self.refresh + + ' ' + self.retry + ' ' + + self.expire + ' ' + str(self.ttl)) return new_record diff --git a/src/tonicdnscli/processing.py b/src/tonicdnscli/processing.py index e6208e7..5a3a0db 100644 --- a/src/tonicdnscli/processing.py +++ b/src/tonicdnscli/processing.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- """ - Copyright (C) 2012 Kouhei Maeda + Copyright (C) 2012, 2013 Kouhei Maeda This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/tonicdnscli/tests/test_command.py b/src/tonicdnscli/tests/test_command.py deleted file mode 100644 index d3bd699..0000000 --- a/src/tonicdnscli/tests/test_command.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -""" -Tests of command.py -""" -import unittest -import tonicdnscli.command as c - - -class commandTests(unittest.TestCase): - def setUp(self): - import os.path - self.maxDiff = None - self.sample = os.path.dirname(__file__) + \ - '/../../../examples/example.org.txt' - self.domain = 'example.org' - self.cu_records = [{'records': - [{'content': '10.10.10.10', - 'type': 'A', - 'name': 'test0.example.org', - 'ttl': 86400}, - {'content': '10.10.10.11', - 'type': 'A', - 'name': 'test1.example.org', - 'ttl': 86400}, - {'content': '10.10.10.12', - 'type': 'A', - 'name': 'test2.example.org', - 'ttl': 86400}, - {'content': 'mx.example.org', - 'priority': 0, - 'type': 'MX', - 'name': 'example.org', - 'ttl': 86400}, - {'content': 'mx2.example.org', - 'priority': 10, - 'type': 'MX', - 'name': 'example.org', - 'ttl': 86400}, - {'content': '10.10.11.10', - 'type': 'A', - 'name': 'mx.example.org', - 'ttl': 3600}, - {'content': '10.10.11.10', - 'type': 'A', - 'name': 'mx2.example.org', - 'ttl': 3600}] - }] - self.r_records = [{'name': 'example.org', - 'records': self.cu_records[0].get('records')}] - self.record = ['test3.example.org A 10.10.20.10 3600'] - self.d_cu_record = [{'records': [{'name': 'test3.example.org', - 'type': 'A', - 'content': '10.10.20.10', - 'ttl': 3600}]}] - self.d_r_record = [{'name': self.domain, - 'records': [{'name': 'test3.example.org', - 'type': 'A', - 'content': '10.10.20.10', - 'ttl': 3600}]}] - - def test_check_infile(self): - self.assertEquals(self.domain, c.check_infile( - self.sample)) - - def test_set_json(self): - self.assertEquals(self.cu_records, - c.set_json(self.domain, True, filename=self.sample)) - self.assertEquals(self.r_records, - c.set_json(self.domain, False, filename=self.sample)) - self.assertEquals(self.d_cu_record, - c.set_json(self.domain, True, record=self.record)) - self.assertEquals(self.d_r_record, - c.set_json(self.domain, False, record=self.record)) - -if __name__ == '__main__': - unittest.main() diff --git a/src/tonicdnscli/tests/test_connect.py b/src/tonicdnscli/tests/test_connect.py deleted file mode 100644 index 346d8a5..0000000 --- a/src/tonicdnscli/tests/test_connect.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -""" -Tests of connect.py -""" -import unittest -from minimock import mock, Mock, restore -import tonicdnscli.connect as conn -import sys -if sys.version_info > (2, 6) and sys.version_info < (2, 8): - import StringIO as io -elif sys.version_info > (3, 0): - import io as io - -if sys.version_info > (2, 6) and sys.version_info < (2, 8): - import urllib2 as urllib -elif sys.version_info > (3, 0): - import urllib.request as urllib - - -class connectTests(unittest.TestCase): - def setUp(self): - - self.datajson = '''{"name": "example.org", "type": "MASTER", -"notified_serial": "2012042701", -"records": [{"name": "example.org", "type": "SOA", "content": -"ns.example.org hostmaster.example.org 2012020501 3600 900 86400 3600", -"ttl": "86400", "priority": null, "change_date": "1328449038"}, -{"name": "example.org", "type": "NS", "content": "ns.example.org", -"ttl": "86400", "priority": null, "change_date":"1328449038"}]}''' - - self.datadict = {"name": "example.org", "type": "MASTER", -"notified_serial": "2012042701", -"records": [{"name": "example.org", "type": "SOA", "content": -"ns.example.org hostmaster.example.org 2012020501 3600 900 86400 3600", -"ttl": "86400", "priority": False, "change_date": "1328449038"}, -{"name": "example.org", "type": "NS", "content": "ns.example.org", -"ttl": "86400", "priority": False, "change_date":"1328449038"}]} - - urllib.build_opener = Mock('build_opener', - returns=Mock('opener', - open=Mock('opener.open', - returns=Mock('opener.open', - read=Mock('opener.open.read', - returns=self.datajson))))) - - self.uri = 'https://ns.example.org' - self.token = 'efb9fc406a15bf9bdc60f52b36c14bcc6a1fd041' - self.data = '' - - def tearDown(self): - restore() - - def test_tonicdns_client(self): - dumpout = io.StringIO() - ostdout = sys.stdout - sys.stdout = dumpout - uri = self.uri + '/zone/example.org' - conn.tonicdns_client(uri, - 'GET', self.token, self.data) - sys.stdout = ostdout - dumpout.seek(0) - self.assert_(dumpout.getvalue()) - - def test_print_formatted(self): - dumpout = io.StringIO() - ostdout = sys.stdout - sys.stdout = dumpout - conn.print_formatted(self.datadict) - sys.stdout = ostdout - dumpout.seek(0) - self.assert_(dumpout.getvalue()) - -if __name__ == '__main__': - unittest.main() diff --git a/src/tonicdnscli/tests/test_converter.py b/src/tonicdnscli/tests/test_converter.py deleted file mode 100644 index a811606..0000000 --- a/src/tonicdnscli/tests/test_converter.py +++ /dev/null @@ -1,159 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -""" -Tests of converter.py -""" -import unittest -from tonicdnscli.converter import JSONConverter -from datetime import date - - -class JSONConvertTests(unittest.TestCase): - def setUp(self): - self.str1 = """# name type content ttl priority -test0.example.org A 10.10.10.10 86400 -test1.example.org A 10.10.10.11 86400 -test2.example.org A 10.10.10.12 86400 -example.org MX mx.example.org 86400 0 -example.org MX mx2.example.org 86400 10 -mx.example.org A 10.10.11.10 3600 -mx2.example.org A\t\t10.10.11.10 3600""" - self.list1 = ["""test0.example.org A 10.10.10.10 86400 -test1.example.org A 10.10.10.11 86400 -test2.example.org A 10.10.10.12 86400 -example.org MX mx.example.org 86400 0 -example.org MX mx2.example.org 86400 10 -mx.example.org A 10.10.11.10 3600 -mx2.example.org A\t\t10.10.11.10 3600 -"""] - self.list2 = ["""test0.example.org A 10.10.10.10 86400 -test1.example.org A 10.10.10.11 86400 -test2.example.org A 10.10.10.12 86400\n""", -"""example.org MX mx.example.org 86400 0 -example.org MX mx2.example.org 86400 10 -mx.example.org A 10.10.11.10 3600\n""", -'mx2.example.org A\t\t10.10.11.10 3600\n'] - - self.list3 = [{'name': 'test0.example.org', 'type': 'A', - 'content': '10.10.10.10', 'ttl': 86400}] - self.list4 = [{'name': 'example.org', 'type': 'MX', - 'content': 'mx.example.org', - 'ttl': 86400, 'priority': 0}] - - self.dicts1 = [{'content': '10.10.10.10', 'name': 'test0.example.org', - 'ttl': 86400, 'type': 'A'}, - {'content': '10.10.10.11', 'name': 'test1.example.org', - 'ttl': 86400, 'type': 'A'}, - {'content': '10.10.10.12', 'name': 'test2.example.org', - 'ttl': 86400, 'type': 'A'}, - {'content': 'mx.example.org', 'name': 'example.org', - 'priority': 0, 'ttl': 86400, 'type': 'MX'}, - {'content': 'mx2.example.org', 'name': 'example.org', - 'priority': 10, 'ttl': 86400, 'type': 'MX'}, - {'content': '10.10.11.10', 'name': 'mx.example.org', - 'ttl': 3600, 'type': 'A'}, - {'content': '10.10.11.10', 'name': 'mx2.example.org', - 'ttl': 3600, 'type': 'A'}] - self.line1 = "test0.example.org A 10.10.10.10 86400" - self.line2 = "example.org MX mx.example.org 86400 0" - self.line3 = "mx2.example.org A\t\t10.10.11.10 3600" - - self.older_cur_soa = { - 'name': 'example.org', - 'type': 'SOA', - 'content': 'ns.example.org postmaster.example.org 2012040501', - 'ttl': 86400, - 'priority': None - } - today = date.strftime(date.today(), '%Y%m%d') - self.today_cur_soa = { - 'name': 'example.org', - 'type': 'SOA', - 'content': 'ns.example.org postmaster.example.org ' + today + '01', - 'ttl': 86400, - 'priority': None - } - self.new_soa = { - 'name': 'example.org', - 'type': 'SOA', - 'content': 'ns.example.org postmaster.example.org ' - + today + '01 3600 900 86400 3600', - 'ttl': 86400, - 'priority': None - } - self.content = { - 'domain': 'example.org', - 'mname': 'ns.example.org', - 'rname': 'postmaster.example.org', - 'refresh': 3600, - 'retry': 900, - 'expire': 86400, - 'minimum': 3600 - } - - def test__init__(self): - o = JSONConverter('example.org') - self.assertEquals('example.org', o.domain) - self.assertEquals(0, o.split_index) - self.assertListEqual([], o.records) - self.assertListEqual([], o.separated_list) - self.assertFalse(o.delta) - - def test_read_records(self): - o = JSONConverter('example.org') - o.read_records(self.str1.splitlines()) - self.assertListEqual(self.dicts1, o.records) - - def test_check_key(self): - o = JSONConverter('example.org') - self.assertEquals("test0.example.org", o.check_key(self.line1, 0)) - self.assertEquals("A", o.check_key(self.line1, 1)) - self.assertEquals("10.10.10.10", o.check_key(self.line1, 2)) - self.assertEquals("86400", o.check_key(self.line1, 3)) - self.assertFalse(o.check_key(self.line1, 4)) - self.assertEquals("0", o.check_key(self.line2, 4)) - self.assertFalse(o.check_key(self.line2, 5)) - self.assertEquals("10.10.11.10", o.check_key(self.line3, 2)) - - def test_generate_records(self): - o = JSONConverter('example.org') - o.generate_records(self.line1) - self.assertListEqual(self.list3, o.records) - o2 = JSONConverter('example.org') - o2.generate_records(self.line2) - self.assertListEqual(self.list4, o2.records) - - def test_generata_data(self): - o1 = JSONConverter('example.org') - o1.generata_data(True) - self.assertListEqual([{'records': []}], o1.dict_records) - o2 = JSONConverter('example.org') - o2.generata_data(False) - self.assertListEqual([{'records': [], 'name': 'example.org'}], - o2.dict_records) - - def test_separate_input_file(self): - import os.path - sample = os.path.dirname(__file__) + \ - '/../../../examples/example.org.txt' - o = JSONConverter('example.org') - with open(sample, 'r') as f: - o.separate_input_file(f) - self.maxDiff = None - self.assertListEqual(self.list1, o.separated_list) - o2 = JSONConverter('example.org') - o2.delta = 3 - with open(sample, 'r') as f2: - o2.separate_input_file(f2) - self.assertListEqual(self.list2, o2.separated_list) - - def test_get_soa(self): - o = JSONConverter('exmaple.org') - self.assertEquals(self.new_soa, - o.get_soa(self.older_cur_soa, self.content)) - self.assertNotEquals(self.new_soa, - o.get_soa(self.today_cur_soa, self.content)) - -if __name__ == '__main__': - unittest.main() diff --git a/src/tonicdnscli/tests/test_pep8.py b/src/tonicdnscli/tests/test_pep8.py deleted file mode 100644 index 2ff0e52..0000000 --- a/src/tonicdnscli/tests/test_pep8.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import os -import pep8 - -CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) -BASE_DIR = os.path.dirname(CURRENT_DIR) - - -def test_pep8(): - arglist = [ - '--statistics', - '--filename=*.py', - '--show-source', - '--benchmark', - '--repeat', - '--show-pep8', - #'--qq', - #'-v', - BASE_DIR, - ] - - options, args = pep8.process_options(arglist) - runner = pep8.input_file - - for path in args: - if os.path.isdir(path): - pep8.input_dir(path, runner=runner) - elif not pep8.excluded(path): - options.counters['files'] += 1 - runner(path) - - pep8.print_statistics() - errors = pep8.get_count('E') - warnings = pep8.get_count('W') - message = 'pep8: %d errors / %d warnings' % (errors, warnings) - print(message) - assert errors + warnings == 0, message diff --git a/src/tonicdnscli/utils.py b/src/tonicdnscli/utils.py index fc4aa3f..154d86a 100644 --- a/src/tonicdnscli/utils.py +++ b/src/tonicdnscli/utils.py @@ -1,7 +1,6 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ - Copyright (C) 2012 Kouhei Maeda + Copyright (C) 2012, 2013 Kouhei Maeda This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,6 +16,7 @@ along with this program. If not, see . """ import sys +from datetime import datetime def print_inline(arg): @@ -26,3 +26,208 @@ def print_inline(arg): def error(msg): print("ERROR: %s" % msg) exit(1) + + +def get_columns_width(rows, columns_width, domain=False): + soa = None + for row in rows: + if row.get('type') == 'SOA': + soa = row + else: + if 'change_date' in row: + row['change_date'] = datetime.fromtimestamp( + int(row.get('change_date'))).strftime("%Y%m%d-%H%M%S") + else: + if domain: + row['change_date'] = None + + # row is content, priority, type, name, ttl + for i, value in enumerate(row.values()): + if value is None: + value = '-' + if columns_width[i] <= len(value): + columns_width[i] = len(value) + else: + columns_width[i] = columns_width[i] + + return columns_width, soa + + +def generate_row_s(row, columns_width, domain): + row_s = '' + + # for domains + row_l = [i for i in row] + row_l.reverse() + + for i, column in enumerate(row_l): + if i == 0: + row_s += ('| ' + column + ' ' * + (columns_width[i] - len(column) - domain + 1)) + else: + row_s += ('| ' + column + ' ' * + (columns_width[i] - len(column) + 1)) + row_s += '|' + return row_s + + +def get_row_s(row_d, key, col_width, domain=None): + if row_d.get(key): + value = row_d.get(key) + hostname = lambda domain: value.split(domain)[0] + + def compare(value, domain): + if value == domain: + #return value + return "" + else: + return hostname(domain) + name_ = compare(value, domain) + + if domain: + return (" " + name_ + " " * + (col_width - len(name_) - len(domain) + 1)) + else: + return (" " + name_ + " " * + (col_width - len(name_) + 1)) + + +def print_header(cols_width, col_header_l, domain=0): + border = '+' + for i, col_width in enumerate(cols_width): + if i == 0: + border += "-" * (col_width - domain + 1) + '-+' + else: + border += "-" * (col_width + 1) + '-+' + + sys.stdout.write("%s\n" % border) + print(generate_row_s(col_header_l, cols_width, domain)) + sys.stdout.write("%s\n" % border) + + +def print_bottom(cols_width, domain=0): + border = '+' + for i, col_width in enumerate(cols_width): + if i == 0: + border += "-" * (col_width - domain + 1) + '-+' + else: + border += "-" * (col_width + 1) + '-+' + sys.stdout.write("%s\n" % border) + + +def pretty_print(rows, keyword, domain): + """ + rows is + list when get domains + dict when get specific domain + """ + if isinstance(rows, dict): + pretty_print_domain(rows, keyword, domain) + elif isinstance(rows, list): + pretty_print_zones(rows) + + +def pretty_print_zones(rows): + col_header_l = ['notified_serial', 'type', 'name'] + col_width_l = [len(i) for i in col_header_l] + col_width, dummy = get_columns_width(rows, col_width_l) + + col_width.reverse() + + print_header(col_width, col_header_l) + + for row in rows: + print generate_row_s(row.values(), col_width, 0) + + print_bottom(col_width) + + +def pretty_print_domain(rows, keyword, domain): + """ + Arguments: + + rows: get response data + keyword: search keyword + + """ + if len(rows.get('records')) == 0: + return None + + # six columns; priority, name, content, ttl, change_date, type + header_l = ['prio', 'name', 'content', + 'ttl', 'change date', 'type'] + # 0->4, 1->0, 2->2, 3->3, 4->5, 5->1 + header_l_sorted = ['name', 'type', 'content', + 'ttl', 'prio', 'change date'] + header_l_sorted.reverse() + + cols_width = [len(i) for i in header_l] + + """ + if key == 'change_date': + value = datetime.fromtimestamp( + int(row_d.get(key))).strftime("%Y%m%d-%H%M%S") + """ + + cw_, soa = get_columns_width(rows.get('records'), + cols_width, True) + + # sorted as name, type, content, ttl, priority, change_date + cols_width_sorted = [cw_[1], cw_[5], cw_[2], + cw_[3], cw_[0], cw_[4]] + + if isinstance(soa, dict): + soa_s = ('zone: ' + soa.get('name') + '\n' + + 'SOA record: ' + soa.get('content') + '\n' + + 'ttl: ' + soa.get('ttl') + '\n' + + 'change date: ' + soa.get('change_date')) + domain = soa.get('name') + print(soa_s) + + print domain + + if keyword != 'SOA': + print_header(cols_width_sorted, header_l_sorted, len(domain)) + str_value = '' + for row in rows.get('records'): + if row.get('type') == 'SOA': + pass + else: + # name + if row.get('name'): + str_value = get_row_s(row, 'name', + cols_width_sorted[0], + domain=domain) + sys.stdout.write("|%s" % str_value) + # type + if row.get('type'): + str_value = get_row_s(row, 'type', + cols_width_sorted[1]) + sys.stdout.write("|%s" % str_value) + # content + if row.get('content'): + str_value = get_row_s(row, 'content', + cols_width_sorted[2]) + sys.stdout.write("|%s" % str_value) + # ttl + if row.get('ttl'): + str_value = get_row_s(row, 'ttl', + cols_width_sorted[3]) + sys.stdout.write("|%s" % str_value) + # priority + if row.get('priority') is None: + val = {'priority': '-'} + else: + val = row.copy() + str_value = get_row_s(val, 'priority', + cols_width_sorted[4]) + sys.stdout.write("|%s" % str_value) + if row.get('change_date') is None: + val = {'change_date': '-'} + else: + val = row.copy() + str_value = get_row_s(val, 'change_date', + cols_width_sorted[5]) + print("|%s|" % str_value) + + print_bottom(cols_width_sorted, len(domain)) diff --git a/utils/add_account.py b/utils/add_account.py index 58c984c..2185d87 100644 --- a/utils/add_account.py +++ b/utils/add_account.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- """ - Copyright (C) 2012 Kouhei Maeda + Copyright (C) 2012, 2013 Kouhei Maeda This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/utils/pre-commit.txt b/utils/pre-commit.txt index 6dfcba3..7fa57ae 100755 --- a/utils/pre-commit.txt +++ b/utils/pre-commit.txt @@ -1,8 +1,8 @@ #!/bin/sh -which nosetests || exit 1 +which py.test || exit 1 ( cd $(git rev-parse --show-toplevel) -nosetests -vd || exit 1 +py.test -v src || exit 1 python setup.py check -r || exit 1 )