2020from fs .iotools import line_iterator
2121from fs .mode import Mode
2222from fs .path import dirname
23+ from cachetools import TTLCache
2324
2425
2526log = logging .getLogger (__name__ )
@@ -156,7 +157,8 @@ class WebDAVFS(FS):
156157 'virtual' : False ,
157158 }
158159
159- def __init__ (self , url , login = None , password = None , root = None ):
160+ def __init__ (self , url , login = None , password = None , root = None ,
161+ cache_maxsize = 10000 , cache_ttl = 60 ):
160162 self .url = url
161163 self .root = root
162164 super (WebDAVFS , self ).__init__ ()
@@ -167,6 +169,8 @@ def __init__(self, url, login=None, password=None, root=None):
167169 'webdav_password' : password ,
168170 'root' : self .root
169171 }
172+ self .info_cache = TTLCache (maxsize = cache_maxsize ,
173+ ttl = cache_ttl )
170174 self .client = wc .Client (options )
171175
172176 def _create_resource (self , path ):
@@ -182,7 +186,8 @@ def _create_info_dict(info):
182186 info_dict = {
183187 'basic' : {"is_dir" : False },
184188 'details' : {'type' : int (ResourceType .file )},
185- 'access' : {}
189+ 'access' : {},
190+ 'other' : {}
186191 }
187192
188193 if six .PY2 :
@@ -230,9 +235,8 @@ def exists(self, path):
230235
231236 def getinfo (self , path , namespaces = None ):
232237 _path = self .validatepath (path )
233- namespaces = namespaces or ()
234-
235238 if _path in '/' :
239+ < << << << Updated upstream
236240 info_dict = {
237241 "basic" : {
238242 "name" : "" ,
@@ -257,18 +261,51 @@ def getinfo(self, path, namespaces=None):
257261 raise errors .ResourceNotFound (path , exc = exc )
258262
259263 return Info (info_dict )
264+ == == == =
265+ self .info_cache .clear ()
266+ try :
267+ _path = self .validatepath (path )
268+ namespaces = namespaces or ()
269+ urn = wu .Urn (_path .encode ('utf-8' ))
270+ path = self .client .get_full_path (urn );
271+ if path in self .info_cache :
272+ info = self .info_cache [path ]
273+ response = None
274+ else :
275+ response = self .client .execute_request (action = 'info' ,
276+ path = urn .quote ())
277+ info = wc .WebDavXmlUtils .parse_info_response (content = response .content , path = path , hostname = self .client .webdav .hostname )
278+ if info ['name' ] is None :
279+ info ['name' ] = _path .split ("/" )[- 1 ]
280+ if wc .WebDavXmlUtils .parse_is_dir_response (content = response .content , path = path , hostname = self .client .webdav .hostname ):
281+ info ['isdir' ] = True
282+ info ['files' ] = []
283+ for i in wc .WebDavXmlUtils .parse_get_list_info_response (response .content ):
284+ if i ['path' ].rstrip ('/' ) != path .rstrip ('/' ):
285+ self .info_cache [i ['path' ]] = i
286+ filename = wu .Urn (i ['path' ], i ['isdir' ]).filename ()
287+ if six .PY2 :
288+ filename = filename .decode ('utf-8' )
289+ filename = filename .rstrip ('/' )
290+ info ['files' ].append (filename )
291+ self .info_cache [path ] = info
292+ info_dict = self ._create_info_dict (info )
293+ if info .get ('isdir' , False ):
294+ info_dict ['basic' ]['is_dir' ] = True
295+ info_dict ['details' ]['type' ] = ResourceType .directory
296+ except we .RemoteResourceNotFound as exc :
297+ raise errors .ResourceNotFound (path , exc = exc )
298+ retval = Info (info_dict )
299+ return retval
300+ >> >> >> > Stashed changes
260301
261302 def listdir (self , path ):
262- _path = self .validatepath (path )
263-
264- if not self .getinfo (_path ).is_dir :
303+ info = self .getinfo (path )
304+ if not info .is_dir :
265305 raise errors .DirectoryExpected (path )
266-
267- dir_list = self .client .list (_path .encode ('utf-8' ))
268- if six .PY2 :
269- dir_list = map (operator .methodcaller ('decode' , 'utf-8' ), dir_list )
270-
271- return list (map (operator .methodcaller ('rstrip' , '/' ), dir_list ))
306+ for i in info .raw ['other' ]['files' ]:
307+ yield i
308+ return
272309
273310 def makedir (self , path , permissions = None , recreate = False ):
274311 _path = self .validatepath (path )
0 commit comments