Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Clean up of code per pylint warnings

  • Loading branch information...
commit b552af372df4a826fea17d934d2204a6cd36a913 1 parent ec1172d
@paltman paltman authored
View
24 notification/backends/__init__.py
@@ -3,9 +3,10 @@
from django.conf import settings
from django.core import exceptions
-from base import BaseBackend
+from .base import BaseBackend
+# pylint: disable-msg=C0103
# mostly for backend compatibility
default_backends = [
("email", "notification.backends.email.EmailBackend"),
@@ -14,14 +15,17 @@
def load_backends():
backends = []
- for medium_id, bits in enumerate(getattr(settings, "NOTIFICATION_BACKENDS", default_backends)):
+ configured_backends = getattr(settings, "NOTIFICATION_BACKENDS", default_backends)
+ for medium_id, bits in enumerate(configured_backends):
if len(bits) == 2:
label, backend_path = bits
spam_sensitivity = None
elif len(bits) == 3:
label, backend_path, spam_sensitivity = bits
else:
- raise exceptions.ImproperlyConfigured, "NOTIFICATION_BACKENDS does not contain enough data."
+ raise exceptions.ImproperlyConfigured(
+ "NOTIFICATION_BACKENDS does not contain enough data."
+ )
dot = backend_path.rindex(".")
backend_mod, backend_class = backend_path[:dot], backend_path[dot + 1:]
try:
@@ -29,9 +33,21 @@ def load_backends():
__import__(backend_mod)
mod = sys.modules[backend_mod]
except ImportError, e:
- raise exceptions.ImproperlyConfigured, 'Error importing notification backend %s: "%s"' % (backend_mod, e)
+ raise exceptions.ImproperlyConfigured(
+ "Error importing notification backend {}: \"{}\"".format(backend_mod, e)
+ )
# add the backend label and an instantiated backend class to the
# backends list.
backend_instance = getattr(mod, backend_class)(medium_id, spam_sensitivity)
backends.append(((medium_id, label), backend_instance))
return dict(backends)
+
+
+def load_media_defaults(backends):
+ media = []
+ defaults = {}
+ for key, backend in backends.items():
+ # key is a tuple (medium_id, backend_label)
+ media.append(key)
+ defaults[key[0]] = backend.spam_sensitivity
+ return media, defaults
View
14 notification/backends/base.py
@@ -22,11 +22,11 @@ def can_send(self, user, notice_type):
from notification.models import NoticeSetting
return NoticeSetting.for_user(user, notice_type, self.medium_id).send
- def deliver(self, recipient, notice_type, extra_context):
+ def deliver(self, recipient, sender, notice_type, extra_context):
"""
Deliver a notification to the given recipient.
"""
- raise NotImplemented()
+ raise NotImplementedError()
def get_formatted_messages(self, formats, label, context):
"""
@@ -34,13 +34,13 @@ def get_formatted_messages(self, formats, label, context):
are fully rendered templates with the given context.
"""
format_templates = {}
- for format in formats:
+ for fmt in formats:
# conditionally turn off autoescaping for .txt extensions in format
- if format.endswith(".txt"):
+ if fmt.endswith(".txt"):
context.autoescape = False
- format_templates[format] = render_to_string((
- "notification/%s/%s" % (label, format),
- "notification/%s" % format), context_instance=context)
+ format_templates[fmt] = render_to_string((
+ "notification/%s/%s" % (label, fmt),
+ "notification/%s" % fmt), context_instance=context)
return format_templates
def default_context(self):
View
24 notification/engine.py
@@ -48,14 +48,18 @@ def send_all(*args):
for user, label, extra_context, sender in notices:
try:
user = User.objects.get(pk=user)
- logging.info("emitting notice %s to %s" % (label, user))
+ logging.info("emitting notice {} to {}".format(label, user))
# call this once per user to be atomic and allow for logging to
# accurately show how long each takes.
if notification.send_now([user], label, extra_context, sender):
sent_actual += 1
except User.DoesNotExist:
# Ignore deleted users, just warn about them
- logging.warning("not emitting notice %s to user %s since it does not exist" % (label, user))
+ logging.warning(
+ "not emitting notice {} to user {} since it does not exist".format(
+ label,
+ user)
+ )
sent += 1
queued_batch.delete()
batches += 1
@@ -66,21 +70,23 @@ def send_all(*args):
sent_actual=sent_actual,
run_time="%.2f seconds" % (time.time() - start_time)
)
- except:
+ except Exception: # pylint: disable-msg=W0703
# get the exception
- exc_class, e, t = sys.exc_info()
+ _, e, _ = sys.exc_info()
# email people
current_site = Site.objects.get_current()
- subject = "[%s emit_notices] %r" % (current_site.name, e)
- message = "%s" % ("\n".join(traceback.format_exception(*sys.exc_info())),)
+ subject = "[{} emit_notices] {}".format(current_site.name, e)
+ message = "\n".join(
+ traceback.format_exception(*sys.exc_info()) # pylint: disable-msg=W0142
+ )
mail_admins(subject, message, fail_silently=True)
# log it as critical
- logging.critical("an exception occurred: %r" % e)
+ logging.critical("an exception occurred: {}".format(e))
finally:
logging.debug("releasing lock...")
lock.release()
logging.debug("released.")
logging.info("")
- logging.info("%s batches, %s sent" % (batches, sent,))
- logging.info("done in %.2f seconds" % (time.time() - start_time))
+ logging.info("{} batches, {} sent".format(batches, sent,))
+ logging.info("done in {:.2f} seconds".format(time.time() - start_time))
View
221 notification/lockfile.py
@@ -6,21 +6,21 @@
Usage:
->>> lock = FileLock('somefile')
+>>> lock = FileLock("somefile")
>>> try:
... lock.acquire()
... except AlreadyLocked:
-... print 'somefile', 'is locked already.'
+... print "somefile", "is locked already."
... except LockFailed:
-... print 'somefile', 'can\\'t be locked.'
+... print "somefile", "can\\"t be locked."
... else:
-... print 'got lock'
+... print "got lock"
got lock
>>> print lock.is_locked()
True
>>> lock.release()
->>> lock = FileLock('somefile')
+>>> lock = FileLock("somefile")
>>> print lock.is_locked()
False
>>> with lock:
@@ -32,7 +32,7 @@
>>> with lock:
... lock.acquire()
...
->>> # Though no counter is kept, so you can't unlock multiple times...
+>>> # Though no counter is kept, so you can"t unlock multiple times...
>>> print lock.is_locked()
False
@@ -64,9 +64,11 @@
if not hasattr(threading.Thread, "get_name"):
threading.Thread.get_name = threading.Thread.getName
-__all__ = ['Error', 'LockError', 'LockTimeout', 'AlreadyLocked',
- 'LockFailed', 'UnlockError', 'NotLocked', 'NotMyLock',
- 'LinkFileLock', 'MkdirFileLock', 'SQLiteFileLock']
+
+__all__ = ["Error", "LockError", "LockTimeout", "AlreadyLocked",
+ "LockFailed", "UnlockError", "NotLocked", "NotMyLock",
+ "LinkFileLock", "MkdirFileLock", "SQLiteFileLock"]
+
class Error(Exception):
"""
@@ -79,6 +81,7 @@ class Error(Exception):
"""
pass
+
class LockError(Error):
"""
Base class for error arising from attempts to acquire the lock.
@@ -90,6 +93,7 @@ class LockError(Error):
"""
pass
+
class LockTimeout(LockError):
"""Raised when lock creation fails within a user-defined period of time.
@@ -100,6 +104,7 @@ class LockTimeout(LockError):
"""
pass
+
class AlreadyLocked(LockError):
"""Some other thread/process is locking the file.
@@ -110,6 +115,7 @@ class AlreadyLocked(LockError):
"""
pass
+
class LockFailed(LockError):
"""Lock file creation failed for some other reason.
@@ -120,6 +126,7 @@ class LockFailed(LockError):
"""
pass
+
class UnlockError(Error):
"""
Base class for errors arising from attempts to release the lock.
@@ -131,6 +138,7 @@ class UnlockError(Error):
"""
pass
+
class NotLocked(UnlockError):
"""Raised when an attempt is made to unlock an unlocked file.
@@ -141,6 +149,7 @@ class NotLocked(UnlockError):
"""
pass
+
class NotMyLock(UnlockError):
"""Raised when an attempt is made to unlock a file someone else locked.
@@ -151,12 +160,13 @@ class NotMyLock(UnlockError):
"""
pass
+
class LockBase:
"""Base class for platform-specific lock classes."""
def __init__(self, path, threaded=True):
"""
- >>> lock = LockBase('somefile')
- >>> lock = LockBase('somefile', threaded=False)
+ >>> lock = LockBase("somefile")
+ >>> lock = LockBase("somefile", threaded=False)
"""
self.path = path
self.lock_file = os.path.abspath(path) + ".lock"
@@ -172,84 +182,85 @@ def __init__(self, path, threaded=True):
"%s.%s%s" % (self.hostname,
tname,
self.pid))
-
+
def acquire(self, timeout=None):
"""
Acquire the lock.
-
+
* If timeout is omitted (or None), wait forever trying to lock the
file.
-
+
* If timeout > 0, try to acquire the lock for that many seconds. If
the lock period expires and the file is still locked, raise
LockTimeout.
-
+
* If timeout <= 0, raise AlreadyLocked immediately if the file is
already locked.
"""
- raise NotImplemented("implement in subclass")
-
+ raise NotImplementedError("implement in subclass")
+
def release(self):
"""
Release the lock.
If the file is not locked, raise NotLocked.
"""
- raise NotImplemented("implement in subclass")
-
+ raise NotImplementedError("implement in subclass")
+
def is_locked(self):
"""
Tell whether or not the file is locked.
"""
- raise NotImplemented("implement in subclass")
-
+ raise NotImplementedError("implement in subclass")
+
def i_am_locking(self):
"""
Return True if this object is locking the file.
"""
- raise NotImplemented("implement in subclass")
-
+ raise NotImplementedError("implement in subclass")
+
def break_lock(self):
"""
Remove a lock. Useful if a locking thread failed to unlock.
"""
- raise NotImplemented("implement in subclass")
-
+ raise NotImplementedError("implement in subclass")
+
def __enter__(self):
"""
Context manager support.
"""
self.acquire()
return self
-
+
def __exit__(self, *_exc):
"""
Context manager support.
"""
self.release()
+
class LinkFileLock(LockBase):
"""Lock access to a file using atomic property of link(2)."""
-
+
def acquire(self, timeout=None):
try:
open(self.unique_name, "wb").close()
except IOError:
raise LockFailed("failed to create %s" % self.unique_name)
-
+
end_time = time.time()
if timeout is not None and timeout > 0:
end_time += timeout
-
+
while True:
# Try and create a hard link to it.
try:
os.link(self.unique_name, self.lock_file)
except OSError:
- # Link creation failed. Maybe we've double-locked?
+ # Link creation failed. Maybe we"ve double-locked?
nlinks = os.stat(self.unique_name).st_nlink
if nlinks == 2:
- # The original link plus the one I created == 2. We're
+ # The original link plus the one I created == 2. We"re
# good to go.
return
else:
@@ -262,9 +273,9 @@ def acquire(self, timeout=None):
raise AlreadyLocked
time.sleep(timeout is not None and timeout/10 or 0.1)
else:
- # Link creation succeeded. We're good to go.
+ # Link creation succeeded. We"re good to go.
return
-
+
def release(self):
if not self.is_locked():
raise NotLocked
@@ -272,25 +283,26 @@ def release(self):
raise NotMyLock
os.unlink(self.unique_name)
os.unlink(self.lock_file)
-
+
def is_locked(self):
return os.path.exists(self.lock_file)
-
+
def i_am_locking(self):
return (self.is_locked() and
os.path.exists(self.unique_name) and
os.stat(self.unique_name).st_nlink == 2)
-
+
def break_lock(self):
if os.path.exists(self.lock_file):
os.unlink(self.lock_file)
+
class MkdirFileLock(LockBase):
"""Lock file by creating a directory."""
def __init__(self, path, threaded=True):
"""
- >>> lock = MkdirFileLock('somefile')
- >>> lock = MkdirFileLock('somefile', threaded=False)
+ >>> lock = MkdirFileLock("somefile")
+ >>> lock = MkdirFileLock("somefile", threaded=False)
"""
LockBase.__init__(self, path, threaded)
if threaded:
@@ -299,21 +311,21 @@ def __init__(self, path, threaded=True):
tname = ""
# Lock file itself is a directory. Place the unique file name into
# it.
- self.unique_name = os.path.join(self.lock_file,
- "%s.%s%s" % (self.hostname,
- tname,
- self.pid))
-
+ self.unique_name = os.path.join(
+ self.lock_file,
+ "{}.{}{}".format(self.hostname, tname, self.pid)
+ )
+
def acquire(self, timeout=None):
end_time = time.time()
if timeout is not None and timeout > 0:
end_time += timeout
-
+
if timeout is None:
wait = 0.1
else:
wait = max(0, timeout / 10)
-
+
while True:
try:
os.mkdir(self.lock_file)
@@ -332,12 +344,12 @@ def acquire(self, timeout=None):
raise AlreadyLocked
time.sleep(wait)
else:
- # Couldn't create the lock for some other reason
+ # Couldn"t create the lock for some other reason
raise LockFailed("failed to create %s" % self.lock_file)
else:
open(self.unique_name, "wb").close()
return
-
+
def release(self):
if not self.is_locked():
raise NotLocked
@@ -345,99 +357,104 @@ def release(self):
raise NotMyLock
os.unlink(self.unique_name)
os.rmdir(self.lock_file)
-
+
def is_locked(self):
return os.path.exists(self.lock_file)
-
+
def i_am_locking(self):
return (self.is_locked() and
os.path.exists(self.unique_name))
-
+
def break_lock(self):
if os.path.exists(self.lock_file):
for name in os.listdir(self.lock_file):
os.unlink(os.path.join(self.lock_file, name))
os.rmdir(self.lock_file)
-class SQLiteFileLock(LockBase):
- "Demonstration of using same SQL-based locking."
+class SQLiteFileLock(LockBase):
+ """Demonstration of using same SQL-based locking."""
+
import tempfile
_fd, testdb = tempfile.mkstemp()
os.close(_fd)
os.unlink(testdb)
del _fd, tempfile
-
+
def __init__(self, path, threaded=True):
LockBase.__init__(self, path, threaded)
self.lock_file = unicode(self.lock_file)
self.unique_name = unicode(self.unique_name)
-
+
import sqlite3
self.connection = sqlite3.connect(SQLiteFileLock.testdb)
- c = self.connection.cursor()
+ cursor = self.connection.cursor()
try:
- c.execute("create table locks"
- "("
- " lock_file varchar(32),"
- " unique_name varchar(32)"
- ")")
+ cursor.execute("create table locks"
+ "("
+ " lock_file varchar(32),"
+ " unique_name varchar(32)"
+ ")")
except sqlite3.OperationalError:
pass
else:
self.connection.commit()
import atexit
atexit.register(os.unlink, SQLiteFileLock.testdb)
-
+
+ def create_lock(self, cursor):
+ # Not locked. Try to lock it.
+ cursor.execute("insert into locks"
+ " (lock_file, unique_name)"
+ " values"
+ " (?, ?)",
+ (self.lock_file, self.unique_name))
+ self.connection.commit()
+
+ # Check to see if we are the only lock holder.
+ cursor.execute("select * from locks where unique_name = ?",
+ (self.unique_name,))
+ rows = cursor.fetchall()
+ if len(rows) > 1:
+ # Nope. Someone else got there. Remove our lock.
+ cursor.execute("delete from locks where unique_name = ?",
+ (self.unique_name,))
+ self.connection.commit()
+ return False
+ return True
+
+ def i_am_the_only_lock(self, cursor):
+ # Check to see if we are the only lock holder.
+ cursor.execute("select * from locks where unique_name = ?",
+ (self.unique_name,))
+ rows = cursor.fetchall()
+ if len(rows) == 1:
+ # We"re the locker, so go home.
+ return
+
def acquire(self, timeout=None):
end_time = time.time()
if timeout is not None and timeout > 0:
end_time += timeout
-
+
if timeout is None:
wait = 0.1
elif timeout <= 0:
wait = 0
else:
wait = timeout / 10
-
+
cursor = self.connection.cursor()
-
+
while True:
- if not self.is_locked():
- # Not locked. Try to lock it.
- cursor.execute("insert into locks"
- " (lock_file, unique_name)"
- " values"
- " (?, ?)",
- (self.lock_file, self.unique_name))
- self.connection.commit()
-
- # Check to see if we are the only lock holder.
- cursor.execute("select * from locks"
- " where unique_name = ?",
- (self.unique_name,))
- rows = cursor.fetchall()
- if len(rows) > 1:
- # Nope. Someone else got there. Remove our lock.
- cursor.execute("delete from locks"
- " where unique_name = ?",
- (self.unique_name,))
- self.connection.commit()
- else:
- # Yup. We're done, so go home.
+ if self.is_locked():
+ if self.i_am_the_only_lock(cursor):
return
else:
- # Check to see if we are the only lock holder.
- cursor.execute("select * from locks"
- " where unique_name = ?",
- (self.unique_name,))
- rows = cursor.fetchall()
- if len(rows) == 1:
- # We're the locker, so go home.
+ if self.create_lock(cursor):
return
-
+
# Maybe we should wait a bit longer.
if timeout is not None and time.time() > end_time:
if timeout > 0:
@@ -446,10 +463,10 @@ def acquire(self, timeout=None):
else:
# Someone else has the lock and we are impatient..
raise AlreadyLocked
-
- # Well, okay. We'll give it a bit longer.
+
+ # Well, okay. We"ll give it a bit longer.
time.sleep(wait)
-
+
def release(self):
if not self.is_locked():
raise NotLocked
@@ -460,14 +477,14 @@ def release(self):
" where unique_name = ?",
(self.unique_name,))
self.connection.commit()
-
+
def _who_is_locking(self):
cursor = self.connection.cursor()
cursor.execute("select unique_name from locks"
" where lock_file = ?",
(self.lock_file,))
return cursor.fetchone()[0]
-
+
def is_locked(self):
cursor = self.connection.cursor()
cursor.execute("select * from locks"
@@ -475,7 +492,7 @@ def is_locked(self):
(self.lock_file,))
rows = cursor.fetchall()
return not not rows
-
+
def i_am_locking(self):
cursor = self.connection.cursor()
cursor.execute("select * from locks"
@@ -483,7 +500,7 @@ def i_am_locking(self):
" and unique_name = ?",
(self.lock_file, self.unique_name))
return not not cursor.fetchall()
-
+
def break_lock(self):
cursor = self.connection.cursor()
cursor.execute("delete from locks"
@@ -491,6 +508,8 @@ def break_lock(self):
(self.lock_file,))
self.connection.commit()
+
+# pylint: disable-msg=C0103
if hasattr(os, "link"):
FileLock = LinkFileLock
else:
View
17 notification/models.py
@@ -13,6 +13,11 @@
DEFAULT_QUEUE_ALL = False
+QUEUE_ALL = getattr(settings, "NOTIFICATION_QUEUE_ALL", DEFAULT_QUEUE_ALL)
+NOTIFICATION_BACKENDS = backends.load_backends()
+NOTICE_MEDIA, NOTICE_MEDIA_DEFAULTS = backends.load_media_defaults(
+ backends=NOTIFICATION_BACKENDS
+)
class LanguageStoreNotAvailable(Exception):
@@ -64,16 +69,6 @@ def create(cls, label, display, description, default=2, verbosity=1):
print "Created %s NoticeType" % label
-NOTIFICATION_BACKENDS = backends.load_backends()
-
-NOTICE_MEDIA = []
-NOTICE_MEDIA_DEFAULTS = {}
-for key, backend in NOTIFICATION_BACKENDS.items():
- # key is a tuple (medium_id, backend_label)
- NOTICE_MEDIA.append(key)
- NOTICE_MEDIA_DEFAULTS[key[0]] = backend.spam_sensitivity
-
-
class NoticeSetting(models.Model):
"""
Indicates, for a given user, whether to send notifications
@@ -119,6 +114,7 @@ def get_notification_language(user):
try:
app_label, model_name = settings.NOTIFICATION_LANGUAGE_MODULE.split(".")
model = models.get_model(app_label, model_name)
+ # pylint: disable-msg=W0212
language_model = model._default_manager.get(user__id__exact=user.id)
if hasattr(language_model, "language"):
return language_model.language
@@ -175,7 +171,6 @@ def send(*args, **kwargs):
be queued or not. A per call ``queue`` or ``now`` keyword argument can be
used to always override the default global behavior.
"""
- QUEUE_ALL = getattr(settings, "NOTIFICATION_QUEUE_ALL", DEFAULT_QUEUE_ALL)
queue_flag = kwargs.pop("queue", False)
now_flag = kwargs.pop("now", False)
assert not (queue_flag and now_flag), "'queue' and 'now' cannot both be True."
View
5 notification/signals.py
@@ -1,4 +1,7 @@
import django.dispatch
-emitted_notices = django.dispatch.Signal(providing_args=["batches", "sent", "sent_actual", "run_time"])
+# pylint: disable-msg=C0103
+emitted_notices = django.dispatch.Signal(
+ providing_args=["batches", "sent", "sent_actual", "run_time"]
+)
View
4 notification/views.py
@@ -50,12 +50,12 @@ def notice_settings(request):
next_page = request.POST.get("next_page", ".")
return HttpResponseRedirect(next_page)
- notice_settings = {
+ settings = {
"column_headers": [medium_display for medium_id, medium_display in NOTICE_MEDIA],
"rows": settings_table,
}
return render_to_response("notification/notice_settings.html", {
"notice_types": notice_types,
- "notice_settings": notice_settings,
+ "notice_settings": settings,
}, context_instance=RequestContext(request))
Please sign in to comment.
Something went wrong with that request. Please try again.