From f6948a7aaf1dae32bca2a2e6a24ed6cc581c88f3 Mon Sep 17 00:00:00 2001 From: Yves Fischer Date: Fri, 5 Dec 2014 00:56:21 +0100 Subject: pep8 --- imdb-lookup/imdbinfo.py | 184 ++++++++++++++++++++++++++++++------------------ 1 file changed, 117 insertions(+), 67 deletions(-) (limited to 'imdb-lookup') diff --git a/imdb-lookup/imdbinfo.py b/imdb-lookup/imdbinfo.py index 8521e98..2f5e106 100755 --- a/imdb-lookup/imdbinfo.py +++ b/imdb-lookup/imdbinfo.py @@ -14,7 +14,6 @@ import math import logging import hashlib from io import BytesIO - from urllib.parse import quote as urlencode try: @@ -23,9 +22,11 @@ try: import requests except ImportError as e: print("Missing dependency: {0}".format(str(e))) - print("Install using system package manager or `pip install --user (one of: Pillow tmdbsimple requests)`") + print("Install using system package manager") + print("or `pip install --user (one of: Pillow tmdbsimple requests)`") sys.exit(1) + def read_key(): if "TMDB_KEY" in os.environ.keys(): return os.environ["TMDB_KEY"] @@ -36,14 +37,17 @@ def read_key(): if os.path.exists(os.path.join(cfg_home, "tmdbkey")): return open(os.path.join(cfg_home, "tmdbkey"), "r").read().strip() if os.path.exists(os.path.join(os.path.expanduser("~"), ".tmdbkey")): - return open(os.path.join(os.path.expanduser("~"), ".tmdbkey")).read().strip() - raise Exception("No TheMovieDB Key defined. Set Env. var. TMDB_KEY or .tmdbkey file") - + return open(os.path.join(os.path.expanduser("~"), + ".tmdbkey")).read().strip() + raise Exception("No TMDB Key defined. Set TMDB_KEY=.. or .tmdbkey file") + + class TMDBCache(object): def __enter__(self): - self.logger = logging.getLogger(self.__class__.__module__ + "." + self.__class__.__name__) + logger_name = self.__class__.__module__ + "." + self.__class__.__name__ + self.logger = logging.getLogger(logger_name) self.logger.info("Open db") - self.db = dbm.open(self._get_db_filename("tmdbmovie.dbm"),"c") + self.db = dbm.open(self._get_db_filename("tmdbmovie.dbm"), "c") self.db_images = dbm.open(self._get_db_filename("tmdbposter.dbm"), "c") return self @@ -68,23 +72,29 @@ class TMDBCache(object): def infos(self, movie_id): try: self.logger.debug("movie %s", movie_id) - return self._cache(movie_id + "movies.info", tmdb.Movies(movie_id).info) + return self._cache(movie_id + "movies.info", + tmdb.Movies(movie_id).info) except Exception as e: - raise Exception("Failed to query movie with id {id}: {reason}".format(id=movie_id, reason=str(e))) + raise Exception("Failed to query movie-id {id}: {reason}".format( + id=movie_id, reason=str(e))) def alternative_title(self, movie_id, locale): """Returns the title in selected locale or original title otherwise""" try: + key = movie_id + "movies.alt_titles" + search = tmdb.Movies(movie_id).search.alternative_titles + titles = self._cache(key, search) alt_title = list(filter(lambda l: l["iso_3166_1"] == locale, - self._cache(movie_id + "movies.alt_titles", tmdb.Movies(movie_id).alternative_titles)["titles"])) + titles["titles"])) if alt_title: return alt_title[0]["title"] else: infos = self.infos(movie_id) return infos["title"] or infos["original_title"] except Exception as e: - raise Exception("Failed to query movie with id {id}: {reason}".format(id=movie_id, reason=str(e))) - + raise Exception("Failed to query movie-id {id}: {reason}".format( + id=movie_id, reason=str(e))) + def prune(self, movie_id): self.logger.debug("prune {}".format(movie_id)) keys = [ @@ -99,11 +109,11 @@ class TMDBCache(object): else: self.logger.debug("Key not in db {}".format(key)) - def poster(self, poster_path, format="w185"): + def poster(self, poster_path, f="w185"): self.logger.debug("poster %s", poster_path) - key = "poster_{}_{}".format(format, poster_path) - keyContentType = "poster_{}_{}_content_type".format(format, poster_path) - url = "http://image.tmdb.org/t/p/{}/{}".format(format, poster_path) + key = "poster_{}_{}".format(f, poster_path) + keyContentType = "poster_{}_{}_content_type".format(f, poster_path) + url = "http://image.tmdb.org/t/p/{}/{}".format(f, poster_path) if key not in self.db_images: r = requests.get(url) self.db_images[key] = r.content @@ -112,23 +122,27 @@ class TMDBCache(object): def poster_base64(self, poster_path, format="w185"): p = self.poster(poster_path, format) - if not p: return None + if not p: + return None contentType, data = p image = Image.open(BytesIO(data)) buf = BytesIO() image.save(buf, "JPEG", quality=10, optimize=True) - data64 = "".join(map(lambda c: isinstance(c,int) and chr(c) or c, - filter(lambda c: c!='\n', base64.encodestring(buf.getvalue())))) + data64 = base64.encodestring(buf.getvalue()) + data64 = "".join(map(lambda c: isinstance(c, int) and chr(c) or c, + filter(lambda c: c != '\n', data64))) return "data:{};base64,{}".format(contentType, data64) def _imdb_request(self, path, query): # see also https://github.com/richardasaurus/imdb-pie - # nice library but a bit strange API, so we chose to reimplement stuff here + # nice library but a bit strange API, + # so we chose to reimplement stuff here BASE_URI = 'app.imdb.com' API_KEY = '2wex6aeu6a8q9e49k7sfvufd6rhh0n' SHA1_KEY = hashlib.sha1(API_KEY.encode('utf8')).hexdigest() HEADERS = { - 'user-agent' : 'AppleWebKit/534.46 (KHTML, like Gecko) Ver sion/5.1 Mobile/9A405', + 'user-agent': 'AppleWebKit/534.46 (KHTML, like Gecko) ' + + 'Version/5.1 Mobile/9A405', } PARAMS = { "api": "v1", @@ -140,14 +154,15 @@ class TMDBCache(object): } q = query.copy() q.update(PARAMS) - return requests.get("https://{}{}".format(BASE_URI, path), params=q, headers=HEADERS) + return requests.get("https://{}{}".format(BASE_URI, path), + params=q, headers=HEADERS) def imdb_movie(self, movie_id): def do_request(): r = self._imdb_request("/title/maindetails", {'tconst': movie_id}) assert r.status_code == 200, "Request must return status-code 200" data = json.loads(r.text) - assert data != None and data['data'], "Data must not be empty" + assert data is not None and data['data'], "Data must not be empty" return data key = "imdb_maindetails_{}".format(movie_id) return self._cache(key, do_request) @@ -155,13 +170,15 @@ class TMDBCache(object): def weight_rating(infos): """ add 'rating' to all infos""" + infos = list(infos) maxvotes = max(map(lambda i: i["vote_count"], infos)) for info in infos: - f = math.sin(math.pi * ( info["vote_average"]/10.0 ) ) + f = math.sin(math.pi * (info["vote_average"]/10.0)) d = (float(info["vote_count"]) / maxvotes) - 0.5 info['rating'] = info["vote_average"] + 2 * d * f return infos + class Protector(object): """ The Protector saves the caller from exception. All callable attributes of child are dynamically @@ -180,11 +197,13 @@ class Protector(object): """ def __init__(self, child): self.child = child + def __getattr__(self, name): attr = getattr(self.child, name) + def protected(*a, **kw): try: - return attr(*a,**kw) + return attr(*a, **kw) except KeyboardInterrupt as e: raise e except Exception as e: @@ -195,11 +214,13 @@ class Protector(object): else: return attr + def do_aka(args, imdb_ids): with TMDBCache() as tmdbcache: for (filename, imdb_id) in imdb_ids: print(tmdbcache.alternative_title(imdb_id, locale=args.lang)) + def do_data(args, imdb_ids): def print_data(data, io, indent=0): if isinstance(data, dict): @@ -209,67 +230,73 @@ def do_data(args, imdb_ids): else: io.write("\n{}{}: ".format(indent*" ", key)) print_data(val, io, indent+1) - elif isinstance(data, list) and len(data)>0: + elif isinstance(data, list) and len(data) > 0: for val in data: print_data(val, io, indent+2) - elif type(data) in (bool,str,int,float): + elif type(data) in (bool, str, int, float): io.write(str(data)) with TMDBCache() as tmdbcache: for (filename, imdb_id) in imdb_ids: - print_data({ - "TMDB" : tmdbcache.infos(imdb_id), - "IMDB" : tmdbcache.imdb_movie(imdb_id)}, sys.stdout) + print_data({"TMDB": tmdbcache.infos(imdb_id), + "IMDB": tmdbcache.imdb_movie(imdb_id)}, sys.stdout) + def do_year(args, imdb_ids): with TMDBCache() as tmdbcache: for (filename, imdb_id) in imdb_ids: print(tmdbcache.infos(imdb_id)["release_date"].split("-")[0]) + def do_prune(args, imdb_ids): with TMDBCache() as tmdbcache: for (filename, imdb_id) in imdb_ids: tmdbcache.prune(imdb_id) + def do_rating(args, imdb_ids): """Calculates a rating based on vote_average and vote_count""" with TMDBCache() as tmdbcache: - infos = list(filter(lambda i: "vote_average" in i and "vote_count" in i, - map(lambda fid: tmdbcache.infos(fid[1]), imdb_ids))) + infos = filter(lambda i: "vote_average" in i and "vote_count" in i, + map(lambda fid: tmdbcache.infos(fid[1]), imdb_ids)) weight_rating(infos) for info in infos: - print("{rating:.02f} {imdb_id} {title:30s} avg={vote_average:.1f} count={vote_count:.0f}".format(**info)) + print("{rating:.02f} {imdb_id} {title:30s} avg=" + + "{vote_average:.1f} count={vote_count:.0f}".format(**info)) def do_index(args, imdb_ids): """creates a index website""" + valid_extensions = [".mkv", ".avi", ".mov", ".mp4", ".mpg"] + def listMovieFiles(path): for root, dirs, files in os.walk(path): for curfile in files: - if sum(map(curfile.endswith, [".mkv", ".avi", ".mov", ".mp4"])): + if sum(map(curfile.endswith, valid_extensions)): yield os.path.join(root, curfile) def asBase64(poster): contentType, data = poster - data64 = filter(lambda c: c!='\n', base64.encodestring(data)) + data64 = filter(lambda c: c != '\n', base64.encodestring(data)) return "data:{};base64,{}".format(contentType, data64) try: from jinja2 import Template except ImportError: print("Failed to import jinja2 library for html-templating") sys.exit(1) - template_file = os.path.join(os.path.dirname(__file__), "index.jinja2.html") + template_file = os.path.join(os.path.dirname(__file__), + "index.jinja2.html") template = Template(open(template_file, "r").read()) with TMDBCache() as tmdbcache: mapping = { - 'gmtime' : time.gmtime(), - 'input' : imdb_ids, - 'tmdbcache' : Protector(tmdbcache), - 'title' : 'Movie overview', - 'urlencode' : urlencode, - 'int' : int, - 'listMovieFiles' : listMovieFiles, - 'math' : math, + 'gmtime': time.gmtime(), + 'input': imdb_ids, + 'tmdbcache': Protector(tmdbcache), + 'title': 'Movie overview', + 'urlencode': urlencode, + 'int': int, + 'listMovieFiles': listMovieFiles, + 'math': math, } assert not os.path.exists("index.html"), "index.html already exists" stream = template.generate(mapping) @@ -277,16 +304,19 @@ def do_index(args, imdb_ids): for output in stream: outfile.write(output.encode('utf-8')) + class HelpAction(argparse._HelpAction): def __call__(self, parser, namespace, values, option_string=None): formatter = parser._get_formatter() - formatter.add_usage(parser.usage, parser._actions, parser._mutually_exclusive_groups) + formatter.add_usage(parser.usage, + parser._actions, + parser._mutually_exclusive_groups) formatter.start_section(parser._optionals.title) formatter.add_text(parser._optionals.description) formatter.add_arguments(parser._optionals._group_actions) formatter.end_section() - + subparsers_actions = [ action for action in parser._actions if isinstance(action, argparse._SubParsersAction)] @@ -296,8 +326,10 @@ class HelpAction(argparse._HelpAction): subparsers = subparsers_action.choices for subaction in subparsers_action._get_subactions(): subparser = subparsers[subaction.dest] - formatter.start_section("{} {} {}".format(formatter._prog, subaction.dest, - formatter._format_actions_usage(subparser._actions, []))) + usage = formatter._format_actions_usage(subparser._actions, []) + formatter.start_section("{} {} {}".format(formatter._prog, + subaction.dest, + usage)) formatter.add_text(subaction.help) formatter.add_arguments(subparser._positionals._group_actions) formatter.add_arguments(subparser._optionals._group_actions) @@ -306,6 +338,7 @@ class HelpAction(argparse._HelpAction): print(formatter.format_help()) parser.exit(0) + def do_test(args): import doctest doctest.testmod() @@ -315,37 +348,52 @@ if __name__ == "__main__": parser = argparse.ArgumentParser(add_help=False) parser.add_argument("--help", action=HelpAction, help="Display full help") - parser.add_argument("--log-level", action='store', type=int, - help="Set log level (CRITICAL=50,ERROR=40,WARNING=30,INFO=20,DEBUG=10,NOTSET=0") - parser.add_argument("-h", action=argparse._HelpAction, help="Display short help") + parser.add_argument("--log-level", action='store', type=int, + help="Set log level (CRITICAL=50," + + "ERROR=40,WARNING=30,INFO=20,DEBUG=10,NOTSET=0") + parser.add_argument("-h", action=argparse._HelpAction, + help="Display short help") subparsers = parser.add_subparsers() - parser_aka = subparsers.add_parser("aka", add_help=False, help="Print alternative title in other languages") + parser_aka = subparsers.add_parser("aka", add_help=False, + help="Print alternative titles") parser_aka.add_argument("--lang", help="Language code (default 'DE')") parser_aka.set_defaults(func=do_aka) - parser_aka.add_argument("files", action="append", nargs="+", help="Files containing distinct movie-ids") + parser_aka.add_argument("files", action="append", nargs="+", + help="Files containing distinct movie-ids") - parser_data = subparsers.add_parser("data", add_help=False, help="Print all available data") + parser_data = subparsers.add_parser("data", add_help=False, + help="Print all available data") parser_data.set_defaults(func=do_data) - parser_data.add_argument("files", action="append", nargs="+", help="Files containing distinct movie-ids") + parser_data.add_argument("files", action="append", nargs="+", + help="Files containing distinct movie-ids") - parser_year = subparsers.add_parser("year", add_help=False, help="Print only the release year") + parser_year = subparsers.add_parser("year", add_help=False, + help="Print only the release year") parser_year.set_defaults(func=do_year) - parser_year.add_argument("files", action="append", nargs="+", help="Files containing distinct movie-ids") + parser_year.add_argument("files", action="append", nargs="+", + help="Files containing distinct movie-ids") - parser_prune = subparsers.add_parser("prune", add_help=False, help="Delete cache entries") + parser_prune = subparsers.add_parser("prune", add_help=False, + help="Delete cache entries") parser_prune.set_defaults(func=do_prune) - parser_prune.add_argument("files", action="append", nargs="+", help="Files containing distinct movie-ids") + parser_prune.add_argument("files", action="append", nargs="+", + help="Files containing distinct movie-ids") - parser_rating = subparsers.add_parser("rating", add_help=False, help="Print movie ratings") + parser_rating = subparsers.add_parser("rating", add_help=False, + help="Print movie ratings") parser_rating.set_defaults(func=do_rating) - parser_rating.add_argument("files", action="append", nargs="+", help="Files containing distinct movie-ids") + parser_rating.add_argument("files", action="append", nargs="+", + help="Files containing distinct movie-ids") - parser_index = subparsers.add_parser("index", add_help=False, help="Generate index.html file") + parser_index = subparsers.add_parser("index", add_help=False, + help="Generate index.html file") parser_index.set_defaults(func=do_index) - parser_index.add_argument("files", action="append", nargs="+", help="Files containing distinct movie-ids") + parser_index.add_argument("files", action="append", nargs="+", + help="Files containing distinct movie-ids") - parser_test = subparsers.add_parser("test", add_help=False, help="Run testsuite") + parser_test = subparsers.add_parser("test", add_help=False, + help="Run testsuite") parser_test.set_defaults(func=do_test) args = parser.parse_args(sys.argv[1:]) @@ -353,11 +401,13 @@ if __name__ == "__main__": logging.basicConfig(level=args.log_level) if "files" in args: - ids = map(lambda filename: (lambda x: (filename, x.groups()[0]) if x else None)(re.match(".*#(tt[0-9]{7}).*", filename)), - args.files[0]) + ids = args.files[0] + ids = map(lambda filename: + (lambda x: (filename, x.groups()[0]) if x else None) + (re.match(".*#(tt[0-9]{7}).*", filename)), + ids) args.func(args, list(filter(lambda i: i is not None, ids))) elif "func" in args: args.func(args) else: HelpAction("")(parser, None, None) - -- cgit v1.2.1