mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 18:24:30 -04:00
Fix thumbnail type detection in lrf.meta and initial integration of BBeBook into libprs500
This commit is contained in:
parent
ee2c0ca1b0
commit
268405d35c
@ -14,8 +14,8 @@
|
|||||||
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
""" The GUI to libprs500. Also has ebook library management features. """
|
""" The GUI to libprs500. Also has ebook library management features. """
|
||||||
__docformat__ = "epytext"
|
__docformat__ = "epytext"
|
||||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||||
APP_TITLE = "libprs500"
|
APP_TITLE = "libprs500"
|
||||||
|
|
||||||
import pkg_resources, sys, os, re, StringIO, traceback
|
import pkg_resources, sys, os, re, StringIO, traceback
|
||||||
from PyQt4.uic.Compiler import compiler
|
from PyQt4.uic.Compiler import compiler
|
||||||
|
@ -87,7 +87,7 @@
|
|||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="text" >
|
<property name="text" >
|
||||||
<string>For help visit <a href="http://libprs500.kovidgoyal.net">http://libprs500.kovidgoyal.net</a><br><br><b>libprs500</b> was created by <b>Kovid Goyal</b> &copy; 2006<br>%1 %2 %3</string>
|
<string>For help visit <a href="https://libprs500.kovidgoyal.net/wiki/GuiUsage">http://libprs500.kovidgoyal.net</a><br><br><b>libprs500</b> was created by <b>Kovid Goyal</b> &copy; 2006<br>%1 %2 %3</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="textFormat" >
|
<property name="textFormat" >
|
||||||
<enum>Qt::RichText</enum>
|
<enum>Qt::RichText</enum>
|
||||||
|
BIN
libprs500/lrf/BBeBook-0.2.jar
Normal file
BIN
libprs500/lrf/BBeBook-0.2.jar
Normal file
Binary file not shown.
191
libprs500/lrf/makelrf.py
Executable file
191
libprs500/lrf/makelrf.py
Executable file
@ -0,0 +1,191 @@
|
|||||||
|
## Copyright (C) 2006 Kovid Goyal kovid@kovidgoyal.net
|
||||||
|
## This program is free software; you can redistribute it and/or modify
|
||||||
|
## it under the terms of the GNU General Public License as published by
|
||||||
|
## the Free Software Foundation; either version 2 of the License, or
|
||||||
|
## (at your option) any later version.
|
||||||
|
##
|
||||||
|
## This program is distributed in the hope that it will be useful,
|
||||||
|
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
## GNU General Public License for more details.
|
||||||
|
##
|
||||||
|
## You should have received a copy of the GNU General Public License along
|
||||||
|
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
import hashlib
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
import pkg_resources
|
||||||
|
import subprocess
|
||||||
|
from tempfile import mkdtemp
|
||||||
|
from optparse import OptionParser
|
||||||
|
import xml.dom.minidom as dom
|
||||||
|
|
||||||
|
from libprs500.lrf.meta import LRFException, LRFMetaFile
|
||||||
|
from libprs500.ptempfile import PersistentTemporaryFile
|
||||||
|
|
||||||
|
_bbebook = 'BBeBook-0.2.jar'
|
||||||
|
|
||||||
|
def generate_thumbnail(path):
|
||||||
|
""" Generate a JPEG thumbnail of size ~ 128x128 (aspect ratio preserved)"""
|
||||||
|
try:
|
||||||
|
import Image
|
||||||
|
except ImportError:
|
||||||
|
raise LRFException("Unable to initialize Python Imaging Library." \
|
||||||
|
"Thumbnail generation is disabled")
|
||||||
|
im = Image.open(path)
|
||||||
|
im.thumbnail((128, 128), Image.ANTIALIAS)
|
||||||
|
thumb = PersistentTemporaryFile(prefix="makelrf_", suffix=".jpeg")
|
||||||
|
thumb.close()
|
||||||
|
im = im.convert()
|
||||||
|
im.save(thumb.name)
|
||||||
|
return thumb
|
||||||
|
|
||||||
|
def create_xml(cfg):
|
||||||
|
doc = dom.getDOMImplementation().createDocument(None, None, None)
|
||||||
|
def add_field(parent, tag, value):
|
||||||
|
elem = doc.createElement(tag)
|
||||||
|
elem.appendChild(doc.createTextNode(value))
|
||||||
|
parent.appendChild(elem)
|
||||||
|
|
||||||
|
info = doc.createElement('Info')
|
||||||
|
info.setAttribute('version', '1.0')
|
||||||
|
book_info = doc.createElement('BookInfo')
|
||||||
|
doc_info = doc.createElement('DocInfo')
|
||||||
|
info.appendChild(book_info)
|
||||||
|
info.appendChild(doc_info)
|
||||||
|
add_field(book_info, 'File', cfg['File'])
|
||||||
|
add_field(doc_info, 'Output', cfg['Output'])
|
||||||
|
for field in ['Title', 'Author', 'BookID', 'Publisher', 'Label', \
|
||||||
|
'Category', 'Classification', 'Icon', 'Cover', 'FreeText']:
|
||||||
|
if cfg.has_key(field):
|
||||||
|
add_field(book_info, field, cfg[field])
|
||||||
|
add_field(doc_info, 'Language', 'en')
|
||||||
|
add_field(doc_info, 'Creator', _bbebook)
|
||||||
|
add_field(doc_info, 'CreationDate', time.strftime('%Y-%m-%d', time.gmtime()))
|
||||||
|
doc.appendChild(info)
|
||||||
|
return doc.toxml()
|
||||||
|
|
||||||
|
def makelrf(author=None, title=None, \
|
||||||
|
thumbnail=None, src=None, odir=".",\
|
||||||
|
rasterize=True, cover=None):
|
||||||
|
src = os.path.normpath(os.path.abspath(src))
|
||||||
|
bbebook = pkg_resources.resource_filename(__name__, _bbebook)
|
||||||
|
if not os.access(src, os.R_OK):
|
||||||
|
raise LRFException("Unable to read from file: " + src)
|
||||||
|
if thumbnail:
|
||||||
|
thumb = os.path.abspath(options.thumbnail)
|
||||||
|
if not os.access(thumb, os.R_OK):
|
||||||
|
raise LRFException("Unable to read from " + thumb)
|
||||||
|
else:
|
||||||
|
thumb = pkg_resources.resource_filename(__name__, 'cover.jpg')
|
||||||
|
|
||||||
|
if not author:
|
||||||
|
author = "Unknown"
|
||||||
|
if not title:
|
||||||
|
title = os.path.basename(src)
|
||||||
|
label = os.path.basename(src)
|
||||||
|
id = hashlib.md5(os.path.basename(label)).hexdigest()
|
||||||
|
name, ext = os.path.splitext(label)
|
||||||
|
cwd = os.path.dirname(src)
|
||||||
|
dirpath = None
|
||||||
|
try:
|
||||||
|
if ext == ".rar":
|
||||||
|
dirpath = mkdtemp('','makelrf')
|
||||||
|
cwd = dirpath
|
||||||
|
cmd = " ".join(["unrar", "e", '"'+src+'"'])
|
||||||
|
proc = subprocess.Popen(cmd, cwd=cwd, shell=True, stderr=subprocess.PIPE)
|
||||||
|
if proc.wait():
|
||||||
|
raise LRFException("unrar failed with error:\n\n" + \
|
||||||
|
proc.stderr.read())
|
||||||
|
path, msize = None, 0
|
||||||
|
for root, dirs, files in os.walk(dirpath):
|
||||||
|
for name in files:
|
||||||
|
if os.path.splitext(name)[1] == ".html":
|
||||||
|
size = os.stat(os.path.join(root, name)).st_size
|
||||||
|
if size > msize:
|
||||||
|
msize, path = size, os.path.join(root, name)
|
||||||
|
if not path:
|
||||||
|
raise LRFException("Could not find .html file in rar archive")
|
||||||
|
src = path
|
||||||
|
|
||||||
|
name = re.sub("\s", "_", name)
|
||||||
|
name = os.path.abspath(os.path.join(odir, name)) + ".lrf"
|
||||||
|
cfg = { 'File' : src, 'Output' : name, 'Label' : label, 'BookID' : id, \
|
||||||
|
'Author' : author, 'Title' : title, 'Publisher' : 'Unknown' \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if cover:
|
||||||
|
cover = os.path.normpath(os.path.abspath(cover))
|
||||||
|
try:
|
||||||
|
thumbf = generate_thumbnail(cover)
|
||||||
|
thumb = thumbf.name
|
||||||
|
except Exception, e:
|
||||||
|
print >> sys.stderr, "WARNING: Unable to generate thumbnail:\n", \
|
||||||
|
str(e)
|
||||||
|
thumb = cover
|
||||||
|
cfg['Cover'] = cover
|
||||||
|
cfg['Icon'] = thumb
|
||||||
|
config = PersistentTemporaryFile(prefix='makelrf_', suffix='.xml')
|
||||||
|
config.write(create_xml(cfg))
|
||||||
|
config.close()
|
||||||
|
jar = '-jar "' + bbebook + '"'
|
||||||
|
cmd = " ".join(["java", jar, "-r" if rasterize else "", '"'+config.name+'"'])
|
||||||
|
proc = subprocess.Popen(cmd, \
|
||||||
|
cwd=cwd, shell=True, stderr=subprocess.PIPE)
|
||||||
|
if proc.wait():
|
||||||
|
raise LRFException("BBeBook failed with error:\n\n" + \
|
||||||
|
proc.stderr.read())
|
||||||
|
# Needed as BBeBook-0.2 doesn't handle non GIF thumbnails correctly.
|
||||||
|
lrf = open(name, "r+b")
|
||||||
|
LRFMetaFile(lrf).fix_thumbnail_type()
|
||||||
|
lrf.close()
|
||||||
|
return name
|
||||||
|
finally:
|
||||||
|
if dirpath:
|
||||||
|
shutil.rmtree(dirpath, True)
|
||||||
|
|
||||||
|
def main(cargs=None):
|
||||||
|
parser = OptionParser(usage=\
|
||||||
|
"""usage: %prog [options] mybook.[html|pdf|rar]
|
||||||
|
|
||||||
|
%prog converts mybook to mybook.lrf
|
||||||
|
If you specify a rar file you must have the unrar command line client
|
||||||
|
installed. makelrf assumes the rar file is an archive containing the
|
||||||
|
html file you want converted."""\
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_option("-t", "--title", action="store", type="string", \
|
||||||
|
dest="title", help="Set the book title")
|
||||||
|
parser.add_option("-a", "--author", action="store", type="string", \
|
||||||
|
dest="author", help="Set the author")
|
||||||
|
parser.add_option('-r', '--rasterize', action='store_true', \
|
||||||
|
dest="rasterize",
|
||||||
|
help="Convert pdfs into image files.")
|
||||||
|
parser.add_option('-c', '--cover', action='store', dest='cover',\
|
||||||
|
help="Path to a graphic that will be set as the cover. "\
|
||||||
|
"If it is specified the thumbnail is automatically "\
|
||||||
|
"generated from it")
|
||||||
|
parser.add_option("--thumbnail", action="store", type="string", \
|
||||||
|
dest="thumbnail", \
|
||||||
|
help="Path to a graphic that will be set as the thumbnail")
|
||||||
|
if not cargs:
|
||||||
|
cargs = sys.argv
|
||||||
|
options, args = parser.parse_args()
|
||||||
|
if len(args) != 1:
|
||||||
|
parser.print_help()
|
||||||
|
sys.exit(1)
|
||||||
|
src = args[0]
|
||||||
|
root, ext = os.path.splitext(src)
|
||||||
|
if ext not in ['.html', '.pdf', '.rar']:
|
||||||
|
print >> sys.stderr, "Can only convert files ending in .html|.pdf|.rar"
|
||||||
|
parser.print_help()
|
||||||
|
sys.exit(1)
|
||||||
|
name = makelrf(author=options.author, title=options.title, \
|
||||||
|
thumbnail=options.thumbnail, src=src, cover=options.cover, \
|
||||||
|
rasterize=options.rasterize)
|
||||||
|
print "LRF generated:", name
|
@ -155,7 +155,7 @@ class xml_field(object):
|
|||||||
class LRFMetaFile(object):
|
class LRFMetaFile(object):
|
||||||
""" Has properties to read and write all Meta information in a LRF file. """
|
""" Has properties to read and write all Meta information in a LRF file. """
|
||||||
# The first 8 bytes of all valid LRF files
|
# The first 8 bytes of all valid LRF files
|
||||||
LRF_HEADER = u'LRF'.encode('utf-16')[2:]+'\0\0'
|
LRF_HEADER = 'LRF'.encode('utf-16le')+'\0\0'
|
||||||
|
|
||||||
lrf_header = fixed_stringfield(length=8, start=0)
|
lrf_header = fixed_stringfield(length=8, start=0)
|
||||||
version = field(fmt=WORD, start=8)
|
version = field(fmt=WORD, start=8)
|
||||||
@ -281,6 +281,19 @@ class LRFMetaFile(object):
|
|||||||
return self.info_start+ self.compressed_info_size-4
|
return self.info_start+ self.compressed_info_size-4
|
||||||
return { "fget":fget, "doc":doc }
|
return { "fget":fget, "doc":doc }
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _detect_thumbnail_type(cls, slice):
|
||||||
|
""" @param slice: The first 16 bytes of the thumbnail """
|
||||||
|
ttype = 0x14 # GIF
|
||||||
|
if "PNG" in slice:
|
||||||
|
ttype = 0x12
|
||||||
|
if "BM" in slice:
|
||||||
|
ttype = 0x13
|
||||||
|
if "JFIF" in slice:
|
||||||
|
ttype = 0x11
|
||||||
|
return ttype
|
||||||
|
|
||||||
|
|
||||||
@safe_property
|
@safe_property
|
||||||
def thumbnail():
|
def thumbnail():
|
||||||
doc = \
|
doc = \
|
||||||
@ -299,6 +312,7 @@ class LRFMetaFile(object):
|
|||||||
if self.version <= 800:
|
if self.version <= 800:
|
||||||
raise LRFException("Cannot store thumbnails in LRF files \
|
raise LRFException("Cannot store thumbnails in LRF files \
|
||||||
of version <= 800")
|
of version <= 800")
|
||||||
|
slice = data[0:16]
|
||||||
orig_size = self.thumbnail_size
|
orig_size = self.thumbnail_size
|
||||||
self._file.seek(self.toc_object_offset)
|
self._file.seek(self.toc_object_offset)
|
||||||
toc = self._file.read(self.object_index_offset - self.toc_object_offset)
|
toc = self._file.read(self.object_index_offset - self.toc_object_offset)
|
||||||
@ -314,14 +328,7 @@ class LRFMetaFile(object):
|
|||||||
self._file.write(objects)
|
self._file.write(objects)
|
||||||
self._file.flush()
|
self._file.flush()
|
||||||
self._file.truncate() # Incase old thumbnail was bigger than new
|
self._file.truncate() # Incase old thumbnail was bigger than new
|
||||||
ttype = 0x14
|
self.thumbnail_type = self._detect_thumbnail_type(slice)
|
||||||
if data[1:4] == "PNG":
|
|
||||||
ttype = 0x12
|
|
||||||
if data[0:2] == "BM":
|
|
||||||
ttype = 0x13
|
|
||||||
if data[0:4] == "JIFF":
|
|
||||||
ttype = 0x11
|
|
||||||
self.thumbnail_type = ttype
|
|
||||||
# Needed as new thumbnail may have different size than old thumbnail
|
# Needed as new thumbnail may have different size than old thumbnail
|
||||||
self.update_object_offsets(self.toc_object_offset - orig_offset)
|
self.update_object_offsets(self.toc_object_offset - orig_offset)
|
||||||
return { "fget":fget, "fset":fset, "doc":doc }
|
return { "fget":fget, "fset":fset, "doc":doc }
|
||||||
@ -392,6 +399,11 @@ class LRFMetaFile(object):
|
|||||||
self._file.flush()
|
self._file.flush()
|
||||||
|
|
||||||
def thumbail_extension(self):
|
def thumbail_extension(self):
|
||||||
|
"""
|
||||||
|
Return the extension for the thumbnail image type as specified
|
||||||
|
by L{self.thumbnail_type}. If the LRF file was created by buggy
|
||||||
|
software, the extension maye be incorrect. See L{self.fix_thumbnail_type}.
|
||||||
|
"""
|
||||||
ext = "gif"
|
ext = "gif"
|
||||||
ttype = self.thumbnail_type
|
ttype = self.thumbnail_type
|
||||||
if ttype == 0x11:
|
if ttype == 0x11:
|
||||||
@ -402,6 +414,15 @@ class LRFMetaFile(object):
|
|||||||
ext = "bm"
|
ext = "bm"
|
||||||
return ext
|
return ext
|
||||||
|
|
||||||
|
def fix_thumbnail_type(self):
|
||||||
|
"""
|
||||||
|
Attempt to guess the thumbnail image format and set
|
||||||
|
L{self.thumbnail_type} accordingly.
|
||||||
|
"""
|
||||||
|
slice = self.thumbnail[0:16]
|
||||||
|
self.thumbnail_type = self._detect_thumbnail_type(slice)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
import sys, os.path
|
import sys, os.path
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
|
17
prs-500.e4p
17
prs-500.e4p
@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE Project SYSTEM "Project-4.0.dtd">
|
<!DOCTYPE Project SYSTEM "Project-4.0.dtd">
|
||||||
<!-- eric4 project file for project prs-500 -->
|
<!-- eric4 project file for project prs-500 -->
|
||||||
<!-- Saved: 2006-12-08, 23:24:29 -->
|
<!-- Saved: 2007-01-03, 23:14:45 -->
|
||||||
<!-- Copyright (C) 2006 Kovid Goyal, kovid@kovidgoyal.net -->
|
<!-- Copyright (C) 2007 Kovid Goyal, kovid@kovidgoyal.net -->
|
||||||
<Project version="4.0">
|
<Project version="4.0">
|
||||||
<ProgLanguage mixed="0">Python</ProgLanguage>
|
<ProgLanguage mixed="0">Python</ProgLanguage>
|
||||||
<UIType>Qt4</UIType>
|
<UIType>Qt4</UIType>
|
||||||
@ -84,6 +84,15 @@
|
|||||||
<Dir>gui</Dir>
|
<Dir>gui</Dir>
|
||||||
<Name>widgets.py</Name>
|
<Name>widgets.py</Name>
|
||||||
</Source>
|
</Source>
|
||||||
|
<Source>
|
||||||
|
<Dir>libprs500</Dir>
|
||||||
|
<Dir>lrf</Dir>
|
||||||
|
<Name>makelrf.py</Name>
|
||||||
|
</Source>
|
||||||
|
<Source>
|
||||||
|
<Dir>libprs500</Dir>
|
||||||
|
<Name>ptempfile.py</Name>
|
||||||
|
</Source>
|
||||||
</Sources>
|
</Sources>
|
||||||
<Forms>
|
<Forms>
|
||||||
<Form>
|
<Form>
|
||||||
@ -230,10 +239,10 @@
|
|||||||
</VcsOtherData>
|
</VcsOtherData>
|
||||||
</Vcs>
|
</Vcs>
|
||||||
<FiletypeAssociations>
|
<FiletypeAssociations>
|
||||||
<FiletypeAssociation pattern="*.py" type="SOURCES" />
|
|
||||||
<FiletypeAssociation pattern="*.ui.h" type="FORMS" />
|
<FiletypeAssociation pattern="*.ui.h" type="FORMS" />
|
||||||
<FiletypeAssociation pattern="*.idl" type="INTERFACES" />
|
|
||||||
<FiletypeAssociation pattern="*.ui" type="FORMS" />
|
<FiletypeAssociation pattern="*.ui" type="FORMS" />
|
||||||
|
<FiletypeAssociation pattern="*.idl" type="INTERFACES" />
|
||||||
|
<FiletypeAssociation pattern="*.py" type="SOURCES" />
|
||||||
<FiletypeAssociation pattern="*.ptl" type="SOURCES" />
|
<FiletypeAssociation pattern="*.ptl" type="SOURCES" />
|
||||||
</FiletypeAssociations>
|
</FiletypeAssociations>
|
||||||
</Project>
|
</Project>
|
||||||
|
35
setup.py
35
setup.py
@ -13,18 +13,25 @@
|
|||||||
## with this program; if not, write to the Free Software Foundation, Inc.,
|
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
#!/usr/bin/env python2.5
|
#!/usr/bin/env python2.5
|
||||||
|
import sys
|
||||||
|
|
||||||
import ez_setup
|
import ez_setup
|
||||||
ez_setup.use_setuptools()
|
ez_setup.use_setuptools()
|
||||||
|
|
||||||
# Try to install the Python imaging library as the package name (PIL) doesn't match the distributionfile name, thus declaring itas a dependency is useless
|
# Try to install the Python imaging library as the package name (PIL) doesn't
|
||||||
#from setuptools.command.easy_install import main as easy_install
|
# match the distribution file name, thus declaring itas a dependency is useless
|
||||||
#try:
|
from setuptools.command.easy_install import main as easy_install
|
||||||
# try:
|
try:
|
||||||
# import Image
|
try:
|
||||||
# except ImportError:
|
import Image
|
||||||
# print "Trying to install thePython Imaging Library"
|
except ImportError:
|
||||||
# easy_install(["-f", "http://www.pythonware.com/products/pil/", "Imaging"])
|
print "Trying to install the Python Imaging Library"
|
||||||
#except: pass
|
easy_install(["-f", "http://www.pythonware.com/products/pil/", "Imaging"])
|
||||||
|
except Exception, e:
|
||||||
|
print >> sys.stderr, e
|
||||||
|
print >> sys.stderr, \
|
||||||
|
"WARNING: Could not install the Python Imaging Library.", \
|
||||||
|
"Some functionality will be unavailable"
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
@ -43,11 +50,15 @@ setup(
|
|||||||
author='Kovid Goyal',
|
author='Kovid Goyal',
|
||||||
author_email='kovid@kovidgoyal.net',
|
author_email='kovid@kovidgoyal.net',
|
||||||
url = 'http://libprs500.kovidgoyal.net',
|
url = 'http://libprs500.kovidgoyal.net',
|
||||||
package_data = { 'libprs500.gui' : ['*.ui'] },
|
package_data = { \
|
||||||
|
'libprs500.gui' : ['*.ui'], \
|
||||||
|
'libprs500.lrf' : ['*.jar', '*.jpg'] \
|
||||||
|
},
|
||||||
entry_points = {
|
entry_points = {
|
||||||
'console_scripts': [ \
|
'console_scripts': [ \
|
||||||
'prs500 = libprs500.cli.main:main', \
|
'prs500 = libprs500.cli.main:main', \
|
||||||
'lrf-meta = libprs500.lrf.meta:main' \
|
'lrf-meta = libprs500.lrf.meta:main', \
|
||||||
|
'makelrf = libprs500.lrf.makelrf:main'\
|
||||||
],
|
],
|
||||||
'gui_scripts' : [ 'prs500-gui = libprs500.gui.main:main']
|
'gui_scripts' : [ 'prs500-gui = libprs500.gui.main:main']
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user