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.
@@ -0,0 +1,2 @@
1
+ """oktopios-orm — ORM pour le langage Oktopios."""
2
+ __version__ = "0.1.0"
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,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -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