[tor-commits] [stem/master] Provide a connection with stem.manual.database
atagar at torproject.org
atagar at torproject.org
Sat Aug 26 22:51:43 UTC 2017
commit 17ab84ac5ebf896a77d1ce67bee54bb00d3c0bfd
Author: Damian Johnson <atagar at torproject.org>
Date: Sat Aug 26 14:59:08 2017 -0700
Provide a connection with stem.manual.database
In dabbling with this more I've been finding the context manager enforced by
stem.manual.database() annoying. When on an interactive prompt I want a method
to quickly get a no-hassle database connection - not a cursor that's only
usable within a 'with' block.
Reason I provided a cursor was to ensure callers had read-only access.
However, just checked and when the database file is read-only (as our
cached_tor_manual.sqlite should be when installed) attempting to write
to it behaves how I'd expect...
>>> import stem.manual
>>> conn = stem.manual.database()
>>> conn.execute('CREATE TABLE new_table(name TEXT PRIMARY KEY, description TEXT)')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
sqlite3.OperationalError: attempt to write a readonly database
---
stem/manual.py | 18 ++++++++++++------
test/unit/manual.py | 8 +++++---
2 files changed, 17 insertions(+), 9 deletions(-)
diff --git a/stem/manual.py b/stem/manual.py
index fc648cc9..e78f917c 100644
--- a/stem/manual.py
+++ b/stem/manual.py
@@ -47,7 +47,6 @@ us what our torrc options do...
.. versionadded:: 1.5.0
"""
-import contextlib
import os
import shutil
import sqlite3
@@ -95,26 +94,33 @@ CATEGORY_SECTIONS = OrderedDict((
))
- at contextlib.contextmanager
def database(path = None):
"""
- Provides a database cursor for a sqlite cache.
+ Provides database connection for our sqlite cache. This database should be
+ treated as being read-only, with this restriction being enforced in the
+ future.
.. versionadded:: 1.6.0
:param str path: cached manual content to read, if not provided this uses
the bundled manual information
- :returns: :class:`sqlite3.Cursor` for the database cache
+ :returns: :class:`sqlite3.Connection` for the database cache
:raises: **IOError** if a **path** was provided and we were unable to read it
"""
if path is None:
path = CACHE_PATH
+ elif not os.path.exists(path):
+ raise IOError("%s doesn't exist" % path)
- with sqlite3.connect(path) as conn:
- yield conn.cursor()
+ # TODO: When we only support python 3.4+ we can use sqlite's uri argument to
+ # get a read-only connection...
+ #
+ # https://docs.python.org/3/library/sqlite3.html#sqlite3.connect
+
+ return sqlite3.connect(path)
class ConfigOption(object):
diff --git a/test/unit/manual.py b/test/unit/manual.py
index eab9bdfc..eaca3629 100644
--- a/test/unit/manual.py
+++ b/test/unit/manual.py
@@ -103,9 +103,11 @@ def _cached_manual():
class TestManual(unittest.TestCase):
def test_database(self):
- with stem.manual.database() as cursor:
- cursor.execute('SELECT description FROM torrc WHERE name="CookieAuthFile"')
- self.assertEqual("If set, this option overrides the default location and file name for Tor's cookie file. (See CookieAuthentication above.)", cursor.fetchone()[0])
+ with stem.manual.database() as conn:
+ self.assertEqual("If set, this option overrides the default location and file name for Tor's cookie file. (See CookieAuthentication above.)", conn.execute('SELECT description FROM torrc WHERE name="CookieAuthFile"').fetchone()[0])
+
+ def test_missing_database(self):
+ self.assertRaisesRegexp(IOError, "/no/such/path doesn't exist", stem.manual.database, '/no/such/path')
def test_has_all_summaries(self):
"""
More information about the tor-commits
mailing list