示例#1
0
 def _try_parse_value(cls, vals: utils.misc.dotdict,
                      child: lxml.objectify.ObjectifiedElement, tag: str,
                      text: str, custom_types: CustomTypes) -> bool:
     if tag == 'icon_url':
         vals.icon_url = text
     elif tag == 'banner_url':
         vals.banner_url = text
     elif tag == 'rating_info':
         vals.rating_info = custom_types['rating_info']._parse(child)
     elif tag == 'star_rating_info':
         vals.rating_stars = custom_types['rating_stars']._parse(child)
     elif tag == 'release_date_on_eshop':
         vals.release_date_eshop = text
     elif tag == 'release_date_on_retail':
         vals.release_date_retail = text
     elif tag == 'price_on_retail_detail':
         xmlutils.validate_schema(child, {
             'amount': None,
             'currency': None,
             'raw_value': None
         }, True)
         vals.price_retail = common.SamuraiPrice(
             float(child.raw_value.text)
             if hasattr(child, 'raw_value') else None, child.currency)
     else:
         return False
     return True
示例#2
0
    def _try_parse_value(cls, vals: utils.misc.dotdict, child: lxml.objectify.ObjectifiedElement, tag: str, text: str, custom_types: title_list.CustomTypes) -> bool:
        if 'is_public' not in vals:
            xml = child.getparent()
            vals.is_public = utils.misc.get_bool(xml.get('public'))

        if tag == 'formal_name':
            vals.formal_name = text
        elif tag == 'genres':
            vals.genres = []
            for genre in child.genre:
                xmlutils.validate_schema(genre, {'name': None}, False)
                vals.genres.append(common.IDName(int(genre.get('id')), genre.name.text))
        elif tag == 'keywords':
            vals.keywords = [keyword.text for keyword in getattr(child, 'keyword', [])]
        elif tag == 'ticket_available':
            vals.has_ticket = utils.misc.get_bool(text)
        elif tag == 'download_code_sales':
            vals.sales_download_code = utils.misc.get_bool(text)
        elif tag == 'download_card_sales':
            xmlutils.validate_schema(child, {'image_url': None}, True)
            vals.sales_download_card = SamuraiDownloadCardSales(
                utils.misc.get_bool(child.get('available')),
                xmlutils.get_text(child, 'image_url')
            )
        else:
            return super()._try_parse_value(vals, child, tag, text, custom_types)
        return True
示例#3
0
    def _read(self, reader, config):
        info = xmlutils.read_object(reader)
        assert info.tag == 'version_list_info'
        xmlutils.validate_schema(info, {'version': None, 'fqdn': None}, False)

        self.latest = int(info.version.text)
        self.fqdn = info.fqdn.text
示例#4
0
 def _read(self, reader, config):
     news_xml = xmlutils.load_root(reader, 'news')
     xmlutils.validate_schema(
         news_xml, {
             'news_entry': {
                 'headline': None,
                 'description': None,
                 'date': None,
                 'images': {
                     'image': None
                 }
             }
         }, True)
     self.entries = []
     for entry in getattr(news_xml, 'news_entry', []):
         if hasattr(entry, 'images'):
             images = [
                 SamuraiNewsImage(image.get('url'), image.get('type'),
                                  int(image.get('index')),
                                  int(image.get('width')),
                                  int(image.get('height')))
                 for image in entry.images.image
             ]
         else:
             images = []
         self.entries.append(
             SamuraiNewsEntry(entry.headline.text, entry.description.text,
                              entry.date.text, images))
示例#5
0
    def _read(self, reader, config):
        prices = xmlutils.load_root(reader, 'online_prices')
        xmlutils.validate_schema(
            prices, {
                'online_price': {
                    'aoc_id': None,
                    'eshop_sales_status': None,
                    'price': {
                        'regular_price': {
                            'amount': None,
                            'currency': None,
                            'raw_value': None
                        }
                    }
                }
            }, False)

        self.prices = {}
        for price in prices.online_price:
            assert len(price.price.getchildren()) == 1
            regular_price = price.price.regular_price
            self.prices[ids.ContentID(price.aoc_id.text)] = SamuraiDlcPrice(
                price.eshop_sales_status.text, regular_price.get('id'),
                common.SamuraiPrice(float(regular_price.raw_value.text),
                                    regular_price.currency.text))
示例#6
0
 def _try_parse_value(cls, vals: utils.misc.dotdict, child: lxml.objectify.ObjectifiedElement, tag: str, text: str, custom_types: CustomTypes) -> bool:
     if tag == 'icon_url':
         vals.icon_url = text
     elif tag == 'banner_url':
         vals.banner_url = text
     elif tag == 'thumbnail_url':
         vals.thumbnail_url = text
     elif tag == 'title':
         xmlutils.validate_schema(child, {'name': None, 'icon_url': None, 'banner_url': None, 'thumbnails': {'thumbnail': None}}, True)
         if hasattr(child, 'thumbnails'):
             thumbnails = [common.SamuraiThumbnail._parse(t) for t in child.thumbnails.thumbnail]
         else:
             thumbnails = []
         vals.title = SamuraiMovieLinkedTitle(
             ids.ContentID(child.get('id')),
             child.name.text,
             xmlutils.get_text(child, 'icon_url'),
             xmlutils.get_text(child, 'banner_url'),
             thumbnails
         )
     elif tag == 'rating_info':
         vals.rating_info = custom_types['rating_info']._parse(child)
     else:
         return False
     return True
示例#7
0
    def _read(self, reader, config):
        ec_info = xmlutils.load_root(reader, 'title_ec_info')
        xmlutils.validate_schema(
            ec_info, {
                'title_id': None,
                'content_size': None,
                'title_version': None,
                'disable_download': None,
                'content_lock': {
                    'seed_published': None,
                    'external_seed': None,
                    'playable_date': None
                }
            }, True)

        self.title_id = ids.TitleID(ec_info.title_id.text)
        self.content_size = int(ec_info.content_size.text)
        self.version = int(ec_info.title_version.text)
        self.download_disabled = utils.misc.get_bool(
            ec_info.disable_download.text)

        if hasattr(ec_info, 'content_lock'):
            self.seed_published = utils.misc.get_bool(
                ec_info.content_lock.seed_published.text)
            self.external_seed = xmlutils.get_text(ec_info.content_lock,
                                                   'external_seed')
            self.playable_date = xmlutils.get_text(ec_info.content_lock,
                                                   'playable_date')
示例#8
0
    def _read(self, reader, config):
        aocs = xmlutils.load_root(reader, 'aocs')
        xmlutils.validate_schema(aocs, {'aoc': {'data_size': None}}, False)

        self.sizes = {
            ids.ContentID(aoc.get('id')): int(aoc.data_size.text)
            for aoc in aocs.aoc
        }
示例#9
0
def test_xml__validate_schema__superset(xml_element):
    xml.validate_schema(xml_element,
                        {'node': {
                            'el1': None,
                            'el2': None,
                            'el3': None
                        }}, True)
    with pytest.raises(XmlSchemaError):
        xml.validate_schema(xml_element, {'node': {'el1': None}}, True)
示例#10
0
    def _read(self, reader, config):
        pairs = xmlutils.load_root(reader, 'title_id_pairs')
        if len(pairs.getchildren()) == 0:
            raise NoIDPairMatchError

        xmlutils.validate_schema(pairs, {
            'title_id_pair': {
                'ns_uid': None,
                'title_id': None,
                'type': None
            }
        }, False)
        assert len(pairs.getchildren()) == 1
        pair = pairs.title_id_pair

        assert pair.type.text in (
            'T', 'D'
        )  # 'Title'/'Demo'?  # not sure if there are any other types
        self.content_id = ids.ContentID(pair.ns_uid.text)
        self.title_id = ids.TitleID(pair.title_id.text)
示例#11
0
    def _read(self, reader, config):
        content = xmlutils.load_root(reader, 'content')
        assert len(content.getchildren()) == 1
        demo = content.demo

        xmlutils.validate_schema(
            demo, {
                'name': None,
                'icon_url': None,
                'rating_info': common.SamuraiRatingDetailed._get_schema()[0]
            }, True)
        for child, tag, text in xmlutils.iter_children(demo):
            if tag == 'name':
                self.name = text
            elif tag == 'icon_url':
                self.icon_url = text
            elif tag == 'rating_info':
                self.rating_info = common.SamuraiRatingDetailed._parse(child)
            else:
                raise ValueError(f'unknown tag: {tag}')
示例#12
0
    def _parse(cls, xml: lxml.objectify.ObjectifiedElement) -> 'SamuraiDlc3DS':
        vals = utils.misc.dotdict()

        for child, tag, text in xmlutils.iter_children(xml):
            if tag == 'name':
                vals.name = text
            elif tag == 'price':
                xmlutils.validate_schema(
                    child,
                    {'regular_price': {
                        'amount': None,
                        'currency': None
                    }}, False)
                vals.price = common.SamuraiPrice(
                    float(child.regular_price.amount.text),
                    child.regular_price.currency.text)
            else:
                raise ValueError(f'unknown tag: {tag}')

        return cls(**vals)
示例#13
0
    def _parse(cls,
               xml: lxml.objectify.ObjectifiedElement) -> 'SamuraiDlcWiiU':
        vals = utils.misc.dotdict()
        vals.is_new = utils.misc.get_bool(xml.get('new'))
        vals.content_id = ids.ContentID(xml.get('id'))

        for child, tag, text in xmlutils.iter_children(xml):
            if tag == 'name':
                vals.name = text
            elif tag == 'item_new_since':
                vals.release_date = text
            elif tag == 'icon_url':
                vals.icon_url = text
            elif tag == 'screenshots':
                vals.screenshots = [
                    common.SamuraiScreenshot._parse(screenshot)
                    for screenshot in child.screenshot
                ]
            elif tag == 'promotion_images':
                vals.promotion_image_urls = []
                for image in child.promotion_image:
                    assert set(image.attrib.keys()) == {'index', 'url'}
                    vals.promotion_image_urls.append(image.get('url'))
            elif tag == 'promotion_movie_url':
                vals.promotion_video_url = text
            elif tag == 'content_indexes':
                xmlutils.validate_schema(child, {'content_index': None}, False)
                vals.content_indexes = SamuraiDlcContentIndexes(
                    child.get('variation'),
                    [int(i.text) for i in child.content_index])
            elif tag == 'description':
                vals.description = text
            elif tag == 'disclaimer':
                vals.disclaimer = text
            elif tag == 'allow_overlap':
                vals.allow_overlap = utils.misc.get_bool(text)
            else:
                raise ValueError(f'unknown tag: {tag}')

        return cls(**vals)
示例#14
0
    def _try_parse_value(cls, vals: utils.misc.dotdict,
                         child: lxml.objectify.ObjectifiedElement, tag: str,
                         text: str, custom_types: CustomTypes) -> bool:
        # kind of hacky, but it works
        if 'is_new' not in vals:
            xml = child.getparent()
            vals.is_new = utils.misc.get_bool(xml.get('new'))
            vals.content_id = ids.ContentID(xml.get('id'))

        if tag == 'product_code':
            vals.product_code = text
        elif tag == 'name':
            vals.name = text
        elif tag == 'platform':
            vals.platform = common.SamuraiPlatform._parse(child)
        elif tag == 'publisher':
            xmlutils.validate_schema(child, {'name': None}, False)
            vals.publisher = common.IDName(int(child.get('id')),
                                           child.name.text)
        elif tag == 'display_genre':
            vals.genre = text
        elif tag == 'retail_sales':
            vals.sales_retail = utils.misc.get_bool(text)
        elif tag == 'eshop_sales':
            vals.sales_eshop = utils.misc.get_bool(text)
        elif tag == 'demo_available':
            vals.has_demo = utils.misc.get_bool(text)
        elif tag == 'aoc_available':
            vals.has_dlc__inaccurate = utils.misc.get_bool(text)
        elif tag == 'in_app_purchase':
            vals.has_iap__inaccurate = utils.misc.get_bool(text)
        elif tag == 'release_date_on_original':
            pass  # unused
        elif tag == 'price_on_retail':
            pass  # unused
        elif tag == 'tentative_price_on_eshop':
            pass  # unused
        else:
            return False
        return True
示例#15
0
    def _read(self, reader, config):
        versionlist = xmlutils.read_object(reader)
        assert versionlist.tag == 'version_list'
        xmlutils.validate_schema(versionlist, {
            'version': None,
            'titles': {
                'title': {
                    'id': None,
                    'version': None
                }
            }
        }, True)

        # sanity check
        if self.__version is not None:
            assert int(versionlist.version.text) == self.__version

        if hasattr(versionlist.titles, 'title'):
            self.updates = [(ids.TitleID(title.id.text),
                             int(title.version.text))
                            for title in versionlist.titles.title]
        else:
            self.updates = []
示例#16
0
 def _try_parse_value(cls, vals: utils.misc.dotdict, child: lxml.objectify.ObjectifiedElement, tag: str, text: str, custom_types: title_list.CustomTypes) -> bool:
     if tag == 'package_url':
         vals.package_url = text
     elif tag == 'thumbnails':
         vals.thumbnails = [common.SamuraiThumbnail._parse(t) for t in child.thumbnail]
     elif tag == 'hero_banner_url':
         vals.hero_banner_url = text
     elif tag == 'web_sales':
         vals.sales_web = utils.misc.get_bool(text)
     elif tag == 'top_image':
         xmlutils.validate_schema(child, {'type': None, 'url': None}, False)
         vals.top_image_type = child.type.text
         vals.top_image_url = child.url.text
     elif tag == 'description':
         vals.description = text
     elif tag == 'price_description':
         vals.price_description = text
     elif tag == 'features':
         vals.features = [SamuraiTitleFeature._parse(feature) for feature in child.feature]
     elif tag == 'play_styles':
         xmlutils.validate_schema(child, {'play_style': {
             'controllers': {'controller': {'id': None, 'name': None, 'icons': {'icon': None}}},
             'features': {'feature': SamuraiTitleFeature._get_schema()[0]}}
         }, True)
         vals.play_styles = []
         for play_style in child.play_style:
             if hasattr(play_style, 'controllers'):
                 controllers = [
                     SamuraiTitleController(
                         utils.misc.get_bool(controller.get('required')),
                         int(controller.get('type')),
                         int(controller.id.text),
                         controller.name.text,
                         [common.SamuraiIcon._parse(icon) for icon in controller.icons.icon] if hasattr(controller, 'icons') else None
                     )
                     for controller in play_style.controllers.controller
                 ]
             else:
                 controllers = []
             if hasattr(play_style, 'features'):
                 features = [SamuraiTitleFeature._parse(feature) for feature in play_style.features.feature]
             else:
                 features = []
             vals.play_styles.append(SamuraiTitlePlayStyle(play_style.get('type'), controllers, features))
     elif tag == 'languages':
         vals.languages = []
         for language in child.language:
             xmlutils.validate_schema(language, {'iso_code': None, 'name': None}, False)
             vals.languages.append(SamuraiTitleLanguage(language.iso_code.text, language.name.text))
     elif tag == 'number_of_players':
         # sometimes this field contains additional text in a second line, discard it for now and use the first non-empty line
         cleaned_text = next(line for line in text.replace('<br>', '\n').split('\n') if line)
         matches = re.search(r'(\d+)(?:\s*-\s*(\d+))?', cleaned_text)
         if matches:
             vals.num_players = (int(matches[1]), int(matches[2] or matches[1]))
         elif cleaned_text.startswith('*'):  # disclaimer instead of specific player numbers (example: 50010000037675)
             vals.num_players = None
         elif re.search(r'[\u3040-\u30ff\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff\uff66-\uff9f]', cleaned_text):  # ignore errors if text contains japanese/chinese/korean characters
             vals.num_players = None
         else:
             raise RuntimeError(f'Could not parse player details: {text}')
         vals.num_players_raw = text
     elif tag == 'disclaimer':
         vals.disclaimer = text
     elif tag == 'copyright':
         xmlutils.validate_schema(child, {'text': None, 'image_url': None}, True)
         vals.copyright = SamuraiTitleCopyright(child.find('text').text, xmlutils.get_text(child, 'image_url'))
     elif tag == 'screenshots':
         vals.screenshots = [SamuraiTitleScreenshot._parse(screenshot) for screenshot in child.screenshot]
     elif tag == 'main_images':
         vals.main_images = [SamuraiTitleScreenshot._parse(image) for image in child.image]
     elif tag == 'preference':
         target = child.find('target_player')
         style = child.find('play_style')
         vals.preferences = SamuraiTitlePreference(
             SamuraiTitlePreferenceTarget(int(target.everyone.text), int(target.gamers.text)),
             SamuraiTitlePreferenceStyle(int(style.casual.text), int(style.intense.text))
         )
     elif tag == 'web_sites':
         vals.websites = []
         for website in child.web_site:
             xmlutils.validate_schema(website, {'name': None, 'url': None, 'official': None}, False)
             vals.websites.append(SamuraiTitleWebsite(
                 website.name.text,
                 website.url.text,
                 utils.misc.get_bool(website.official.text)
             ))
     elif tag == 'movies':
         vals.movies = [movie_list.SamuraiListMovie._parse(m) for m in child.movie]
     elif tag == 'demo_titles':
         vals.demos = [
             SamuraiTitleLinkedDemo(
                 ids.ContentID(demo.get('id')),
                 demo.name.text,
                 xmlutils.get_text(demo, 'icon_url')
             )
             for demo in child.demo_title
         ]
     elif tag == 'peripheral_description':
         vals.peripheral_description = text
     elif tag == 'network_feature_description':
         vals.network_feature_description = text
     elif tag == 'spec_description':
         vals.spec_description = text
     elif tag == 'data_size':
         vals.size = int(text)
     elif tag == 'alternate_rating_image_url':
         vals.rating_info_alternate_image_url = text
     elif tag == 'save_data_count':
         vals.save_data_count = text
     elif tag == 'save_data_volume':
         vals.save_data_volume = text
     elif tag == 'catch_copy':
         vals.catch_copy = text
     elif tag == 'shared_movies':
         vals.shared_movies = [SamuraiSharedMovie._parse(movie) for movie in child.shared_movie]
     elif tag == 'title_notices':
         xmlutils.validate_schema(child, {'title_notice': {'url': None, 'display_name': None, 'description': None}}, False)
         vals.title_notices = [
             SamuraiTitleNotice(
                 notice.get('type'),
                 notice.url.text,
                 notice.display_name.text,
                 notice.description.text
             )
             for notice in child.title_notice
         ]
     elif tag == 'title_metas':
         xmlutils.validate_schema(child, {'title_meta': {'value': None}}, False)
         vals.title_metas = [(m.get('type'), m.value.text) for m in child.title_meta]
     elif tag == 'digital_manuals':
         xmlutils.validate_schema(child, {'digital_manual': {'name': None, 'url': None}}, False)
         vals.digital_manuals = [SamuraiDigitalManual(manual.name.text, manual.url.text) for manual in child.digital_manual]
     elif tag == 'aoc_infos':
         vals.aoc_infos = text
     else:
         return super()._try_parse_value(vals, child, tag, text, custom_types)
     return True
示例#17
0
 def _read(self, reader, config):
     telops_xml = xmlutils.load_root(reader, 'telops')
     xmlutils.validate_schema(telops_xml, {'telop': None}, True)
     self.entries = [el.text for el in getattr(telops_xml, 'telop', [])]