s/IBaseCap/CapBase/ (refs #1424)
This commit is contained in:
parent
0f90d6e9dd
commit
e5f11a15eb
31 changed files with 63 additions and 63 deletions
|
|
@ -19,7 +19,7 @@ Select capabilities
|
|||
*******************
|
||||
|
||||
Each module implements one or many :doc:`capabilities </api/capabilities/index>` to tell what kind of features the
|
||||
website provides. A capability is a class derived from :class:`weboob.capabilities.base.IBaseCap` and with some abstract
|
||||
website provides. A capability is a class derived from :class:`weboob.capabilities.base.CapBase` and with some abstract
|
||||
methods (which raise ``NotImplementedError``).
|
||||
|
||||
A capability needs to be as generic as possible to allow a maximum number of modules to implements it.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from .base import UserError, NotLoaded, NotAvailable, BaseObject, IBaseCap
|
||||
from .base import UserError, NotLoaded, NotAvailable, BaseObject, CapBase
|
||||
|
||||
__all__ = ['UserError', 'NotLoaded', 'NotAvailable', 'BaseObject', 'IBaseCap']
|
||||
__all__ = ['UserError', 'NotLoaded', 'NotAvailable', 'BaseObject', 'CapBase']
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from .base import IBaseCap, BaseObject, StringField, Field, UserError
|
||||
from .base import CapBase, BaseObject, StringField, Field, UserError
|
||||
|
||||
|
||||
__all__ = ['AccountRegisterError', 'Account', 'StatusField', 'CapAccount']
|
||||
|
|
@ -56,7 +56,7 @@ class StatusField(object):
|
|||
self.flags = flags
|
||||
|
||||
|
||||
class CapAccount(IBaseCap):
|
||||
class CapAccount(CapBase):
|
||||
"""
|
||||
Capability for websites when you can create and manage accounts.
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ from weboob.tools.ordereddict import OrderedDict
|
|||
|
||||
|
||||
__all__ = ['UserError', 'FieldNotFound', 'NotAvailable',
|
||||
'NotLoaded', 'IBaseCap', 'Field', 'IntField', 'DecimalField',
|
||||
'NotLoaded', 'CapBase', 'Field', 'IntField', 'DecimalField',
|
||||
'FloatField', 'StringField', 'BytesField',
|
||||
'empty', 'BaseObject']
|
||||
|
||||
|
|
@ -146,7 +146,7 @@ class NotLoadedType(object):
|
|||
NotLoaded = NotLoadedType()
|
||||
|
||||
|
||||
class IBaseCap(object):
|
||||
class CapBase(object):
|
||||
"""
|
||||
This is the base class for all capabilities.
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from .base import IBaseCap, BaseObject, Field, StringField,\
|
||||
from .base import CapBase, BaseObject, Field, StringField,\
|
||||
IntField, UserError
|
||||
from .date import DateField, DeltaField
|
||||
|
||||
|
|
@ -232,7 +232,7 @@ class Query(BaseObject):
|
|||
BaseObject.__init__(self, '')
|
||||
|
||||
|
||||
class CapBugTracker(IBaseCap):
|
||||
class CapBugTracker(CapBase):
|
||||
"""
|
||||
Bug trackers websites.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
import datetime
|
||||
|
||||
from .base import IBaseCap, BaseObject, StringField, UserError
|
||||
from .base import CapBase, BaseObject, StringField, UserError
|
||||
from .date import DateField
|
||||
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ class ChatMessage(BaseObject):
|
|||
self.date = datetime.datetime.utcnow()
|
||||
|
||||
|
||||
class CapChat(IBaseCap):
|
||||
class CapChat(CapBase):
|
||||
"""
|
||||
Websites with a chat system.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from .base import IBaseCap, BaseObject, StringField, IntField, Field
|
||||
from .base import CapBase, BaseObject, StringField, IntField, Field
|
||||
from .date import DateField
|
||||
|
||||
|
||||
|
|
@ -69,7 +69,7 @@ class Person(BaseObject):
|
|||
self.name = name
|
||||
|
||||
|
||||
class CapCinema(IBaseCap):
|
||||
class CapCinema(CapBase):
|
||||
"""
|
||||
Cinema databases.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
from weboob.tools.ordereddict import OrderedDict
|
||||
|
||||
from .base import IBaseCap, BaseObject, UserError, StringField, Field
|
||||
from .base import CapBase, BaseObject, UserError, StringField, Field
|
||||
|
||||
|
||||
__all__ = ['CapCollection', 'BaseCollection', 'Collection', 'CollectionNotFound']
|
||||
|
|
@ -95,7 +95,7 @@ class Collection(BaseCollection):
|
|||
return u'Unknown collection'
|
||||
|
||||
|
||||
class CapCollection(IBaseCap):
|
||||
class CapCollection(CapBase):
|
||||
def iter_resources_flat(self, objs, split_path, clean_only=False):
|
||||
"""
|
||||
Call iter_resources() to fetch all resources in the tree.
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from .base import IBaseCap, BaseObject, Field, StringField, BytesField, IntField, \
|
||||
from .base import CapBase, BaseObject, Field, StringField, BytesField, IntField, \
|
||||
UserError
|
||||
from weboob.tools.ordereddict import OrderedDict
|
||||
|
||||
|
|
@ -165,7 +165,7 @@ class Query(BaseObject):
|
|||
self.message = message
|
||||
|
||||
|
||||
class CapContact(IBaseCap):
|
||||
class CapContact(CapBase):
|
||||
def iter_contacts(self, status=Contact.STATUS_ALL, ids=None):
|
||||
"""
|
||||
Iter contacts
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from .base import IBaseCap, BaseObject, StringField, Field
|
||||
from .base import CapBase, BaseObject, StringField, Field
|
||||
from .date import DateField
|
||||
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ class Revision(BaseObject):
|
|||
minor = Field('Is this change minor?', bool)
|
||||
|
||||
|
||||
class CapContent(IBaseCap):
|
||||
class CapContent(CapBase):
|
||||
def get_content(self, id, revision=None):
|
||||
"""
|
||||
Get a content from an ID.
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from .base import IBaseCap, BaseObject, Field, StringField, UserError
|
||||
from .base import CapBase, BaseObject, Field, StringField, UserError
|
||||
from .date import DateField
|
||||
from .contact import Contact
|
||||
|
||||
|
|
@ -90,7 +90,7 @@ class Event(BaseObject):
|
|||
message = StringField('Message of the event')
|
||||
|
||||
|
||||
class CapDating(IBaseCap):
|
||||
class CapDating(CapBase):
|
||||
"""
|
||||
Capability for dating websites.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from .base import IBaseCap, BaseObject, NotAvailable, Field, StringField
|
||||
from .base import CapBase, BaseObject, NotAvailable, Field, StringField
|
||||
from .date import DateField
|
||||
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ class BaseFile(BaseObject):
|
|||
return self.id2url(self.id)
|
||||
|
||||
|
||||
class CapFile(IBaseCap):
|
||||
class CapFile(CapBase):
|
||||
"""
|
||||
Provide file download
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
|
||||
from weboob.tools.capabilities.thumbnail import Thumbnail
|
||||
from .base import IBaseCap, BaseObject, NotLoaded, Field, StringField, \
|
||||
from .base import CapBase, BaseObject, NotLoaded, Field, StringField, \
|
||||
BytesField, IntField, FloatField
|
||||
from .date import DateField
|
||||
|
||||
|
|
@ -104,7 +104,7 @@ class BaseImage(BaseObject):
|
|||
return self.data is not NotLoaded
|
||||
|
||||
|
||||
class CapGallery(IBaseCap):
|
||||
class CapGallery(CapBase):
|
||||
"""
|
||||
This capability represents the ability for a website backend to provide videos.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from .base import IBaseCap, BaseObject, StringField, FloatField, Field, UserError, empty
|
||||
from .base import CapBase, BaseObject, StringField, FloatField, Field, UserError, empty
|
||||
from .date import DateField
|
||||
|
||||
__all__ = ['Gauge', 'GaugeSensor', 'GaugeMeasure', 'CapGauge', 'SensorNotFound']
|
||||
|
|
@ -74,7 +74,7 @@ class GaugeSensor(BaseObject):
|
|||
return "<GaugeSensor id=%s name=%s>" % (self.id, self.name)
|
||||
|
||||
|
||||
class CapGauge(IBaseCap):
|
||||
class CapGauge(CapBase):
|
||||
def iter_gauges(self, pattern=None):
|
||||
"""
|
||||
Iter gauges.
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from .base import IBaseCap, BaseObject, StringField, FloatField
|
||||
from .base import CapBase, BaseObject, StringField, FloatField
|
||||
|
||||
|
||||
__all__ = ['IpLocation', 'CapGeolocIp']
|
||||
|
|
@ -42,7 +42,7 @@ class IpLocation(BaseObject):
|
|||
BaseObject.__init__(self, ipaddr)
|
||||
|
||||
|
||||
class CapGeolocIp(IBaseCap):
|
||||
class CapGeolocIp(CapBase):
|
||||
"""
|
||||
Access information about IP addresses database.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from .base import IBaseCap, BaseObject, Field, IntField, DecimalField, \
|
||||
from .base import CapBase, BaseObject, Field, IntField, DecimalField, \
|
||||
StringField, BytesField
|
||||
from .date import DateField
|
||||
|
||||
|
|
@ -89,7 +89,7 @@ class City(BaseObject):
|
|||
name = StringField('Name of city')
|
||||
|
||||
|
||||
class CapHousing(IBaseCap):
|
||||
class CapHousing(CapBase):
|
||||
"""
|
||||
Capability of websites to search housings.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from .base import BaseObject, IBaseCap, StringField
|
||||
from .base import BaseObject, CapBase, StringField
|
||||
from .date import DateField
|
||||
|
||||
__all__ = ['BaseJobAdvert', 'CapJob']
|
||||
|
|
@ -68,7 +68,7 @@ class BaseJobAdvert(BaseObject):
|
|||
return self.id2url(self.id)
|
||||
|
||||
|
||||
class CapJob(IBaseCap):
|
||||
class CapJob(CapBase):
|
||||
"""
|
||||
Capability of job annouce websites.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from .base import IBaseCap, BaseObject, StringField
|
||||
from .base import CapBase, BaseObject, StringField
|
||||
|
||||
|
||||
__all__ = ['SongLyrics', 'CapLyrics']
|
||||
|
|
@ -37,7 +37,7 @@ class SongLyrics(BaseObject):
|
|||
self.title = title
|
||||
|
||||
|
||||
class CapLyrics(IBaseCap):
|
||||
class CapLyrics(CapBase):
|
||||
"""
|
||||
Lyrics websites.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
import datetime
|
||||
import time
|
||||
|
||||
from .base import IBaseCap, BaseObject, NotLoaded, Field, StringField, \
|
||||
from .base import CapBase, BaseObject, NotLoaded, Field, StringField, \
|
||||
IntField, UserError
|
||||
from .date import DateField
|
||||
|
||||
|
|
@ -165,7 +165,7 @@ class Thread(_Thread):
|
|||
yield m
|
||||
|
||||
|
||||
class CapMessages(IBaseCap):
|
||||
class CapMessages(CapBase):
|
||||
"""
|
||||
Capability to read messages.
|
||||
"""
|
||||
|
|
@ -209,7 +209,7 @@ class CantSendMessage(UserError):
|
|||
"""
|
||||
|
||||
|
||||
class CapMessagesPost(IBaseCap):
|
||||
class CapMessagesPost(CapBase):
|
||||
"""
|
||||
This capability allow user to send a message.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from .base import IBaseCap, BaseObject, Field, StringField
|
||||
from .base import CapBase, BaseObject, Field, StringField
|
||||
from .date import DateField
|
||||
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ class Parcel(BaseObject):
|
|||
history = Field('History', list)
|
||||
|
||||
|
||||
class CapParcel(IBaseCap):
|
||||
class CapParcel(CapBase):
|
||||
def get_parcel_tracking(self, id):
|
||||
"""
|
||||
Get information abouut a parcel.
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from .base import IBaseCap, BaseObject, NotLoaded, Field, StringField, UserError
|
||||
from .base import CapBase, BaseObject, NotLoaded, Field, StringField, UserError
|
||||
|
||||
|
||||
__all__ = ['PasteNotFound', 'BasePaste', 'CapPaste']
|
||||
|
|
@ -63,7 +63,7 @@ class BasePaste(BaseObject):
|
|||
return self.id2url(self.id)
|
||||
|
||||
|
||||
class CapPaste(IBaseCap):
|
||||
class CapPaste(CapBase):
|
||||
"""
|
||||
This capability represents the ability for a website backend to store plain text.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from .base import IBaseCap, BaseObject, Field, DecimalField, \
|
||||
from .base import CapBase, BaseObject, Field, DecimalField, \
|
||||
StringField
|
||||
from .date import DateField
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ class Price(BaseObject):
|
|||
product = Field('Product', Product)
|
||||
|
||||
|
||||
class CapPriceComparison(IBaseCap):
|
||||
class CapPriceComparison(CapBase):
|
||||
"""
|
||||
Capability for price comparison websites.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from .base import IBaseCap, BaseObject, Field, StringField
|
||||
from .base import CapBase, BaseObject, Field, StringField
|
||||
from weboob.tools.capabilities.streaminfo import StreamInfo
|
||||
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ class Radio(BaseObject):
|
|||
current = Field('Current emission', StreamInfo)
|
||||
streams = Field('List of streams', list)
|
||||
|
||||
class CapRadio(IBaseCap):
|
||||
class CapRadio(CapBase):
|
||||
"""
|
||||
Capability of radio websites.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from .base import IBaseCap, BaseObject, StringField, IntField, Field, empty
|
||||
from .base import CapBase, BaseObject, StringField, IntField, Field, empty
|
||||
|
||||
import lxml.etree as ET
|
||||
|
||||
|
|
@ -161,7 +161,7 @@ class Recipe(BaseObject):
|
|||
return header + ET.tostring(doc, encoding='UTF-8', pretty_print=True).decode('utf-8')
|
||||
|
||||
|
||||
class CapRecipe(IBaseCap):
|
||||
class CapRecipe(CapBase):
|
||||
"""
|
||||
Recipe providers.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from .base import IBaseCap, BaseObject, StringField, IntField, UserError
|
||||
from .base import CapBase, BaseObject, StringField, IntField, UserError
|
||||
|
||||
|
||||
__all__ = ['Subtitle', 'CapSubtitle']
|
||||
|
|
@ -48,7 +48,7 @@ class Subtitle(BaseObject):
|
|||
BaseObject.__init__(self, id)
|
||||
self.name = name
|
||||
|
||||
class CapSubtitle(IBaseCap):
|
||||
class CapSubtitle(CapBase):
|
||||
"""
|
||||
Subtitle providers.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from .base import IBaseCap, BaseObject, Field, StringField, FloatField, \
|
||||
from .base import CapBase, BaseObject, Field, StringField, FloatField, \
|
||||
IntField, UserError
|
||||
from .date import DateField
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ class Torrent(BaseObject):
|
|||
self.name = name
|
||||
|
||||
|
||||
class CapTorrent(IBaseCap):
|
||||
class CapTorrent(CapBase):
|
||||
"""
|
||||
Torrent trackers.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from .base import IBaseCap, BaseObject, StringField, UserError
|
||||
from .base import CapBase, BaseObject, StringField, UserError
|
||||
|
||||
|
||||
__all__ = ['TranslationFail', 'LanguageNotSupported', 'CapTranslate']
|
||||
|
|
@ -51,7 +51,7 @@ class Translation(BaseObject):
|
|||
text = StringField('Translation')
|
||||
|
||||
|
||||
class CapTranslate(IBaseCap):
|
||||
class CapTranslate(CapBase):
|
||||
"""
|
||||
Capability of online translation website to translate word or sentence
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
import datetime
|
||||
|
||||
from .base import IBaseCap, BaseObject, StringField, DecimalField, UserError
|
||||
from .base import CapBase, BaseObject, StringField, DecimalField, UserError
|
||||
from .date import TimeField, DeltaField, DateField
|
||||
|
||||
__all__ = ['Station', 'Departure', 'RoadStep', 'RoadmapError', 'RoadmapFilters', 'CapTravel']
|
||||
|
|
@ -95,7 +95,7 @@ class RoadmapFilters(BaseObject):
|
|||
BaseObject.__init__(self, '')
|
||||
|
||||
|
||||
class CapTravel(IBaseCap):
|
||||
class CapTravel(CapBase):
|
||||
"""
|
||||
Travel websites.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
from datetime import datetime, date
|
||||
|
||||
from .base import IBaseCap, BaseObject, Field, FloatField, \
|
||||
from .base import CapBase, BaseObject, Field, FloatField, \
|
||||
StringField, UserError
|
||||
from .date import DateField
|
||||
|
||||
|
|
@ -109,7 +109,7 @@ class CityNotFound(UserError):
|
|||
"""
|
||||
|
||||
|
||||
class CapWeather(IBaseCap):
|
||||
class CapWeather(CapBase):
|
||||
"""
|
||||
Capability for weather websites.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ class WebNip(object):
|
|||
Note: each backend is locked when it is returned.
|
||||
|
||||
:param caps: optional list of capabilities to select backends
|
||||
:type caps: tuple[:class:`weboob.capabilities.base.IBaseCap`]
|
||||
:type caps: tuple[:class:`weboob.capabilities.base.CapBase`]
|
||||
:rtype: iter[:class:`weboob.tools.backend.BaseBackend`]
|
||||
"""
|
||||
for _, backend in sorted(self.backend_instances.iteritems()):
|
||||
|
|
@ -222,7 +222,7 @@ class WebNip(object):
|
|||
:param backends: list of backends to iterate on
|
||||
:type backends: list[:class:`str`]
|
||||
:param caps: iterate on backends which implement this caps
|
||||
:type caps: list[:class:`weboob.capabilities.base.IBaseCap`]
|
||||
:type caps: list[:class:`weboob.capabilities.base.CapBase`]
|
||||
:rtype: A :class:`weboob.core.bcall.BackendsCall` object (iterable)
|
||||
"""
|
||||
backends = self.backend_instances.values()
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ from threading import RLock
|
|||
from copy import copy
|
||||
|
||||
from weboob.capabilities.base import BaseObject, FieldNotFound, \
|
||||
IBaseCap, NotLoaded, NotAvailable
|
||||
CapBase, NotLoaded, NotAvailable
|
||||
from weboob.tools.misc import iter_fields
|
||||
from weboob.tools.log import getLogger
|
||||
from weboob.tools.value import ValuesDict
|
||||
|
|
@ -350,11 +350,11 @@ class BaseBackend(object):
|
|||
"""
|
||||
Iter capabilities implemented by this backend.
|
||||
|
||||
:rtype: iter[:class:`weboob.capabilities.base.IBaseCap`]
|
||||
:rtype: iter[:class:`weboob.capabilities.base.CapBase`]
|
||||
"""
|
||||
def iter_caps(cls):
|
||||
for base in cls.__bases__:
|
||||
if issubclass(base, IBaseCap) and base != IBaseCap:
|
||||
if issubclass(base, CapBase) and base != CapBase:
|
||||
yield base
|
||||
for cap in iter_caps(base):
|
||||
yield cap
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue