Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/origin/develop' into feature/vu…
Browse files Browse the repository at this point in the history
…eify-display-show-rebased

# Conflicts:
#	themes-default/slim/package.json
#	themes-default/slim/src/components/show-header.vue
#	themes-default/slim/src/store/modules/statuses.js
#	themes-default/slim/yarn.lock
#	themes/dark/assets/js/medusa-runtime.js
#	themes/light/assets/js/medusa-runtime.js
  • Loading branch information
p0psicles committed Jun 3, 2019
2 parents a0d4a63 + 2000fe7 commit f653fd1
Show file tree
Hide file tree
Showing 54 changed files with 2,277 additions and 1,699 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#### Improvements
- Converted the sub-menu into a Vue SFC ([#6724](https://github.com/pymedusa/Medusa/pull/6724))
- Converted View Log page into a Vue SFC ([#6738](https://github.com/pymedusa/Medusa/pull/6738))
- Converted the Quality Chooser into a Vue SFC ([#6737](https://github.com/pymedusa/Medusa/pull/6737))

#### Fixes
- Fixed lists not being saved when used with comma separated items ([#6428](https://github.com/pymedusa/Medusa/pull/6428))
Expand Down
5 changes: 2 additions & 3 deletions dredd/api-description.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1075,7 +1075,7 @@ definitions:
items:
type: integer
format: int32
prefered:
preferred:
type: array
items:
type: integer
Expand Down Expand Up @@ -2566,8 +2566,7 @@ parameters:
type: string
enum:
- main
- statuses
- qualities
- consts
- metadata
- search
- notifiers
Expand Down
56 changes: 26 additions & 30 deletions medusa/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,16 @@
import platform
import re
import uuid
from builtins import object
from builtins import str
from functools import reduce

import knowit

from medusa.recompiled import tags
from medusa.search import PROPER_SEARCH

from six import PY3, viewitems
from six import text_type, viewitems

if PY3:
long = int

INSTANCE_ID = str(uuid.uuid1())
INSTANCE_ID = text_type(uuid.uuid1())
VERSION = '0.3.1'
USER_AGENT = 'Medusa/{version} ({system}; {release}; {instance})'.format(
version=VERSION, system=platform.system(), release=platform.release(),
Expand Down Expand Up @@ -176,7 +171,7 @@ class Quality(object):
UHD_8K_BLURAY: '8K UHD BluRay',
}

sceneQualityStrings = {
scene_quality_strings = {
NA: 'N/A',
UNKNOWN: 'Unknown',
SDTV: '',
Expand All @@ -196,33 +191,34 @@ class Quality(object):
UHD_8K_BLURAY: '4320p BluRay',
}

combinedQualityStrings = {
combined_quality_strings = {
ANYHDTV: 'HDTV',
ANYWEBDL: 'WEB-DL',
ANYBLURAY: 'BluRay'
ANYBLURAY: 'BluRay',
}

cssClassStrings = {
# A reverse map from quality values and any-sets to "keys"
quality_keys = {
NA: 'na',
UNKNOWN: 'Unknown',
SDTV: 'SDTV',
SDDVD: 'SDDVD',
HDTV: 'HD720p',
RAWHDTV: 'RawHD',
FULLHDTV: 'HD1080p',
HDWEBDL: 'HD720p',
FULLHDWEBDL: 'HD1080p',
HDBLURAY: 'HD720p',
FULLHDBLURAY: 'HD1080p',
UHD_4K_TV: 'UHD-4K',
UHD_8K_TV: 'UHD-8K',
UHD_4K_WEBDL: 'UHD-4K',
UHD_8K_WEBDL: 'UHD-8K',
UHD_4K_BLURAY: 'UHD-4K',
UHD_8K_BLURAY: 'UHD-8K',
ANYHDTV: 'any-hd',
ANYWEBDL: 'any-hd',
ANYBLURAY: 'any-hd'
UNKNOWN: 'unknown',
SDTV: 'sdtv',
SDDVD: 'sddvd',
HDTV: 'hdtv',
RAWHDTV: 'rawhdtv',
FULLHDTV: 'fullhdtv',
HDWEBDL: 'hdwebdl',
FULLHDWEBDL: 'fullhdwebdl',
HDBLURAY: 'hdbluray',
FULLHDBLURAY: 'fullhdbluray',
UHD_4K_TV: 'uhd4ktv',
UHD_4K_WEBDL: 'uhd4kwebdl',
UHD_4K_BLURAY: 'uhd4kbluray',
UHD_8K_TV: 'uhd8ktv',
UHD_8K_WEBDL: 'uhd8kwebdl',
UHD_8K_BLURAY: 'uhd8kbluray',
ANYHDTV: 'anyhdtv',
ANYWEBDL: 'anywebdl',
ANYBLURAY: 'anybluray',
}

@staticmethod
Expand Down
17 changes: 5 additions & 12 deletions medusa/search/manual.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import logging
import threading
import time
from builtins import zip
from datetime import datetime

from dateutil import parser
Expand All @@ -26,6 +25,8 @@
from medusa.show.naming import contains_at_least_one_word, filter_bad_releases
from medusa.show.show import Show

from six.moves import zip

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

Expand All @@ -34,16 +35,6 @@
SEARCH_STATUS_SEARCHING = 'searching'


def get_quality_class(ep_obj):
"""Find the quality class for the episode."""
if ep_obj.quality in Quality.cssClassStrings:
quality_class = Quality.cssClassStrings[ep_obj.quality]
else:
quality_class = Quality.cssClassStrings[Quality.UNKNOWN]

return quality_class


def get_episode(series_id, season=None, episode=None, absolute=None, indexer=None):
"""
Get a specific episode object based on show, season and episode number.
Expand Down Expand Up @@ -103,8 +94,10 @@ def get_episodes(search_thread, searchstatus):
'season': ep.season,
'searchstatus': searchstatus,
'status': statusStrings[ep.status],
# TODO: `quality_name` and `quality_style` should both be removed
# when converting forced/manual episode search to Vue (use QualityPill component directly)
'quality_name': Quality.qualityStrings[ep.quality],
'quality_style': get_quality_class(ep),
'quality_style': Quality.quality_keys.get(ep.quality) or Quality.quality_keys[Quality.UNKNOWN],
'overview': Overview.overviewStrings[series_obj.get_overview(
ep.status, ep.quality,
manually_searched=ep.manually_searched
Expand Down
120 changes: 58 additions & 62 deletions medusa/server/api/v2/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
ws,
)
from medusa.common import IGNORED, Quality, SKIPPED, WANTED
from medusa.helpers.utils import to_camel_case
from medusa.indexers.indexer_config import get_indexer_config
from medusa.logger.adapters.style import BraceAdapter
from medusa.server.api.v2.base import (
Expand All @@ -34,6 +35,7 @@
)

from six import iteritems, itervalues, text_type
from six.moves import map

from tornado.escape import json_decode

Expand Down Expand Up @@ -447,7 +449,8 @@ def sections(cls):
"""Get the available section names."""
return [
name[5:]
for (name, function) in inspect.getmembers(cls, predicate=inspect.isfunction)
for (name, function)
in inspect.getmembers(cls, predicate=lambda f: inspect.isfunction(f) or inspect.ismethod(f))
if name.startswith('data_')
]

Expand Down Expand Up @@ -595,72 +598,65 @@ def data_main():

return section_data

@staticmethod
def data_qualities():
"""Qualities."""
# The consts info only needs to be generated once.
_generated_data_consts = {}

@classmethod
def data_consts(cls):
"""Constant values - values that will never change during runtime."""
if cls._generated_data_consts:
return cls._generated_data_consts

section_data = {}

section_data['values'] = {}
section_data['values']['na'] = common.Quality.NA
section_data['values']['unknown'] = common.Quality.UNKNOWN
section_data['values']['sdtv'] = common.Quality.SDTV
section_data['values']['sddvd'] = common.Quality.SDDVD
section_data['values']['hdtv'] = common.Quality.HDTV
section_data['values']['rawhdtv'] = common.Quality.RAWHDTV
section_data['values']['fullhdtv'] = common.Quality.FULLHDTV
section_data['values']['hdwebdl'] = common.Quality.HDWEBDL
section_data['values']['fullhdwebdl'] = common.Quality.FULLHDWEBDL
section_data['values']['hdbluray'] = common.Quality.HDBLURAY
section_data['values']['fullhdbluray'] = common.Quality.FULLHDBLURAY
section_data['values']['uhd4ktv'] = common.Quality.UHD_4K_TV
section_data['values']['uhd4kwebdl'] = common.Quality.UHD_4K_WEBDL
section_data['values']['uhd4kbluray'] = common.Quality.UHD_4K_BLURAY
section_data['values']['uhd8ktv'] = common.Quality.UHD_8K_TV
section_data['values']['uhd8kwebdl'] = common.Quality.UHD_8K_WEBDL
section_data['values']['uhd8kbluray'] = common.Quality.UHD_8K_BLURAY

section_data['anySets'] = {}
section_data['anySets']['anyhdtv'] = common.Quality.ANYHDTV
section_data['anySets']['anywebdl'] = common.Quality.ANYWEBDL
section_data['anySets']['anybluray'] = common.Quality.ANYBLURAY

section_data['presets'] = {}
section_data['presets']['any'] = common.ANY
section_data['presets']['sd'] = common.SD
section_data['presets']['hd'] = common.HD
section_data['presets']['hd720p'] = common.HD720p
section_data['presets']['hd1080p'] = common.HD1080p
section_data['presets']['uhd'] = common.UHD
section_data['presets']['uhd4k'] = common.UHD_4K
section_data['presets']['uhd8k'] = common.UHD_8K

section_data['strings'] = {}
section_data['strings']['values'] = common.Quality.qualityStrings
section_data['strings']['anySets'] = common.Quality.combinedQualityStrings
section_data['strings']['presets'] = common.qualityPresetStrings
section_data['strings']['cssClass'] = common.Quality.cssClassStrings
section_data['qualities'] = {}

return section_data
def make_quality(value, name, key=None):
return {
'value': value,
'key': key or Quality.quality_keys.get(value),
'name': name
}

@staticmethod
def data_statuses():
"""Statuses."""
section_data = {}
section_data['qualities']['values'] = [
make_quality(value, name)
for (value, name)
in sorted(iteritems(common.Quality.qualityStrings))
]

section_data['qualities']['anySets'] = [
make_quality(value, name)
for (value, name)
in sorted(iteritems(common.Quality.combined_quality_strings))
]

section_data['qualities']['presets'] = [
make_quality(value, name, name.lower().replace('-', ''))
for (value, name)
in sorted(
iteritems(common.qualityPresetStrings),
# Sort presets based on the order defined in `qualityPresets`
key=lambda i: common.qualityPresets.index(i[0])
)
]

section_data['statuses'] = [
{
'value': value,
'key': to_camel_case(key.lower()),
'name': common.statusStrings[value],
}
for (value, key)
in map(
lambda key: (getattr(common, key), key),
# Sorted by value
('UNSET', 'UNAIRED', 'SNATCHED', 'WANTED', 'DOWNLOADED', 'SKIPPED', 'ARCHIVED',
'IGNORED', 'SNATCHED_PROPER', 'SUBTITLED', 'FAILED', 'SNATCHED_BEST')
)
]

section_data['values'] = {}
section_data['values']['unset'] = common.UNSET
section_data['values']['unaired'] = common.UNAIRED
section_data['values']['snatched'] = common.SNATCHED
section_data['values']['wanted'] = common.WANTED
section_data['values']['downloaded'] = common.DOWNLOADED
section_data['values']['skipped'] = common.SKIPPED
section_data['values']['archived'] = common.ARCHIVED
section_data['values']['ignored'] = common.IGNORED
section_data['values']['snatchedProper'] = common.SNATCHED_PROPER
section_data['values']['subtitled'] = common.SUBTITLED
section_data['values']['failed'] = common.FAILED
section_data['values']['snatchedBest'] = common.SNATCHED_BEST
section_data['strings'] = common.statusStrings
# Save it for next time
cls._generated_data_consts = section_data

return section_data

Expand Down
6 changes: 3 additions & 3 deletions medusa/tv/episode.py
Original file line number Diff line number Diff line change
Expand Up @@ -1522,9 +1522,9 @@ def release_group(series, name):
'%QN': Quality.qualityStrings[self.quality],
'%Q.N': dot(Quality.qualityStrings[self.quality]),
'%Q_N': us(Quality.qualityStrings[self.quality]),
'%SQN': Quality.sceneQualityStrings[self.quality] + encoder,
'%SQ.N': dot(Quality.sceneQualityStrings[self.quality] + encoder),
'%SQ_N': us(Quality.sceneQualityStrings[self.quality] + encoder),
'%SQN': Quality.scene_quality_strings[self.quality] + encoder,
'%SQ.N': dot(Quality.scene_quality_strings[self.quality] + encoder),
'%SQ_N': us(Quality.scene_quality_strings[self.quality] + encoder),
'%S': str(self.season),
'%0S': '%02d' % self.season,
'%E': str(self.episode),
Expand Down
41 changes: 40 additions & 1 deletion tests/apiv2/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

import pytest

from six import iteritems, itervalues, text_type
from six import integer_types, iteritems, itervalues, string_types, text_type

from tornado.httpclient import HTTPError

Expand Down Expand Up @@ -227,6 +227,45 @@ def test_config_get_not_found(http_client, create_url, auth_headers, config_main
assert 404 == error.value.code


@pytest.mark.gen_test
def test_config_get_consts(http_client, create_url, auth_headers):
# given

def gen_schema(data):
if isinstance(data, dict):
return {k: gen_schema(v) for (k, v) in iteritems(data)}
if isinstance(data, list):
return [json.loads(v) for v in set([json.dumps(gen_schema(v)) for v in data])]
if isinstance(data, string_types):
return 'str'
if isinstance(data, integer_types):
return 'int'
return type(data).__name__

expected_schema = gen_schema({
'qualities': {
'values': [{'value': 8, 'key': 'hdtv', 'name': 'HDTV'}],
'anySets': [{'value': 40, 'key': 'anyhdtv', 'name': 'ANYHDTV'}],
'presets': [{'value': 65518, 'key': 'any', 'name': 'ANY'}],
},
'statuses': [{'value': 3, 'key': 'wanted', 'name': 'Wanted'}],
})

url = create_url('/config/consts')

# when
response = yield http_client.fetch(url, **auth_headers)
data = json.loads(response.body)

# then
assert response.code == 200
assert expected_schema == gen_schema(data)
assert len(common.Quality.qualityStrings) == len(data['qualities']['values'])
assert len(common.Quality.combined_quality_strings) == len(data['qualities']['anySets'])
assert len(common.qualityPresetStrings) == len(data['qualities']['presets'])
assert len(common.statusStrings) == len(data['statuses'])


@pytest.fixture
def config_metadata(monkeypatch, app_config):
# initialize metadata_providers
Expand Down
Loading

0 comments on commit f653fd1

Please sign in to comment.