##// END OF EJS Templates
Merge pull request #5390 from minrk/finish-5333...
Brian E. Granger -
r15906:7b9b9b23 merge
parent child Browse files
Show More
@@ -1,125 +1,137 b''
1 """Notebook related utilities
1 """Notebook related utilities
2
2
3 Authors:
3 Authors:
4
4
5 * Brian Granger
5 * Brian Granger
6 """
6 """
7
7
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2011 The IPython Development Team
9 # Copyright (C) 2011 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 from __future__ import print_function
15 from __future__ import print_function
16
16
17 import os
17 import os
18 import stat
18 import stat
19
19
20 try:
20 try:
21 from urllib.parse import quote, unquote
21 from urllib.parse import quote, unquote
22 except ImportError:
22 except ImportError:
23 from urllib import quote, unquote
23 from urllib import quote, unquote
24
24
25 from IPython.utils import py3compat
25 from IPython.utils import py3compat
26
26
27 # UF_HIDDEN is a stat flag not defined in the stat module.
27 # UF_HIDDEN is a stat flag not defined in the stat module.
28 # It is used by BSD to indicate hidden files.
28 # It is used by BSD to indicate hidden files.
29 UF_HIDDEN = getattr(stat, 'UF_HIDDEN', 32768)
29 UF_HIDDEN = getattr(stat, 'UF_HIDDEN', 32768)
30
30
31 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
32 # Imports
32 # Imports
33 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
34
34
35 def url_path_join(*pieces):
35 def url_path_join(*pieces):
36 """Join components of url into a relative url
36 """Join components of url into a relative url
37
37
38 Use to prevent double slash when joining subpath. This will leave the
38 Use to prevent double slash when joining subpath. This will leave the
39 initial and final / in place
39 initial and final / in place
40 """
40 """
41 initial = pieces[0].startswith('/')
41 initial = pieces[0].startswith('/')
42 final = pieces[-1].endswith('/')
42 final = pieces[-1].endswith('/')
43 stripped = [s.strip('/') for s in pieces]
43 stripped = [s.strip('/') for s in pieces]
44 result = '/'.join(s for s in stripped if s)
44 result = '/'.join(s for s in stripped if s)
45 if initial: result = '/' + result
45 if initial: result = '/' + result
46 if final: result = result + '/'
46 if final: result = result + '/'
47 if result == '//': result = '/'
47 if result == '//': result = '/'
48 return result
48 return result
49
49
50 def path2url(path):
50 def path2url(path):
51 """Convert a local file path to a URL"""
51 """Convert a local file path to a URL"""
52 pieces = [ quote(p) for p in path.split(os.sep) ]
52 pieces = [ quote(p) for p in path.split(os.sep) ]
53 # preserve trailing /
53 # preserve trailing /
54 if pieces[-1] == '':
54 if pieces[-1] == '':
55 pieces[-1] = '/'
55 pieces[-1] = '/'
56 url = url_path_join(*pieces)
56 url = url_path_join(*pieces)
57 return url
57 return url
58
58
59 def url2path(url):
59 def url2path(url):
60 """Convert a URL to a local file path"""
60 """Convert a URL to a local file path"""
61 pieces = [ unquote(p) for p in url.split('/') ]
61 pieces = [ unquote(p) for p in url.split('/') ]
62 path = os.path.join(*pieces)
62 path = os.path.join(*pieces)
63 return path
63 return path
64
64
65 def url_escape(path):
65 def url_escape(path):
66 """Escape special characters in a URL path
66 """Escape special characters in a URL path
67
67
68 Turns '/foo bar/' into '/foo%20bar/'
68 Turns '/foo bar/' into '/foo%20bar/'
69 """
69 """
70 parts = py3compat.unicode_to_str(path).split('/')
70 parts = py3compat.unicode_to_str(path).split('/')
71 return u'/'.join([quote(p) for p in parts])
71 return u'/'.join([quote(p) for p in parts])
72
72
73 def url_unescape(path):
73 def url_unescape(path):
74 """Unescape special characters in a URL path
74 """Unescape special characters in a URL path
75
75
76 Turns '/foo%20bar/' into '/foo bar/'
76 Turns '/foo%20bar/' into '/foo bar/'
77 """
77 """
78 return u'/'.join([
78 return u'/'.join([
79 py3compat.str_to_unicode(unquote(p))
79 py3compat.str_to_unicode(unquote(p))
80 for p in py3compat.unicode_to_str(path).split('/')
80 for p in py3compat.unicode_to_str(path).split('/')
81 ])
81 ])
82
82
83 def is_hidden(abs_path, abs_root=''):
83 def is_hidden(abs_path, abs_root=''):
84 """Is a file hidden or contained in a hidden directory?
84 """Is a file hidden or contained in a hidden directory?
85
85
86 This will start with the rightmost path element and work backwards to the
86 This will start with the rightmost path element and work backwards to the
87 given root to see if a path is hidden or in a hidden directory. Hidden is
87 given root to see if a path is hidden or in a hidden directory. Hidden is
88 determined by either name starting with '.' or the UF_HIDDEN flag as
88 determined by either name starting with '.' or the UF_HIDDEN flag as
89 reported by stat.
89 reported by stat.
90
90
91 Parameters
91 Parameters
92 ----------
92 ----------
93 abs_path : unicode
93 abs_path : unicode
94 The absolute path to check for hidden directories.
94 The absolute path to check for hidden directories.
95 abs_root : unicode
95 abs_root : unicode
96 The absolute path of the root directory in which hidden directories
96 The absolute path of the root directory in which hidden directories
97 should be checked for.
97 should be checked for.
98 """
98 """
99 if not abs_root:
99 if not abs_root:
100 abs_root = abs_path.split(os.sep, 1)[0] + os.sep
100 abs_root = abs_path.split(os.sep, 1)[0] + os.sep
101 inside_root = abs_path[len(abs_root):]
101 inside_root = abs_path[len(abs_root):]
102 if any(part.startswith('.') for part in inside_root.split(os.sep)):
102 if any(part.startswith('.') for part in inside_root.split(os.sep)):
103 return True
103 return True
104
104
105 # check that dirs can be listed
106 # may fail on Windows junctions or non-user-readable dirs
107 if os.path.isdir(abs_path):
108 try:
109 os.listdir(abs_path)
110 except OSError:
111 return True
112
105 # check UF_HIDDEN on any location up to root
113 # check UF_HIDDEN on any location up to root
106 path = abs_path
114 path = abs_path
107 while path and path.startswith(abs_root) and path != abs_root:
115 while path and path.startswith(abs_root) and path != abs_root:
108 st = os.stat(path)
116 try:
117 # may fail on Windows junctions
118 st = os.stat(path)
119 except OSError:
120 return True
109 if getattr(st, 'st_flags', 0) & UF_HIDDEN:
121 if getattr(st, 'st_flags', 0) & UF_HIDDEN:
110 return True
122 return True
111 path = os.path.dirname(path)
123 path = os.path.dirname(path)
112
124
113 return False
125 return False
114
126
115 def to_os_path(path, root=''):
127 def to_os_path(path, root=''):
116 """Convert an API path to a filesystem path
128 """Convert an API path to a filesystem path
117
129
118 If given, root will be prepended to the path.
130 If given, root will be prepended to the path.
119 root must be a filesystem path already.
131 root must be a filesystem path already.
120 """
132 """
121 parts = path.strip('/').split('/')
133 parts = path.strip('/').split('/')
122 parts = [p for p in parts if p != ''] # remove duplicate splits
134 parts = [p for p in parts if p != ''] # remove duplicate splits
123 path = os.path.join(root, *parts)
135 path = os.path.join(root, *parts)
124 return path
136 return path
125
137
General Comments 0
You need to be logged in to leave comments. Login now