aece2dd7830baecab9b1106f1a43fc9d08eb6969
[theonering] / src / util / io.py
1 #!/usr/bin/env python
2
3
4 from __future__ import with_statement
5
6 import os
7 import pickle
8 import contextlib
9 import itertools
10 import functools
11
12
13 @contextlib.contextmanager
14 def change_directory(directory):
15         previousDirectory = os.getcwd()
16         os.chdir(directory)
17         currentDirectory = os.getcwd()
18
19         try:
20                 yield previousDirectory, currentDirectory
21         finally:
22                 os.chdir(previousDirectory)
23
24
25 @contextlib.contextmanager
26 def pickled(filename):
27         """
28         Here is an example usage:
29         with pickled("foo.db") as p:
30                 p("users", list).append(["srid", "passwd", 23])
31         """
32
33         if os.path.isfile(filename):
34                 data = pickle.load(open(filename))
35         else:
36                 data = {}
37
38         def getter(item, factory):
39                 if item in data:
40                         return data[item]
41                 else:
42                         data[item] = factory()
43                         return data[item]
44
45         yield getter
46
47         pickle.dump(data, open(filename, "w"))
48
49
50 @contextlib.contextmanager
51 def redirect(object_, attr, value):
52         """
53         >>> import sys
54         ... with redirect(sys, 'stdout', open('stdout', 'w')):
55         ...     print "hello"
56         ...
57         >>> print "we're back"
58         we're back
59         """
60         orig = getattr(object_, attr)
61         setattr(object_, attr, value)
62         try:
63                 yield
64         finally:
65                 setattr(object_, attr, orig)
66
67
68 def pathsplit(path):
69         """
70         >>> pathsplit("/a/b/c")
71         ['', 'a', 'b', 'c']
72         >>> pathsplit("./plugins/builtins.ini")
73         ['.', 'plugins', 'builtins.ini']
74         """
75         pathParts = path.split(os.path.sep)
76         return pathParts
77
78
79 def commonpath(l1, l2, common=None):
80         """
81         >>> commonpath(pathsplit('/a/b/c/d'), pathsplit('/a/b/c1/d1'))
82         (['', 'a', 'b'], ['c', 'd'], ['c1', 'd1'])
83         >>> commonpath(pathsplit("./plugins/"), pathsplit("./plugins/builtins.ini"))
84         (['.', 'plugins'], [''], ['builtins.ini'])
85         >>> commonpath(pathsplit("./plugins/builtins"), pathsplit("./plugins"))
86         (['.', 'plugins'], ['builtins'], [])
87         """
88         if common is None:
89                 common = []
90
91         if l1 == l2:
92                 return l1, [], []
93
94         for i, (leftDir, rightDir) in enumerate(zip(l1, l2)):
95                 if leftDir != rightDir:
96                         return l1[0:i], l1[i:], l2[i:]
97         else:
98                 if leftDir == rightDir:
99                         i += 1
100                 return l1[0:i], l1[i:], l2[i:]
101
102
103 def relpath(p1, p2):
104         """
105         >>> relpath('/', '/')
106         './'
107         >>> relpath('/a/b/c/d', '/')
108         '../../../../'
109         >>> relpath('/a/b/c/d', '/a/b/c1/d1')
110         '../../c1/d1'
111         >>> relpath('/a/b/c/d', '/a/b/c1/d1/')
112         '../../c1/d1'
113         >>> relpath("./plugins/builtins", "./plugins")
114         '../'
115         >>> relpath("./plugins/", "./plugins/builtins.ini")
116         'builtins.ini'
117         """
118         sourcePath = os.path.normpath(p1)
119         destPath = os.path.normpath(p2)
120
121         (common, sourceOnly, destOnly) = commonpath(pathsplit(sourcePath), pathsplit(destPath))
122         if len(sourceOnly) or len(destOnly):
123                 relParts = itertools.chain(
124                         (('..' + os.sep) * len(sourceOnly), ),
125                         destOnly,
126                 )
127                 return os.path.join(*relParts)
128         else:
129                 return "."+os.sep