GithubHelp home page GithubHelp logo

meraki-analytics / cassiopeia Goto Github PK

View Code? Open in Web Editor NEW
544.0 22.0 132.0 2.39 MB

An all-inclusive Python framework for the Riot Games League of Legends API. Cass focuses on making the data easy and fun to work with, while providing all the tools necessary to create a website or do data analysis.

License: MIT License

Python 100.00%
league-of-legends riot-games-api champion-gg-api python api

cassiopeia's People

Contributors

10se1ucgo avatar alexf-git avatar areesedt avatar artemigkh avatar balmeet-singh avatar bangingheads avatar ckcollab avatar fculpo avatar hawk93 avatar iann838 avatar jchristgit avatar jjmaldonis avatar jputlock avatar k-orne avatar lukepeltier avatar m1so avatar m3adow avatar makersf avatar mathougui avatar mertkutay avatar nhurman avatar octobomb avatar raven-seldon avatar rdk31 avatar robrua avatar samgho avatar satrium avatar stephen19k avatar xecez avatar zlehmann avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cassiopeia's Issues

Error with python 2.7.10

Hello, I downloaded your library but when I imported it, it says:

Traceback (most recent call last):
File "<pyshell#0>", line 1, in
from cassiopeia import riotapi
File "C:\Python27\lib\site-packages\cassiopeia\riotapi.py", line 5, in
import cassiopeia.dto.requests
File "C:\Python27\lib\site-packages\cassiopeia\dto\requests.py", line 5, in
import urllib.parse
ImportError: No module named parse

You should use the Request library for that reason. I'm using python 2.7.10.

In-Memory cache fills up indefinitely by default

Right now, the in-memory cache only ever gets fuller. When pulling a lot of data from the API, this can start to be a problem. I'd propose either explicitly mentioning this and how to reset the cache in documentation, or (ideally) having a maximum size for the cache / maximum number of stored objects, with some expulsion policy (LRU?), and a sane default value to start off with (but this might be hard to do properly).

parse_match_information.py meets ValueError: 'TEAM_BUILDER_DRAFT_RANKED_5x5' is not a valid Queue

Hello!

First, I'd like to apologize in advance for my scrubliness. I'm very new to Python and this whole API thing in general. I literally just updated Python to 3.X, pip installed cassiopeia, copied some test code, and ran it. The first test code (with the "{name} is a level {level} summoner on the NA server" stuff) worked just fine. But then I tried the one for Dyrus' information and I get the following output:

Basic match information:
Match ID: 2100218822
Version/Patch: 6.3.0.240
Creation date: 2016-02-17 19:07:55.464000 (which was -1 day, 19:29:12.675141 ago)
Duration: 0:32:24
Map: Map.summoners_rift
Mode: GameMode.classic
Type: GameType.matched
Platform: Platform.north_america
Traceback (most recent call last):
File "parse_match_information.py", line 88, in
main()
File "parse_match_information.py", line 32, in main
print(" Queue: {0}".format(match.queue))
File "//anaconda/lib/python3.5/site-packages/cassiopeia/type/core/match.py", line 91, in queue
return cassiopeia.type.core.common.Queue(self.data.queueType) if self.data.queueType else None
File "//anaconda/lib/python3.5/enum.py", line 235, in call
return cls.new(cls, value)
File "//anaconda/lib/python3.5/enum.py", line 470, in new
raise ValueError("%r is not a valid %s" % (value, cls.name))
ValueError: 'TEAM_BUILDER_DRAFT_RANKED_5x5' is not a valid Queue

Is this an error associated with how Riot has been updating the queue interfaces, or did I do something wrong?

Sorry I'm such a scrub! D:
And thank you in advance for your help!

Use the Api as a class instead of as bunch of functions

Made some changes to the structure of the code.
Now you have a class which exposes all the api functions as members.
Moreover you can have multiple of this class, which can share any of the key, region, rate limiter and so on.

You can find the changes here. Let me know if you are interested into them (at the moment core doesn't work, as it hasn't been translated to the new pattern)

from cassiopeia.dto.requests import RequestGateway
from cassiopeia.baseriotapi import BaseAPI

rg = RequestGateway('your-api-key', 'NA', print_calls=True)
NA = BaseAPI(rg1)
nb3=NA.get_summoners_by_name(['Nightblue3'])
print(nb3)

rg2 = RequestGateway(rg1.api_key, 'KR', rate_limiter=rg1.rate_limiter)
KR = BaseAPI(rg2)
print(KR.get_summoners_by_name(['cowsep']))

rg2._region = 'NA'
rg2._print_calls = True
print(KR.get_summoners_by_id([nb3['nightblue3'].id]))

Prints

https://na.api.pvp.net/api/lol/na/v1.4/summoner/by-name/Nightblue3?api_key=
{'nightblue3': Summoner({'summonerLevel': 30, 'revisionDate': 1441986280000, 'name': 'Nightblue3', 'profileIconId': 909, 'id': 25850956})}
{'cowsep': Summoner({'summonerLevel': 30, 'revisionDate': 1441972531000, 'name': 'Cowsep', 'profileIconId': 787, 'id': 28730386})}
https://NA.api.pvp.net/api/lol/NA/v1.4/summoner/25850956?api_key=
{'25850956': Summoner({'summonerLevel': 30, 'revisionDate': 1441986280000, 'name': 'Nightblue3', 'profileIconId': 909, 'id': 25850956})}

Examples with summoners, but you can use it for any function in the api

Matchlist and season

I want a list of games that I've played in season 2015.

from cassiopeia import riotapi
riotapi.set_region("NA")
riotapi.set_api_key("xxx")

summoner = riotapi.get_summoner_by_name("dyrus")
mylist = riotapi.get_match_list(summoner, seasons="SEASON2015")

Unfortunately, I am getting "AttributeError: 'str' object has no attribute 'value'"

Have I not imported something properly?

New Release before new LoL patch

Would it be possible to have a new release before the new patch hits the servers?

The addition of Rift Herald is quite noteworthy, and that means we can start collecting its data since the start of the patch.

AttributeError: 'datetime.timedelta' object has no attribute 'time

calling time on frame.timestamp throw an AttributeError:

for frame in match.timeline.frames:
    print("The following skill level up events occured between minute {} and {}".format(frame.timestamp.time.minute, 
                                frame.timestamp.time.minute + match.timeline.frame_interval))


---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-95-6aa68e02efc5> in <module>()
      1 from cassiopeia.type.core.common import EventType
      2 for frame in match.timeline.frames:
----> 3     print("The following skill level up events occured between minute {} and {}".format(frame.timestamp.time.minute, 
      4                                 frame.timestamp.time.minute + match.timeline.frame_interval))
      5     for event in frame:

AttributeError: 'datetime.timedelta' object has no attribute 'time'

On a sidenote, your links for the examples in the documentation are broken, I think there is an s missing after example:

https://github.com/meraki-analytics/cassiopeia/blob/master/example/is_dyrus_in_game.py

Cache problems with requests on different regions

I found a problem calling get_summoner_by_name methods on riotapi.
If I search for a summoner with the same name in 2 different regions I get 2 times the same summoner cause of caching that doesn't check for region match
simple test:
riotapi.set_region('EUW')
summ1=riotapi.get_summoner_by_name('INC Hawkido')
riotapi.set_region('EUNE')
summ2=riotapi.get_summoner_by_name('INC Hawkido')
print(summ1.to_json())
print(summ2.to_json())
Both summoners are equal but "INC Hawkido" doesn't exist in EUNE

How to secure the API key?

Hi all,

Sorry if this is the wrong place to post this. I was looking at the documentation and it says to do riotapi.set_api_key("YOUR-API-KEY-HERE") to set the API key. However, the Riot documentation says for a production key, you need to "have the client application access your own server, which then makes the appropriate request to the API using HTTPS.". How would this be done with cassiopeia? I'm new to servers in general - would I need to use a server from say, AWS and have that call the set_api_key method? Thanks in advance for your help!

Best,
Jason

Documentation issue

Not really sure if it should go here, but the documentation for cassiopeia.riotapi, cassiopeia.baseriotapi, and cassiopeia.type.core at the documentation site are currently blank.
Yesterday they were not.

edit: something else odd is that if I search for something the search succeeds, but still leads to a blank doc page.

Rate limiters "leaks" calls

Testing a (single-threaded) script of mine I got blacklisted( 2 times!!)
overflow of limit

Did not make any call from the web interface. Just run the program and went to sleep. (No API calls in the previous hours either).
All the requests went through the baseriotapi.

I don't think the problem is related to #14 , as my program is not multi thread and thus there can not happen the race condition.

At a first glance I can not spot the problem, but I'm not really an export in python threading.

Problem with match_list

I have a issue with the summoner.match_list(), when i try to do:
summoner = riotapi.get_summoner_by_name("bynikiyo")
match_list = summoner.match_list()
for participant in match_list[0].match():
print(participant.champion.name)

When I obtain this match is not the last match I played, i don't know the problem.
How can I get the last match?

Allow to use the DTOs without SQLAlchemy

How do you feel about splitting the DTOs from the SQLAlchemy?
I mean, having the DTOs without importing SQLALchemy and have the SQLAlchemy bindings in separate files.

I'm starting a project now, and would like to use your DTOs in order not to redo all the work you already done to extract the informations in a simple way.
I only need the parsing though, as I'll gather the data in a different way and I'm not interested in the additional features of your library.

Taking for example match.py, we could have

dto/match.py
dto/alchemy/match_alchemy.py

match.py would contain line 5-594
match_alchemy.py would contain
line 1-5
from cassiopeia.type.dto.match import *
line 594-926

This way whoever needs to have the data parsing can use your library without pulling external dependencies and using pure python.

If you believe this can be useful I might make a pull request for the changes I'll do for my project

'Siege' is not a valid StatSummaryType

Hi,

It seems that riotapi.get_stats throws an exception because of an update on the playerStatSummaryType (https://developer.riotgames.com/docs/game-constants) that now includes the new type 'Siege' for Nexus Siege games.

See below error:

C:\Django\cgames\common\util\lol_utils.py in get_lol_stats(summoner, c_user)
     45 
     46         try:
---> 47                 stats = riotapi.get_stats(summoner)
     48         except APIError as error:
     49                 return -1

C:\Envs\cgames\lib\site-packages\cassiopeia\core\statsapi.py in get_stats(summoner, season)
     36 
     37     stats = cassiopeia.dto.statsapi.get_stats(summoner.id, season.value if season else None)
---> 38     return {cassiopeia.type.core.common.StatSummaryType(summary.playerStatSummaryType): cassiopeia.type.core.stats.StatsSummary(summary) for summary in stats.playerStatSummaries}

C:\Envs\cgames\lib\site-packages\cassiopeia\core\statsapi.py in <dictcomp>(.0)
     36 
     37     stats = cassiopeia.dto.statsapi.get_stats(summoner.id, season.value if season else None)
---> 38     return {cassiopeia.type.core.common.StatSummaryType(summary.playerStatSummaryType): cassiopeia.type.core.stats.StatsSummary(summary) for summary in stats.playerStatSummaries}

c:\anaconda3\Lib\enum.py in __call__(cls, value, names, module, qualname, type, start)
    239         """
    240         if names is None:  # simple value lookup
--> 241             return cls.__new__(cls, value)
    242         # otherwise, functional API: we're creating a new Enum type
    243         return cls._create_(value, names, module=module, qualname=qualname, type=type, start=start)

c:\anaconda3\Lib\enum.py in __new__(cls, value)
    474                 if member._value_ == value:
    475                     return member
--> 476         raise ValueError("%r is not a valid %s" % (value, cls.__name__))
    477 
    478     def __repr__(self):

ValueError: 'Siege' is not a valid StatSummaryType

Need Help - Databasing issue..? "500 error"

I guess this is more like a stupid question then a issue ticket...
I'm just really new to this whole api and db thing. I just know that there is a call limit in riot api and that using db can resolve the issue. That is why I really appreciate your library.

But then... I do not really know how to take advantage of the db...

What I am trying to do is extracting all my ranked match list of season5.
And for all ten participants of each match, I want to know the champ statistics of the champ selected by each participant. I'm making it into a data frame. So the table would look sth like below
[match#1, participant#1, dyrus, mundo, kda, gold]
...
[match#1, participant#10, doublelift, vayne, kda, gold]

Now.. apparently it's a quite heavy work (at least in the way I coded it). If I run my code for 1020 matches it takes some time but still works the exact way I wanted. But if I run the code for more than about 3050games it crashes and gives me 500 error.And when I went to developer.riotgames.com, I see messages like "Rate limit exceeded 83 times in the last 6 hours." I thought I shouldn't be seeing this message when I'm using db.
Though I read that cass offers "automatic databasing", I was getting a feeling that I'm still missing sth silly to take advantage of this "databasing" concept.
I don't want to waste your time by asking to teach me technical things, but I was hoping if I could get some sort of guidance to fully utilize your library. Below is the code I used

from cassiopeia import riotapi
from cassiopeia.core import *
from cassiopeia.dto import *
from cassiopeia.type import *
from cassiopeia.type.core.common import *
from cassiopeia.type.core.common import LoadPolicy
import random
import cassiopeia.riotapi
import cassiopeia.dto.statsapi
import cassiopeia.core.requests
import cassiopeia.type.core.common
import cassiopeia.type.core.stats
import time

import numpy as np
import pandas as pd
riotapi.set_rate_limit(3000, 10)
riotapi.set_load_policy(LoadPolicy.eager)
riotapi.set_load_policy(LoadPolicy.lazy)
key="abcd"
riotapi.set_region("NA")
riotapi.set_api_key(key)

def extract_participant(sum_name): 
    quetype=Queue.ranked_solo    
    myseason=Season.season_5 
    summoner = riotapi.get_summoner_by_name(sum_name)
    mygamelist=riotapi.get_match_list(summoner, num_matches=50, ranked_queues=quetype, seasons=myseason) #matchlist objects
    mydict= dict()

    for game in mygamelist:
        mydict[game.id]=[]
        for i in range(0,10):
            participant=game.match().participants[i] 
            champstat=participant.summoner.ranked_stats(season=myseason)[participant.champion]
            participant_list=[]
            participant_list.append(participant.summoner_name)
            participant_list.append(participant.side)
    return mydict

d = pd.Series(extract_participant('dyrus'))

Match list error

Hi! First of all many thanks for creating this awesome wrapper for the Riot Lol API! I followed your documentation and cassiopeia is really easy and "pythonic" to use :)

Unfortunately I have a problem when trying to call matchlist() for my own EUW account:

match_list = summoner.match_list()

---------------------------------------------------------------------------
HTTPError                                 Traceback (most recent call last)
/home/cs/anaconda3/lib/python3.5/site-packages/cassiopeia/dto/requests.py in make_request(request, method, params, payload, static, include_base, tournament)
     87     try:
---> 88         content = limiter.call(execute_request, url, method, payload) if limiter else execute_request(url, method, payload)
     89         return json.loads(content) if content else {}

/home/cs/anaconda3/lib/python3.5/site-packages/cassiopeia/type/api/rates.py in call(self, method, *args)
    128         try:
--> 129             return method(*args) if method else None
    130         except:

/home/cs/anaconda3/lib/python3.5/site-packages/cassiopeia/dto/requests.py in execute_request(url, method, payload)
    123         request.add_header("Accept-Encoding", "gzip")
--> 124         response = urllib.request.urlopen(request)
    125         content = response.read()

/home/cs/anaconda3/lib/python3.5/urllib/request.py in urlopen(url, data, timeout, cafile, capath, cadefault, context)
    161         opener = _opener
--> 162     return opener.open(url, data, timeout)
    163 

/home/cs/anaconda3/lib/python3.5/urllib/request.py in open(self, fullurl, data, timeout)
    470             meth = getattr(processor, meth_name)
--> 471             response = meth(req, response)
    472 

/home/cs/anaconda3/lib/python3.5/urllib/request.py in http_response(self, request, response)
    580             response = self.parent.error(
--> 581                 'http', request, response, code, msg, hdrs)
    582 

/home/cs/anaconda3/lib/python3.5/urllib/request.py in error(self, proto, *args)
    508             args = (dict, 'default', 'http_error_default') + orig_args
--> 509             return self._call_chain(*args)
    510 

/home/cs/anaconda3/lib/python3.5/urllib/request.py in _call_chain(self, chain, kind, meth_name, *args)
    442             func = getattr(handler, meth_name)
--> 443             result = func(*args)
    444             if result is not None:

/home/cs/anaconda3/lib/python3.5/urllib/request.py in http_error_default(self, req, fp, code, msg, hdrs)
    588     def http_error_default(self, req, fp, code, msg, hdrs):
--> 589         raise HTTPError(req.full_url, code, msg, hdrs, fp)
    590 

HTTPError: HTTP Error 503: Service Unavailable

During handling of the above exception, another exception occurred:

APIError                                  Traceback (most recent call last)
<ipython-input-14-c9202207845b> in <module>()
----> 1 match_list = summoner.match_list()

/home/cs/anaconda3/lib/python3.5/site-packages/cassiopeia/type/core/common.py in curried(*args, **kwargs)
     95         @functools.wraps(self.method)
     96         def curried(*args, **kwargs):
---> 97             return self.method(obj, *args, **kwargs)
     98         return curried
     99 

/home/cs/anaconda3/lib/python3.5/site-packages/cassiopeia/type/core/summoner.py in match_list(self, num_matches, begin_index, begin_time, end_time, champions, ranked_queues, seasons)
    222         return          list<MatchReference>         the summoner's match history
    223         """
--> 224         return cassiopeia.riotapi.get_match_list(self, num_matches, begin_index, begin_time, end_time, champions, ranked_queues, seasons)
    225 
    226     @cassiopeia.type.core.common.immutablemethod

/home/cs/anaconda3/lib/python3.5/site-packages/cassiopeia/core/matchlistapi.py in get_match_list(summoner, num_matches, begin_index, begin_time, end_time, champions, ranked_queues, seasons)
     47     seasons = [season.value for season in seasons] if isinstance(seasons, list) else seasons.value if seasons else None
     48 
---> 49     history = cassiopeia.dto.matchlistapi.get_match_list(summoner.id, num_matches, begin_index, begin_time, end_time, champion_ids, ranked_queues, seasons)
     50 
     51     # Load required data if loading policy is eager

/home/cs/anaconda3/lib/python3.5/site-packages/cassiopeia/dto/matchlistapi.py in get_match_list(summoner_id, num_matches, begin_index, begin_time, end_time, champion_ids, ranked_queues, seasons)
     35         params["seasons"] = ",".join(seasons) if isinstance(seasons, list) else str(seasons)
     36 
---> 37     return cassiopeia.type.dto.matchlist.MatchList(cassiopeia.dto.requests.get(request, params))

/home/cs/anaconda3/lib/python3.5/site-packages/cassiopeia/dto/requests.py in get(request, params, static, include_base, tournament)
     39 
     40 def get(request, params={}, static=False, include_base=True, tournament=False):
---> 41     return make_request(request=request, method="GET", params=params, static=static, include_base=include_base, tournament=tournament)
     42 
     43 

/home/cs/anaconda3/lib/python3.5/site-packages/cassiopeia/dto/requests.py in make_request(request, method, params, payload, static, include_base, tournament)
     98             return make_request(request, method, params, payload, static, include_base, tournament)
     99         else:
--> 100             raise cassiopeia.type.api.exception.APIError("Server returned error {code} on call: {url}".format(code=e.code, url=url), e.code)
    101 
    102 

APIError: Server returned error 503 on call: https://euw.api.pvp.net/api/lol/euw/v2.2/matchlist/by-summoner/39991913?api_key=f16dc75b-6067-429e-81ba-f2025cf6e2c6

Do you know what's going on here?

matchID should be long, not int

Using the Match Collection example given in the code, I receive mySQL database integrity errors. It seems the data returned from the API is being cast to an int, when the API reference says match ID is a long. Now that match IDs exceed the limits of an integer, this will need a fix.

Below is the full traceback of the crash caused by the script. This occurred using v0.1.1, the current release.

Traceback (most recent call last):
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/engine/base.py", line 1139, in _execute_context
    context)
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/engine/default.py", line 450, in do_execute
    cursor.execute(statement, parameters)
  File "/usr/lib/python3/dist-packages/mysql/connector/cursor.py", line 515, in execute
    self._handle_result(self._connection.cmd_query(stmt))
  File "/usr/lib/python3/dist-packages/mysql/connector/connection.py", line 636, in cmd_query
    result = self._handle_result(self._send_cmd(ServerCmd.QUERY, query))
  File "/usr/lib/python3/dist-packages/mysql/connector/connection.py", line 554, in _handle_result
    raise errors.get_exception(packet)
mysql.connector.errors.IntegrityError: 1062 (23000): Duplicate entry '2147483647' for key 'PRIMARY'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "data_collect_spider.py", line 103, in <module>
    main()
  File "data_collect_spider.py", line 93, in main
    match = riotapi.get_match(match_reference)
  File "data_collect_spider.py", line 34, in call_wrapper
    return api_call_method(*args, **kwargs)
  File "/usr/local/lib/python3.4/dist-packages/cassiopeia/core/matchapi.py", line 38, in get_match
    cassiopeia.core.requests.data_store.store(match, id_)
  File "/usr/local/lib/python3.4/dist-packages/cassiopeia/type/api/store.py", line 269, in store
    self.session.commit()
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/session.py", line 801, in commit
    self.transaction.commit()
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/session.py", line 392, in commit
    self._prepare_impl()
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/session.py", line 372, in _prepare_impl
    self.session.flush()
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/session.py", line 2019, in flush
    self._flush(objects)
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/session.py", line 2137, in _flush
    transaction.rollback(_capture_exception=True)
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/util/langhelpers.py", line 60, in __exit__
    compat.reraise(exc_type, exc_value, exc_tb)
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/util/compat.py", line 184, in reraise
    raise value
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/session.py", line 2101, in _flush
    flush_context.execute()
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/unitofwork.py", line 373, in execute
    rec.execute(self)
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/unitofwork.py", line 532, in execute
    uow
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/persistence.py", line 174, in save_obj
    mapper, table, insert)
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/persistence.py", line 767, in _emit_insert_statements
    execute(statement, multiparams)
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/engine/base.py", line 914, in execute
    return meth(self, multiparams, params)
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/sql/elements.py", line 323, in _execute_on_connection
    return connection._execute_clauseelement(self, multiparams, params)
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/engine/base.py", line 1010, in _execute_clauseelement
    compiled_sql, distilled_params
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/engine/base.py", line 1146, in _execute_context
    context)
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/engine/base.py", line 1341, in _handle_dbapi_exception
    exc_info
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/util/compat.py", line 200, in raise_from_cause
    reraise(type(exception), exception, tb=exc_tb, cause=cause)
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/util/compat.py", line 183, in reraise
    raise value.with_traceback(tb)
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/engine/base.py", line 1139, in _execute_context
    context)
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/engine/default.py", line 450, in do_execute
    cursor.execute(statement, parameters)
  File "/usr/lib/python3/dist-packages/mysql/connector/cursor.py", line 515, in execute
    self._handle_result(self._connection.cmd_query(stmt))
  File "/usr/lib/python3/dist-packages/mysql/connector/connection.py", line 636, in cmd_query
    result = self._handle_result(self._send_cmd(ServerCmd.QUERY, query))
  File "/usr/lib/python3/dist-packages/mysql/connector/connection.py", line 554, in _handle_result
    raise errors.get_exception(packet)
sqlalchemy.exc.IntegrityError: (mysql.connector.errors.IntegrityError) 1062 (23000): Duplicate entry '2147483647' for key 'PRIMARY' [SQL: 'INSERT INTO `MatchDetail` (`mapId`, `matchCreation`, `matchDuration`, `matchId`, `matchMode`, `matchType`, `matchVersion`, `platformId`, `queueType`, region, season) VALUES (%(mapId)s, %(matchCreation)s, %(matchDuration)s, %(matchId)s, %(matchMode)s, %(matchType)s, %(matchVersion)s, %(platformId)s, %(queueType)s, %(region)s, %(season)s)'] [parameters: {'queueType': 'TEAM_BUILDER_DRAFT_RANKED_5x5', 'matchDuration': 2403, 'matchMode': 'CLASSIC', 'platformId': 'NA1', 'matchId': 2162216772, 'matchCreation': 1461059195437, 'season': 'SEASON2016', 'matchVersion': '6.7.140.3288', 'matchType': 'MATCHED_GAME', 'mapId': 11, 'region': 'NA'}]

404 Error - Missing Matches not being skipped

Hi there,

I am attempting to use the match_collection.py in the examples, and all is working well until I reach a 404 error. Its not passing that match for some reason. Any idea why this is? error message below

"Stored Match #2162108185 in my database
Stored Match #2162092305 in my database
Stored Match #2161987774 in my database
Stored Match #2161926113 in my database
Stored Match #2161885900 in my database
Stored Match #2157893127 in my database
Stored Match #2157173442 in my database
Stored Match #2157097118 in my database
Stored Match #2156370327 in my database
Stored Match #2156315148 in my database
Stored Match #2156191811 in my database
Stored Match #2156133395 in my database
Stored Match #2156084763 in my database
Stored Match #2156039683 in my database
https://na.api.pvp.net/api/lol/na/v2.2/match/2156031498?includeTimeline=True&api_key=xxxx
Got a 400 or 404

Stored None in my database

AttributeError Traceback (most recent call last)
in ()
84
85 if name == "main":
---> 86 main()

in main()
76 match = riotapi.get_match(match_reference)
77 print("Stored {0} in my database".format(match))
---> 78 for participant in match.participants:
79 if participant.summoner not in unpulled_summoners and participant.summoner not in pulled_summoners:
80 unpulled_summoners.append(participant.summoner)

AttributeError: 'NoneType' object has no attribute 'participants'

In [ ]:"

I have included a few confirmation messages to show it works for most matches. I have tried to re run it a few times but to no luck. I have copied the code in the example exactly (tripled checked) but the error part of the code that i have copied pasted is below.

def auto_retry(api_call_method):
""" A decorator to automatically retry 500s (Service Unavailable) and skip 400s (Bad Request) or 404s (Not Found). """
def call_wrapper(_args, *_kwargs):
try:
return api_call_method(_args, *_kwargs)
except APIError as error:
# Try Again Once
if error.error_code in [500]:
try:
print("Got a 500, trying again...")
return api_call_method(_args, *_kwargs)
except APIError as another_error:
if another_error.error_code in [500, 400, 404]:
pass
else:
raise another_error

        # Skip
        elif error.error_code in [400, 404]:
            print("Got a 400 or 404")
            pass

        # Fatal
        else:
            raise error
return call_wrapper

Difference between dto and core?

Hey guys, can you tell me the difference between dto and core in root directory and type directory? I'm trying to use cassiopeia but don't know which one I should call.

Besides, I want to know how to obtain Event data in a Match?

Thank you.

Usage of the champion static data api is very slow and causes all of the pages I have that use it to lag considerably.

Currently I have a page that calls the a match object to get champion images for champions played that match. I believe this call ends up getting all champion information instead of just the image link I request. I believe this is causing tremendous lag on the page and I'm sure that's not intended. There's nowhere in the documentation that I can see where I can turn this type of requesting off.

[BUG] baseriotapi.get_shard()

Hey,

I think I found a bug.

If you execute this python code (I tested it with python 3 & 3.5):

from cassiopeia import baseriotapi

baseriotapi.set_region("na")
baseriotapi.set_api_key("API_KEY")

content = baseriotapi.get_shard()

This traceback appears:

Traceback (most recent call last):
  File "test.py", line 7, in <module>
    content = baseriotapi.get_shard()
  File "/tmp/cassiopeia/dto/statusapi.py", line 24, in get_shard
    return cassiopeia.type.dto.status.ShardStatus(cassiopeia.dto.requests.get(request, static=True, include_base=False))
  File "/tmp/cassiopeia/dto/requests.py", line 41, in get
    return make_request(request=request, method="GET", params=params, static=static, include_base=include_base, tournament=tournament)
  File "/tmp/cassiopeia/dto/requests.py", line 91, in make_request
    content = limiter.call(execute_request, url, method, payload) if limiter else execute_request(url, method, payload)
  File "/tmp/cassiopeia/type/api/rates.py", line 158, in call
    return method(*args) if method else None
  File "/tmp/cassiopeia/dto/requests.py", line 134, in execute_request
    content = zlib.decompress(content, zlib.MAX_WBITS | 16).decode(encoding="UTF-8")
zlib.error: Error -3 while decompressing data: incorrect header check

'Stats' object is not callable

Hey,
I'm having an issue with getting games[0].stats to work. I'm trying to get information from the game, but when I add anything to the end of it, even if it says that it should work, I just get an error.

Example Code:
`from cassiopeia import riotapi
riotapi.set_region("NA")
riotapi.set_api_key("#My API key is here#")

summoner = riotapi.get_summoner_by_name("MonsterCWP")
games = riotapi.get_recent_games(summoner)
gamewin = games[0].stats(summoner).win
print(gamewin)`

Error when run:
Traceback (most recent call last):
File "Test.py", line 8, in
gamewin = games[0].stats(summoner).win
TypeError: 'Stats' object is not callable

Also, not sure if this is relevant, but
print(games.stats)
just prints "Stats" in the console and nothing else. Not sure if that is intended.

Anything incredibly obvious that I'm doing wrong, or is it something else?
Thanks.

Help with sqlalchemy error

Gonna start by saying I'm definitely a bit over my head here and I'm having a hard time trying to figure out what's going wrong. It's probably a mistake in my environment or something silly.

When I try to get cassiopeia to store its cache in a db, I get an error from sqlalchemy saying
sqlalchemy.exc.InvalidRequestError: SQL expression, column, or mapped entity expected - got '<class 'cassiopeia.type.dto.summoner.Summoner'>

Any suggestions on how to poke around with this?

from cassiopeia import riotapi
from cassiopeia.type.api import store

import apikey

REGION = 'NA'
API_KEY = apikey.API_KEY
riotapi.set_region(REGION)
riotapi.set_api_key(API_KEY)
store.__sa_bound = True
my_store = store.SQLAlchemyDB(flavor="mysql+pymysql", host="localhost", database="lol", username="cassio",
                              password="password")
riotapi.set_data_store(my_store)



summoner = riotapi.get_summoner_by_name("FatalElement")
print("{name} is a level {level} summoner on the NA server.".format(name=summoner.name, level=summoner.level))

/home/devin/.virtualenvs/lol/bin/python /home/devin/PycharmProjects/lol/store_test.py
Traceback (most recent call last):
  File "/home/devin/PycharmProjects/lol/store_test.py", line 19, in <module>
    summoner = riotapi.get_summoner_by_name("FatalElement")
  File "/home/devin/.virtualenvs/lol/lib/python3.4/site-packages/cassiopeia/core/summonerapi.py", line 95, in get_summoner_by_name
    summoner = cassiopeia.core.requests.data_store.get(cassiopeia.type.core.summoner.Summoner, name, "name")
  File "/home/devin/.virtualenvs/lol/lib/python3.4/site-packages/cassiopeia/type/api/store.py", line 229, in get
    val = self.session.query(class_.dto_type).filter(getattr(class_.dto_type, key_field) == keys).first()
  File "/home/devin/.virtualenvs/lol/lib/python3.4/site-packages/sqlalchemy/orm/session.py", line 1272, in query
    return self._query_cls(entities, self, **kwargs)
  File "/home/devin/.virtualenvs/lol/lib/python3.4/site-packages/sqlalchemy/orm/query.py", line 110, in __init__
    self._set_entities(entities)
  File "/home/devin/.virtualenvs/lol/lib/python3.4/site-packages/sqlalchemy/orm/query.py", line 118, in _set_entities
    entity_wrapper(self, ent)
  File "/home/devin/.virtualenvs/lol/lib/python3.4/site-packages/sqlalchemy/orm/query.py", line 3804, in __init__
    "expected - got '%r'" % (column, )
sqlalchemy.exc.InvalidRequestError: SQL expression, column, or mapped entity expected - got '<class 'cassiopeia.type.dto.summoner.Summoner'>'

Process finished with exit code 1

Python 3.4.3

how to count API requests

I have a question about what accounts as a single "request" or "call" to API when I use Cassiopeia.
I'm trying to reduce as many api requests as possible here.

Let's say I have


match_one = matchobject
dyrus=match_one.participant[0]     ### the first participant of this match is dyrus
champstat=dyrus.summoner.ranked_stats(season=Season.season_5)[dyrus.champion]

"dyrus" is a participant object of a game. and the particiapnt is Dyrus
"champstat" gives me the Dyrus's season 5 ranked statistics of the champion he played for match_one

Now I want to collect a few specific statistics of Dyrus's poppy into a list. So I say,

dyruslist=[]

dyruslist.append(dyrus.champion.id)

dyruslist.append(champstat.wins)
dyruslist.append(champstat.kda)
dyruslist.append(champstat.gold_earned)

My question here is - how many "api requests" have I just made?

is it 4? because I asked for four different data?
(dyrus.champion.id, champstat.wins, champstat.kda, champstat.gold_earned)

or is it just 1? since everything really came from the summoner object, "dyrus"?

or sth else?

If it's 4, would you have any hints that might reduce the number of requests?

.
.
.
.
.

One idea was while keeping everything the same, I use "to_json" attribute for champstat.

match_one = matchobject
dyrus=match_one.participant[0]
champstat=dyrus.summoner.ranked_stats(season=Season.season_5).to_json
champstat[champid][kda]

(something like this)

then champstat would be in json format and I use this jason to find out wins, kda, and gold earned. Since i'm just reading numbers from a single json, would this method reduce number of "requests"?

matchlistapi end_index fixed at +20

Hello there,
is there a reason why the end_index is hard coded with a fixed offset by 20 to the given begin_index in the matchlist API? See the code here.

I did not find a limit for the returned games from riot, so I guess there is no reason to limit the requested batch?

Issue with side attribute from participant (minor issue simple fix)

Hello, I've been playing around with your library, which is awesome by the way. After getting a current game and getting the list of participants out, I'm getting an error when trying to get the side of the participant. You can see in the provided screen shot. The compiler cannot find Side from the library because the constructor name is declared lowercase instead of uppercase in the return statement. Again thank you for making this library, if you would like any help with it I'd be glad to contribute.
cassiopeia error

SQLAlchemyDB using SQLite

To use a local sqlite database, the form would be as follows (excerpt pull_masters_tier.py):

32 `db = SQLAlchemyDB("sqlite", "", "", "", "/database.db")'
In order to get: sqlite:///database.db

However this throws sqlalchemy.exc.ArgumentError even though the engine creation documentation says that this would be an acceptable form.

Resolved by amending store.py:

238

try:
    self.db = sqlalchemy.create_engine("{flavor}://{username} {password}@{host}/{database}".format(flavor=flavor, host=host, database=database, username=username, password=password))
except sqlalchemy.exc.ArgumentError:
    self.db = sqlalchemy.create_engine("{flavor}:///{database}".format(flavor=flavor, database=database))

AttributeError: 'MatchReference' object has no attribute 'platformid'

Here is the problem:

match_reference_list was obtained by

match_reference_list = riotapi.get_match_list(summoner=summoner, seasons=seasons, ranked_queues=ranked_queues)

Then I wanted match_reference_list[0].platform and got:

Traceback (most recent call last):

  File "<ipython-input-2-cd23f710ee43>", line 1, in <module>
    match_reference_list[0].platform

  File "C:\Anaconda3\lib\site-packages\cassiopeia\type\core\matchlist.py", line 55, in platform
    return cassiopeia.type.core.common.Platform(self.data.platformid) if self.data.platformid else None

AttributeError: 'MatchReference' object has no attribute 'platformid

However, match_reference_list[0].data returned:

MatchReference({'platformId': 'NA1', 'role': 'SOLO', 'lane': 'TOP', 'queue': 'RANKED_SOLO_5x5', 'matchId': 2067797383, 'season': 'PRESEASON2016', 'champion': 92, 'timestamp': 1452811832918})

and cassiopeia.type.core.matchlist.MatchReference.platform returned: <property at 0x13bbcdae188>

begin_end

It would be a good practice to add the begin_end in the match_list function

:)

Update the API to expose S6 data

I think the most noticeable change is the introduction of RiftHerald fields.

Opening the issue so we can coordinate and we won't have 3 different people working on the same thing.

Is anyone working on that?
If not, I might start looking into the match DTO

PEP8

Get the repo pep8 compliant, add a linter to CI if/when setup

get_ranked_stats from cassiopeia/cassiopeia/core/statsapi.py

https://github.com/robrua/cassiopeia/blob/789e354bbcd1e091c50c8c562adfc64ff69d5133/cassiopeia/core/statsapi.py

I get that this function will return
{object of champ: object of my aggstat of that champ}

For example,
dyrus = riotapi.get_summoner_by_name("dyrus")
dyrusstat=riotapi.get_ranked_stats(summoner=dyrus, season=Season.season_5)

Now, if I print(dyrusstat[object of champ]), I will get the agg stat of that object of champ.

But I am not able to understand how to bring that object of champ.

if I want to call how dyrus did for "Dr. Mundo". How can I index within this dictionary generated by the function?

I tried to bring a champ object by using cassiopeia.riotapi.get_champions_by_id() function, but didnt work. (i.e dyrusstat[cassiopeia.riotapi.get_champions_by_id(36)] where 36 is mundo id > this didn't work)

calculate_average_kda example issues

Hi,

I think in your example script line 41 deaths += participant.stats.kills needs to be adjusted to deaths += participant.stats.deaths.

In addition, for me
stats = stats[StatSummaryType.ranked_fives].stats print("Total ranked K/D/A for {0}: {1}/{2}/{3} == {4}".format(dyrus.name, stats.kills, stats.deaths, stats.assists, round(stats.kda, 3)))

throws an AttributeError: 'NoneType' object has no attribute 'kills'

[Summoner by Name] Non existing summoners are ignored without any notice

If you call
get_summoners_by_name(summoners)

and summoners is a list, if some summoners do not exists the result will simply ignore them.

Is this supposed to happen?

To check if there was any missing summoner the length of the names and the result can be compared. I'm hesitant to make a pull request as I don't know if this is intended, or do you believe it might be good to raise an exception (personally I don't think it's a good idea) or warn the user (to define how. print a warning if print_calls is on?)

trouble getting season_6

I thought I saw a ticket regarding season_6 issue, but I couldn't find it.

I am having trouble working with season 6.


quetype=Queue.ranked_solo
myseason=Season.season_6
dyrus = riotapi.get_summoner_by_name('dyrus')
gamelist=riotapi.get_match_list(dyrus, ranked_queues=quetype, seasons=myseason)

Here I want to get the list of Dyrus' games in Season 6. I was able to get the list for season 5 using the same code, but not 6. I checked the class Season as well. Can't figure out why.

Thanks

Champion spell name lengths

The field for champion spell names created in sqlalchemy is 30 characters but there are spells with names longer than 30 characters. The longest I've found is Elise w (Volatile Spiderling / Skittering Frenzy) which is 39 characters, so unless I did something wrong the name field for champion spells should probably have a longer length.

So many service 429s

Hello!

Background: Kinda-ish new to Python, and really new to rate limits/calls.

I'm running a code where I'm pulling all Master tier matches from 4 October. I'm using the code you've kindly provided "pull_masters_tier.py" as a base. To make sure things are running smoothly, I have the line "print("Got {0}".format(match))" to show me that it is gathering matches correctly. However, I'm getting a lot of "SERVICE 429." It looks something like this as the script is running:
Got Match #2310443223
SERVICE 429
SERVICE 429
Got Match #2310385404
Got Match #2310326909
Got Match #2310279651
Got Match #2310264967
Got Match #2310198579
Got Match #2310203223
Got Match #2309999296
SERVICE 429
SERVICE 429
Got Match #2309988823
Got Match #2309994894
Got Match #2309974510
SERVICE 429
SERVICE 429
SERVICE 429
SERVICE 429

Is this related to my rate limit? I don't want to get blacklisted and need to know if things are going alright. The data is getting saved to a file nicely, so that is alright. But I'm working on a very large project with this data and will need to gather data a LOT in the near future.

Sorry for the noob question and thank you in advance!

No module name parse

>>> from cassiopeia import riotapi
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/cassiopeia/riotapi.py", line 5, in <module>
    import cassiopeia.dto.requests
  File "/usr/local/lib/python2.7/dist-packages/cassiopeia/dto/requests.py", line 5, in <module>
    import urllib.parse
ImportError: No module named parse

And I have done this before:

pi@raspberry ~/rito $ sudo pip install parse
Collecting parse
/usr/local/lib/python2.7/dist-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py:90: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.
  InsecurePlatformWarning
  Downloading parse-1.6.6-py2-none-any.whl
Installing collected packages: parse
Successfully installed parse-1.6.6

Any idea?

Getting summoner name from match fails sometimes?

Hey there, I tried getting the summoner name from a custom game I played alone and I wasn't able to get summoner names?

See match id 2030810178 on NA servers.

Here's the participant data:

CombinedParticipant({'participant': Participant({'stats': ParticipantStats({'physicalDamageDealt': 47867, 'firstBloodAssist': False, 'totalPlayerScore': 0, 'deaths': 0, 'objectivePlayerScore': 0, 'largestCriticalStrike': 112, 'totalDamageDealt': 47867, 'magicDamageDealtToChampions': 0, 'largestMultiKill': 0, 'largestKillingSpree': 0, 'quadraKills': 0, 'magicDamageTaken': 0, 'towerKills': 3, 'teamObjective': 0, 'neutralMinionsKilledEnemyJungle': 0, 'firstTowerAssist': False, 'neutralMinionsKilledTeamJungle': 0, 'firstTowerKill': False, 'item2': 0, 'item3': 0, 'item0': 1038, 'item1': 3086, 'item6': 3340, 'wardsPlaced': 0, 'item4': 0, 'item5': 0, 'minionsKilled': 46, 'tripleKills': 0, 'firstBloodKill': False, 'champLevel': 12, 'nodeNeutralizeAssist': 0, 'nodeCaptureAssist': 0, 'unrealKills': 0, 'winner': True, 'magicDamageDealt': 0, 'kills': 0, 'doubleKills': 0, 'firstInhibitorKill': True, 'trueDamageTaken': 0, 'nodeNeutralize': 0, 'firstInhibitorAssist': False, 'assists': 0, 'totalScoreRank': 0, 'neutralMinionsKilled': 0, 'combatPlayerScore': 0, 'nodeCapture': 0, 'visionWardsBoughtInGame': 0, 'physicalDamageDealtToChampions': 0, 'goldSpent': 2500, 'trueDamageDealt': 0, 'trueDamageDealtToChampions': 0, 'totalTimeCrowdControlDealt': 29, 'pentaKills': 0, 'wardsKilled': 0, 'totalHeal': 0, 'goldEarned': 5001, 'sightWardsBoughtInGame': 0, 'totalDamageDealtToChampions': 0, 'totalUnitsHealed': 0, 'inhibitorKills': 1, 'totalDamageTaken': 2477, 'killingSprees': 0, 'physicalDamageTaken': 2477}), 'spell1Id': 4, 'participantId': 1, 'runes': [Rune({'runeId': 5273, 'rank': 9}), Rune({'runeId': 5297, 'rank': 9}), Rune({'runeId': 5317, 'rank': 9}), Rune({'runeId': 5357, 'rank': 3})], 'highestAchievedSeasonTier': u'UNRANKED', 'teamId': 100, 'spell2Id': 14, 'masteries': [], 'timeline': ParticipantTimeline({'vilemawAssistsPerMinCounts': None, 'goldPerMinDeltas': ParticipantTimelineData({'thirtyToEnd': 0.0, 'twentyToThirty': 0.0, 'zeroToTen': 111.0, '_type': 'goldPerMinDeltas', 'tenToTwenty': 310.8}), 'baronAssistsPerMinCounts': None, 'ancientGolemAssistsPerMinCounts': None, 'elderLizardAssistsPerMinCounts': None, 'towerKillsPerMinCounts': None, 'xpDiffPerMinDeltas': None, 'creepsPerMinDeltas': ParticipantTimelineData({'thirtyToEnd': 0.0, 'twentyToThirty': 0.0, 'zeroToTen': 0.7, '_type': 'creepsPerMinDeltas', 'tenToTwenty': 3.8}), 'dragonKillsPerMinCounts': None, 'damageTakenDiffPerMinDeltas': None, 'role': u'SOLO', 'towerKillsPerMinDeltas': None, 'elderLizardKillsPerMinCounts': None, 'ancientGolemKillsPerMinCounts': None, 'csDiffPerMinDeltas': None, 'baronKillsPerMinCounts': None, 'assistedLaneKillsPerMinDeltas': None, 'assistedLaneDeathsPerMinDeltas': None, 'wardsPerMinDeltas': None, 'lane': u'MIDDLE', 'inhibitorKillsPerMinCounts': None, 'towerAssistsPerMinCounts': None, 'vilemawKillsPerMinCounts': None, 'xpPerMinDeltas': ParticipantTimelineData({'thirtyToEnd': 0.0, 'twentyToThirty': 0.0, 'zeroToTen': 218.20000000000002, '_type': 'xpPerMinDeltas', 'tenToTwenty': 522.4}), 'dragonAssistsPerMinCounts': None, 'inhibitorAssistsPerMinCounts': None, 'damageTakenPerMinDeltas': ParticipantTimelineData({'thirtyToEnd': 0.0, 'twentyToThirty': 0.0, 'zeroToTen': 36.1, '_type': 'damageTakenPerMinDeltas', 'tenToTwenty': 206.6})}), 'championId': 104}), 'identity': ParticipantIdentity({'player': None, 'participantId': 1})})

Is it possible to get the summoner name from get_match? I could have sworn I have done that, maybe it's just single player games?

Error:

In [26]: match.blue_team.participants[0].summoner_name
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-26-431ee5f5d5ad> in <module>()
----> 1 match.blue_team.participants[0].summoner_name

/Users/eric/.virtualenvs/chronster/lib/python2.7/site-packages/cassiopeia/type/core/match.pyc in summoner_name(self)
    212     def summoner_name(self):
    213         """str    the participant's summoner name"""
--> 214         return self.data.identity.player.summonerName
    215 
    216 

AttributeError: 'NoneType' object has no attribute 'summonerName'```

SQLAlchemy as dependency?

I'm wondering why SQLAlchemy is a dependency. I looked at the code and it seems like it's only used when SQLAlchemy is actually installed, but works perfectly without it. Still, it's automatically installed over pip even though it's not needed.

I like this API more than the others since it's activately in development, but since I want to use it in a Django application with Django database models, I have no use for the SQLAlchemy support.

AttributeError: 'Image' object has no attribute 'full'

In your documentation for riot API vs base API you list a method full for images. Calling this method raises an exception:


---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-122-658f312182ae> in <module>()
----> 1 match.participants['methodds'].champion.image.full

AttributeError: 'Image' object has no attribute 'full'

In addition, while calling image.link returns a string, e.g. Karma.png, what would be the base url for this image? I would like to use cassiopeia for downloading all champion images.

ban.champion.name for ban in match.red_team.bans Returns nothing

Hello!

Thank you so much for your help last time, I thought it was very useful! I'm running into another problem again. The line
print(" Red Team Bans: {0}".format([ban.champion.name for ban in match.red_team.bans]))
Returns
Red Team Bans: []
Which I know is incorrect, because this game is a ranked 5v5. Do you know what I'm messing up on? This line was taken from the file parse_match_information.py

Thank you so much in advance!

Python 2.7 and lower support

I installed via "pip install cassiopeia" and I have a python 2.7 installation. I'm currently going through it now and changing the imports from Python 3 to python 2.7, because they look to be not that many. I just think you should have a disclaimer or something.

Remove sqlalchemy dependency?

Heyoo! First of all, thanks so much for all the hard work on this, definitely stands above the rest of the Riot python APIs :)

Do you think it would make sense to remove the requirement to install sqlalchemy along with this? I believe it's not required? I wouldn't mind doing the work myself, just wondering if that's kosher!

'UNRANKED' Tier handling

  File "...\cassiopeia\type\core\match.py", line 178, in previous_season_tier
    return cassiopeia.type.core.common.Tier(self.data.participant.highestAchievedSeasonTier) if self.data.participant.highestAchievedSeasonTier else None

  File "C:\Anaconda3\lib\enum.py", line 235, in __call__
    return cls.__new__(cls, value)

  File "C:\Anaconda3\lib\enum.py", line 470, in __new__
    raise ValueError("%r is not a valid %s" % (value, cls.__name__))

ValueError: 'UNRANKED' is not a valid Tier

Here if self.data.participant.highestAchievedSeasonTier has a value 'UNRANKED', it will raise a ValueError.

The Tier class in cassiopeia.type.core.common does not have one unranked value:

class Tier(enum.Enum):
    challenger = "CHALLENGER"
    master = "MASTER"
    diamond = "DIAMOND"
    platinum = "PLATINUM"
    gold = "GOLD"
    silver = "SILVER"
    bronze = "BRONZE"

After I add a line it's okay:

unranked = "UNRANKED"

I'm not quite familiar with the manner of Github and do not know if it's appropriate to commit a fix like this.

Ghost match

Hey guys,

I spent half an hour to understand an error happened when I used Cass. Firstly you can try this query, and will find a match_id '2405929288':

https://na.api.pvp.net/api/lol/na/v2.2/matchlist/by-summoner/73099728?rankedQueues=RANKED_SOLO_5x5&seasons=PRESEASON2016&api_key=XXX

Then you try to get the details of this match, and it will return 404, which means even if we can find a match_id in one match list, we are not 100% sure it has record from the match method:

https://na.api.pvp.net/api/lol/na/v2.2/match/2405929288?includeTimeline=0&api_key=XXX

{
    "status": {
        "message": "Not Found",
        "status_code": 404
    }
}

Because of this, we may get an None when we use match = riotapi.get_match(mf)
in Cass. Right now I choose to use if match is None to avoid this (can not use '==' because Match.eq use Match.id).

Update: And then I found the region of this match is 'EUW', which means the region setting is useless?

Update 2: I reconsidered this problem, and found that if Cass. returned 404 correctly, there should not be this problem. So I think the exception part of Cass. should be checked.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.