-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adiciona a chamada de UF no cliente da API #24
Conversation
logging.info("Extracting data from Fogo Cruzado's API...") | ||
client = load_client() | ||
resp = client.get(url="https://api.fogocruzado.org.br/api/v1/cities") | ||
return to_dataframe(resp) | ||
return extract_data_api("https://api.fogocruzado.org.br/api/v1/cities") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Essa mudança não era absolutamente necessária, mas o corpo de ambas as funções era o praticamente o mesmo, então reduzi a repetição utiliando a extract_data_api
para executar a extract_cities_api
.
Esse arquivo vai sumir já já quando criarmos os métodos cities
e occurrences
no cliente.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
Token, | ||
CredentialsNotFoundError, | ||
IncorrectCrdentialsError, | ||
Token, | ||
UnknownFormatError, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apenas organizei em ordem alfabética pois estava me perdendo me pergntando já importamos isso…
from crossfire.fogocruzado_utils import extract_data_api, extract_cities_api | ||
|
||
from crossfire.load_data import InvalidDateIntervalError, get_fogocruzado | ||
from geopandas import GeoDataFrame | ||
from pandas import DataFrame | ||
|
||
from crossfire.fogocruzado_utils import extract_data_api, extract_cities_api | ||
from crossfire.load_data import InvalidDateIntervalError, get_fogocruzado | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Organizei os import
s de acordo com a PEP8 pois estava me perdendo procurando as coisas importadas.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cuducos , fiquei meio perdido. Se der para fazermos um review juntos rapidinho, pq não sei se pude me expressaar em minhas dúvidas...
De qq forma, aprovo e vo tentar estuda-lo melhor à tarde.
Python/crossfire/crossfire/client.py
Outdated
@@ -44,12 +74,20 @@ def __init__(self, **kwargs): | |||
|
|||
self.cached_token = None | |||
|
|||
@cached_property | |||
def has_pandas(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Entendo que essa propriedade checa se o pandas está instalado. Confirma?
Se não está instalaldo, não saltaria um erro jpa no import?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Se não está instalaldo, não saltaria um erro jpa no import?
Esse é um ótimo ponto. Na verdade eu introduzi esse padrão adiantando o que sugeri sobre o Pandas poder eventualmente não ser uma dependência. Também documentei essa ideia no meu rascunho #27.
Se formos para frente com essa ideia, vamos também mudar o import
— vc prefere que eu já mude agora para algo como:
try:
from pandas import DataFrame
has_pandas = True
except ModuleNotFoundError:
has_pandas = False
Dessa forma podemos matar esse método. O que acha?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sugeri e3f505e ✨
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cuducos concordo com essa proposta de ter o pandas
como uma dependencia extra...
if format and format not in FORMATS: | ||
raise UnknownFormatError(format) | ||
|
||
response = method(self, *args, **kwargs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
De onde vem este method
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Vou usar as palavras de um amigo meu, excelente pessoa e com nível técnico avançado:
Ela recebe um
method
como parâmetro e é "empacotado" por umwrapper
que pode ter parâmetros posicionais ou nomados...
Ou seja, quando eu uso:
@parse_response
def get(url):
print(url)
method
é a própria função get
— o empacotamento do decorador com @parse_response
seguido de def get
na outra linhaé basicamente
parse_response(get)`
Repare que não estou executando a função get
ainda, apenas passando o nome dela (uma referência a ela). Aí ela é executada no corpo da função (decorador) parse_response
— bem na linha em q vc comentou : )
@@ -64,13 +102,19 @@ def token(self): | |||
) | |||
return self.cached_token.value | |||
|
|||
@parse_response |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Estw decorador chama a função criada antes, né?
Ela recebe um method
como parâmetro e é "empacotado" por um wrapper
que pode ter parâmetros posicionais ou nomados...
É isso?
|
||
if "headers" not in kwargs: | ||
kwargs["headers"] = auth | ||
else: | ||
kwargs["headers"].update(auth) | ||
|
||
return get(*args, **kwargs) | ||
|
||
def states(self, format=None): | ||
return self.get(f"{URL}/states", format=format) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Esse get
é o que possui parse_response
como decorador, confirma? vc está passando a url como parẫmetro posicional e o format, como nomeado.
Logo, format será usado no wrapper
, quando informado. Mas ainda não entendi o method
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Esse
get
é o que possuiparse_response
como decorador, confirma?
Perfeito.
Logo,
format
será usado nowrapper
, quando informado.
Exato, como documentei aqui. Alguma sugestão de melhoria para deixar isso mais claro?
Mas ainda não entendi o
method
.
Entendeu sim hahaha… vc descreve o que é o método nesse teu comentário. Vamos falar mais sobre ele pois posso estar interpretando errado : )
logging.info("Extracting data from Fogo Cruzado's API...") | ||
client = load_client() | ||
resp = client.get(url="https://api.fogocruzado.org.br/api/v1/cities") | ||
return to_dataframe(resp) | ||
return extract_data_api("https://api.fogocruzado.org.br/api/v1/cities") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
Esse PR adiciona o endpoint
states
ao cliente da API:honE adiciona a opção para não utilizar o Pandas caso não seja desejado:
No caminho:
Bearer
no cabeçalho)to_dataframe
para o módulo do cliente (creio que oload_data
deve sumir já já)to_dataframe
(retorna umDataFrame
com os dados dedata
na resposta, não com a resposta toda)