degal/config.py
changeset 118 60b126ff0b74
parent 117 a2e4562deaab
child 120 55cb7fc9c8fb
--- a/degal/config.py	Sun Jun 14 20:05:11 2009 +0300
+++ b/degal/config.py	Sun Jun 14 22:52:07 2009 +0300
@@ -2,53 +2,117 @@
     Configuration
 """
 
-import logging
+import copy, logging
 
-class Configuration (object) :
+class InstanceContext (object) :
+    """
+        An object that behaves like a dict, performing all item lookups as attribute lookups on the given object.
+
+        Useful for binding an exec statement's locals.
+    """
+
+    def __init__ (self, obj) : self.obj = obj
+    def __getitem__ (self, key) : return getattr(self.obj, key)
+    def __setitem__ (self, key, value) : setattr(self.obj, key, value)
+
+class ConfigurationMachinery (object) :
+    """
+        The low-level configuration machinery.
+    """
+
+    def import_py (self, path) :
+        """
+            Import python-style configuration from the given File object into this one.
+
+            This runs the file's code using exec, using a context mapped to this object.
+        """
+
+        # the code
+        file = open(path)
+ 
+        # build suitable locals/globals to proxy this object
+        locals = InstanceContext(self)
+
+        # run
+        exec file in {}, locals
+       
+    def import_file (self, path) :
+        """
+            Import configuration from the given File into this one.
+        """
+        
+        # as python code
+        self.import_py(path)
+
+    def load (self, path) :
+        """
+            Loads the configuration from the given File, creating a new Configuration with defaults from this one.
+        """
+
+        # copy ourself
+        new = copy.copy(self)
+
+        # import into it
+        new.import_file(path)
+
+        # return
+        return new
+
+class Configuration (ConfigurationMachinery) :
     """
         Various configuration settings
     """
-    ## runtime settings
 
-    # the path to the gallery
+    # the path to the gallery root
+    # only valid in top-level config
     gallery_path        = "."
     
     # force-update items
     force_thumb         = False
     force_html          = False
 
+    def get_force_update (self) :
+        return self.force_thumb or self.force_html
+
+    def set_force_update (self, value) :
+        self.force_thumb = self.force_html = value
+    
+    force_update = property(get_force_update, set_force_update)
+
     # minimum logging level
     log_level           = logging.INFO
 
+    def quiet (self) : self.log_level = logging.WARN
+    def debug (self) : self.log_level = logging.DEBUG
+
     # number of threads to use for concurrency
     thread_count        = 2
 
-    ## detailed configuration
-    # the name of the gallery
-    gallery_title       = "Image Gallery"
+    # the name of this folder, only applies on one level
+    # default applies to the root gallery
+    title               = "Image Gallery"
 
-    # recognized image extensions
+    # recognized image extensions, case-insensitive
     image_exts          = ('jpg', 'jpeg', 'png', 'gif', 'bmp')
     
-    # subdirectory used for generated thumbnails/previews
+    # subdirectory names used for generated thumbnails/previews
     thumb_dir           = 'thumbs'
     preview_dir         = 'previews'
 
-    # size of generated thumbnails/previews
+    # size of generated thumbnails/previews as (width, height) tuples
     thumb_size          = (160, 120)
     preview_size        = (640, 480)
 
     # number of images displayed per folder page
     images_per_page     = 50
     
-    # load Exif data for images
-    # this may be slow
-    exif_enabled        = False
+    # load Exif data for images, this may be slow
+    with_exif           = False
 
     # exif tags used in output
     # Copyright (C) 2008, Santtu Pajukanta <santtu@pajukanta.fi>
     # XXX: import from dexif?
-    exif_tags           = [
+    exif_tags           = (
         # TODO Create date is in a useless format, needs some strptime love
         ("CreateDate",              "Create date"               ),
         ("Model",                   "Camera model"              ),
@@ -60,15 +124,15 @@
         ("ISO",                     "ISO"                       ),
         ("ShootingMode",            "Shooting mode"             ),
         ("LensType",                "Lens type"                 ),
-        ("FocalLength",             "Focal length"              )
-    ]
-    
+        ("FocalLength",             "Focal length"              ),
+    )
 
-    ### functions
+    # XXX: move elsewhere?
     def is_image (self, file) :
         """
             Tests if the given File is an image, based on its file extension
+
         """
 
         return file.matchext(self.image_exts)
-
+