1 """ |
1 """ |
2 Configuration |
2 Configuration |
3 """ |
3 """ |
4 |
4 |
5 import logging |
5 import copy, logging |
6 |
6 |
7 class Configuration (object) : |
7 class InstanceContext (object) : |
|
8 """ |
|
9 An object that behaves like a dict, performing all item lookups as attribute lookups on the given object. |
|
10 |
|
11 Useful for binding an exec statement's locals. |
|
12 """ |
|
13 |
|
14 def __init__ (self, obj) : self.obj = obj |
|
15 def __getitem__ (self, key) : return getattr(self.obj, key) |
|
16 def __setitem__ (self, key, value) : setattr(self.obj, key, value) |
|
17 |
|
18 class ConfigurationMachinery (object) : |
|
19 """ |
|
20 The low-level configuration machinery. |
|
21 """ |
|
22 |
|
23 def import_py (self, path) : |
|
24 """ |
|
25 Import python-style configuration from the given File object into this one. |
|
26 |
|
27 This runs the file's code using exec, using a context mapped to this object. |
|
28 """ |
|
29 |
|
30 # the code |
|
31 file = open(path) |
|
32 |
|
33 # build suitable locals/globals to proxy this object |
|
34 locals = InstanceContext(self) |
|
35 |
|
36 # run |
|
37 exec file in {}, locals |
|
38 |
|
39 def import_file (self, path) : |
|
40 """ |
|
41 Import configuration from the given File into this one. |
|
42 """ |
|
43 |
|
44 # as python code |
|
45 self.import_py(path) |
|
46 |
|
47 def load (self, path) : |
|
48 """ |
|
49 Loads the configuration from the given File, creating a new Configuration with defaults from this one. |
|
50 """ |
|
51 |
|
52 # copy ourself |
|
53 new = copy.copy(self) |
|
54 |
|
55 # import into it |
|
56 new.import_file(path) |
|
57 |
|
58 # return |
|
59 return new |
|
60 |
|
61 class Configuration (ConfigurationMachinery) : |
8 """ |
62 """ |
9 Various configuration settings |
63 Various configuration settings |
10 """ |
64 """ |
11 ## runtime settings |
|
12 |
65 |
13 # the path to the gallery |
66 # the path to the gallery root |
|
67 # only valid in top-level config |
14 gallery_path = "." |
68 gallery_path = "." |
15 |
69 |
16 # force-update items |
70 # force-update items |
17 force_thumb = False |
71 force_thumb = False |
18 force_html = False |
72 force_html = False |
19 |
73 |
|
74 def get_force_update (self) : |
|
75 return self.force_thumb or self.force_html |
|
76 |
|
77 def set_force_update (self, value) : |
|
78 self.force_thumb = self.force_html = value |
|
79 |
|
80 force_update = property(get_force_update, set_force_update) |
|
81 |
20 # minimum logging level |
82 # minimum logging level |
21 log_level = logging.INFO |
83 log_level = logging.INFO |
|
84 |
|
85 def quiet (self) : self.log_level = logging.WARN |
|
86 def debug (self) : self.log_level = logging.DEBUG |
22 |
87 |
23 # number of threads to use for concurrency |
88 # number of threads to use for concurrency |
24 thread_count = 2 |
89 thread_count = 2 |
25 |
90 |
26 ## detailed configuration |
91 # the name of this folder, only applies on one level |
27 # the name of the gallery |
92 # default applies to the root gallery |
28 gallery_title = "Image Gallery" |
93 title = "Image Gallery" |
29 |
94 |
30 # recognized image extensions |
95 # recognized image extensions, case-insensitive |
31 image_exts = ('jpg', 'jpeg', 'png', 'gif', 'bmp') |
96 image_exts = ('jpg', 'jpeg', 'png', 'gif', 'bmp') |
32 |
97 |
33 # subdirectory used for generated thumbnails/previews |
98 # subdirectory names used for generated thumbnails/previews |
34 thumb_dir = 'thumbs' |
99 thumb_dir = 'thumbs' |
35 preview_dir = 'previews' |
100 preview_dir = 'previews' |
36 |
101 |
37 # size of generated thumbnails/previews |
102 # size of generated thumbnails/previews as (width, height) tuples |
38 thumb_size = (160, 120) |
103 thumb_size = (160, 120) |
39 preview_size = (640, 480) |
104 preview_size = (640, 480) |
40 |
105 |
41 # number of images displayed per folder page |
106 # number of images displayed per folder page |
42 images_per_page = 50 |
107 images_per_page = 50 |
43 |
108 |
44 # load Exif data for images |
109 # load Exif data for images, this may be slow |
45 # this may be slow |
110 with_exif = False |
46 exif_enabled = False |
|
47 |
111 |
48 # exif tags used in output |
112 # exif tags used in output |
49 # Copyright (C) 2008, Santtu Pajukanta <santtu@pajukanta.fi> |
113 # Copyright (C) 2008, Santtu Pajukanta <santtu@pajukanta.fi> |
50 # XXX: import from dexif? |
114 # XXX: import from dexif? |
51 exif_tags = [ |
115 exif_tags = ( |
52 # TODO Create date is in a useless format, needs some strptime love |
116 # TODO Create date is in a useless format, needs some strptime love |
53 ("CreateDate", "Create date" ), |
117 ("CreateDate", "Create date" ), |
54 ("Model", "Camera model" ), |
118 ("Model", "Camera model" ), |
55 ("Aperture", "Aperture" ), |
119 ("Aperture", "Aperture" ), |
56 ("ExposureMode", "Exposure mode" ), |
120 ("ExposureMode", "Exposure mode" ), |
58 ("ExposureTime", "Exposure time" ), |
122 ("ExposureTime", "Exposure time" ), |
59 ("Flash", "Flash mode" ), |
123 ("Flash", "Flash mode" ), |
60 ("ISO", "ISO" ), |
124 ("ISO", "ISO" ), |
61 ("ShootingMode", "Shooting mode" ), |
125 ("ShootingMode", "Shooting mode" ), |
62 ("LensType", "Lens type" ), |
126 ("LensType", "Lens type" ), |
63 ("FocalLength", "Focal length" ) |
127 ("FocalLength", "Focal length" ), |
64 ] |
128 ) |
65 |
|
66 |
129 |
67 ### functions |
130 # XXX: move elsewhere? |
68 def is_image (self, file) : |
131 def is_image (self, file) : |
69 """ |
132 """ |
70 Tests if the given File is an image, based on its file extension |
133 Tests if the given File is an image, based on its file extension |
|
134 |
71 """ |
135 """ |
72 |
136 |
73 return file.matchext(self.image_exts) |
137 return file.matchext(self.image_exts) |
74 |
138 |