Skip to content

Commit

Permalink
Merge pull request #143 from psi29a/better_logging
Browse files Browse the repository at this point in the history
better logging and version bump
  • Loading branch information
psi29a committed Mar 3, 2016
2 parents 540e556 + aa04595 commit 95e0e93
Show file tree
Hide file tree
Showing 12 changed files with 86 additions and 72 deletions.
9 changes: 9 additions & 0 deletions docs/source/NEWS.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
Changelog
=========

Release 16.0.1 (UNRELEASED)
---------------------------

Features
^^^^^^^^

- Make existing logging more verbose, indicate that it is TxMongo raising the error or sending the message.
- Add additional logging.

Release 16.0.0 (2016-02-25)
---------------------------

Expand Down
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
# built documents.
#
# The short X.Y version.
version = '16.0.0'
version = '16.0.1'
# The full version, including alpha/beta/rc tags.
release = version

Expand Down
2 changes: 1 addition & 1 deletion python-txmongo.spec
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Name: python-txmongo
Version: 16.0.0
Version: 16.0.1
Release: 1%{?dist}
Summary: Twisted driver for MongoDB

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

setup(
name="txmongo",
version="16.0.0",
version="16.0.1",
description="Asynchronous Python driver for MongoDB <http://www.mongodb.org>",
author="Alexandre Fiori, Bret Curtis",
author_email="fiorix@gmail.com, psi29a@gmail.com",
Expand Down
4 changes: 2 additions & 2 deletions txmongo/_gridfs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def __init__(self, database, collection="fs"):
The `collection` parameter.
"""
if not isinstance(database, Database):
raise TypeError("database must be an instance of Database")
raise TypeError("TxMongo: database must be an instance of Database.")

self.__database = database
self.__collection = database[collection]
Expand Down Expand Up @@ -140,7 +140,7 @@ def get_last_version(self, filename):
doc = yield self.__files.find_one({"filename": filename},
filter=filter.sort(DESCENDING("uploadDate")))
if doc is None:
raise NoFile("no file in gridfs with filename %r" % filename)
raise NoFile("TxMongo: no file in gridfs with filename {0}".format(repr(filename)))

defer.returnValue(GridOut(self.__collection, doc))

Expand Down
34 changes: 17 additions & 17 deletions txmongo/_gridfs/grid_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ def _create_property(field_name, docstring,

def getter(self):
if closed_only and not self._closed:
raise AttributeError("can only get %r on a closed file" %
field_name)
raise AttributeError(
"TxMongo: can only get {0} on a closed file.".format(repr(field_name)))
return self._file.get(field_name, None)

def setter(self, value):
if self._closed:
raise AttributeError("cannot set %r on a closed file" %
field_name)
raise AttributeError(
"TxMongo: cannot set {0} on a closed file.".format(repr(field_name)))
self._file[field_name] = value

if read_only:
Expand Down Expand Up @@ -97,7 +97,7 @@ def __init__(self, root_collection, **kwargs):
- `**kwargs` (optional): file level options (see above)
"""
if not isinstance(root_collection, Collection):
raise TypeError("root_collection must be an instance of Collection")
raise TypeError("TxMongo: root_collection must be an instance of Collection.")

# Handle alternative naming
if "content_type" in kwargs:
Expand Down Expand Up @@ -141,11 +141,11 @@ def closed(self):
def __getattr__(self, name):
if name in self._file:
return self._file[name]
raise AttributeError("GridIn object has no attribute '%s'" % name)
raise AttributeError("TxMongo: GridIn object has no attribute '{0}'".format(name))

def __setattr__(self, name, value):
if self._closed:
raise AttributeError("cannot set %r on a closed file" % name)
raise AttributeError("TxMongo: cannot set {0} on a closed file.".format(repr(name)))
object.__setattr__(self, name, value)

@defer.inlineCallbacks
Expand Down Expand Up @@ -213,21 +213,21 @@ def write(self, data):
to the file
"""
if self._closed:
raise ValueError("cannot write to a closed file")
raise ValueError("TxMongo: cannot write to a closed file.")

try:
# file-like
read = data.read
except AttributeError:
# string
if not isinstance(data, (bytes, unicode)):
raise TypeError("can only write strings or file-like objects")
raise TypeError("TxMongo: can only write strings or file-like objects.")
if isinstance(data, unicode):
try:
data = data.encode(self.encoding)
except AttributeError:
raise TypeError("must specify an encoding for file in "
"order to write %s" % data)
raise TypeError("TxMongo: must specify an encoding for file in "
"order to write {0}".format(data))
read = StringIO(data).read

if self._buffer.tell() > 0:
Expand Down Expand Up @@ -287,7 +287,7 @@ def __init__(self, root_collection, doc):
- `file_id`: value of ``"_id"`` for the file to read
"""
if not isinstance(root_collection, Collection):
raise TypeError("root_collection must be an instance of Collection")
raise TypeError("TxMongo: root_collection must be an instance of Collection.")

self.__chunks = root_collection.chunks
self._file = doc
Expand Down Expand Up @@ -316,7 +316,7 @@ def __init__(self, root_collection, doc):
def __getattr__(self, name):
if name in self._file:
return self._file[name]
raise AttributeError("GridOut object has no attribute '%s'" % name)
raise AttributeError("TxMongo: GridOut object has no attribute '{0}'".format(name))

@defer.inlineCallbacks
def read(self, size=-1):
Expand All @@ -341,7 +341,7 @@ def read(self, size=-1):
chunk = yield self.__chunks.find_one({"files_id": self._id,
"n": chunk_number})
if not chunk:
raise CorruptGridFile("no chunk #%d" % chunk_number)
raise CorruptGridFile("TxMongo: no chunk #{0}".format(chunk_number))

if not data:
data += chunk["data"][self.__position % self.chunk_size:]
Expand Down Expand Up @@ -379,10 +379,10 @@ def seek(self, pos, whence=os.SEEK_SET):
elif whence == os.SEEK_END:
new_pos = int(self.length) + pos
else:
raise IOError(22, "Invalid value for `whence`")
raise IOError(22, "TxMongo: invalid value for `whence`")

if new_pos < 0:
raise IOError(22, "Invalid value for `pos` - must be positive")
raise IOError(22, "TxMongo: invalid value for `pos` - must be positive")

self.__position = new_pos

Expand Down Expand Up @@ -412,7 +412,7 @@ def __next__(self):
chunk = yield self.__chunks.find_one({"files_id": self.__id,
"n": self.__current_chunk})
if not chunk:
raise CorruptGridFile("no chunk #%d" % self.__current_chunk)
raise CorruptGridFile("TxMongo: no chunk #{0}".format(self.__current_chunk))
self.__current_chunk += 1
defer.returnValue(bytes(chunk["data"]))
next = __next__
51 changes: 26 additions & 25 deletions txmongo/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,19 @@
class Collection(object):
def __init__(self, database, name, write_concern=None):
if not isinstance(name, (bytes, unicode)):
raise TypeError("name must be an instance of (bytes, unicode)")
raise TypeError("TxMongo: name must be an instance of (bytes, unicode).")

if not name or ".." in name:
raise InvalidName("collection names cannot be empty")
raise InvalidName("TxMongo: collection names cannot be empty.")
if "$" in name and not (name.startswith("oplog.$main") or
name.startswith("$cmd")):
raise InvalidName("collection names must not contain '$': %r" % name)
msg = "TxMongo: collection names must not contain '$', '{0}'".format(repr(name))
raise InvalidName(msg)
if name[0] == "." or name[-1] == ".":
raise InvalidName("collection names must not start or end with '.': %r" % name)
msg = "TxMongo: collection names must not start or end with '.', '{0}'".format(repr(name))
raise InvalidName(msg)
if "\x00" in name:
raise InvalidName("collection names must not contain the null character")
raise InvalidName("TxMongo: collection names must not contain the null character.")

self._database = database
self._collection_name = unicode(name)
Expand Down Expand Up @@ -112,7 +114,7 @@ def _normalize_fields_projection(fields):
as_dict = {}
for field in fields:
if not isinstance(field, (bytes, unicode)):
raise TypeError("fields must be a list of key names")
raise TypeError("TxMongo: fields must be a list of key names.")
as_dict[field] = 1
if not as_dict:
# Empty list should be treated as "_id only"
Expand Down Expand Up @@ -178,13 +180,13 @@ def find_with_cursor(self, spec=None, skip=0, limit=0, fields=None, filter=None,
spec = SON()

if not isinstance(spec, dict):
raise TypeError("spec must be an instance of dict")
raise TypeError("TxMongo: spec must be an instance of dict.")
if not isinstance(fields, (dict, list)) and fields is not None:
raise TypeError("fields must be an instance of dict or list")
raise TypeError("TxMongo: fields must be an instance of dict or list.")
if not isinstance(skip, int):
raise TypeError("skip must be an instance of int")
raise TypeError("TxMongo: skip must be an instance of int.")
if not isinstance(limit, int):
raise TypeError("limit must be an instance of int")
raise TypeError("TxMongo: limit must be an instance of int.")

fields = self._normalize_fields_projection(fields)

Expand Down Expand Up @@ -295,8 +297,7 @@ def group(self, keys, initial, reduce, condition=None, finalize=None, **kwargs):
@defer.inlineCallbacks
def filemd5(self, spec, **kwargs):
if not isinstance(spec, ObjectId):
raise ValueError("filemd5 expected an objectid for its "
"non-keyword argument")
raise ValueError("TxMongo: filemd5 expected an objectid for its non-keyword argument.")

result = yield self._database.command("filemd5", spec, root=self._collection_name, **kwargs)
defer.returnValue(result.get("md5"))
Expand Down Expand Up @@ -337,9 +338,9 @@ def insert(self, docs, safe=None, flags=0, **kwargs):
ids.append(oid)
doc["_id"] = oid
else:
raise TypeError("insert takes a document or a list of documents")
raise TypeError("TxMongo: insert takes a document or a list of documents.")
else:
raise TypeError("insert takes a document or a list of documents")
raise TypeError("TxMongo: insert takes a document or a list of documents.")

docs = [BSON.encode(d) for d in docs]
insert = Insert(flags=flags, collection=str(self), documents=docs)
Expand Down Expand Up @@ -392,11 +393,11 @@ def insert_many(self, documents, ordered=True, **kwargs):
@defer.inlineCallbacks
def update(self, spec, document, upsert=False, multi=False, safe=None, flags=0, **kwargs):
if not isinstance(spec, dict):
raise TypeError("spec must be an instance of dict")
raise TypeError("TxMongo: spec must be an instance of dict.")
if not isinstance(document, dict):
raise TypeError("document must be an instance of dict")
raise TypeError("TxMongo: document must be an instance of dict.")
if not isinstance(upsert, bool):
raise TypeError("upsert must be an instance of bool")
raise TypeError("TxMongo: upsert must be an instance of bool.")

if multi:
flags |= UPDATE_MULTI
Expand Down Expand Up @@ -470,7 +471,7 @@ def replace_one(self, filter, replacement, upsert=False, **kwargs):
@defer.inlineCallbacks
def save(self, doc, safe=None, **kwargs):
if not isinstance(doc, dict):
raise TypeError("cannot save objects of type %s" % type(doc))
raise TypeError("TxMongo: cannot save objects of type {0}".format(type(doc)))
oid = doc.get("_id")
if oid:
result = yield self.update(
Expand All @@ -486,7 +487,7 @@ def remove(self, spec, safe=None, single=False, flags=0, **kwargs):
if isinstance(spec, ObjectId):
spec = SON(dict(_id=spec))
if not isinstance(spec, dict):
raise TypeError("spec must be an instance of dict, not %s" % type(spec))
raise TypeError("TxMongo: spec must be an instance of dict, not {0}".format(type(spec)))

if single:
flags |= DELETE_SINGLE_REMOVE
Expand Down Expand Up @@ -542,7 +543,7 @@ def drop(self, **kwargs):
@defer.inlineCallbacks
def create_index(self, sort_fields, **kwargs):
if not isinstance(sort_fields, qf.sort):
raise TypeError("sort_fields must be an instance of filter.sort")
raise TypeError("TxMongo: sort_fields must be an instance of filter.sort")

if "name" not in kwargs:
name = self._gen_index_name(sort_fields["orderby"])
Expand Down Expand Up @@ -584,7 +585,7 @@ def drop_index(self, index_identifier, **kwargs):
elif isinstance(index_identifier, qf.sort):
name = self._gen_index_name(index_identifier["orderby"])
else:
raise TypeError("index_identifier must be a name or instance of filter.sort")
raise TypeError("TxMongo: index_identifier must be a name or instance of filter.sort")

result = yield self._database.command("deleteIndexes", self._collection_name,
index=name, allowable_errors=["ns not found"],
Expand Down Expand Up @@ -650,10 +651,10 @@ def find_and_modify(self, query=None, update=None, upsert=False, **kwargs):
no_obj_error = "No matching object found"

if not update and not kwargs.get("remove", None):
raise ValueError("Must either update or remove")
raise ValueError("TxMongo: must either update or remove.")

if update and kwargs.get("remove", None):
raise ValueError("Can't do both update and remove")
raise ValueError("TxMongo: can't do both update and remove.")

params = kwargs
# No need to include empty args
Expand All @@ -672,7 +673,7 @@ def find_and_modify(self, query=None, update=None, upsert=False, **kwargs):
defer.returnValue(None)
else:
# Should never get here because of allowable_errors
raise ValueError("Unexpected Error: %s" % (result,))
raise ValueError("TxMongo: unexpected error '{0}'".format(result))
defer.returnValue(result.get("value"))

# Distinct findAndModify utility method is needed because traditional
Expand All @@ -684,7 +685,7 @@ def _new_find_and_modify(self, filter, projection, sort, upsert=None,
return_document=ReturnDocument.BEFORE, **kwargs):
validate_is_mapping("filter", filter)
if not isinstance(return_document, bool):
raise ValueError("return_document must be ReturnDocument.BEFORE "
raise ValueError("TxMongo: return_document must be ReturnDocument.BEFORE "
"or ReturnDocument.AFTER")

cmd = SON([("findAndModify", self._collection_name),
Expand Down
14 changes: 8 additions & 6 deletions txmongo/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,23 +89,23 @@ def configure(self, proto):

# Make sure we got a result document.
if len(reply.documents) != 1:
raise OperationFailure("Invalid document length.")
raise OperationFailure("TxMongo: invalid document length.")

# Get the configuration document from the reply.
config = reply.documents[0].decode()

# Make sure the command was successful.
if not config.get("ok"):
code = config.get("code")
msg = config.get("err", "Unknown error")
msg = "TxMongo: " + config.get("err", "Unknown error")
raise OperationFailure(msg, code)

# Check that the replicaSet matches.
set_name = config.get("setName")
expected_set_name = self.uri["options"].get("replicaset")
if expected_set_name and (expected_set_name != set_name):
# Log the invalid replica set failure.
msg = "Mongo instance does not match requested replicaSet."
msg = "TxMongo: Mongo instance does not match requested replicaSet."
raise ConfigurationError(msg)

# Track max bson object size limit.
Expand All @@ -132,7 +132,8 @@ def configure(self, proto):
# Check if this node is the master.
ismaster = config.get("ismaster")
if not ismaster:
raise AutoReconnect("MongoDB host `%s` is not master." % config.get('me'))
msg = "TxMongo: MongoDB host `%s` is not master." % config.get('me')
raise AutoReconnect(msg)

def clientConnectionFailed(self, connector, reason):
self.instance = None
Expand Down Expand Up @@ -167,12 +168,13 @@ def retryNextHost(self, connector=None):
configured list of hosts.
"""
if not self.continueTrying:
log.msg("Abandoning %s on explicit request" % (connector,))
msg = "TxMongo: Abandoning {0} on explicit request.".format(connector)
log.msg(msg)
return

if connector is None:
if self.connector is None:
raise ValueError("no connector to retry")
raise ValueError("TxMongo: No additional connector to retry.")
else:
connector = self.connector

Expand Down
Loading

0 comments on commit 95e0e93

Please sign in to comment.