Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hotfix 0.2.10 #5163

Merged
merged 12 commits into from
Sep 9, 2018
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@

-----

## 0.2.10 (2018-09-09)

#### Fixes
- Fixed UI bugs in home page (when using "split home in tabs") and status page ([#5126](https://github.com/pymedusa/Medusa/pull/5126) + [#5127](https://github.com/pymedusa/Medusa/pull/5127))
- Fixed error due to `null` values in the episodes database table ([#5132](https://github.com/pymedusa/Medusa/pull/5132))
- Fixed extraneous calls to AniDB when navigating to any show's page ([#5166](https://github.com/pymedusa/Medusa/pull/5166))
- Fixed being unable to start Medusa due to an import error ([#5145](https://github.com/pymedusa/Medusa/pull/5145))
- Fixed UI bugs on:
- Home page (when using "split home in tabs") ([#5126](https://github.com/pymedusa/Medusa/pull/5126))
- Status page ([#5127](https://github.com/pymedusa/Medusa/pull/5127))
- Preview Rename page ([#5169](https://github.com/pymedusa/Medusa/pull/5169))
- Post Processing Config page - saving `select-list` values incorrectly ([#5165](https://github.com/pymedusa/Medusa/pull/5165))
- Fixed bug in TorrentLeech provider when fetching multiple pages of results ([#5172](https://github.com/pymedusa/Medusa/pull/5172))

-----

## 0.2.9 (2018-09-06)

#### Improvements
Expand Down
7 changes: 7 additions & 0 deletions dredd/api-description.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ paths:
description: Filter series based on paused status
type: boolean
- $ref: '#/parameters/detailed'
- $ref: '#/parameters/fetch'
- $ref: '#/parameters/page'
- $ref: '#/parameters/limit'
- $ref: '#/parameters/sort'
Expand Down Expand Up @@ -1829,6 +1830,12 @@ parameters:
required: false
description: Whether response should contain detailed information
type: boolean
fetch:
name: fetch
in: query
required: false
description: Whether response should fetch external information
type: boolean
page:
name: page
in: query
Expand Down
2 changes: 0 additions & 2 deletions ext/backports/__init__.py

This file was deleted.

1 change: 1 addition & 0 deletions ext/configparser.pth
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import sys, types, os;has_mfs = sys.version_info > (3, 5);p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('backports',));importlib = has_mfs and __import__('importlib.util');has_mfs and __import__('importlib.machinery');m = has_mfs and sys.modules.setdefault('backports', importlib.util.module_from_spec(importlib.machinery.PathFinder.find_spec('backports', [os.path.dirname(p)])));m = m or sys.modules.setdefault('backports', types.ModuleType('backports'));mp = (m or []) and m.__dict__.setdefault('__path__',[]);(p not in mp) and mp.append(p)
2 changes: 1 addition & 1 deletion ext/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
:: | `chardet` | [3.0.4](https://pypi.org/project/chardet/3.0.4/) | **`medusa`**, `beautifulsoup4`, `feedparser`, `html5lib`, `pysrt`, `requests`, `subliminal` | -
:: | `cloudflare-scrape` | pymedusa/[320456e](https://github.com/pymedusa/cloudflare-scrape/tree/320456e8b28cedb807363a7a892b1379db843f66) | **`medusa`** | Module: `cfscrape`
:: | <code><b>configobj</b>.py</code><br>`validate.py`<br>`_version.py` | [5.0.6](https://pypi.org/project/configobj/5.0.6/) | **`medusa`** | -
:: | <code><b>configparser</b>.py</code><br>`backports.configparser` | [3.5.0](https://pypi.org/project/configparser/3.5.0/) | `adba` | -
:: | <code><b>configparser</b>.py</code><br>`configparser.pth`<br>`backports.configparser` | [3.5.0](https://pypi.org/project/configparser/3.5.0/) | `adba` | `configparser.pth` was renamed from `configparser-3.5.0-py2.7-nspkg.pth`
:: | <code><b>contextlib2</b>.py</code> | [0.5.5](https://pypi.org/project/contextlib2/0.5.5/) | **`medusa`**, `tvdbapiv2`, `vcrpy`(?) | Markers: `python_version < '3.5'`
:: | <code><b>decorator</b>.py</code> | [4.3.0](https://pypi.org/project/decorator/4.3.0/) | `validators` | -
:: | `dirtyjson` | [1.0.7](https://pypi.org/project/dirtyjson/1.0.7/) | **`medusa`** | -
Expand Down
38 changes: 38 additions & 0 deletions medusa/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,34 @@
logger = logging.getLogger(__name__)


def fix_incorrect_list_values(data):
"""
@TODO: Remove this in a future version.

Due to a bug introduced in v0.2.9, the value might be a string representing a Python dict.
See: https://github.com/pymedusa/Medusa/issues/5155

Example: `"{u'id': 0, u'value': u'!sync'}"` to `"!sync"`
"""
import ast

result = []
for item in data:
if not item:
continue
if not (item.startswith('{') and item.endswith('}')):
# Simple value, don't do anything to it
result.append(item)
continue
try:
# Get the value: `{u'id': 0, u'value': u'!sync'}` => `!sync`
result.append(ast.literal_eval(item)['value'])
except (SyntaxError, KeyError):
pass

return result


class Application(object):
"""Main application module."""

Expand Down Expand Up @@ -604,7 +632,11 @@ def initialize(self, console_logging=True):
app.RANDOMIZE_PROVIDERS = bool(check_setting_int(app.CFG, 'General', 'randomize_providers', 0))
app.ALLOW_HIGH_PRIORITY = bool(check_setting_int(app.CFG, 'General', 'allow_high_priority', 1))
app.SKIP_REMOVED_FILES = bool(check_setting_int(app.CFG, 'General', 'skip_removed_files', 0))

app.ALLOWED_EXTENSIONS = check_setting_list(app.CFG, 'General', 'allowed_extensions', app.ALLOWED_EXTENSIONS)
# @TODO: Remove this in a future version.
app.ALLOWED_EXTENSIONS = fix_incorrect_list_values(app.ALLOWED_EXTENSIONS)

app.USENET_RETENTION = check_setting_int(app.CFG, 'General', 'usenet_retention', 500)
app.CACHE_TRIMMING = bool(check_setting_int(app.CFG, 'General', 'cache_trimming', 0))
app.MAX_CACHE_AGE = check_setting_int(app.CFG, 'General', 'max_cache_age', 30)
Expand Down Expand Up @@ -646,7 +678,11 @@ def initialize(self, console_logging=True):
app.MOVE_ASSOCIATED_FILES = bool(check_setting_int(app.CFG, 'General', 'move_associated_files', 0))
app.POSTPONE_IF_SYNC_FILES = bool(check_setting_int(app.CFG, 'General', 'postpone_if_sync_files', 1))
app.POSTPONE_IF_NO_SUBS = bool(check_setting_int(app.CFG, 'General', 'postpone_if_no_subs', 0))

app.SYNC_FILES = check_setting_list(app.CFG, 'General', 'sync_files', app.SYNC_FILES)
# @TODO: Remove this in a future version.
app.SYNC_FILES = fix_incorrect_list_values(app.SYNC_FILES)

app.NFO_RENAME = bool(check_setting_int(app.CFG, 'General', 'nfo_rename', 1))
app.CREATE_MISSING_SHOW_DIRS = bool(check_setting_int(app.CFG, 'General', 'create_missing_show_dirs', 0))
app.ADD_SHOWS_WO_DIR = bool(check_setting_int(app.CFG, 'General', 'add_shows_wo_dir', 0))
Expand Down Expand Up @@ -919,6 +955,8 @@ def initialize(self, console_logging=True):
app.NO_RESTART = bool(check_setting_int(app.CFG, 'General', 'no_restart', 0))

app.EXTRA_SCRIPTS = [x.strip() for x in check_setting_list(app.CFG, 'General', 'extra_scripts')]
# @TODO: Remove this in a future version.
app.EXTRA_SCRIPTS = fix_incorrect_list_values(app.EXTRA_SCRIPTS)

app.USE_LISTVIEW = bool(check_setting_int(app.CFG, 'General', 'use_listview', 0))

Expand Down
2 changes: 1 addition & 1 deletion medusa/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
# To enable, set SPOOF_USER_AGENT = True
SPOOF_USER_AGENT = False
INSTANCE_ID = str(uuid.uuid1())
VERSION = '0.2.9'
VERSION = '0.2.10'
USER_AGENT = 'Medusa/{version} ({system}; {release}; {instance})'.format(
version=VERSION, system=platform.system(), release=platform.release(),
instance=INSTANCE_ID)
Expand Down
36 changes: 34 additions & 2 deletions medusa/init/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import mimetypes
import os
import shutil
import site
import sys


Expand Down Expand Up @@ -46,8 +47,39 @@ def _ext_lib_location():


def _configure_syspath():
sys.path.insert(1, _lib_location())
sys.path.insert(1, _ext_lib_location())
"""Add the vendored libraries into `sys.path`."""
# Note: These paths will be inserted into `sys.path` in reverse order (LIFO)
# So the last path on this list will be inserted as the first path on `sys.path`
# right after the current working dir.
# For example: [ cwd, pathN, ..., path1, path0, <rest_of_sys.path> ]

paths_to_insert = [
_lib_location(),
_ext_lib_location()
]

if sys.version_info[0] == 2:
# Add Python 2-only vendored libraries
paths_to_insert.extend([
# path_to_lib2,
# path_to_ext2
])
elif sys.version_info[0] == 3:
# Add Python 3-only vendored libraries
paths_to_insert.extend([
# path_to_lib3,
# path_to_ext3
])

# Insert paths into `sys.path` and handle `.pth` files
# Inspired by: https://bugs.python.org/issue7744
for dirpath in paths_to_insert:
# Clear `sys.path`
sys.path, remainder = sys.path[:1], sys.path[1:]
# Add directory as a site-packages directory and handle `.pth` files
site.addsitedir(dirpath)
# Restore rest of `sys.path`
sys.path.extend(remainder)


def _register_utf8_codec():
Expand Down
4 changes: 3 additions & 1 deletion medusa/providers/torrent/json/torrentleech.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
from requests.compat import urljoin
from requests.utils import dict_from_cookiejar

from six.moves import range

log = BraceAdapter(logging.getLogger(__name__))
log.logger.addHandler(logging.NullHandler())

Expand Down Expand Up @@ -217,7 +219,7 @@ def _pagination(self, data, mode, search_url):
' in your profile options on {name}.', {'name': self.name})

try:
pages = math.ceil(self.max_torrents / per_page)
pages = int(math.ceil(self.max_torrents / per_page))
except ZeroDivisionError:
pages = 1

Expand Down
9 changes: 7 additions & 2 deletions medusa/server/api/v2/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ def filter_series(current):

if not series_slug:
detailed = self._parse_boolean(self.get_argument('detailed', default=False))
data = [s.to_json(detailed=detailed) for s in Series.find_series(predicate=filter_series)]
fetch = self._parse_boolean(self.get_argument('fetch', default=False))
data = [
s.to_json(detailed=detailed, fetch=fetch)
for s in Series.find_series(predicate=filter_series)
]
return self._paginate(data, sort='title')

identifier = SeriesIdentifier.from_slug(series_slug)
Expand All @@ -61,7 +65,8 @@ def filter_series(current):
return self._not_found('Series not found')

detailed = self._parse_boolean(self.get_argument('detailed', default=True))
data = series.to_json(detailed=detailed)
fetch = self._parse_boolean(self.get_argument('fetch', default=False))
data = series.to_json(detailed=detailed, fetch=fetch)
if path_param:
if path_param not in data:
return self._bad_request("Invalid path parameter '{0}'".format(path_param))
Expand Down
2 changes: 1 addition & 1 deletion medusa/tv/episode.py
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,7 @@ def load_from_db(self, season, episode):
self.airdate = date.fromordinal(int(sql_results[0][b'airdate']))
self.status = int(sql_results[0][b'status'] or UNSET)
self.quality = int(sql_results[0][b'quality'] or Quality.NA)
self.watched = int(sql_results[0][b'watched'])
self.watched = bool(sql_results[0][b'watched'])

# don't overwrite my location
if sql_results[0][b'location']:
Expand Down
38 changes: 24 additions & 14 deletions medusa/tv/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -1965,8 +1965,13 @@ def __unicode__(self):
to_return += u'anime: {0}\n'.format(self.is_anime)
return to_return

def to_json(self, detailed=True):
"""Return JSON representation."""
def to_json(self, detailed=True, fetch=False):
"""
Return JSON representation.

:param detailed: Append seasons & episodes data as well
:param fetch: Fetch and append external data (for example AniDB release groups)
"""
bw_list = self.release_groups or BlackAndWhiteList(self)

data = {}
Expand Down Expand Up @@ -2018,22 +2023,27 @@ def to_json(self, detailed=True):
data['config']['defaultEpisodeStatus'] = self.default_ep_status_name
data['config']['aliases'] = list(self.aliases)
data['config']['release'] = {}
# These are for now considered anime-only options, as they query anidb for available release groups.
data['config']['release']['ignoredWords'] = self.release_ignore_words
data['config']['release']['requiredWords'] = self.release_required_words

# These are for now considered anime-only options
if self.is_anime:
data['config']['release']['blacklist'] = bw_list.blacklist
data['config']['release']['whitelist'] = bw_list.whitelist
try:
data['config']['release']['allgroups'] = get_release_groups_for_anime(self.name)
except AnidbAdbaConnectionException as error:
data['config']['release']['allgroups'] = []
log.warning(
'An anidb adba exception occurred when attempting to get the release groups for the show {show}'
'\nError: {error}',
{'show': self.name, 'error': error}
)

data['config']['release']['ignoredWords'] = self.release_ignore_words
data['config']['release']['requiredWords'] = self.release_required_words
# Fetch data from external sources
if fetch:
# These are for now considered anime-only options, as they query anidb for available release groups.
if self.is_anime:
try:
data['config']['release']['allgroups'] = get_release_groups_for_anime(self.name)
except AnidbAdbaConnectionException as error:
data['config']['release']['allgroups'] = []
log.warning(
'An anidb adba exception occurred when attempting to get the release groups for the show {show}'
'\nError: {error}',
{'show': self.name, 'error': error}
)

if detailed:
episodes = self.get_all_episodes()
Expand Down
15 changes: 12 additions & 3 deletions themes-default/slim/src/components/config-post-processing.vue
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
<span>Sync File Extensions</span>
</label>
<div class="col-sm-10 content">
<select-list name="sync_files" id="sync_files" csv-enabled :list-items="postProcessing.syncFiles" @change="postProcessing.syncFiles = $event"></select-list>
<select-list name="sync_files" id="sync_files" csv-enabled :list-items="postProcessing.syncFiles" @change="onChangeSyncFiles"></select-list>
<span>comma seperated list of extensions or filename globs Medusa ignores when Post Processing</span>
</div>
</div>
Expand Down Expand Up @@ -154,7 +154,7 @@
<span>Keep associated file extensions</span>
</label>
<div class="col-sm-10 content">
<select-list name="allowed_extensions" id="allowed_extensions" csv-enabled :list-items="postProcessing.allowedExtensions" @change="postProcessing.allowedExtensions = $event"></select-list>
<select-list name="allowed_extensions" id="allowed_extensions" csv-enabled :list-items="postProcessing.allowedExtensions" @change="onChangeAllowedExtensions"></select-list>
<span>Comma seperated list of associated file extensions Medusa should keep while post processing.</span><br>
<span>Leaving it empty means all associated files will be deleted</span>
</div>
Expand Down Expand Up @@ -229,7 +229,7 @@
<span>Extra Scripts</span>
</label>
<div class="col-sm-10 content">
<select-list name="extra_scripts" id="extra_scripts" csv-enabled :list-items="postProcessing.extraScripts" @change="postProcessing.extraScripts = $event"></select-list>
<select-list name="extra_scripts" id="extra_scripts" csv-enabled :list-items="postProcessing.extraScripts" @change="onChangeExtraScripts"></select-list>
<span>See <app-link :href="postProcessing.extraScriptsUrl" class="wikie"><strong>Wiki</strong></app-link> for script arguments description and usage.</span>
</div>
</div>
Expand Down Expand Up @@ -433,6 +433,15 @@ export default {
};
},
methods: {
onChangeSyncFiles(items) {
this.postProcessing.syncFiles = items.map(item => item.value);
},
onChangeAllowedExtensions(items) {
this.postProcessing.allowedExtensions = items.map(item => item.value);
},
onChangeExtraScripts(items) {
this.postProcessing.extraScripts = items.map(item => item.value);
},
saveNaming(values) {
if (!this.configLoaded) {
return;
Expand Down
25 changes: 13 additions & 12 deletions themes-default/slim/src/components/select-list.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ export default {
},
data() {
return {
lock: false,
editItems: [],
newItem: '',
indexCounter: 0,
Expand All @@ -64,20 +63,24 @@ export default {
};
},
created() {
/*
These are needed in order to test the component,
but they break the component in the application:

this.editItems = this.sanitize(this.listItems);
this.csv = this.editItems.map(item => item.value).join(', ');
*/

/**
* ListItems property might receive values originating from the API,
* that are sometimes not avaiable when rendering.
* @TODO: Maybe we can remove this in the future.
* that are sometimes not available when rendering.
* @TODO: This is not ideal! Maybe we can remove this in the future.
*/
const unwatchProp = this.$watch('listItems', () => {
unwatchProp();

this.lock = true;
this.editItems = this.sanitize(this.listItems);
this.$nextTick(() => {
this.lock = false;
});
this.csv = this.editItems.map(x => x.value).join(', ');
this.csv = this.editItems.map(item => item.value).join(', ');
});
},
methods: {
Expand Down Expand Up @@ -138,7 +141,7 @@ export default {
}
}));
} else {
this.csv = this.editItems.map(x => x.value).join(', ');
this.csv = this.editItems.map(item => item.value).join(', ');
}
},
/**
Expand All @@ -154,9 +157,7 @@ export default {
watch: {
editItems: {
handler() {
if (!this.lock) {
this.$emit('change', this.editItems);
}
this.$emit('change', this.editItems);
},
deep: true
},
Expand Down
Loading