-
Notifications
You must be signed in to change notification settings - Fork 54
/
path.txt
264 lines (211 loc) · 8.13 KB
/
path.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
=======
py.path
=======
**Note**: The 'py' library is in "maintenance mode" and so is not
recommended for new projects. Please check out
`pathlib <https://docs.python.org/3/library/pathlib.html>`_ or
`pathlib2 <https://pypi.python.org/pypi/pathlib2/>`_ for path
operations.
The 'py' lib provides a uniform high-level api to deal with filesystems
and filesystem-like interfaces: ``py.path``. It aims to offer a central
object to fs-like object trees (reading from and writing to files, adding
files/directories, examining the types and structure, etc.), and out-of-the-box
provides a number of implementations of this API.
py.path.local - local file system path
===============================================
.. _`local`:
basic interactive example
-------------------------------------
The first and most obvious of the implementations is a wrapper around a local
filesystem. It's just a bit nicer in usage than the regular Python APIs, and
of course all the functionality is bundled together rather than spread over a
number of modules.
.. sourcecode:: pycon
>>> import py
>>> temppath = py.path.local('py.path_documentation')
>>> foopath = temppath.join('foo') # get child 'foo' (lazily)
>>> foopath.check() # check if child 'foo' exists
False
>>> foopath.write('bar') # write some data to it
>>> foopath.check()
True
>>> foopath.read()
'bar'
>>> foofile = foopath.open() # return a 'real' file object
>>> foofile.read(1)
'b'
reference documentation
---------------------------------
.. autoclass:: py._path.local.LocalPath
:members:
:inherited-members:
``py.path.svnurl`` and ``py.path.svnwc``
==================================================
Two other ``py.path`` implementations that the py lib provides wrap the
popular `Subversion`_ revision control system: the first (called 'svnurl')
by interfacing with a remote server, the second by wrapping a local checkout.
Both allow you to access relatively advanced features such as metadata and
versioning, and both in a way more user-friendly manner than existing other
solutions.
Some example usage of ``py.path.svnurl``:
.. sourcecode:: pycon
.. >>> import py
.. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk')
>>> url = py.path.svnurl('http://codespeak.net/svn/py')
>>> info = url.info()
>>> info.kind
'dir'
>>> firstentry = url.log()[-1]
>>> import time
>>> time.strftime('%Y-%m-%d', time.gmtime(firstentry.date))
'2004-10-02'
Example usage of ``py.path.svnwc``:
.. sourcecode:: pycon
.. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk')
>>> temp = py.path.local('py.path_documentation')
>>> wc = py.path.svnwc(temp.join('svnwc'))
>>> wc.checkout('http://codespeak.net/svn/py/dist/py/path/local')
>>> wc.join('local.py').check()
True
.. _`Subversion`: http://subversion.tigris.org/
svn path related API reference
-----------------------------------------
.. autoclass:: py._path.svnwc.SvnWCCommandPath
:members:
:inherited-members:
.. autoclass:: py._path.svnurl.SvnCommandPath
:members:
:inherited-members:
.. autoclass:: py._path.svnwc.SvnAuth
:members:
:inherited-members:
Common vs. specific API, Examples
========================================
All Path objects support a common set of operations, suitable
for many use cases and allowing to transparently switch the
path object within an application (e.g. from "local" to "svnwc").
The common set includes functions such as `path.read()` to read all data
from a file, `path.write()` to write data, `path.listdir()` to get a list
of directory entries, `path.check()` to check if a node exists
and is of a particular type, `path.join()` to get
to a (grand)child, `path.visit()` to recursively walk through a node's
children, etc. Only things that are not common on 'normal' filesystems (yet),
such as handling metadata (e.g. the Subversion "properties") require
using specific APIs.
A quick 'cookbook' of small examples that will be useful 'in real life',
which also presents parts of the 'common' API, and shows some non-common
methods:
Searching `.txt` files
--------------------------------
Search for a particular string inside all files with a .txt extension in a
specific directory.
.. sourcecode:: pycon
>>> dirpath = temppath.ensure('testdir', dir=True)
>>> dirpath.join('textfile1.txt').write('foo bar baz')
>>> dirpath.join('textfile2.txt').write('frob bar spam eggs')
>>> subdir = dirpath.ensure('subdir', dir=True)
>>> subdir.join('textfile1.txt').write('foo baz')
>>> subdir.join('textfile2.txt').write('spam eggs spam foo bar spam')
>>> results = []
>>> for fpath in dirpath.visit('*.txt'):
... if 'bar' in fpath.read():
... results.append(fpath.basename)
>>> results.sort()
>>> results
['textfile1.txt', 'textfile2.txt', 'textfile2.txt']
Working with Paths
----------------------------
This example shows the ``py.path`` features to deal with
filesystem paths Note that the filesystem is never touched,
all operations are performed on a string level (so the paths
don't have to exist, either):
.. sourcecode:: pycon
>>> p1 = py.path.local('/foo/bar')
>>> p2 = p1.join('baz/qux')
>>> p2 == py.path.local('/foo/bar/baz/qux')
True
>>> sep = py.path.local.sep
>>> p2.relto(p1).replace(sep, '/') # os-specific path sep in the string
'baz/qux'
>>> p2.bestrelpath(p1).replace(sep, '/')
'../..'
>>> p2.join(p2.bestrelpath(p1)) == p1
True
>>> p3 = p1 / 'baz/qux' # the / operator allows joining, too
>>> p2 == p3
True
>>> p4 = p1 + ".py"
>>> p4.basename == "bar.py"
True
>>> p4.ext == ".py"
True
>>> p4.purebasename == "bar"
True
This should be possible on every implementation of ``py.path``, so
regardless of whether the implementation wraps a UNIX filesystem, a Windows
one, or a database or object tree, these functions should be available (each
with their own notion of path seperators and dealing with conversions, etc.).
Checking path types
-------------------------------
Now we will show a bit about the powerful 'check()' method on paths, which
allows you to check whether a file exists, what type it is, etc.:
.. sourcecode:: pycon
>>> file1 = temppath.join('file1')
>>> file1.check() # does it exist?
False
>>> file1 = file1.ensure(file=True) # 'touch' the file
>>> file1.check()
True
>>> file1.check(dir=True) # is it a dir?
False
>>> file1.check(file=True) # or a file?
True
>>> file1.check(ext='.txt') # check the extension
False
>>> textfile = temppath.ensure('text.txt', file=True)
>>> textfile.check(ext='.txt')
True
>>> file1.check(basename='file1') # we can use all the path's properties here
True
Setting svn-properties
--------------------------------
As an example of 'uncommon' methods, we'll show how to read and write
properties in an ``py.path.svnwc`` instance:
.. sourcecode:: pycon
.. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk')
>>> wc.propget('foo')
''
>>> wc.propset('foo', 'bar')
>>> wc.propget('foo')
'bar'
>>> len(wc.status().prop_modified) # our own props
1
>>> msg = wc.revert() # roll back our changes
>>> len(wc.status().prop_modified)
0
SVN authentication
----------------------------
Some uncommon functionality can also be provided as extensions, such as SVN
authentication:
.. sourcecode:: pycon
.. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk')
>>> auth = py.path.SvnAuth('anonymous', 'user', cache_auth=False,
... interactive=False)
>>> wc.auth = auth
>>> wc.update() # this should work
>>> path = wc.ensure('thisshouldnotexist.txt')
>>> try:
... path.commit('testing')
... except py.process.cmdexec.Error, e:
... pass
>>> 'authorization failed' in str(e)
True
Known problems / limitations
===================================
* The SVN path objects require the "svn" command line,
there is currently no support for python bindings.
Parsing the svn output can lead to problems, particularly
regarding if you have a non-english "locales" setting.
* While the path objects basically work on windows,
there is no attention yet on making unicode paths
work or deal with the famous "8.3" filename issues.