oktopios-orm 0.1.0__py3-none-any.whl
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.
oktopios_orm/__init__.py
ADDED
oktopios_orm/orm.okp
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// =====================================================================
|
|
2
|
+
// oktopios-framework — Couche ORM
|
|
3
|
+
// Écrit EN Oktopios, s'appuie sur la réflexion et les décorateurs du
|
|
4
|
+
// langage (>= 0.6.0). Chargé via : use "framework/orm.okp"
|
|
5
|
+
//
|
|
6
|
+
// - Schema : migrations (génère le schéma SQL depuis les modèles décorés)
|
|
7
|
+
// - Repo : dépôt générique (save / all / findBy / remove + hydratation)
|
|
8
|
+
// - Query : constructeur de requêtes fluide
|
|
9
|
+
//
|
|
10
|
+
// Décorateurs reconnus :
|
|
11
|
+
// @Entity("table") (classe) -> nom de table
|
|
12
|
+
// @Column("colonne") (champ) -> nom de colonne
|
|
13
|
+
// @Id (champ) -> clé primaire
|
|
14
|
+
// =====================================================================
|
|
15
|
+
inject Type
|
|
16
|
+
inject DataImport
|
|
17
|
+
|
|
18
|
+
// ---------------------------------------------------------------------
|
|
19
|
+
// Schema — génération de schéma / migrations
|
|
20
|
+
// ---------------------------------------------------------------------
|
|
21
|
+
class Schema {
|
|
22
|
+
fun sqlType(t: string): string {
|
|
23
|
+
if (t == "int") { return "INTEGER" }
|
|
24
|
+
if (t == "float") { return "REAL" }
|
|
25
|
+
if (t == "bool") { return "INTEGER" }
|
|
26
|
+
return "TEXT"
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
fun tableName(entity: any): string {
|
|
30
|
+
var e = Type.annotation(entity, "Entity")
|
|
31
|
+
if (e != null) { return e[0] }
|
|
32
|
+
return Type.className(entity)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
fun columnName(entity: any, champ: string): string {
|
|
36
|
+
var c = Type.fieldAnnotation(entity, champ, "Column")
|
|
37
|
+
if (c != null) { return c[0] }
|
|
38
|
+
return champ
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
fun idField(entity: any): string {
|
|
42
|
+
for (f in Type.fields(entity)) {
|
|
43
|
+
if (Type.fieldAnnotation(entity, f, "Id") != null) { return f }
|
|
44
|
+
}
|
|
45
|
+
return "id"
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
fun createTableSQL(entity: any): string {
|
|
49
|
+
var defs = ""
|
|
50
|
+
for (f in Type.fields(entity)) {
|
|
51
|
+
if (defs != "") { defs = defs + ", " }
|
|
52
|
+
var ligne = this.columnName(entity, f) + " " + this.sqlType(Type.fieldType(entity, f))
|
|
53
|
+
if (Type.fieldAnnotation(entity, f, "Id") != null) {
|
|
54
|
+
ligne = ligne + " PRIMARY KEY"
|
|
55
|
+
}
|
|
56
|
+
defs = defs + ligne
|
|
57
|
+
}
|
|
58
|
+
return "CREATE TABLE IF NOT EXISTS " + this.tableName(entity) + " (" + defs + ")"
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Crée la table dans la base à partir d'un exemple d'entité (modèle décoré)
|
|
62
|
+
fun migrate(db: string, entity: any): string {
|
|
63
|
+
var sql = this.createTableSQL(entity)
|
|
64
|
+
DataImport.execSQL(db, sql, [])
|
|
65
|
+
return sql
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ---------------------------------------------------------------------
|
|
70
|
+
// Repo — dépôt de données générique pour un modèle
|
|
71
|
+
// ---------------------------------------------------------------------
|
|
72
|
+
class Repo {
|
|
73
|
+
var db: string
|
|
74
|
+
var table: string
|
|
75
|
+
var model: string
|
|
76
|
+
var schema: Schema
|
|
77
|
+
|
|
78
|
+
// `sample` : une instance du modèle, utilisée pour lire les métadonnées
|
|
79
|
+
fun __construct(db: string, sample: any) {
|
|
80
|
+
this.db = db
|
|
81
|
+
this.schema = new Schema()
|
|
82
|
+
this.table = this.schema.tableName(sample)
|
|
83
|
+
this.model = Type.className(sample)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
fun save(entity: any): int {
|
|
87
|
+
var colonnes = ""
|
|
88
|
+
var marques = ""
|
|
89
|
+
var valeurs = []
|
|
90
|
+
for (f in Type.fields(entity)) {
|
|
91
|
+
if (colonnes != "") {
|
|
92
|
+
colonnes = colonnes + ", "
|
|
93
|
+
marques = marques + ", "
|
|
94
|
+
}
|
|
95
|
+
colonnes = colonnes + this.schema.columnName(entity, f)
|
|
96
|
+
marques = marques + "?"
|
|
97
|
+
valeurs = valeurs + [Type.get(entity, f)]
|
|
98
|
+
}
|
|
99
|
+
var sql = "INSERT INTO " + this.table + " (" + colonnes + ") VALUES (" + marques + ")"
|
|
100
|
+
return DataImport.execSQL(this.db, sql, valeurs)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Transforme les lignes SQL (colonnes) en instances du modèle (champs)
|
|
104
|
+
fun hydrate(lignes: any): any {
|
|
105
|
+
var objets = []
|
|
106
|
+
for (ligne in lignes) {
|
|
107
|
+
var obj = Type.create(this.model)
|
|
108
|
+
for (f in Type.fields(obj)) {
|
|
109
|
+
var col = this.schema.columnName(obj, f)
|
|
110
|
+
Type.set(obj, f, ligne[col])
|
|
111
|
+
}
|
|
112
|
+
objets = objets + [obj]
|
|
113
|
+
}
|
|
114
|
+
return objets
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
fun all(): any {
|
|
118
|
+
return this.hydrate(DataImport.execSQL(this.db, "SELECT * FROM " + this.table, []))
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
fun findBy(colonne: string, valeur: any): any {
|
|
122
|
+
var sql = "SELECT * FROM " + this.table + " WHERE " + colonne + " = ?"
|
|
123
|
+
return this.hydrate(DataImport.execSQL(this.db, sql, [valeur]))
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
fun remove(colonne: string, valeur: any): int {
|
|
127
|
+
var sql = "DELETE FROM " + this.table + " WHERE " + colonne + " = ?"
|
|
128
|
+
return DataImport.execSQL(this.db, sql, [valeur])
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ---------------------------------------------------------------------
|
|
133
|
+
// Query — constructeur de requêtes fluide
|
|
134
|
+
// ---------------------------------------------------------------------
|
|
135
|
+
class Query {
|
|
136
|
+
var db: string
|
|
137
|
+
var table: string
|
|
138
|
+
var champs: string
|
|
139
|
+
var conds: string
|
|
140
|
+
var params: any
|
|
141
|
+
var ordre: string
|
|
142
|
+
|
|
143
|
+
fun __construct(db: string, table: string) {
|
|
144
|
+
this.db = db
|
|
145
|
+
this.table = table
|
|
146
|
+
this.champs = "*"
|
|
147
|
+
this.conds = ""
|
|
148
|
+
this.params = []
|
|
149
|
+
this.ordre = ""
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
fun select(champs: string): Query {
|
|
153
|
+
this.champs = champs
|
|
154
|
+
return this
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
fun where(colonne: string, op: string, valeur: any): Query {
|
|
158
|
+
if (this.conds != "") { this.conds = this.conds + " AND " }
|
|
159
|
+
this.conds = this.conds + colonne + " " + op + " ?"
|
|
160
|
+
this.params = this.params + [valeur]
|
|
161
|
+
return this
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
fun orderBy(colonne: string, sens: string): Query {
|
|
165
|
+
this.ordre = " ORDER BY " + colonne + " " + sens
|
|
166
|
+
return this
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
fun sql(): string {
|
|
170
|
+
var s = "SELECT " + this.champs + " FROM " + this.table
|
|
171
|
+
if (this.conds != "") { s = s + " WHERE " + this.conds }
|
|
172
|
+
s = s + this.ordre
|
|
173
|
+
return s
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
fun get(): any {
|
|
177
|
+
return DataImport.execSQL(this.db, this.sql(), this.params)
|
|
178
|
+
}
|
|
179
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: oktopios-orm
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: ORM pour le langage Oktopios — modeles decores, migrations, query-builder (facon Doctrine / Django ORM)
|
|
5
|
+
Author: Mouanwiya Ali Soule
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2025 Mouanwiya Ali Soule
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/ALISOULEMOUANWIYA/oktopios-orm
|
|
29
|
+
Project-URL: Language, https://pypi.org/project/oktopios/
|
|
30
|
+
Keywords: oktopios,orm,database,sqlite,migrations,okp
|
|
31
|
+
Requires-Python: >=3.8
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
License-File: LICENSE
|
|
34
|
+
Requires-Dist: oktopios>=0.7.0
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
|
|
37
|
+
# oktopios-orm 🐙🗄️
|
|
38
|
+
|
|
39
|
+
ORM pour le langage **[Oktopios](https://pypi.org/project/oktopios/)** — dans
|
|
40
|
+
l'esprit de **Doctrine** (Symfony) et de l'**ORM de Django** : modèles déclarés
|
|
41
|
+
par décorateurs, migrations automatiques, dépôt générique et query-builder.
|
|
42
|
+
|
|
43
|
+
Deuxième couche de l'écosystème :
|
|
44
|
+
**langage `oktopios` → `oktopios-orm` → `oktopios-framework`**.
|
|
45
|
+
|
|
46
|
+
## Installation
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install oktopios-orm
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Cela installe aussi le langage `oktopios` (dépendance). Comme Django a besoin de
|
|
53
|
+
Python et Doctrine de PHP, `oktopios-orm` a besoin de l'interpréteur `oktopios`.
|
|
54
|
+
|
|
55
|
+
## Utilisation
|
|
56
|
+
|
|
57
|
+
Dans un fichier `.okp` :
|
|
58
|
+
|
|
59
|
+
```okp
|
|
60
|
+
use "oktopios_orm/orm.okp" // résolu depuis le paquet installé
|
|
61
|
+
inject Type
|
|
62
|
+
|
|
63
|
+
@Entity("articles")
|
|
64
|
+
class Article {
|
|
65
|
+
@Id
|
|
66
|
+
var id: int
|
|
67
|
+
@Column("titre")
|
|
68
|
+
var title: string
|
|
69
|
+
var vues: int
|
|
70
|
+
fun __construct(title: string, vues: int) {
|
|
71
|
+
this.title = title
|
|
72
|
+
this.vues = vues
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
var schema = new Schema()
|
|
77
|
+
var sample = new Article("", 0)
|
|
78
|
+
schema.migrate("blog.db", sample) // CREATE TABLE articles (id INTEGER PRIMARY KEY, titre TEXT, vues INTEGER)
|
|
79
|
+
|
|
80
|
+
var repo = new Repo("blog.db", sample)
|
|
81
|
+
var a = new Article("Bonjour", 100)
|
|
82
|
+
Type.set(a, "id", 1)
|
|
83
|
+
repo.save(a)
|
|
84
|
+
|
|
85
|
+
for (x in repo.all()) { print(x.title) }
|
|
86
|
+
|
|
87
|
+
var q = new Query("blog.db", "articles")
|
|
88
|
+
print(q.select("id, titre, vues").where("vues", ">", 50).orderBy("vues", "DESC").get())
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Exécuter : `okp examples/blog.okp`
|
|
92
|
+
|
|
93
|
+
## Contenu (`oktopios_orm/orm.okp`)
|
|
94
|
+
|
|
95
|
+
- **`Schema`** — migrations : génère le schéma SQL depuis les modèles décorés
|
|
96
|
+
(`@Entity`, `@Id`, `@Column`) ; mapping des types (`int→INTEGER`, `string→TEXT`,
|
|
97
|
+
`float→REAL`, `bool→INTEGER`).
|
|
98
|
+
- **`Repo`** — dépôt générique : `save`, `all`, `findBy`, `remove`, hydratation
|
|
99
|
+
ligne → objet typé (par réflexion).
|
|
100
|
+
- **`Query`** — constructeur de requêtes fluide : `select().where().orderBy().get()`,
|
|
101
|
+
paramétré (anti-injection).
|
|
102
|
+
|
|
103
|
+
## Décorateurs reconnus
|
|
104
|
+
|
|
105
|
+
| Décorateur | Cible | Effet |
|
|
106
|
+
|---|---|---|
|
|
107
|
+
| `@Entity("table")` | classe | nom de la table |
|
|
108
|
+
| `@Column("colonne")` | champ | nom de la colonne |
|
|
109
|
+
| `@Id` | champ | clé primaire |
|
|
110
|
+
|
|
111
|
+
## Licence
|
|
112
|
+
|
|
113
|
+
MIT © Mouanwiya Ali Soule
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
oktopios_orm/__init__.py,sha256=tS_5qQIanGz4veKTrPuKYAe_itQAuZnSRVao3bm_6Jk,75
|
|
2
|
+
oktopios_orm/orm.okp,sha256=wVjbCZ1K3UugAQdEGumVyuMCYZ011oIRuHHyakpg6mA,6016
|
|
3
|
+
oktopios_orm-0.1.0.dist-info/licenses/LICENSE,sha256=JnDpJVqc6gG-fDrMoIu7AHH9jVEOZhJs8V92NcdQFJU,1076
|
|
4
|
+
oktopios_orm-0.1.0.dist-info/METADATA,sha256=hj6uswsp8qrMEi5TKH7niCSHnRuLZ8KCncLTvCqk8fI,4090
|
|
5
|
+
oktopios_orm-0.1.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
6
|
+
oktopios_orm-0.1.0.dist-info/top_level.txt,sha256=JIx5GSVOtl8RH2u3p6w8PMd9aFx1dYucgBgU1AHCW7E,13
|
|
7
|
+
oktopios_orm-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Mouanwiya Ali Soule
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
oktopios_orm
|