mirror of
https://github.com/pkkid/python-plexapi
synced 2024-11-12 23:17:07 +00:00
style: lint all python files (#1228)
This commit is contained in:
parent
dba3369f55
commit
a6b6ebfbff
28 changed files with 131 additions and 105 deletions
10
.flake8
10
.flake8
|
@ -5,12 +5,14 @@
|
|||
# E701: multiple statements on one line (colon)
|
||||
# E702: multiple statements on one line (semicolon)
|
||||
# E731: do not assign a lambda expression, use a def
|
||||
# W293: blank line contains whitespace
|
||||
# W503: line break before binary operator
|
||||
# W605: invalid escape sequence
|
||||
[flake8]
|
||||
ignore=E128,E701,E702,E731,W293,W503,W605
|
||||
exclude=compat.py
|
||||
ignore=E128,E701,E702,E731,W503,W605
|
||||
exclude=compat.py,venv
|
||||
per-file-ignores =
|
||||
tests/payloads.py:E501
|
||||
max-complexity = -1
|
||||
max-line-length = 125
|
||||
# The GitHub editor is 127 chars wide
|
||||
max-line-length = 127
|
||||
show-source = True
|
||||
|
|
8
.github/workflows/ci.yaml
vendored
8
.github/workflows/ci.yaml
vendored
|
@ -54,9 +54,13 @@ jobs:
|
|||
run: |
|
||||
. venv/bin/activate
|
||||
# stop the build if there are Python syntax errors or undefined names
|
||||
flake8 plexapi --count --select=E9,F63,F7,F82 --show-source --statistics
|
||||
echo "::group::flake8 pass 1"
|
||||
flake8 --count --select=E9,F63,F7,F82 --show-source --statistics
|
||||
echo "::endgroup::"
|
||||
# The GitHub editor is 127 chars wide
|
||||
flake8 plexapi --count --max-complexity=12 --max-line-length=127 --statistics
|
||||
echo "::group::flake8 pass 2"
|
||||
flake8 --count --max-complexity=12 --max-line-length=127 --statistics
|
||||
echo "::endgroup::"
|
||||
|
||||
|
||||
pytest:
|
||||
|
|
15
docs/conf.py
15
docs/conf.py
|
@ -12,12 +12,13 @@
|
|||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
import copy, sys
|
||||
import copy
|
||||
from os.path import abspath, dirname, join
|
||||
import sys
|
||||
path = dirname(dirname(abspath(__file__)))
|
||||
sys.path.append(path)
|
||||
sys.path.append(join(path, 'plexapi'))
|
||||
import plexapi
|
||||
import plexapi # noqa: E402
|
||||
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
|
@ -27,13 +28,17 @@ extensions = [
|
|||
]
|
||||
|
||||
# -- Monkey-patch docstring to not auto-link :ivars ------------------------
|
||||
from sphinx.domains.python import PythonDomain
|
||||
from sphinx.domains.python import PythonDomain # noqa: E402
|
||||
print('Monkey-patching PythonDomain.resolve_xref()')
|
||||
old_resolve_xref = copy.deepcopy(PythonDomain.resolve_xref)
|
||||
|
||||
|
||||
def new_resolve_xref(*args):
|
||||
if '.' not in args[5]: # target
|
||||
return None
|
||||
return old_resolve_xref(*args)
|
||||
|
||||
|
||||
PythonDomain.resolve_xref = new_resolve_xref
|
||||
|
||||
# -- Napoleon Settings -----------------------------------------------------
|
||||
|
@ -79,7 +84,7 @@ author = 'M.Shepanski'
|
|||
# The short X.Y version.
|
||||
version = plexapi.VERSION
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
#release = '2.0.2'
|
||||
# release = '2.0.2'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
@ -137,7 +142,7 @@ html_context = {'css_files': ['_static/custom.css']}
|
|||
html_theme_options = {
|
||||
'collapse_navigation': False,
|
||||
'display_version': False,
|
||||
#'navigation_depth': 3,
|
||||
# 'navigation_depth': 3,
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3102,6 +3102,7 @@ class FirstCharacter(PlexObject):
|
|||
size (str): Total amount of library items starting with this character.
|
||||
title (str): Character (#, !, A, B, C, ...).
|
||||
"""
|
||||
|
||||
def _loadData(self, data):
|
||||
""" Load attribute values from Plex XML response. """
|
||||
self._data = data
|
||||
|
|
|
@ -1008,6 +1008,7 @@ class BaseResource(PlexObject):
|
|||
selected (bool): True if the resource is currently selected.
|
||||
thumb (str): The URL to retrieve the resource thumbnail.
|
||||
"""
|
||||
|
||||
def _loadData(self, data):
|
||||
self._data = data
|
||||
self.key = data.attrib.get('key')
|
||||
|
|
|
@ -23,7 +23,6 @@ you can set items to be synced to your app) you need to init some variables.
|
|||
You have to fake platform/device/model because transcoding profiles are hardcoded in Plex, and you obviously have
|
||||
to explicitly specify that your app supports `sync-target`.
|
||||
"""
|
||||
|
||||
import requests
|
||||
|
||||
import plexapi
|
||||
|
|
|
@ -106,14 +106,20 @@ def test_history_User(account, shared_username):
|
|||
user = account.user(shared_username)
|
||||
history = user.history()
|
||||
|
||||
assert isinstance(history, list)
|
||||
|
||||
|
||||
def test_history_UserServer(account, shared_username, plex):
|
||||
userSharedServer = account.user(shared_username).server(plex.friendlyName)
|
||||
history = userSharedServer.history()
|
||||
|
||||
assert isinstance(history, list)
|
||||
|
||||
|
||||
def test_history_UserSection(account, shared_username, plex):
|
||||
userSharedServerSection = (
|
||||
account.user(shared_username).server(plex.friendlyName).section("Movies")
|
||||
)
|
||||
history = userSharedServerSection.history()
|
||||
|
||||
assert isinstance(history, list)
|
||||
|
|
|
@ -777,7 +777,7 @@ def test_library_search_exceptions(movies):
|
|||
movies.search(sort="titleSort:bad")
|
||||
|
||||
|
||||
def _test_library_search(library, obj):
|
||||
def _test_library_search(library, obj): # noqa: C901
|
||||
# Create & operator
|
||||
AndOperator = namedtuple("AndOperator", ["key", "title"])
|
||||
andOp = AndOperator("&=", "and")
|
||||
|
|
|
@ -28,6 +28,7 @@ def test_navigate_around_artist(account, plex):
|
|||
print(f"Album: {album}")
|
||||
print(f"Tracks: {tracks}...")
|
||||
print(f"Track: {track}")
|
||||
assert isinstance(albums, list), "Unable to list artist albums."
|
||||
assert artist.track("As Colourful as Ever") == track, "Unable to get artist track."
|
||||
assert album.track("As Colourful as Ever") == track, "Unable to get album track."
|
||||
assert album.artist() == artist, "album.artist() doesn't match expected artist."
|
||||
|
|
|
@ -418,7 +418,7 @@ def test_video_Movie_upload_select_remove_subtitle(movie, subtitle):
|
|||
|
||||
try:
|
||||
os.remove(filepath)
|
||||
except:
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ import os
|
|||
from datetime import datetime
|
||||
from plexapi.server import PlexServer
|
||||
|
||||
TAGS = {'keep5':5, 'keep10':10, 'keep15':15, 'keepSeason':'season'}
|
||||
TAGS = {'keep5': 5, 'keep10': 10, 'keep15': 15, 'keepSeason': 'season'}
|
||||
datestr = lambda: datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
|
||||
|
@ -40,7 +40,7 @@ def keep_episodes(show, keep):
|
|||
""" Delete all but last count episodes in show. """
|
||||
deleted = 0
|
||||
print('%s Cleaning %s to %s episodes.' % (datestr(), show.title, keep))
|
||||
sort = lambda x:x.originallyAvailableAt or x.addedAt
|
||||
sort = lambda x: x.originallyAvailableAt or x.addedAt
|
||||
items = sorted(show.episodes(), key=sort, reverse=True)
|
||||
for episode in items[keep:]:
|
||||
delete_episode(episode)
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
"""
|
||||
Backup and restore the watched status of Plex libraries to a json file.
|
||||
"""
|
||||
import argparse, json
|
||||
import argparse
|
||||
from collections import defaultdict
|
||||
import json
|
||||
from plexapi import utils
|
||||
|
||||
SECTIONS = ('movie', 'show')
|
||||
|
@ -32,7 +33,7 @@ def _item_key(item):
|
|||
|
||||
def _iter_sections(plex, opts):
|
||||
libraries = opts.libraries.split(',') if opts.libraries else []
|
||||
libraries = [l.strip().lower() for l in libraries]
|
||||
libraries = [lib.strip().lower() for lib in libraries]
|
||||
for section in plex.library.sections():
|
||||
title = section.title.lower()
|
||||
if section.type in SECTIONS and (not libraries or title in libraries):
|
||||
|
@ -76,11 +77,11 @@ def restore_watched(plex, opts):
|
|||
skey = section.title.lower()
|
||||
for item in _iter_items(section):
|
||||
ikey = _item_key(item)
|
||||
sval = source.get(skey,{}).get(ikey)
|
||||
sval = source.get(skey, {}).get(ikey)
|
||||
if sval is None:
|
||||
raise SystemExit('%s not found' % ikey)
|
||||
if (sval is not None and item.isWatched != sval) and (not opts.watchedonly or sval):
|
||||
differences[skey][ikey] = {'isWatched':sval, 'item':item}
|
||||
differences[skey][ikey] = {'isWatched': sval, 'item': item}
|
||||
print('Applying %s differences to destination' % len(differences))
|
||||
import pprint; pprint.pprint(differences)
|
||||
|
||||
|
@ -93,7 +94,8 @@ if __name__ == '__main__':
|
|||
parser.add_argument('-u', '--username', default=CONFIG.get('auth.myplex_username'), help='Plex username')
|
||||
parser.add_argument('-p', '--password', default=CONFIG.get('auth.myplex_password'), help='Plex password')
|
||||
parser.add_argument('-s', '--servername', help='Plex server name')
|
||||
parser.add_argument('-w', '--watchedonly', default=False, action='store_true', help='Only backup or restore watched items.')
|
||||
parser.add_argument('-w', '--watchedonly', default=False, action='store_true',
|
||||
help='Only backup or restore watched items.')
|
||||
parser.add_argument('-l', '--libraries', help='Only backup or restore the specified libraries (comma separated).')
|
||||
opts = parser.parse_args()
|
||||
account = utils.getMyPlexAccount(opts)
|
||||
|
|
|
@ -121,15 +121,15 @@ def setup_music(music_path, docker=False):
|
|||
"Broke for free": {
|
||||
"Layers": [
|
||||
"1 - As Colorful As Ever.mp3",
|
||||
#"02 - Knock Knock.mp3",
|
||||
#"03 - Only Knows.mp3",
|
||||
#"04 - If.mp3",
|
||||
#"05 - Note Drop.mp3",
|
||||
#"06 - Murmur.mp3",
|
||||
#"07 - Spellbound.mp3",
|
||||
#"08 - The Collector.mp3",
|
||||
#"09 - Quit Bitching.mp3",
|
||||
#"10 - A Year.mp3",
|
||||
# "02 - Knock Knock.mp3",
|
||||
# "03 - Only Knows.mp3",
|
||||
# "04 - If.mp3",
|
||||
# "05 - Note Drop.mp3",
|
||||
# "06 - Murmur.mp3",
|
||||
# "07 - Spellbound.mp3",
|
||||
# "08 - The Collector.mp3",
|
||||
# "09 - Quit Bitching.mp3",
|
||||
# "10 - A Year.mp3",
|
||||
]
|
||||
},
|
||||
|
||||
|
@ -279,7 +279,7 @@ def add_library_section(server, section):
|
|||
raise SystemExit("Timeout adding section to Plex instance.")
|
||||
|
||||
|
||||
def create_section(server, section, opts):
|
||||
def create_section(server, section, opts): # noqa: C901
|
||||
processed_media = 0
|
||||
expected_media_count = section.pop("expected_media_count", 0)
|
||||
expected_media_type = (section["type"],)
|
||||
|
@ -337,7 +337,7 @@ def create_section(server, section, opts):
|
|||
notifier.stop()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if __name__ == "__main__": # noqa: C901
|
||||
default_ip = get_default_ip()
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
# Authentication arguments
|
||||
|
|
|
@ -63,10 +63,10 @@ def get_item_from_url(url):
|
|||
server = servers[0].connect()
|
||||
return server.fetchItem(key)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Command line parser
|
||||
from plexapi import CONFIG
|
||||
from tqdm import tqdm
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('-u', '--username', help='Your Plex username',
|
||||
default=CONFIG.get('auth.myplex_username'))
|
||||
|
@ -84,4 +84,3 @@ if __name__ == '__main__':
|
|||
url = item._server.url('%s?download=1' % part.key)
|
||||
filepath = utils.download(url, token=item._server._token, filename=filename, savepath=os.getcwd(),
|
||||
session=item._server._session, showstatus=True)
|
||||
#print(' %s' % filepath)
|
||||
|
|
|
@ -6,7 +6,14 @@ items to build a collection of attributes on each media type. The resulting list
|
|||
can be compared with the current object implementation in python-plexapi to track
|
||||
new attributes and deprecate old ones.
|
||||
"""
|
||||
import argparse, copy, pickle, plexapi, os, re, sys, time
|
||||
import argparse
|
||||
import copy
|
||||
import pickle
|
||||
import plexapi
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
from os.path import abspath, dirname, join
|
||||
from collections import defaultdict
|
||||
from datetime import datetime
|
||||
|
@ -296,19 +303,19 @@ class PlexAttributes():
|
|||
def _safe_connect(self, elem):
|
||||
try:
|
||||
return elem.connect()
|
||||
except:
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def _safe_reload(self, elem):
|
||||
try:
|
||||
elem.reload()
|
||||
except:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def _(text, color):
|
||||
FMTSTR = '\033[%dm%s\033[0m'
|
||||
COLORS = {'blue':34, 'cyan':36, 'green':32, 'grey':30, 'purple':35, 'red':31, 'white':37, 'yellow':33}
|
||||
COLORS = {'blue': 34, 'cyan': 36, 'green': 32, 'grey': 30, 'purple': 35, 'red': 31, 'white': 37, 'yellow': 33}
|
||||
return FMTSTR % (COLORS[color], text)
|
||||
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ from os.path import abspath, dirname, join
|
|||
from plexapi import utils
|
||||
from plexapi.server import PlexServer
|
||||
|
||||
GROUPNAMES = {'butler':'Scheduled Task', 'dlna':'DLNA'}
|
||||
GROUPNAMES = {'butler': 'Scheduled Task', 'dlna': 'DLNA'}
|
||||
OUTPUT = join(dirname(dirname(abspath(__file__))), 'docs/settingslist.rst')
|
||||
|
||||
|
||||
|
@ -20,7 +20,7 @@ def _setting_group(setting):
|
|||
return setting.group
|
||||
|
||||
|
||||
def _write_settings(handle, groups, group):
|
||||
def _write_settings(handle, groups, group): # noqa: C901
|
||||
title = GROUPNAMES.get(group, group.title())
|
||||
print('\n%s Settings\n%s' % (title, '-' * (len(title) + 9)))
|
||||
handle.write('%s Settings\n%s\n' % (title, '-' * (len(title) + 9)))
|
||||
|
|
|
@ -47,7 +47,7 @@ def _list_devices(account, servers):
|
|||
def _test_servers(servers):
|
||||
items, seen = [], set()
|
||||
print('Finding Plex clients..')
|
||||
listargs = [[PlexServer, s, t, None, 5] for s,t in servers.items()]
|
||||
listargs = [[PlexServer, s, t, None, 5] for s, t in servers.items()]
|
||||
results = utils.threaded(_connect, listargs)
|
||||
for url, token, plex, runtime in results:
|
||||
clients = plex.clients() if plex else []
|
||||
|
|
|
@ -41,17 +41,17 @@ def _iter_items(search):
|
|||
|
||||
if __name__ == '__main__':
|
||||
datestr = lambda: datetime.now().strftime('%Y-%m-%d %H:%M:%S') # noqa
|
||||
print('{datestr} Starting plex-markwatched script..'.format(datestr=datestr()))
|
||||
print(f'{datestr()} Starting plex-markwatched script..')
|
||||
plex = PlexServer()
|
||||
for section in plex.library.sections():
|
||||
print('{datestr} Checking {section.title} for unwatched items..'.format(datestr=datestr()))
|
||||
print(f'{datestr()} Checking {section.title} for unwatched items..')
|
||||
for item in _iter_items(section.search(collection='markwatched')):
|
||||
if not item.isWatched:
|
||||
print('{datestr} Marking {_get_title(item)} watched.'.format(datestr=datestr()))
|
||||
print(f'{datestr()} Marking {_get_title(item)} watched.')
|
||||
item.markWatched()
|
||||
# Check all OnDeck items
|
||||
print('{datestr} Checking OnDeck for unwatched items..'.format(datestr=datestr()))
|
||||
print(f'{datestr()} Checking OnDeck for unwatched items.')
|
||||
for item in plex.library.onDeck():
|
||||
if not item.isWatched and _has_markwatched_tag(item):
|
||||
print('{datestr} Marking {_get_title(item)} watched.'.format(datestr=datestr()))
|
||||
print(f'{datestr()} Marking {_get_title(item)} watched.')
|
||||
item.markWatched()
|
||||
|
|
|
@ -90,10 +90,9 @@ def main():
|
|||
if arguments.tag:
|
||||
subprocess.run(["git", "tag", str(bumped), "-m", f"Release {bumped}"])
|
||||
|
||||
|
||||
def test_bump_version():
|
||||
"""Make sure it all works."""
|
||||
import pytest
|
||||
|
||||
assert bump_version(Version("4.7.0"), "patch") == Version("4.7.1")
|
||||
assert bump_version(Version("4.7.0"), "minor") == Version("4.8.0")
|
||||
assert bump_version(Version("4.7.3"), "minor") == Version("4.8.0")
|
||||
|
|
Loading…
Reference in a new issue