gamsapi 52.5.0__cp312-cp312-win_amd64.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.
- gams/__init__.py +27 -0
- gams/_version.py +1 -0
- gams/connect/__init__.py +28 -0
- gams/connect/agents/__init__.py +24 -0
- gams/connect/agents/_excel/__init__.py +32 -0
- gams/connect/agents/_excel/excelagent.py +312 -0
- gams/connect/agents/_excel/workbook.py +155 -0
- gams/connect/agents/_sqlconnectors/__init__.py +42 -0
- gams/connect/agents/_sqlconnectors/_accesshandler.py +211 -0
- gams/connect/agents/_sqlconnectors/_databasehandler.py +250 -0
- gams/connect/agents/_sqlconnectors/_mysqlhandler.py +168 -0
- gams/connect/agents/_sqlconnectors/_postgreshandler.py +131 -0
- gams/connect/agents/_sqlconnectors/_pyodbchandler.py +112 -0
- gams/connect/agents/_sqlconnectors/_sqlalchemyhandler.py +74 -0
- gams/connect/agents/_sqlconnectors/_sqlitehandler.py +262 -0
- gams/connect/agents/_sqlconnectors/_sqlserverhandler.py +179 -0
- gams/connect/agents/concatenate.py +440 -0
- gams/connect/agents/connectagent.py +743 -0
- gams/connect/agents/csvreader.py +675 -0
- gams/connect/agents/csvwriter.py +151 -0
- gams/connect/agents/domainwriter.py +143 -0
- gams/connect/agents/excelreader.py +756 -0
- gams/connect/agents/excelwriter.py +467 -0
- gams/connect/agents/filter.py +223 -0
- gams/connect/agents/gamsreader.py +112 -0
- gams/connect/agents/gamswriter.py +239 -0
- gams/connect/agents/gdxreader.py +109 -0
- gams/connect/agents/gdxwriter.py +146 -0
- gams/connect/agents/labelmanipulator.py +303 -0
- gams/connect/agents/projection.py +539 -0
- gams/connect/agents/pythoncode.py +71 -0
- gams/connect/agents/rawcsvreader.py +248 -0
- gams/connect/agents/rawexcelreader.py +312 -0
- gams/connect/agents/schema/CSVReader.yaml +92 -0
- gams/connect/agents/schema/CSVWriter.yaml +44 -0
- gams/connect/agents/schema/Concatenate.yaml +52 -0
- gams/connect/agents/schema/DomainWriter.yaml +25 -0
- gams/connect/agents/schema/ExcelReader.yaml +121 -0
- gams/connect/agents/schema/ExcelWriter.yaml +78 -0
- gams/connect/agents/schema/Filter.yaml +74 -0
- gams/connect/agents/schema/GAMSReader.yaml +20 -0
- gams/connect/agents/schema/GAMSWriter.yaml +47 -0
- gams/connect/agents/schema/GDXReader.yaml +23 -0
- gams/connect/agents/schema/GDXWriter.yaml +32 -0
- gams/connect/agents/schema/LabelManipulator.yaml +99 -0
- gams/connect/agents/schema/Projection.yaml +24 -0
- gams/connect/agents/schema/PythonCode.yaml +6 -0
- gams/connect/agents/schema/RawCSVReader.yaml +34 -0
- gams/connect/agents/schema/RawExcelReader.yaml +42 -0
- gams/connect/agents/schema/SQLReader.yaml +75 -0
- gams/connect/agents/schema/SQLWriter.yaml +103 -0
- gams/connect/agents/sqlreader.py +301 -0
- gams/connect/agents/sqlwriter.py +276 -0
- gams/connect/connectdatabase.py +275 -0
- gams/connect/connectvalidator.py +93 -0
- gams/connect/errors.py +34 -0
- gams/control/__init__.py +136 -0
- gams/control/database.py +2231 -0
- gams/control/execution.py +1900 -0
- gams/control/options.py +2792 -0
- gams/control/workspace.py +1198 -0
- gams/core/__init__.py +24 -0
- gams/core/cfg/__init__.py +26 -0
- gams/core/cfg/_cfgmcc.cp312-win_amd64.pyd +0 -0
- gams/core/cfg/cfgmcc.py +519 -0
- gams/core/dct/__init__.py +26 -0
- gams/core/dct/_dctmcc.cp312-win_amd64.pyd +0 -0
- gams/core/dct/dctmcc.py +574 -0
- gams/core/embedded/__init__.py +26 -0
- gams/core/embedded/gamsemb.py +1024 -0
- gams/core/emp/__init__.py +24 -0
- gams/core/emp/emplexer.py +89 -0
- gams/core/emp/empyacc.py +281 -0
- gams/core/gdx/__init__.py +26 -0
- gams/core/gdx/_gdxcc.cp312-win_amd64.pyd +0 -0
- gams/core/gdx/gdxcc.py +866 -0
- gams/core/gev/__init__.py +26 -0
- gams/core/gev/_gevmcc.cp312-win_amd64.pyd +0 -0
- gams/core/gev/gevmcc.py +855 -0
- gams/core/gmd/__init__.py +26 -0
- gams/core/gmd/_gmdcc.cp312-win_amd64.pyd +0 -0
- gams/core/gmd/gmdcc.py +917 -0
- gams/core/gmo/__init__.py +26 -0
- gams/core/gmo/_gmomcc.cp312-win_amd64.pyd +0 -0
- gams/core/gmo/gmomcc.py +2046 -0
- gams/core/idx/__init__.py +26 -0
- gams/core/idx/_idxcc.cp312-win_amd64.pyd +0 -0
- gams/core/idx/idxcc.py +510 -0
- gams/core/numpy/__init__.py +29 -0
- gams/core/numpy/_gams2numpy.cp312-win_amd64.pyd +0 -0
- gams/core/numpy/gams2numpy.py +1048 -0
- gams/core/opt/__init__.py +26 -0
- gams/core/opt/_optcc.cp312-win_amd64.pyd +0 -0
- gams/core/opt/optcc.py +840 -0
- gams/engine/__init__.py +204 -0
- gams/engine/api/__init__.py +13 -0
- gams/engine/api/auth_api.py +7653 -0
- gams/engine/api/cleanup_api.py +751 -0
- gams/engine/api/default_api.py +887 -0
- gams/engine/api/hypercube_api.py +2629 -0
- gams/engine/api/jobs_api.py +5229 -0
- gams/engine/api/licenses_api.py +2220 -0
- gams/engine/api/namespaces_api.py +7783 -0
- gams/engine/api/usage_api.py +5627 -0
- gams/engine/api/users_api.py +5931 -0
- gams/engine/api_client.py +804 -0
- gams/engine/api_response.py +21 -0
- gams/engine/configuration.py +601 -0
- gams/engine/exceptions.py +216 -0
- gams/engine/models/__init__.py +86 -0
- gams/engine/models/bad_input.py +89 -0
- gams/engine/models/cleanable_job_result.py +104 -0
- gams/engine/models/cleanable_job_result_page.py +113 -0
- gams/engine/models/engine_license.py +107 -0
- gams/engine/models/files_not_found.py +93 -0
- gams/engine/models/forwarded_token_response.py +112 -0
- gams/engine/models/generic_key_value_pair.py +89 -0
- gams/engine/models/hypercube.py +160 -0
- gams/engine/models/hypercube_page.py +111 -0
- gams/engine/models/hypercube_summary.py +91 -0
- gams/engine/models/hypercube_token.py +97 -0
- gams/engine/models/identity_provider.py +107 -0
- gams/engine/models/identity_provider_ldap.py +121 -0
- gams/engine/models/identity_provider_oauth2.py +146 -0
- gams/engine/models/identity_provider_oauth2_scope.py +89 -0
- gams/engine/models/identity_provider_oauth2_with_secret.py +152 -0
- gams/engine/models/identity_provider_oidc.py +133 -0
- gams/engine/models/identity_provider_oidc_with_secret.py +143 -0
- gams/engine/models/inex.py +91 -0
- gams/engine/models/invitation.py +136 -0
- gams/engine/models/invitation_quota.py +106 -0
- gams/engine/models/invitation_token.py +87 -0
- gams/engine/models/job.py +165 -0
- gams/engine/models/job_no_text_entry.py +138 -0
- gams/engine/models/job_no_text_entry_page.py +111 -0
- gams/engine/models/license.py +91 -0
- gams/engine/models/log_piece.py +96 -0
- gams/engine/models/message.py +87 -0
- gams/engine/models/message_and_token.py +99 -0
- gams/engine/models/message_with_webhook_id.py +89 -0
- gams/engine/models/model_auth_token.py +87 -0
- gams/engine/models/model_configuration.py +125 -0
- gams/engine/models/model_default_instance.py +99 -0
- gams/engine/models/model_default_user_instance.py +98 -0
- gams/engine/models/model_hypercube_job.py +106 -0
- gams/engine/models/model_hypercube_usage.py +130 -0
- gams/engine/models/model_instance_info.py +116 -0
- gams/engine/models/model_instance_info_full.py +123 -0
- gams/engine/models/model_instance_pool_info.py +112 -0
- gams/engine/models/model_job_labels.py +179 -0
- gams/engine/models/model_job_usage.py +133 -0
- gams/engine/models/model_pool_usage.py +124 -0
- gams/engine/models/model_usage.py +115 -0
- gams/engine/models/model_user.py +96 -0
- gams/engine/models/model_userinstance_info.py +119 -0
- gams/engine/models/model_userinstancepool_info.py +95 -0
- gams/engine/models/model_version.py +91 -0
- gams/engine/models/models.py +120 -0
- gams/engine/models/namespace.py +104 -0
- gams/engine/models/namespace_quota.py +96 -0
- gams/engine/models/namespace_with_permission.py +96 -0
- gams/engine/models/not_found.py +91 -0
- gams/engine/models/password_policy.py +97 -0
- gams/engine/models/perm_and_username.py +89 -0
- gams/engine/models/quota.py +117 -0
- gams/engine/models/quota_exceeded.py +97 -0
- gams/engine/models/status_code_meaning.py +89 -0
- gams/engine/models/stream_entry.py +89 -0
- gams/engine/models/system_wide_license.py +92 -0
- gams/engine/models/text_entries.py +87 -0
- gams/engine/models/text_entry.py +101 -0
- gams/engine/models/time_span.py +95 -0
- gams/engine/models/time_span_pool_worker.py +99 -0
- gams/engine/models/token_forward_error.py +87 -0
- gams/engine/models/user.py +127 -0
- gams/engine/models/user_group_member.py +96 -0
- gams/engine/models/user_groups.py +108 -0
- gams/engine/models/vapid_info.py +87 -0
- gams/engine/models/webhook.py +138 -0
- gams/engine/models/webhook_parameterized_event.py +99 -0
- gams/engine/py.typed +0 -0
- gams/engine/rest.py +258 -0
- gams/magic/__init__.py +32 -0
- gams/magic/gams_magic.py +142 -0
- gams/magic/interactive.py +402 -0
- gams/tools/__init__.py +30 -0
- gams/tools/errors.py +34 -0
- gams/tools/toolcollection/__init__.py +24 -0
- gams/tools/toolcollection/alg/__init__.py +24 -0
- gams/tools/toolcollection/alg/rank.py +51 -0
- gams/tools/toolcollection/data/__init__.py +24 -0
- gams/tools/toolcollection/data/csvread.py +444 -0
- gams/tools/toolcollection/data/csvwrite.py +311 -0
- gams/tools/toolcollection/data/exceldump.py +47 -0
- gams/tools/toolcollection/data/sqlitewrite.py +276 -0
- gams/tools/toolcollection/gdxservice/__init__.py +24 -0
- gams/tools/toolcollection/gdxservice/gdxencoding.py +104 -0
- gams/tools/toolcollection/gdxservice/gdxrename.py +94 -0
- gams/tools/toolcollection/linalg/__init__.py +24 -0
- gams/tools/toolcollection/linalg/cholesky.py +57 -0
- gams/tools/toolcollection/linalg/eigenvalue.py +56 -0
- gams/tools/toolcollection/linalg/eigenvector.py +58 -0
- gams/tools/toolcollection/linalg/invert.py +55 -0
- gams/tools/toolcollection/linalg/ols.py +138 -0
- gams/tools/toolcollection/tooltemplate.py +321 -0
- gams/tools/toolcollection/win32/__init__.py +24 -0
- gams/tools/toolcollection/win32/excelmerge.py +93 -0
- gams/tools/toolcollection/win32/exceltalk.py +76 -0
- gams/tools/toolcollection/win32/msappavail.py +49 -0
- gams/tools/toolcollection/win32/shellexecute.py +54 -0
- gams/tools/tools.py +116 -0
- gams/transfer/__init__.py +35 -0
- gams/transfer/_abcs/__init__.py +37 -0
- gams/transfer/_abcs/container_abcs.py +433 -0
- gams/transfer/_internals/__init__.py +63 -0
- gams/transfer/_internals/algorithms.py +436 -0
- gams/transfer/_internals/casepreservingdict.py +124 -0
- gams/transfer/_internals/constants.py +270 -0
- gams/transfer/_internals/domainviolation.py +103 -0
- gams/transfer/_internals/specialvalues.py +172 -0
- gams/transfer/containers/__init__.py +26 -0
- gams/transfer/containers/_container.py +1794 -0
- gams/transfer/containers/_io/__init__.py +28 -0
- gams/transfer/containers/_io/containers.py +164 -0
- gams/transfer/containers/_io/gdx.py +1029 -0
- gams/transfer/containers/_io/gmd.py +872 -0
- gams/transfer/containers/_mixins/__init__.py +26 -0
- gams/transfer/containers/_mixins/ccc.py +1274 -0
- gams/transfer/syms/__init__.py +33 -0
- gams/transfer/syms/_methods/__init__.py +24 -0
- gams/transfer/syms/_methods/tables.py +120 -0
- gams/transfer/syms/_methods/toDict.py +115 -0
- gams/transfer/syms/_methods/toList.py +83 -0
- gams/transfer/syms/_methods/toValue.py +60 -0
- gams/transfer/syms/_mixins/__init__.py +32 -0
- gams/transfer/syms/_mixins/equals.py +626 -0
- gams/transfer/syms/_mixins/generateRecords.py +499 -0
- gams/transfer/syms/_mixins/pivot.py +313 -0
- gams/transfer/syms/_mixins/pve.py +627 -0
- gams/transfer/syms/_mixins/sa.py +27 -0
- gams/transfer/syms/_mixins/sapve.py +27 -0
- gams/transfer/syms/_mixins/saua.py +27 -0
- gams/transfer/syms/_mixins/sauapve.py +199 -0
- gams/transfer/syms/_mixins/spve.py +1528 -0
- gams/transfer/syms/_mixins/ve.py +936 -0
- gams/transfer/syms/container_syms/__init__.py +31 -0
- gams/transfer/syms/container_syms/_alias.py +984 -0
- gams/transfer/syms/container_syms/_equation.py +333 -0
- gams/transfer/syms/container_syms/_parameter.py +973 -0
- gams/transfer/syms/container_syms/_set.py +604 -0
- gams/transfer/syms/container_syms/_universe_alias.py +461 -0
- gams/transfer/syms/container_syms/_variable.py +321 -0
- gamsapi-52.5.0.dist-info/METADATA +150 -0
- gamsapi-52.5.0.dist-info/RECORD +257 -0
- gamsapi-52.5.0.dist-info/WHEEL +5 -0
- gamsapi-52.5.0.dist-info/licenses/LICENSE +22 -0
- gamsapi-52.5.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
connection:
|
|
2
|
+
type: dict
|
|
3
|
+
required: true
|
|
4
|
+
connectionType:
|
|
5
|
+
type: string
|
|
6
|
+
default: sqlite
|
|
7
|
+
allowed: [pyodbc, sqlalchemy, postgres, sqlite, mysql, sqlserver, access]
|
|
8
|
+
connectionArguments:
|
|
9
|
+
type: dict
|
|
10
|
+
default: null
|
|
11
|
+
nullable: true
|
|
12
|
+
type:
|
|
13
|
+
type: string
|
|
14
|
+
default: par
|
|
15
|
+
allowed: [par, set]
|
|
16
|
+
indexSubstitutions:
|
|
17
|
+
type: dict
|
|
18
|
+
default: null
|
|
19
|
+
nullable: true
|
|
20
|
+
valueSubstitutions:
|
|
21
|
+
type: dict
|
|
22
|
+
default: null
|
|
23
|
+
nullable: true
|
|
24
|
+
dTypeMap:
|
|
25
|
+
type: dict
|
|
26
|
+
default: null
|
|
27
|
+
nullable: true
|
|
28
|
+
readSQLArguments:
|
|
29
|
+
type: dict
|
|
30
|
+
default: null
|
|
31
|
+
nullable: true
|
|
32
|
+
trace:
|
|
33
|
+
type: integer
|
|
34
|
+
default: 0
|
|
35
|
+
symbols:
|
|
36
|
+
type: list
|
|
37
|
+
required: true
|
|
38
|
+
schema:
|
|
39
|
+
type: dict
|
|
40
|
+
schema:
|
|
41
|
+
name:
|
|
42
|
+
type: string
|
|
43
|
+
required: true
|
|
44
|
+
query:
|
|
45
|
+
type: string
|
|
46
|
+
required: true
|
|
47
|
+
type:
|
|
48
|
+
type: string
|
|
49
|
+
default: null
|
|
50
|
+
allowed: [par, set]
|
|
51
|
+
nullable: true
|
|
52
|
+
valueColumns:
|
|
53
|
+
default: infer
|
|
54
|
+
oneof:
|
|
55
|
+
- type: string
|
|
56
|
+
allowed: [infer, lastCol, none]
|
|
57
|
+
- type: list
|
|
58
|
+
schema:
|
|
59
|
+
type: string
|
|
60
|
+
indexSubstitutions:
|
|
61
|
+
type: dict
|
|
62
|
+
default: null
|
|
63
|
+
nullable: true
|
|
64
|
+
valueSubstitutions:
|
|
65
|
+
type: dict
|
|
66
|
+
default: null
|
|
67
|
+
nullable: true
|
|
68
|
+
dTypeMap:
|
|
69
|
+
type: dict
|
|
70
|
+
default: null
|
|
71
|
+
nullable: true
|
|
72
|
+
readSQLArguments:
|
|
73
|
+
type: dict
|
|
74
|
+
default: null
|
|
75
|
+
nullable: true
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
connection:
|
|
2
|
+
type: dict
|
|
3
|
+
required: true
|
|
4
|
+
connectionType:
|
|
5
|
+
type: string
|
|
6
|
+
default: sqlite
|
|
7
|
+
allowed: [pyodbc, sqlalchemy, postgres, sqlite, mysql, sqlserver, access]
|
|
8
|
+
connectionArguments:
|
|
9
|
+
type: dict
|
|
10
|
+
default: null
|
|
11
|
+
nullable: true
|
|
12
|
+
schemaName:
|
|
13
|
+
type: string
|
|
14
|
+
default: null
|
|
15
|
+
nullable: true
|
|
16
|
+
ifExists:
|
|
17
|
+
type: string
|
|
18
|
+
default: fail
|
|
19
|
+
allowed: [append, replace, fail]
|
|
20
|
+
insertMethod:
|
|
21
|
+
type: string
|
|
22
|
+
default: default
|
|
23
|
+
allowed: [bcp, bulkInsert, default]
|
|
24
|
+
unstack:
|
|
25
|
+
type: boolean
|
|
26
|
+
default: false
|
|
27
|
+
skipText:
|
|
28
|
+
type: boolean
|
|
29
|
+
default: false
|
|
30
|
+
small:
|
|
31
|
+
type: boolean
|
|
32
|
+
default: false
|
|
33
|
+
fast:
|
|
34
|
+
type: boolean
|
|
35
|
+
default: false
|
|
36
|
+
valueSubstitutions:
|
|
37
|
+
type: dict
|
|
38
|
+
default: null
|
|
39
|
+
nullable: true
|
|
40
|
+
columnEncloser:
|
|
41
|
+
type: string
|
|
42
|
+
default: "'"
|
|
43
|
+
dTypeMap:
|
|
44
|
+
type: dict
|
|
45
|
+
default: null
|
|
46
|
+
nullable: true
|
|
47
|
+
toSQLArguments:
|
|
48
|
+
type: dict
|
|
49
|
+
default: null
|
|
50
|
+
nullable: true
|
|
51
|
+
trace:
|
|
52
|
+
type: integer
|
|
53
|
+
default: 0
|
|
54
|
+
symbols:
|
|
55
|
+
default: all
|
|
56
|
+
oneof:
|
|
57
|
+
- type: string
|
|
58
|
+
allowed: [all]
|
|
59
|
+
- type: list
|
|
60
|
+
schema:
|
|
61
|
+
type: dict
|
|
62
|
+
allow_unknown: false
|
|
63
|
+
schema:
|
|
64
|
+
name:
|
|
65
|
+
type: string
|
|
66
|
+
required: true
|
|
67
|
+
tableName:
|
|
68
|
+
type: string
|
|
69
|
+
required: true
|
|
70
|
+
schemaName:
|
|
71
|
+
type: string
|
|
72
|
+
default: null
|
|
73
|
+
nullable: true
|
|
74
|
+
ifExists:
|
|
75
|
+
type: string
|
|
76
|
+
default: null
|
|
77
|
+
allowed: [append, replace, fail]
|
|
78
|
+
nullable: true
|
|
79
|
+
insertMethod:
|
|
80
|
+
type: string
|
|
81
|
+
default: null
|
|
82
|
+
allowed: [bcp, bulkInsert, default]
|
|
83
|
+
nullable: true
|
|
84
|
+
unstack:
|
|
85
|
+
type: boolean
|
|
86
|
+
default: null
|
|
87
|
+
nullable: true
|
|
88
|
+
skipText:
|
|
89
|
+
type: boolean
|
|
90
|
+
default: null
|
|
91
|
+
nullable: true
|
|
92
|
+
valueSubstitutions:
|
|
93
|
+
type: dict
|
|
94
|
+
default: null
|
|
95
|
+
nullable: true
|
|
96
|
+
dTypeMap:
|
|
97
|
+
type: dict
|
|
98
|
+
default: null
|
|
99
|
+
nullable: true
|
|
100
|
+
toSQLArguments:
|
|
101
|
+
type: dict
|
|
102
|
+
default: null
|
|
103
|
+
nullable: true
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
#
|
|
2
|
+
# GAMS - General Algebraic Modeling System Python API
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2017-2026 GAMS Development Corp. <support@gams.com>
|
|
5
|
+
# Copyright (c) 2017-2026 GAMS Software GmbH <support@gams.com>
|
|
6
|
+
#
|
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
# furnished to do so, subject to the following conditions:
|
|
13
|
+
#
|
|
14
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
15
|
+
# copies or substantial portions of the Software.
|
|
16
|
+
#
|
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
|
+
# SOFTWARE.
|
|
24
|
+
#
|
|
25
|
+
|
|
26
|
+
import gams.transfer as gt
|
|
27
|
+
import numpy as np
|
|
28
|
+
import pandas as pd
|
|
29
|
+
from gams.connect.agents.connectagent import ConnectAgent
|
|
30
|
+
from gams.connect.agents._sqlconnectors import (
|
|
31
|
+
AccessConnector,
|
|
32
|
+
MySQLConnector,
|
|
33
|
+
PostgresConnector,
|
|
34
|
+
PyodbcConnector,
|
|
35
|
+
SQLAlchemyConnector,
|
|
36
|
+
SQLiteConnector,
|
|
37
|
+
SQLServerConnector,
|
|
38
|
+
)
|
|
39
|
+
from gams.connect.agents._sqlconnectors._databasehandler import ConnectionType
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class SQLReader(ConnectAgent):
|
|
43
|
+
|
|
44
|
+
def __init__(self, cdb, inst, agent_index):
|
|
45
|
+
super().__init__(cdb, inst, agent_index)
|
|
46
|
+
self._parse_options(self._inst)
|
|
47
|
+
|
|
48
|
+
def _parse_options(self, inst):
|
|
49
|
+
self._connection = inst["connection"]
|
|
50
|
+
self._connection_args = self._dict_get(inst, "connectionArguments", {})
|
|
51
|
+
self._cnctn_type = inst["connectionType"]
|
|
52
|
+
self._sym_type = inst["type"]
|
|
53
|
+
self._symbols = inst["symbols"]
|
|
54
|
+
self._dtype_map = inst["dTypeMap"]
|
|
55
|
+
self._value_sub = inst["valueSubstitutions"]
|
|
56
|
+
self._index_sub = inst["indexSubstitutions"]
|
|
57
|
+
self._read_sql_args = inst["readSQLArguments"]
|
|
58
|
+
self._trace = inst["trace"]
|
|
59
|
+
self._handler = self._get_handler(self._cnctn_type)
|
|
60
|
+
|
|
61
|
+
def _get_handler(
|
|
62
|
+
self, cnctn_type
|
|
63
|
+
) -> (
|
|
64
|
+
SQLiteConnector
|
|
65
|
+
| SQLAlchemyConnector
|
|
66
|
+
| PyodbcConnector
|
|
67
|
+
| MySQLConnector
|
|
68
|
+
| PostgresConnector
|
|
69
|
+
| SQLServerConnector
|
|
70
|
+
| AccessConnector
|
|
71
|
+
):
|
|
72
|
+
handlers = {
|
|
73
|
+
ConnectionType.SQLITE.value: SQLiteConnector,
|
|
74
|
+
ConnectionType.SQLALCHEMY.value: SQLAlchemyConnector,
|
|
75
|
+
ConnectionType.PYODBC.value: PyodbcConnector,
|
|
76
|
+
ConnectionType.MYSQL.value: MySQLConnector,
|
|
77
|
+
ConnectionType.POSTGRES.value: PostgresConnector,
|
|
78
|
+
ConnectionType.SQLSERVER.value: SQLServerConnector,
|
|
79
|
+
ConnectionType.ACCESS.value: AccessConnector,
|
|
80
|
+
}
|
|
81
|
+
handler_class = handlers[cnctn_type]
|
|
82
|
+
|
|
83
|
+
return handler_class(
|
|
84
|
+
error_callback=self._connect_error,
|
|
85
|
+
printLog_callback=self._cdb.print_log,
|
|
86
|
+
trace=self._trace,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
def _open(self):
|
|
90
|
+
options = {"isWrite": False}
|
|
91
|
+
self._handler.connect(
|
|
92
|
+
connection_details=self._connection,
|
|
93
|
+
connection_args=self._connection_args,
|
|
94
|
+
**options,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
def execute(self):
|
|
98
|
+
if self._trace > 0:
|
|
99
|
+
self._log_instructions(self._inst, self._inst_raw)
|
|
100
|
+
self._describe_container(self._cdb.container, "Connect Container (before):")
|
|
101
|
+
|
|
102
|
+
self._open()
|
|
103
|
+
|
|
104
|
+
try:
|
|
105
|
+
symbols_raw = self._symbols.copy()
|
|
106
|
+
for s in self._symbols:
|
|
107
|
+
self._update_sym_inst(s, self._inst)
|
|
108
|
+
for sym, sym_raw in zip(self._symbols, symbols_raw):
|
|
109
|
+
if sym["valueColumns"] == "infer":
|
|
110
|
+
if sym["type"] == "par":
|
|
111
|
+
sym["valueColumns"] = (
|
|
112
|
+
"lastCol" # the last column will be a value column per default
|
|
113
|
+
)
|
|
114
|
+
elif sym["type"] == "set":
|
|
115
|
+
sym["valueColumns"] = (
|
|
116
|
+
"none" # all columns will be index columns per default
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
sym_name = sym["name"]
|
|
120
|
+
sym_type = sym["type"]
|
|
121
|
+
dtype_map = sym["dTypeMap"]
|
|
122
|
+
value_col = sym["valueColumns"]
|
|
123
|
+
index_sub = sym["indexSubstitutions"]
|
|
124
|
+
value_sub = sym["valueSubstitutions"]
|
|
125
|
+
read_sql_args = self._dict_get(sym, "readSQLArguments", {})
|
|
126
|
+
|
|
127
|
+
if self._trace > 0:
|
|
128
|
+
self._log_instructions(
|
|
129
|
+
sym, sym_raw, description=f"Read symbol >{sym['name']}<:"
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
self._symbols_exist_cdb(sym_name)
|
|
133
|
+
|
|
134
|
+
try:
|
|
135
|
+
df = self._handler.read_table(
|
|
136
|
+
sql_query=sym["query"], read_sql_args=read_sql_args
|
|
137
|
+
)
|
|
138
|
+
except Exception as e:
|
|
139
|
+
self._connect_error(
|
|
140
|
+
f"{type(e).__module__}, {type(e).__name__}: {e}"
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
if self._trace > 2:
|
|
144
|
+
self._cdb.print_log(f"DataFrame({sym_name}) after reading:\n{df}\n")
|
|
145
|
+
|
|
146
|
+
cols = list(df.columns)
|
|
147
|
+
|
|
148
|
+
if dtype_map:
|
|
149
|
+
df = df.astype(
|
|
150
|
+
{c: dtype_map[c] for c in cols if c in dtype_map.keys()}
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
index_sub_flag = False
|
|
154
|
+
stack = False
|
|
155
|
+
if isinstance(value_col, str):
|
|
156
|
+
if value_col == "lastCol":
|
|
157
|
+
dim = len(cols) - 1
|
|
158
|
+
if dim > 0:
|
|
159
|
+
df.set_index(cols[:-1], inplace=True)
|
|
160
|
+
elif sym_type == "set":
|
|
161
|
+
self._connect_error(
|
|
162
|
+
"Dimension must be greater than 0 for a set."
|
|
163
|
+
)
|
|
164
|
+
elif value_col == "none":
|
|
165
|
+
if sym_type == "set":
|
|
166
|
+
df.set_index(cols, inplace=True)
|
|
167
|
+
index_sub_flag = True
|
|
168
|
+
dim = len(cols)
|
|
169
|
+
elif sym_type == "par":
|
|
170
|
+
self._connect_error(
|
|
171
|
+
"A parameter requires at least one value column."
|
|
172
|
+
)
|
|
173
|
+
else:
|
|
174
|
+
self._connect_error(
|
|
175
|
+
f"Invalid string >{value_col}< for valueColumns was passed."
|
|
176
|
+
)
|
|
177
|
+
elif isinstance(value_col, list):
|
|
178
|
+
if len(value_col) == 0:
|
|
179
|
+
if sym_type == "set":
|
|
180
|
+
df.set_index(cols, inplace=True)
|
|
181
|
+
index_sub_flag = True
|
|
182
|
+
dim = len(cols)
|
|
183
|
+
else:
|
|
184
|
+
self._connect_error(
|
|
185
|
+
"A Parameter requires at least one value column."
|
|
186
|
+
)
|
|
187
|
+
else:
|
|
188
|
+
if all(x in cols for x in value_col):
|
|
189
|
+
index_col = [c for c in cols if c not in value_col]
|
|
190
|
+
if index_col != []:
|
|
191
|
+
df.set_index(index_col, inplace=True)
|
|
192
|
+
dim = len(index_col)
|
|
193
|
+
if (
|
|
194
|
+
len(value_col) > 1
|
|
195
|
+
): # automatically stack column names to index for more than one value/text column
|
|
196
|
+
stack = True
|
|
197
|
+
dim += 1
|
|
198
|
+
else:
|
|
199
|
+
not_in_df = list(set(value_col) - set(cols))
|
|
200
|
+
self._connect_error(
|
|
201
|
+
f"The following column(s) do not exist in the DataFrame({sym_name}): {not_in_df}"
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
if self._trace > 2:
|
|
205
|
+
self._cdb.print_log(
|
|
206
|
+
f"DataFrame({sym_name}) after .set_index():\n{df}"
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
domain = []
|
|
210
|
+
if dim > 0:
|
|
211
|
+
if stack:
|
|
212
|
+
columns = df.columns
|
|
213
|
+
# stack from column axis to index axis
|
|
214
|
+
# pandas-version-check
|
|
215
|
+
if self._pandas_version_before(
|
|
216
|
+
pd.__version__, "2.2"
|
|
217
|
+
): # pandas < 2.2.0
|
|
218
|
+
df = df.stack(dropna=False)
|
|
219
|
+
else: # pandas >= 2.2.0
|
|
220
|
+
df = df.stack(future_stack=True)
|
|
221
|
+
if dim == 1:
|
|
222
|
+
df = df.droplevel(
|
|
223
|
+
level=0
|
|
224
|
+
) # drop pandas default index level
|
|
225
|
+
if self._trace > 1:
|
|
226
|
+
self._cdb.print_log(
|
|
227
|
+
"Automatically stack column names to index for more than one value/text column."
|
|
228
|
+
)
|
|
229
|
+
if self._trace > 2:
|
|
230
|
+
self._cdb.print_log(
|
|
231
|
+
f"DataFrame({sym_name}) after stack:\n{df}"
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
# write relaxed domain information
|
|
235
|
+
domain = [str(d) if d is not None else "*" for d in df.index.names]
|
|
236
|
+
|
|
237
|
+
df = df.reset_index() # reset indices
|
|
238
|
+
if self._trace > 2:
|
|
239
|
+
self._cdb.print_log(
|
|
240
|
+
f"DataFrame({sym_name}) after .reset_index():\n{df}"
|
|
241
|
+
)
|
|
242
|
+
if index_sub: # index substitution
|
|
243
|
+
if (
|
|
244
|
+
index_sub_flag
|
|
245
|
+
): # case where all columns in the dataFrame are set to indices
|
|
246
|
+
df = df.replace(index_sub)
|
|
247
|
+
else: # inplace=True is not working since df.iloc[:,:-1] makes a copy
|
|
248
|
+
df.iloc[:, :-1] = df.iloc[:, :-1].replace(index_sub)
|
|
249
|
+
if self._trace > 2:
|
|
250
|
+
self._cdb.print_log(
|
|
251
|
+
f"DataFrame({sym_name}) after index substitution:\n{df}"
|
|
252
|
+
)
|
|
253
|
+
if stack: # categories substitution
|
|
254
|
+
columns = pd.Index(pd.Series(columns).replace(index_sub))
|
|
255
|
+
|
|
256
|
+
df = df.fillna(value=np.nan)
|
|
257
|
+
if value_sub: # value substitution
|
|
258
|
+
df.isetitem(-1, df.iloc[:, -1].replace(value_sub))
|
|
259
|
+
if self._trace > 2:
|
|
260
|
+
self._cdb.print_log(
|
|
261
|
+
f"DataFrame({sym_name}) after value substitution:\n{df}"
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
if sym_type == "par":
|
|
265
|
+
sym = gt.Parameter(self._cdb.container, sym_name, domain=domain)
|
|
266
|
+
df = df.dropna()
|
|
267
|
+
else:
|
|
268
|
+
sym = gt.Set(self._cdb.container, sym_name, domain=domain)
|
|
269
|
+
df = df.dropna()
|
|
270
|
+
if len(value_col) > 0 or value_col != "none":
|
|
271
|
+
df[df.columns[-1]] = df[df.columns[-1]].astype(str)
|
|
272
|
+
|
|
273
|
+
df.columns = range(df.columns.size) # reset column names
|
|
274
|
+
|
|
275
|
+
if self._trace > 2:
|
|
276
|
+
self._cdb.print_log(
|
|
277
|
+
f"Final DataFrame({sym_name}) that will be processed by GAMSTransfer:\n{df}"
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
sym.setRecords(df)
|
|
281
|
+
|
|
282
|
+
if stack:
|
|
283
|
+
sym.records.isetitem(
|
|
284
|
+
dim - 1,
|
|
285
|
+
sym.records.iloc[:, dim - 1].astype(
|
|
286
|
+
pd.CategoricalDtype(
|
|
287
|
+
categories=columns.unique(), ordered=True
|
|
288
|
+
)
|
|
289
|
+
),
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
finally:
|
|
293
|
+
self._handler.close()
|
|
294
|
+
|
|
295
|
+
if self._trace > 2:
|
|
296
|
+
for name, sym in self._cdb.container.data.items():
|
|
297
|
+
self._cdb.print_log(
|
|
298
|
+
f"Connect Container symbol={name}:\n {sym.records}\n"
|
|
299
|
+
)
|
|
300
|
+
if self._trace > 0:
|
|
301
|
+
self._describe_container(self._cdb.container, "Connect Container (after):")
|