gibson-cli 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.
- api/BaseApi.py +45 -0
- api/Cli.py +248 -0
- bin/gibson.py +16 -0
- command/Api.py +31 -0
- command/Base.py +28 -0
- command/BaseCommand.py +26 -0
- command/Build.py +69 -0
- command/Code.py +198 -0
- command/Conf.py +74 -0
- command/Count.py +35 -0
- command/Dev.py +121 -0
- command/Forget.py +34 -0
- command/Import.py +109 -0
- command/List.py +61 -0
- command/Merge.py +35 -0
- command/Model.py +42 -0
- command/Models.py +31 -0
- command/Modify.py +43 -0
- command/Module.py +42 -0
- command/New.py +38 -0
- command/OpenApi.py +141 -0
- command/Question.py +105 -0
- command/Remove.py +80 -0
- command/Rename.py +71 -0
- command/Rewrite.py +107 -0
- command/Schema.py +42 -0
- command/Schemas.py +31 -0
- command/Show.py +37 -0
- command/Test.py +42 -0
- command/Tests.py +31 -0
- command/Tree.py +92 -0
- command/WarGames.py +35 -0
- command/auth/Auth.py +25 -0
- command/auth/Login.py +17 -0
- command/auth/Logout.py +7 -0
- command/tests/test_command_BaseCommand.py +10 -0
- command/tests/test_command_Conf.py +19 -0
- conf/Api.py +3 -0
- conf/Code.py +9 -0
- conf/Custom.py +4 -0
- conf/Datastore.py +4 -0
- conf/Dependencies.py +24 -0
- conf/Dev.py +15 -0
- conf/Frameworks.py +7 -0
- conf/Modeler.py +3 -0
- conf/Paths.py +10 -0
- conf/Platform.py +16 -0
- conf/Project.py +18 -0
- conf/Version.py +2 -0
- conf/dev/Api.py +5 -0
- conf/dev/Base.py +3 -0
- conf/dev/Model.py +3 -0
- conf/dev/Schema.py +3 -0
- conf/tests/test_conf_Dependencies.py +5 -0
- conf/tests/test_conf_Platform.py +7 -0
- core/CommandRouter.py +249 -0
- core/Configuration.py +418 -0
- core/Conversation.py +270 -0
- core/Env.py +12 -0
- core/Memory.py +148 -0
- core/TimeKeeper.py +12 -0
- core/utils.py +19 -0
- data/default-ref-table.tmpl +4 -0
- data/default-table.tmpl +6 -0
- db/TableExceptions.py +6 -0
- db/tests/test_db_TableExceptions.py +9 -0
- dev/Dev.py +92 -0
- display/Header.py +6 -0
- display/WorkspaceFooter.py +10 -0
- display/WorkspaceHeader.py +8 -0
- display/tests/test_display_Header.py +9 -0
- display/tests/test_display_WorkspaceFooter.py +9 -0
- display/tests/test_display_WorkspaceHeader.py +8 -0
- gibson_cli-0.1.0.dist-info/METADATA +306 -0
- gibson_cli-0.1.0.dist-info/RECORD +102 -0
- gibson_cli-0.1.0.dist-info/WHEEL +5 -0
- gibson_cli-0.1.0.dist-info/entry_points.txt +2 -0
- gibson_cli-0.1.0.dist-info/top_level.txt +12 -0
- lang/Python.py +57 -0
- lang/tests/test_lang_Python.py +70 -0
- services/auth/Server.py +75 -0
- services/code/context/schema/DataDictionary.py +12 -0
- services/code/context/schema/EntityKeys.py +49 -0
- services/code/context/schema/Manager.py +28 -0
- services/code/context/schema/tests/test_code_context_schema_DataDictionary.py +8 -0
- services/code/context/schema/tests/test_code_context_schema_EntityKeys.py +52 -0
- services/code/context/schema/tests/test_code_context_schema_Manager.py +34 -0
- services/code/customization/Authenticator.py +51 -0
- services/code/customization/BaseCustomization.py +12 -0
- services/code/customization/CustomizationManager.py +20 -0
- services/code/customization/tests/test_code_customization_Authenticator.py +53 -0
- services/code/customization/tests/test_code_customization_BaseCustomization.py +14 -0
- structure/Entity.py +115 -0
- structure/constraints/ReferenceConstraint.py +36 -0
- structure/keys/ForeignKey.py +41 -0
- structure/keys/Index.py +64 -0
- structure/keys/IndexAttribute.py +14 -0
- structure/keys/tests/test_ForeignKey.py +80 -0
- structure/keys/tests/test_Index.py +98 -0
- structure/keys/tests/test_IndexAttribute.py +17 -0
- structure/testing.py +194 -0
- structure/tests/test_Entity.py +107 -0
@@ -0,0 +1,102 @@
|
|
1
|
+
api/BaseApi.py,sha256=W5C_Rq-sf_MOwArozYG0ILFL8nyXhSwX84dpLT69o1M,1055
|
2
|
+
api/Cli.py,sha256=CPl_VnNuPyXkQNIv-YNfKpQbAdJIP8i2DeHbsmodXlA,8380
|
3
|
+
bin/gibson.py,sha256=Ip7qGG6yR_lCQYkBTgfpMXS-OT2meB6kYnK9gL53hvI,340
|
4
|
+
command/Api.py,sha256=-dGNE5StHlmN97g59mFraUZcaBEk5sBBMLShJoG4Yb8,961
|
5
|
+
command/Base.py,sha256=OqN_O8wAq_swESCBQ1bF5j4AT1K4PAjep68u-WxGT7U,785
|
6
|
+
command/BaseCommand.py,sha256=y0qD75qQ7b_phn3z2JSsraDpKovF_CEqiSUld_0LwrY,763
|
7
|
+
command/Build.py,sha256=8Gw1dSakBsgNiAw5rKLTuhf6qAXGONQ--_XCx5j2k9s,2551
|
8
|
+
command/Code.py,sha256=ltmU5htLvFShh-jgf0hdfKaENvkIE2vl_IGuGU_Z6K8,6725
|
9
|
+
command/Conf.py,sha256=afZMpJ-tS1wcY3s6cjNjmW6d8hihRw-mZvaS7hFV47w,2376
|
10
|
+
command/Count.py,sha256=xsYPRXP8TrW0T8P6uhjuovc28oR2iQgukL81eLoMpOc,976
|
11
|
+
command/Dev.py,sha256=gD_0AeQ0uPNCMsYAAIrCJBefKicMaLYHmFf2kog7H-Y,4218
|
12
|
+
command/Forget.py,sha256=iM8SdUMMdiw8Vbn3bJ6dgdnNXg-MIt3VM4G1ix3Kei4,1058
|
13
|
+
command/Import.py,sha256=4jNHpKSn_vjCUC1GUY1ZiLiMpSJuWyxLYJBi2W_jfeQ,3649
|
14
|
+
command/List.py,sha256=L2eTIxivZqalXQ4TwdSukGXVJ60bnPN0DA0MKdBfC84,2154
|
15
|
+
command/Merge.py,sha256=afiEZaY7BPwV91S0T0KbZJ7JHh-BhoAvmQhbzyGZZJo,1069
|
16
|
+
command/Model.py,sha256=P6Eo61zOj--C565m7nYe6lUnJJWr0utw7Eavlpt35VA,1195
|
17
|
+
command/Models.py,sha256=wzJqqdvPr-7vn4F_zqKPr7f70qHe1k7nGtteEjRPoz0,897
|
18
|
+
command/Modify.py,sha256=gRqbBdrUeRt1xhdAPNyiqgStTC3zrsm0EWng4FbwWgM,1256
|
19
|
+
command/Module.py,sha256=LKBCYagACPLqSC4emRXszX_f3lvhlmD9Kgh0kzCto8I,1260
|
20
|
+
command/New.py,sha256=ojmlN1YEs71uwouLDuSO_Eox4PDcTAZ8Sw32xWlrjWA,1137
|
21
|
+
command/OpenApi.py,sha256=G8R_Dc8hPLCgWZAMNHIgHN9JBfnfDrDdT2ie0a-Rrx4,4321
|
22
|
+
command/Question.py,sha256=vH04VrSXak4rOnYvV2e1eTGScli-_vIPyA9NR8PlmIA,3728
|
23
|
+
command/Remove.py,sha256=vkBeD641MvbR9YwwXpq2Cej36QWwt-VTzn8XBDpxmpE,2356
|
24
|
+
command/Rename.py,sha256=XOYAHkckYw5m4Vr_XomjkyhZT2QGlmv7yZnFUW38-3w,2186
|
25
|
+
command/Rewrite.py,sha256=yh7IPjtN7y0YzXs9K-I5E47SRVziI7bp0gis_8S_PGM,3111
|
26
|
+
command/Schema.py,sha256=U6SH_fTfEprIvvX8eDmHoMC4B6AfaGMrR17co13JO2M,1199
|
27
|
+
command/Schemas.py,sha256=d4zgLFrXaaBSuAX8ouy429DXiWnx6uwEeFUDWAr4NmA,900
|
28
|
+
command/Show.py,sha256=oNGKeNfEo6Qz1n4rJIRjlLuHWHWs5lB0TWE8Vn3hE2U,1190
|
29
|
+
command/Test.py,sha256=2zfxSTm-lwvzERTZNgD99z-AtOWb4RdAN1B93aa-UEk,1194
|
30
|
+
command/Tests.py,sha256=1l8iJs2W6fJDKMPL9Qdx7Qzm2I3azg_esthrZihK-S4,897
|
31
|
+
command/Tree.py,sha256=JWvUimeHWY5-6vEh6axTkhAdI-dVTxbKSjx_4isAAx8,3041
|
32
|
+
command/WarGames.py,sha256=vgMXSddUEU_PwDKyI7K0j-FN7uPs5jznfRj-CWh78FI,1280
|
33
|
+
command/auth/Auth.py,sha256=taUwmwAsJWN19oKmjgVGhPA_A8vj6vQLmNUVkuiqfjg,666
|
34
|
+
command/auth/Login.py,sha256=C3ZzV-Pp1C4RtAhpJ3IkJIwfgRY8pcUQmZRyMLT5hpU,454
|
35
|
+
command/auth/Logout.py,sha256=kxyHEGUXp4Ql6VS9R0eQfZqRDf8yhAslZNXExwh1gjY,199
|
36
|
+
command/tests/test_command_BaseCommand.py,sha256=BCeceiGl6ljjxkPiHMKzzrzjK1BUPWTHu9fTwGIETJI,350
|
37
|
+
command/tests/test_command_Conf.py,sha256=4tgWLoIYNuv-bmCAFFy2Kl9nau5KtCwKJMKwMCfL8ow,569
|
38
|
+
conf/Api.py,sha256=GM9okYs1A8ujPjDwzziOoQpqRYFkr-dz5pgkfb6j4DI,59
|
39
|
+
conf/Code.py,sha256=3Bd5kxCbgWaUOyYLRejOO_SqM9spGk1dYAf2hYzuDSw,199
|
40
|
+
conf/Custom.py,sha256=7S5v3bQK3UKuGUMTrAJeubWqszDtMlJI19-yOXk1TFs,101
|
41
|
+
conf/Datastore.py,sha256=PVAnysrk4wH1oCWxTUaakH2_x83Zpm4vzD1ELhfMDSw,90
|
42
|
+
conf/Dependencies.py,sha256=DZxyFtDR_3QpmsZbHApJFSeA7uYrMX1Bdx4lZKJ49Uo,891
|
43
|
+
conf/Dev.py,sha256=xWccZPN5lW2j9O5ZfBDS9gMmxf75AhjGaDUnw0abEyo,316
|
44
|
+
conf/Frameworks.py,sha256=Dv5iqeVe0JmNCKX5a-6S_dCrx7WZyI3qkTAFX6JWfDU,173
|
45
|
+
conf/Modeler.py,sha256=RayW3VFD_2nCFXZepfEcCXTUX2tWd7WtOjHULNVCai8,67
|
46
|
+
conf/Paths.py,sha256=NHJ_YLzmTIUUVLvtZornRdl1xPSluSmpFlMNsnqonxA,192
|
47
|
+
conf/Platform.py,sha256=ai7bLab2Ak_zWiANJH78Pj3YjTlTCQ1EEtkFaVDijOc,307
|
48
|
+
conf/Project.py,sha256=2lc_rr7giu1aGA4Ue4sU3Ey8-_yB2orLM1cw8f9zcdo,440
|
49
|
+
conf/Version.py,sha256=S_mJGw2v6jONwOHFgzEGwVDr-Ng4M4a3Z6CPrF38TzM,33
|
50
|
+
conf/dev/Api.py,sha256=EKZwy-3h7NxLdP6AYtwyTpJhD1kdQN6gVLuWw4_2KC8,158
|
51
|
+
conf/dev/Base.py,sha256=HisA87syPa5sJFjfjyxWRkLIKuVM5CtAkwW3f2zJx5Y,72
|
52
|
+
conf/dev/Model.py,sha256=HbHRX3VDxR7hXlzuxkKw4Bf7FH6XMfQ96k9BeIUoBf4,73
|
53
|
+
conf/dev/Schema.py,sha256=kOSlX1jEyVb82xd8TO8jEAimLcaefIFJr6d2JYvyTqg,74
|
54
|
+
conf/tests/test_conf_Dependencies.py,sha256=zmUFIANwpmFSMeEV5CllJstaqSSOBh9-Vgk-nETdlx0,109
|
55
|
+
conf/tests/test_conf_Platform.py,sha256=amq1YqxHOXimIP6eIoSg-hAKZ8S68cDAXRdNEaTkdfw,131
|
56
|
+
core/CommandRouter.py,sha256=fIzXKcGciMDHuXLkb6tp_N6sKs5SoqduCt-F1FE2U_c,9169
|
57
|
+
core/Configuration.py,sha256=Rw8g0W11BK1TW7WdWef6tIB4YVLuRGiUtn-VjL8OFu0,13881
|
58
|
+
core/Conversation.py,sha256=l9-8laUpHMtg14o4hzEho_CAX4Ahh2niVKUF3-0milI,8106
|
59
|
+
core/Env.py,sha256=ulL7y1xqlz6Mrg_hVUM3NzSumDCI2B1Zjfz9StT2Ju0,413
|
60
|
+
core/Memory.py,sha256=A7YtZFZwHqYpTFODsms8r_RNFNj3l-HKmaD8DhKH6So,3910
|
61
|
+
core/TimeKeeper.py,sha256=0mzs04wizjGEJbiQFWZyi4ja4XgeJaDqc0JzPCHp9po,250
|
62
|
+
core/utils.py,sha256=KTnPvA3sUYnLFTZG7Tke5YEdls8Da0rNbeaOm8hapiU,408
|
63
|
+
data/default-ref-table.tmpl,sha256=cVqjTsmHDjmTGrbDEpNHaDG-GX1iWMzsQDXk5TASEXg,123
|
64
|
+
data/default-table.tmpl,sha256=4t7SmXBuZN4nV5SjuQp6PBdo0-c3hdRnl8TQ2wdaS3w,247
|
65
|
+
db/TableExceptions.py,sha256=F1NGHDhusg9E_3tLez1_abrbANtWyR0UtC_wE9CwNFE,137
|
66
|
+
db/tests/test_db_TableExceptions.py,sha256=siPrXUBenRHW5nOO-n1eExTwgaJgZASAYdhDJXeXTJg,215
|
67
|
+
dev/Dev.py,sha256=QWdzf1mvi95WCEMHnlnk8Xj5k75mBQE3-hTH3yiFESE,2888
|
68
|
+
display/Header.py,sha256=moTxePVMNhtpeFtcI9EhnnLSK1gHIQiwYiWQtBPq_bY,298
|
69
|
+
display/WorkspaceFooter.py,sha256=1-PsPtLcC7xUZLwufSSaVo9caXuyZEwfR_iZatxwHF4,316
|
70
|
+
display/WorkspaceHeader.py,sha256=1oyyhZJF6C0SUCY2Cs_VkXt5Plp8xLb51XWa278l9mo,217
|
71
|
+
display/tests/test_display_Header.py,sha256=rQ7ip3ViJ62H9sFFWGjsLEn8c4C2s4KJpFhaeah4crY,317
|
72
|
+
display/tests/test_display_WorkspaceFooter.py,sha256=fDxXdwDmQLIRWYIBHbh32gfy2eW6Nlc4uq3wCOtGLIM,352
|
73
|
+
display/tests/test_display_WorkspaceHeader.py,sha256=Mhloli8KkyVFqv3-Ci4CDggXjrdJ5xebyZmw4foxsuE,309
|
74
|
+
lang/Python.py,sha256=qplU7xoplAIwWTTUSP1RcG3eMhHNUcbyJxCh1yZsXP8,1672
|
75
|
+
lang/tests/test_lang_Python.py,sha256=nulN-VSftAG2BM9HGFUP2RGUHebJAOCWIVPLbHY96Uk,1961
|
76
|
+
services/auth/Server.py,sha256=s5qNHxhY-ySSGa2RaK4zZIS3K908ulihx35d2F2Xg2k,1973
|
77
|
+
services/code/context/schema/DataDictionary.py,sha256=zWLzxOzW8iMHxfXPEwnnbruEAtFa8j1UpghNd4AHzfA,369
|
78
|
+
services/code/context/schema/EntityKeys.py,sha256=c8psaGfKseGN9V84xTjotgoLNs41sshbgX9K6ToFXHI,1548
|
79
|
+
services/code/context/schema/Manager.py,sha256=rzj4eTfLn2NDJVop4VWqedNZ6oN0ST1hXqK54UwHe5A,892
|
80
|
+
services/code/context/schema/tests/test_code_context_schema_DataDictionary.py,sha256=ASqifx7re5BU2RDKV3S0T00jxQTEiGEXa7rRcOeqa8E,357
|
81
|
+
services/code/context/schema/tests/test_code_context_schema_EntityKeys.py,sha256=vdynazkI_TMGo5TVvhDeAelU08FrXOKMHx-jF05jOs0,2086
|
82
|
+
services/code/context/schema/tests/test_code_context_schema_Manager.py,sha256=xVGeYj838VwhLNVIWYBDijBO7ObIPfSfVrU0DUlLweo,1216
|
83
|
+
services/code/customization/Authenticator.py,sha256=5qnBjO_U7GhuQkC0boGgjqo5YTe-axyBWkl2ggkLg2I,1565
|
84
|
+
services/code/customization/BaseCustomization.py,sha256=YZT3yP6cObTTPWjIvOyt5Cf6sRNVHtEXDJEmtcRRrzc,286
|
85
|
+
services/code/customization/CustomizationManager.py,sha256=U4TFhIGUyUtJfeP72Ke9fxVTR3sonRDU2lFFLprCq68,570
|
86
|
+
services/code/customization/tests/test_code_customization_Authenticator.py,sha256=eKOZ1F6zpSQsLo8bpjvcYozlGGGv8Gll7MSMXBWyUTs,1935
|
87
|
+
services/code/customization/tests/test_code_customization_BaseCustomization.py,sha256=RUTepr2upveeEZowszk8HEEVBQ7y2MQin_Sh5BhKEAI,398
|
88
|
+
structure/Entity.py,sha256=iDEtPy0fEAniABxffLxiYF6wWHQdrIWgW4L_-gB4hOA,3518
|
89
|
+
structure/testing.py,sha256=NAXg4JWb_ysS-OCWZyJ4413vv7FnnWCyjD9Tj4dK_VM,7545
|
90
|
+
structure/constraints/ReferenceConstraint.py,sha256=5zzKk--A2Bu1ZsN8QqS4jNILwq_BhOrV-f26WHKz5I0,1145
|
91
|
+
structure/keys/ForeignKey.py,sha256=1XN_XssLz6NcQp3vf91TrBZ7006xZKnPnTexu-nvpKQ,1230
|
92
|
+
structure/keys/Index.py,sha256=k5QfUyQM6hRkCNq1NtWWuAGxElmG4bXSCSRivzjr9g4,1694
|
93
|
+
structure/keys/IndexAttribute.py,sha256=GL-ma2v_GidZ6jjIlFc6IWKe4Gtg4UJUlqf1cYisqS0,298
|
94
|
+
structure/keys/tests/test_ForeignKey.py,sha256=rcNEgHpYjg5fYsbSHa1zd_N09NFRRyimDhVSnd13RQs,2261
|
95
|
+
structure/keys/tests/test_Index.py,sha256=0ZFHEnU5DJBtxG2TCavVD13Rq6aloUXPFM1bspWhbXg,2163
|
96
|
+
structure/keys/tests/test_IndexAttribute.py,sha256=_v3aKmL06cgXuV3xLXJMdp-8oPxHStj7qymtF3HtGrQ,381
|
97
|
+
structure/tests/test_Entity.py,sha256=MYog9b_IV3gbfYx9_hPmCgX3JNPz0t6cXQ-LU1WobjE,3117
|
98
|
+
gibson_cli-0.1.0.dist-info/METADATA,sha256=OMPI6DftiUJ_LO30DLGRDp9-d9nwswwLVQb9Lr77x2I,10886
|
99
|
+
gibson_cli-0.1.0.dist-info/WHEEL,sha256=Wyh-_nZ0DJYolHNn1_hMa4lM7uDedD_RGVwbmTjyItk,91
|
100
|
+
gibson_cli-0.1.0.dist-info/entry_points.txt,sha256=VAGCYo_zQgGI5bYR4Ql4rHhl5Zt7iA-Irt1v4iriLvQ,43
|
101
|
+
gibson_cli-0.1.0.dist-info/top_level.txt,sha256=e26JAjLAeXm2tl9nuW9OxrRvzkIXNYlXnHo-Yf5ZtnE,70
|
102
|
+
gibson_cli-0.1.0.dist-info/RECORD,,
|
lang/Python.py
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
import os
|
2
|
+
|
3
|
+
|
4
|
+
class Python:
|
5
|
+
def define_python_path(self, paths: list):
|
6
|
+
additions = []
|
7
|
+
for entry in paths:
|
8
|
+
path = self.make_python_path(entry)
|
9
|
+
if path is not None:
|
10
|
+
add_path = True
|
11
|
+
for addition in additions:
|
12
|
+
if addition in path:
|
13
|
+
add_path = False
|
14
|
+
break
|
15
|
+
|
16
|
+
if add_path:
|
17
|
+
additions.append(path)
|
18
|
+
|
19
|
+
if additions == []:
|
20
|
+
return None
|
21
|
+
|
22
|
+
return ":".join(additions)
|
23
|
+
|
24
|
+
def make_import_path(self, os_path):
|
25
|
+
if os_path is None:
|
26
|
+
return None
|
27
|
+
|
28
|
+
os_path = os.path.expandvars(os_path)
|
29
|
+
|
30
|
+
pythonpath = os.environ["PYTHONPATH"].split(":")
|
31
|
+
for entry in pythonpath:
|
32
|
+
path = os_path.replace(entry, "")
|
33
|
+
if path != os_path:
|
34
|
+
path = path.replace("/", ".")
|
35
|
+
if path in [None, ""]:
|
36
|
+
# There is no import path, the file is at the top level. Note,
|
37
|
+
# this is explicitly not None as that will cause the back end
|
38
|
+
# to incorrectly exclude the import.
|
39
|
+
return ""
|
40
|
+
|
41
|
+
if path[0] == ".":
|
42
|
+
path = path[1:]
|
43
|
+
|
44
|
+
return path
|
45
|
+
|
46
|
+
raise RuntimeError(
|
47
|
+
"cannot make import path; please execute:\n\n"
|
48
|
+
+ f" export PYTHONPATH=$PYTHONPATH:{os_path}\n"
|
49
|
+
)
|
50
|
+
|
51
|
+
def make_python_path(self, path):
|
52
|
+
pythonpath = os.environ["PYTHONPATH"].split(":")
|
53
|
+
for entry in pythonpath:
|
54
|
+
if entry in path:
|
55
|
+
return None
|
56
|
+
|
57
|
+
return path
|
@@ -0,0 +1,70 @@
|
|
1
|
+
import os
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
|
5
|
+
from lang.Python import Python
|
6
|
+
|
7
|
+
|
8
|
+
def test_make_python_path_no_match():
|
9
|
+
assert Python().make_python_path("/a/b/c") == "/a/b/c"
|
10
|
+
|
11
|
+
|
12
|
+
def test_make_python_path_match():
|
13
|
+
last_pythonpath = os.environ["PYTHONPATH"]
|
14
|
+
|
15
|
+
try:
|
16
|
+
os.environ["PYTHONPATH"] = "/a/b/c:/d/e/f"
|
17
|
+
assert Python().make_python_path("/a/b/c/g") is None
|
18
|
+
assert Python().make_python_path("/d/e/f/h") is None
|
19
|
+
finally:
|
20
|
+
os.environ["PYTHONPATH"] = last_pythonpath
|
21
|
+
|
22
|
+
|
23
|
+
def test_define_python_path():
|
24
|
+
last_pythonpath = os.environ["PYTHONPATH"]
|
25
|
+
|
26
|
+
try:
|
27
|
+
os.environ["PYTHONPATH"] = "/a/b/c:/d/e/f"
|
28
|
+
assert Python().define_python_path(["/a/b/c", "/d/e/f"]) is None
|
29
|
+
assert Python().define_python_path(["/g/h/i", "/j/k/l"]) == "/g/h/i:/j/k/l"
|
30
|
+
finally:
|
31
|
+
os.environ["PYTHONPATH"] = last_pythonpath
|
32
|
+
|
33
|
+
|
34
|
+
def test_make_import_path_exceptions():
|
35
|
+
with pytest.raises(RuntimeError) as e:
|
36
|
+
Python().make_import_path("/a/b/c")
|
37
|
+
|
38
|
+
assert str(e.value) == (
|
39
|
+
"""cannot make import path; please execute:
|
40
|
+
|
41
|
+
export PYTHONPATH=$PYTHONPATH:/a/b/c
|
42
|
+
"""
|
43
|
+
)
|
44
|
+
|
45
|
+
|
46
|
+
def test_make_import_path():
|
47
|
+
last_pythonpath = os.environ["PYTHONPATH"]
|
48
|
+
|
49
|
+
try:
|
50
|
+
os.environ["PYTHONPATH"] = "/a/b/c"
|
51
|
+
assert Python().make_import_path(None) is None
|
52
|
+
assert Python().make_import_path("/a/b/c/services/base") == "services.base"
|
53
|
+
assert Python().make_import_path("/a/b/c/services/base/model") == (
|
54
|
+
"services.base.model"
|
55
|
+
)
|
56
|
+
assert Python().make_import_path("/a/b/c/services/base/schema") == (
|
57
|
+
"services.base.schema"
|
58
|
+
)
|
59
|
+
finally:
|
60
|
+
os.environ["PYTHONPATH"] = last_pythonpath
|
61
|
+
|
62
|
+
|
63
|
+
def test_make_import_path_match_on_top_level():
|
64
|
+
last_pythonpath = os.environ["PYTHONPATH"]
|
65
|
+
|
66
|
+
try:
|
67
|
+
os.environ["PYTHONPATH"] = "/a/b/c"
|
68
|
+
assert Python().make_import_path("/a/b/c") == ""
|
69
|
+
finally:
|
70
|
+
os.environ["PYTHONPATH"] = last_pythonpath
|
services/auth/Server.py
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
import webbrowser
|
2
|
+
|
3
|
+
import time
|
4
|
+
from http.server import HTTPServer, BaseHTTPRequestHandler
|
5
|
+
from threading import Thread
|
6
|
+
from socket import socket
|
7
|
+
from urllib.parse import urlparse, parse_qs
|
8
|
+
|
9
|
+
|
10
|
+
# HTTP handler for processing the token sent from the web browser
|
11
|
+
class Handler(BaseHTTPRequestHandler):
|
12
|
+
def do_GET(self):
|
13
|
+
url = urlparse(self.path)
|
14
|
+
params = parse_qs(url.query)
|
15
|
+
token = params.get("token", [""])[0]
|
16
|
+
|
17
|
+
if token:
|
18
|
+
self.respond(200, "OK")
|
19
|
+
self.server.token = token
|
20
|
+
else:
|
21
|
+
self.respond(400, "Bad Request")
|
22
|
+
|
23
|
+
self.server._stop()
|
24
|
+
|
25
|
+
# Suppress logging
|
26
|
+
def log_message(self, format, *args):
|
27
|
+
pass
|
28
|
+
|
29
|
+
# Format the response
|
30
|
+
def respond(self, code, message):
|
31
|
+
self.send_response(code)
|
32
|
+
self.send_header("Content-type", "text")
|
33
|
+
self.send_header("Access-Control-Allow-Origin", "*")
|
34
|
+
self.send_header(
|
35
|
+
"Access-Control-Allow-Headers",
|
36
|
+
"Origin, X-Requested-With, Content-Type, Accept",
|
37
|
+
)
|
38
|
+
self.end_headers()
|
39
|
+
self.wfile.write(message.encode("utf8"))
|
40
|
+
|
41
|
+
|
42
|
+
# Temporary HTTP server to handle the login process
|
43
|
+
class Server(HTTPServer):
|
44
|
+
port = None
|
45
|
+
token = None
|
46
|
+
thread = None
|
47
|
+
|
48
|
+
def __init__(self, app_domain: str):
|
49
|
+
sock = socket()
|
50
|
+
sock.bind(("", 0))
|
51
|
+
self.port = sock.getsockname()[1]
|
52
|
+
super().__init__(("localhost", self.port), Handler)
|
53
|
+
|
54
|
+
self.app_domain = app_domain
|
55
|
+
|
56
|
+
def get_token(self):
|
57
|
+
self._start()
|
58
|
+
self._open_browser()
|
59
|
+
|
60
|
+
while self.thread is not None:
|
61
|
+
time.sleep(1)
|
62
|
+
|
63
|
+
return self.token
|
64
|
+
|
65
|
+
def _open_browser(self):
|
66
|
+
webbrowser.open(f"{self.app_domain}/signup?cli={self.port}")
|
67
|
+
|
68
|
+
def _start(self):
|
69
|
+
thread = Thread(target=self.serve_forever)
|
70
|
+
thread.start()
|
71
|
+
self.thread = thread
|
72
|
+
|
73
|
+
def _stop(self):
|
74
|
+
Thread(target=self.shutdown).start()
|
75
|
+
self.thread = None
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class DataDictionary:
|
2
|
+
def __init__(self):
|
3
|
+
self.__attributes = {}
|
4
|
+
|
5
|
+
def from_code_writer_schema_context(self, data: dict):
|
6
|
+
for name, definition in data.items():
|
7
|
+
self.__attributes[name] = definition
|
8
|
+
|
9
|
+
return self
|
10
|
+
|
11
|
+
def get_attribute_definition(self, attribute_name):
|
12
|
+
return self.__attributes.get(attribute_name, None)
|
@@ -0,0 +1,49 @@
|
|
1
|
+
from structure.constraints.ReferenceConstraint import ReferenceConstraint
|
2
|
+
from structure.keys.ForeignKey import ForeignKey
|
3
|
+
from structure.keys.Index import Index
|
4
|
+
|
5
|
+
|
6
|
+
class EntityKeys:
|
7
|
+
def __init__(self):
|
8
|
+
self.__entity_name = None
|
9
|
+
self.__index = []
|
10
|
+
self.__primary = []
|
11
|
+
self.__unique = []
|
12
|
+
|
13
|
+
def best_sql_foreign_key(self):
|
14
|
+
elements = []
|
15
|
+
if self.__primary != []:
|
16
|
+
elements = self.__primary
|
17
|
+
elif self.__unique != []:
|
18
|
+
elements = self.__unique
|
19
|
+
|
20
|
+
if elements == []:
|
21
|
+
return None
|
22
|
+
|
23
|
+
reference_constraint = ReferenceConstraint()
|
24
|
+
reference_constraint.attributes = []
|
25
|
+
reference_constraint.references = self.__entity_name
|
26
|
+
|
27
|
+
foreign_key = ForeignKey()
|
28
|
+
foreign_key.attributes = []
|
29
|
+
foreign_key.reference = reference_constraint
|
30
|
+
|
31
|
+
index = Index()
|
32
|
+
|
33
|
+
data_types = []
|
34
|
+
for element in elements:
|
35
|
+
foreign_key.attributes.append(f"{self.__entity_name}_{element['name']}")
|
36
|
+
reference_constraint.attributes.append(element["name"])
|
37
|
+
index.add_attribute(f"{self.__entity_name}_{element['name']}")
|
38
|
+
data_types.append(element["data"]["type"])
|
39
|
+
|
40
|
+
return foreign_key, index, data_types
|
41
|
+
|
42
|
+
def from_code_writer_schema_context(
|
43
|
+
self, entity_name: str, index: list, primary: list, unique: list
|
44
|
+
):
|
45
|
+
self.__entity_name = entity_name
|
46
|
+
self.__index = index
|
47
|
+
self.__primary = primary
|
48
|
+
self.__unique = unique
|
49
|
+
return self
|
@@ -0,0 +1,28 @@
|
|
1
|
+
from services.code.context.schema.DataDictionary import DataDictionary
|
2
|
+
from services.code.context.schema.EntityKeys import EntityKeys
|
3
|
+
|
4
|
+
|
5
|
+
class Manager:
|
6
|
+
def __init__(self):
|
7
|
+
self.__entity_keys_map = {}
|
8
|
+
self.data_dictionary = DataDictionary()
|
9
|
+
self.json = None
|
10
|
+
|
11
|
+
def from_code_writer_schema_context(self, context: dict):
|
12
|
+
self.data_dictionary.from_code_writer_schema_context(
|
13
|
+
context["data"]["dictionary"]
|
14
|
+
)
|
15
|
+
|
16
|
+
for entity_name, keys in context["keys"].items():
|
17
|
+
self.__entity_keys_map[
|
18
|
+
entity_name
|
19
|
+
] = EntityKeys().from_code_writer_schema_context(
|
20
|
+
entity_name, keys["index"], keys["primary"], keys["unique"]
|
21
|
+
)
|
22
|
+
|
23
|
+
self.json = context
|
24
|
+
|
25
|
+
return self
|
26
|
+
|
27
|
+
def get_entity_keys(self, entity_name):
|
28
|
+
return self.__entity_keys_map.get(entity_name, None)
|
@@ -0,0 +1,8 @@
|
|
1
|
+
from services.code.context.schema.DataDictionary import DataDictionary
|
2
|
+
|
3
|
+
|
4
|
+
def test_configure():
|
5
|
+
data_dict = DataDictionary().from_code_writer_schema_context({"a": "b", "c": "d"})
|
6
|
+
assert data_dict.get_attribute_definition("z") is None
|
7
|
+
assert data_dict.get_attribute_definition("a") == "b"
|
8
|
+
assert data_dict.get_attribute_definition("c") == "d"
|
@@ -0,0 +1,52 @@
|
|
1
|
+
from services.code.context.schema.EntityKeys import EntityKeys
|
2
|
+
from structure.constraints.ReferenceConstraint import ReferenceConstraint
|
3
|
+
from structure.keys.ForeignKey import ForeignKey
|
4
|
+
from structure.keys.Index import Index
|
5
|
+
|
6
|
+
|
7
|
+
def test_best_sql_foreign_key_no_match():
|
8
|
+
assert EntityKeys().best_sql_foreign_key() is None
|
9
|
+
|
10
|
+
|
11
|
+
def test_best_sql_foreign_key_choose_primary():
|
12
|
+
ek = EntityKeys().from_code_writer_schema_context(
|
13
|
+
"abc",
|
14
|
+
[],
|
15
|
+
[
|
16
|
+
{"data": {"type": "pk_type_1"}, "name": "pk_name_1"},
|
17
|
+
{"data": {"type": "pk_type_2"}, "name": "pk_name_2"},
|
18
|
+
],
|
19
|
+
[{"data": {"type": "uk_type_1"}, "name": "uk_name_1"}],
|
20
|
+
)
|
21
|
+
|
22
|
+
foreign_key, index, data_types = ek.best_sql_foreign_key()
|
23
|
+
assert isinstance(foreign_key, ForeignKey)
|
24
|
+
assert isinstance(foreign_key.reference, ReferenceConstraint)
|
25
|
+
assert isinstance(index, Index)
|
26
|
+
assert foreign_key.attributes == ["abc_pk_name_1", "abc_pk_name_2"]
|
27
|
+
assert foreign_key.reference.attributes == ["pk_name_1", "pk_name_2"]
|
28
|
+
assert foreign_key.reference.references == "abc"
|
29
|
+
assert len(index.attributes) == 2
|
30
|
+
assert index.attributes[0].name == "abc_pk_name_1"
|
31
|
+
assert index.attributes[1].name == "abc_pk_name_2"
|
32
|
+
assert len(data_types) == 2
|
33
|
+
assert data_types[0] == "pk_type_1"
|
34
|
+
assert data_types[1] == "pk_type_2"
|
35
|
+
|
36
|
+
|
37
|
+
def test_best_sql_foreign_key_choose_unique():
|
38
|
+
ek = EntityKeys().from_code_writer_schema_context(
|
39
|
+
"abc", [], [], [{"data": {"type": "uk_type_1"}, "name": "uk_name_1"}]
|
40
|
+
)
|
41
|
+
|
42
|
+
foreign_key, index, data_types = ek.best_sql_foreign_key()
|
43
|
+
assert isinstance(foreign_key, ForeignKey)
|
44
|
+
assert isinstance(foreign_key.reference, ReferenceConstraint)
|
45
|
+
assert isinstance(index, Index)
|
46
|
+
assert foreign_key.attributes == ["abc_uk_name_1"]
|
47
|
+
assert foreign_key.reference.attributes == ["uk_name_1"]
|
48
|
+
assert foreign_key.reference.references == "abc"
|
49
|
+
assert len(index.attributes) == 1
|
50
|
+
assert index.attributes[0].name == "abc_uk_name_1"
|
51
|
+
assert len(data_types) == 1
|
52
|
+
assert data_types[0] == "uk_type_1"
|
@@ -0,0 +1,34 @@
|
|
1
|
+
from services.code.context.schema.EntityKeys import EntityKeys
|
2
|
+
from services.code.context.schema.Manager import Manager
|
3
|
+
|
4
|
+
|
5
|
+
def test_get_entity_keys_no_such_entity_name():
|
6
|
+
assert Manager().get_entity_keys("abc") is None
|
7
|
+
|
8
|
+
|
9
|
+
def test_from_code_writer_schema_context_data_dictionary():
|
10
|
+
context = {"data": {"dictionary": {"abc": "def", "ghi": "jkl"}}, "keys": {}}
|
11
|
+
|
12
|
+
manager = Manager().from_code_writer_schema_context(context)
|
13
|
+
assert manager.data_dictionary.get_attribute_definition("abc") == "def"
|
14
|
+
assert manager.data_dictionary.get_attribute_definition("ghi") == "jkl"
|
15
|
+
|
16
|
+
|
17
|
+
def test_from_code_writer_schema_context_get_entity_keys():
|
18
|
+
context = {
|
19
|
+
"data": {"dictionary": {}},
|
20
|
+
"keys": {
|
21
|
+
"abc_def": {
|
22
|
+
"index": [],
|
23
|
+
"primary": [
|
24
|
+
{"data": {"type": "pk_type_1"}, "name": "pk_name_1"},
|
25
|
+
{"data": {"type": "pk_type_2"}, "name": "pk_name_2"},
|
26
|
+
],
|
27
|
+
"unique": [],
|
28
|
+
}
|
29
|
+
},
|
30
|
+
}
|
31
|
+
|
32
|
+
manager = Manager().from_code_writer_schema_context(context)
|
33
|
+
assert manager.get_entity_keys("def_ghi") is None
|
34
|
+
assert isinstance(manager.get_entity_keys("abc_def"), EntityKeys)
|
@@ -0,0 +1,51 @@
|
|
1
|
+
import os
|
2
|
+
|
3
|
+
from core.Configuration import Configuration
|
4
|
+
from services.code.customization.BaseCustomization import BaseCustomization
|
5
|
+
|
6
|
+
|
7
|
+
class Authenticator(BaseCustomization):
|
8
|
+
def __init__(self, configuration: Configuration):
|
9
|
+
super().__init__(configuration)
|
10
|
+
self.__link_target = None
|
11
|
+
self.__file_contents = None
|
12
|
+
|
13
|
+
def __get_file_name(self):
|
14
|
+
return (
|
15
|
+
self.configuration.project.dev.api.path
|
16
|
+
+ "/"
|
17
|
+
+ self.configuration.project.dev.api.version
|
18
|
+
+ "/Authenticator.py"
|
19
|
+
)
|
20
|
+
|
21
|
+
def preserve(self):
|
22
|
+
authenticator_file_name = self.__get_file_name()
|
23
|
+
|
24
|
+
if os.path.islink(authenticator_file_name):
|
25
|
+
self.__link_target = os.readlink(authenticator_file_name)
|
26
|
+
elif os.path.isfile(authenticator_file_name):
|
27
|
+
with open(authenticator_file_name, "r") as f:
|
28
|
+
self.__file_contents = f.read()
|
29
|
+
|
30
|
+
return self
|
31
|
+
|
32
|
+
def restore(self):
|
33
|
+
authenticator_file_name = self.__get_file_name()
|
34
|
+
|
35
|
+
if self.__link_target is not None:
|
36
|
+
try:
|
37
|
+
os.unlink(authenticator_file_name)
|
38
|
+
except FileNotFoundError:
|
39
|
+
pass
|
40
|
+
|
41
|
+
os.symlink(self.__link_target, authenticator_file_name)
|
42
|
+
elif self.__file_contents is not None:
|
43
|
+
try:
|
44
|
+
os.unlink(authenticator_file_name)
|
45
|
+
except FileNotFoundError:
|
46
|
+
pass
|
47
|
+
|
48
|
+
with open(authenticator_file_name, "w") as f:
|
49
|
+
f.write(self.__file_contents)
|
50
|
+
|
51
|
+
return self
|
@@ -0,0 +1,12 @@
|
|
1
|
+
from core.Configuration import Configuration
|
2
|
+
|
3
|
+
|
4
|
+
class BaseCustomization:
|
5
|
+
def __init__(self, configuration: Configuration):
|
6
|
+
self.configuration = configuration
|
7
|
+
|
8
|
+
def preserve(self):
|
9
|
+
raise NotImplementedError
|
10
|
+
|
11
|
+
def restore(self):
|
12
|
+
raise NotImplementedError
|
@@ -0,0 +1,20 @@
|
|
1
|
+
from core.Configuration import Configuration
|
2
|
+
from services.code.customization.Authenticator import Authenticator
|
3
|
+
|
4
|
+
|
5
|
+
class CustomizationManager:
|
6
|
+
def __init__(self, configuration: Configuration):
|
7
|
+
self.configuration = configuration
|
8
|
+
self.customizations = [Authenticator(self.configuration)]
|
9
|
+
|
10
|
+
def preserve(self):
|
11
|
+
for customization in self.customizations:
|
12
|
+
customization.preserve()
|
13
|
+
|
14
|
+
return self
|
15
|
+
|
16
|
+
def restore(self):
|
17
|
+
for customization in self.customizations:
|
18
|
+
customization.restore()
|
19
|
+
|
20
|
+
return self
|
@@ -0,0 +1,53 @@
|
|
1
|
+
import os
|
2
|
+
import shutil
|
3
|
+
|
4
|
+
from core.Configuration import Configuration
|
5
|
+
from services.code.customization.Authenticator import Authenticator
|
6
|
+
|
7
|
+
|
8
|
+
def test_link_target():
|
9
|
+
configuration = Configuration()
|
10
|
+
configuration.project.dev.api.path = "/tmp/gibsonai-unit-test"
|
11
|
+
configuration.project.dev.api.version = "v1"
|
12
|
+
|
13
|
+
try:
|
14
|
+
os.makedirs("/tmp/gibsonai-unit-test/v1")
|
15
|
+
|
16
|
+
os.symlink("/etc/passwd", "/tmp/gibsonai-unit-test/v1/Authenticator.py")
|
17
|
+
|
18
|
+
authenticator = Authenticator(configuration).preserve()
|
19
|
+
os.unlink("/tmp/gibsonai-unit-test/v1/Authenticator.py")
|
20
|
+
authenticator.restore()
|
21
|
+
|
22
|
+
assert os.path.islink("/tmp/gibsonai-unit-test/v1/Authenticator.py") is True
|
23
|
+
assert os.readlink("/tmp/gibsonai-unit-test/v1/Authenticator.py") == (
|
24
|
+
"/etc/passwd"
|
25
|
+
)
|
26
|
+
finally:
|
27
|
+
shutil.rmtree("/tmp/gibsonai-unit-test")
|
28
|
+
|
29
|
+
|
30
|
+
def test_file_contents():
|
31
|
+
configuration = Configuration()
|
32
|
+
configuration.project.dev.api.path = "/tmp/gibsonai-unit-test"
|
33
|
+
configuration.project.dev.api.version = "v1"
|
34
|
+
|
35
|
+
try:
|
36
|
+
os.makedirs("/tmp/gibsonai-unit-test/v1")
|
37
|
+
|
38
|
+
with open("/tmp/gibsonai-unit-test/v1/Authenticator.py", "w") as f:
|
39
|
+
f.write("abc def\nghi jkl")
|
40
|
+
|
41
|
+
authenticator = Authenticator(configuration).preserve()
|
42
|
+
os.unlink("/tmp/gibsonai-unit-test/v1/Authenticator.py")
|
43
|
+
assert os.path.islink("/tmp/gibsonai-unit-test/v1/Authenticator.py") is False
|
44
|
+
assert os.path.isfile("/tmp/gibsonai-unit-test/v1/Authenticator.py") is False
|
45
|
+
authenticator.restore()
|
46
|
+
|
47
|
+
assert os.path.islink("/tmp/gibsonai-unit-test/v1/Authenticator.py") is False
|
48
|
+
assert os.path.isfile("/tmp/gibsonai-unit-test/v1/Authenticator.py") is True
|
49
|
+
|
50
|
+
with open("/tmp/gibsonai-unit-test/v1/Authenticator.py", "r") as f:
|
51
|
+
assert f.read() == "abc def\nghi jkl"
|
52
|
+
finally:
|
53
|
+
shutil.rmtree("/tmp/gibsonai-unit-test")
|