commit python-buku for openSUSE:Factory
Hello community, here is the log from the commit of package python-buku for openSUSE:Factory checked in at 2019-05-02 19:21:51 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-buku (Old) and /work/SRC/openSUSE:Factory/.python-buku.new.5148 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "python-buku" Thu May 2 19:21:51 2019 rev:8 rq:700083 version:4.2.2 Changes: -------- --- /work/SRC/openSUSE:Factory/python-buku/python-buku.changes 2019-04-04 15:28:31.202923751 +0200 +++ /work/SRC/openSUSE:Factory/.python-buku.new.5148/python-buku.changes 2019-05-02 19:22:03.017873597 +0200 @@ -1,0 +2,23 @@ +Thu May 2 07:47:06 UTC 2019 - mvetter@suse.com + +- Update to 4.2.2: + * This is a minor release that fixes broken prompt due to PR #373. + +------------------------------------------------------------------- +Thu May 2 06:32:10 UTC 2019 - mvetter@suse.com + +- Update to 4.2.1: + * This is a minor release with a single fix on top of v4.2 to + address a packaging problem. + +------------------------------------------------------------------- +Tue Apr 30 05:48:26 UTC 2019 - mvetter@suse.com + +- Update to 4.2 + * Disabled appending tags from page on update + * Improved Windows color support using colorama (optional dep) + * New format option to show only title and tag + * Python 3.4 is EOL, support discontinued + * Several fixes and code refactor + +------------------------------------------------------------------- Old: ---- buku-4.1.tar.gz New: ---- buku-4.2.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-buku.spec ++++++ --- /var/tmp/diff_new_pack.nsZCyL/_old 2019-05-02 19:22:04.509876694 +0200 +++ /var/tmp/diff_new_pack.nsZCyL/_new 2019-05-02 19:22:04.513876703 +0200 @@ -12,14 +12,14 @@ # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. -# Please submit bugfixes or comments via https://bugs.opensuse.org/ +# Please submit bugfixes or comments via http://bugs.opensuse.org/ # %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define skip_python2 1 Name: python-buku -Version: 4.1 +Version: 4.2.2 Release: 0 Summary: Command-line bookmark manager License: GPL-3.0-or-later @@ -44,6 +44,7 @@ # /SECTION Requires: python-base Requires: python-beautifulsoup4 >= 4.4.1 +Requires: python-colorama Requires: python-cryptography >= 1.2.3 Requires: python-html5lib >= 1.0.1 Requires: python-requests >= 2.9.1 ++++++ buku-4.1.tar.gz -> buku-4.2.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buku-4.1/CHANGELOG new/buku-4.2.2/CHANGELOG --- old/buku-4.1/CHANGELOG 2019-01-15 07:24:39.000000000 +0100 +++ new/buku-4.2.2/CHANGELOG 2019-05-02 08:47:59.000000000 +0200 @@ -1,3 +1,28 @@ +Buku v4.2.2 +2019-05-02 + +- Fixes broken prompt due to PR #373 + +------------------------------------------------------------------------------- + +Buku v4.2.1 +2019-04-30 + +- A fix on top of v4.2 to address a packaging problem + +------------------------------------------------------------------------------- + +Buku v4.2 +2019-04-30 + +- Disabled appending tags from page on update +- Improved Windows color support using colorama (optional dep) +- New format option to show only title and tag +- Python 3.4 is EOL, support discontinued +- Several fixes and code refactor + +------------------------------------------------------------------------------- + Buku v4.1 2019-01-15 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buku-4.1/PKG-INFO new/buku-4.2.2/PKG-INFO --- old/buku-4.1/PKG-INFO 2019-01-16 00:47:36.000000000 +0100 +++ new/buku-4.2.2/PKG-INFO 2019-05-02 08:48:20.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: buku -Version: 4.1 +Version: 4.2.2 Summary: Bookmark manager like a text-based mini-web. Home-page: https://github.com/jarun/Buku Author: Arun Prakash Jana @@ -20,9 +20,9 @@ </p> <p align="center"> - <a href="https://travis-ci.org/jarun/Buku"><img src="https://img.shields.io/travis/jarun/Buku.svg" alt="Build Status" /></a> + <a href="https://repology.org/metapackage/buku"><img src="https://repology.org/badge/tiny-repos/buku.svg" alt="Availability"></a> + <a href="https://circleci.com/gh/jarun/workflows/Buku"><img src="https://img.shields.io/circleci/project/github/jarun/Buku.svg" alt="Build Status" /></a> <a href="http://buku.readthedocs.io/en/latest/?badge=latest"><img src="https://readthedocs.org/projects/buku/badge/?version=latest" alt="Docs Status" /></a> - <a href="https://snyk.io/test/github/jarun/Buku"><img src="https://snyk.io/test/github/jarun/Buku/badge.svg" /></a> <a href="https://github.com/jarun/buku/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-GPLv3-yellow.svg?maxAge=2592000" alt="License" /></a> </p> @@ -38,16 +38,16 @@ [bukuserver](https://github.com/jarun/Buku/tree/master/bukuserver) exposes a browsable front-end on a local web host server. - `buku` fetches the title, tags and description of a bookmarked url from the web and stores it. You can use your favourite editor to compose and update bookmarks. With multiple search options, including regex and a deep scan mode (particularly for URLs), it can find any bookmark instantly. Multiple search results can be opened in the browser at once. `buku` can look up the latest snapshot of a broken link on the Wayback Machine. There's an Easter egg to revisit random forgotten bookmarks too! *Buku* is too busy to track you: no hidden history, obsolete records, usage analytics or homing. For more details, please refer to the wiki page on [operational notes](https://github.com/jarun/Buku/wiki/Operational-notes). + `buku` can auto-import bookmarks from your browser(s) or fetch the title and description of a bookmarked url from the web. You can use your favourite editor to compose and update bookmarks. With multiple search options, including regex and a deep scan mode (particularly for URLs), it can find any bookmark instantly. `buku` can look up the latest snapshot of a broken link on the Wayback Machine. There's an Easter egg to revisit random forgotten bookmarks too! *Buku* is too busy to track you: no hidden history, obsolete records, usage analytics or homing. - To get started right away, jump to the [Quickstart](#quickstart) section. We have one of the best documentation around. You'll find handy examples in the man page too. + To get started right away, jump to the [Quickstart](#quickstart) section. We have one of the best documentation around. You'll find handy examples in the man page too. For more details, please refer to the wiki page on [operational notes](https://github.com/jarun/Buku/wiki/Operational-notes). There are several [projects based on `buku`](#related-projects), including a browser plug-in. *Love smart and efficient utilities? Explore [my repositories](https://github.com/jarun?tab=repositories). Buy me a cup of coffee if they help you.* <p align="center"> - <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=RMLTQ76JSXJ4Q"><img src="https://img.shields.io/badge/PayPal-donate-green.svg" alt="Donate via PayPal!" /></a> + <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=RMLTQ76JSXJ4Q"><img src="https://img.shields.io/badge/PayPal-donate-1eb0fc.svg" alt="Donate via PayPal!" /></a> </p> ### Table of Contents @@ -65,6 +65,7 @@ - [Colors](#colors) - [Quickstart](#quickstart) - [Examples](#examples) + - [Automation](#automation) - [Troubleshooting](#troubleshooting) - [Editor integration](#editor-integration) - [Collaborators](#collaborators) @@ -94,7 +95,7 @@ | Feature | Dependency | | --- | --- | - | Scripting language | Python 3.4+ | + | Scripting language | Python 3.5+ | | HTTPS | certifi, urllib3 | | Encryption | cryptography | | HTML | beautifulsoup4, html5lib | @@ -124,7 +125,6 @@ - [Slackware](http://slackbuilds.org/repository/14.2/desktop/Buku/) (`slackpkg install buku`) - [Termux](https://pypi.python.org/pypi/buku/) (`pip3 install buku`) - [Ubuntu](https://packages.ubuntu.com/search?keywords=buku&searchon=names&exact=1) (`apt-get install buku`) - - [Ubuntu PPA](https://launchpad.net/~twodopeshaggy/+archive/ubuntu/jarun/) (`apt-get install buku`) - [Void Linux](https://github.com/voidlinux/void-packages/tree/master/srcpkgs/buku) (`xbps-install -S buku`) #### Release packages @@ -175,10 +175,10 @@ bookmark URL with comma-separated tags -u, --update [...] update fields of an existing bookmark accepts indices and ranges - refresh title, desc, tags if no edit options + refresh title and desc if no edit options if no arguments: - update results when used with search - - otherwise refresh all titles, desc, tags + - otherwise refresh all titles and desc -w, --write [editor|index] open editor to edit a fresh bookmark edit last bookmark, if index=-1 @@ -239,9 +239,9 @@ print all bookmarks, if no arguments -n shows the last n results (like tail) -f, --format N limit fields in -p or JSON search output - N=1: URL, N=2: URL and tag, N=3: title, - N=4: URL, title and tag. To omit DB index, - use N0, e.g., 10, 20, 30, 40. + N=1: URL; N=2: URL, tag; N=3: title; + N=4: URL, title, tag; N=5: title, tag; + N0 (10, 20, 30, 40, 50) omits DB index -j, --json JSON formatted output for -p and search --colors COLORS set output colors in five-letter string --nc disable color output @@ -299,7 +299,7 @@ 2. Create a sweeter shortcut with some convenience. alias b='buku --suggest' - 3. Auto-import bookmarks from your browser(s). + 3. Auto-import bookmarks from your browser(s). Please quit the relevant browsers beforehand to ensure the databases are not locked. b --ai 4. Manually add a bookmark (for hands-on). @@ -371,7 +371,7 @@ $ buku -u $ buku -u --tacit (show only failures and exceptions) - This operation does not modify the indexes, URLs, tags or comments. Only title is refreshed if fetched title is non-empty. + This operation can update the title or description fields of non-immutable bookmarks by parsing the fetched page. Fields are updated only if the fetched fields are non-empty. Tags remain untouched. 13. **Delete** bookmark at index 15012014: $ buku -d 15012014 @@ -468,6 +468,10 @@ $ buku -h $ man buku + ### Automation + + Interactive workflows can be automated using expect. Issue [#368](https://github.com/jarun/Buku/issues/368) has a working example on automating auto-import. + ### Troubleshooting #### Editor integration @@ -521,13 +525,13 @@ Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search Classifier: Topic :: Utilities -Requires-Python: >=3.4 +Requires-Python: >=3.5 Description-Content-Type: text/markdown Provides-Extra: packaging -Provides-Extra: tests Provides-Extra: server +Provides-Extra: tests diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buku-4.1/README.md new/buku-4.2.2/README.md --- old/buku-4.1/README.md 2019-01-15 07:24:39.000000000 +0100 +++ new/buku-4.2.2/README.md 2019-04-30 06:42:09.000000000 +0200 @@ -12,9 +12,9 @@ </p> <p align="center"> -<a href="https://travis-ci.org/jarun/Buku"><img src="https://img.shields.io/travis/jarun/Buku.svg" alt="Build Status" /></a> +<a href="https://repology.org/metapackage/buku"><img src="https://repology.org/badge/tiny-repos/buku.svg" alt="Availability"></a> +<a href="https://circleci.com/gh/jarun/workflows/Buku"><img src="https://img.shields.io/circleci/project/github/jarun/Buku.svg" alt="Build Status" /></a> <a href="http://buku.readthedocs.io/en/latest/?badge=latest"><img src="https://readthedocs.org/projects/buku/badge/?version=latest" alt="Docs Status" /></a> -<a href="https://snyk.io/test/github/jarun/Buku"><img src="https://snyk.io/test/github/jarun/Buku/badge.svg" /></a> <a href="https://github.com/jarun/buku/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-GPLv3-yellow.svg?maxAge=2592000" alt="License" /></a> </p> @@ -30,16 +30,16 @@ [bukuserver](https://github.com/jarun/Buku/tree/master/bukuserver) exposes a browsable front-end on a local web host server. -`buku` fetches the title, tags and description of a bookmarked url from the web and stores it. You can use your favourite editor to compose and update bookmarks. With multiple search options, including regex and a deep scan mode (particularly for URLs), it can find any bookmark instantly. Multiple search results can be opened in the browser at once. `buku` can look up the latest snapshot of a broken link on the Wayback Machine. There's an Easter egg to revisit random forgotten bookmarks too! *Buku* is too busy to track you: no hidden history, obsolete records, usage analytics or homing. For more details, please refer to the wiki page on [operational notes](https://github.com/jarun/Buku/wiki/Operational-notes). +`buku` can auto-import bookmarks from your browser(s) or fetch the title and description of a bookmarked url from the web. You can use your favourite editor to compose and update bookmarks. With multiple search options, including regex and a deep scan mode (particularly for URLs), it can find any bookmark instantly. `buku` can look up the latest snapshot of a broken link on the Wayback Machine. There's an Easter egg to revisit random forgotten bookmarks too! *Buku* is too busy to track you: no hidden history, obsolete records, usage analytics or homing. -To get started right away, jump to the [Quickstart](#quickstart) section. We have one of the best documentation around. You'll find handy examples in the man page too. +To get started right away, jump to the [Quickstart](#quickstart) section. We have one of the best documentation around. You'll find handy examples in the man page too. For more details, please refer to the wiki page on [operational notes](https://github.com/jarun/Buku/wiki/Operational-notes). There are several [projects based on `buku`](#related-projects), including a browser plug-in. *Love smart and efficient utilities? Explore [my repositories](https://github.com/jarun?tab=repositories). Buy me a cup of coffee if they help you.* <p align="center"> -<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=RMLTQ76JSXJ4Q"><img src="https://img.shields.io/badge/PayPal-donate-green.svg" alt="Donate via PayPal!" /></a> +<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=RMLTQ76JSXJ4Q"><img src="https://img.shields.io/badge/PayPal-donate-1eb0fc.svg" alt="Donate via PayPal!" /></a> </p> ### Table of Contents @@ -57,6 +57,7 @@ - [Colors](#colors) - [Quickstart](#quickstart) - [Examples](#examples) +- [Automation](#automation) - [Troubleshooting](#troubleshooting) - [Editor integration](#editor-integration) - [Collaborators](#collaborators) @@ -86,7 +87,7 @@ | Feature | Dependency | | --- | --- | -| Scripting language | Python 3.4+ | +| Scripting language | Python 3.5+ | | HTTPS | certifi, urllib3 | | Encryption | cryptography | | HTML | beautifulsoup4, html5lib | @@ -116,7 +117,6 @@ - [Slackware](http://slackbuilds.org/repository/14.2/desktop/Buku/) (`slackpkg install buku`) - [Termux](https://pypi.python.org/pypi/buku/) (`pip3 install buku`) - [Ubuntu](https://packages.ubuntu.com/search?keywords=buku&searchon=names&exact=1) (`apt-get install buku`) -- [Ubuntu PPA](https://launchpad.net/~twodopeshaggy/+archive/ubuntu/jarun/) (`apt-get install buku`) - [Void Linux](https://github.com/voidlinux/void-packages/tree/master/srcpkgs/buku) (`xbps-install -S buku`) #### Release packages @@ -167,10 +167,10 @@ bookmark URL with comma-separated tags -u, --update [...] update fields of an existing bookmark accepts indices and ranges - refresh title, desc, tags if no edit options + refresh title and desc if no edit options if no arguments: - update results when used with search - - otherwise refresh all titles, desc, tags + - otherwise refresh all titles and desc -w, --write [editor|index] open editor to edit a fresh bookmark edit last bookmark, if index=-1 @@ -231,9 +231,9 @@ print all bookmarks, if no arguments -n shows the last n results (like tail) -f, --format N limit fields in -p or JSON search output - N=1: URL, N=2: URL and tag, N=3: title, - N=4: URL, title and tag. To omit DB index, - use N0, e.g., 10, 20, 30, 40. + N=1: URL; N=2: URL, tag; N=3: title; + N=4: URL, title, tag; N=5: title, tag; + N0 (10, 20, 30, 40, 50) omits DB index -j, --json JSON formatted output for -p and search --colors COLORS set output colors in five-letter string --nc disable color output @@ -291,7 +291,7 @@ 2. Create a sweeter shortcut with some convenience. alias b='buku --suggest' -3. Auto-import bookmarks from your browser(s). +3. Auto-import bookmarks from your browser(s). Please quit the relevant browsers beforehand to ensure the databases are not locked. b --ai 4. Manually add a bookmark (for hands-on). @@ -363,7 +363,7 @@ $ buku -u $ buku -u --tacit (show only failures and exceptions) - This operation does not modify the indexes, URLs, tags or comments. Only title is refreshed if fetched title is non-empty. + This operation can update the title or description fields of non-immutable bookmarks by parsing the fetched page. Fields are updated only if the fetched fields are non-empty. Tags remain untouched. 13. **Delete** bookmark at index 15012014: $ buku -d 15012014 @@ -460,6 +460,10 @@ $ buku -h $ man buku +### Automation + +Interactive workflows can be automated using expect. Issue [#368](https://github.com/jarun/Buku/issues/368) has a working example on automating auto-import. + ### Troubleshooting #### Editor integration diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buku-4.1/buku.1 new/buku-4.2.2/buku.1 --- old/buku-4.1/buku.1 2019-01-15 07:24:39.000000000 +0100 +++ new/buku-4.2.2/buku.1 2019-05-02 08:47:59.000000000 +0200 @@ -1,4 +1,4 @@ -.TH "BUKU" "1" "15 Jan 2019" "Version 4.1" "User Commands" +.TH "BUKU" "1" "02 May 2019" "Version 4.2.2" "User Commands" .SH NAME buku \- Bookmark manager like a text-based mini-web .SH SYNOPSIS @@ -51,7 +51,7 @@ .IP 6. 4 \fBUpdate\fR operation: - If --title, --tag or --comment is passed without argument, clear the corresponding field from DB. - - If --url is passed (and --title is omitted), update the title from web using the URL. Description is updated (if --comment is omitted) and tags are appended to (if --tag is omitted). + - If --url is passed (and --title is omitted), update the title from web using the URL. Description is updated (if --comment is omitted). Tags remain untouched. - If indices are passed without any other options (--url, --title, --tag, --comment and --immutable), read the URLs from DB and update titles, description and append tags from web. Bookmarks marked immutable are skipped. - Can update bookmarks matching a search, when combined with any of the search options and no arguments to update are passed. .PP @@ -101,7 +101,7 @@ along with comma-separated tags. A tag can have multiple words. .TP .BI \-u " " \--update " [...]" -Update fields of the bookmarks at specified indices in DB. If no arguments are specified, all titles and descriptions are refreshed from the web. Tags are appended. Works with update modifiers for the fields url, title, tag and comment. If only indices are passed without any edit options, titles and descriptions are fetched and updated (if not empty). Accepts hyphenated ranges and space-separated indices. Updates search results when used with search options, if no arguments. +Update fields of the bookmarks at specified indices in DB. If no arguments are specified, all titles and descriptions are refreshed from the web. Tags remain untouched. Works with update modifiers for the fields url, title, tag and comment. If only indices are passed without any edit options, titles and descriptions are fetched and updated (if not empty). Accepts hyphenated ranges and space-separated indices. Updates search results when used with search options, if no arguments. .TP .BI \-w " " \--write " [editor|index]" Edit a bookmark in @@ -223,9 +223,12 @@ = 3, show only title. .br .I N -= 4, show URL, title and tags in a single line += 4, show URL, title and tags in a single line. .br -To omit DB index from printed results, use N0, e.g., 10, 20, 30, 40. +.I N += 5, show title and tags in a single line. +.br +To omit DB index from printed results, use N0, e.g., 10, 20, 30, 40, 50. .TP .BI \-j " " \--json Output data formatted as JSON, works with --print output and search results. @@ -576,7 +579,7 @@ .EE .PP .IP "" 4 -This operation does not modify the indexes, URLs, tags or comments. Only title is refreshed if fetched title is non-empty. +This operation can update the title or description fields of non-immutable bookmarks by parsing the fetched page. Fields are updated only if the fetched fields are non-empty. Tags remain untouched. .PP .IP 13. 4 \fBDelete\fR bookmark at index 15012014: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buku-4.1/buku.egg-info/PKG-INFO new/buku-4.2.2/buku.egg-info/PKG-INFO --- old/buku-4.1/buku.egg-info/PKG-INFO 2019-01-16 00:47:35.000000000 +0100 +++ new/buku-4.2.2/buku.egg-info/PKG-INFO 2019-05-02 08:48:19.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: buku -Version: 4.1 +Version: 4.2.2 Summary: Bookmark manager like a text-based mini-web. Home-page: https://github.com/jarun/Buku Author: Arun Prakash Jana @@ -20,9 +20,9 @@ </p> <p align="center"> - <a href="https://travis-ci.org/jarun/Buku"><img src="https://img.shields.io/travis/jarun/Buku.svg" alt="Build Status" /></a> + <a href="https://repology.org/metapackage/buku"><img src="https://repology.org/badge/tiny-repos/buku.svg" alt="Availability"></a> + <a href="https://circleci.com/gh/jarun/workflows/Buku"><img src="https://img.shields.io/circleci/project/github/jarun/Buku.svg" alt="Build Status" /></a> <a href="http://buku.readthedocs.io/en/latest/?badge=latest"><img src="https://readthedocs.org/projects/buku/badge/?version=latest" alt="Docs Status" /></a> - <a href="https://snyk.io/test/github/jarun/Buku"><img src="https://snyk.io/test/github/jarun/Buku/badge.svg" /></a> <a href="https://github.com/jarun/buku/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-GPLv3-yellow.svg?maxAge=2592000" alt="License" /></a> </p> @@ -38,16 +38,16 @@ [bukuserver](https://github.com/jarun/Buku/tree/master/bukuserver) exposes a browsable front-end on a local web host server. - `buku` fetches the title, tags and description of a bookmarked url from the web and stores it. You can use your favourite editor to compose and update bookmarks. With multiple search options, including regex and a deep scan mode (particularly for URLs), it can find any bookmark instantly. Multiple search results can be opened in the browser at once. `buku` can look up the latest snapshot of a broken link on the Wayback Machine. There's an Easter egg to revisit random forgotten bookmarks too! *Buku* is too busy to track you: no hidden history, obsolete records, usage analytics or homing. For more details, please refer to the wiki page on [operational notes](https://github.com/jarun/Buku/wiki/Operational-notes). + `buku` can auto-import bookmarks from your browser(s) or fetch the title and description of a bookmarked url from the web. You can use your favourite editor to compose and update bookmarks. With multiple search options, including regex and a deep scan mode (particularly for URLs), it can find any bookmark instantly. `buku` can look up the latest snapshot of a broken link on the Wayback Machine. There's an Easter egg to revisit random forgotten bookmarks too! *Buku* is too busy to track you: no hidden history, obsolete records, usage analytics or homing. - To get started right away, jump to the [Quickstart](#quickstart) section. We have one of the best documentation around. You'll find handy examples in the man page too. + To get started right away, jump to the [Quickstart](#quickstart) section. We have one of the best documentation around. You'll find handy examples in the man page too. For more details, please refer to the wiki page on [operational notes](https://github.com/jarun/Buku/wiki/Operational-notes). There are several [projects based on `buku`](#related-projects), including a browser plug-in. *Love smart and efficient utilities? Explore [my repositories](https://github.com/jarun?tab=repositories). Buy me a cup of coffee if they help you.* <p align="center"> - <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=RMLTQ76JSXJ4Q"><img src="https://img.shields.io/badge/PayPal-donate-green.svg" alt="Donate via PayPal!" /></a> + <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=RMLTQ76JSXJ4Q"><img src="https://img.shields.io/badge/PayPal-donate-1eb0fc.svg" alt="Donate via PayPal!" /></a> </p> ### Table of Contents @@ -65,6 +65,7 @@ - [Colors](#colors) - [Quickstart](#quickstart) - [Examples](#examples) + - [Automation](#automation) - [Troubleshooting](#troubleshooting) - [Editor integration](#editor-integration) - [Collaborators](#collaborators) @@ -94,7 +95,7 @@ | Feature | Dependency | | --- | --- | - | Scripting language | Python 3.4+ | + | Scripting language | Python 3.5+ | | HTTPS | certifi, urllib3 | | Encryption | cryptography | | HTML | beautifulsoup4, html5lib | @@ -124,7 +125,6 @@ - [Slackware](http://slackbuilds.org/repository/14.2/desktop/Buku/) (`slackpkg install buku`) - [Termux](https://pypi.python.org/pypi/buku/) (`pip3 install buku`) - [Ubuntu](https://packages.ubuntu.com/search?keywords=buku&searchon=names&exact=1) (`apt-get install buku`) - - [Ubuntu PPA](https://launchpad.net/~twodopeshaggy/+archive/ubuntu/jarun/) (`apt-get install buku`) - [Void Linux](https://github.com/voidlinux/void-packages/tree/master/srcpkgs/buku) (`xbps-install -S buku`) #### Release packages @@ -175,10 +175,10 @@ bookmark URL with comma-separated tags -u, --update [...] update fields of an existing bookmark accepts indices and ranges - refresh title, desc, tags if no edit options + refresh title and desc if no edit options if no arguments: - update results when used with search - - otherwise refresh all titles, desc, tags + - otherwise refresh all titles and desc -w, --write [editor|index] open editor to edit a fresh bookmark edit last bookmark, if index=-1 @@ -239,9 +239,9 @@ print all bookmarks, if no arguments -n shows the last n results (like tail) -f, --format N limit fields in -p or JSON search output - N=1: URL, N=2: URL and tag, N=3: title, - N=4: URL, title and tag. To omit DB index, - use N0, e.g., 10, 20, 30, 40. + N=1: URL; N=2: URL, tag; N=3: title; + N=4: URL, title, tag; N=5: title, tag; + N0 (10, 20, 30, 40, 50) omits DB index -j, --json JSON formatted output for -p and search --colors COLORS set output colors in five-letter string --nc disable color output @@ -299,7 +299,7 @@ 2. Create a sweeter shortcut with some convenience. alias b='buku --suggest' - 3. Auto-import bookmarks from your browser(s). + 3. Auto-import bookmarks from your browser(s). Please quit the relevant browsers beforehand to ensure the databases are not locked. b --ai 4. Manually add a bookmark (for hands-on). @@ -371,7 +371,7 @@ $ buku -u $ buku -u --tacit (show only failures and exceptions) - This operation does not modify the indexes, URLs, tags or comments. Only title is refreshed if fetched title is non-empty. + This operation can update the title or description fields of non-immutable bookmarks by parsing the fetched page. Fields are updated only if the fetched fields are non-empty. Tags remain untouched. 13. **Delete** bookmark at index 15012014: $ buku -d 15012014 @@ -468,6 +468,10 @@ $ buku -h $ man buku + ### Automation + + Interactive workflows can be automated using expect. Issue [#368](https://github.com/jarun/Buku/issues/368) has a working example on automating auto-import. + ### Troubleshooting #### Editor integration @@ -521,13 +525,13 @@ Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search Classifier: Topic :: Utilities -Requires-Python: >=3.4 +Requires-Python: >=3.5 Description-Content-Type: text/markdown Provides-Extra: packaging -Provides-Extra: tests Provides-Extra: server +Provides-Extra: tests diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buku-4.1/buku.egg-info/requires.txt new/buku-4.2.2/buku.egg-info/requires.txt --- old/buku-4.1/buku.egg-info/requires.txt 2019-01-16 00:47:35.000000000 +0100 +++ new/buku-4.2.2/buku.egg-info/requires.txt 2019-05-02 08:48:19.000000000 +0200 @@ -24,9 +24,11 @@ beautifulsoup4>=4.6.0 flake8>=3.4.1 hypothesis>=3.7.0 +mypy-extensions==0.4.1 py>=1.5.0 pylint>=1.7.2 pytest-cov pytest>=3.4.2 PyYAML>=4.2b1 +setuptools>=41.0.1 vcrpy>=1.13.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buku-4.1/buku.py new/buku-4.2.2/buku.py --- old/buku-4.1/buku.py 2019-01-16 00:47:34.000000000 +0100 +++ new/buku-4.2.2/buku.py 2019-05-02 08:48:18.000000000 +0200 @@ -34,6 +34,7 @@ import sys import threading import time +from typing import Any, Dict, List, Optional, Tuple import webbrowser try: import readline @@ -45,8 +46,12 @@ import urllib3 from urllib3.exceptions import LocationParseError from urllib3.util import parse_url, make_headers +try: + from mypy_extensions import TypedDict +except ImportError: + TypedDict = None # type: ignore -__version__ = '4.1' +__version__ = '4.2.2' __author__ = 'Arun Prakash Jana <engineerarun@gmail.com>' __license__ = 'GPLv3' @@ -328,6 +333,9 @@ sys.exit(1) +BookmarkVar = Tuple[int, str, str, str, str, int] + + class BukuDb: """Abstracts all database operations. @@ -343,7 +351,9 @@ Sets the verbosity of the APIs. Default is False. """ - def __init__(self, json=False, field_filter=0, chatty=False, dbfile=None, colorize=True): + def __init__( + self, json: Optional[bool] = False, field_filter: Optional[int] = 0, chatty: Optional[bool] = False, + dbfile: Optional[str] = None, colorize: Optional[bool] = True) -> None: """Database initialization API. Parameters @@ -394,7 +404,7 @@ return os.path.join(data_home, 'buku') @staticmethod - def initdb(dbfile=None, chatty=False): + def initdb(dbfile: Optional[str] = None, chatty: Optional[bool] = False) -> Tuple[sqlite3.Connection, sqlite3.Cursor]: """Initialize the database connection. Create DB file and/or bookmarks table if they don't exist. @@ -515,7 +525,7 @@ resultset = self.cur.fetchall() return resultset[0][0] if resultset else -1 - def get_max_id(self): + def get_max_id(self) -> int: """Fetch the ID of the last record. Returns @@ -530,13 +540,13 @@ def add_rec( self, - url, - title_in=None, - tags_in=None, - desc=None, - immutable=0, - delay_commit=False, - fetch=True): + url: str, + title_in: Optional[str] = None, + tags_in: Optional[str] = None, + desc: Optional[str] = None, + immutable: Optional[int] = 0, + delay_commit: Optional[bool] = False, + fetch: Optional[bool] = True) -> int: """Add a new bookmark. Parameters @@ -589,15 +599,13 @@ LOGDBG('Title: [%s]', ptitle) else: ptitle = pdesc = ptags = '' + LOGDBG('ptags: [%s]', ptags) if title_in is not None: ptitle = title_in # Fix up tags, if broken - if tags_in and tags_in != DELIM: - tags_in = delim_wrap(tags_in) - else: - tags_in = delim_wrap(parse_tags([ptags])) + tags_in = delim_wrap(tags_in) # Process description if desc is None: @@ -866,9 +874,6 @@ query += ' desc = ?,' arguments += (pdesc,) to_update = True - - if not tags_in and ptags: - self.append_tag_at_index(index, delim_wrap(ptags)) elif not to_update and not tag_modified: ret = self.refreshdb(index, threads) if ret and index and self.chatty: @@ -1015,7 +1020,7 @@ to_update = False if not title or title == '': - print(blank_url_str % row[0]) + LOGERR(blank_url_str, row[0]) else: query += ' metadata = ?,' arguments += (title,) @@ -1035,7 +1040,6 @@ LOGDBG('refreshdb query: "%s", args: %s', query, arguments) self.cur.execute(query, arguments) - self.append_tag_at_index(row[0], delim_wrap(tags), delay_commit=True) # Save after fetching 32 titles per thread if count & 0b11111 == 0: @@ -1994,11 +1998,11 @@ # If range starts from 0 throw an error if low <= 0: raise IndexError - else: - qry = 'SELECT URL from bookmarks where id BETWEEN ? AND ?' - for row in self.cur.execute(qry, (low, high)): - browse(row[0]) - return True + + qry = 'SELECT URL from bookmarks where id BETWEEN ? AND ?' + for row in self.cur.execute(qry, (low, high)): + browse(row[0]) + return True except IndexError: LOGERR('Index out of range') return False @@ -2031,7 +2035,7 @@ return False - def exportdb(self, filepath, resultset=None): + def exportdb(self, filepath: str, resultset: Optional[List[BookmarkVar]] = None) -> bool: """Export DB bookmarks to file. Exports full DB, if resultset is None @@ -2059,7 +2063,6 @@ """ count = 0 - timestamp = str(int(time.time())) if not resultset: resultset = self.get_rec_all() @@ -2080,12 +2083,9 @@ qry = 'INSERT INTO bookmarks(URL, metadata, tags, desc, flags) VALUES (?, ?, ?, ?, ?)' for row in resultset: outdb.cur.execute(qry, (row[1], row[2], row[3], row[4], row[5])) + count += 1 outdb.conn.commit() outdb.close() - - count = self.get_max_id() - if count == -1: - count = 0 print('%s exported' % count) return True @@ -2095,48 +2095,19 @@ LOGERR(e) return False + res = {} # type: Dict if filepath.endswith('.md'): - for row in resultset: - if row[2] == '': - out = '- [Untitled](' + row[1] + ')\n' - else: - out = '- [' + row[2] + '](' + row[1] + ')\n' - outfp.write(out) - count += 1 - + res = convert_bookmark_set(resultset, 'markdown') + count += res['count'] + outfp.write(res['data']) elif filepath.endswith('.org'): - for row in resultset: - if row[2] == '': - out = '* [[{}][Untitled]]\n'.format(row[1]) - else: - out = '* [[{}][{}]]\n'.format(row[1], row[2]) - outfp.write(out) - count += 1 + res = convert_bookmark_set(resultset, 'org') + count += res['count'] + outfp.write(res['data']) else: - outfp.write('<!DOCTYPE NETSCAPE-Bookmark-file-1>\n\n' - '<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">\n' - '<TITLE>Bookmarks</TITLE>\n' - '<H1>Bookmarks</H1>\n\n' - '<DL><p>\n' - ' <DT><H3 ADD_DATE="%s" LAST_MODIFIED="%s" ' - 'PERSONAL_TOOLBAR_FOLDER="true">Buku bookmarks</H3>\n' - ' <DL><p>\n' - % (timestamp, timestamp)) - - for row in resultset: - out = (' <DT><A HREF="%s" ADD_DATE="%s" LAST_MODIFIED="%s"' - % (row[1], timestamp, timestamp)) - if row[3] != DELIM: - out += ' TAGS="' + row[3][1:-1] + '"' - out += '>' + row[2] + '</A>\n' - if row[4] != '': - out += ' <DD>' + row[4] + '\n' - - outfp.write(out) - count += 1 - - outfp.write(' </DL><p>\n</DL><p>') - + res = convert_bookmark_set(resultset, 'html') + count += res['count'] + outfp.write(res['data']) outfp.close() print('%s exported' % count) return True @@ -2226,11 +2197,7 @@ """ # Connect to input DB - if sys.version_info >= (3, 4, 4): - # Python 3.4.4 and above - conn = sqlite3.connect('file:%s?mode=ro' % path, uri=True) - else: - conn = sqlite3.connect(path) + conn = sqlite3.connect('file:%s?mode=ro' % path, uri=True) cur = conn.cursor() res = cur.execute('SELECT DISTINCT fk, parent, title FROM moz_bookmarks WHERE type=1') @@ -2483,11 +2450,7 @@ try: # Connect to input DB - if sys.version_info >= (3, 4, 4): - # Python 3.4.4 and above - indb_conn = sqlite3.connect('file:%s?mode=ro' % path, uri=True) - else: - indb_conn = sqlite3.connect(path) + indb_conn = sqlite3.connect('file:%s?mode=ro' % path, uri=True) indb_cur = indb_conn.cursor() indb_cur.execute('SELECT * FROM bookmarks') @@ -2553,18 +2516,19 @@ if MYPROXY is None: gen_headers() + ca_certs = os.getenv('BUKU_CA_CERTS', default=certifi.where()) if MYPROXY: manager = urllib3.ProxyManager( MYPROXY, num_pools=1, headers=MYHEADERS, cert_reqs='CERT_REQUIRED', - ca_certs=certifi.where()) + ca_certs=ca_certs) else: manager = urllib3.PoolManager(num_pools=1, headers={'User-Agent': USER_AGENT}, cert_reqs='CERT_REQUIRED', - ca_certs=certifi.where()) + ca_certs=ca_certs) try: r = manager.request( @@ -2794,6 +2758,70 @@ # Helper functions # ---------------- + +ConverterResult = TypedDict('ConverterResult', {'data': str, 'count': int}) if TypedDict else Dict[str, Any] + + +def convert_bookmark_set( + bookmark_set: List[BookmarkVar], + export_type: str) -> ConverterResult: # type: ignore + """Convert list of bookmark set into multiple data format. + + Parameters + ---------- + bookmark_set: bookmark set + export type: one of supported type: markdown, html, org + + Returns + ------- + converted data and count of converted bookmark set + """ + assert export_type in ['markdown', 'html', 'org'] + # compatibility + resultset = bookmark_set + + count = 0 + out = '' + if export_type == 'markdown': + for row in resultset: + if not row[2]: + out += '- [Untitled](' + row[1] + ')\n' + else: + out += '- [' + row[2] + '](' + row[1] + ')\n' + count += 1 + elif export_type == 'org': + for row in resultset: + if not row[2]: + out += '* [[{}][Untitled]]\n'.format(row[1]) + else: + out += '* [[{}][{}]]\n'.format(row[1], row[2]) + count += 1 + elif export_type == 'html': + timestamp = str(int(time.time())) + out = ( + '<!DOCTYPE NETSCAPE-Bookmark-file-1>\n\n' + '<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">\n' + '<TITLE>Bookmarks</TITLE>\n' + '<H1>Bookmarks</H1>\n\n' + '<DL><p>\n' + ' <DT><H3 ADD_DATE="{0}" LAST_MODIFIED="{0}" ' + 'PERSONAL_TOOLBAR_FOLDER="true">Buku bookmarks</H3>\n' + ' <DL><p>\n'.format(timestamp)) + + for row in resultset: + out += ' <DT><A HREF="%s" ADD_DATE="%s" LAST_MODIFIED="%s"' % (row[1], timestamp, timestamp) + if row[3] != DELIM: + out += ' TAGS="' + row[3][1:-1] + '"' + out += '>{}</A>\n'.format(row[2] if row[2] else '') + if row[4] != '': + out += ' <DD>' + row[4] + '\n' + count += 1 + + out += ' </DL><p>\n</DL><p>' + + return {'data': out, 'count': count} + + def get_firefox_profile_name(path): """List folder and detect default Firefox profile name. @@ -3144,14 +3172,14 @@ # Get the netloc token try: netloc = parse_url(url).netloc + if not netloc: + # Try of prepend '//' and get netloc + netloc = parse_url('//' + url).netloc + if not netloc: + return True except LocationParseError as e: LOGERR('%s, URL: %s', e, url) return True - if not netloc: - # Try of prepend '//' and get netloc - netloc = parse_url('//' + url).netloc - if not netloc: - return True LOGDBG('netloc: %s', netloc) @@ -3398,17 +3426,17 @@ ProxyManager or PoolManager ProxyManager if https_proxy is defined, PoolManager otherwise. """ - + ca_certs = os.getenv('BUKU_CA_CERTS', default=certifi.where()) if MYPROXY: return urllib3.ProxyManager(MYPROXY, num_pools=1, headers=MYHEADERS, timeout=15, - cert_reqs='CERT_REQUIRED', ca_certs=certifi.where()) + cert_reqs='CERT_REQUIRED', ca_certs=ca_certs) return urllib3.PoolManager( num_pools=1, headers=MYHEADERS, timeout=15, cert_reqs='CERT_REQUIRED', - ca_certs=certifi.where()) + ca_certs=ca_certs) def network_handler(url, http_head=False): @@ -4008,6 +4036,9 @@ elif field_filter == 4: for row in records: print('%s\t%s\t%s\t%s' % (row[0], row[1], row[2], row[3][1:-1])) + elif field_filter == 5: + for row in records: + print('%s\t%s\t%s' % (row[0], row[2], row[3][1:-1])) elif field_filter == 10: for row in records: print(row[1]) @@ -4020,6 +4051,9 @@ elif field_filter == 40: for row in records: print('%s\t%s\t%s' % (row[1], row[2], row[3][1:-1])) + elif field_filter == 50: + for row in records: + print('%s\t%s' % (row[2], row[3][1:-1])) except BrokenPipeError: sys.stdout = os.fdopen(1) sys.exit(1) @@ -4224,19 +4258,20 @@ if MYPROXY is None: gen_headers() + ca_certs = os.getenv('BUKU_CA_CERTS', default=certifi.where()) if MYPROXY: manager = urllib3.ProxyManager( MYPROXY, num_pools=1, headers=MYHEADERS, cert_reqs='CERT_REQUIRED', - ca_certs=certifi.where() + ca_certs=ca_certs ) else: manager = urllib3.PoolManager(num_pools=1, headers={'User-Agent': USER_AGENT}, cert_reqs='CERT_REQUIRED', - ca_certs=certifi.where()) + ca_certs=ca_certs) try: r = manager.request( @@ -4683,10 +4718,10 @@ bookmark URL with comma-separated tags -u, --update [...] update fields of an existing bookmark accepts indices and ranges - refresh title, desc, tags if no edit options + refresh title and desc if no edit options if no arguments: - update results when used with search - - otherwise refresh all titles, desc, tags + - otherwise refresh all titles and desc -w, --write [editor|index] open editor to edit a fresh bookmark edit last bookmark, if index=-1 @@ -4790,9 +4825,9 @@ print all bookmarks, if no arguments -n shows the last n results (like tail) -f, --format N limit fields in -p or JSON search output - N=1: URL, N=2: URL and tag, N=3: title, - N=4: URL, title and tag. To omit DB index, - use N0, e.g., 10, 20, 30, 40. + N=1: URL; N=2: URL, tag; N=3: title; + N=4: URL, title, tag; N=5: title, tag; + N0 (10, 20, 30, 40, 50) omits DB index -j, --json JSON formatted output for -p and search --colors COLORS set output colors in five-letter string --nc disable color output @@ -4817,7 +4852,7 @@ addarg('-e', '--export', nargs=1, help=hide) addarg('-i', '--import', nargs=1, dest='importfile', help=hide) addarg('-p', '--print', nargs='*', help=hide) - addarg('-f', '--format', type=int, default=0, choices={1, 2, 3, 4, 10, 20, 30, 40}, help=hide) + addarg('-f', '--format', type=int, default=0, choices={1, 2, 3, 4, 5, 10, 20, 30, 40, 50}, help=hide) addarg('-j', '--json', action='store_true', help=hide) addarg('--colors', dest='colorstr', type=argparser.is_colorstr, metavar='COLORS', help=hide) addarg('--nc', action='store_true', help=hide) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buku-4.1/bukuserver/server.py new/buku-4.2.2/bukuserver/server.py --- old/buku-4.1/bukuserver/server.py 2019-01-01 16:28:25.000000000 +0100 +++ new/buku-4.2.2/bukuserver/server.py 2019-05-01 01:32:47.000000000 +0200 @@ -14,7 +14,7 @@ from markupsafe import Markup import click import flask -from flask import ( +from flask import ( # type: ignore __version__ as flask_version, abort, current_app, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buku-4.1/requirements.txt new/buku-4.2.2/requirements.txt --- old/buku-4.1/requirements.txt 2019-01-01 16:28:25.000000000 +0100 +++ new/buku-4.2.2/requirements.txt 2019-04-30 06:42:09.000000000 +0200 @@ -1,5 +1,7 @@ +# use setup.py for latest required package beautifulsoup4>=4.4.1 certifi cryptography>=1.2.3 +html5lib>=1.0.1 setuptools urllib3>=1.23 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buku-4.1/setup.py new/buku-4.2.2/setup.py --- old/buku-4.1/setup.py 2019-01-15 07:24:39.000000000 +0100 +++ new/buku-4.2.2/setup.py 2019-05-01 01:32:47.000000000 +0200 @@ -10,7 +10,7 @@ shutil.copyfile('buku', 'buku.py') with open('buku.py', encoding='utf-8') as f: - version = re.search('__version__ = \'([^\']+)\'', f.read()).group(1) + version = re.search('__version__ = \'([^\']+)\'', f.read()).group(1) # type: ignore with open('README.md', encoding='utf-8') as f: long_description = f.read() @@ -20,11 +20,13 @@ 'beautifulsoup4>=4.6.0', 'flake8>=3.4.1', 'hypothesis>=3.7.0', + 'mypy-extensions==0.4.1', 'py>=1.5.0', 'pylint>=1.7.2', 'pytest-cov', 'pytest>=3.4.2', 'PyYAML>=4.2b1', + 'setuptools>=41.0.1', 'vcrpy>=1.13.0', ] @@ -52,7 +54,7 @@ author_email='engineerarun@gmail.com', url='https://github.com/jarun/Buku', license='GPLv3', - python_requires='>=3.4', # requires pip>=9.0.0 + python_requires='>=3.5', # requires pip>=9.0.0 platforms=['any'], py_modules=['buku'], install_requires=[ @@ -85,9 +87,9 @@ 'Operating System :: OS Independent', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3 :: Only', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', 'Topic :: Internet :: WWW/HTTP :: Indexing/Search', 'Topic :: Utilities' ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buku-4.1/tests/test_buku.py new/buku-4.2.2/tests/test_buku.py --- old/buku-4.1/tests/test_buku.py 2019-01-01 16:28:25.000000000 +0100 +++ new/buku-4.2.2/tests/test_buku.py 2019-05-01 01:32:47.000000000 +0200 @@ -3,6 +3,7 @@ from unittest import mock from urllib.parse import urlparse import json +import logging import os import signal import sys @@ -528,15 +529,15 @@ ['about:new_page', ((None, None, None, 0, 1))], ['chrome://version/', ((None, None, None, 0, 1))], ['chrome://version/', ((None, None, None, 0, 1))], - [ - 'http://4pda.ru/forum/index.php?showtopic=182463&st=1640#entry6044923', - ( - 'Samsung GT-I5800 Galaxy 580 - Обсуждение - 4PDA', - 'Samsung GT-I5800 Galaxy 580 - Обсуждение - 4PDA', - None, - 0, 0 - ) - ], + # [ + # 'http://4pda.ru/forum/index.php?showtopic=182463&st=1640#entry6044923', + # ( + # 'Samsung GT-I5800 Galaxy 580 - Обсуждение - 4PDA', + # 'Samsung GT-I5800 Galaxy 580 - Обсуждение - 4PDA', + # None, + # 0, 0 + # ) + # ], [ 'https://www.google.ru/search?' 'newwindow=1&safe=off&q=xkbcomp+alt+gr&' @@ -726,4 +727,41 @@ params, stdin=subprocess.PIPE, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) m_popen_retval.communicate.assert_called_once_with(content) else: - m_popen.assert_not_called() + logging.info('popen is called {} on unrecognized platform'.format(m_popen.call_count)) + + +@pytest.mark.parametrize('export_type, exp_res', [ + [ + 'html', + '<!DOCTYPE NETSCAPE-Bookmark-file-1>\n\n' + '<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">\n' + '<TITLE>Bookmarks</TITLE>\n<H1>Bookmarks</H1>\n\n<DL><p>\n' + ' <DT><H3 ADD_DATE="1556430615" LAST_MODIFIED="1556430615" PERSONAL_TOOLBAR_FOLDER="true">Buku bookmarks</H3>\n' + ' <DL><p>\n' + ' <DT><A HREF="htttp://example.com" ADD_DATE="1556430615" LAST_MODIFIED="1556430615"></A>\n' + ' <DT><A HREF="htttp://example.org" ADD_DATE="1556430615" LAST_MODIFIED="1556430615"></A>\n' + ' <DT><A HREF="http://google.com" ADD_DATE="1556430615" LAST_MODIFIED="1556430615">Google</A>\n' + ' </DL><p>\n</DL><p>' + ], + ['org', '* [[htttp://example.com][Untitled]]\n* [[htttp://example.org][Untitled]]\n* [[http://google.com][Google]]\n'], + ['markdown', '- [Untitled](htttp://example.com)\n- [Untitled](htttp://example.org)\n- [Google](http://google.com)\n'], + ['random', None], +]) +def test_convert_bookmark_set(export_type, exp_res, monkeypatch): + from buku import convert_bookmark_set + import buku + bms = [ + (1, 'htttp://example.com', '', ',', '', 0), + (1, 'htttp://example.org', None, ',', '', 0), + (2, 'http://google.com', 'Google', ',', '', 0)] + if export_type == 'random': + with pytest.raises(AssertionError): + convert_bookmark_set(bms, export_type=export_type) + else: + + def return_fixed_number(): + return 1556430615 + monkeypatch.setattr(buku.time, 'time', return_fixed_number) + res = convert_bookmark_set(bms, export_type=export_type) + assert res['count'] == 3 + assert exp_res == res['data'] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/buku-4.1/tests/test_bukuDb.py new/buku-4.2.2/tests/test_bukuDb.py --- old/buku-4.1/tests/test_bukuDb.py 2019-01-15 08:37:12.000000000 +0100 +++ new/buku-4.2.2/tests/test_bukuDb.py 2019-05-01 01:53:29.000000000 +0200 @@ -13,7 +13,7 @@ import zipfile from genericpath import exists from itertools import product -from tempfile import TemporaryDirectory +from tempfile import TemporaryDirectory, NamedTemporaryFile from unittest import mock import unittest @@ -1027,52 +1027,71 @@ @pytest.mark.parametrize( - 'kwargs, exp_query, exp_arguments', + 'kwargs, exp_query, exp_query_p37, exp_arguments, exp_arguments_p37', [ [ {'index': 1, 'url': 'http://example.com'}, 'UPDATE bookmarks SET URL = ?, metadata = ? WHERE id = ?', - ['http://example.com', 'Example Domain', 1] + 'UPDATE bookmarks SET URL = ?, desc = ?, metadata = ? WHERE id = ?', + ['http://example.com', 'Example Domain', 1], + ['http://example.com', '', 'Example Domain', 1] ], [ {'index': 1, 'url': 'http://example.com', 'title_in': 'randomtitle'}, 'UPDATE bookmarks SET URL = ?, metadata = ? WHERE id = ?', + 'UPDATE bookmarks SET URL = ?, metadata = ? WHERE id = ?', + ['http://example.com', 'randomtitle', 1], ['http://example.com', 'randomtitle', 1] ], [ {'index': 1, 'url': 'http://example.com', 'tags_in': 'tag1'}, 'UPDATE bookmarks SET URL = ?, tags = ?, metadata = ? WHERE id = ?', - ['http://example.com', ',tag1', 'Example Domain', 1] + 'UPDATE bookmarks SET URL = ?, tags = ?, desc = ?, metadata = ? WHERE id = ?', + ['http://example.com', ',tag1', 'Example Domain', 1], + ['http://example.com', ',tag1,', '', 'Example Domain', 1] ], [ {'index': 1, 'url': 'http://example.com', 'tags_in': '+,tag1'}, 'UPDATE bookmarks SET URL = ?, metadata = ? WHERE id = ?', - ['http://example.com', 'Example Domain', 1] + 'UPDATE bookmarks SET URL = ?, desc = ?, metadata = ? WHERE id = ?', + ['http://example.com', 'Example Domain', 1], + ['http://example.com', '', 'Example Domain', 1] ], [ {'index': 1, 'url': 'http://example.com', 'tags_in': '-,tag1'}, 'UPDATE bookmarks SET URL = ?, metadata = ? WHERE id = ?', - ['http://example.com', 'Example Domain', 1] + 'UPDATE bookmarks SET URL = ?, desc = ?, metadata = ? WHERE id = ?', + ['http://example.com', 'Example Domain', 1], + ['http://example.com', '', 'Example Domain', 1] ], [ {'index': 1, 'url': 'http://example.com', 'desc': 'randomdesc'}, 'UPDATE bookmarks SET URL = ?, desc = ?, metadata = ? WHERE id = ?', + 'UPDATE bookmarks SET URL = ?, desc = ?, metadata = ? WHERE id = ?', + ['http://example.com', 'randomdesc', 'Example Domain', 1], ['http://example.com', 'randomdesc', 'Example Domain', 1] ], ] ) -def test_update_rec_exec_arg(caplog, kwargs, exp_query, exp_arguments): +def test_update_rec_exec_arg(caplog, kwargs, exp_query, exp_query_p37, exp_arguments, exp_arguments_p37): """test method.""" + if (sys.version_info.major, sys.version_info.minor) == (3, 7): + caplog.set_level(logging.DEBUG) + exp_query = exp_query_p37 + exp_arguments = exp_arguments_p37 bdb = BukuDb() res = bdb.update_rec(**kwargs) assert res + exp_log = 'query: "{}", args: {}'.format(exp_query, exp_arguments) + if (sys.version_info.major, sys.version_info.minor) == (3, 7): + exp_log = 'update_rec ' + exp_log try: assert caplog.records[-1].getMessage() == exp_log assert caplog.records[-1].levelname == 'DEBUG' @@ -1088,37 +1107,57 @@ @pytest.mark.parametrize( - 'tags_to_search, exp_query, exp_arguments', + 'tags_to_search, exp_query, exp_query_p37, exp_arguments, exp_arguments_p37', [ [ 'tag1, tag2', "SELECT id, url, metadata, tags, desc FROM bookmarks WHERE tags LIKE '%' || ? || '%' " "OR tags LIKE '%' || ? || '%' ORDER BY id ASC", - [',tag1,', ',tag2,'] - + "SELECT id, url, metadata, tags, desc " + "FROM (SELECT *, CASE WHEN tags LIKE '%' || ? || '%' THEN 1 ELSE 0 END + CASE " + "WHEN tags LIKE '%' || ? || '%' THEN 1 ELSE 0 END AS score " + "FROM bookmarks WHERE score > 0 ORDER BY score DESC)", + [',tag1,', ',tag2,'], + None ], [ - 'tag1+tag2,tag3, tag4', + 'tag2+tag2,tag3, tag4', "SELECT id, url, metadata, tags, desc FROM bookmarks WHERE tags LIKE '%' || ? || '%' " "OR tags LIKE '%' || ? || '%' OR tags LIKE '%' || ? || '%' ORDER BY id ASC", - [',tag1+tag2,', ',tag3,', ',tag4,'] + "SELECT id, url, metadata, tags, desc " + "FROM (SELECT *, CASE WHEN tags LIKE '%' || ? || '%' THEN 1 ELSE 0 END + CASE " + "WHEN tags LIKE '%' || ? || '%' THEN 1 ELSE 0 END + CASE " + "WHEN tags LIKE '%' || ? || '%' THEN 1 ELSE 0 END AS score " + "FROM bookmarks WHERE score > 0 ORDER BY score DESC)", + [',tag1+tag2,', ',tag3,', ',tag4,'], + [',tag2+tag2,', ',tag3,', ',tag4,'] ], [ 'tag1 + tag2+tag3', "SELECT id, url, metadata, tags, desc FROM bookmarks WHERE tags LIKE '%' || ? || '%' " "AND tags LIKE '%' || ? || '%' ORDER BY id ASC", - [',tag1,', ',tag2+tag3,'] + None, + [',tag1,', ',tag2+tag3,'], + None ], [ 'tag1-tag2 + tag 3 - tag4', "SELECT id, url, metadata, tags, desc FROM bookmarks WHERE (tags LIKE '%' || ? || '%' " "AND tags LIKE '%' || ? || '%' ) AND tags NOT REGEXP ? ORDER BY id ASC", - [',tag1-tag2,', ',tag 3,', ',tag4,'] + None, + [',tag1-tag2,', ',tag 3,', ',tag4,'], + None ] ] ) -def test_search_by_tag_query(caplog, tags_to_search, exp_query, exp_arguments): +def test_search_by_tag_query(caplog, tags_to_search, exp_query, exp_query_p37, exp_arguments, exp_arguments_p37): """test that the correct query and argments are constructed""" + if (sys.version_info.major, sys.version_info.minor) == (3, 7): + caplog.set_level(logging.DEBUG) + if exp_query_p37: + exp_query = exp_query_p37 + if exp_arguments_p37: + exp_arguments = exp_arguments_p37 bdb = BukuDb() bdb.search_by_tag(tags_to_search) exp_log = 'query: "{}", args: {}'.format(exp_query, exp_arguments) @@ -1174,6 +1213,8 @@ @pytest.mark.parametrize('read_in_retval', ['y', 'n', '']) def test_update_rec_update_all_bookmark(caplog, read_in_retval): """test method.""" + if (sys.version_info.major, sys.version_info.minor) == (3, 7): + caplog.set_level(logging.DEBUG) with mock.patch('buku.read_in', return_value=read_in_retval): import buku bdb = buku.BukuDb() @@ -1183,8 +1224,12 @@ return assert res try: - assert caplog.records[0].getMessage() == \ - 'query: "UPDATE bookmarks SET tags = ?", args: [\',tags1\']' + if (sys.version_info.major, sys.version_info.minor) == (3, 7): + assert caplog.records[0].getMessage() == \ + 'update_rec query: "UPDATE bookmarks SET tags = ?", args: [\',tags1,\']' + else: + assert caplog.records[0].getMessage() == \ + 'query: "UPDATE bookmarks SET tags = ?", args: [\',tags1\']' assert caplog.records[0].levelname == 'DEBUG' except IndexError as e: # TODO: fix test @@ -1372,6 +1417,50 @@ assert exp_res == res +def test_exportdb_empty_db(): + with NamedTemporaryFile(delete=False) as f: + db = BukuDb(dbfile=f.name) + with NamedTemporaryFile(delete=False) as f2: + res = db.exportdb(f2.name) + assert not res + + +def test_exportdb_single_rec(tmpdir): + with NamedTemporaryFile(delete=False) as f: + db = BukuDb(dbfile=f.name) + db.add_rec('http://example.com') + exp_file = tmpdir.join('export') + db.exportdb(exp_file.strpath) + with open(exp_file.strpath) as f: + assert f.read() + + +def test_exportdb_to_db(): + with NamedTemporaryFile(delete=False) as f1, NamedTemporaryFile(delete=False, suffix='.db') as f2: + db = BukuDb(dbfile=f1.name) + db.add_rec('http://example.com') + db.add_rec('http://google.com') + with mock.patch('builtins.input', return_value='y'): + db.exportdb(f2.name) + db2 = BukuDb(dbfile=f2.name) + assert db.get_rec_all() == db2.get_rec_all() + + +@pytest.mark.parametrize( + 'urls, exp_res', + [ + [[], -1], + [['http://example.com'], 1], + [['htttp://example.com', 'http://google.com'], 2], + ]) +def test_get_max_id(urls, exp_res): + with NamedTemporaryFile(delete=False) as f: + db = BukuDb(dbfile=f.name) + if urls: + list(map(lambda x: db.add_rec(x), urls)) + assert db.get_max_id() == exp_res + + # Helper functions for testcases
participants (1)
-
root