Compare commits

..

24 Commits

Author SHA1 Message Date
f244255386 update urls to new github comictagger organization 2019-10-05 16:31:12 +02:00
254e2c25ee Brand new README file (#156) 2019-10-05 16:09:04 +02:00
7455cf17c8 fix broken drag & drop on macOS (#142) 2019-09-29 23:02:44 +01:00
d93cb50896 add version info to mac info_plist (#146) 2019-09-29 22:11:42 +01:00
3316cab775 fix travis regex 2019-09-28 17:05:15 +02:00
c01f00f6c3 multi platform build on travis (#145) 2019-09-28 17:01:05 +02:00
06ff25550e use setuptools_scm to handle version 2019-09-28 14:59:36 +02:00
1f7ef44556 remove obsolete download_url (https://git.io/JeZrE) 2019-09-28 14:57:09 +02:00
fabf2b4df6 Merge tag '1.2.0+2' into develop
1.2.0+2
2019-09-25 01:55:29 +02:00
0fbaeb861e Merge branch 'release/1.2.0+2' 2019-09-25 01:55:15 +02:00
3dcc04a318 try to fix appveyor deployment 2019-09-25 01:55:03 +02:00
933e053df3 Merge tag '1.2.0+1' into develop
1.2.0+1
2019-09-25 01:30:32 +02:00
5f22a583e8 Merge branch 'release/1.2.0+1' 2019-09-25 01:30:03 +02:00
3174b49d94 bump version to force appveyor deploy 2019-09-25 01:29:50 +02:00
93ce311359 Release 1.2.0 2019-09-25 00:51:28 +02:00
bc43c5e329 Release 1.2.0 2019-09-25 00:50:50 +02:00
9bf7aa20fb bump version to 1.2.0 2019-09-25 00:49:52 +02:00
5416bb15c3 Appveyor GitHub release (#139) 2019-09-24 23:36:08 +01:00
562a659195 Travis build for macOS build (#100) 2019-09-24 23:30:23 +01:00
1d3d6e2741 bump version 1.1.32-rc1 2019-09-22 12:47:19 +01:00
c9724527b5 Fixed TLS version for the Comic Vine (#135)
* Fixed TLS version for the comicvine

* Fixed TLS version for the Comic Vine - Auto-Identify and Auto-Tag functions
2019-09-22 12:40:59 +01:00
2891209b4e bump version 2019-02-04 20:27:37 +01:00
5b87e19d3e Limit Comic Vine search result queries (#119)
* Tweaked search string based on new comic vine search behavior
Placated Beaufitul Soup by passing the parser

* Limit search results fetching after recent Comic Vine changes.
Also, minor debug comment tweaks.
2019-02-04 20:16:44 +01:00
tlc
674e24fc41 Enable Zip64 (#96) 2018-09-20 00:09:24 +02:00
20 changed files with 185 additions and 111 deletions

8
.gitignore vendored
View File

@ -3,4 +3,10 @@
/dist
*.pyc
/.vscode
venv
venv
*.o
*.a
*.so
build/
ctversion.py
.eggs

42
.travis.yml Normal file
View File

@ -0,0 +1,42 @@
language: python
branches:
only:
- develop
- /^\d+\.\d+\.\d+$/
env:
global:
- PYTHON=python
- PIP=pip
- SETUPTOOLS_SCM_PRETEND_VERSION=$TRAVIS_TAG
- MAKE=make
matrix:
include:
- os: linux
- os: osx
language: generic
osx_image: xcode8.3
env: PYTHON=python3 PIP=pip3 MACOSX_DEPLOYMENT_TARGET=10.11
- os: windows
language: bash
env: PATH=/C/Python37:/C/Python37/Scripts:$PATH MAKE=mingw32-make
before_install:
- if [ "$TRAVIS_OS_NAME" = "windows" ]; then choco install -y python mingw zip; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew upgrade python3 ; fi
install:
- $PIP install --upgrade setuptools
- $PIP install -r requirements.txt
script:
- $MAKE dist
deploy:
name: $TRAVIS_TAG
body: Released ComicTagger $TRAVIS_TAG
provider: releases
skip_cleanup: true
api_key:
secure: RgohcOJOfLhXXT12bMWaLwOqhe+ClSCYXjYuUJuWK4/E1fdd1xu1ebdQU+MI/R8cZ0Efz3sr2n3NkO/Aa8gN68xEfuF7RVRMm64P9oPrfZgGdsD6H43rU/6kN8bgaDRmCYpLTfXaJ+/gq0x1QDkhWJuceF2BYEGGvL0BvS/TUsLyjVxs8ujTplLyguXHNEv4/7Yz7SBNZZmUHjBuq/y+l8ds3ra9rSgAVAN1tMXoFKJPv+SNNkpTo5WUNMPzBnN041F1rzqHwYDLog2V7Krp9JkXzheRFdAr51/tJBYzEd8AtYVdYvaIvoO6A4PiTZ7MpsmcZZPAWqLQU00UTm/PhT/LVR+7+f8lOBG07RgNNHB+edjDRz3TAuqyuZl9wURWTZKTPuO49TkZMz7Wm0DRNZHvBm1IXLeSG7Tll2YL1+WpZNZg+Dhro2J1QD3vxDXafhMdTCB4z0q5aKpG93IT0p6oXOO0oEGOPZYbA2c5R3SXWSyqd1E1gdhbVjIZr59h++TEf1zz07tvWHqPuAF/Ly/j+dIcY2wj0EzRWaSASWgUpTnMljAkHtWhqDw4GXGDRkRUWRJl1d0/JyVqCeIdRzDQNl8/q7BcO3F1zqr1PgnYdz0lfwWxL1/ekw2vHOJE/GOdkyvX0aJrnaOV338mjJbfGHYv4ESc9ow1kdtIbiU=
file_glob: true
file: dist/*.zip
draft: true
on:
tags: true

View File

@ -1,11 +1,14 @@
VERSION_STR := $(shell python -c 'import comictaggerlib.ctversion; print( comictaggerlib.ctversion.version)')
PIP ?= pip
VERSION_STR := $(shell python setup.py --version)
ifeq ($(OS),Windows_NT)
OS_VERSION=win-$(PROCESSOR_ARCHITECTURE)
APP_NAME=comictagger.exe
FINAL_NAME=ComicTagger-$(VERSION_STR).exe
FINAL_NAME=ComicTagger-$(VERSION_STR)-$(OS_VERSION).exe
else ifeq ($(shell uname -s),Darwin)
OS_VERSION=osx-$(shell defaults read loginwindow SystemVersionStampAsString)-$(shell uname -m)
APP_NAME=ComicTagger.app
FINAL_NAME=ComicTagger-$(VERSION_STR).app
FINAL_NAME=ComicTagger-$(VERSION_STR)-$(OS_VERSION).app
else
APP_NAME=comictagger
FINAL_NAME=ComicTagger-$(VERSION_STR)
@ -28,6 +31,7 @@ clean:
rm -f unrar/libunrar.so unrar/libunrar.a unrar/unrar
rm -f comictaggerlib/libunrar.so
rm -rf comictaggerlib/ui/__pycache__
rm comitaggerlib/ctversion.py
pydist:
make clean
@ -51,5 +55,6 @@ else
endif
dist: unrar
$(PIP) install .
pyinstaller -y comictagger.spec
mv dist/$(APP_NAME) dist/$(FINAL_NAME)
cd dist && zip -r $(FINAL_NAME).zip $(APP_NAME)

View File

@ -1,17 +1,48 @@
A fork from the primary dev branch at https://github.com/davide-romanini/comictagger
[![Build Status](https://travis-ci.org/comictagger/comictagger.svg?branch=develop)](https://travis-ci.org/comictagger/comictagger)
[![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/comictagger/community)
[![Google Group](https://img.shields.io/badge/discuss-on%20groups-%23207de5)](https://groups.google.com/forum/#!forum/comictagger)
[![Twitter](https://img.shields.io/badge/%40comictagger-twitter-lightgrey)](https://twitter.com/comictagger)
[![Facebook](https://img.shields.io/badge/comictagger-facebook-lightgrey)](https://www.facebook.com/ComicTagger-139615369550787/)
Changes:
- Ported to Python 3
- Ported to PyQt5
- Added more application and GUI awareness of the unrar library, and removed references to the old scheme that used the unrar executable.
- Got setup.py working again to build sdist packages, suitable (I think) for PyPI. An install from the package will attempt to build unrar library. It should work on most Linux distros, and was tested on a Mac OSX system with dev tools from homebrew. If the library doesn't build, the GUI has instructions on where to download the library.
- Removed/changes obsolete links to old Google code website.
- Set a environment variable to scale the GUI on 4k displays
Notes:
- I did some testing with the pyinstaller build, and it worked on both platforms. I did encounter two problems:
- Mac build showed the wrong widget set. I found a solution here that seemed to work: https://stackoverflow.com/questions/48626999/packaging-with-pyinstaller-pyqt5-setstyle-ignored
- Windows build had problems grabbing images from ComicVine using SSL. It think that some libraries are missing from the monolithic exe, but I couldn't figure out how to fix the problem.
- In setup.py you can also find the remains of an attempt to do some desktop integration from a pip install. It does work, but can cause problems with wheel installs, and I don't know if it's worth the bother. I kept the commented-out code in place, just in case.
# ComicTagger
With Python 3, it's much easier to get the app working from scratch on a new distro, as all of the dependencies are available as wheels, including PyQt5, so just a simple "pip install comictagger.zip" is all that's needed.
ComicTagger is a **multi-platform** app for **writing metadata to digital comics**, written in Python and PyQt.
![ComicTagger logo](comictaggerlib/graphics/app.png?raw=true)
## Features
* Runs on macOS, Microsoft Windows, and Linux systems
* Get comic information from [Comic Vine](https://comicvine.gamespot.com/)
* **Automatic issue matching** using advanced image processing techniques
* **Batch processing** in the GUI for tagging hundreds or more comics at a time
* Support for **ComicRack** and **ComicBookLover** tagging formats
* Native full support for **CBZ** digital comics
* Native read only support for **CBR** digital comics: full support enabled installing additional [rar tools](https://www.rarlab.com/download.htm)
* Command line interface (CLI) enabling **custom scripting** and **batch operations on large collections**
For details, screen-shots, release notes, and more, visit [the Wiki](https://github.com/comictagger/comictagger/wiki)
## Installation
### Binaries
Windows and macOS binaries are provided in the [Releases Page](https://github.com/comictagger/comictagger/releases).
Just unzip the archive in any folder and run, no additional installation steps are required.
### PIP installation
A pip package is provided, you can install it with:
```
$ pip install comictagger
```
### From source
1. ensure you have a recent version of python3 and setuptools installed
2. clone this repository `git clone https://github.com/comictagger/comictagger.git`
3. `pip install -r requirements.txt`
4. `python comictagger.py`

View File

@ -1,6 +0,0 @@
version: 1.0.{build}
build_script:
- cmd: powershell -exec bypass -File windows\fullbuild.ps1
artifacts:
- path: dist\*.exe
name: ComicTagger

View File

@ -153,6 +153,7 @@ class ZipArchiver:
zf = zipfile.ZipFile(
self.path,
mode='a',
allowZip64=True,
compression=zipfile.ZIP_DEFLATED)
zf.writestr(archive_file, data)
zf.close()
@ -185,7 +186,7 @@ class ZipArchiver:
os.close(tmp_fd)
zin = zipfile.ZipFile(self.path, 'r')
zout = zipfile.ZipFile(tmp_name, 'w')
zout = zipfile.ZipFile(tmp_name, 'w', allowZip64=True)
for item in zin.infolist():
buffer = zin.read(item.filename)
if (item.filename not in exclude_list):
@ -270,7 +271,7 @@ class ZipArchiver:
"""Replace the current zip with one copied from another archive"""
try:
zout = zipfile.ZipFile(self.path, 'w')
zout = zipfile.ZipFile(self.path, 'w', allowZip64=True)
for fname in otherArchive.getArchiveFilenameList():
data = otherArchive.readArchiveFile(fname)
if data is not None:

View File

@ -123,7 +123,7 @@ def which(program):
def removearticles(text):
text = text.lower()
articles = ['and', 'a', '&', 'issue']
articles = ['and', 'a', '&', 'issue', 'the']
newText = ''
for word in text.split(' '):
if word not in articles:

View File

@ -1,6 +1,7 @@
# -*- mode: python -*-
import platform
from comictaggerlib import ctversion
block_cipher = None
@ -9,10 +10,12 @@ binaries = [
]
if platform.system() == "Windows":
from site import getsitepackages
sitepackages = getsitepackages()[1]
# add ssl qt libraries not discovered automatically
binaries.extend([
('./venv/Lib/site-packages/PyQt5/Qt/bin/libeay32.dll', './PyQt5/Qt/bin'),
('./venv/Lib/site-packages/PyQt5/Qt/bin/ssleay32.dll', './PyQt5/Qt/bin')
('%s/PyQt5/Qt/bin/libeay32.dll' % sitepackages, './PyQt5/Qt/bin'),
('%s/PyQt5/Qt/bin/ssleay32.dll' % sitepackages, './PyQt5/Qt/bin')
])
a = Analysis(['comictagger.py'],
@ -45,6 +48,9 @@ app = BUNDLE(exe,
name='ComicTagger.app',
icon='mac/app.icns',
info_plist={
'NSHighResolutionCapable': 'True'
'NSHighResolutionCapable': 'True',
'CFBundleDisplayName': 'ComicTagger',
'CFBundleShortVersionString': ctversion.version,
'CFBundleVersion': ctversion.version
},
bundle_identifier=None)

View File

@ -105,7 +105,7 @@ class ComicVineTalker(QObject):
self.log_func = None
# always use a tls context for urlopen
self.ssl = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
self.ssl = ssl.SSLContext(ssl.PROTOCOL_TLS)
def setLogFunc(self, log_func):
self.log_func = log_func
@ -188,7 +188,7 @@ class ComicVineTalker(QObject):
# connect to server:
# if there is a 500 error, try a few more times before giving up
# any other error, just bail
# print "ATB---", url
#print("---", url)
for tries in range(3):
try:
resp = urllib.request.urlopen(url, context=self.ssl)
@ -226,10 +226,10 @@ class ComicVineTalker(QObject):
original_series_name = series_name
# Split and rejoin to remove extra internal spaces
# Split and rejoin to remove extra internal spaces
query_word_list = series_name.split()
query_string = " ".join( query_word_list ).strip()
#print "Query string = ", query_string
#print ("Query string = ", query_string)
query_string = urllib.parse.quote_plus(query_string.encode("utf-8"))
@ -246,6 +246,19 @@ class ComicVineTalker(QObject):
current_result_count = cv_response['number_of_page_results']
total_result_count = cv_response['number_of_total_results']
# 8 Dec 2018 - Comic Vine changed query results again. Terms are now
# ORed together, and we get thousands of results. Good news is the
# results are sorted by relevance, so we can be smart about halting
# the search.
# 1. Don't fetch more than some sane amount of pages.
max_results = 500
# 2. Halt when not all of our search terms are present in a result
# 3. Halt when the results contain more (plus threshold) words than
# our search
result_word_count_max = len(query_word_list) + 3
total_result_count = min(total_result_count, max_results)
if callback is None:
self.writeLog(
"Found {0} of {1} results\n".format(
@ -258,7 +271,29 @@ class ComicVineTalker(QObject):
callback(current_result_count, total_result_count)
# see if we need to keep asking for more pages...
stop_searching = False
while (current_result_count < total_result_count):
last_result = search_results[-1]['name']
# See if the last result's name has all the of the search terms.
# if not, break out of this, loop, we're done.
#print("Searching for {} in '{}'".format(query_word_list, last_result))
for term in query_word_list:
if term not in last_result.lower():
#print("Term '{}' not in last result. Halting search result fetching".format(term))
stop_searching = True
break
# Also, stop searching when the word count of last results is too much longer
# than our search terms list
if len(utils.removearticles(last_result).split()) > result_word_count_max:
#print("Last result '{}' is too long. Halting search result fetching".format(last_result))
stop_searching = True
if stop_searching:
break
if callback is None:
self.writeLog(
"getting another page of results {0} of {1}...\n".format(
@ -274,6 +309,15 @@ class ComicVineTalker(QObject):
if callback is not None:
callback(current_result_count, total_result_count)
# Remove any search results that don't contain all the search terms
# (iterate backwards for easy removal)
for i in range(len(search_results) - 1, -1, -1):
record = search_results[i]
for term in query_word_list:
if term not in record['name'].lower():
del search_results[i]
break
# for record in search_results:
#print(u"{0}: {1} ({2})".format(record['id'], record['name'] , record['start_year']))
# print(record)
@ -328,16 +372,16 @@ class ComicVineTalker(QObject):
limit = cv_response['limit']
current_result_count = cv_response['number_of_page_results']
total_result_count = cv_response['number_of_total_results']
# print "ATB total_result_count", total_result_count
#print("total_result_count", total_result_count)
#print("ATB Found {0} of {1} results".format(cv_response['number_of_page_results'], cv_response['number_of_total_results']))
#print("Found {0} of {1} results".format(cv_response['number_of_page_results'], cv_response['number_of_total_results']))
volume_issues_result = cv_response['results']
page = 1
offset = 0
# see if we need to keep asking for more pages...
while (current_result_count < total_result_count):
#print("ATB getting another page of issue results {0} of {1}...".format(current_result_count, total_result_count))
#print("getting another page of issue results {0} of {1}...".format(current_result_count, total_result_count))
page += 1
offset += cv_response['number_of_page_results']
@ -380,16 +424,16 @@ class ComicVineTalker(QObject):
limit = cv_response['limit']
current_result_count = cv_response['number_of_page_results']
total_result_count = cv_response['number_of_total_results']
# print "ATB total_result_count", total_result_count
#print("total_result_count", total_result_count)
#print("ATB Found {0} of {1} results\n".format(cv_response['number_of_page_results'], cv_response['number_of_total_results']))
#print("Found {0} of {1} results\n".format(cv_response['number_of_page_results'], cv_response['number_of_total_results']))
filtered_issues_result = cv_response['results']
page = 1
offset = 0
# see if we need to keep asking for more pages...
while (current_result_count < total_result_count):
#print("ATB getting another page of issue results {0} of {1}...\n".format(current_result_count, total_result_count))
#print("getting another page of issue results {0} of {1}...\n".format(current_result_count, total_result_count))
page += 1
offset += cv_response['number_of_page_results']

View File

@ -1,3 +0,0 @@
# This file should contain only these comments, and the line below.
# Used by packaging makefiles and app
version = "1.1.30-rc1"

View File

@ -67,7 +67,7 @@ class ImageFetcher(QObject):
self.create_image_db()
# always use a tls context for urlopen
self.ssl = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
self.ssl = ssl.SSLContext(ssl.PROTOCOL_TLS)
def clearCache(self):
os.unlink(self.db_file)

View File

@ -545,7 +545,7 @@ class TaggerWindow(QtWidgets.QMainWindow):
def aboutApp(self):
website = "https://github.com/davide-romanini/comictagger"
website = "https://github.com/comictagger/comictagger"
email = "comictagger@gmail.com"
license_link = "http://www.apache.org/licenses/LICENSE-2.0"
license_name = "Apache License 2.0"
@ -582,35 +582,8 @@ class TaggerWindow(QtWidgets.QMainWindow):
if self.droppedFiles is not None:
event.accept()
# http://stackoverflow.com/questions/34689562/pyqt-mimedata-filename
def getUrlFromLocalFileID(self, localFileID):
import sys
if not sys.platform == 'darwin':
return localFileID.toLocalFile()
import objc
import CoreFoundation as CF
localFileQString = QString(localFileID.toLocalFile())
relCFStringRef = CF.CFStringCreateWithCString(
CF.kCFAllocatorDefault,
localFileQString.toUtf8(),
CF.kCFStringEncodingUTF8
)
relCFURL = CF.CFURLCreateWithFileSystemPath(
CF.kCFAllocatorDefault,
relCFStringRef,
CF.kCFURLPOSIXPathStyle,
False # is directory
)
absCFURL = CF.CFURLCreateFilePathURL(
CF.kCFAllocatorDefault,
relCFURL,
objc.NULL
)
local = QUrl(str(absCFURL[0])).toLocalFile()
return local
return localFileID.toLocalFile()
def dropEvent(self, event):
# if self.dirtyFlagVerification("Open Archive",
@ -2049,10 +2022,10 @@ class TaggerWindow(QtWidgets.QMainWindow):
dlg.exec_()
def showWiki(self):
webbrowser.open("https://github.com/davide-romanini/comictagger/wiki")
webbrowser.open("https://github.com/comictagger/comictagger/wiki")
def reportBug(self):
webbrowser.open("https://github.com/davide-romanini/comictagger/issues")
webbrowser.open("https://github.com/comictagger/comictagger/issues")
def showForum(self):
webbrowser.open("http://comictagger.forumotion.com/")

View File

@ -1 +0,0 @@
1.1.16-beta-rc

View File

@ -5,7 +5,7 @@ TAGGER_BASE ?= ../
TAGGER_SRC := $(TAGGER_BASE)/comictaggerlib
APP_NAME := ComicTagger
VERSION_STR := $(shell grep version $(TAGGER_SRC)/ctversion.py| cut -d= -f2 | sed 's/\"//g')
VERSION_STR := $(shell python setup.py --version)
MAC_BASE := $(TAGGER_BASE)/mac
DIST_DIR := $(MAC_BASE)/dist

View File

@ -5,4 +5,4 @@ natsort==3.5.2
PyPDF2==1.24
pillow>=4.3.0
PyQt5>=5.10.1
git+https://github.com/pyinstaller/pyinstaller@develop
pyinstaller>=3.5

View File

@ -23,7 +23,6 @@ import sys
import shutil
import platform
import tempfile
import comictaggerlib.ctversion
python_requires='>=3',
@ -193,18 +192,22 @@ setup(name="comictagger",
'build_py': BuildPyCommand,
'install': customInstall,
},
version=comictaggerlib.ctversion.version,
description="A cross-platform GUI/CLI app for writing metadata to comic archives",
author="ComicTagger team",
author_email="comictagger@gmail.com",
url="https://github.com/davide-romanini/comictagger",
download_url="https://pypi.python.org/packages/source/c/comictagger/comictagger-{0}.zip".format(comictaggerlib.ctversion.version),
url="https://github.com/comictagger/comictagger",
packages=["comictaggerlib", "comicapi"],
package_data={
'comictaggerlib': ['ui/*', 'graphics/*', '*.so'],
},
entry_points=dict(console_scripts=['comictagger=comictaggerlib.main:ctmain']),
data_files=platform_data_files,
setup_requires=[
"setuptools_scm"
],
use_scm_version={
'write_to': 'comictaggerlib/ctversion.py'
},
classifiers=[
"Development Status :: 4 - Beta",
"Environment :: Console",

View File

@ -1,5 +0,0 @@
# to be run inside comictagger folder
# installs conda and pip dependencies
activate comictagger
conda install -y pyqt=4
pip install -r .\requirements.txt

View File

@ -1,3 +0,0 @@
$env:PATH+=";C:\ProgramData\Miniconda2\Scripts;C:\ProgramData\Miniconda2"
$env:PATH+=";C:\tools\mingw64\bin"
Set-Alias make mingw32-make.exe -scope Global

View File

@ -1,8 +0,0 @@
# Script to be run inside appveyor for a full build
choco install -y mingw
refreshenv
$env:PATH="C:\Python36-x64;$env:path"
python -m venv venv
.\venv\Scripts\Activate.ps1
pip install -r .\requirements.txt
mingw32-make dist

View File

@ -1,11 +0,0 @@
# This script should be run into an admin PowerShell to install all required
# packages needed for building comictagger on windows
#
# NOTE: this script has not been fully tested on a fresh windows VM.
#
# install chocolatey
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
choco install -y git mingw miniconda
$env:PATH+=";C:\ProgramData\Miniconda2\Scripts;C:\ProgramData\Miniconda2"
$env:PATH+=";C:\tools\mingw64\bin"
conda create -y --name comictagger python=2