Skip to content
Snippets Groups Projects
output.py 5.61 KiB
Newer Older
  • Learn to ignore specific revisions
  • import tabulate
    
    
    
    def comma_separated(it):
        return ", ".join(it)
    
    
    
    FIELDS = {
    
        "ARTIST": {
    
            "ID": {"field": "id", "truncate": 0},
            "Name": {"field": "name"},
    
            "Albums": {"field": "albums", "handler": lambda v: len(v), "truncate": 0},
            "Tracks": {
                "field": "albums",
                "handler": lambda v: sum([a["tracks_count"] for a in v]),
                "truncate": 0,
            },
            "Artist": {"field": ["album.artist.name", "track.artist.name"]},
        },
        "ALBUM": {
    
            "ID": {"field": "id", "truncate": 0},
            "Title": {"field": "title"},
    
            "Tracks": {"field": "tracks", "handler": lambda v: len(v), "truncate": 0},
            "Artist": {"field": "artist.name"},
        },
    
        "CHANNEL": {
            "Category": {"field": "artist.content_category", "truncate": 0},
            "Username": {"field": "actor.full_username", "truncate": 0},
            "Name": {"field": "artist.name"},
            "Descsription": {"field": "artist.description.text"},
            "RSS URL": {"field": "rss_url"},
            "Artist": {"field": "artist.id"},
            "Metadata": {"field": "metadata"},
            "Tags": {"field": "artist.tags", "handler": ", ".join,},
        },
    
        "TRACK": {
    
            "ID": {"field": "id", "truncate": 0},
            "Title": {"field": "title"},
    
            "Artist": {"field": ["album.artist.name", "track.artist.name"]},
            "Album": {"field": "album.title"},
    
            "Disc": {"field": "disc", "handler": lambda v: v or 1},
            "Position": {"field": "position"},
    
        "UPLOAD": {
            "Source": {"field": "source"},
            "Track": {"field": "track.title"},
            "Artist": {"field": "track.artist.name"},
            "Size": {"field": "size"},
            "Import status": {"field": "import_status"},
            "Mimetype": {"field": "mimetype"},
        },
    
            "Name": {"field": "name"},
    
            "Description": {"field": "description"},
            "Uploads": {"field": "uploads_count"},
        },
    
        "TRACK_FAVORITE": {
            "Track ID": {"field": "track.id", "truncate": 0},
            "Track": {"field": "track.title"},
            "Artist": {"field": "track.artist.name"},
            "Favorite Date": {"field": "creation_date"},
        },
    
        "PLAYLIST": {
            "Tracks Count": {"field": "tracks_count"},
            "User": {"field": "user.username"},
        },
    
        "PLAYLIST_TRACK": {
    
            "ID": {"field": "track.id"},
    
            "Position": {"field": "index"},
            "Title": {"field": "track.title"},
            "Artist": {"field": "track.artist.name"},
            "Album": {"field": "track.album.title"},
        },
    
        "USER": {
            "Username": {"field": "username"},
            "Federation ID": {"field": "full_username"},
            "Email": {"field": "email"},
            "Joined": {"field": "date_joined"},
            "Staff": {"field": "is_staff"},
            "Admin": {"field": "is_admin"},
            "Permissions": {
                "field": "permissions",
                "handler": lambda v: ", ".join([k for k, v in v.items() if v]),
            },
        },
    
            "Name": {"field": "name"},
            "Visibility": {"field": "privacy_level"},
    
            "Created": {"field": "creation_date"},
    
            "Modified": {"field": "modification_date"},
    
            "UUID": {"field": "uuid", "truncate": 0},
    
            "ID": {"field": "id", "truncate": 0},
    
            "Tags": {"field": "tags", "handler": ", ".join,},
    
    TABLE_FORMATS = sorted(tabulate._table_formats.keys())
    
    
    
    def recursive_getattr(obj, key, permissive=False):
        """
        Given a dictionary such as {'user': {'name': 'Bob'}} and
        a dotted string such as user.name, returns 'Bob'.
    
        If the value is not present, returns None
        """
        v = obj
        for k in key.split("."):
            try:
                v = v.get(k)
            except (TypeError, AttributeError):
                if not permissive:
                    raise
                return
            if v is None:
                return
    
        return v
    
    
    def get_value(obj, config, truncate=30):
        field = config["field"]
        if isinstance(field, list):
            value = [recursive_getattr(obj, f, permissive=True) for f in field]
            value = "/".join([str(v) for v in value if v is not None])
        else:
    
            value = recursive_getattr(obj, field, permissive=True)
    
        if config.get("handler"):
            value = config["handler"](value)
        value = str(value)
    
        if truncate and len(value) > truncate:
            value = value[:truncate] + ""
        return value
    
    
    
    def table(objects, fields, type, headers=True, format="simple"):
    
    
        configs = {}
    
        for f in fields:
            try:
                configs[f] = FIELDS[type][f]
            except KeyError:
                try:
                    configs[f] = FIELDS["*"][f]
                except KeyError:
                    raise ValueError("{} is not a valid field for type {}".format(f, type))
    
    
        headers = fields if headers else []
    
        rows = [
            [
                get_value(obj, configs[f], truncate=configs[f].get("truncate", 30))
                for f in fields
            ]
            for obj in objects
        ]
    
        return tabulate.tabulate(rows, headers=headers, tablefmt=format)
    
    
    
    def obj_table(obj, fields, type, headers=True, format="simple"):
        """
        same as table(), but output a two-column table for a single object,
        with fields on the left and values on the right
        """
        configs = {}
    
        for f in fields:
            try:
                configs[f] = FIELDS[type][f]
            except KeyError:
                try:
                    configs[f] = FIELDS["*"][f]
                except KeyError:
                    raise ValueError("{} is not a valid field for type {}".format(f, type))
    
        rows = [
            (f, get_value(obj, configs[f], truncate=configs[f].get("truncate", 30)))
            for f in fields
        ]
    
        return tabulate.tabulate(rows, headers=[], tablefmt=format)