vrbase 1.0.0__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.
vrbase-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,624 @@
1
+ Metadata-Version: 2.4
2
+ Name: vrbase
3
+ Version: 1.0.0
4
+ Summary: Русская документо-ориентированная база данных — проще чем SQL
5
+ Author: Pantapan1
6
+ Keywords: база данных,database,json,русский,documents,nosql
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Topic :: Database
13
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
14
+ Requires-Python: >=3.8
15
+ Description-Content-Type: text/markdown
16
+ Requires-Dist: cryptography>=41.0.0
17
+ Dynamic: author
18
+ Dynamic: classifier
19
+ Dynamic: description
20
+ Dynamic: description-content-type
21
+ Dynamic: keywords
22
+ Dynamic: requires-dist
23
+ Dynamic: requires-python
24
+ Dynamic: summary
25
+
26
+ VRBase — Русская база данных
27
+
28
+ Документо-ориентированная база данных на русском языке. Проще чем SQL, быстрее чем JSON вручную.
29
+
30
+ https://img.shields.io/pypi/v/vrbase.svg
31
+ https://img.shields.io/badge/python-3.8+-blue.svg
32
+ https://img.shields.io/badge/license-MIT-green.svg
33
+
34
+ ---
35
+
36
+ 📖 Оглавление
37
+
38
+ · Почему VRBase
39
+ · Установка
40
+ · Быстрый старт
41
+ · Основные понятия
42
+ · Полное руководство
43
+ · База данных
44
+ · Коробка
45
+ · Документы
46
+ · Поиск
47
+ · Обновление
48
+ · Удаление
49
+ · Индексы
50
+ · Запросы
51
+ · Агрегация
52
+ · Шифрование
53
+ · Миграции
54
+ · Сравнение с SQL
55
+ · Примеры
56
+ · API Reference
57
+
58
+ ---
59
+
60
+ Почему VRBase
61
+
62
+ Проблема SQL
63
+
64
+ ```sql
65
+ CREATE TABLE players (
66
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
67
+ name TEXT NOT NULL,
68
+ level INTEGER DEFAULT 1,
69
+ inventory TEXT,
70
+ stats TEXT
71
+ );
72
+
73
+ INSERT INTO players (name, level, inventory, stats)
74
+ VALUES ('Миро', 10, '["меч","щит"]', '{"hp":100,"mp":50}');
75
+
76
+ SELECT * FROM players WHERE level > 5 ORDER BY level DESC LIMIT 10;
77
+ ```
78
+
79
+ Решение VRBase
80
+
81
+ ```python
82
+ from vrbase import База
83
+
84
+ мир = База("survival")
85
+ игроки = мир.коробка("игроки")
86
+
87
+ игроки.положить({
88
+ "имя": "Миро",
89
+ "уровень": 10,
90
+ "инвентарь": ["меч", "щит"],
91
+ "статы": {"здоровье": 100, "мана": 50}
92
+ })
93
+
94
+ топ = игроки.найти(где={"уровень": "> 5"}, сортировка="уровень убыв", лимит=10)
95
+ ```
96
+
97
+ Разница: Не нужно думать о схемах, типах данных, JOIN'ах, миграциях. Просто кладёшь словарь и ищешь по-русски.
98
+
99
+ ---
100
+
101
+ Установка
102
+
103
+ ```bash
104
+ pip install vrbase
105
+ ```
106
+
107
+ Или из исходников:
108
+
109
+ ```bash
110
+ git clone https://github.com/Pantapan1/VRBase.git
111
+ cd VRBase
112
+ pip install -e .
113
+ ```
114
+
115
+ Зависимости: cryptography>=41.0.0 (только для шифрования)
116
+
117
+ ---
118
+
119
+ Быстрый старт
120
+
121
+ ```python
122
+ from vrbase import База
123
+
124
+ # Создаём или открываем базу
125
+ мир = База("мой_мир")
126
+
127
+ # Создаём коробку (аналог таблицы)
128
+ игроки = мир.коробка("игроки")
129
+
130
+ # Добавляем игрока
131
+ игроки.положить({
132
+ "имя": "Миро",
133
+ "уровень": 1,
134
+ "класс": "воин",
135
+ "инвентарь": ["меч", "зелье"],
136
+ "статы": {"здоровье": 100, "мана": 50}
137
+ })
138
+
139
+ # Ищем
140
+ новички = игроки.найти(где={"уровень": "< 5"})
141
+
142
+ # Обновляем
143
+ игроки.обновить(где={"имя": "Миро"}, данные={"уровень": 10})
144
+
145
+ # Сохраняем
146
+ мир.сохранить()
147
+
148
+ print(f"Игроков: {игроки.считать()}")
149
+ ```
150
+
151
+ ---
152
+
153
+ Основные понятия
154
+
155
+ VRBase SQL
156
+ База Database
157
+ Коробка Table
158
+ Документ Row
159
+ Ключ Column
160
+ положить() INSERT
161
+ найти() SELECT
162
+ обновить() UPDATE
163
+ удалить() DELETE
164
+ Индекс Index
165
+
166
+ ---
167
+
168
+ Полное руководство
169
+
170
+ База данных
171
+
172
+ ```python
173
+ from vrbase import База
174
+
175
+ # Обычная база (файл .json)
176
+ мир = База("survival")
177
+
178
+ # База с шифрованием (.enc)
179
+ мир = База("survival", ключ="мой_секретный_пароль")
180
+
181
+ # База в конкретной папке
182
+ мир = База("survival", путь="/path/to/survival.json")
183
+
184
+ # Контекстный менеджер (авто-сохранение)
185
+ with База("survival") as мир:
186
+ игроки = мир.коробка("игроки")
187
+ игроки.положить({"имя": "Миро"})
188
+ # Автоматически сохранится
189
+
190
+ # Просмотр информации
191
+ print(мир.инфо())
192
+ # {'имя': 'survival', 'коробок': 1, 'документов': 1, 'размер_байт': 256}
193
+
194
+ # Бэкап
195
+ мир.бэкап() # → survival_2026-05-09_12-30-00.json
196
+
197
+ # Сохранить копию
198
+ мир.сохранить_как("survival_backup.json")
199
+
200
+ # Очистить
201
+ мир.очистить() # Удаляет всё
202
+ ```
203
+
204
+ Коробка
205
+
206
+ ```python
207
+ игроки = мир.коробка("игроки")
208
+
209
+ # Сколько документов
210
+ print(len(игроки)) # 5
211
+ print(игроки.размер()) # 5
212
+ print(игроки.память()) # 2500 (байт в памяти)
213
+
214
+ # Все ключи документов
215
+ print(игроки.ключи()) # ['_id', '_создан', 'имя', 'уровень', ...]
216
+
217
+ # Уникальные значения поля
218
+ print(игроки.уникальные("класс")) # ['воин', 'маг', 'вор']
219
+
220
+ # Есть ли документ с таким условием
221
+ if игроки.есть(где={"имя": "Миро"}):
222
+ print("Миро существует")
223
+
224
+ # Перебор
225
+ for игрок in игроки:
226
+ print(игрок['имя'])
227
+
228
+ # Доступ по ID
229
+ игрок = игроки[0] # Первый документ
230
+ ```
231
+
232
+ Документы
233
+
234
+ ```python
235
+ # Добавить один
236
+ ид = игроки.положить({
237
+ "имя": "Миро",
238
+ "уровень": 1,
239
+ "инвентарь": ["меч", "хлеб"],
240
+ "статы": {"здоровье": 100, "выносливость": 80}
241
+ })
242
+ print(ид) # 0
243
+
244
+ # Добавить много
245
+ игроки.положить_много([
246
+ {"имя": "Кай", "уровень": 5},
247
+ {"имя": "Анна", "уровень": 7},
248
+ {"имя": "Олег", "уровень": 3}
249
+ ])
250
+
251
+ # Автоматически добавляются поля:
252
+ # _id — уникальный номер
253
+ # _создан — время создания в ISO формате
254
+ # _обновлён — время последнего обновления
255
+
256
+ игрок = игроки.найти_один(где={"имя": "Миро"})
257
+ print(игрок['_id']) # 0
258
+ print(игрок['_создан']) # 2026-05-09T12:30:00
259
+ ```
260
+
261
+ Поиск
262
+
263
+ ```python
264
+ # Точное совпадение
265
+ игроки.найти(где={"уровень": 10})
266
+
267
+ # Больше / меньше
268
+ игроки.найти(где={"уровень": "> 5"})
269
+ игроки.найти(где={"уровень": ">= 10"})
270
+ игроки.найти(где={"уровень": "< 3"})
271
+ игроки.найти(где={"уровень": "!= 5"})
272
+
273
+ # Диапазон
274
+ игроки.найти(где={"уровень": "между 5 и 20"})
275
+
276
+ # Поиск подстроки
277
+ игроки.найти(где={"имя": "содержит мир"}) # найдёт "Миро", "Владимир"
278
+
279
+ # Начинается с / заканчивается на
280
+ игроки.найти(где={"имя": "начинается с М"})
281
+ игроки.найти(где={"имя": "заканчивается на о"})
282
+
283
+ # Пусто / не пусто
284
+ игроки.найти(где={"инвентарь": "пусто"})
285
+ игроки.найти(где={"инвентарь": "не пусто"})
286
+
287
+ # Поиск по вложенному полю
288
+ игроки.найти(где={"статы.здоровье": "> 50"})
289
+
290
+ # Содержит в списке
291
+ игроки.найти(содержит={"инвентарь": "меч"})
292
+
293
+ # Сортировка
294
+ игроки.найти(сортировка="уровень убыв")
295
+ игроки.найти(сортировка="имя возр")
296
+
297
+ # Комбинированный поиск
298
+ ветераны = игроки.найти(
299
+ где={"уровень": "> 10", "класс": "воин"},
300
+ сортировка="уровень убыв",
301
+ лимит=5
302
+ )
303
+
304
+ # Найти один
305
+ миро = игроки.найти_один(имя="Миро")
306
+
307
+ # Найти по ID
308
+ игрок = игроки.найти_по_id(0)
309
+ ```
310
+
311
+ Обновление
312
+
313
+ ```python
314
+ # Обновить по условию
315
+ игроки.обновить(
316
+ где={"имя": "Миро"},
317
+ данные={"уровень": 15, "золото": 500}
318
+ )
319
+
320
+ # Обновить по ID
321
+ игроки.обновить_по_id(0, {"уровень": 20})
322
+
323
+ # Обновить все документы
324
+ игроки.обновить_все({"бонус": 0})
325
+
326
+ # Обновить вложенное поле
327
+ игроки.обновить(
328
+ где={"имя": "Миро"},
329
+ данные={"статы.здоровье": 150}
330
+ )
331
+
332
+ # Авто-обновление _обновлён
333
+ игрок = игроки.найти_один(имя="Миро")
334
+ print(игрок['_обновлён']) # 2026-05-09T13:00:00
335
+ ```
336
+
337
+ Удаление
338
+
339
+ ```python
340
+ # Удалить по условию
341
+ игроки.удалить(где={"уровень": "< 2"})
342
+
343
+ # Удалить по ID
344
+ игроки.удалить_по_id(0)
345
+
346
+ # Удалить всё
347
+ игроки.удалить_все()
348
+ ```
349
+
350
+ Индексы
351
+
352
+ Индексы ускоряют поиск в 10-1000 раз на больших объёмах данных.
353
+
354
+ ```python
355
+ # Создать индекс
356
+ игроки.создать_индекс("имя")
357
+ игроки.создать_индекс("уровень")
358
+
359
+ # Составной индекс
360
+ игроки.создать_индекс(["класс", "уровень"])
361
+
362
+ # Поиск с индексом (автоматически используется)
363
+ игроки.найти(где={"имя": "Миро"}) # O(log n) вместо O(n)
364
+
365
+ # Удалить индекс
366
+ игроки.удалить_индекс("имя")
367
+
368
+ # Перестроить все индексы
369
+ игроки.перестроить_индексы()
370
+
371
+ # Статистика индекса
372
+ индекс = игроки.создать_индекс("уровень")
373
+ print(индекс.статистика())
374
+ # {'тип': 'числовой', 'уникальных': 15, 'минимум': 1, 'максимум': 50, 'среднее': 12.3}
375
+ ```
376
+
377
+ Запросы
378
+
379
+ Сложные запросы через конструктор:
380
+
381
+ ```python
382
+ from vrbase import Запрос
383
+
384
+ # Сложный запрос
385
+ результат = (Запрос(игроки)
386
+ .где(уровень="> 5")
387
+ .и_(класс="воин")
388
+ .или(класс="маг")
389
+ .не_(статус="мёртв")
390
+ .содержит(инвентарь="меч")
391
+ .сортировать_по("уровень", убывание=True)
392
+ .лимит(10)
393
+ .пропустить(5)
394
+ .выполнить())
395
+
396
+ # Выбрать только определённые поля
397
+ результат = (Запрос(игроки)
398
+ .выбрать("имя", "уровень")
399
+ .где(уровень="> 10")
400
+ .выполнить())
401
+
402
+ # Уникальные значения
403
+ результат = (Запрос(игроки)
404
+ .выбрать("класс")
405
+ .уникальные()
406
+ .выполнить())
407
+
408
+ # Проверить существование
409
+ есть = (Запрос(игроки)
410
+ .где(имя="Миро")
411
+ .существует())
412
+
413
+ # Парсинг строки запроса
414
+ from vrbase import ПарсерЗапроса
415
+
416
+ запрос = ПарсерЗапроса.разобрать(
417
+ "выбрать имя, уровень где уровень > 5 сортировка по уровень лимит 5",
418
+ игроки
419
+ )
420
+ результат = запрос.выполнить()
421
+ ```
422
+
423
+ Агрегация
424
+
425
+ ```python
426
+ # Подсчёт
427
+ стата = (игроки.агрегация()
428
+ .считать()
429
+ .выполнить())
430
+ # [{'количество': 150}]
431
+
432
+ # Группировка
433
+ стата = (игроки.агрегация()
434
+ .группировать_по("класс")
435
+ .считать()
436
+ .среднее("уровень")
437
+ .выполнить())
438
+ # [
439
+ # {'класс': 'воин', 'количество': 50, 'среднее_уровень': 12.3},
440
+ # {'класс': 'маг', 'количество': 30, 'среднее_уровень': 15.1}
441
+ # ]
442
+
443
+ # Сумма, минимум, максимум
444
+ стата = (игроки.агрегация()
445
+ .группировать_по("класс")
446
+ .считать("игроков")
447
+ .сумма("золото", "всего_золота")
448
+ .максимум("уровень", "макс_уровень")
449
+ .выполнить())
450
+ ```
451
+
452
+ Шифрование
453
+
454
+ ```python
455
+ from vrbase import Шифр
456
+
457
+ # Зашифровать данные
458
+ зашифровано = Шифр.зашифровать("секретные данные", "мой_пароль")
459
+
460
+ # Расшифровать
461
+ данные = Шифр.расшифровать(зашифровано, "мой_пароль")
462
+
463
+ # Зашифровать файл
464
+ Шифр.зашифровать_файл("data.json", "пароль", "data.enc")
465
+
466
+ # Расшифровать файл
467
+ Шифр.расшифровать_файл("data.enc", "пароль", "data.json")
468
+
469
+ # Хэш строки
470
+ хэш = Шифр.хэш("важные данные")
471
+
472
+ # Хэш файла
473
+ хэш = Шифр.хэш_файла("data.json")
474
+
475
+ # Сравнить файлы
476
+ одинаковые = Шифр.сравнить_хэши("file1.json", "file2.json")
477
+
478
+ # Электронная подпись
479
+ подпись = Шифр.подписать("документ", "ключ")
480
+ валидна = Шифр.проверить_подпись("документ", подпись, "ключ")
481
+
482
+ # Сгенерировать пароль
483
+ пароль = Шифр.сгенерировать_пароль(16)
484
+
485
+ # Проверить надёжность пароля
486
+ print(Шифр.надёжность_пароля("qwerty")) # Слабый
487
+ print(Шифр.надёжность_пароля("Qw3rty!@2026")) # Очень надёжный
488
+ ```
489
+
490
+ Миграции
491
+
492
+ ```python
493
+ from vrbase import Миграция, МенеджерМиграций
494
+
495
+ менеджер = МенеджерМиграций(мир)
496
+
497
+ # Создать миграцию
498
+ v1 = (Миграция("1.0.0", "Начальная структура")
499
+ .добавить_поле("игроки", "золото", 100)
500
+ .добавить_поле("игроки", "опыт", 0))
501
+
502
+ v2 = (Миграция("1.1.0", "Добавляем магию")
503
+ .добавить_поле("игроки", "мана", 50)
504
+ .добавить_поле("игроки", "макс_мана", 50))
505
+
506
+ v3 = (Миграция("2.0.0", "Переименовываем")
507
+ .переименовать_поле("игроки", "золото", "монеты"))
508
+
509
+ # Зарегистрировать
510
+ менеджер.зарегистрировать(v1)
511
+ менеджер.зарегистрировать(v2)
512
+ менеджер.зарегистрировать(v3)
513
+
514
+ # Применить все
515
+ менеджер.применить()
516
+
517
+ # Применить до определённой версии
518
+ менеджер.применить(до_версии="1.1.0")
519
+
520
+ # Статус
521
+ print(менеджер.статус())
522
+ # {'всего': 3, 'применено': 2, 'ожидают': 1}
523
+
524
+ # Откатить
525
+ менеджер.откатить("1.0.0")
526
+ ```
527
+
528
+ ---
529
+
530
+ Сравнение с SQL
531
+
532
+ Действие SQL VRBase
533
+ Создать таблицу CREATE TABLE ... мир.коробка("имя")
534
+ Вставить INSERT INTO ... .положить({...})
535
+ Выбрать все SELECT * FROM ... .найти_все()
536
+ Выбрать с условием WHERE x = 5 .найти(где={"x": 5})
537
+ Больше/меньше WHERE x > 5 .найти(где={"x": "> 5"})
538
+ Сортировка ORDER BY x DESC сортировка="x убыв"
539
+ Лимит LIMIT 10 лимит=10
540
+ Обновить UPDATE ... SET ... .обновить(где=..., данные=...)
541
+ Удалить DELETE FROM ... .удалить(где=...)
542
+ Индекс CREATE INDEX ... .создать_индекс(...)
543
+ JOIN LEFT JOIN ... Вложенные документы
544
+ Схема Обязательна Не нужна
545
+ Миграции ALTER TABLE ... Автоматически
546
+
547
+ ---
548
+
549
+ Примеры
550
+
551
+ RPG-бот на RuGram + VRBase
552
+
553
+ ```python
554
+ from ядро import РуГрам
555
+ from vrbase import База
556
+
557
+ бот = РуГрам("ТОКЕН")
558
+ мир = База("rpg_bot")
559
+ игроки = мир.коробка("игроки")
560
+
561
+ @бот.обработать(команда="start")
562
+ def старт(сообщение, контекст):
563
+ игрок = игроки.найти_один(чат_ид=сообщение.чат.ид)
564
+ if not игрок:
565
+ игроки.положить({
566
+ "чат_ид": сообщение.чат.ид,
567
+ "имя": сообщение.от.имя,
568
+ "уровень": 1,
569
+ "здоровье": 100,
570
+ "золото": 0
571
+ })
572
+ мир.сохранить()
573
+
574
+ бот.отправить(сообщение.чат.ид, "Добро пожаловать!")
575
+ ```
576
+
577
+ ---
578
+
579
+ API Reference
580
+
581
+ База
582
+
583
+ Метод Описание
584
+ База(имя, путь, ключ) Создать/открыть базу
585
+ .коробка(имя) Получить коробку
586
+ .сохранить() Сохранить на диск
587
+ .загрузить() Загрузить с диска
588
+ .бэкап() Создать копию
589
+ .очистить() Удалить всё
590
+ .инфо() Информация о базе
591
+ .список_коробок() Список коробок
592
+ .размер() Размер файла в байтах
593
+
594
+ Коробка
595
+
596
+ Метод Описание
597
+ .положить(документ) Добавить документ
598
+ .положить_много(список) Добавить много
599
+ .найти(где, содержит, сортировка, лимит) Поиск
600
+ .найти_один(**условия) Найти один
601
+ .найти_все() Все документы
602
+ .найти_по_id(ид) По ID
603
+ .считать(где) Количество
604
+ .обновить(где, данные) Обновить
605
+ .обновить_по_id(ид, данные) Обновить по ID
606
+ .обновить_все(данные) Обновить все
607
+ .удалить(где) Удалить
608
+ .удалить_по_id(ид) Удалить по ID
609
+ .удалить_все() Очистить
610
+ .есть(где) Проверить существование
611
+ .создать_индекс(ключ) Создать индекс
612
+ .удалить_индекс(ключ) Удалить индекс
613
+ .уникальные(ключ) Уникальные значения
614
+ .ключи() Все ключи
615
+ .экспорт() Экспорт данных
616
+ .импорт(данные) Импорт данных
617
+ .запрос() Создать запрос
618
+ .агрегация() Создать агрегацию
619
+
620
+ ---
621
+
622
+ Лицензия
623
+
624
+ MIT License. Свободное использование, модификация и распространение.