PYield 0.3.5__tar.gz → 0.3.6__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.3.5 → pyield-0.3.6}/PKG-INFO +6 -16
- {pyield-0.3.5 → pyield-0.3.6}/README.md +5 -15
- pyield-0.3.6/pyield/__about__.py +1 -0
- {pyield-0.3.5 → pyield-0.3.6}/pyield/anbima.py +1 -1
- {pyield-0.3.5 → pyield-0.3.6}/pyield/br_calendar.py +42 -29
- {pyield-0.3.5 → pyield-0.3.6}/pyield/br_holidays.py +13 -15
- {pyield-0.3.5 → pyield-0.3.6}/pyield/di_futures.py +4 -3
- {pyield-0.3.5 → pyield-0.3.6}/pyield/di_web.py +3 -2
- {pyield-0.3.5 → pyield-0.3.6}/pyield/di_xml.py +24 -4
- {pyield-0.3.5 → pyield-0.3.6}/pyproject.toml +2 -1
- pyield-0.3.6/tests/__init__.py +0 -0
- pyield-0.3.5/pyield/__about__.py +0 -1
- {pyield-0.3.5 → pyield-0.3.6}/LICENSE +0 -0
- {pyield-0.3.5 → pyield-0.3.6}/pyield/__init__.py +0 -0
- {pyield-0.3.5 → pyield-0.3.6}/pyield/br_holidays_new.txt +0 -0
- {pyield-0.3.5 → pyield-0.3.6}/pyield/br_holidays_old.txt +0 -0
- /pyield-0.3.5/tests/__init__.py → /pyield-0.3.6/pyield/py.typed +0 -0
- {pyield-0.3.5 → pyield-0.3.6}/tests/test_br_calendar.py +0 -0
- {pyield-0.3.5 → pyield-0.3.6}/tests/test_di.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PYield
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.6
|
|
4
4
|
Summary: A Python library for analysis of fixed income instruments in Brazil
|
|
5
5
|
Keywords: fixed-income, brazil, finance, analysis, bonds
|
|
6
6
|
Author-Email: Carlos Carvalho <cr.cj@outlook.com>
|
|
@@ -51,10 +51,11 @@ Description-Content-Type: text/markdown
|
|
|
51
51
|
Welcome to PYield, a Python library designed for the analysis of fixed income instruments in Brazil. This library is tailored for financial analysts, researchers, and enthusiasts interested in the Brazilian fixed income market. Leveraging the power of popular Python libraries like Pandas and Requests, PYield simplifies the process of obtaining and processing data from key sources such as Tesouro Nacional (TN), Banco Central (BC), ANBIMA, and B3.
|
|
52
52
|
## Features
|
|
53
53
|
|
|
54
|
-
- Data Collection
|
|
55
|
-
- Data Processing
|
|
56
|
-
- Analysis Tools
|
|
57
|
-
- Easy Integration
|
|
54
|
+
- **Data Collection**: Automated fetching of data from BC, ANBIMA and B3.
|
|
55
|
+
- **Data Processing**: Efficient processing and normalization of fixed income data.
|
|
56
|
+
- **Analysis Tools**: Built-in functions for common analysis tasks in fixed income markets.
|
|
57
|
+
- **Easy Integration**: Seamless integration with Python data analysis workflows.
|
|
58
|
+
- **Type Hints**: Full support for static type checking, enhancing development experience and code quality.
|
|
58
59
|
|
|
59
60
|
## Installation
|
|
60
61
|
|
|
@@ -67,17 +68,6 @@ pip install pyield
|
|
|
67
68
|
```python
|
|
68
69
|
import pyield as yd
|
|
69
70
|
|
|
70
|
-
# Get a pandas dataframe with the DI raw data from B3 (first date available is 05-06-1991)
|
|
71
|
-
>>> yd.get_di(trade_date='2024-03-08', raw=True)
|
|
72
|
-
VENCTO CONTR. ABERT.(1) CONTR. FECH.(2) NÚM. NEGOC. ... AJUSTE VAR. PTOS. ÚLT.OF. COMPRA ÚLT.OF. VENDA
|
|
73
|
-
J24 3608626 3608626 294 ... 99,383.080 0,17- 10.952 10.956
|
|
74
|
-
K24 607759 607759 179 ... 98,508.490 0,03+ 10.774 10.780
|
|
75
|
-
M24 339641 339641 194 ... 97,706.210 1,68- 10.602 10.604
|
|
76
|
-
... ... ... ... ... ... ... ... ...
|
|
77
|
-
F37 3517 3517 0 ... 26,863.980 336,32- 0.000 0.000
|
|
78
|
-
F38 2200 2200 0 ... 24,262.320 327,41- 0.000 0.000
|
|
79
|
-
F39 0 0 0 ... 21,894.700 317,01- 0.000 0.000
|
|
80
|
-
|
|
81
71
|
# Get a pandas dataframe with the DI processed data from B3 (default)
|
|
82
72
|
>>> yd.get_di(trade_date='2024-03-08')
|
|
83
73
|
TradeDate ExpirationCode ExpirationDate BDToExpiration ... LastRate LastAskRate LastBidRate SettlementRate
|
|
@@ -9,10 +9,11 @@
|
|
|
9
9
|
Welcome to PYield, a Python library designed for the analysis of fixed income instruments in Brazil. This library is tailored for financial analysts, researchers, and enthusiasts interested in the Brazilian fixed income market. Leveraging the power of popular Python libraries like Pandas and Requests, PYield simplifies the process of obtaining and processing data from key sources such as Tesouro Nacional (TN), Banco Central (BC), ANBIMA, and B3.
|
|
10
10
|
## Features
|
|
11
11
|
|
|
12
|
-
- Data Collection
|
|
13
|
-
- Data Processing
|
|
14
|
-
- Analysis Tools
|
|
15
|
-
- Easy Integration
|
|
12
|
+
- **Data Collection**: Automated fetching of data from BC, ANBIMA and B3.
|
|
13
|
+
- **Data Processing**: Efficient processing and normalization of fixed income data.
|
|
14
|
+
- **Analysis Tools**: Built-in functions for common analysis tasks in fixed income markets.
|
|
15
|
+
- **Easy Integration**: Seamless integration with Python data analysis workflows.
|
|
16
|
+
- **Type Hints**: Full support for static type checking, enhancing development experience and code quality.
|
|
16
17
|
|
|
17
18
|
## Installation
|
|
18
19
|
|
|
@@ -25,17 +26,6 @@ pip install pyield
|
|
|
25
26
|
```python
|
|
26
27
|
import pyield as yd
|
|
27
28
|
|
|
28
|
-
# Get a pandas dataframe with the DI raw data from B3 (first date available is 05-06-1991)
|
|
29
|
-
>>> yd.get_di(trade_date='2024-03-08', raw=True)
|
|
30
|
-
VENCTO CONTR. ABERT.(1) CONTR. FECH.(2) NÚM. NEGOC. ... AJUSTE VAR. PTOS. ÚLT.OF. COMPRA ÚLT.OF. VENDA
|
|
31
|
-
J24 3608626 3608626 294 ... 99,383.080 0,17- 10.952 10.956
|
|
32
|
-
K24 607759 607759 179 ... 98,508.490 0,03+ 10.774 10.780
|
|
33
|
-
M24 339641 339641 194 ... 97,706.210 1,68- 10.602 10.604
|
|
34
|
-
... ... ... ... ... ... ... ... ...
|
|
35
|
-
F37 3517 3517 0 ... 26,863.980 336,32- 0.000 0.000
|
|
36
|
-
F38 2200 2200 0 ... 24,262.320 327,41- 0.000 0.000
|
|
37
|
-
F39 0 0 0 ... 21,894.700 317,01- 0.000 0.000
|
|
38
|
-
|
|
39
29
|
# Get a pandas dataframe with the DI processed data from B3 (default)
|
|
40
30
|
>>> yd.get_di(trade_date='2024-03-08')
|
|
41
31
|
TradeDate ExpirationCode ExpirationDate BDToExpiration ... LastRate LastAskRate LastBidRate SettlementRate
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.3.6"
|
|
@@ -28,7 +28,7 @@ def process_reference_date(
|
|
|
28
28
|
if reference_date: # Force reference_date to be a pd.Timestamp
|
|
29
29
|
processed_date = pd.Timestamp(reference_date)
|
|
30
30
|
else: # If no reference_date is given, use the previous business day
|
|
31
|
-
today = pd.Timestamp.today().
|
|
31
|
+
today = pd.Timestamp.today().normalize()
|
|
32
32
|
processed_date = cl.offset_bdays(today, -1)
|
|
33
33
|
|
|
34
34
|
return processed_date
|
|
@@ -3,14 +3,14 @@ from typing import Literal
|
|
|
3
3
|
import pandas as pd
|
|
4
4
|
import numpy as np
|
|
5
5
|
|
|
6
|
-
from .br_holidays import
|
|
6
|
+
from .br_holidays import BrHolidays
|
|
7
7
|
|
|
8
8
|
# Instância global da classe Holidays
|
|
9
|
-
br_holidays =
|
|
9
|
+
br_holidays = BrHolidays()
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def convert_to_numpy_date(
|
|
13
|
-
dates:
|
|
13
|
+
dates: pd.Timestamp | pd.Series,
|
|
14
14
|
) -> np.datetime64 | np.ndarray:
|
|
15
15
|
"""
|
|
16
16
|
Converts the input dates to a numpy datetime64[D] format.
|
|
@@ -21,13 +21,10 @@ def convert_to_numpy_date(
|
|
|
21
21
|
Returns:
|
|
22
22
|
np.datetime64 | np.ndarray: The input dates in a numpy datetime64[D] format.
|
|
23
23
|
"""
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if isinstance(dates_pd, pd.Timestamp):
|
|
28
|
-
return np.datetime64(dates_pd, "D")
|
|
24
|
+
if isinstance(dates, pd.Timestamp):
|
|
25
|
+
return np.datetime64(dates, "D")
|
|
29
26
|
else:
|
|
30
|
-
return
|
|
27
|
+
return dates.to_numpy().astype("datetime64[D]")
|
|
31
28
|
|
|
32
29
|
|
|
33
30
|
def offset_bdays(
|
|
@@ -68,17 +65,19 @@ def offset_bdays(
|
|
|
68
65
|
>>> yd.offset_bdays(date, -1)
|
|
69
66
|
Timestamp('2023-12-21') # Offset to the previous business day
|
|
70
67
|
"""
|
|
71
|
-
|
|
68
|
+
# Assure that the input is in pandas datetime64[ns] format
|
|
69
|
+
dates_pd = pd.to_datetime(dates)
|
|
72
70
|
|
|
73
|
-
selected_holidays = br_holidays.get_applicable_holidays(
|
|
71
|
+
selected_holidays = br_holidays.get_applicable_holidays(dates_pd, holiday_list)
|
|
72
|
+
selected_holidays_np = convert_to_numpy_date(selected_holidays)
|
|
74
73
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
dates_np, offsets=offset, roll="forward", holidays=
|
|
74
|
+
dates_np = convert_to_numpy_date(dates_pd)
|
|
75
|
+
offsetted_dates_np = np.busday_offset(
|
|
76
|
+
dates_np, offsets=offset, roll="forward", holidays=selected_holidays_np
|
|
78
77
|
)
|
|
79
78
|
|
|
80
79
|
# Convert the dates back to a pandas datetime64[ns] format
|
|
81
|
-
return pd.to_datetime(
|
|
80
|
+
return pd.to_datetime(offsetted_dates_np, unit="ns")
|
|
82
81
|
|
|
83
82
|
|
|
84
83
|
def count_bdays(start, end, holiday_list: Literal["old", "new", "infer"] = "infer"):
|
|
@@ -118,19 +117,24 @@ def count_bdays(start, end, holiday_list: Literal["old", "new", "infer"] = "infe
|
|
|
118
117
|
>>> yd.count_bdays(start, end)
|
|
119
118
|
array([22, 40])
|
|
120
119
|
"""
|
|
121
|
-
#
|
|
122
|
-
|
|
123
|
-
|
|
120
|
+
# Assure that the inputs are in pandas datetime64[ns] format
|
|
121
|
+
start_pd = pd.to_datetime(start)
|
|
122
|
+
end_pd = pd.to_datetime(end)
|
|
124
123
|
|
|
125
124
|
# Determine which list of holidays to use
|
|
126
|
-
selected_holidays = br_holidays.get_applicable_holidays(
|
|
125
|
+
selected_holidays = br_holidays.get_applicable_holidays(start_pd, holiday_list)
|
|
126
|
+
selected_holidays_np = convert_to_numpy_date(selected_holidays)
|
|
127
|
+
|
|
128
|
+
# Convert inputs to numpy datetime64[D] before calling numpy.busday_count
|
|
129
|
+
start_np = convert_to_numpy_date(start_pd)
|
|
130
|
+
end_np = convert_to_numpy_date(end_pd)
|
|
127
131
|
|
|
128
|
-
return np.busday_count(start_np, end_np, holidays=
|
|
132
|
+
return np.busday_count(start_np, end_np, holidays=selected_holidays_np)
|
|
129
133
|
|
|
130
134
|
|
|
131
135
|
def generate_bdays(
|
|
132
|
-
start=None,
|
|
133
|
-
end=None,
|
|
136
|
+
start: str | pd.Timestamp | None = None,
|
|
137
|
+
end: str | pd.Timestamp | None = None,
|
|
134
138
|
inclusive="both",
|
|
135
139
|
holiday_list: Literal["old", "new", "infer"] = "infer",
|
|
136
140
|
**kwargs,
|
|
@@ -175,15 +179,24 @@ def generate_bdays(
|
|
|
175
179
|
2023-12-29 2023-12-29
|
|
176
180
|
dtype: object
|
|
177
181
|
"""
|
|
178
|
-
if start
|
|
179
|
-
|
|
182
|
+
if start:
|
|
183
|
+
start_pd = pd.to_datetime(start)
|
|
184
|
+
else:
|
|
185
|
+
start_pd = pd.Timestamp.today().normalize()
|
|
180
186
|
|
|
181
|
-
if end
|
|
182
|
-
|
|
187
|
+
if end:
|
|
188
|
+
end_pd = pd.to_datetime(end)
|
|
189
|
+
else:
|
|
190
|
+
end_pd = pd.Timestamp.today().normalize()
|
|
183
191
|
|
|
184
|
-
|
|
185
|
-
|
|
192
|
+
selected_holidays = br_holidays.get_applicable_holidays(start_pd, holiday_list)
|
|
193
|
+
selected_holidays_list = selected_holidays.to_list()
|
|
186
194
|
|
|
187
195
|
return pd.bdate_range(
|
|
188
|
-
|
|
196
|
+
start_pd,
|
|
197
|
+
end_pd,
|
|
198
|
+
freq="C",
|
|
199
|
+
inclusive=inclusive,
|
|
200
|
+
holidays=selected_holidays_list,
|
|
201
|
+
**kwargs,
|
|
189
202
|
)
|
|
@@ -2,12 +2,11 @@ from pathlib import Path
|
|
|
2
2
|
from typing import Literal
|
|
3
3
|
|
|
4
4
|
import pandas as pd
|
|
5
|
-
import numpy as np
|
|
6
5
|
|
|
7
6
|
|
|
8
|
-
class
|
|
7
|
+
class BrHolidays:
|
|
9
8
|
# The date (inclusive) when the new holidays list starts to be valid
|
|
10
|
-
TRANSITION_DATE =
|
|
9
|
+
TRANSITION_DATE = pd.to_datetime("2023-12-26")
|
|
11
10
|
|
|
12
11
|
def __init__(self):
|
|
13
12
|
current_dir = Path(__file__).parent
|
|
@@ -16,34 +15,33 @@ class BRHolidays:
|
|
|
16
15
|
self.new_holidays = self._load_holidays(new_holidays_path)
|
|
17
16
|
self.old_holidays = self._load_holidays(old_holidays_path)
|
|
18
17
|
|
|
19
|
-
def _load_holidays(self, file_path: Path) ->
|
|
18
|
+
def _load_holidays(self, file_path: Path) -> pd.Series:
|
|
19
|
+
"""Loads the list of holidays from a text file and returns it as a pd.Series of pd.Timestamp."""
|
|
20
20
|
df = pd.read_csv(file_path, header=None, names=["date"], comment="#")
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
return holiday_dates.values.astype("datetime64[D]")
|
|
21
|
+
# Convert the dates to a pd.Series of pd.Timestamp
|
|
22
|
+
return pd.to_datetime(df["date"], format="%d/%m/%Y")
|
|
24
23
|
|
|
25
24
|
def get_applicable_holidays(
|
|
26
25
|
self,
|
|
27
|
-
dates:
|
|
26
|
+
dates: pd.Timestamp | pd.Series,
|
|
28
27
|
holiday_list: Literal["old", "new", "infer"] = "infer",
|
|
29
|
-
) ->
|
|
28
|
+
) -> pd.Series:
|
|
30
29
|
"""
|
|
31
30
|
Returns the correct list of holidays to use based on the most recent date in the input.
|
|
32
31
|
|
|
33
32
|
Args:
|
|
34
|
-
dates (
|
|
35
|
-
holidays.
|
|
33
|
+
dates (pd.Timestamp | pd.Series): The date(s) to use to infer the holidays.
|
|
36
34
|
holiday_list (str): The holidays list to use. Valid options are 'old', 'new' or
|
|
37
35
|
'infer'. If 'infer' is used, the list of holidays is selected based on the
|
|
38
36
|
earliest (minimum) date in the input.
|
|
39
37
|
|
|
40
38
|
Returns:
|
|
41
|
-
|
|
39
|
+
pd.Series: The list of holidays to use.
|
|
42
40
|
"""
|
|
43
|
-
if isinstance(dates,
|
|
41
|
+
if isinstance(dates, pd.Timestamp):
|
|
44
42
|
earliest_date = dates
|
|
45
43
|
else:
|
|
46
|
-
earliest_date =
|
|
44
|
+
earliest_date = dates.min()
|
|
47
45
|
|
|
48
46
|
match holiday_list:
|
|
49
47
|
case "old":
|
|
@@ -51,7 +49,7 @@ class BRHolidays:
|
|
|
51
49
|
case "new":
|
|
52
50
|
return self.new_holidays
|
|
53
51
|
case "infer":
|
|
54
|
-
if earliest_date <
|
|
52
|
+
if earliest_date < BrHolidays.TRANSITION_DATE:
|
|
55
53
|
return self.old_holidays
|
|
56
54
|
else:
|
|
57
55
|
return self.new_holidays
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
from typing import Literal
|
|
1
|
+
from typing import Literal, Optional
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
import pandas as pd
|
|
4
|
+
import pandas.api.types
|
|
4
5
|
|
|
5
6
|
from . import di_web as diw
|
|
6
7
|
from . import di_xml as dix
|
|
7
8
|
from . import br_calendar as brc
|
|
8
9
|
|
|
9
10
|
|
|
10
|
-
def get_expiration_date(expiration_code: str) -> pd.Timestamp:
|
|
11
|
+
def get_expiration_date(expiration_code: str) -> Optional[pd.Timestamp]:
|
|
11
12
|
"""
|
|
12
13
|
Internal function to convert the expiration code into its expiration date.
|
|
13
14
|
|
|
@@ -66,7 +67,7 @@ def get_expiration_date(expiration_code: str) -> pd.Timestamp:
|
|
|
66
67
|
return brc.offset_bdays(expiration, offset=0)
|
|
67
68
|
|
|
68
69
|
except (KeyError, ValueError):
|
|
69
|
-
return pd.NaT
|
|
70
|
+
return pd.NaT # type: ignore
|
|
70
71
|
|
|
71
72
|
|
|
72
73
|
def get_di(
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import io
|
|
2
2
|
import warnings
|
|
3
|
+
from typing import Optional
|
|
3
4
|
|
|
4
5
|
import pandas as pd
|
|
5
6
|
import requests
|
|
@@ -10,7 +11,7 @@ from . import di_futures as dif
|
|
|
10
11
|
|
|
11
12
|
def get_old_expiration_date(
|
|
12
13
|
ExpirationCode: str, trade_date: pd.Timestamp
|
|
13
|
-
) -> pd.Timestamp:
|
|
14
|
+
) -> Optional[pd.Timestamp]:
|
|
14
15
|
"""
|
|
15
16
|
Internal function to convert an old DI contract code into its ExpirationDate date. Valid for
|
|
16
17
|
contract codes up to 21-05-2006.
|
|
@@ -67,7 +68,7 @@ def get_old_expiration_date(
|
|
|
67
68
|
return brc.offset_bdays(ExpirationDate, offset=0, holiday_list="old")
|
|
68
69
|
|
|
69
70
|
except (KeyError, ValueError):
|
|
70
|
-
return pd.NaT
|
|
71
|
+
return pd.NaT # type: ignore
|
|
71
72
|
|
|
72
73
|
|
|
73
74
|
def get_raw_di(trade_date: pd.Timestamp) -> pd.DataFrame:
|
|
@@ -57,7 +57,7 @@ def extract_xml_from_zip(zip_file: io.BytesIO) -> io.BytesIO:
|
|
|
57
57
|
return io.BytesIO(inner_file_content)
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
def extract_di_data_from_xml(xml_file: io.BytesIO) -> list:
|
|
60
|
+
def extract_di_data_from_xml(xml_file: io.BytesIO) -> list[dict]:
|
|
61
61
|
parser = etree.XMLParser(
|
|
62
62
|
ns_clean=True, remove_blank_text=True, remove_comments=True, recover=True
|
|
63
63
|
)
|
|
@@ -69,18 +69,38 @@ def extract_di_data_from_xml(xml_file: io.BytesIO) -> list:
|
|
|
69
69
|
'//ns:TckrSymb[starts-with(text(), "DI1")]', namespaces=namespaces
|
|
70
70
|
)
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
if (
|
|
73
|
+
tckr_symbols is None
|
|
74
|
+
or not isinstance(tckr_symbols, list)
|
|
75
|
+
or len(tckr_symbols) == 0
|
|
76
|
+
):
|
|
77
|
+
return []
|
|
78
|
+
|
|
79
|
+
# Lista para armazenar os dados com type hinting
|
|
80
|
+
# di_data: list[dict] = []
|
|
73
81
|
di_data = []
|
|
74
82
|
|
|
75
83
|
# Processar cada TckrSymb encontrado
|
|
76
84
|
for tckr_symb in tckr_symbols:
|
|
77
|
-
|
|
78
|
-
|
|
85
|
+
if isinstance(tckr_symb, etree._Element):
|
|
86
|
+
price_report = tckr_symb.getparent()
|
|
87
|
+
if price_report is not None:
|
|
88
|
+
price_report = price_report.getparent()
|
|
89
|
+
else:
|
|
90
|
+
# Handle the case where tckr_symb doesn't have a parent
|
|
91
|
+
continue
|
|
92
|
+
else:
|
|
93
|
+
# Handle the case where tckr_symb is not an _Element
|
|
94
|
+
continue
|
|
79
95
|
|
|
80
96
|
# Extrair a data de negociação
|
|
97
|
+
if price_report is None:
|
|
98
|
+
continue
|
|
81
99
|
trade_date = price_report.find(".//ns:TradDt/ns:Dt", namespaces)
|
|
82
100
|
|
|
83
101
|
# Preparar o dicionário de dados do ticker com a data de negociação
|
|
102
|
+
if trade_date is None:
|
|
103
|
+
continue
|
|
84
104
|
ticker_data = {"TradDt": trade_date.text, "TckrSymb": tckr_symb.text}
|
|
85
105
|
|
|
86
106
|
# Acessar o elemento FinInstrmAttrbts que contém o TckrSymb
|
|
File without changes
|
pyield-0.3.5/pyield/__about__.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.3.5"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|