mirror of
https://github.com/gryf/pygtktalog.git
synced 2026-03-27 14:33:34 +01:00
Compare commits
4 Commits
54c24b18b1
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 85ab034a36 | |||
| 4b02641481 | |||
| 51e3bfa441 | |||
| c74174fc8f |
@@ -34,6 +34,7 @@ pycatalog requires python and following libraries:
|
|||||||
* `python 3.10`_ and up
|
* `python 3.10`_ and up
|
||||||
* `sqlalchemy 1.4`_
|
* `sqlalchemy 1.4`_
|
||||||
* `exifread`_ for parse EXIF information
|
* `exifread`_ for parse EXIF information
|
||||||
|
* `mutagen`_ for extracting tags from audio files
|
||||||
|
|
||||||
Pycatalog extensively uses external programs in unix spirit, however there is
|
Pycatalog extensively uses external programs in unix spirit, however there is
|
||||||
small possibility of using it Windows (probably with limitations) and quite big
|
small possibility of using it Windows (probably with limitations) and quite big
|
||||||
@@ -88,3 +89,4 @@ file in top-level directory.
|
|||||||
.. _sqlalchemy 1.4: http://www.sqlalchemy.org
|
.. _sqlalchemy 1.4: http://www.sqlalchemy.org
|
||||||
.. _tagging files: http://en.wikipedia.org/wiki/tag_%28metadata%29
|
.. _tagging files: http://en.wikipedia.org/wiki/tag_%28metadata%29
|
||||||
.. _tox: https://testrun.org/tox
|
.. _tox: https://testrun.org/tox
|
||||||
|
.. _mutagen: https://github.com/quodlibet/mutagen
|
||||||
|
|||||||
@@ -19,13 +19,14 @@ TYPE_MAP = {0: 'd', 1: 'd', 2: 'f', 3: 'l'}
|
|||||||
|
|
||||||
class Iface(object):
|
class Iface(object):
|
||||||
"""Main class which interacts with the pyGTKtalog modules"""
|
"""Main class which interacts with the pyGTKtalog modules"""
|
||||||
def __init__(self, dbname, pretend=False, debug=False):
|
def __init__(self, dbname, pretend=False, debug=False, use_color=True):
|
||||||
"""Init"""
|
"""Init"""
|
||||||
self.engine = dbcommon.connect(dbname)
|
self.engine = dbcommon.connect(dbname)
|
||||||
self.sess = dbcommon.Session()
|
self.sess = dbcommon.Session()
|
||||||
self.dry_run = pretend
|
self.dry_run = pretend
|
||||||
self.root = None
|
self.root = None
|
||||||
self._dbname = dbname
|
self._dbname = dbname
|
||||||
|
self.use_color = use_color
|
||||||
if debug:
|
if debug:
|
||||||
scan.LOG.setLevel('DEBUG')
|
scan.LOG.setLevel('DEBUG')
|
||||||
LOG.setLevel('DEBUG')
|
LOG.setLevel('DEBUG')
|
||||||
@@ -64,10 +65,10 @@ class Iface(object):
|
|||||||
"""Make the path to the item in the DB"""
|
"""Make the path to the item in the DB"""
|
||||||
orig_node = node
|
orig_node = node
|
||||||
if node.parent == node:
|
if node.parent == node:
|
||||||
return {u'/': (u' ', 0, u' ')}
|
return {'/': (u' ', 0, u' ')}
|
||||||
|
|
||||||
ext = ''
|
ext = ''
|
||||||
if node.parent.type == dbo.TYPE['root']:
|
if node.parent.type == dbo.TYPE['root'] and self.use_color:
|
||||||
ext = misc.colorize(' (%s)' % node.filepath, 'white')
|
ext = misc.colorize(' (%s)' % node.filepath, 'white')
|
||||||
|
|
||||||
path = []
|
path = []
|
||||||
@@ -108,8 +109,11 @@ class Iface(object):
|
|||||||
self.sess.commit()
|
self.sess.commit()
|
||||||
self.sess.close()
|
self.sess.close()
|
||||||
|
|
||||||
def list(self, path=None, recursive=False, long_=False):
|
def list(self, path=None, recursive=False, long_=False, mode='plain'):
|
||||||
"""Simulate ls command for the provided item path"""
|
"""Simulate ls command for the provided item path"""
|
||||||
|
if mode == 'mc':
|
||||||
|
self.use_color = False
|
||||||
|
|
||||||
self.root = self.sess.query(dbo.File)
|
self.root = self.sess.query(dbo.File)
|
||||||
self.root = self.root.filter(dbo.File.type == dbo.TYPE['root']).first()
|
self.root = self.root.filter(dbo.File.type == dbo.TYPE['root']).first()
|
||||||
if path:
|
if path:
|
||||||
@@ -119,6 +123,7 @@ class Iface(object):
|
|||||||
node = self.root
|
node = self.root
|
||||||
msg = "Content of path `/':"
|
msg = "Content of path `/':"
|
||||||
|
|
||||||
|
if mode != 'mc':
|
||||||
print(misc.colorize(msg, 'white'))
|
print(misc.colorize(msg, 'white'))
|
||||||
|
|
||||||
if recursive:
|
if recursive:
|
||||||
@@ -126,9 +131,29 @@ class Iface(object):
|
|||||||
else:
|
else:
|
||||||
items = self._list(node)
|
items = self._list(node)
|
||||||
|
|
||||||
if long_:
|
if mode == 'mc':
|
||||||
filenames = []
|
filenames = []
|
||||||
format_str = (u'{} {:>%d,} {} {}' %
|
format_str = ('{} 1 {} {} {:>%d} {} {}' %
|
||||||
|
len(str(sorted([i[1] for i in
|
||||||
|
items.values()])[-1])))
|
||||||
|
for fname in sorted(items.keys()):
|
||||||
|
type_, size, date = items[fname]
|
||||||
|
if type_ == 'd':
|
||||||
|
perms = 'drwxrwxrwx'
|
||||||
|
elif type_ == 'l':
|
||||||
|
perms = 'lrw-rw-rw-'
|
||||||
|
elif type_ == 'f':
|
||||||
|
perms = '-rw-rw-rw-'
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
filenames.append(format_str
|
||||||
|
.format(perms, os.getuid(),
|
||||||
|
os.getgid(), size,
|
||||||
|
date.strftime('%d/%m/%Y %H:%M:%S'),
|
||||||
|
fname))
|
||||||
|
elif long_:
|
||||||
|
filenames = []
|
||||||
|
format_str = ('{} {:>%d,} {} {}' %
|
||||||
_get_highest_size_length(items))
|
_get_highest_size_length(items))
|
||||||
for fname in sorted(items.keys()):
|
for fname in sorted(items.keys()):
|
||||||
type_, size, date = items[fname]
|
type_, size, date = items[fname]
|
||||||
@@ -254,8 +279,12 @@ def _get_highest_size_length(item_dict):
|
|||||||
@misc.asserdb
|
@misc.asserdb
|
||||||
def list_db(args):
|
def list_db(args):
|
||||||
"""List"""
|
"""List"""
|
||||||
|
if args.mode == 'mc':
|
||||||
|
LOG.setLevel(100) # supress logging
|
||||||
|
|
||||||
obj = Iface(args.db, False, args.debug)
|
obj = Iface(args.db, False, args.debug)
|
||||||
obj.list(path=args.path, recursive=args.recursive, long_=args.long)
|
obj.list(path=args.path, recursive=args.recursive, long_=args.long,
|
||||||
|
mode=args.mode)
|
||||||
obj.close()
|
obj.close()
|
||||||
|
|
||||||
|
|
||||||
@@ -298,6 +327,12 @@ def main():
|
|||||||
list_ = subparser.add_parser('list')
|
list_ = subparser.add_parser('list')
|
||||||
list_.add_argument('db')
|
list_.add_argument('db')
|
||||||
list_.add_argument('path', nargs='?')
|
list_.add_argument('path', nargs='?')
|
||||||
|
list_.add_argument('-m', '--mode', help='List items using mode. By '
|
||||||
|
'default is simply plain mode, other possibility is to '
|
||||||
|
'use "mc" mode, which is suitable to use with extfs '
|
||||||
|
'plugin', default='plain')
|
||||||
|
list_.add_argument('-c', '--color', help='Use colors for listing',
|
||||||
|
action='store_true', default=False)
|
||||||
list_.add_argument('-l', '--long', help='Show size, date and type',
|
list_.add_argument('-l', '--long', help='Show size, date and type',
|
||||||
action='store_true', default=False)
|
action='store_true', default=False)
|
||||||
list_.add_argument('-r', '--recursive', help='list items in '
|
list_.add_argument('-r', '--recursive', help='list items in '
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ import re
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import mimetypes
|
import mimetypes
|
||||||
|
|
||||||
|
import exifread
|
||||||
|
import mutagen
|
||||||
|
|
||||||
from pycatalog.dbobjects import File, TYPE
|
from pycatalog.dbobjects import File, TYPE
|
||||||
from pycatalog import dbcommon
|
from pycatalog import dbcommon
|
||||||
from pycatalog.logger import get_logger
|
from pycatalog.logger import get_logger
|
||||||
@@ -212,13 +215,28 @@ class Scan(object):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def _audio(self, fobj, filepath):
|
def _audio(self, fobj, filepath):
|
||||||
# tags, depending on the format?
|
tags = mutagen.File(filepath)
|
||||||
|
if not tags:
|
||||||
return
|
return
|
||||||
|
fobj.description = tags.pprint()
|
||||||
|
|
||||||
def _image(self, fobj, filepath):
|
def _image(self, fobj, filepath):
|
||||||
# exif?
|
"""Read exif if exists, add it to description"""
|
||||||
|
with open(filepath, 'rb') as obj:
|
||||||
|
exif = exifread.process_file(obj)
|
||||||
|
if not exif:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
data = []
|
||||||
|
# longest key + 2, since we need a colon and a space after it
|
||||||
|
longest_key = max([len(k) for k in exif]) + 2
|
||||||
|
for key in exif:
|
||||||
|
if 'thumbnail' in key.lower() and isinstance(exif[key], bytes):
|
||||||
|
data.append(f"{key + ':' :<{longest_key}}thumbnail present")
|
||||||
|
continue
|
||||||
|
data.append(f"{key + ':' :<{longest_key}}{exif[key]}")
|
||||||
|
fobj.description = "\n".join(data)
|
||||||
|
|
||||||
def _video(self, fobj, filepath):
|
def _video(self, fobj, filepath):
|
||||||
"""
|
"""
|
||||||
Make captures for a movie. Save it under uniq name.
|
Make captures for a movie. Save it under uniq name.
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
Pillow
|
|
||||||
exifread
|
|
||||||
sqlalchemy
|
|
||||||
Reference in New Issue
Block a user