Prepare for objects that are also Collections
Don't force objects to have an id, especially since that id was incorrect. "plap/plop" would have the same id as "plop", i.e. "plop". We don't rely on the id for handling Collections anymore. Change to use more unique property names. Change the display, instead of using '*', we use '~', and there is no "Collection" header anymore. Updated formatters could use that way of showing the object is also a collection too. refs #774
This commit is contained in:
parent
f4dbefb6ef
commit
fae4470101
4 changed files with 61 additions and 48 deletions
|
|
@ -82,11 +82,11 @@ class CanalplusBrowser(BaseBrowser):
|
|||
|
||||
if len(split_path) == 0:
|
||||
for channel in channels:
|
||||
if channel.level == 1:
|
||||
if channel.path_level == 1:
|
||||
yield channel
|
||||
elif len(split_path) == 1:
|
||||
for channel in channels:
|
||||
if channel.level == 2 and split_path == channel.parent:
|
||||
if channel.path_level == 2 and split_path == channel.parent_path:
|
||||
yield channel
|
||||
elif len(split_path) == 2:
|
||||
subchannels = self.iter_resources(split_path[0:1])
|
||||
|
|
|
|||
|
|
@ -106,9 +106,9 @@ class RedmineBackend(BaseBackend, ICapContent, ICapBugTracker, ICapCollection):
|
|||
return self.iter_issues(query)
|
||||
|
||||
def validate_collection(self, objs, collection):
|
||||
if collection.level == 0:
|
||||
if collection.path_level == 0:
|
||||
return
|
||||
if Issue in objs and collection.level == 1:
|
||||
if Issue in objs and collection.path_level == 1:
|
||||
for project in self.iter_projects():
|
||||
if collection.basename == project.id:
|
||||
return Collection([project.id], project.name)
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
from .base import IBaseCap, CapBaseObject
|
||||
|
||||
__all__ = ['ICapCollection', 'Collection', 'CollectionNotFound']
|
||||
__all__ = ['ICapCollection', 'BaseCollection', 'Collection', 'CollectionNotFound']
|
||||
|
||||
|
||||
class CollectionNotFound(Exception):
|
||||
|
|
@ -31,39 +31,49 @@ class CollectionNotFound(Exception):
|
|||
Exception.__init__(self, msg)
|
||||
|
||||
|
||||
class Collection(CapBaseObject):
|
||||
class BaseCollection(CapBaseObject):
|
||||
"""
|
||||
Inherit from this if you want to create an object that is *also* a Collection.
|
||||
However, this probably will not work properly for now.
|
||||
"""
|
||||
def __init__(self, split_path):
|
||||
self.split_path = split_path
|
||||
|
||||
@property
|
||||
def basename(self):
|
||||
return self.split_path[-1] if self.path_level else None
|
||||
|
||||
@property
|
||||
def parent_path(self):
|
||||
return self.split_path[0:-1] if self.path_level else None
|
||||
|
||||
@property
|
||||
def path_level(self):
|
||||
return len(self.split_path)
|
||||
|
||||
|
||||
class Collection(BaseCollection):
|
||||
"""
|
||||
A Collection is a "fake" object returned in results, which shows you can get
|
||||
more results if you go into its path.
|
||||
|
||||
It is a dumb object, it must not contain callbacks to a backend.
|
||||
|
||||
Do not inherit from this class if you want to make a regular CapBaseObject
|
||||
a Collection, use BaseCollection instead.
|
||||
"""
|
||||
def __init__(self, split_path, title=None, backend=None):
|
||||
self.split_path = split_path
|
||||
def __init__(self, split_path, title=None):
|
||||
self.title = title
|
||||
_id = self.basename
|
||||
CapBaseObject.__init__(self, _id, backend)
|
||||
BaseCollection.__init__(self, split_path)
|
||||
|
||||
def __unicode__(self):
|
||||
if self.title and self.id:
|
||||
return u'%s (%s)' % (self.id, self.title)
|
||||
elif self.id:
|
||||
return u'%s' % self.id
|
||||
if self.title and self.basename:
|
||||
return u'%s (%s)' % (self.basename, self.title)
|
||||
elif self.basename:
|
||||
return u'%s' % self.basename
|
||||
else:
|
||||
return u'Unknown collection'
|
||||
|
||||
@property
|
||||
def basename(self):
|
||||
return self.split_path[-1] if self.level else None
|
||||
|
||||
@property
|
||||
def parent(self):
|
||||
return self.split_path[0:-1] if self.level else None
|
||||
|
||||
@property
|
||||
def level(self):
|
||||
return len(self.split_path)
|
||||
|
||||
|
||||
class ICapCollection(IBaseCap):
|
||||
def iter_resources_flat(self, objs, split_path, clean_only=False):
|
||||
|
|
@ -93,7 +103,7 @@ class ICapCollection(IBaseCap):
|
|||
If the path is invalid (i.e. can't be handled by this module),
|
||||
it should return None.
|
||||
"""
|
||||
collection = Collection(split_path, None, self.name)
|
||||
collection = Collection(split_path, None)
|
||||
return self.validate_collection(objs, collection) or collection
|
||||
|
||||
def validate_collection(self, objs, collection):
|
||||
|
|
@ -105,7 +115,7 @@ class ICapCollection(IBaseCap):
|
|||
You can replace the collection object entirely by returning a new one.
|
||||
"""
|
||||
# Root
|
||||
if collection.level == 0:
|
||||
if collection.path_level == 0:
|
||||
return
|
||||
try:
|
||||
i = self.iter_resources(objs, collection.split_path)
|
||||
|
|
@ -121,20 +131,20 @@ class ICapCollection(IBaseCap):
|
|||
def test():
|
||||
c = Collection([])
|
||||
assert c.basename is None
|
||||
assert c.parent is None
|
||||
assert c.level == 0
|
||||
assert c.parent_path is None
|
||||
assert c.path_level == 0
|
||||
|
||||
c = Collection([u'lol'])
|
||||
assert c.basename == u'lol'
|
||||
assert c.parent == []
|
||||
assert c.level == 1
|
||||
assert c.parent_path == []
|
||||
assert c.path_level == 1
|
||||
|
||||
c = Collection([u'lol', u'cat'])
|
||||
assert c.basename == u'cat'
|
||||
assert c.parent == [u'lol']
|
||||
assert c.level == 2
|
||||
assert c.parent_path == [u'lol']
|
||||
assert c.path_level == 2
|
||||
|
||||
c = Collection([u'w', u'e', u'e', u'b', u'o', u'o', u'b'])
|
||||
assert c.basename == u'b'
|
||||
assert c.parent == [u'w', u'e', u'e', u'b', u'o', u'o']
|
||||
assert c.level == 7
|
||||
assert c.parent_path == [u'w', u'e', u'e', u'b', u'o', u'o']
|
||||
assert c.path_level == 7
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ from weboob.tools.application.formatters.iformatter import MandatoryFieldsNotFou
|
|||
from weboob.tools.misc import to_unicode
|
||||
from weboob.tools.path import WorkingPath
|
||||
from weboob.tools.ordereddict import OrderedDict
|
||||
from weboob.capabilities.collection import Collection, ICapCollection, CollectionNotFound
|
||||
from weboob.capabilities.collection import Collection, BaseCollection, ICapCollection, CollectionNotFound
|
||||
|
||||
from .console import BackendNotGiven, ConsoleApplication
|
||||
from .formatters.load import FormattersLoader, FormatterLoadError
|
||||
|
|
@ -864,19 +864,13 @@ class ReplApplication(Cmd, ConsoleApplication):
|
|||
print obj
|
||||
|
||||
if self.collections:
|
||||
print
|
||||
print 'Collections:'
|
||||
for collection in self.collections:
|
||||
if collection.basename and collection.title:
|
||||
print u'%s* (%s) %s (%s)%s' % \
|
||||
print u'%s~ (%s) %s (%s)%s' % \
|
||||
(self.BOLD, collection.basename, collection.title, collection.backend, self.NC)
|
||||
elif collection.basename:
|
||||
print u'%s* (%s) (%s)%s' % \
|
||||
(self.BOLD, collection.basename, collection.backend, self.NC)
|
||||
else:
|
||||
print collection
|
||||
|
||||
self.flush()
|
||||
print u'%s~ (%s) (%s)%s' % \
|
||||
(self.BOLD, collection.basename, collection.backend, self.NC)
|
||||
|
||||
def do_cd(self, line):
|
||||
"""
|
||||
|
|
@ -938,6 +932,13 @@ class ReplApplication(Cmd, ConsoleApplication):
|
|||
|
||||
return (objects, collections)
|
||||
|
||||
def all_collections(self):
|
||||
"""
|
||||
Get all objects that are collections: regular objects and fake dumb objects.
|
||||
"""
|
||||
obj_collections = [obj for obj in self.objects if isinstance(obj, BaseCollection)]
|
||||
return obj_collections + self.collections
|
||||
|
||||
def complete_cd(self, text, line, begidx, endidx):
|
||||
directories = set()
|
||||
if len(self.working_path.get()):
|
||||
|
|
@ -945,7 +946,8 @@ class ReplApplication(Cmd, ConsoleApplication):
|
|||
mline = line.partition(' ')[2]
|
||||
offs = len(mline) - len(text)
|
||||
|
||||
if len(self.collections) == 0:
|
||||
# refresh only if needed
|
||||
if len(self.objects) == 0 and len(self.collections) == 0:
|
||||
try:
|
||||
self.objects, self.collections = self._fetch_objects(objs=self.COLLECTION_OBJECTS)
|
||||
except CallErrors, errors:
|
||||
|
|
@ -955,7 +957,8 @@ class ReplApplication(Cmd, ConsoleApplication):
|
|||
else:
|
||||
self.bcall_error_handler(backend, error, backtrace)
|
||||
|
||||
for collection in self.collections:
|
||||
collections = self.all_collections()
|
||||
for collection in collections:
|
||||
directories.add(collection.basename.encode(sys.stdout.encoding or locale.getpreferredencoding()))
|
||||
|
||||
return [s[offs:] for s in directories if s.startswith(mline)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue