devserver: general cleanup

* Unified logging API via module/class-local _Log() calls.

* Renamed modules: devserver_util --> common_util (this is the common
  util module, and it saves a lot of characters in many places);
  downloadable_artifact --> build_artifact (we don't have any
  non-downloadable artifacts); buildutil.py --> build_util.py (for
  uniformity)

* Reorganized Artifact (now BuildArtifact) class hierarchy to properly
  reflect the inheritance chains.

BUG=None
TEST=Unit tests run successfully

Change-Id: I91f3bd7afe78cc1e2be10b64640515402fb6184b
Reviewed-on: https://gerrit.chromium.org/gerrit/33755
Reviewed-by: Chris Sosa <sosa@chromium.org>
Commit-Ready: Gilad Arnold <garnold@chromium.org>
Tested-by: Gilad Arnold <garnold@chromium.org>
diff --git a/log_util.py b/log_util.py
new file mode 100644
index 0000000..8b608a9
--- /dev/null
+++ b/log_util.py
@@ -0,0 +1,25 @@
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Logging via CherryPy."""
+
+import re
+
+import cherrypy
+
+
+class Loggable(object):
+  """Provides a log method, with automatic log tag generation."""
+  _CAMELCASE_RE = re.compile('(?<=.)([A-Z])')
+
+  def _Log(self, message, *args, **kwargs):
+    return LogWithTag(
+        self._CAMELCASE_RE.sub(r'_\1', self.__class__.__name__).upper(),
+        message, *args, **kwargs)
+
+
+def LogWithTag(tag, message, *args, **kwargs):
+  # CherryPy log doesn't seem to take any optional args, so we'll just join
+  # them into a single string, if any are provided.
+  return cherrypy.log(message + ((' ' + ' '.join(args)) if args else ''), tag)