Пример #1
0
def test_skip_cache_read(skip, requests_mock):
    path = 'test_skip_cache_read'
    url = MOCK_BASE + path
    requests_mock.get(url, [{'text': 'first'}, {'text': 'second'}])

    source = _get_source(None)
    session = cast(CacheMixin, source._session)
    reqdata = ReqData(path=path)

    res = source.get(reqdata, skip_cache_read=skip)
    # response should have been stored in cache either way
    assert url in session.cache.urls
    # first response is never from cache
    assert res.from_cache is False  # type: ignore
    assert res.text == 'first'

    res = source.get(reqdata, skip_cache_read=skip)
    # second response should only be from cache if skip_cache_read=False
    assert res.from_cache is (not skip)  # type: ignore
    # if skip_cache_read=True, new request should have been sent (and stored)
    expected_text = 'second' if skip else 'first'
    assert res.text == expected_text

    # new request with skip_cache_read=False should return same data as previous one
    res = source.get(reqdata, skip_cache_read=False)
    assert res.from_cache is True  # type: ignore
    assert res.text == expected_text
Пример #2
0
def test_skip_cache_write(skip, requests_mock):
    path = 'test_skip_cache_write'
    url = MOCK_BASE + path
    requests_mock.get(url, [{
        'text': 'first'
    }, {
        'text': 'second'
    }, {
        'text': 'third'
    }])

    source = _get_source(None)
    session = cast(CacheMixin, source._session)
    reqdata = ReqData(path=path)

    res = source.get(reqdata, skip_cache_write=True)
    # response should not be in cache
    assert url not in session.cache.urls
    assert res.text == 'first'

    res = source.get(reqdata, skip_cache_write=skip)
    # second response should be in cache only if skip_cache_write=False
    assert (url in session.cache.urls) is not skip
    assert res.from_cache is False  # type: ignore
    assert res.text == 'second'

    res = source.get(reqdata, skip_cache_write=False)
    # response should be in cache
    assert url in session.cache.urls
    assert res.from_cache is not skip  # type: ignore
    # if second response was not written to cache, we should've gotten the third one now
    expected_text = 'third' if skip else 'second'
    assert res.text == expected_text
Пример #3
0
def test_config__timeout():
    source = _get_source(
        SourceConfig(timeout=42,
                     response_status_checking=StatusCheckMode.NONE))
    with patch.object(source._session, 'get') as mock_get:
        source.get(ReqData(path=MOCK_PATH))
        assert mock_get.call_args[1]['timeout'] == 42
Пример #4
0
    def get_dlcs_for_title(
            self, title: Union[ids.TContentIDInput, SamuraiListTitle,
                               SamuraiTitleElement],
            **kwargs: Any) -> Union[SamuraiTitleDlcsWiiU, SamuraiTitleDlcs3DS]:
        # note: this endpoint doesn't seem to be reliable for all titles,
        #        some titles have aoc/iap but this response is empty
        if isinstance(title, (SamuraiListTitle, SamuraiTitleElement)):
            content_id = title.content_id
        else:
            content_id = ids.ContentID.get_inst(title)

        dlcs_type: Union[SamuraiTitleDlcs3DS, SamuraiTitleDlcsWiiU]
        if content_id.type.platform == ids.ContentPlatform._3DS:
            dlcs_type = SamuraiTitleDlcs3DS()
            params = {}  # 3DS DLC results aren't paginated
        elif content_id.type.platform == ids.ContentPlatform.WIIU:
            dlcs_type = SamuraiTitleDlcsWiiU()
            params = {
                'limit': 200
            }  # assuming a maximum of 200 DLCs per title, seems reasonable
        else:
            assert False  # unhandled, should never happen

        return self._create_type(
            ReqData(path=f'title/{ids.ContentID.get_str(content_id)}/aocs',
                    params=params), dlcs_type, **kwargs)
Пример #5
0
    def __init__(self,
                 region: Union[str, Region],
                 shop_id: int,
                 *,
                 lang: Optional[str] = None,
                 cdn: Optional[bool] = False,
                 config: Optional[SourceConfig] = None):
        params: RequestDict = {'shop_id': shop_id}
        if lang:
            params['lang'] = lang

        region = region.country_code if isinstance(region, Region) else region

        if cdn:
            host = 'samurai-wup.cdn.nintendo.net'
            fingerprint = '43:8D:A9:4A:60:CB:00:DF:F2:B3:EB:17:A7:A2:1C:98:BD:11:FC:4A:A6:49:62:C1:2C:EF:41:BB:1F:28:88:95'
        else:
            host = 'samurai.wup.shop.nintendo.net'
            fingerprint = 'C6:6E:7D:66:D0:73:62:2F:A3:28:7F:A6:2F:F5:73:5C:71:EE:EB:3D:93:AC:B3:14:7A:8F:85:B4:07:D4:CE:ED'
        super().__init__(ReqData(path=f'https://{host}/samurai/ws/{region}/',
                                 params=params),
                         config,
                         verify_tls=False,
                         require_fingerprint=fingerprint)

        self.region = region
        self.shop_id = shop_id
        self.lang = lang
Пример #6
0
 def get_ec_info(self, content_id: ids.TContentIDInput,
                 **kwargs: Any) -> NinjaEcInfo:
     return self._create_type(
         ReqData(
             path=
             f'{self.region}/title/{ids.ContentID.get_str(content_id)}/ec_info'
         ), NinjaEcInfo(), **kwargs)
Пример #7
0
 def get_tmd(self,
             title_id: ids.TTitleIDInput,
             version: Optional[int] = None,
             **kwargs: Any) -> TMD:
     return self._create_type(
         ReqData(path=f'{ids.TitleID.get_str(title_id)}/tmd' +
                 (f'.{version}' if version is not None else '')),
         TMD(title_id), **kwargs)
Пример #8
0
 def get_latest_updatelist_version(self,
                                   *,
                                   skip_cache_read: bool = True,
                                   **kwargs: Any) -> UpdateListVersion:
     return self._create_type(ReqData(path='latest_version'),
                              UpdateListVersion(),
                              skip_cache_read=skip_cache_read,
                              **kwargs)
Пример #9
0
 def __init__(self, cert: CertType, config: Optional[SourceConfig] = None):
     super().__init__(
         ReqData(path='https://ccs.c.shop.nintendowifi.net/ccs/download/',
                 cert=cert),
         config,
         verify_tls=False,
         require_fingerprint=
         'E9:74:4D:71:E3:06:6A:84:80:1D:0B:52:5E:26:8E:80:70:41:F4:20')
Пример #10
0
def test_cached_nolimit(mock_sleep):
    source = new_source(cache=True)
    reqdata = ReqData(path=MOCK_URL)

    assert not source.get(reqdata).from_cache
    assert mock_sleep.call_count == 0

    assert source.get(reqdata).from_cache
    assert mock_sleep.call_count == 0
Пример #11
0
 def _get_list(self, list_type: Type[_TList], path: str, offset: int,
               limit: int, other_params: RequestDict,
               **kwargs: Any) -> _TList:
     return self._create_type(
         ReqData(path=path,
                 params={
                     'offset': offset,
                     'limit': limit,
                     **other_params
                 }), list_type(), **kwargs)
Пример #12
0
 def get_dlc_prices(self, *dlcs: Union[ids.TContentIDInput, SamuraiDlcWiiU],
                    **kwargs: Any) -> SamuraiDlcPrices:
     return self._create_type(
         ReqData(path='aocs/prices',
                 params={
                     'aoc[]':
                     ','.join(
                         ids.ContentID.get_str(i)
                         for i in self.__get_dlc_ids(dlcs))
                 }), SamuraiDlcPrices(), **kwargs)
Пример #13
0
 def get_app(self,
             title_id: ids.TTitleIDInput,
             content_id: int,
             *,
             skip_cache: bool = True,
             **kwargs: Any) -> UnloadableType:
     return self._create_type(
         ReqData(path=f'{ids.TitleID.get_str(title_id)}/{content_id:08X}'),
         skip_cache=skip_cache,
         **kwargs)
Пример #14
0
def test_unloadable(skip_cache):
    source = _get_source(None)
    reqdata = ReqData(path=MOCK_PATH)

    inst = source._create_type(reqdata, skip_cache=skip_cache)

    assert isinstance(inst, UnloadableType)
    assert inst.reqdata is reqdata
    assert inst.kwargs['skip_cache'] is skip_cache
    with inst.get_reader() as reader:
        assert reader.read() == b'response'
Пример #15
0
 def __init__(self, config: Optional[SourceConfig] = None):
     super().__init__(
         ReqData(
             path=
             'https://tagaya-wup.cdn.nintendo.net/tagaya/versionlist/EUR/GB/'
         ),
         config,
         verify_tls=False,
         require_fingerprint=
         '43:8D:A9:4A:60:CB:00:DF:F2:B3:EB:17:A7:A2:1C:98:BD:11:FC:4A:A6:49:62:C1:2C:EF:41:BB:1F:28:88:95'
     )
Пример #16
0
 def __init__(self, config: Optional[SourceConfig] = None):
     super().__init__(
         ReqData(
             path=
             'https://tagaya.wup.shop.nintendo.net/tagaya/versionlist/EUR/GB/'
         ),
         config,
         verify_tls=False,
         require_fingerprint=
         'C6:6E:7D:66:D0:73:62:2F:A3:28:7F:A6:2F:F5:73:5C:71:EE:EB:3D:93:AC:B3:14:7A:8F:85:B4:07:D4:CE:ED'
     )
Пример #17
0
 def get_idbe(self,
              title_id: ids.TTitleIDInput,
              version: Optional[int] = None,
              **kwargs: Any) -> IDBE:
     tid_str = ids.TitleID.get_str(title_id)
     return self._create_type(
         # server seems to ignore first value, it probably doesn't matter what is supplied here
         # based on nn_idbe.rpl .text+0x1d0
         ReqData(path=f'{tid_str[12:14]}/{tid_str}' +
                 (f'-{version}' if version is not None else '') + '.idbe'),
         IDBE(title_id),
         **kwargs)
Пример #18
0
    def get_dlcs_wiiu(self, *dlc_ids: ids.TContentIDInput,
                      **kwargs: Any) -> SamuraiDlcsWiiU:
        for dlc_id in dlc_ids:
            dlc_id = ids.ContentID.get_inst(dlc_id)
            if dlc_id.type.platform != ids.ContentPlatform.WIIU:
                raise ValueError(f'content ID {dlc_id} is not a WiiU title')

        return self._create_type(
            ReqData(path='aocs',
                    params={
                        'aoc[]':
                        ','.join(ids.ContentID.get_str(i) for i in dlc_ids)
                    }), SamuraiDlcsWiiU(), **kwargs)
Пример #19
0
 def __init__(self, platform: str, config: Optional[SourceConfig] = None):
     # platform does not matter, both servers seem to contain the same data
     if platform not in ('wup', 'ctr'):
         raise ValueError('`platform` must be either \'wup\' or \'ctr\'')
     super().__init__(
         ReqData(
             path=f'https://idbe-{platform}.cdn.nintendo.net/icondata/'),
         config,
         verify_tls=False,
         # fingerprints for ctr/wup certs are the same
         require_fingerprint=
         '43:8D:A9:4A:60:CB:00:DF:F2:B3:EB:17:A7:A2:1C:98:BD:11:FC:4A:A6:49:62:C1:2C:EF:41:BB:1F:28:88:95'
     )
     self.platform = platform
Пример #20
0
def test_skip_cache(skip, expected_cache_status, callable):
    source = _get_source(None)
    reqdata = ReqData(path=MOCK_PATH)

    if callable:
        skip_val = skip

        def skip(r):  # noqa
            assert isinstance(r, requests.PreparedRequest)
            return skip_val

    for expected in expected_cache_status:
        result = source.get(reqdata, skip_cache=skip)
        assert result.from_cache is expected  # type: ignore
        assert result.content == b'response'
Пример #21
0
    def __init__(self,
                 region: Union[str, Region],
                 cert: CertType,
                 config: Optional[SourceConfig] = None):
        super().__init__(
            ReqData(path='https://ninja.wup.shop.nintendo.net/ninja/ws/',
                    cert=cert),
            config,
            verify_tls=False,
            require_fingerprint=
            'C6:6E:7D:66:D0:73:62:2F:A3:28:7F:A6:2F:F5:73:5C:71:EE:EB:3D:93:AC:B3:14:7A:8F:85:B4:07:D4:CE:ED'
        )

        self.region = region.country_code if isinstance(region,
                                                        Region) else region
Пример #22
0
    def get_id_pair(self,
                    *,
                    content_id: Optional[ids.TContentIDInput] = None,
                    title_id: Optional[ids.TTitleIDInput] = None,
                    **kwargs: Any) -> NinjaIDPair:
        if (content_id is None) == (title_id is None):
            raise ValueError(
                'Exactly one of `content_id`/`title_id` must be set')

        return self._create_type(
            ReqData(path='titles/id_pair',
                    params={'title_id[]': ids.TitleID.get_str(title_id)}
                    if title_id else {
                        'ns_uid[]':
                        ids.ContentID.get_str(
                            cast(ids.TContentIDInput, content_id))
                    }), NinjaIDPair(), **kwargs)
Пример #23
0
 def __init__(self, config: Optional[SourceConfig] = None):
     super().__init__(
         ReqData(
             path='http://ccs.cdn.c.shop.nintendowifi.net/ccs/download/'),
         config)
Пример #24
0
 def check(code):
     result = func(ReqData(path=f'code/{code}'))
     if hasattr(result, '__enter__'):
         with result:
             pass
Пример #25
0
 def get_title(self, content_id: ids.TContentIDInput,
               **kwargs: Any) -> SamuraiTitle:
     return self._create_type(
         ReqData(path=f'title/{ids.ContentID.get_str(content_id)}'),
         SamuraiTitle(), **kwargs)
Пример #26
0
 def get_telops(self, **kwargs: Any) -> SamuraiTelops:
     return self._create_type(ReqData(path='telops'), SamuraiTelops(),
                              **kwargs)
Пример #27
0
 def get_news(self, **kwargs: Any) -> SamuraiNews:
     return self._create_type(ReqData(path='news'), SamuraiNews(), **kwargs)
Пример #28
0
 def get_demo(self, content_id: ids.TContentIDInput,
              **kwargs: Any) -> SamuraiDemo:
     return self._create_type(
         ReqData(path=f'demo/{ids.ContentID.get_str(content_id)}'),
         SamuraiDemo(), **kwargs)
Пример #29
0
 def get_h3(self, title_id: ids.TTitleIDInput, content_id: int,
            **kwargs: Any) -> UnloadableType:
     return self._create_type(
         ReqData(
             path=f'{ids.TitleID.get_str(title_id)}/{content_id:08X}.h3'),
         **kwargs)
Пример #30
0
 def get_cetk(self, title_id: ids.TTitleIDInput, **kwargs: Any) -> Ticket:
     return self._create_type(
         ReqData(path=f'{ids.TitleID.get_str(title_id)}/cetk'),
         Ticket(title_id), **kwargs)