Add setup.py for installation as a system tool.

This commit is contained in:
Alessio Sergi 2016-11-06 19:44:44 +01:00
parent 10b2439093
commit 4cf02b9fa9
10 changed files with 134 additions and 66 deletions

View File

@ -13,7 +13,7 @@ addons:
- devscripts
- zsh
script:
- ./tests/ci-test-wrapper --watch .travis.yml
- ./ci-test-wrapper --watch .travis.yml
- git fetch --unshallow --tags origin
- ./tools/makedeb
deploy:

3
MANIFEST.in Normal file
View File

@ -0,0 +1,3 @@
include CHANGELOG LICENSE README.md buku.1 requirements.txt
recursive-include tests *.py
recursive-include auto-completion *

View File

@ -12,7 +12,7 @@ install:
install -m755 -d $(MANDIR)
install -m755 -d $(DOCDIR)
gzip -c buku.1 > buku.1.gz
install -m755 buku $(BINDIR)
install -m755 buku.py $(BINDIR)/buku
install -m644 buku.1.gz $(MANDIR)
install -m644 README.md $(DOCDIR)
rm -f buku.1.gz

View File

@ -92,7 +92,8 @@ To remove, run:
`buku` is a standalone utility. From the containing directory, run:
$ ./buku
$ chmod +x buku.py
$ ./buku.py
#### Debian package

23
buku → buku.py Executable file → Normal file
View File

@ -38,6 +38,10 @@ try:
except ImportError:
pass
__version__ = '2.6'
__author__ = 'Arun Prakash Jana <engineerarun@gmail.com>'
__license__ = 'GPLv3'
# Globals
update = False # Update a bookmark in DB
tags_in = None # Input tags specified at cmdline
@ -47,7 +51,6 @@ tagsearch = False # Search bookmarks by tag
title_data = None # Title fetched from a webpage
interrupted = False # Received SIGINT
DELIM = ',' # Delimiter used to store tags in DB
_VERSION_ = '2.6' # Program version
# Crypto globals
BLOCKSIZE = 65536
@ -1734,7 +1737,7 @@ def check_upstream_release():
% response.status)
else:
latest = json.loads(response.read().decode('utf-8'))[0]['name']
if latest == 'v' + _VERSION_:
if latest == 'v' + __version__:
print('This is the latest release')
else:
print('Latest upstream release is %s' % latest)
@ -1842,7 +1845,7 @@ Version %s
Copyright (C) 2015-2016 Arun Prakash Jana <engineerarun@gmail.com>
License: GPLv3
Webpage: https://github.com/jarun/Buku
''' % _VERSION_)
''' % __version__)
# Help
def print_help(self, file=None):
@ -1854,18 +1857,21 @@ Webpage: https://github.com/jarun/Buku
# Handle piped input
def main(argv, pipeargs=None):
def piped_input(argv, pipeargs=None):
if not sys.stdin.isatty():
pipeargs.extend(argv)
for s in sys.stdin.readlines():
pipeargs.extend(s.split())
if __name__ == '__main__':
def main():
global tags_in, title_in, description
pipeargs = []
atexit.register(logging.shutdown)
try:
main(sys.argv, pipeargs)
piped_input(sys.argv, pipeargs)
except KeyboardInterrupt:
pass
@ -2046,7 +2052,7 @@ if __name__ == '__main__':
description = ' '.join(args.desc)
if args.debug:
logger.setLevel(logging.DEBUG)
logger.debug('Version %s', _VERSION_)
logger.debug('Version %s', __version__)
# Move pre-1.9 database to new location
# BukuDb.move_legacy_dbfile()
@ -2269,3 +2275,6 @@ if __name__ == '__main__':
# Close DB connection and quit
bdb.close_quit(0)
if __name__ == '__main__':
main()

View File

@ -4,8 +4,8 @@ set -e
declare here repo_root
here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
repo_root="$here/.."
export GIT_DIR="$here/../.git"
repo_root="$here"
export GIT_DIR="$here/.git"
declare -a watchlist
watchlist=(buku tests)
@ -89,5 +89,5 @@ fi
# Test buku(1) with $repo_root at the beginning of $PATH (so that buku
# from this repo is picked up).
cd $here
cd "$here/tests"
PATH="$repo_root:$PATH" python -m pytest test_*.py --cov buku

54
setup.py Normal file
View File

@ -0,0 +1,54 @@
#!/usr/bin/env python3
import re
import sys
from setuptools import setup
if sys.version_info < (3, 3):
print('ERROR: Buku requires at least Python 3.3 to run.')
sys.exit(1)
with open('buku.py') as f:
version = re.search('__version__ = \'([^\']+)\'', f.read()).group(1)
with open('README.md', encoding='utf-8') as f:
long_description = f.read()
setup(
name='buku',
version=version,
description='Powerful command-line bookmark manager. Your mini web!',
long_description=long_description,
author='Arun Prakash Jana',
author_email='engineerarun@gmail.com',
url='https://github.com/jarun/Buku',
license='GPLv3',
platforms=['any'],
py_modules=['buku'],
entry_points={
'console_scripts': ['buku=buku:main']
},
extras_require={
'CRYPTO': ['cryptography'],
'HTML': ['beautifulsoup4']
},
test_suite='tests',
tests_require=['pytest-cov', 'pytest-catchlog'],
keywords='cli bookmarks tag utility',
classifiers=[
'Development Status :: 5 - Production/Stable',
'Environment :: Console',
'Intended Audience :: End Users/Desktop',
'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
'Natural Language :: English',
'Operating System :: OS Independent',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3 :: Only',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Topic :: Internet :: WWW/HTTP :: Indexing/Search',
'Topic :: Utilities'
]
)

0
tests/__init__.py Normal file
View File

View File

@ -1,44 +1,40 @@
#!/usr/bin/env python3
#
# Unit test cases for buku
# -*- coding: utf-8 -*-
from genericpath import exists
import imp
#
import os
import re
from tempfile import TemporaryDirectory
import unittest, pytest
from unittest import mock
from os.path import join, expanduser
import sqlite3
from genericpath import exists
from tempfile import TemporaryDirectory
buku = imp.load_source('buku', '../buku')
import pytest
import unittest
from unittest import mock as mock
from buku import BukuDb, parse_tags, prompt
TEST_TEMP_DIR_OBJ = TemporaryDirectory(prefix='bukutest_')
TEST_TEMP_DIR_PATH = TEST_TEMP_DIR_OBJ.name
TEST_TEMP_DBDIR_PATH = join(TEST_TEMP_DIR_PATH, 'buku')
TEST_TEMP_DBFILE_PATH = join(TEST_TEMP_DBDIR_PATH, 'bookmarks.db')
TEST_TEMP_DBDIR_PATH = os.path.join(TEST_TEMP_DIR_PATH, 'buku')
TEST_TEMP_DBFILE_PATH = os.path.join(TEST_TEMP_DBDIR_PATH, 'bookmarks.db')
from buku import BukuDb, parse_tags
TEST_BOOKMARKS = [ ['http://slashdot.org',
'SLASHDOT',
parse_tags(['old,news']),
"News for old nerds, stuff that doesn't matter",
],
['http://www.zażółćgęśląjaźń.pl/',
'ZAŻÓŁĆ',
parse_tags(['zażółć,gęślą,jaźń']),
"Testing UTF-8, zażółć gęślą jaźń.",
],
['https://test.com:8080',
'test',
parse_tags(['test,tes,est,es']),
"a case for replace_tag test",
],
TEST_BOOKMARKS = [
['http://slashdot.org',
'SLASHDOT',
parse_tags(['old,news']),
"News for old nerds, stuff that doesn't matter"],
['http://www.zażółćgęśląjaźń.pl/',
'ZAŻÓŁĆ',
parse_tags(['zażółć,gęślą,jaźń']),
"Testing UTF-8, zażółć gęślą jaźń."],
['https://test.com:8080',
'test',
parse_tags(['test,tes,est,es']),
"a case for replace_tag test"],
]
@pytest.fixture()
def setup():
os.environ['XDG_DATA_HOME'] = TEST_TEMP_DIR_PATH
@ -47,6 +43,7 @@ def setup():
if exists(TEST_TEMP_DBFILE_PATH):
os.remove(TEST_TEMP_DBFILE_PATH)
class TestBukuDb(unittest.TestCase):
def setUp(self):
@ -65,7 +62,7 @@ class TestBukuDb(unittest.TestCase):
# @unittest.skip('skipping')
def test_get_dbdir_path(self):
dbdir_expected = TEST_TEMP_DBDIR_PATH
dbdir_local_expected = join(expanduser('~'), '.local', 'share', 'buku')
dbdir_local_expected = os.path.join(os.path.expanduser('~'), '.local', 'share', 'buku')
dbdir_relative_expected = os.path.abspath('.')
# desktop linux
@ -113,12 +110,12 @@ class TestBukuDb(unittest.TestCase):
# the expected bookmark
expected = (1, 'http://slashdot.org', 'SLASHDOT', ',news,old,',
"News for old nerds, stuff that doesn't matter", 0)
"News for old nerds, stuff that doesn't matter", 0)
bookmark_from_db = self.bdb.get_bm_by_id(1)
# asserting bookmark matches expected
self.assertEqual(expected, bookmark_from_db)
# asserting None returned if index out of range
self.assertIsNone(self.bdb.get_bm_by_id( len(self.bookmarks[0]) + 1 ))
self.assertIsNone(self.bdb.get_bm_by_id(len(self.bookmarks[0]) + 1))
# @unittest.skip('skipping')
def test_get_bm_id(self):
@ -190,19 +187,18 @@ class TestBukuDb(unittest.TestCase):
# tags to add
new_tags = ",foo,bar,baz"
# record of original tags for each bookmark
old_tagsets = { i: self.bdb.get_bm_by_id(i)[3] for i in inclusive_range(1, len(self.bookmarks)) }
old_tagsets = {i: self.bdb.get_bm_by_id(i)[3] for i in inclusive_range(1, len(self.bookmarks))}
with mock.patch('builtins.input', return_value='y'):
self.bdb.append_tag_at_index(0, new_tags)
# updated tags for each bookmark
from_db = [ (i, self.bdb.get_bm_by_id(i)[3]) for i in inclusive_range(1, len(self.bookmarks)) ]
from_db = [(i, self.bdb.get_bm_by_id(i)[3]) for i in inclusive_range(1, len(self.bookmarks))]
for index, tagset in from_db:
# checking if new tags added to bookmark
self.assertTrue(split_and_test_membership(new_tags, tagset))
# checking if old tags still exist for boomark
self.assertTrue(split_and_test_membership(old_tagsets[index], tagset))
# @unittest.skip('skipping')
def test_delete_tag_at_index(self):
# adding bookmarks
@ -211,7 +207,7 @@ class TestBukuDb(unittest.TestCase):
get_tags_at_idx = lambda i: self.bdb.get_bm_by_id(i)[3]
# list of two-tuples, each containg bookmark index and corresponding tags
tags_by_index = [ (i, get_tags_at_idx(i)) for i in inclusive_range(1, len(self.bookmarks)) ]
tags_by_index = [(i, get_tags_at_idx(i)) for i in inclusive_range(1, len(self.bookmarks))]
for i, tags in tags_by_index:
# get the first tag from the bookmark
@ -242,10 +238,10 @@ class TestBukuDb(unittest.TestCase):
title_search = bookmark[1]
# Expect a five-tuple containing all bookmark data
# db index, URL, title, tags, description
expected = [(i + 1,) + tuple(bookmark)]
expected = [(i + 1,) + tuple(bookmark)]
# search db by tag, url (domain name), and title
for keyword in (tag_search, url_search, title_search):
with mock.patch('buku.prompt') as mock_prompt:
with mock.patch('buku.prompt'):
# search by keyword
results = self.bdb.searchdb([keyword])
self.assertEqual(results, expected)
@ -256,7 +252,7 @@ class TestBukuDb(unittest.TestCase):
for bookmark in self.bookmarks:
self.bdb.add_bm(*bookmark)
with mock.patch('buku.prompt') as mock_prompt:
with mock.patch('buku.prompt'):
get_first_tag = lambda x: ''.join(x[2].split(',')[:2])
for i in range(len(self.bookmarks)):
# search for bookmark with a tag that is known to exist
@ -280,16 +276,16 @@ class TestBukuDb(unittest.TestCase):
# search the db with keywords from each bookmark
# searching using the first tag from bookmarks
get_first_tag = lambda x: x[2].split(',')[1]
results = self.bdb.searchdb([ get_first_tag(bm) for bm in self.bookmarks ])
buku.prompt(results)
results = self.bdb.searchdb([get_first_tag(bm) for bm in self.bookmarks])
prompt(results)
except StopIteration:
# catch exception thrown by reaching the end of the side effect iterable
pass
# collect arguments passed to open_in_browser
arg_list = [ args[0] for args, _ in mock_open_in_browser.call_args_list ]
arg_list = [args[0] for args, _ in mock_open_in_browser.call_args_list]
# expect a list of one-tuples that are bookmark URLs
expected = [ x[0] for x in self.bookmarks]
expected = [x[0] for x in self.bookmarks]
# checking if open_in_browser called with expected arguments
self.assertEqual(arg_list, expected)
@ -306,16 +302,16 @@ class TestBukuDb(unittest.TestCase):
# search the db with keywords from each bookmark
# searching using the first tag from bookmarks
get_first_tag = lambda x: x[2].split(',')[1]
results = self.bdb.searchdb([ get_first_tag(bm) for bm in self.bookmarks[:2] ])
buku.prompt(results)
results = self.bdb.searchdb([get_first_tag(bm) for bm in self.bookmarks[:2]])
prompt(results)
except StopIteration:
# catch exception thrown by reaching the end of the side effect iterable
pass
# collect arguments passed to open_in_browser
arg_list = [ args[0] for args, _ in mock_open_in_browser.call_args_list ]
arg_list = [args[0] for args, _ in mock_open_in_browser.call_args_list]
# expect a list of one-tuples that are bookmark URLs
expected = [ x[0] for x in self.bookmarks][:2]
expected = [x[0] for x in self.bookmarks][:2]
# checking if open_in_browser called with expected arguments
self.assertEqual(arg_list, expected)
@ -377,7 +373,7 @@ class TestBukuDb(unittest.TestCase):
# removing nonexistent tag which is also a substring of other tag
self.bdb.replace_tag("e")
for url, title, _, _ in self.bookmarks:
for url, title, _, _ in self.bookmarks:
# retrieving from db
index = self.bdb.get_bm_id(url)
from_db = self.bdb.get_bm_by_id(index)
@ -408,6 +404,7 @@ class TestBukuDb(unittest.TestCase):
# def test_import_bookmark(self):
# self.fail()
def test_print_bm(capsys, caplog, setup):
bdb = BukuDb()
out, err = capsys.readouterr()
@ -445,6 +442,7 @@ def test_print_bm(capsys, caplog, setup):
assert out == "\x1b[1m3 records found\x1b[21m\n\n\x1b[1m\x1b[93m2. \x1b[0m\x1b[92mhttp://blank-title.com\x1b[0m\n \x1b[91m+\x1b[0m blank title\n \x1b[91m#\x1b[0m blank,title\n\n\x1b[1m\x1b[93m3. \x1b[0m\x1b[92mhttp://empty-tags.com\x1b[0m\n \x1b[91m>\x1b[0m empty tags\n \x1b[91m+\x1b[0m empty tags\n\n\x1b[1m\x1b[93m4. \x1b[0m\x1b[92mhttp://all-empty.com\x1b[0m\n \x1b[91m+\x1b[0m all empty\n\n"
assert err == ''
def test_list_tags(capsys, setup):
bdb = BukuDb()
@ -460,6 +458,7 @@ def test_list_tags(capsys, setup):
assert out == " 1. 1\n 2. 2\n 3. 3\n 4. Ant\n 5. ant\n 6. bee\n 7. Bee\n 8. Cat\n 9. cat\n"
assert err == ''
def test_compactdb(setup):
bdb = BukuDb()
@ -478,10 +477,12 @@ def test_compactdb(setup):
# Helper functions for testcases
def split_and_test_membership(a, b):
# :param a, b: comma separated strings to split
# test everything in a in b
return all( x in b.split(',') for x in a.split(',') )
return all(x in b.split(',') for x in a.split(','))
def inclusive_range(start, end):
return range(start, end + 1)

View File

@ -1,10 +1,10 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import imp, unittest
buku = imp.load_source('buku', '../buku')
import os
import signal
import unittest
from buku import *
from buku import is_int, parse_tags
class TestHelpers(unittest.TestCase):