xdg 0.5.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/HISTORY CHANGED
@@ -1,65 +1,81 @@
1
1
  = RELEASE HISTORY
2
2
 
3
+ == 1.0.0 / 2009-12-01
4
+
5
+ This is major reimplementation of the XDG API to be more flexiable
6
+ and object-oriented. Instead of a single module with every
7
+ needed method, the system is devided up into sub-modules, one for
8
+ each set of XDG locations. So, for example, instead of "XDG.data_dirs"
9
+ you use "XDG::Data.dirs" or "XDG.data.dirs".
10
+
11
+ Changes:
12
+
13
+ * Reworked API and underlying implementation to be more OOP-style.
14
+ * Began work on xdg/extended.rb, exploring future proposals.
15
+ * Provides xdg/compat.rb, for backward compatabilty (temporary).
16
+
17
+
3
18
  == 0.5.2 / 2009-05-30
4
19
 
5
20
  This release requires rbconfig.rb and uses system entries in place of
6
- hardcoded FHS locations.
21
+ some hardcoded FHS locations.
7
22
 
8
23
  Changes:
9
24
 
10
- * 1 Enhancement
11
-
12
- * replaced hardcoded system directories with rbconfig entries.
25
+ * Replaced hardcoded system directories with rbconfig entries.
13
26
 
14
27
 
15
28
  == 0.5.1 / 2008-11-17
16
29
 
17
30
  Changes:
18
31
 
19
- * 4 Enhancements
20
-
21
- * data work directory is '.local', not '.share'
22
- * data_work is deprecated
23
- * updated website
32
+ * Fixed data work directory is '.local', not '.share'
33
+ * Deprecated #data_work
24
34
 
25
35
 
26
36
  == 0.5.0 / 2008-10-28
27
37
 
28
38
  Changes:
29
39
 
30
- * 1 Enhancement
31
-
32
- * changed _glob to _select
40
+ * Changed _glob to _select
33
41
 
34
42
 
35
43
  == 0.4.0 / 2008-10-26
36
44
 
37
- Changes:
45
+ This release removes the xdg_ prefix from the instance-level
46
+ method names. Now module and instance levels are the same.
38
47
 
39
- * 9 Enhancements
48
+ Also, data_file, config_file and cache_file have been replaced with
49
+ data_find, config_find, cache_find, data_glob, config_glob and
50
+ cache_glob.
40
51
 
41
- * removed xdg_ prefixes and replaced _file methods with _find and _glob methods
42
- * prepare for v0.4 release
43
- * remove some old commented-out code
44
- * fixed data_find and data_glob
45
- * Update RELEASE file
46
- * updated documentation for 0.4 release
47
- * added MANIFEST to .gitignore
48
- * correction or RELEASE
49
- * Fixed plural in RELEASE file
52
+ What's next? Well, I can't say I'm fond of the term 'glob', so I
53
+ may rename that to 'map' or 'collect' (or 'select'?) and then
54
+ add the ability to use blocks for matching too.
55
+
56
+ Changes:
57
+
58
+ * Renamed instance level methods without 'xdg_' prefix.
59
+ * Replace _file methods with _find and _glob methods.
60
+ * Prepare for v0.4 release
61
+ * Remove some old commented-out code
62
+ * Fixed data_find and data_glob
63
+ * Update RELEASE file
64
+ * Updated documentation for 0.4 release
65
+ * Added MANIFEST to .gitignore
66
+ * Correction or RELEASE
67
+ * Fixed plural in RELEASE file
50
68
 
51
69
 
52
70
  == 0.3.0 / 2008-10-11
53
71
 
54
72
  Changes:
55
73
 
56
- * 5 Enhancements
57
-
58
- * removed xdg_ prefix from module methods
59
- * moved web/index.html to doc directory
60
- * updated reap serives
61
- * prepare for next release
62
- * fixed issue of xdg_ prefix still being used internally
74
+ * Removed xdg_ prefix from module methods
75
+ * Moved web/index.html to doc directory
76
+ * Updated reap serives
77
+ * Prepare for next release
78
+ * Fixed issue of xdg_ prefix still being used internally
63
79
 
64
80
 
65
81
  == 0.1.0 / 2008-09-27
data/MANIFEST CHANGED
@@ -1,33 +1,22 @@
1
- #!mast bin lib meta test [A-Z]*
2
- lib
1
+ #!mast bin lib meta script test [A-Z]*
2
+ lib/xdg/compat.rb
3
+ lib/xdg/extended.rb
3
4
  lib/xdg.rb
4
- meta
5
- meta/abstract
6
5
  meta/authors
6
+ meta/collection
7
7
  meta/contact
8
+ meta/description
8
9
  meta/homepage
9
- meta/package
10
+ meta/name
11
+ meta/repository
10
12
  meta/summary
11
13
  meta/title
12
14
  meta/version
13
- test
14
- test/fakeroot
15
- test/fakeroot/.cache
16
- test/fakeroot/.config
17
- test/fakeroot/.share
18
- test/fakeroot/etc
19
- test/fakeroot/etc/xdg
15
+ script/test
20
16
  test/fakeroot/etc/xdg/bar.config
21
- test/fakeroot/home
22
- test/fakeroot/home/.cache
23
17
  test/fakeroot/home/.cache/foo.cache
24
- test/fakeroot/home/.config
25
18
  test/fakeroot/home/.config/foo.config
26
- test/fakeroot/home/.local
27
- test/fakeroot/home/.local/share
28
19
  test/fakeroot/home/.local/share/foo.dat
29
- test/fakeroot/usr
30
- test/fakeroot/usr/share
31
20
  test/fakeroot/usr/share/bar.dat
32
21
  test/test_xdg.rb
33
22
  README
data/README CHANGED
@@ -1,6 +1,7 @@
1
1
  = XDG Base Directory Standard for Ruby
2
2
 
3
- http://xdg.rubyforge.org
3
+ * http://rubyworks.github.com/xdg
4
+ * http://github.com/rubyworks/xdg
4
5
 
5
6
  == Introduction
6
7
 
@@ -11,62 +12,86 @@ If your program utilizes user or system-wide support files
11
12
  (eg. configuration files), you owe it to yourself to checkout
12
13
  the XDG standard.
13
14
 
14
- What's next? The API should be stable now. I do not forsee
15
- and reasons for it to change. In the future, I may add some
16
- additional ruby-esque features, perhaps for other parts of
17
- the XDG utilities, but that should be purely in addition to
18
- what is already here. If all this holds true for a while a
19
- 1.0 release will be forth-coming.
20
-
21
15
  [1]http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
22
16
 
23
- == Release Notes
24
17
 
25
- Please see the RELEASE file.
18
+ == HOW TO USE
19
+
20
+ XDG consists of a small set of modules, one for each XDG directory. Each of
21
+ these has a small base set of easy to use methods.
22
+
23
+ XDG::Config.home
24
+ XDG::Config.dirs
25
+ XDG::Config.find(pattern){ |path| ... }
26
+ XDG::Config.search(pattern){ |path| ... }
26
27
 
27
- == Usage
28
+ XDG::Data.home
29
+ XDG::Data.dirs
30
+ XDG::Data.find(pattern){ |path| ... }
31
+ XDG::Data.search(pattern){ |path| ... }
28
32
 
29
- XDG is a module with a small set of easy to use methods:
33
+ XDG::Cache.home
34
+ XDG::Cache.find(pattern){ |path| ... }
35
+ XDG::Cache.search(pattern){ |path| ... }
30
36
 
31
- XDG.config_home
32
- XDG.config_dirs
33
- XDG.config_find(pattern){ |path| ... }
34
- XDG.config_select(pattern){ |path| ... }
37
+ XDG can also access these modules via methods.
35
38
 
36
- XDG.data_home
37
- XDG.data_dirs
38
- XDG.data_find(pattern){ |path| ... }
39
- XDG.data_select(pattern){ |path| ... }
39
+ XDG.config.home
40
+ XDG.config.dirs
41
+ XDG.config.find(pattern){ |path| ... }
42
+ XDG.config.search(pattern){ |path| ... }
40
43
 
41
- XDG.cache_home
42
- XDG.cache_find(pattern){ |path| ... }
43
- XDG.cache_select(pattern){ |path| ... }
44
+ XDG.data.home
45
+ XDG.data.dirs
46
+ XDG.data.find(pattern){ |path| ... }
47
+ XDG.data.search(pattern){ |path| ... }
44
48
 
45
- XDG.config_work
46
- XDG.cache_work
49
+ XDG.cache.home
50
+ XDG.cache.find(pattern){ |path| ... }
51
+ XDG.cache.search(pattern){ |path| ... }
47
52
 
48
53
  If you know XDG these are pretty much self-explanitory.
49
54
  But see the RDocs for specifics.
50
55
 
51
- == Installation
56
+ === Extended Functionality
57
+
58
+ The Ruby XDG module also provides extended functionality
59
+ not part of the standard specification. These extensions are
60
+ simply add-on funcitonality deemed useful, or implementations
61
+ of proposals being discussed for a possible future version of
62
+ the standard.
63
+
64
+ require 'xdg/extended'
65
+
66
+ XDG.config.work
67
+ XDG.cache.work
68
+
69
+ See the API for the extended.rb, to learn more. Note that
70
+ the extended modules are subject to great change of change
71
+ as they are still being designed.
72
+
73
+
74
+ == HOW TO INSTALL
52
75
 
53
76
  Using RubyGems:
54
77
 
55
78
  $ sudo gem install xdg
56
79
 
57
- Installing the tarball requires Ruby Setup
58
- (see http://setup.rubyforge.org).
80
+ Installing the tarball requires Ruby Setup (see http://proutils.github.com/setup).
59
81
 
60
82
  $ tar -xvzf xdg-0.5.2
61
83
  $ cd xdg-0.5.2
62
84
  $ sudo setup.rb all
63
85
 
64
- == Development
65
86
 
66
- Visit http://rubyforge.org/projects/xdg
87
+ == DEVELOPMENT
88
+
89
+ Visit http://github.com/proutils/xdg
90
+
67
91
 
68
- == Copyright
92
+ == COPYRIGHT
69
93
 
70
- Copyright (c) 2008 Tiger Ops / 7rans
94
+ Copyright (c) 2008, 2009 Thomas Sawyer
71
95
  Distributed under the terms of the LGPL v3 license.
96
+ See COPYING file for details.
72
97
 
data/lib/xdg.rb CHANGED
@@ -7,12 +7,11 @@ require 'rbconfig'
7
7
  #
8
8
  # http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
9
9
  #
10
- # Some important clarifications, not made clear by the
11
- # above specification.
10
+ # Some important clarifications, not made clear by the above specification.
12
11
  #
13
12
  # The data directories are for "read-only" files. In other words once
14
13
  # something is put there, it should only be read, and never written to
15
- # by a program. (Generally speaking only users or package mangers should
14
+ # by a program. (Generally speaking only users or package managers should
16
15
  # be adding, changing or removing files from the data locations.)
17
16
  #
18
17
  # The config locations are where you store files that may change,
@@ -21,217 +20,239 @@ require 'rbconfig'
21
20
  # not just root and sudo admin scripts.
22
21
  #
23
22
  # The cache locations stores files that could just as well be deleted
24
- # and everyihtng would still work fine. This is for variable and
25
- # temporary files. much like var/ in FHS.
23
+ # and everything would still work fine. This is for variable and
24
+ # temporary files. Much like var/ and tmp/ in FHS.
26
25
  #
27
26
  # The module returns all paths as String.
28
27
  #
29
28
  module XDG
30
29
 
31
- extend self #module_function
30
+ #module_function
31
+ extend self
32
32
 
33
33
  # Returns user's home directory.
34
+ #
34
35
  def home
35
36
  File.expand_path('~') # ENV['HOME']
36
37
  end
37
38
 
38
- # Location of user's personal config directory.
39
- def config_home
40
- File.expand_path(
41
- ENV['XDG_CONFIG_HOME'] || File.join(home, '.config')
42
- )
43
- end
44
-
45
- # List of user's shared config directories.
46
- def config_dirs
47
- dirs = ENV['XDG_CONFIG_DIRS'].to_s.split(/[:;]/)
48
- if dirs.empty?
49
- dirs = File.join(Config::CONFIG['sysconfdir'], 'xdg') #%w{/etc/xdg}
39
+ # Access to data resource locations.
40
+ #
41
+ # XDG.data.each{ |dir| ... }
42
+ #
43
+ def data(*glob_and_flags, &block)
44
+ if !glob_and_flags.empty? or block_given?
45
+ Data.select(*glob_and_flags, &block)
46
+ else
47
+ Data
50
48
  end
51
- dirs.collect{ |d| File.expand_path(d) }
52
- end
53
-
54
- # Location of user's personal data directory.
55
- def data_home
56
- File.expand_path(
57
- ENV['XDG_DATA_HOME'] || File.join(home, '.local', 'share')
58
- )
59
49
  end
60
50
 
61
- # List of user's shared data directores.
62
- def data_dirs
63
- dirs = ENV['XDG_DATA_DIRS'].split(/[:;]/)
64
- if dirs.empty?
65
- dirs = [ Config::CONFIG['localdatadir'], Config::CONFIG['datadir'] ] #%w{/usr/local/share/ /usr/share/}
51
+ # Access to configuration locations.
52
+ #
53
+ # XDG.config.each{ |dir| ... }
54
+ #
55
+ def config(*glob_and_flags, &block)
56
+ if !glob_and_flags.empty? or block_given?
57
+ Config.select(*glob_and_flags, &block)
58
+ else
59
+ Config
66
60
  end
67
- dirs.collect{ |d| File.expand_path(d) }
68
61
  end
69
62
 
70
- # Location of user's personal cache directory.
71
- def cache_home
72
- File.expand_path(
73
- ENV['XDG_CACHE_HOME'] || File.join(home, '.cache')
74
- )
75
- end
76
-
77
- # Find a file or directory in data dirs.
63
+ # Access to cache locations.
78
64
  #
79
- # See: +data_select+.
65
+ # XDG.cache.each{ |dir| ... }
80
66
  #
81
- def data_find(*glob_and_flags, &block)
82
- data_select(*glob_and_flags, &block).first
67
+ def cache(*glob_and_flags, &block)
68
+ if !glob_and_flags.empty? or block_given?
69
+ Cache.select(*glob_and_flags, &block)
70
+ else
71
+ Cache
72
+ end
83
73
  end
84
74
 
85
- # Return array of matching files or directories
86
- # in any of the data locations.
75
+ # Each directory set shares these common methods.
87
76
  #
88
- # This starts with the user's home directory
89
- # and then searches system directories.
90
- #
91
- # String parameters are joined into a pathname
92
- # while Integers and Symbols treated as flags.
93
- #
94
- # For example, the following are equivalent:
95
- #
96
- # XDG.data_select('stick/units', File::FNM_CASEFOLD)
97
- #
98
- # XDG.data_select('stick', 'uits', :casefold)
99
- #
100
- def data_select(*glob_and_flags, &block)
101
- glob, flags = *glob_and_flags.partition{ |e| String===e }
102
- glob = ['**/*'] if glob.empty?
103
- flag = flags.inject(0) do |m, f|
104
- if Symbol === f
105
- m + File::const_get("FNM_#{f.to_s.upcase}")
106
- else
107
- m + f.to_i
108
- end
77
+ module Common
78
+
79
+ # Returns a complete list of directories, starting
80
+ # with the home location and moving outward.
81
+ def list
82
+ [home, *dirs]
109
83
  end
110
- find = []
111
- [data_home, *data_dirs].each do |dir|
112
- path = File.join(dir, *glob)
113
- if block_given?
114
- find.concat(Dir.glob(path, flag).select(&block))
115
- else
116
- find.concat(Dir.glob(path, flag))
84
+
85
+ # Return array of matching files or directories
86
+ # in any of the resource locations, starting with
87
+ # the home directory and searching outward into
88
+ # system directories.
89
+ #
90
+ # Unlike #select, this doesn't take a block and each
91
+ # additional glob argument is treated as a logical-or.
92
+ #
93
+ # XDG::Data.glob("stick/*.rb", "stick/*.yaml")
94
+ #
95
+ def glob(*glob_and_flags)
96
+ glob, flags = *parse_arguments(*glob_and_flags)
97
+ find = []
98
+ list.each do |dir|
99
+ glob.each do |pattern|
100
+ find.concat(Dir.glob(File.join(dir, pattern), flags))
101
+ end
117
102
  end
103
+ find.uniq
118
104
  end
119
- find
120
- end
121
105
 
122
- # Return the fist matching file or directory
123
- # from the config locations.
124
- #
125
- # See: +config_select+.
126
- #
127
- def config_find(*glob_and_flags, &block)
128
- config_select(*glob_and_flags, &block).first
129
- end
106
+ # Return array of matching files or directories
107
+ # in any of the resource locations, starting with
108
+ # the home directory and searching outward into
109
+ # system directories.
110
+ #
111
+ # String parameters are joined into a pathname
112
+ # while Integers and Symbols treated as flags.
113
+ #
114
+ # For example, the following are equivalent:
115
+ #
116
+ # XDG.data.select('stick/units', File::FNM_CASEFOLD)
117
+ #
118
+ # XDG.data.select('stick', 'units', :casefold)
119
+ #
120
+ def select(*glob_and_flags, &block)
121
+ glob, flag = *parse_arguments(*glob_and_flags)
122
+ find = []
123
+ list.each do |dir|
124
+ path = File.join(dir, *glob)
125
+ hits = Dir.glob(path, flag)
126
+ hits = hits.select(&block) if block_given?
127
+ find.concat(hits)
128
+ end
129
+ find.uniq
130
+ end
130
131
 
131
- # Return array of matching files or directories
132
- # in any of the config locations.
133
- #
134
- # This starts with the user's home directory
135
- # and then searches system directories.
136
- #
137
- # String parameters are joined into a pathname
138
- # while Integers and Symbols treated as flags.
139
- #
140
- # For example, the following are equivalent:
141
- #
142
- # XDG.config_select('sow/plugins', File::FNM_CASEFOLD)
143
- #
144
- # XDG.config_select('sow', 'plugins', :casefold)
145
- #
146
- def config_select(*glob_and_flags)
147
- glob, flags = *glob_and_flags.partition{ |e| String===e }
148
- glob = ['**/*'] if glob.empty?
149
- flag = flags.inject(0) do |m, f|
150
- if Symbol === f
151
- m + File::const_get("FNM_#{f.to_s.upcase}")
152
- else
153
- m + f.to_i
132
+ # Find a file or directory. This works just like #select
133
+ # except that it returns the first match found.
134
+ #
135
+ # TODO: It would be more efficient to traverse the dirs and use #fnmatch.
136
+ #
137
+ def find(*glob_and_flags, &block)
138
+ glob, flag = *parse_arguments(*glob_and_flags)
139
+ find = nil
140
+ list.each do |dir|
141
+ path = File.join(dir, *glob)
142
+ hits = Dir.glob(path, flag)
143
+ hits = hits.select(&block) if block_given?
144
+ find = hits.first
145
+ break if find
154
146
  end
147
+ find
155
148
  end
156
- find = []
157
- [config_home, *config_dirs].each do |dir|
158
- path = File.join(dir, *glob)
159
- if block_given?
160
- find.concat(Dir.glob(path, flag).select(&block))
161
- else
162
- find.concat(Dir.glob(path, flag))
149
+
150
+ private
151
+
152
+ def parse_arguments(*glob_and_flags)
153
+ glob, flags = *glob_and_flags.partition{ |e| String===e }
154
+ glob = ['**/*'] if glob.empty?
155
+ flag = flags.inject(0) do |m, f|
156
+ if Symbol === f
157
+ m + File::const_get("FNM_#{f.to_s.upcase}")
158
+ else
159
+ m + f.to_i
160
+ end
163
161
  end
162
+ return glob, flag
164
163
  end
165
- find
164
+
166
165
  end
167
166
 
168
- # Return the fist matching file or directory
169
- # in the cache directory.
170
- #
171
- # See: +cache_select+.
167
+ # = DATA LOCATIONS
172
168
  #
173
- def cache_find(*glob_and_flags, &block)
174
- cache_select(*glob_and_flags, &block).first
169
+ module Data
170
+ include Common
171
+
172
+ # Location of personal data directory.
173
+ def home
174
+ @home ||= (
175
+ File.expand_path(
176
+ ENV['XDG_DATA_HOME'] || File.join(XDG.home, '.local', 'share')
177
+ )
178
+ )
179
+ end
180
+
181
+ # List of shared data directores.
182
+ def dirs
183
+ @dirs ||= (
184
+ dirs = ENV['XDG_DATA_DIRS'].split(/[:;]/)
185
+ if dirs.empty?
186
+ #dirs = [ Config::CONFIG['localdatadir'], Config::CONFIG['datadir'] ]
187
+ dirs = Resource.dirs.map{ |d| File.join(d, 'share') }
188
+ end
189
+ dirs = dirs.map{ |d| File.expand_path(d) }.uniq
190
+ dirs = dirs.select{ |d| File.directory?(d) }
191
+ dirs
192
+ )
193
+ end
194
+
195
+ extend self
175
196
  end
176
197
 
177
- # Return array of matching files or directories
178
- # from the cache directory.
198
+ # = CONFIGUTATION LOCATIONS
179
199
  #
180
- # String parameters are joined into a pathname
181
- # while Integers and Symbols treated as flags.
182
- #
183
- # For example, the following are equivalent:
184
- #
185
- # XDG.cache_select('sow/tmp', File::FNM_CASEFOLD)
186
- #
187
- # XDG.cache_select('sow', 'tmp', :casefold)
188
- #
189
- def cache_select(*glob_and_flags)
190
- glob, flags = *glob_and_flags.partition{ |e| String===e }
191
- glob = ['**/*'] if glob.empty?
192
- flag = flags.inject(0) do |m, f|
193
- if Symbol === f
194
- m + File::const_get("FNM_#{f.to_s.upcase}")
195
- else
196
- m + f.to_i
197
- end
200
+ module Config
201
+ include Common
202
+ extend self
203
+
204
+ # Location of personal config directory.
205
+ def home
206
+ @home ||= (
207
+ File.expand_path(
208
+ ENV['XDG_CONFIG_HOME'] || File.join(XDG.home, '.config')
209
+ )
210
+ )
198
211
  end
199
- path = File.join(cache_home,*glob)
200
- if block_given?
201
- Dir.glob(path, flag).select(&block)
202
- else
203
- Dir.glob(path, flag)
212
+
213
+ # List of shared config directories.
214
+ def dirs
215
+ @dirs ||= (
216
+ dirs = ENV['XDG_CONFIG_DIRS'].to_s.split(/[:;]/)
217
+ if dirs.empty?
218
+ #dirs = ['etc/xdg', 'etc']
219
+ sysconfdir = ::Config::CONFIG['sysconfdir']
220
+ dirs = [ File.join(sysconfdir, 'xdg'), sysconfdir ]
221
+ end
222
+ dirs = dirs.map{ |d| File.expand_path(d) }.uniq
223
+ dirs = dirs.select{ |d| File.directory?(d) }
224
+ dirs
225
+ )
204
226
  end
227
+
228
+ extend self
205
229
  end
206
230
 
207
- #--
208
- # The following are not strictly XDG spec,
209
- # but are useful in an analogous respect.
210
- #++
231
+ # = CACHE LOCATIONS
232
+ #
233
+ module Cache
234
+ include Common
211
235
 
212
- # Location of working config directory.
213
- def config_work
214
- File.expand_path(
215
- File.join(Dir.pwd, '.config')
216
- )
217
- end
236
+ # Location of user's personal cache directory.
237
+ def home
238
+ @home ||= (
239
+ File.expand_path(
240
+ ENV['XDG_CACHE_HOME'] || File.join(XDG.home, '.cache')
241
+ )
242
+ )
243
+ end
244
+
245
+ # Serves as a no-op, since there are no common cache directories
246
+ # defined by the XDG standard. (Though one might argue that
247
+ # <tt>tmp/</tt> is one.)
248
+ def dirs
249
+ @dirs ||= []
250
+ end
218
251
 
219
- # DEPRECATED -- Does not make sense to have this.
220
- # Location of working data directory.
221
- #def data_work
222
- # File.expand_path(
223
- # File.join(Dir.pwd, '.local')
224
- # )
225
- #end
226
-
227
- # Location of working cache directory.
228
- def cache_work
229
- File.expand_path(
230
- File.join(Dir.pwd, '.cache')
231
- )
252
+ extend self
232
253
  end
233
254
 
234
255
  end # module XDG
235
256
 
236
- # Copyright (c)2008 Tiger Ops / Trans
237
- # Distributed under the terms of the GPL v3.
257
+ # Copyright (c) 2008,2009 Thomas Sawyer
258
+ # Distributed under the terms of the LGPL v3.