<p align="center">
<img src="https://s3.shakhbanov.org/logo.jpeg" alt="Лого" width="200" />
</p>
# shakhbanov_ml
**ML инструменты для временного ряда**
Добро пожаловать в `shakhbanov_ml` - набор инструментов для обработки и анализа временных рядов. Этот пакет включает в себя методы для восстановления пропусков, очистки данных и прогнозирования, специально разработанные для упрощения работы с временными рядами.
---
## 🚀 Установка
```bash
pip install shakhbanov
```
## 🔧 Использование
### 📥 Импортируем библиотеки и загружаем данные
```python
import pandas as pd
from shakhbanov.metrics import wape
from shakhbanov.forecast import BurgerKing
from shakhbanov.cleaner import DataCleaner
from shakhbanov.kalman_gap_filler import KalmanGapFiller
data = pd.read_csv('timeseries.csv')
```
### 🔍 Восстанавливаем пропущенные периоды методом фильтра Калмана
```python
# Инициализация KalmanGapFiller с параметрами
data = KalmanGapFiller(date_column='ds', # Колонка с датами
group_column='id', # Колонка с идентификаторами групп
target_columns=['value', 'value2'], # Колонки с целевыми значениями
tqdm=True, # Показ прогресса выполнения
parallel=True # Использование параллельной обработки
).process(data) # Обработка данных
```
### 🧹 Очищаем данные от выбросов с учетом тренда
```python
data = DataCleaner(method='mean', # Метод расчета центральной тенденции ('mean', 'median' или 'mode')
weeks=4, # Количество недель для расчета скользящего среднего
window=365, # Размер окна для скользящего среднего и стандартного отклонения
std=2, # Количество стандартных отклонений для определения выбросов
tqdm=True, # Флаг для использования индикатора прогресса tqdm
plot=False, # Флаг для включения или отключения визуализации
num_plot=5, # Количество объектов для визуализации
parallel=True).clean_data(data=data, column=['value', 'value2'], series_id='id')
```
### 📈 Прогнозирование
```python
bk = BurgerKing(
data=data, # Набор данных
freq='D', # Частота временного ряда
periods=180, # Количество периодов для прогнозирования
target=['check_qnty', 'avg'], # Целевые переменные для прогнозирования
levels=['W', 'M'], # Уровни для ресемплинга ('W' - еженедельно, 'M' - ежемесячно)
agg=['mean', 'median'], # Функции агрегации
n_splits=5, # Количество разбиений для TimeSeriesSplit
n_estimators=350, # Количество итераций для бустинга в LightGBM
early_stopping_rounds=150, # Количество раундов для ранней остановки в LightGBM
lgb_params={
'objective': 'regression',
'metric': 'mse',
'learning_rate': 0.01,
'num_leaves': 31,
'verbose': -1
}, # Параметры для LightGBM
prophet_params={
'yearly_seasonality': True,
'weekly_seasonality': True,
'daily_seasonality': False
}, # Параметры для Prophet
holidays_getter=None, # Кастомный получатель праздников
tqdm=True # Включить индикаторы прогресса tqdm
)
results_df = bk.run()
```
### 📊 Замеряем качество
```python
wape(data, test)
```
## 📞 Контакты
- 🌐 Сайт: [shakhbanov.org](https://shakhbanov.org)
- 📧 Email: [zurab@shakhbanov.ru](mailto:zurab@shakhbanov.ru)
---
### README.md in English
# shakhbanov_ml
**ML tools for time series**
Welcome to `shakhbanov_ml` - a toolkit for processing and analyzing time series. This package includes methods for gap filling, data cleaning, and forecasting, specifically designed to simplify working with time series data.
---
## 🚀 Installation
```bash
pip install shakhbanov
```
## 🔧 Usage
### 📥 Import Libraries and Load Data
```python
import pandas as pd
from shakhbanov.metrics import wape
from shakhbanov.forecast import BurgerKing
from shakhbanov.cleaner import DataCleaner
from shakhbanov.kalman_gap_filler import KalmanGapFiller
data = pd.read_csv('timeseries.csv')
```
### 🔍 Fill Missing Periods using Kalman Filter
```python
# Initialize KalmanGapFiller with parameters
data = KalmanGapFiller(date_column='ds',
group_column='id',
target_columns=['value', 'value2'],
tqdm=True,
parallel=True).process(data)
```
### 🧹 Clean Data from Outliers Considering Trend
```python
data = DataCleaner(method='mean', # Method for calculating central tendency ('mean', 'median' or 'mode')
weeks=4, # Number of weeks for calculating the moving average
window=365, # Window size for moving average and standard deviation
std=2, # Number of standard deviations for identifying outliers
tqdm=True, # Flag to use tqdm progress indicator
plot=False, # Flag to enable or disable visualization
num_plot=5, # Number of items to visualize
parallel=True # Flag to use parallel processing
).clean_data(data=data, column=['value', 'value2'], series_id='id')
```
### 📈 Forecasting
```python
bk = BurgerKing(
data=data, # Dataset
freq='D', # Frequency of the time series data
periods=180, # Number of periods to forecast
target=['check_qnty', 'avg'], # Target variables to forecast
levels=['W', 'M'], # Levels for resampling ('W' for weekly, 'M' for monthly)
agg=['mean', 'median'], # Aggregation functions
n_splits=5, # Number of splits for TimeSeriesSplit
n_estimators=350, # Number of boosting iterations for LightGBM
early_stopping_rounds=150, # Rounds of early stopping for LightGBM
lgb_params={
'objective': 'regression',
'metric': 'mse',
'learning_rate': 0.01,
'num_leaves': 31,
'verbose': -1
}, # Parameters for LightGBM
prophet_params={
'yearly_seasonality': True,
'weekly_seasonality': True,
'daily_seasonality': False
}, # Parameters for Prophet
holidays_getter=None, # Custom holidays getter
tqdm=True # Enable tqdm progress bars
)
results_df = bk.run()
```
### 📊 Measure Quality
```python
wape(data, test)
```
## 📞 Contacts
- 🌐 Website: [shakhbanov.org](https://shakhbanov.org)
- 📧 Email: [zurab@shakhbanov.ru](mailto:zurab@shakhbanov.ru)
Raw data
{
"_id": null,
"home_page": "https://shakhbanov.org",
"name": "shakhbanov",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.6",
"maintainer_email": null,
"keywords": null,
"author": "Zurab Shakhbanov",
"author_email": "zurab@shakhbanov.ru",
"download_url": "https://files.pythonhosted.org/packages/99/97/e2a45f82341d916e447004fb324cfb3b7e49aaa6215dcabee3fa131c29c9/shakhbanov-1.3.1.tar.gz",
"platform": null,
"description": "<p align=\"center\">\n <img src=\"https://s3.shakhbanov.org/logo.jpeg\" alt=\"\u041b\u043e\u0433\u043e\" width=\"200\" />\n</p>\n\n# shakhbanov_ml\n\n**ML \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0433\u043e \u0440\u044f\u0434\u0430**\n\n\u0414\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c \u0432 `shakhbanov_ml` - \u043d\u0430\u0431\u043e\u0440 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0440\u044f\u0434\u043e\u0432. \u042d\u0442\u043e\u0442 \u043f\u0430\u043a\u0435\u0442 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043e\u0432, \u043e\u0447\u0438\u0441\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u0440\u044f\u0434\u0430\u043c\u0438.\n\n---\n\n## \ud83d\ude80 \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430\n\n```bash\npip install shakhbanov\n```\n\n## \ud83d\udd27 \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\n\n### \ud83d\udce5 \u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435\n\n```python\nimport pandas as pd\n\nfrom shakhbanov.metrics import wape\nfrom shakhbanov.forecast import BurgerKing\nfrom shakhbanov.cleaner import DataCleaner\nfrom shakhbanov.kalman_gap_filler import KalmanGapFiller\n\ndata = pd.read_csv('timeseries.csv')\n```\n\n### \ud83d\udd0d \u0412\u043e\u0441\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u0435 \u043f\u0435\u0440\u0438\u043e\u0434\u044b \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u0444\u0438\u043b\u044c\u0442\u0440\u0430 \u041a\u0430\u043b\u043c\u0430\u043d\u0430\n\n```python\n# \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f KalmanGapFiller \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438\ndata = KalmanGapFiller(date_column='ds', # \u041a\u043e\u043b\u043e\u043d\u043a\u0430 \u0441 \u0434\u0430\u0442\u0430\u043c\u0438\n group_column='id', # \u041a\u043e\u043b\u043e\u043d\u043a\u0430 \u0441 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430\u043c\u0438 \u0433\u0440\u0443\u043f\u043f\n target_columns=['value', 'value2'], # \u041a\u043e\u043b\u043e\u043d\u043a\u0438 \u0441 \u0446\u0435\u043b\u0435\u0432\u044b\u043c\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \n tqdm=True, # \u041f\u043e\u043a\u0430\u0437 \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f\n parallel=True # \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438\n ).process(data) # \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445\n```\n\n### \ud83e\uddf9 \u041e\u0447\u0438\u0449\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 \u0432\u044b\u0431\u0440\u043e\u0441\u043e\u0432 \u0441 \u0443\u0447\u0435\u0442\u043e\u043c \u0442\u0440\u0435\u043d\u0434\u0430\n\n```python\ndata = DataCleaner(method='mean', # \u041c\u0435\u0442\u043e\u0434 \u0440\u0430\u0441\u0447\u0435\u0442\u0430 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u043e\u0439 \u0442\u0435\u043d\u0434\u0435\u043d\u0446\u0438\u0438 ('mean', 'median' \u0438\u043b\u0438 'mode')\n weeks=4, # \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043d\u0435\u0434\u0435\u043b\u044c \u0434\u043b\u044f \u0440\u0430\u0441\u0447\u0435\u0442\u0430 \u0441\u043a\u043e\u043b\u044c\u0437\u044f\u0449\u0435\u0433\u043e \u0441\u0440\u0435\u0434\u043d\u0435\u0433\u043e\n window=365, # \u0420\u0430\u0437\u043c\u0435\u0440 \u043e\u043a\u043d\u0430 \u0434\u043b\u044f \u0441\u043a\u043e\u043b\u044c\u0437\u044f\u0449\u0435\u0433\u043e \u0441\u0440\u0435\u0434\u043d\u0435\u0433\u043e \u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u0438\u044f\n std=2, # \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0432\u044b\u0431\u0440\u043e\u0441\u043e\u0432\n tqdm=True, # \u0424\u043b\u0430\u0433 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440\u0430 \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u0430 tqdm\n plot=False, # \u0424\u043b\u0430\u0433 \u0434\u043b\u044f \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438\n num_plot=5, # \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0434\u043b\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438\n parallel=True).clean_data(data=data, column=['value', 'value2'], series_id='id')\n```\n\n### \ud83d\udcc8 \u041f\u0440\u043e\u0433\u043d\u043e\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\n\n```python\nbk = BurgerKing(\n data=data, # \u041d\u0430\u0431\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445\n freq='D', # \u0427\u0430\u0441\u0442\u043e\u0442\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0433\u043e \u0440\u044f\u0434\u0430\n periods=180, # \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0435\u0440\u0438\u043e\u0434\u043e\u0432 \u0434\u043b\u044f \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f\n target=['check_qnty', 'avg'], # \u0426\u0435\u043b\u0435\u0432\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f\n levels=['W', 'M'], # \u0423\u0440\u043e\u0432\u043d\u0438 \u0434\u043b\u044f \u0440\u0435\u0441\u0435\u043c\u043f\u043b\u0438\u043d\u0433\u0430 ('W' - \u0435\u0436\u0435\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u043e, 'M' - \u0435\u0436\u0435\u043c\u0435\u0441\u044f\u0447\u043d\u043e)\n agg=['mean', 'median'], # \u0424\u0443\u043d\u043a\u0446\u0438\u0438 \u0430\u0433\u0440\u0435\u0433\u0430\u0446\u0438\u0438\n n_splits=5, # \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0430\u0437\u0431\u0438\u0435\u043d\u0438\u0439 \u0434\u043b\u044f TimeSeriesSplit\n n_estimators=350, # \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0439 \u0434\u043b\u044f \u0431\u0443\u0441\u0442\u0438\u043d\u0433\u0430 \u0432 LightGBM\n early_stopping_rounds=150, # \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0430\u0443\u043d\u0434\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u043d\u043d\u0435\u0439 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0432 LightGBM\n lgb_params={\n 'objective': 'regression',\n 'metric': 'mse',\n 'learning_rate': 0.01,\n 'num_leaves': 31,\n 'verbose': -1\n }, # \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f LightGBM\n prophet_params={\n 'yearly_seasonality': True,\n 'weekly_seasonality': True,\n 'daily_seasonality': False\n }, # \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f Prophet\n holidays_getter=None, # \u041a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u044c \u043f\u0440\u0430\u0437\u0434\u043d\u0438\u043a\u043e\u0432\n tqdm=True # \u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u0430 tqdm\n)\n\nresults_df = bk.run()\n```\n\n### \ud83d\udcca \u0417\u0430\u043c\u0435\u0440\u044f\u0435\u043c \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e\n\n```python\nwape(data, test)\n```\n\n## \ud83d\udcde \u041a\u043e\u043d\u0442\u0430\u043a\u0442\u044b\n\n- \ud83c\udf10 \u0421\u0430\u0439\u0442: [shakhbanov.org](https://shakhbanov.org)\n- \ud83d\udce7 Email: [zurab@shakhbanov.ru](mailto:zurab@shakhbanov.ru)\n\n---\n\n### README.md in English\n\n\n# shakhbanov_ml\n\n**ML tools for time series**\n\nWelcome to `shakhbanov_ml` - a toolkit for processing and analyzing time series. This package includes methods for gap filling, data cleaning, and forecasting, specifically designed to simplify working with time series data.\n\n---\n\n## \ud83d\ude80 Installation\n\n```bash\npip install shakhbanov\n```\n\n## \ud83d\udd27 Usage\n\n### \ud83d\udce5 Import Libraries and Load Data\n\n```python\nimport pandas as pd\n\nfrom shakhbanov.metrics import wape\nfrom shakhbanov.forecast import BurgerKing\nfrom shakhbanov.cleaner import DataCleaner\nfrom shakhbanov.kalman_gap_filler import KalmanGapFiller\n\ndata = pd.read_csv('timeseries.csv')\n```\n\n### \ud83d\udd0d Fill Missing Periods using Kalman Filter\n\n```python\n# Initialize KalmanGapFiller with parameters\ndata = KalmanGapFiller(date_column='ds',\n group_column='id', \n target_columns=['value', 'value2'],\n tqdm=True, \n parallel=True).process(data)\n```\n\n### \ud83e\uddf9 Clean Data from Outliers Considering Trend\n\n```python\ndata = DataCleaner(method='mean', # Method for calculating central tendency ('mean', 'median' or 'mode')\n weeks=4, # Number of weeks for calculating the moving average\n window=365, # Window size for moving average and standard deviation\n std=2, # Number of standard deviations for identifying outliers\n tqdm=True, # Flag to use tqdm progress indicator\n plot=False, # Flag to enable or disable visualization\n num_plot=5, # Number of items to visualize\n parallel=True # Flag to use parallel processing\n ).clean_data(data=data, column=['value', 'value2'], series_id='id')\n\n```\n\n### \ud83d\udcc8 Forecasting\n\n```python\nbk = BurgerKing(\n data=data, # Dataset\n freq='D', # Frequency of the time series data\n periods=180, # Number of periods to forecast\n target=['check_qnty', 'avg'], # Target variables to forecast\n levels=['W', 'M'], # Levels for resampling ('W' for weekly, 'M' for monthly)\n agg=['mean', 'median'], # Aggregation functions\n n_splits=5, # Number of splits for TimeSeriesSplit\n n_estimators=350, # Number of boosting iterations for LightGBM\n early_stopping_rounds=150, # Rounds of early stopping for LightGBM\n lgb_params={\n 'objective': 'regression',\n 'metric': 'mse',\n 'learning_rate': 0.01,\n 'num_leaves': 31,\n 'verbose': -1\n }, # Parameters for LightGBM\n prophet_params={\n 'yearly_seasonality': True,\n 'weekly_seasonality': True,\n 'daily_seasonality': False\n }, # Parameters for Prophet\n holidays_getter=None, # Custom holidays getter\n tqdm=True # Enable tqdm progress bars\n)\n\nresults_df = bk.run()\n```\n\n### \ud83d\udcca Measure Quality\n\n```python\nwape(data, test)\n```\n\n## \ud83d\udcde Contacts\n\n- \ud83c\udf10 Website: [shakhbanov.org](https://shakhbanov.org)\n- \ud83d\udce7 Email: [zurab@shakhbanov.ru](mailto:zurab@shakhbanov.ru)\n",
"bugtrack_url": null,
"license": null,
"summary": "ML tools for time series",
"version": "1.3.1",
"project_urls": {
"Download": "https://github.com/shakhbanov/shakhbanov/archive/refs/heads/main.zip",
"GitHub": "https://github.com/shakhbanov/shakhbanov",
"Homepage": "https://shakhbanov.org"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "9997e2a45f82341d916e447004fb324cfb3b7e49aaa6215dcabee3fa131c29c9",
"md5": "6314241fa65374eb1a14c930220e80b2",
"sha256": "310f1cc7ae0b7249ce91743d9ed67280dec69e826d04eb1f643e91df8f50f6d6"
},
"downloads": -1,
"filename": "shakhbanov-1.3.1.tar.gz",
"has_sig": false,
"md5_digest": "6314241fa65374eb1a14c930220e80b2",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.6",
"size": 24235,
"upload_time": "2024-08-26T18:08:50",
"upload_time_iso_8601": "2024-08-26T18:08:50.432802Z",
"url": "https://files.pythonhosted.org/packages/99/97/e2a45f82341d916e447004fb324cfb3b7e49aaa6215dcabee3fa131c29c9/shakhbanov-1.3.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-08-26 18:08:50",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "shakhbanov",
"github_project": "shakhbanov",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "shakhbanov"
}