##// END OF EJS Templates
only check listdir on dirs...
MinRK -
Show More
@@ -1,135 +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 path can be listed
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):
106 try:
108 try:
107 os.listdir(abs_path)
109 os.listdir(abs_path)
108 except Exception:
110 except OSError:
109 return True
111 return True
110
112
111 # check UF_HIDDEN on any location up to root
113 # check UF_HIDDEN on any location up to root
112 path = abs_path
114 path = abs_path
113 while path and path.startswith(abs_root) and path != abs_root:
115 while path and path.startswith(abs_root) and path != abs_root:
114 try:
116 try:
115 # may fail on Windows junctions
117 # may fail on Windows junctions
116 st = os.stat(path)
118 st = os.stat(path)
117 except Exception:
119 except OSError:
118 return True
120 return True
119 if getattr(st, 'st_flags', 0) & UF_HIDDEN:
121 if getattr(st, 'st_flags', 0) & UF_HIDDEN:
120 return True
122 return True
121 path = os.path.dirname(path)
123 path = os.path.dirname(path)
122
124
123 return False
125 return False
124
126
125 def to_os_path(path, root=''):
127 def to_os_path(path, root=''):
126 """Convert an API path to a filesystem path
128 """Convert an API path to a filesystem path
127
129
128 If given, root will be prepended to the path.
130 If given, root will be prepended to the path.
129 root must be a filesystem path already.
131 root must be a filesystem path already.
130 """
132 """
131 parts = path.strip('/').split('/')
133 parts = path.strip('/').split('/')
132 parts = [p for p in parts if p != ''] # remove duplicate splits
134 parts = [p for p in parts if p != ''] # remove duplicate splits
133 path = os.path.join(root, *parts)
135 path = os.path.join(root, *parts)
134 return path
136 return path
135
137
General Comments 0
You need to be logged in to leave comments. Login now