pybasedb-json 0.2.0__tar.gz → 0.4.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.
Files changed (31) hide show
  1. pybasedb_json-0.4.0/PKG-INFO +146 -0
  2. pybasedb_json-0.4.0/README.md +120 -0
  3. pybasedb_json-0.4.0/pybase/__init__.py +44 -0
  4. pybasedb_json-0.4.0/pybase/backup.py +100 -0
  5. pybasedb_json-0.4.0/pybase/collections.py +309 -0
  6. pybasedb_json-0.4.0/pybase/crypto.py +59 -0
  7. pybasedb_json-0.4.0/pybase/database.py +151 -0
  8. pybasedb_json-0.4.0/pybase/exceptions.py +30 -0
  9. pybasedb_json-0.4.0/pybase/hooks.py +133 -0
  10. pybasedb_json-0.4.0/pybase/index.py +54 -0
  11. pybasedb_json-0.4.0/pybase/media.py +214 -0
  12. pybasedb_json-0.4.0/pybase/pybase.py +57 -0
  13. pybasedb_json-0.4.0/pybase/query.py +28 -0
  14. pybasedb_json-0.4.0/pybase/server.py +222 -0
  15. pybasedb_json-0.4.0/pybase/utils.py +23 -0
  16. pybasedb_json-0.4.0/pybase/validation.py +382 -0
  17. pybasedb_json-0.4.0/pybasedb_json.egg-info/PKG-INFO +146 -0
  18. {pybasedb_json-0.2.0 → pybasedb_json-0.4.0}/pybasedb_json.egg-info/SOURCES.txt +8 -0
  19. {pybasedb_json-0.2.0 → pybasedb_json-0.4.0}/pyproject.toml +6 -3
  20. pybasedb_json-0.2.0/PKG-INFO +0 -92
  21. pybasedb_json-0.2.0/README.md +0 -69
  22. pybasedb_json-0.2.0/pybase/__init__.py +0 -13
  23. pybasedb_json-0.2.0/pybase/collections.py +0 -133
  24. pybasedb_json-0.2.0/pybase/database.py +0 -72
  25. pybasedb_json-0.2.0/pybase/exceptions.py +0 -14
  26. pybasedb_json-0.2.0/pybase/query.py +0 -73
  27. pybasedb_json-0.2.0/pybase/utils.py +0 -11
  28. pybasedb_json-0.2.0/pybasedb_json.egg-info/PKG-INFO +0 -92
  29. {pybasedb_json-0.2.0 → pybasedb_json-0.4.0}/pybasedb_json.egg-info/dependency_links.txt +0 -0
  30. {pybasedb_json-0.2.0 → pybasedb_json-0.4.0}/pybasedb_json.egg-info/top_level.txt +0 -0
  31. {pybasedb_json-0.2.0 → pybasedb_json-0.4.0}/setup.cfg +0 -0
@@ -0,0 +1,146 @@
1
+ Metadata-Version: 2.4
2
+ Name: pybasedb-json
3
+ Version: 0.4.0
4
+ Summary: Banco de dados local com JSON — schemas, decorator API, server REST, criptografia, zero dependencias
5
+ Author-email: Marcos Gomes <marcosgabrielgomes110@gmail.com>
6
+ Maintainer-email: Marcos Gomes <marcosgabrielgomes110@gmail.com>
7
+ License: MIT
8
+ Project-URL: Homepage, https://github.com/marcosgabrielgomes110-collab/Pybase
9
+ Project-URL: Documentation, https://github.com/marcosgabrielgomes110-collab/Pybase/tree/main/docs
10
+ Project-URL: Repository, https://github.com/marcosgabrielgomes110-collab/Pybase
11
+ Keywords: database,json,local,embedded,nosql,thread-safe,rest-api,schema,media
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Topic :: Database
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
24
+ Requires-Python: >=3.10
25
+ Description-Content-Type: text/markdown
26
+
27
+ <p align="center">
28
+ <img src="assets/logo/logo.png" width="120" alt="Pybase logo">
29
+ </p>
30
+
31
+ # Pybase v0.4
32
+
33
+ Base para criacao de bancos de dados locais com JSON. Zero dependencias, 100% stdlib.
34
+ Operacoes de escrita atomicas, thread-safe.
35
+
36
+ Filosofia **Lego**: cada modulo e independente — voce monta o que precisa.
37
+
38
+ ## Instalacao
39
+
40
+ ```bash
41
+ pip install pybasedb-json
42
+ ```
43
+
44
+ Para o servidor REST (opcional):
45
+ ```bash
46
+ pip install Flask
47
+ ```
48
+
49
+ ## Uso rapido
50
+
51
+ ```python
52
+ from pybase import pybase as pb
53
+
54
+ # Banco de dados (sem senha ou com senha)
55
+ db = pb.Database("./data/mydb")
56
+ # db = pb.Database("./data/mydb", password="senha").open("senha")
57
+
58
+ # Schema com decorator (v0.4+)
59
+ @db.schema.users
60
+ class User:
61
+ name: str
62
+ email: str
63
+ age: int = 0
64
+ active: bool = True
65
+
66
+ # Ou com T() explicito
67
+ # from pybase.validation import T
68
+ # db.schema.users = pb.Schema({"name": pb.T(str), "age": pb.T(int, default=0)})
69
+
70
+ # Colecao com validacao automatica
71
+ users = db["users"]
72
+ users.add({"name": "marcos", "email": "m@m.com"}) # auto-ID
73
+
74
+ # SDK client
75
+ doc = users["1"].get()
76
+ users.find(age=0)
77
+
78
+ # Consultas direto na colecao (v0.4+)
79
+ users.sort("name").limit(10).find(active=True)
80
+ users.find_one(name="ana")
81
+ users.exists(name="joao")
82
+
83
+ # Servidor REST (requer Flask)
84
+ pb.Server(db).run(port=4560) # auto-detecta colecoes
85
+ # Swagger UI: http://localhost:4560/mydb/docs/
86
+ ```
87
+
88
+ ## Modulos
89
+
90
+ | Modulo | Arquivo | Descricao | Deps |
91
+ |--------|---------|-----------|------|
92
+ | Database | `pybase/database.py` | Gerencia diretorio de tabelas JSON | 0 |
93
+ | Collection | `pybase/collections.py` | CRUD atomico thread-safe + query integrado | 0 |
94
+ | Query | `pybase/query.py` | Thin wrapper sobre Collection | 0 |
95
+ | Schema | `pybase/validation.py` | Validacao com T(), decorator, from_example | 0 |
96
+ | Server | `pybase/server.py` | REST API automatica + Swagger UI | Flask |
97
+ | Media | `pybase/media.py` | Upload/download de imagens | 0 |
98
+ | Backup | `pybase/backup.py` | Snapshot e restore (seletivo) | 0 |
99
+ | Crypto | `pybase/crypto.py` | Criptografia stdlib (scrypt + XOR) | 0 |
100
+
101
+ ## Novidades da v0.4
102
+
103
+ - **API simplificada** — `Database("./data/mydb")` sem senha obrigatoria
104
+ - **`update`/`delete`** — nomes em ingles, sem aliases pt-br
105
+ - **Auto-ID** — `users.add({"name": "x"})` gera UUID automatico
106
+ - **`db["colecao"]`** — acesso direto via `__getitem__`
107
+ - **Query integrado** — `collection.sort().limit().find()` direto
108
+ - **`@db.schema.nome`** — schema via decorator de classe
109
+ - **`T()`** — nova API de tipos com kwargs (`T(int, default=0)`)
110
+ - **`Schema.from_example()`** — schema inferido de dados reais
111
+ - **`import global`** — `from pybase import pybase`
112
+ - **PBKDF2** — hashing de senha com salt (600k iteracoes)
113
+ - **Criptografia** — `encrypt()`/`decrypt()` stdlib puro
114
+ - **Server auto-detect** — `Server(db).run()` descobre colecoes
115
+ - **Erros descritivos** — com path + valor + sugestao
116
+
117
+ ## Estrutura
118
+
119
+ ```
120
+ Pybase/
121
+ pybase/
122
+ __init__.py # Database, Collection, Query, Server, Schema, T
123
+ pybase.py # from pybase import pybase
124
+ database.py # Database, SchemaRegistrar
125
+ collections.py # Collection, DocRef, QueryBuilder, SchemaCollection
126
+ query.py # Query wrapper
127
+ exceptions.py # PybaseError > DatabaseError, CollectionError, ...
128
+ validation.py # Schema, T, ValidationError
129
+ server.py # Server REST (Flask)
130
+ media.py # MediaManager
131
+ index.py # Index (hash O(1))
132
+ hooks.py # HooksCollection
133
+ backup.py # take, restore
134
+ crypto.py # encrypt, decrypt (stdlib)
135
+ utils.py # PBKDF2 encode/verify
136
+ docs/ # Documentacao completa
137
+ pyproject.toml
138
+ ```
139
+
140
+ ## Documentacao
141
+
142
+ Veja [docs/](docs/index.md) com referencia completa de cada classe e metodo.
143
+
144
+ ## Licenca
145
+
146
+ MIT
@@ -0,0 +1,120 @@
1
+ <p align="center">
2
+ <img src="assets/logo/logo.png" width="120" alt="Pybase logo">
3
+ </p>
4
+
5
+ # Pybase v0.4
6
+
7
+ Base para criacao de bancos de dados locais com JSON. Zero dependencias, 100% stdlib.
8
+ Operacoes de escrita atomicas, thread-safe.
9
+
10
+ Filosofia **Lego**: cada modulo e independente — voce monta o que precisa.
11
+
12
+ ## Instalacao
13
+
14
+ ```bash
15
+ pip install pybasedb-json
16
+ ```
17
+
18
+ Para o servidor REST (opcional):
19
+ ```bash
20
+ pip install Flask
21
+ ```
22
+
23
+ ## Uso rapido
24
+
25
+ ```python
26
+ from pybase import pybase as pb
27
+
28
+ # Banco de dados (sem senha ou com senha)
29
+ db = pb.Database("./data/mydb")
30
+ # db = pb.Database("./data/mydb", password="senha").open("senha")
31
+
32
+ # Schema com decorator (v0.4+)
33
+ @db.schema.users
34
+ class User:
35
+ name: str
36
+ email: str
37
+ age: int = 0
38
+ active: bool = True
39
+
40
+ # Ou com T() explicito
41
+ # from pybase.validation import T
42
+ # db.schema.users = pb.Schema({"name": pb.T(str), "age": pb.T(int, default=0)})
43
+
44
+ # Colecao com validacao automatica
45
+ users = db["users"]
46
+ users.add({"name": "marcos", "email": "m@m.com"}) # auto-ID
47
+
48
+ # SDK client
49
+ doc = users["1"].get()
50
+ users.find(age=0)
51
+
52
+ # Consultas direto na colecao (v0.4+)
53
+ users.sort("name").limit(10).find(active=True)
54
+ users.find_one(name="ana")
55
+ users.exists(name="joao")
56
+
57
+ # Servidor REST (requer Flask)
58
+ pb.Server(db).run(port=4560) # auto-detecta colecoes
59
+ # Swagger UI: http://localhost:4560/mydb/docs/
60
+ ```
61
+
62
+ ## Modulos
63
+
64
+ | Modulo | Arquivo | Descricao | Deps |
65
+ |--------|---------|-----------|------|
66
+ | Database | `pybase/database.py` | Gerencia diretorio de tabelas JSON | 0 |
67
+ | Collection | `pybase/collections.py` | CRUD atomico thread-safe + query integrado | 0 |
68
+ | Query | `pybase/query.py` | Thin wrapper sobre Collection | 0 |
69
+ | Schema | `pybase/validation.py` | Validacao com T(), decorator, from_example | 0 |
70
+ | Server | `pybase/server.py` | REST API automatica + Swagger UI | Flask |
71
+ | Media | `pybase/media.py` | Upload/download de imagens | 0 |
72
+ | Backup | `pybase/backup.py` | Snapshot e restore (seletivo) | 0 |
73
+ | Crypto | `pybase/crypto.py` | Criptografia stdlib (scrypt + XOR) | 0 |
74
+
75
+ ## Novidades da v0.4
76
+
77
+ - **API simplificada** — `Database("./data/mydb")` sem senha obrigatoria
78
+ - **`update`/`delete`** — nomes em ingles, sem aliases pt-br
79
+ - **Auto-ID** — `users.add({"name": "x"})` gera UUID automatico
80
+ - **`db["colecao"]`** — acesso direto via `__getitem__`
81
+ - **Query integrado** — `collection.sort().limit().find()` direto
82
+ - **`@db.schema.nome`** — schema via decorator de classe
83
+ - **`T()`** — nova API de tipos com kwargs (`T(int, default=0)`)
84
+ - **`Schema.from_example()`** — schema inferido de dados reais
85
+ - **`import global`** — `from pybase import pybase`
86
+ - **PBKDF2** — hashing de senha com salt (600k iteracoes)
87
+ - **Criptografia** — `encrypt()`/`decrypt()` stdlib puro
88
+ - **Server auto-detect** — `Server(db).run()` descobre colecoes
89
+ - **Erros descritivos** — com path + valor + sugestao
90
+
91
+ ## Estrutura
92
+
93
+ ```
94
+ Pybase/
95
+ pybase/
96
+ __init__.py # Database, Collection, Query, Server, Schema, T
97
+ pybase.py # from pybase import pybase
98
+ database.py # Database, SchemaRegistrar
99
+ collections.py # Collection, DocRef, QueryBuilder, SchemaCollection
100
+ query.py # Query wrapper
101
+ exceptions.py # PybaseError > DatabaseError, CollectionError, ...
102
+ validation.py # Schema, T, ValidationError
103
+ server.py # Server REST (Flask)
104
+ media.py # MediaManager
105
+ index.py # Index (hash O(1))
106
+ hooks.py # HooksCollection
107
+ backup.py # take, restore
108
+ crypto.py # encrypt, decrypt (stdlib)
109
+ utils.py # PBKDF2 encode/verify
110
+ docs/ # Documentacao completa
111
+ pyproject.toml
112
+ ```
113
+
114
+ ## Documentacao
115
+
116
+ Veja [docs/](docs/index.md) com referencia completa de cada classe e metodo.
117
+
118
+ ## Licenca
119
+
120
+ MIT
@@ -0,0 +1,44 @@
1
+ try:
2
+ from .server import Server
3
+ except ImportError:
4
+ Server = None
5
+
6
+ from .collections import Collection, DocRef, QueryBuilder, SchemaCollection
7
+ from .database import Database
8
+ from .exceptions import (
9
+ CollectionError,
10
+ DatabaseError,
11
+ DocumentNotFoundError,
12
+ EncryptionError,
13
+ MediaError,
14
+ PybaseError,
15
+ QueryError,
16
+ ValidationError,
17
+ )
18
+ from .query import Query
19
+
20
+ try:
21
+ from .validation import Schema, T
22
+ except ImportError:
23
+ Schema = None
24
+ T = None
25
+
26
+ __all__ = [
27
+ "Collection",
28
+ "Database",
29
+ "DocRef",
30
+ "DocumentNotFoundError",
31
+ "EncryptionError",
32
+ "MediaError",
33
+ "PybaseError",
34
+ "DatabaseError",
35
+ "CollectionError",
36
+ "Query",
37
+ "QueryBuilder",
38
+ "QueryError",
39
+ "Schema",
40
+ "SchemaCollection",
41
+ "Server",
42
+ "T",
43
+ "ValidationError",
44
+ ]
@@ -0,0 +1,100 @@
1
+ # Lego piece: optional backup / restore for Pybase databases.
2
+ # from pybase.backup import take, restore, list_snapshots
3
+ # snap = take(db) # timestamped .json.gz
4
+
5
+ from __future__ import annotations
6
+
7
+ import gzip
8
+ import json
9
+ import os
10
+ from datetime import datetime
11
+ from pathlib import Path
12
+ from typing import TYPE_CHECKING
13
+
14
+ if TYPE_CHECKING:
15
+ from .database import Database
16
+
17
+ _BACKUP_DIR = "backups"
18
+
19
+
20
+ def take(
21
+ db: Database,
22
+ dest: str | Path | None = None,
23
+ *,
24
+ compress: bool = True,
25
+ collections: list[str] | None = None,
26
+ ) -> Path:
27
+ backup_dir = Path(dest) if dest else (db.path_dir / _BACKUP_DIR)
28
+ backup_dir.mkdir(parents=True, exist_ok=True)
29
+
30
+ ts = datetime.now().strftime("%Y%m%d_%H%M%S")
31
+ ext = ".json.gz" if compress else ".json"
32
+ out_path = backup_dir / f"{db.name}_{ts}{ext}"
33
+
34
+ names = collections if collections else db.collections
35
+ snapshot: dict[str, list[dict]] = {}
36
+ for name in names:
37
+ snapshot[name] = db.collection(name).all()
38
+
39
+ raw = json.dumps(snapshot, indent=2).encode("utf-8")
40
+
41
+ if compress:
42
+ # mtime=0 makes the gzip deterministic (same content → same bytes)
43
+ with gzip.GzipFile(out_path, "wb", mtime=0) as f:
44
+ f.write(raw)
45
+ else:
46
+ out_path.write_bytes(raw)
47
+
48
+ return out_path
49
+
50
+
51
+ def restore(
52
+ db_dir: str | Path,
53
+ snapshot: str | Path,
54
+ *,
55
+ merge: bool = False,
56
+ ) -> None:
57
+ # Restore collection data from a snapshot file (.json or .json.gz)
58
+ db_dir = Path(db_dir)
59
+ snap_path = Path(snapshot)
60
+
61
+ if snap_path.suffix == ".gz":
62
+ with gzip.GzipFile(snap_path, "rb") as f:
63
+ raw = f.read()
64
+ else:
65
+ raw = snap_path.read_bytes()
66
+
67
+ data: dict[str, list[dict]] = json.loads(raw)
68
+
69
+ for name, docs in data.items():
70
+ col_path = db_dir / f"{name}_table.json"
71
+ existing = []
72
+ if merge and col_path.exists():
73
+ existing = (json.loads(col_path.read_bytes()) if col_path.stat().st_size else [])
74
+ merged = existing + docs if merge else docs
75
+
76
+ # atomic write
77
+ tmp = col_path.with_suffix(".tmp")
78
+ tmp.write_text(json.dumps(merged, indent=2), encoding="utf-8")
79
+ os.replace(tmp, col_path)
80
+
81
+
82
+ def list_snapshots(backup_dir: str | Path) -> list[Path]:
83
+ # Return snapshots sorted newest first
84
+ d = Path(backup_dir)
85
+ if not d.exists():
86
+ return []
87
+ files = sorted(p for p in d.iterdir() if p.suffix in (".json", ".gz") and p.stem != ".tmp")
88
+ return list(reversed(files))
89
+
90
+
91
+ def clean(backup_dir: str | Path, *, keep: int = 10, dry_run: bool = False) -> list[Path]:
92
+ # Remove old snapshots, keeping the `keep` most recent
93
+ snaps = list_snapshots(backup_dir)
94
+ if len(snaps) <= keep:
95
+ return []
96
+ to_remove = snaps[keep:]
97
+ if not dry_run:
98
+ for p in to_remove:
99
+ p.unlink()
100
+ return to_remove