Merge lp:~mew/charm-helpers/document-core into lp:charm-helpers
- document-core
- Merge into devel
Proposed by
Matthew Wedgwood
Status: | Merged |
---|---|
Merged at revision: | 85 |
Proposed branch: | lp:~mew/charm-helpers/document-core |
Merge into: | lp:charm-helpers |
Diff against target: |
396 lines (+68/-32) 2 files modified
charmhelpers/core/hookenv.py (+53/-23) charmhelpers/core/host.py (+15/-9) |
To merge this branch: | bzr merge lp:~mew/charm-helpers/document-core |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
James Page | Approve | ||
Review via email:
|
Commit message
Description of the change
Add or clean up docstrings for all core functions.
To post a comment you must log in.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Nicola Larosa (teknico) wrote : | # |
- 80. By Matthew Wedgwood
-
Standardize docstring quoting in core
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Matthew Wedgwood (mew) wrote : | # |
I've fixed the docstring quoting in the core modules.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
James Page (james-page) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'charmhelpers/core/hookenv.py' | |||
2 | --- charmhelpers/core/hookenv.py 2013-07-18 16:13:49 +0000 | |||
3 | +++ charmhelpers/core/hookenv.py 2013-09-26 14:36:53 +0000 | |||
4 | @@ -21,7 +21,7 @@ | |||
5 | 21 | 21 | ||
6 | 22 | 22 | ||
7 | 23 | def cached(func): | 23 | def cached(func): |
9 | 24 | ''' Cache return values for multiple executions of func + args | 24 | """Cache return values for multiple executions of func + args |
10 | 25 | 25 | ||
11 | 26 | For example: | 26 | For example: |
12 | 27 | 27 | ||
13 | @@ -32,7 +32,7 @@ | |||
14 | 32 | unit_get('test') | 32 | unit_get('test') |
15 | 33 | 33 | ||
16 | 34 | will cache the result of unit_get + 'test' for future calls. | 34 | will cache the result of unit_get + 'test' for future calls. |
18 | 35 | ''' | 35 | """ |
19 | 36 | def wrapper(*args, **kwargs): | 36 | def wrapper(*args, **kwargs): |
20 | 37 | global cache | 37 | global cache |
21 | 38 | key = str((func, args, kwargs)) | 38 | key = str((func, args, kwargs)) |
22 | @@ -46,8 +46,8 @@ | |||
23 | 46 | 46 | ||
24 | 47 | 47 | ||
25 | 48 | def flush(key): | 48 | def flush(key): |
28 | 49 | ''' Flushes any entries from function cache where the | 49 | """Flushes any entries from function cache where the |
29 | 50 | key is found in the function+args ''' | 50 | key is found in the function+args """ |
30 | 51 | flush_list = [] | 51 | flush_list = [] |
31 | 52 | for item in cache: | 52 | for item in cache: |
32 | 53 | if key in item: | 53 | if key in item: |
33 | @@ -57,7 +57,7 @@ | |||
34 | 57 | 57 | ||
35 | 58 | 58 | ||
36 | 59 | def log(message, level=None): | 59 | def log(message, level=None): |
38 | 60 | "Write a message to the juju log" | 60 | """Write a message to the juju log""" |
39 | 61 | command = ['juju-log'] | 61 | command = ['juju-log'] |
40 | 62 | if level: | 62 | if level: |
41 | 63 | command += ['-l', level] | 63 | command += ['-l', level] |
42 | @@ -66,7 +66,7 @@ | |||
43 | 66 | 66 | ||
44 | 67 | 67 | ||
45 | 68 | class Serializable(UserDict.IterableUserDict): | 68 | class Serializable(UserDict.IterableUserDict): |
47 | 69 | "Wrapper, an object that can be serialized to yaml or json" | 69 | """Wrapper, an object that can be serialized to yaml or json""" |
48 | 70 | 70 | ||
49 | 71 | def __init__(self, obj): | 71 | def __init__(self, obj): |
50 | 72 | # wrap the object | 72 | # wrap the object |
51 | @@ -96,11 +96,11 @@ | |||
52 | 96 | self.data = state | 96 | self.data = state |
53 | 97 | 97 | ||
54 | 98 | def json(self): | 98 | def json(self): |
56 | 99 | "Serialize the object to json" | 99 | """Serialize the object to json""" |
57 | 100 | return json.dumps(self.data) | 100 | return json.dumps(self.data) |
58 | 101 | 101 | ||
59 | 102 | def yaml(self): | 102 | def yaml(self): |
61 | 103 | "Serialize the object to yaml" | 103 | """Serialize the object to yaml""" |
62 | 104 | return yaml.dump(self.data) | 104 | return yaml.dump(self.data) |
63 | 105 | 105 | ||
64 | 106 | 106 | ||
65 | @@ -119,38 +119,38 @@ | |||
66 | 119 | 119 | ||
67 | 120 | 120 | ||
68 | 121 | def in_relation_hook(): | 121 | def in_relation_hook(): |
70 | 122 | "Determine whether we're running in a relation hook" | 122 | """Determine whether we're running in a relation hook""" |
71 | 123 | return 'JUJU_RELATION' in os.environ | 123 | return 'JUJU_RELATION' in os.environ |
72 | 124 | 124 | ||
73 | 125 | 125 | ||
74 | 126 | def relation_type(): | 126 | def relation_type(): |
76 | 127 | "The scope for the current relation hook" | 127 | """The scope for the current relation hook""" |
77 | 128 | return os.environ.get('JUJU_RELATION', None) | 128 | return os.environ.get('JUJU_RELATION', None) |
78 | 129 | 129 | ||
79 | 130 | 130 | ||
80 | 131 | def relation_id(): | 131 | def relation_id(): |
82 | 132 | "The relation ID for the current relation hook" | 132 | """The relation ID for the current relation hook""" |
83 | 133 | return os.environ.get('JUJU_RELATION_ID', None) | 133 | return os.environ.get('JUJU_RELATION_ID', None) |
84 | 134 | 134 | ||
85 | 135 | 135 | ||
86 | 136 | def local_unit(): | 136 | def local_unit(): |
88 | 137 | "Local unit ID" | 137 | """Local unit ID""" |
89 | 138 | return os.environ['JUJU_UNIT_NAME'] | 138 | return os.environ['JUJU_UNIT_NAME'] |
90 | 139 | 139 | ||
91 | 140 | 140 | ||
92 | 141 | def remote_unit(): | 141 | def remote_unit(): |
94 | 142 | "The remote unit for the current relation hook" | 142 | """The remote unit for the current relation hook""" |
95 | 143 | return os.environ['JUJU_REMOTE_UNIT'] | 143 | return os.environ['JUJU_REMOTE_UNIT'] |
96 | 144 | 144 | ||
97 | 145 | 145 | ||
98 | 146 | def service_name(): | 146 | def service_name(): |
100 | 147 | "The name service group this unit belongs to" | 147 | """The name service group this unit belongs to""" |
101 | 148 | return local_unit().split('/')[0] | 148 | return local_unit().split('/')[0] |
102 | 149 | 149 | ||
103 | 150 | 150 | ||
104 | 151 | @cached | 151 | @cached |
105 | 152 | def config(scope=None): | 152 | def config(scope=None): |
107 | 153 | "Juju charm configuration" | 153 | """Juju charm configuration""" |
108 | 154 | config_cmd_line = ['config-get'] | 154 | config_cmd_line = ['config-get'] |
109 | 155 | if scope is not None: | 155 | if scope is not None: |
110 | 156 | config_cmd_line.append(scope) | 156 | config_cmd_line.append(scope) |
111 | @@ -163,6 +163,7 @@ | |||
112 | 163 | 163 | ||
113 | 164 | @cached | 164 | @cached |
114 | 165 | def relation_get(attribute=None, unit=None, rid=None): | 165 | def relation_get(attribute=None, unit=None, rid=None): |
115 | 166 | """Get relation information""" | ||
116 | 166 | _args = ['relation-get', '--format=json'] | 167 | _args = ['relation-get', '--format=json'] |
117 | 167 | if rid: | 168 | if rid: |
118 | 168 | _args.append('-r') | 169 | _args.append('-r') |
119 | @@ -177,6 +178,7 @@ | |||
120 | 177 | 178 | ||
121 | 178 | 179 | ||
122 | 179 | def relation_set(relation_id=None, relation_settings={}, **kwargs): | 180 | def relation_set(relation_id=None, relation_settings={}, **kwargs): |
123 | 181 | """Set relation information for the current unit""" | ||
124 | 180 | relation_cmd_line = ['relation-set'] | 182 | relation_cmd_line = ['relation-set'] |
125 | 181 | if relation_id is not None: | 183 | if relation_id is not None: |
126 | 182 | relation_cmd_line.extend(('-r', relation_id)) | 184 | relation_cmd_line.extend(('-r', relation_id)) |
127 | @@ -192,7 +194,7 @@ | |||
128 | 192 | 194 | ||
129 | 193 | @cached | 195 | @cached |
130 | 194 | def relation_ids(reltype=None): | 196 | def relation_ids(reltype=None): |
132 | 195 | "A list of relation_ids" | 197 | """A list of relation_ids""" |
133 | 196 | reltype = reltype or relation_type() | 198 | reltype = reltype or relation_type() |
134 | 197 | relid_cmd_line = ['relation-ids', '--format=json'] | 199 | relid_cmd_line = ['relation-ids', '--format=json'] |
135 | 198 | if reltype is not None: | 200 | if reltype is not None: |
136 | @@ -203,7 +205,7 @@ | |||
137 | 203 | 205 | ||
138 | 204 | @cached | 206 | @cached |
139 | 205 | def related_units(relid=None): | 207 | def related_units(relid=None): |
141 | 206 | "A list of related units" | 208 | """A list of related units""" |
142 | 207 | relid = relid or relation_id() | 209 | relid = relid or relation_id() |
143 | 208 | units_cmd_line = ['relation-list', '--format=json'] | 210 | units_cmd_line = ['relation-list', '--format=json'] |
144 | 209 | if relid is not None: | 211 | if relid is not None: |
145 | @@ -213,7 +215,7 @@ | |||
146 | 213 | 215 | ||
147 | 214 | @cached | 216 | @cached |
148 | 215 | def relation_for_unit(unit=None, rid=None): | 217 | def relation_for_unit(unit=None, rid=None): |
150 | 216 | "Get the json represenation of a unit's relation" | 218 | """Get the json represenation of a unit's relation""" |
151 | 217 | unit = unit or remote_unit() | 219 | unit = unit or remote_unit() |
152 | 218 | relation = relation_get(unit=unit, rid=rid) | 220 | relation = relation_get(unit=unit, rid=rid) |
153 | 219 | for key in relation: | 221 | for key in relation: |
154 | @@ -225,7 +227,7 @@ | |||
155 | 225 | 227 | ||
156 | 226 | @cached | 228 | @cached |
157 | 227 | def relations_for_id(relid=None): | 229 | def relations_for_id(relid=None): |
159 | 228 | "Get relations of a specific relation ID" | 230 | """Get relations of a specific relation ID""" |
160 | 229 | relation_data = [] | 231 | relation_data = [] |
161 | 230 | relid = relid or relation_ids() | 232 | relid = relid or relation_ids() |
162 | 231 | for unit in related_units(relid): | 233 | for unit in related_units(relid): |
163 | @@ -237,7 +239,7 @@ | |||
164 | 237 | 239 | ||
165 | 238 | @cached | 240 | @cached |
166 | 239 | def relations_of_type(reltype=None): | 241 | def relations_of_type(reltype=None): |
168 | 240 | "Get relations of a specific type" | 242 | """Get relations of a specific type""" |
169 | 241 | relation_data = [] | 243 | relation_data = [] |
170 | 242 | reltype = reltype or relation_type() | 244 | reltype = reltype or relation_type() |
171 | 243 | for relid in relation_ids(reltype): | 245 | for relid in relation_ids(reltype): |
172 | @@ -249,7 +251,7 @@ | |||
173 | 249 | 251 | ||
174 | 250 | @cached | 252 | @cached |
175 | 251 | def relation_types(): | 253 | def relation_types(): |
177 | 252 | "Get a list of relation types supported by this charm" | 254 | """Get a list of relation types supported by this charm""" |
178 | 253 | charmdir = os.environ.get('CHARM_DIR', '') | 255 | charmdir = os.environ.get('CHARM_DIR', '') |
179 | 254 | mdf = open(os.path.join(charmdir, 'metadata.yaml')) | 256 | mdf = open(os.path.join(charmdir, 'metadata.yaml')) |
180 | 255 | md = yaml.safe_load(mdf) | 257 | md = yaml.safe_load(mdf) |
181 | @@ -264,6 +266,7 @@ | |||
182 | 264 | 266 | ||
183 | 265 | @cached | 267 | @cached |
184 | 266 | def relations(): | 268 | def relations(): |
185 | 269 | """Get a nested dictionary of relation data for all related units""" | ||
186 | 267 | rels = {} | 270 | rels = {} |
187 | 268 | for reltype in relation_types(): | 271 | for reltype in relation_types(): |
188 | 269 | relids = {} | 272 | relids = {} |
189 | @@ -278,14 +281,14 @@ | |||
190 | 278 | 281 | ||
191 | 279 | 282 | ||
192 | 280 | def open_port(port, protocol="TCP"): | 283 | def open_port(port, protocol="TCP"): |
194 | 281 | "Open a service network port" | 284 | """Open a service network port""" |
195 | 282 | _args = ['open-port'] | 285 | _args = ['open-port'] |
196 | 283 | _args.append('{}/{}'.format(port, protocol)) | 286 | _args.append('{}/{}'.format(port, protocol)) |
197 | 284 | subprocess.check_call(_args) | 287 | subprocess.check_call(_args) |
198 | 285 | 288 | ||
199 | 286 | 289 | ||
200 | 287 | def close_port(port, protocol="TCP"): | 290 | def close_port(port, protocol="TCP"): |
202 | 288 | "Close a service network port" | 291 | """Close a service network port""" |
203 | 289 | _args = ['close-port'] | 292 | _args = ['close-port'] |
204 | 290 | _args.append('{}/{}'.format(port, protocol)) | 293 | _args.append('{}/{}'.format(port, protocol)) |
205 | 291 | subprocess.check_call(_args) | 294 | subprocess.check_call(_args) |
206 | @@ -293,6 +296,7 @@ | |||
207 | 293 | 296 | ||
208 | 294 | @cached | 297 | @cached |
209 | 295 | def unit_get(attribute): | 298 | def unit_get(attribute): |
210 | 299 | """Get the unit ID for the remote unit""" | ||
211 | 296 | _args = ['unit-get', '--format=json', attribute] | 300 | _args = ['unit-get', '--format=json', attribute] |
212 | 297 | try: | 301 | try: |
213 | 298 | return json.loads(subprocess.check_output(_args)) | 302 | return json.loads(subprocess.check_output(_args)) |
214 | @@ -301,22 +305,46 @@ | |||
215 | 301 | 305 | ||
216 | 302 | 306 | ||
217 | 303 | def unit_private_ip(): | 307 | def unit_private_ip(): |
218 | 308 | """Get this unit's private IP address""" | ||
219 | 304 | return unit_get('private-address') | 309 | return unit_get('private-address') |
220 | 305 | 310 | ||
221 | 306 | 311 | ||
222 | 307 | class UnregisteredHookError(Exception): | 312 | class UnregisteredHookError(Exception): |
223 | 313 | """Raised when an undefined hook is called""" | ||
224 | 308 | pass | 314 | pass |
225 | 309 | 315 | ||
226 | 310 | 316 | ||
227 | 311 | class Hooks(object): | 317 | class Hooks(object): |
228 | 318 | """A convenient handler for hook functions. | ||
229 | 319 | |||
230 | 320 | Example: | ||
231 | 321 | hooks = Hooks() | ||
232 | 322 | |||
233 | 323 | # register a hook, taking its name from the function name | ||
234 | 324 | @hooks.hook() | ||
235 | 325 | def install(): | ||
236 | 326 | ... | ||
237 | 327 | |||
238 | 328 | # register a hook, providing a custom hook name | ||
239 | 329 | @hooks.hook("config-changed") | ||
240 | 330 | def config_changed(): | ||
241 | 331 | ... | ||
242 | 332 | |||
243 | 333 | if __name__ == "__main__": | ||
244 | 334 | # execute a hook based on the name the program is called by | ||
245 | 335 | hooks.execute(sys.argv) | ||
246 | 336 | """ | ||
247 | 337 | |||
248 | 312 | def __init__(self): | 338 | def __init__(self): |
249 | 313 | super(Hooks, self).__init__() | 339 | super(Hooks, self).__init__() |
250 | 314 | self._hooks = {} | 340 | self._hooks = {} |
251 | 315 | 341 | ||
252 | 316 | def register(self, name, function): | 342 | def register(self, name, function): |
253 | 343 | """Register a hook""" | ||
254 | 317 | self._hooks[name] = function | 344 | self._hooks[name] = function |
255 | 318 | 345 | ||
256 | 319 | def execute(self, args): | 346 | def execute(self, args): |
257 | 347 | """Execute a registered hook based on args[0]""" | ||
258 | 320 | hook_name = os.path.basename(args[0]) | 348 | hook_name = os.path.basename(args[0]) |
259 | 321 | if hook_name in self._hooks: | 349 | if hook_name in self._hooks: |
260 | 322 | self._hooks[hook_name]() | 350 | self._hooks[hook_name]() |
261 | @@ -324,6 +352,7 @@ | |||
262 | 324 | raise UnregisteredHookError(hook_name) | 352 | raise UnregisteredHookError(hook_name) |
263 | 325 | 353 | ||
264 | 326 | def hook(self, *hook_names): | 354 | def hook(self, *hook_names): |
265 | 355 | """Decorator, registering them as hooks""" | ||
266 | 327 | def wrapper(decorated): | 356 | def wrapper(decorated): |
267 | 328 | for hook_name in hook_names: | 357 | for hook_name in hook_names: |
268 | 329 | self.register(hook_name, decorated) | 358 | self.register(hook_name, decorated) |
269 | @@ -337,4 +366,5 @@ | |||
270 | 337 | 366 | ||
271 | 338 | 367 | ||
272 | 339 | def charm_dir(): | 368 | def charm_dir(): |
273 | 369 | """Return the root directory of the current charm""" | ||
274 | 340 | return os.environ.get('CHARM_DIR') | 370 | return os.environ.get('CHARM_DIR') |
275 | 341 | 371 | ||
276 | === modified file 'charmhelpers/core/host.py' | |||
277 | --- charmhelpers/core/host.py 2013-08-23 16:42:43 +0000 | |||
278 | +++ charmhelpers/core/host.py 2013-09-26 14:36:53 +0000 | |||
279 | @@ -19,18 +19,22 @@ | |||
280 | 19 | 19 | ||
281 | 20 | 20 | ||
282 | 21 | def service_start(service_name): | 21 | def service_start(service_name): |
283 | 22 | """Start a system service""" | ||
284 | 22 | return service('start', service_name) | 23 | return service('start', service_name) |
285 | 23 | 24 | ||
286 | 24 | 25 | ||
287 | 25 | def service_stop(service_name): | 26 | def service_stop(service_name): |
288 | 27 | """Stop a system service""" | ||
289 | 26 | return service('stop', service_name) | 28 | return service('stop', service_name) |
290 | 27 | 29 | ||
291 | 28 | 30 | ||
292 | 29 | def service_restart(service_name): | 31 | def service_restart(service_name): |
293 | 32 | """Restart a system service""" | ||
294 | 30 | return service('restart', service_name) | 33 | return service('restart', service_name) |
295 | 31 | 34 | ||
296 | 32 | 35 | ||
297 | 33 | def service_reload(service_name, restart_on_failure=False): | 36 | def service_reload(service_name, restart_on_failure=False): |
298 | 37 | """Reload a system service, optionally falling back to restart if reload fails""" | ||
299 | 34 | service_result = service('reload', service_name) | 38 | service_result = service('reload', service_name) |
300 | 35 | if not service_result and restart_on_failure: | 39 | if not service_result and restart_on_failure: |
301 | 36 | service_result = service('restart', service_name) | 40 | service_result = service('restart', service_name) |
302 | @@ -38,11 +42,13 @@ | |||
303 | 38 | 42 | ||
304 | 39 | 43 | ||
305 | 40 | def service(action, service_name): | 44 | def service(action, service_name): |
306 | 45 | """Control a system service""" | ||
307 | 41 | cmd = ['service', service_name, action] | 46 | cmd = ['service', service_name, action] |
308 | 42 | return subprocess.call(cmd) == 0 | 47 | return subprocess.call(cmd) == 0 |
309 | 43 | 48 | ||
310 | 44 | 49 | ||
311 | 45 | def service_running(service): | 50 | def service_running(service): |
312 | 51 | """Determine whether a system service is running""" | ||
313 | 46 | try: | 52 | try: |
314 | 47 | output = subprocess.check_output(['service', service, 'status']) | 53 | output = subprocess.check_output(['service', service, 'status']) |
315 | 48 | except subprocess.CalledProcessError: | 54 | except subprocess.CalledProcessError: |
316 | @@ -55,7 +61,7 @@ | |||
317 | 55 | 61 | ||
318 | 56 | 62 | ||
319 | 57 | def adduser(username, password=None, shell='/bin/bash', system_user=False): | 63 | def adduser(username, password=None, shell='/bin/bash', system_user=False): |
321 | 58 | """Add a user""" | 64 | """Add a user to the system""" |
322 | 59 | try: | 65 | try: |
323 | 60 | user_info = pwd.getpwnam(username) | 66 | user_info = pwd.getpwnam(username) |
324 | 61 | log('user {0} already exists!'.format(username)) | 67 | log('user {0} already exists!'.format(username)) |
325 | @@ -138,7 +144,7 @@ | |||
326 | 138 | 144 | ||
327 | 139 | 145 | ||
328 | 140 | def mount(device, mountpoint, options=None, persist=False): | 146 | def mount(device, mountpoint, options=None, persist=False): |
330 | 141 | '''Mount a filesystem''' | 147 | """Mount a filesystem at a particular mountpoint""" |
331 | 142 | cmd_args = ['mount'] | 148 | cmd_args = ['mount'] |
332 | 143 | if options is not None: | 149 | if options is not None: |
333 | 144 | cmd_args.extend(['-o', options]) | 150 | cmd_args.extend(['-o', options]) |
334 | @@ -155,7 +161,7 @@ | |||
335 | 155 | 161 | ||
336 | 156 | 162 | ||
337 | 157 | def umount(mountpoint, persist=False): | 163 | def umount(mountpoint, persist=False): |
339 | 158 | '''Unmount a filesystem''' | 164 | """Unmount a filesystem""" |
340 | 159 | cmd_args = ['umount', mountpoint] | 165 | cmd_args = ['umount', mountpoint] |
341 | 160 | try: | 166 | try: |
342 | 161 | subprocess.check_output(cmd_args) | 167 | subprocess.check_output(cmd_args) |
343 | @@ -169,7 +175,7 @@ | |||
344 | 169 | 175 | ||
345 | 170 | 176 | ||
346 | 171 | def mounts(): | 177 | def mounts(): |
348 | 172 | '''List of all mounted volumes as [[mountpoint,device],[...]]''' | 178 | """Get a list of all mounted volumes as [[mountpoint,device],[...]]""" |
349 | 173 | with open('/proc/mounts') as f: | 179 | with open('/proc/mounts') as f: |
350 | 174 | # [['/mount/point','/dev/path'],[...]] | 180 | # [['/mount/point','/dev/path'],[...]] |
351 | 175 | system_mounts = [m[1::-1] for m in [l.strip().split() | 181 | system_mounts = [m[1::-1] for m in [l.strip().split() |
352 | @@ -178,7 +184,7 @@ | |||
353 | 178 | 184 | ||
354 | 179 | 185 | ||
355 | 180 | def file_hash(path): | 186 | def file_hash(path): |
357 | 181 | ''' Generate a md5 hash of the contents of 'path' or None if not found ''' | 187 | """Generate a md5 hash of the contents of 'path' or None if not found """ |
358 | 182 | if os.path.exists(path): | 188 | if os.path.exists(path): |
359 | 183 | h = hashlib.md5() | 189 | h = hashlib.md5() |
360 | 184 | with open(path, 'r') as source: | 190 | with open(path, 'r') as source: |
361 | @@ -189,7 +195,7 @@ | |||
362 | 189 | 195 | ||
363 | 190 | 196 | ||
364 | 191 | def restart_on_change(restart_map): | 197 | def restart_on_change(restart_map): |
366 | 192 | ''' Restart services based on configuration files changing | 198 | """Restart services based on configuration files changing |
367 | 193 | 199 | ||
368 | 194 | This function is used a decorator, for example | 200 | This function is used a decorator, for example |
369 | 195 | 201 | ||
370 | @@ -202,7 +208,7 @@ | |||
371 | 202 | In this example, the cinder-api and cinder-volume services | 208 | In this example, the cinder-api and cinder-volume services |
372 | 203 | would be restarted if /etc/ceph/ceph.conf is changed by the | 209 | would be restarted if /etc/ceph/ceph.conf is changed by the |
373 | 204 | ceph_client_changed function. | 210 | ceph_client_changed function. |
375 | 205 | ''' | 211 | """ |
376 | 206 | def wrap(f): | 212 | def wrap(f): |
377 | 207 | def wrapped_f(*args): | 213 | def wrapped_f(*args): |
378 | 208 | checksums = {} | 214 | checksums = {} |
379 | @@ -220,7 +226,7 @@ | |||
380 | 220 | 226 | ||
381 | 221 | 227 | ||
382 | 222 | def lsb_release(): | 228 | def lsb_release(): |
384 | 223 | '''Return /etc/lsb-release in a dict''' | 229 | """Return /etc/lsb-release in a dict""" |
385 | 224 | d = {} | 230 | d = {} |
386 | 225 | with open('/etc/lsb-release', 'r') as lsb: | 231 | with open('/etc/lsb-release', 'r') as lsb: |
387 | 226 | for l in lsb: | 232 | for l in lsb: |
388 | @@ -230,7 +236,7 @@ | |||
389 | 230 | 236 | ||
390 | 231 | 237 | ||
391 | 232 | def pwgen(length=None): | 238 | def pwgen(length=None): |
393 | 233 | '''Generate a random pasword.''' | 239 | """Generate a random pasword.""" |
394 | 234 | if length is None: | 240 | if length is None: |
395 | 235 | length = random.choice(range(35, 45)) | 241 | length = random.choice(range(35, 45)) |
396 | 236 | alphanumeric_chars = [ | 242 | alphanumeric_chars = [ |
Very much appreciated, thank you.
However, please be consistent in your choice of docstring delimiters. The convention is to always use triple double-quotes (""").
There's actually a whole guideline for docstrings alone <http:// www.python. org/dev/ peps/pep- 0257/>.
Inconsistency in this has no use that I know of.