forked from varia/distribusi
refactoring and thumbnailer
This commit is contained in:
parent
4cb03d1131
commit
c0b40c7d30
@ -6,83 +6,78 @@ from distribusi.distribusi import distribusify
|
|||||||
|
|
||||||
def build_argparser():
|
def build_argparser():
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
"""
|
"""
|
||||||
distribusi is a content management system for the web that produces static
|
distribusi is a content management system for the web that produces static
|
||||||
index pages based on folders in the files system. It is inspired by the
|
index pages based on folders in the files system. It is inspired by the
|
||||||
automatic index functions featured in several popular web servers.
|
automatic index functions featured in several popular web servers.
|
||||||
distribusi works by traversing the file system and directory hierarchy to
|
distribusi works by traversing the file system and directory hierarchy to
|
||||||
automatically list all the files in the directory, detect the file types
|
automatically list all the files in the directory, detect the file types
|
||||||
and providing them with relevant html classes and tags for easy styling.
|
and providing them with relevant html classes and tags for easy styling.
|
||||||
""")
|
"""
|
||||||
|
|
||||||
parser.add_argument(
|
|
||||||
'-d', '--directory', help="Select which directory to distribute", default="."
|
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-s', '--style', help="Select a CSS style sheet to include"
|
"-d", "--directory", help="Select which directory to distribute", default="."
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument("-s", "--style", help="Select a CSS style sheet to include")
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-v", "--verbose", help="Print verbose debug output", action="store_true"
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-v', '--verbose', help="Print verbose debug output", action="store_true"
|
"-t",
|
||||||
)
|
"--thumbnail",
|
||||||
|
|
||||||
parser.add_argument(
|
|
||||||
'-t',
|
|
||||||
'--thumbnail',
|
|
||||||
help="Generate 450x450 thumbnails for images",
|
help="Generate 450x450 thumbnails for images",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-n',
|
"-n",
|
||||||
'--no-template',
|
"--no-template",
|
||||||
help="Don't use the template to output html",
|
help="Don't use the template to output html",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-nf',
|
"-c",
|
||||||
'--no-filenames',
|
"--captions",
|
||||||
help="Don't add file names to listing",
|
help="Adds image captions based on EXIF metadata",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-c',
|
"-r",
|
||||||
'--captions',
|
"--remove-index",
|
||||||
help="Adds image captions based on EXIF metadata, requires 'exiftool'",
|
|
||||||
action="store_true",
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument(
|
|
||||||
'-r',
|
|
||||||
'--remove-index',
|
|
||||||
help="Recursively removes all instances of index.html that have been previously made by distribusi",
|
help="Recursively removes all instances of index.html that have been previously made by distribusi",
|
||||||
action="store_true")
|
action="store_true",
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-e',
|
"-e",
|
||||||
'--exclude-directory',
|
"--exclude-directory",
|
||||||
help="Exclude one or multiple directories from indexing",
|
help="Exclude one or multiple directories from indexing",
|
||||||
nargs="*",
|
nargs="*",
|
||||||
metavar='DIR')
|
metavar="DIR",
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-f',
|
"-f",
|
||||||
'--force',
|
"--force",
|
||||||
help="Force whether distribusi overwrites or removes instances of index.html not generated by distribusi, use at own risk!",
|
help="Force whether distribusi overwrites or removes instances of index.html not generated by distribusi, use at own risk!",
|
||||||
action="store_true")
|
action="store_true",
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--no-hidden',
|
"--no-hidden", help="Exclude hidden directories", action="store_true"
|
||||||
help="Exclude hidden directories",
|
)
|
||||||
action="store_true")
|
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--menu-with-index',
|
"--menu-with-index",
|
||||||
help="Append index.html to menu items to aid navigation",
|
help="Append index.html to menu items to aid navigation",
|
||||||
action="store_true")
|
action="store_true",
|
||||||
|
)
|
||||||
|
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
import base64
|
import base64
|
||||||
import os
|
import os
|
||||||
import subprocess
|
|
||||||
from io import BytesIO
|
|
||||||
|
|
||||||
import magic
|
import magic
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
from exif import Image as ExifImage
|
||||||
from distribusi.page_template import html_footer, html_head
|
from distribusi.page_template import html_footer, html_head
|
||||||
from distribusi.mappings import CODE_TYPES, FILE_TYPES, SUB_TYPES
|
from distribusi.mappings import CODE_TYPES, FILE_TYPES, SUB_TYPES
|
||||||
|
|
||||||
@ -14,62 +12,49 @@ MIME_TYPE = magic.Magic(mime=True)
|
|||||||
|
|
||||||
def caption(image):
|
def caption(image):
|
||||||
try:
|
try:
|
||||||
process = subprocess.Popen(
|
with open(image, "rb") as image_file:
|
||||||
['exiftool', '-Comment', image], stdout=subprocess.PIPE)
|
exif_image = ExifImage(image_file)
|
||||||
out, err = process.communicate()
|
caption = exif_image.communication
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
print('Do you have exiftool installed?')
|
caption = ""
|
||||||
try:
|
|
||||||
caption = out.decode("utf-8").split(": ", 1)[1]
|
|
||||||
except Exception as e:
|
|
||||||
caption = ''
|
|
||||||
print(e)
|
|
||||||
return caption
|
return caption
|
||||||
|
|
||||||
|
|
||||||
def thumbnail(image, name, args):
|
def thumbnail(full_path_image, name, args):
|
||||||
|
if full_path_image.endswith("_thumbnail.jpg"):
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
size = (450, 450)
|
size = (450, 450)
|
||||||
im = Image.open(image)
|
thumbnail_image = Image.open(full_path_image)
|
||||||
im.thumbnail(size)
|
thumbnail_image.thumbnail(size)
|
||||||
|
|
||||||
if (im.mode == 'RGBA'):
|
if thumbnail_image.mode == "RGBA":
|
||||||
bg = Image.new('RGBA', im.size, (255,255,255))
|
bg = Image.new("RGBA", im.size, (255, 255, 255))
|
||||||
composite = Image.alpha_composite(bg, im)
|
composite = Image.alpha_composite(bg, thumbnail_image)
|
||||||
im=composite.convert('RGB')
|
thumbnail_image = composite.convert("RGB")
|
||||||
|
|
||||||
output = BytesIO()
|
image_filename_no_ext = os.path.splitext(full_path_image)[0]
|
||||||
im.save(output, format='JPEG')
|
thumbnail_filename = f"{image_filename_no_ext}_thumbnail.jpg"
|
||||||
im_data = output.getvalue()
|
thumbnail_image.save(thumbnail_filename, format="JPEG")
|
||||||
data_url = base64.b64encode(im_data).decode()
|
return os.path.basename(thumbnail_filename)
|
||||||
if args.captions:
|
|
||||||
cap = caption(image)
|
|
||||||
else:
|
|
||||||
cap = name
|
|
||||||
return (
|
|
||||||
"<figure><a href='{}'><img class='thumbnail' src='data:image/jpg;base64,{}'></a><figcaption>{}</figcaption></figure>"
|
|
||||||
).format(name, data_url, cap)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('Thumbnailer:', e)
|
print("Thumbnailer:", e)
|
||||||
return "<figure><a href='{}'><img src='{}'></a><figcaption>{}</figcaption></figure>".format(name, name, name)
|
return
|
||||||
|
|
||||||
|
|
||||||
def div(args, type_, subtype, tag, name):
|
def format_div(args, type_, subtype, tag, name):
|
||||||
id_name = name.split('.')[0].replace(' ', '_')
|
id_name = name.split(".")[0].replace(" ", "_")
|
||||||
if args.no_filenames:
|
filename = f'<span class="filename">{name}</span>'
|
||||||
filename = ''
|
|
||||||
else:
|
|
||||||
filename = '<span class="filename">{}</span>'.format(name)
|
|
||||||
|
|
||||||
if 'image' in type_:
|
if "image" in type_:
|
||||||
html = '<div id="{}" class="{}">{}</div>'
|
html = '<div id="{}" class="{}">{}</div>'
|
||||||
elif 'pdf' in subtype:
|
elif "pdf" in subtype:
|
||||||
html = '<div id="{}" class="{}">{}' + filename + '</div>'
|
html = '<div id="{}" class="{}">{}' + filename + "</div>"
|
||||||
elif 'dir' in type_ or 'html' in subtype or 'unkown-file' in subtype:
|
elif "dir" in type_ or "html" in subtype or "unkown-file" in subtype:
|
||||||
html = '<div id="{}" class="{}">{}</div>'
|
html = '<div id="{}" class="{}">{}</div>'
|
||||||
else:
|
else:
|
||||||
html = '<div id="{}" class="{}">{}' + filename + '</div>'
|
html = '<div id="{}" class="{}">{}' + filename + "</div>"
|
||||||
|
|
||||||
return html.format(id_name, subtype, tag)
|
return html.format(id_name, subtype, tag)
|
||||||
|
|
||||||
@ -80,140 +65,159 @@ def check_distribusi_index(args, index):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if not args.force:
|
if not args.force:
|
||||||
with open(index, 'r') as f:
|
with open(index, "r") as f:
|
||||||
if '<meta name="generator" content="distribusi" />' in f.read():
|
if '<meta name="generator" content="distribusi" />' in f.read():
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
if args.verbose:
|
if args.verbose:
|
||||||
print(index, 'not generated by distribusi, skipping')
|
print(index, "not generated by distribusi, skipping")
|
||||||
return False
|
return False
|
||||||
elif args.force:
|
elif args.force:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def write_index(args,index, html, html_head, html_footer):
|
|
||||||
with open(index, 'w') as f:
|
def write_index(args, index, html, html_head, html_footer):
|
||||||
|
with open(index, "w") as index_file:
|
||||||
if not args.no_template:
|
if not args.no_template:
|
||||||
if args.style:
|
if args.style:
|
||||||
fs = open(args.style, "r")
|
file_style = open(args.style, "r")
|
||||||
style = fs.read()
|
style = file_style.read()
|
||||||
styled_html_head = html_head % style
|
styled_html_head = html_head % style
|
||||||
else:
|
else:
|
||||||
styled_html_head = html_head % ''
|
styled_html_head = html_head % ""
|
||||||
f.write(styled_html_head)
|
index_file.write(styled_html_head)
|
||||||
|
|
||||||
for line in html:
|
for line in html:
|
||||||
f.write(line + '\n')
|
index_file.write(line + "\n")
|
||||||
|
|
||||||
if not args.no_template:
|
if not args.no_template:
|
||||||
f.write(html_footer)
|
index_file.write(html_footer)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_text_files(name, full_path):
|
||||||
|
if name.endswith(".html") or subtype == "html":
|
||||||
|
subtype = "html"
|
||||||
|
# what types of text files to expand
|
||||||
|
tag = '<section id="{}">{}</section>'.format(
|
||||||
|
name, open(full_path).read()
|
||||||
|
)
|
||||||
|
elif subtype in CODE_TYPES or name.endswith(".txt"):
|
||||||
|
# if the plain text is code,
|
||||||
|
# which types do we wrap in pre-tags?
|
||||||
|
tag = "<pre>" + open(full_path).read() + "</pre>"
|
||||||
|
else:
|
||||||
|
subtype = subtype + " unkown-file"
|
||||||
|
tag = "<a href='{}'>{}</a>"
|
||||||
|
# a = FILE_TYPES[type_]
|
||||||
|
return subtype, tag
|
||||||
|
|
||||||
|
|
||||||
|
def handle_image_files(name, full_path, args):
|
||||||
|
if args.thumbnail:
|
||||||
|
caption = ""
|
||||||
|
thumbnail_filename = thumbnail(full_path, name, args)
|
||||||
|
if thumbnail_filename is None:
|
||||||
|
return
|
||||||
|
if args.captions:
|
||||||
|
caption = caption(full_path)
|
||||||
|
return f"<figure><a href='{name}'><img class='thumbnail' src='{thumbnail_filename}'></a><figcaption>{caption}</figcaption></figure>"
|
||||||
|
|
||||||
|
return FILE_TYPES[type_].format(name, caption)
|
||||||
|
|
||||||
|
|
||||||
|
def remove_index_html(root, files):
|
||||||
|
index = os.path.join(root, "index.html")
|
||||||
|
if "index.html" in files:
|
||||||
|
try:
|
||||||
|
if check_distribusi_index(args, index):
|
||||||
|
if args.verbose:
|
||||||
|
print("Removing index.html from", root)
|
||||||
|
os.remove(index)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def remove_hidden_files_and_folders(dirs, files):
|
||||||
|
dirs = list(filter(lambda d: not d.startswith("."), dirs))
|
||||||
|
files = list(filter(lambda f: not f.startswith("."), files))
|
||||||
|
return dirs, files
|
||||||
|
|
||||||
|
|
||||||
def distribusify(args, directory): # noqa
|
def distribusify(args, directory): # noqa
|
||||||
for root, dirs, files in os.walk(directory):
|
for root, dirs, files in os.walk(directory):
|
||||||
|
html = []
|
||||||
|
|
||||||
if args.exclude_directory:
|
if args.exclude_directory:
|
||||||
if args.verbose:
|
if args.verbose:
|
||||||
print('Excluding directory:', ", ".join(args.exclude_directory))
|
print("Excluding directory:", ", ".join(args.exclude_directory))
|
||||||
dirs[:] = [d for d in dirs if d not in args.exclude_directory]
|
dirs[:] = [d for d in dirs if d not in args.exclude_directory]
|
||||||
|
|
||||||
if args.no_hidden:
|
if args.no_hidden:
|
||||||
dirs = list(filter(lambda d: not d.startswith('.'), dirs))
|
dirs, files = remove_hidden_files_and_folders(dirs, files)
|
||||||
files = list(filter(lambda f: not f.startswith('.'), files))
|
|
||||||
|
|
||||||
dirs.sort()
|
|
||||||
files.sort()
|
|
||||||
|
|
||||||
if not args.remove_index:
|
|
||||||
html = []
|
|
||||||
|
|
||||||
if args.verbose:
|
|
||||||
print('Generating directory listing for', root)
|
|
||||||
|
|
||||||
for name in sorted(files):
|
|
||||||
|
|
||||||
if 'index.html' not in name:
|
|
||||||
full_path = os.path.join(root, name)
|
|
||||||
mime = MIME_TYPE.from_file(full_path)
|
|
||||||
# example: MIME plain/text becomes 'type' plain 'subtype' text
|
|
||||||
type_, subtype = mime.split('/')
|
|
||||||
|
|
||||||
caption = name
|
|
||||||
|
|
||||||
if args.verbose:
|
|
||||||
print('Found', name, 'as', mime)
|
|
||||||
|
|
||||||
if type_ in FILE_TYPES:
|
|
||||||
|
|
||||||
a = FILE_TYPES[type_].format(name, caption)
|
|
||||||
|
|
||||||
# expansion for different kind of text files
|
|
||||||
if type_ == 'text':
|
|
||||||
if name.endswith('.html') or subtype == 'html':
|
|
||||||
subtype = 'html'
|
|
||||||
# what types of text files to expand
|
|
||||||
a = '<section id="{}">{}</section>'.format(name, open(full_path).read())
|
|
||||||
elif subtype in CODE_TYPES or name.endswith('.txt'):
|
|
||||||
# if the plain text is code,
|
|
||||||
# which types do we wrap in pre-tags?
|
|
||||||
a = "<pre>" + open(full_path).read() + "</pre>"
|
|
||||||
else:
|
|
||||||
subtype = subtype+' unkown-file'
|
|
||||||
a = "<a href='{}'>{}</a>"
|
|
||||||
# a = FILE_TYPES[type_]
|
|
||||||
|
|
||||||
if type_ == 'image':
|
|
||||||
if args.thumbnail:
|
|
||||||
a = thumbnail(full_path, name, args)
|
|
||||||
if args.no_filenames:
|
|
||||||
caption = ""
|
|
||||||
a = FILE_TYPES[type_].format(name, caption)
|
|
||||||
if args.captions:
|
|
||||||
caption = caption(full_path)
|
|
||||||
a = FILE_TYPES[type_].format(name, caption)
|
|
||||||
|
|
||||||
if subtype in SUB_TYPES:
|
|
||||||
a = SUB_TYPES[subtype]
|
|
||||||
|
|
||||||
if type_ not in FILE_TYPES and subtype not in SUB_TYPES:
|
|
||||||
# catch exceptions not yet defined in FILE_TYPES or SUB_TYPES
|
|
||||||
a = "<a href='{}'>{}</a>"
|
|
||||||
if args.verbose:
|
|
||||||
message = 'not in list of file types, adding as plain href: \n'
|
|
||||||
print(type_, subtype, message, name)
|
|
||||||
subtype = subtype + ' unkown-file'
|
|
||||||
|
|
||||||
a = a.replace('{}', name)
|
|
||||||
|
|
||||||
html.append(div(args, type_, subtype, a, name))
|
|
||||||
|
|
||||||
if root != directory:
|
|
||||||
if args.menu_with_index:
|
|
||||||
html.append('<a href="../index.html">../</a>')
|
|
||||||
else:
|
|
||||||
html.append('<a href="../">../</a>')
|
|
||||||
|
|
||||||
for name in dirs:
|
|
||||||
if args.menu_with_index:
|
|
||||||
a = "<a href='{}/index.html'>{}</a>".replace('{}', name)
|
|
||||||
else:
|
|
||||||
a = "<a href='{}'>{}/</a>".replace('{}', name)
|
|
||||||
|
|
||||||
html.insert(0, div(args, 'dir', 'dir', a, 'folder'))
|
|
||||||
|
|
||||||
index = os.path.join(root, 'index.html')
|
|
||||||
if os.path.exists(index):
|
|
||||||
if check_distribusi_index(args, index):
|
|
||||||
write_index(args,index,html, html_head, html_footer)
|
|
||||||
elif not os.path.exists(index):
|
|
||||||
write_index(args,index,html, html_head, html_footer)
|
|
||||||
|
|
||||||
if args.remove_index:
|
if args.remove_index:
|
||||||
index = os.path.join(root, 'index.html')
|
remove_index_html(root, files)
|
||||||
if 'index.html' in files:
|
|
||||||
try:
|
if args.verbose:
|
||||||
if check_distribusi_index(args, index):
|
print("Generating directory listing for", root)
|
||||||
if args.verbose:
|
|
||||||
print('Removing index.html from', root)
|
for name in sorted(files):
|
||||||
os.remove(index)
|
if "index.html" in name:
|
||||||
except Exception as e:
|
continue
|
||||||
print(e)
|
|
||||||
|
if name.endswith("_thumbnail.jpg"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
full_path = os.path.join(root, name)
|
||||||
|
mime = MIME_TYPE.from_file(full_path)
|
||||||
|
type_, subtype = mime.split("/")
|
||||||
|
caption = name
|
||||||
|
|
||||||
|
if args.verbose:
|
||||||
|
print("Found", name, "as", mime)
|
||||||
|
if type_ in FILE_TYPES:
|
||||||
|
match type_:
|
||||||
|
case "text":
|
||||||
|
subtype, tag = handle_text_files(name, full_path)
|
||||||
|
case "image":
|
||||||
|
tag = handle_image_files(name, full_path, args)
|
||||||
|
if tag is None:
|
||||||
|
continue
|
||||||
|
case _:
|
||||||
|
tag = FILE_TYPES[type_].format(name, caption)
|
||||||
|
|
||||||
|
if subtype in SUB_TYPES:
|
||||||
|
tag = SUB_TYPES[subtype]
|
||||||
|
|
||||||
|
if type_ not in FILE_TYPES and subtype not in SUB_TYPES:
|
||||||
|
# catch exceptions not yet defined in FILE_TYPES or SUB_TYPES
|
||||||
|
tag = "<a href='{}'>{}</a>"
|
||||||
|
if args.verbose:
|
||||||
|
message = "not in list of file types, adding as plain href: \n"
|
||||||
|
print(type_, subtype, message, name)
|
||||||
|
subtype = subtype + " unkown-file"
|
||||||
|
|
||||||
|
tag = tag.replace("{}", name)
|
||||||
|
html.append(format_div(args, type_, subtype, tag, name))
|
||||||
|
|
||||||
|
if root != directory:
|
||||||
|
if args.menu_with_index:
|
||||||
|
html.append('<a href="../index.html">../</a>')
|
||||||
|
else:
|
||||||
|
html.append('<a href="../">../</a>')
|
||||||
|
|
||||||
|
for name in sorted(dirs):
|
||||||
|
if args.menu_with_index:
|
||||||
|
tag = "<a href='{}/index.html'>{}</a>".replace("{}", name)
|
||||||
|
else:
|
||||||
|
tag = "<a href='{}'>{}/</a>".replace("{}", name)
|
||||||
|
|
||||||
|
html.insert(0, format_div(args, "dir", "dir", tag, "folder"))
|
||||||
|
|
||||||
|
index = os.path.join(root, "index.html")
|
||||||
|
if os.path.exists(index):
|
||||||
|
if check_distribusi_index(args, index):
|
||||||
|
write_index(args, index, html, html_head, html_footer)
|
||||||
|
elif not os.path.exists(index):
|
||||||
|
write_index(args, index, html, html_head, html_footer)
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
CODE_TYPES = ['x-c', 'x-shellscript', 'x-python']
|
CODE_TYPES = ["x-c", "x-shellscript", "x-python"]
|
||||||
|
|
||||||
FILE_TYPES = {
|
FILE_TYPES = {
|
||||||
'image': '<figure><img class="image" src="{}"><figcaption>{}</figcaption></figure>',
|
"image": '<figure><img class="image" src="{}"><figcaption>{}</figcaption></figure>',
|
||||||
'text': '<a href="{}" class="text">{}</a>',
|
"text": '<a href="{}" class="text">{}</a>',
|
||||||
'video': ('<video controls>' '<source src="{}"></video>'),
|
"video": ("<video controls>" '<source src="{}"></video>'),
|
||||||
'audio': ('<audio controls class="audio">' '<source src="{}"></audio>'),
|
"audio": ('<audio controls class="audio">' '<source src="{}"></audio>'),
|
||||||
}
|
}
|
||||||
|
|
||||||
SUB_TYPES = {
|
SUB_TYPES = {
|
||||||
'pdf': (
|
"pdf": (
|
||||||
'<object data="{}" class="pdf" type="application/pdf">'
|
'<object data="{}" class="pdf" type="application/pdf">'
|
||||||
'<embed src="{}" type="application/pdf" /></object>')
|
'<embed src="{}" type="application/pdf" /></object>'
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
30
setup.py
30
setup.py
@ -1,28 +1,28 @@
|
|||||||
from setuptools import find_packages, setup
|
from setuptools import find_packages, setup
|
||||||
|
|
||||||
dependencies = ['pillow >= 10.3.0', 'python-magic >= 0.4.15, < 1.0']
|
dependencies = ["pillow >= 10.3.0", "python-magic >= 0.4.15, < 1.0", "exif >= 1.6.0"]
|
||||||
|
|
||||||
with open('README.md', 'r') as handle:
|
with open("README.md", "r") as handle:
|
||||||
long_description = handle.read()
|
long_description = handle.read()
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='distribusi',
|
name="distribusi",
|
||||||
version='0.0.10',
|
version="0.0.11",
|
||||||
url='https://git.vvvvvvaria.org/varia/distribusi',
|
url="https://git.vvvvvvaria.org/varia/distribusi",
|
||||||
license='GPLv3',
|
license="GPLv3",
|
||||||
author='Varia',
|
author="Varia",
|
||||||
description=(
|
description=(
|
||||||
'Distribusi is a content management system for '
|
"Distribusi is a content management system for "
|
||||||
'the web that produces static pages based on '
|
"the web that produces static pages based on "
|
||||||
'the file system.'
|
"the file system."
|
||||||
),
|
),
|
||||||
long_description=long_description,
|
long_description=long_description,
|
||||||
long_description_content_type='text/markdown',
|
long_description_content_type="text/markdown",
|
||||||
packages=find_packages(exclude=['tests']),
|
packages=find_packages(exclude=["tests"]),
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
zip_safe=False,
|
zip_safe=False,
|
||||||
platforms='any',
|
platforms="any",
|
||||||
install_requires=dependencies,
|
install_requires=dependencies,
|
||||||
entry_points={'console_scripts': ['distribusi = distribusi.cli:cli_entrypoint']},
|
entry_points={"console_scripts": ["distribusi = distribusi.cli:cli_entrypoint"]},
|
||||||
classifiers=['Programming Language :: Python :: 3', 'Environment :: Console'],
|
classifiers=["Programming Language :: Python :: 3", "Environment :: Console"],
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user