pyield 0.44.2__tar.gz → 0.44.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyield-0.44.2 → pyield-0.44.4}/PKG-INFO +1 -1
- pyield-0.44.4/pyield/__about__.py +1 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/_internal/retry.py +0 -4
- {pyield-0.44.2 → pyield-0.44.4}/pyield/b3/futures/__init__.py +17 -43
- {pyield-0.44.2 → pyield-0.44.4}/pyield/b3/futures/historical.py +3 -6
- {pyield-0.44.2 → pyield-0.44.4}/pyield/b3/futures/intraday.py +19 -4
- {pyield-0.44.2 → pyield-0.44.4}/pyield/b3/price_report.py +6 -7
- {pyield-0.44.2 → pyield-0.44.4}/pyield/selic/cpm.py +4 -5
- pyield-0.44.2/pyield/__about__.py +0 -1
- {pyield-0.44.2 → pyield-0.44.4}/.gitignore +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/LICENSE +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/README.md +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/__init__.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/_internal/__init__.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/_internal/converters.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/_internal/data_cache.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/_internal/types.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/anbima/__init__.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/anbima/difusao.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/anbima/ettj_intraday.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/anbima/ettj_last.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/anbima/ima.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/anbima/imaq.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/anbima/tpf.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/b3/__init__.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/b3/_contracts.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/b3/_validar_pregao.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/b3/di1.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/b3/di_over.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/b3/futures/common.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/b3/intraday_derivatives.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/bc/__init__.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/bc/auction.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/bc/copom.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/bc/ptax_api.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/bc/rates.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/bc/repo.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/bc/trades_intraday.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/bc/trades_monthly.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/bc/vna.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/bday/__init__.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/bday/core.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/bday/holidays/br_holidays_new.txt +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/bday/holidays/br_holidays_old.txt +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/bday/holidays/brholidays.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/clock.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/fwd.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/interpolator.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/ipca/__init__.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/ipca/historical.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/ipca/projected.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/py.typed +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/rmd.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/selic/__init__.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/selic/probabilities.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/tn/__init__.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/tn/auctions.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/tn/benchmark.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/tn/lft.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/tn/ltn.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/tn/ntnb.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/tn/ntnb1.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/tn/ntnbprinc.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/tn/ntnc.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/tn/ntnf.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/tn/pre.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyield/tn/tools.py +0 -0
- {pyield-0.44.2 → pyield-0.44.4}/pyproject.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyield
|
|
3
|
-
Version: 0.44.
|
|
3
|
+
Version: 0.44.4
|
|
4
4
|
Summary: A Python library for analysis of fixed income instruments in Brazil
|
|
5
5
|
Project-URL: Homepage, https://github.com/crdcj/PYield
|
|
6
6
|
Project-URL: Documentation, https://crdcj.github.io/PYield
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.44.4"
|
|
@@ -11,10 +11,6 @@ _HTTP_MUITAS_REQUISICOES = 429
|
|
|
11
11
|
_HTTP_ERRO_SERVIDOR_MINIMO = 500
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
class DadoIndisponivelError(Exception):
|
|
15
|
-
"""Levantada quando o dado baixado for considerado inválido (dado vazio/pequeno)."""
|
|
16
|
-
|
|
17
|
-
|
|
18
14
|
_EXCECOES_TRANSITORIAS = (
|
|
19
15
|
rex.Timeout,
|
|
20
16
|
rex.ConnectionError,
|
|
@@ -4,7 +4,6 @@ import polars as pl
|
|
|
4
4
|
|
|
5
5
|
import pyield._internal.converters as cv
|
|
6
6
|
from pyield import clock
|
|
7
|
-
from pyield._internal.retry import DadoIndisponivelError
|
|
8
7
|
from pyield._internal.types import DateLike, any_is_empty
|
|
9
8
|
from pyield.b3._contracts import normalizar_codigos_contrato
|
|
10
9
|
from pyield.b3._validar_pregao import data_negociacao_valida
|
|
@@ -13,41 +12,10 @@ from pyield.b3.futures import historical, intraday
|
|
|
13
12
|
logger = logging.getLogger(__name__)
|
|
14
13
|
|
|
15
14
|
|
|
16
|
-
def _buscar_intraday_ou_historico(
|
|
17
|
-
data_negociacao,
|
|
18
|
-
codigos_contrato: list[str],
|
|
19
|
-
full_report: bool,
|
|
20
|
-
) -> pl.DataFrame:
|
|
21
|
-
horario_atual = clock.now().time()
|
|
22
|
-
if horario_atual < intraday.HORA_INICIO_INTRADAY:
|
|
23
|
-
return pl.DataFrame()
|
|
24
|
-
|
|
25
|
-
if horario_atual >= intraday.HORA_FIM_INTRADAY:
|
|
26
|
-
for tentativa_full_report in (full_report, not full_report):
|
|
27
|
-
try:
|
|
28
|
-
df_historico = historical.historical(
|
|
29
|
-
data_negociacao, codigos_contrato, tentativa_full_report
|
|
30
|
-
)
|
|
31
|
-
except DadoIndisponivelError:
|
|
32
|
-
continue
|
|
33
|
-
if not df_historico.is_empty():
|
|
34
|
-
logger.info("Dados consolidados disponíveis. Usando histórico.")
|
|
35
|
-
return df_historico
|
|
36
|
-
logger.info("Histórico consolidado indisponível. Tentando intraday.")
|
|
37
|
-
|
|
38
|
-
dataframes_intraday = [intraday.intraday(codigo) for codigo in codigos_contrato]
|
|
39
|
-
dataframes_intraday = [df for df in dataframes_intraday if not df.is_empty()]
|
|
40
|
-
if not dataframes_intraday:
|
|
41
|
-
return pl.DataFrame()
|
|
42
|
-
if len(dataframes_intraday) == 1:
|
|
43
|
-
return dataframes_intraday[0]
|
|
44
|
-
return pl.concat(dataframes_intraday, how="diagonal_relaxed").sort("TickerSymbol")
|
|
45
|
-
|
|
46
|
-
|
|
47
15
|
def futures(
|
|
48
16
|
date: DateLike,
|
|
49
17
|
contract_code: str | list[str],
|
|
50
|
-
full_report: bool =
|
|
18
|
+
full_report: bool | None = None,
|
|
51
19
|
) -> pl.DataFrame:
|
|
52
20
|
"""Busca dados de um contrato futuro da B3 para a data de referência.
|
|
53
21
|
|
|
@@ -59,10 +27,12 @@ def futures(
|
|
|
59
27
|
- Moedas: DOL, WDO, EUR, GBR, JAP, CNY
|
|
60
28
|
- Índices: IND, WIN, ISP, WSP
|
|
61
29
|
- Commodities: BGI, CCM, ICF, CNL, SJC, SOY, ETH, GLD
|
|
62
|
-
full_report:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
30
|
+
full_report: Controla a fonte de dados quando o dado não está no cache.
|
|
31
|
+
Se None (padrão), prioriza dados intraday (para data de hoje) e
|
|
32
|
+
usa SPR como fallback — ideal para uso interativo.
|
|
33
|
+
Se False, usa o simplified price report (SPR, ~2 KB).
|
|
34
|
+
Se True, usa apenas o price report completo (PR, ~2 MB) —
|
|
35
|
+
indicado para processos batch noturnos.
|
|
66
36
|
|
|
67
37
|
Returns:
|
|
68
38
|
DataFrame Polars com os dados do contrato informado.
|
|
@@ -105,12 +75,16 @@ def futures(
|
|
|
105
75
|
if not data_negociacao_valida(data_negociacao):
|
|
106
76
|
return pl.DataFrame()
|
|
107
77
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
78
|
+
# None: tenta intraday primeiro (só hoje + horário ok)
|
|
79
|
+
if full_report is None:
|
|
80
|
+
eh_hoje = intraday.data_intraday_valida(data_negociacao)
|
|
81
|
+
if eh_hoje:
|
|
82
|
+
horario = clock.now().time()
|
|
83
|
+
if horario >= intraday.HORA_INICIO_INTRADAY:
|
|
84
|
+
df = intraday.intraday(codigos_contrato)
|
|
85
|
+
if not df.is_empty():
|
|
86
|
+
return df
|
|
87
|
+
full_report = False
|
|
114
88
|
|
|
115
89
|
return historical.historical(data_negociacao, codigos_contrato, full_report)
|
|
116
90
|
|
|
@@ -24,9 +24,8 @@ def historical(
|
|
|
24
24
|
Args:
|
|
25
25
|
data: Data de negociação.
|
|
26
26
|
codigo_contrato: Código(s) do contrato futuro na B3.
|
|
27
|
-
full_report: Se False (padrão), usa o simplified price report
|
|
28
|
-
|
|
29
|
-
price report completo (PR, ~2 MB) com todos os dados de negociação.
|
|
27
|
+
full_report: Se False (padrão), usa o simplified price report
|
|
28
|
+
(SPR, ~2 KB). Se True, usa o price report completo (PR, ~2 MB).
|
|
30
29
|
|
|
31
30
|
Returns:
|
|
32
31
|
DataFrame Polars com dados históricos de futuros.
|
|
@@ -88,9 +87,7 @@ def historical(
|
|
|
88
87
|
if codigos_sem_cache:
|
|
89
88
|
for codigo in codigos_sem_cache:
|
|
90
89
|
df_bruto = fetch_price_report(
|
|
91
|
-
date=data,
|
|
92
|
-
contract_code=codigo,
|
|
93
|
-
full_report=full_report,
|
|
90
|
+
date=data, contract_code=codigo, full_report=full_report
|
|
94
91
|
)
|
|
95
92
|
if df_bruto.is_empty():
|
|
96
93
|
continue
|
|
@@ -5,6 +5,7 @@ import polars as pl
|
|
|
5
5
|
import polars.selectors as cs
|
|
6
6
|
|
|
7
7
|
from pyield import bday, clock
|
|
8
|
+
from pyield.b3._contracts import normalizar_codigos_contrato
|
|
8
9
|
from pyield.b3._validar_pregao import data_negociacao_valida
|
|
9
10
|
from pyield.b3.futures.common import expr_dv01
|
|
10
11
|
from pyield.b3.intraday_derivatives import fetch_intraday_derivatives
|
|
@@ -13,8 +14,6 @@ from pyield.fwd import forwards
|
|
|
13
14
|
# Pregão abre às 9:00, porém os dados têm atraso de 15 minutos.
|
|
14
15
|
# Esperar 1 minuto adicional para garantir que estejam disponíveis (9:16h).
|
|
15
16
|
HORA_INICIO_INTRADAY = dt.time(9, 16)
|
|
16
|
-
# Pregão fecha às 18:00h, momento em que os dados consolidados começam a ser preparados.
|
|
17
|
-
HORA_FIM_INTRADAY = dt.time(18, 30)
|
|
18
17
|
|
|
19
18
|
logger = logging.getLogger(__name__)
|
|
20
19
|
|
|
@@ -27,7 +26,7 @@ def data_intraday_valida(data_verificacao: dt.date) -> bool:
|
|
|
27
26
|
return data_verificacao == clock.today()
|
|
28
27
|
|
|
29
28
|
|
|
30
|
-
def intraday(codigo_contrato: str) -> pl.DataFrame:
|
|
29
|
+
def intraday(codigo_contrato: str | list[str]) -> pl.DataFrame:
|
|
31
30
|
"""Busca os dados intraday mais recentes da B3.
|
|
32
31
|
|
|
33
32
|
Os dados intraday da fonte possuem atraso aproximado de 15 minutos.
|
|
@@ -35,7 +34,8 @@ def intraday(codigo_contrato: str) -> pl.DataFrame:
|
|
|
35
34
|
menos 15 minutos.
|
|
36
35
|
|
|
37
36
|
Args:
|
|
38
|
-
codigo_contrato: Código base do contrato futuro na B3
|
|
37
|
+
codigo_contrato: Código base do contrato futuro na B3, ou lista de
|
|
38
|
+
códigos.
|
|
39
39
|
|
|
40
40
|
Returns:
|
|
41
41
|
DataFrame Polars com dados intraday processados.
|
|
@@ -65,6 +65,21 @@ def intraday(codigo_contrato: str) -> pl.DataFrame:
|
|
|
65
65
|
- LastRate (Float64): Última taxa negociada.
|
|
66
66
|
- ForwardRate (Float64): Taxa a termo (apenas DI1/DAP).
|
|
67
67
|
"""
|
|
68
|
+
codigos = normalizar_codigos_contrato(codigo_contrato)
|
|
69
|
+
if not codigos:
|
|
70
|
+
return pl.DataFrame()
|
|
71
|
+
|
|
72
|
+
dfs = [_intraday_contrato(c) for c in codigos]
|
|
73
|
+
dfs = [df for df in dfs if not df.is_empty()]
|
|
74
|
+
if not dfs:
|
|
75
|
+
return pl.DataFrame()
|
|
76
|
+
if len(dfs) == 1:
|
|
77
|
+
return dfs[0]
|
|
78
|
+
return pl.concat(dfs, how="diagonal_relaxed").sort("TickerSymbol")
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _intraday_contrato(codigo_contrato: str) -> pl.DataFrame:
|
|
82
|
+
"""Busca e processa dados intraday de um único contrato."""
|
|
68
83
|
try:
|
|
69
84
|
df_bruto = fetch_intraday_derivatives(codigo_contrato)
|
|
70
85
|
if df_bruto.is_empty():
|
|
@@ -10,7 +10,7 @@ from lxml import etree
|
|
|
10
10
|
from lxml.etree import _Element
|
|
11
11
|
|
|
12
12
|
import pyield._internal.converters as cv
|
|
13
|
-
from pyield._internal.retry import
|
|
13
|
+
from pyield._internal.retry import retry_padrao
|
|
14
14
|
from pyield._internal.types import DateLike, any_is_empty
|
|
15
15
|
from pyield.b3._contracts import normalizar_codigos_contrato
|
|
16
16
|
from pyield.b3._validar_pregao import data_negociacao_valida
|
|
@@ -112,8 +112,7 @@ def _baixar_zip_url(data: dt.date, relatorio_completo: bool) -> bytes:
|
|
|
112
112
|
resposta.raise_for_status()
|
|
113
113
|
|
|
114
114
|
if len(resposta.content) < MIN_TAMANHO_ZIP_BYTES:
|
|
115
|
-
|
|
116
|
-
raise DadoIndisponivelError(f"Sem dados disponíveis para {data_str_formatada}.")
|
|
115
|
+
return bytes()
|
|
117
116
|
return resposta.content
|
|
118
117
|
|
|
119
118
|
|
|
@@ -231,6 +230,8 @@ def _processar_xml_extraido(xml_bytes: bytes, codigo_contrato: str) -> pl.DataFr
|
|
|
231
230
|
@lru_cache(maxsize=64)
|
|
232
231
|
def _obter_xml_price_report(data: dt.date, relatorio_completo: bool) -> bytes:
|
|
233
232
|
dados_zip = _baixar_zip_url(data, relatorio_completo)
|
|
233
|
+
if not dados_zip:
|
|
234
|
+
return bytes()
|
|
234
235
|
return _extrair_xml_zip_aninhado(dados_zip)
|
|
235
236
|
|
|
236
237
|
|
|
@@ -311,8 +312,6 @@ def fetch_price_report(
|
|
|
311
312
|
- MinLimitValue (Float64): Limite mínimo de variação.
|
|
312
313
|
|
|
313
314
|
Raises:
|
|
314
|
-
DadoIndisponivelError: Se a data for válida, mas o endpoint não fornecer
|
|
315
|
-
arquivo para a data consultada.
|
|
316
315
|
requests.HTTPError: Se a requisição HTTP ao endpoint falhar.
|
|
317
316
|
zipfile.BadZipFile: Se o arquivo ZIP recebido estiver corrompido.
|
|
318
317
|
etree.XMLSyntaxError: Se o XML recebido estiver malformado.
|
|
@@ -348,7 +347,7 @@ def fetch_price_report(
|
|
|
348
347
|
dataframes.append(df)
|
|
349
348
|
if not dataframes:
|
|
350
349
|
return pl.DataFrame()
|
|
351
|
-
return pl.concat(dataframes).sort("TickerSymbol")
|
|
350
|
+
return pl.concat(dataframes, how="diagonal").sort("TickerSymbol")
|
|
352
351
|
except (zipfile.BadZipFile, etree.XMLSyntaxError):
|
|
353
352
|
registro.exception(f"Falha ao parsear o price report de {contratos} em {date}.")
|
|
354
353
|
raise
|
|
@@ -433,4 +432,4 @@ def read_price_report(
|
|
|
433
432
|
dataframes.append(df)
|
|
434
433
|
if not dataframes:
|
|
435
434
|
return pl.DataFrame()
|
|
436
|
-
return pl.concat(dataframes).sort("TickerSymbol")
|
|
435
|
+
return pl.concat(dataframes, how="diagonal").sort("TickerSymbol")
|
|
@@ -39,7 +39,7 @@ import requests
|
|
|
39
39
|
|
|
40
40
|
import pyield._internal.converters as cv
|
|
41
41
|
from pyield import bday
|
|
42
|
-
from pyield._internal.retry import
|
|
42
|
+
from pyield._internal.retry import retry_padrao
|
|
43
43
|
from pyield._internal.types import DateLike
|
|
44
44
|
from pyield.b3._validar_pregao import data_negociacao_valida
|
|
45
45
|
from pyield.b3.price_report import (
|
|
@@ -284,12 +284,11 @@ def data(date: DateLike) -> pl.DataFrame:
|
|
|
284
284
|
return _empty_schema()
|
|
285
285
|
|
|
286
286
|
try:
|
|
287
|
-
zip_data = _baixar_zip_url(trade_date,
|
|
287
|
+
zip_data = _baixar_zip_url(trade_date, relatorio_completo=False)
|
|
288
|
+
if not zip_data:
|
|
289
|
+
return _empty_schema()
|
|
288
290
|
xml_bytes = _extrair_xml_zip_aninhado(zip_data)
|
|
289
291
|
records = _parsear_xml_registros(xml_bytes, "CPM")
|
|
290
|
-
except DadoIndisponivelError:
|
|
291
|
-
logger.warning("CPM: dados SPR indisponíveis para %s.", trade_date)
|
|
292
|
-
return _empty_schema()
|
|
293
292
|
except Exception:
|
|
294
293
|
logger.exception("CPM: falha ao baixar SPR para %s.", trade_date)
|
|
295
294
|
return _empty_schema()
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.44.2"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|