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
gams/__init__.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
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
|
+
from gams._version import __version__
|
|
27
|
+
from gams.control import *
|
gams/_version.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "52.5.0"
|
gams/connect/__init__.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
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
|
+
from gams.connect.connectdatabase import ConnectDatabase
|
|
27
|
+
|
|
28
|
+
__all__ = ["ConnectDatabase"]
|
|
@@ -0,0 +1,24 @@
|
|
|
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
|
+
#
|
|
@@ -0,0 +1,32 @@
|
|
|
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
|
+
from gams.connect.agents._excel.workbook import Workbook
|
|
27
|
+
from gams.connect.agents._excel.excelagent import ExcelAgent
|
|
28
|
+
|
|
29
|
+
__all__ = [
|
|
30
|
+
"Workbook",
|
|
31
|
+
"ExcelAgent",
|
|
32
|
+
]
|
|
@@ -0,0 +1,312 @@
|
|
|
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
|
+
from abc import abstractmethod
|
|
27
|
+
from gams.connect.agents.connectagent import ConnectAgent
|
|
28
|
+
import numpy as np
|
|
29
|
+
from openpyxl.utils.cell import column_index_from_string, coordinate_from_string
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ExcelAgent(ConnectAgent):
|
|
33
|
+
@abstractmethod
|
|
34
|
+
def __init__(self, cdb, inst, agent_index):
|
|
35
|
+
super().__init__(cdb, inst, agent_index)
|
|
36
|
+
|
|
37
|
+
def _to_int_if_whole_vec(x):
|
|
38
|
+
if isinstance(x, float) and x.is_integer():
|
|
39
|
+
return int(x)
|
|
40
|
+
return x
|
|
41
|
+
|
|
42
|
+
self._to_int_if_whole = np.vectorize(_to_int_if_whole_vec, otypes=[object])
|
|
43
|
+
|
|
44
|
+
@abstractmethod
|
|
45
|
+
def _create_symbol_instructions(self, rec): ...
|
|
46
|
+
|
|
47
|
+
def _key_map(self, key, index_parameter_map):
|
|
48
|
+
if key is None:
|
|
49
|
+
return None
|
|
50
|
+
key = key.lower().strip()
|
|
51
|
+
if key in index_parameter_map:
|
|
52
|
+
return index_parameter_map[key]
|
|
53
|
+
if self._trace > 1 and key != "":
|
|
54
|
+
self._cdb.print_log(f"Ignoring unsupported option >{key}<.")
|
|
55
|
+
return ""
|
|
56
|
+
|
|
57
|
+
def _parse_key_value(self, value, index_parameter_map):
|
|
58
|
+
args = value
|
|
59
|
+
args = args.replace("=", " ")
|
|
60
|
+
args = args.split(" ")
|
|
61
|
+
args = list(
|
|
62
|
+
filter(lambda x: x != " ", args)
|
|
63
|
+
) # NOTE: This part of code doesnt allow spaces when specifying key-value pairs (e.g. ignoreColumns = 1:3 raises an error -> ignoreColumns=1:3)
|
|
64
|
+
ret = {}
|
|
65
|
+
for args_idx in range(0, len(args), 2):
|
|
66
|
+
key = args[args_idx].strip()
|
|
67
|
+
key = self._key_map(key, index_parameter_map)
|
|
68
|
+
if key is not None and len(key) != 0:
|
|
69
|
+
if args_idx + 1 >= len(args):
|
|
70
|
+
self._connect_error(
|
|
71
|
+
f"Error parsing >{value}< from index sheet. Option >{key}< does not have a value specified."
|
|
72
|
+
)
|
|
73
|
+
v = args[args_idx + 1].strip()
|
|
74
|
+
if v is not None:
|
|
75
|
+
v = self._value_map(key, v, index_parameter_map)
|
|
76
|
+
ret[key] = v
|
|
77
|
+
return ret
|
|
78
|
+
|
|
79
|
+
def _value_map(self, key, value, index_parameter_map):
|
|
80
|
+
if isinstance(value, str):
|
|
81
|
+
value = value.strip()
|
|
82
|
+
bool_mapping = {
|
|
83
|
+
# 1: True,
|
|
84
|
+
True: True,
|
|
85
|
+
"true": True,
|
|
86
|
+
"1": True,
|
|
87
|
+
# 0: False,
|
|
88
|
+
False: False,
|
|
89
|
+
"false": False,
|
|
90
|
+
"0": False,
|
|
91
|
+
}
|
|
92
|
+
m = {}
|
|
93
|
+
supported_keys = dict.fromkeys(index_parameter_map.values())
|
|
94
|
+
for k in supported_keys:
|
|
95
|
+
if k == "autoMerge":
|
|
96
|
+
m["autoMerge"] = bool_mapping
|
|
97
|
+
if k == "mergedCells":
|
|
98
|
+
m["mergedCells"] = bool_mapping
|
|
99
|
+
if k == "ignoreText":
|
|
100
|
+
m["ignoreText"] = bool_mapping
|
|
101
|
+
if k == "clearSheet":
|
|
102
|
+
m["clearSheet"] = bool_mapping
|
|
103
|
+
v = value
|
|
104
|
+
if key in supported_keys:
|
|
105
|
+
if key in ["autoMerge", "ignoreText", "mergedCells", "clearSheet"]:
|
|
106
|
+
if isinstance(value, str):
|
|
107
|
+
value = value.lower()
|
|
108
|
+
v = m[key].get(value, None)
|
|
109
|
+
if v is None:
|
|
110
|
+
self._connect_error(
|
|
111
|
+
f"Invalid value >{value}< for {key}. Allowed values are {', '.join(str(x) for x in m[key].keys())}."
|
|
112
|
+
)
|
|
113
|
+
elif key == "ignoreRows":
|
|
114
|
+
if isinstance(value, str):
|
|
115
|
+
l = value.split(",")
|
|
116
|
+
l = [x.strip() for x in l]
|
|
117
|
+
v = []
|
|
118
|
+
# [9, "4:7", 11] -> [9, 4, 5, 6, 7, 11]
|
|
119
|
+
for x in l:
|
|
120
|
+
if x.isnumeric():
|
|
121
|
+
v.append(int(x))
|
|
122
|
+
elif ":" in x:
|
|
123
|
+
v.extend(self._parse_rows_range(x))
|
|
124
|
+
else:
|
|
125
|
+
self._connect_error(
|
|
126
|
+
f"Value >{x}< for ignoreRows in index file need to be either numeric or in range format e.g. 3:7."
|
|
127
|
+
)
|
|
128
|
+
else:
|
|
129
|
+
v = [value]
|
|
130
|
+
elif key == "ignoreColumns":
|
|
131
|
+
if isinstance(value, str):
|
|
132
|
+
l = value.split(",")
|
|
133
|
+
l = [x.strip() for x in l]
|
|
134
|
+
v = []
|
|
135
|
+
for x in l:
|
|
136
|
+
if x.isnumeric():
|
|
137
|
+
v.append(int(x))
|
|
138
|
+
elif ":" in x:
|
|
139
|
+
v.extend(self._parse_columns_range(x))
|
|
140
|
+
else:
|
|
141
|
+
v.append(column_index_from_string(x))
|
|
142
|
+
else:
|
|
143
|
+
v = [value]
|
|
144
|
+
elif isinstance(value, str) and value.isnumeric():
|
|
145
|
+
v = int(value)
|
|
146
|
+
return v
|
|
147
|
+
|
|
148
|
+
def _coords_to_row_col(self, coordinates):
|
|
149
|
+
c = coordinate_from_string(coordinates)
|
|
150
|
+
return c[1], column_index_from_string(c[0])
|
|
151
|
+
|
|
152
|
+
def normalize_range(self, sym_range):
|
|
153
|
+
if sym_range.endswith("!"):
|
|
154
|
+
sym_range += "A1"
|
|
155
|
+
return sym_range
|
|
156
|
+
|
|
157
|
+
def _split_range(self, sym_range, wb):
|
|
158
|
+
if "!" not in sym_range: # named range
|
|
159
|
+
rng_dict = {x.lower(): x for x in wb.defined_names}
|
|
160
|
+
sym_range_lower = sym_range.lower()
|
|
161
|
+
if sym_range_lower not in rng_dict:
|
|
162
|
+
self._connect_error(f"Named range >{sym_range}< does not exist.")
|
|
163
|
+
rng = wb.resolve_named_range(rng_dict[sym_range_lower])
|
|
164
|
+
if len(rng) == 0:
|
|
165
|
+
self._connect_error(
|
|
166
|
+
f"Named range >{sym_range}< with invalid reference."
|
|
167
|
+
)
|
|
168
|
+
if len(rng) > 1:
|
|
169
|
+
self._connect_error(
|
|
170
|
+
f"Named range is not contiguous: {sym_range} -> {rng}"
|
|
171
|
+
)
|
|
172
|
+
rng = rng[0]
|
|
173
|
+
resolved_range = "!".join(rng)
|
|
174
|
+
sym_range = resolved_range
|
|
175
|
+
sym_range = self.normalize_range(sym_range)
|
|
176
|
+
return sym_range.split("!")
|
|
177
|
+
|
|
178
|
+
def _range_to_coords(self, rng):
|
|
179
|
+
nw, se = rng.split(":") if ":" in rng else (rng, None)
|
|
180
|
+
nw_row, nw_col = self._coords_to_row_col(nw)
|
|
181
|
+
se_col = se_row = None
|
|
182
|
+
if se is not None:
|
|
183
|
+
se_row, se_col = self._coords_to_row_col(se)
|
|
184
|
+
return nw_col - 1, nw_row - 1, se_col, se_row
|
|
185
|
+
|
|
186
|
+
def parse_range(self, sym_range, wb, clear_sheet=False, create_missing=False):
|
|
187
|
+
sheet, rng = self._split_range(sym_range, wb)
|
|
188
|
+
toc_range = f"'{sheet}'!{rng.split(':')[0]}"
|
|
189
|
+
sheet = self.sheet_by_name(sheet, wb, clear_sheet, create_missing)
|
|
190
|
+
nw_col, nw_row, se_col, se_row = self._range_to_coords(rng)
|
|
191
|
+
return sheet, nw_col, nw_row, se_col, se_row, toc_range
|
|
192
|
+
|
|
193
|
+
def parse_index(self, index, wb, index_parameter_map):
|
|
194
|
+
if self._trace > 1:
|
|
195
|
+
self._cdb.print_log(f"Parsing index sheet using range >{index}<")
|
|
196
|
+
sheet, nw_col, nw_row, se_col, se_row, _ = self.parse_range(index, wb)
|
|
197
|
+
data = wb.get_sheet_data(sheet)
|
|
198
|
+
if self._engine == "xlwings":
|
|
199
|
+
data = self._to_int_if_whole(data)
|
|
200
|
+
|
|
201
|
+
data = data[nw_row:se_row, nw_col:se_col]
|
|
202
|
+
header = data[0]
|
|
203
|
+
for idx, h in enumerate(header):
|
|
204
|
+
header[idx] = self._key_map(h, index_parameter_map)
|
|
205
|
+
|
|
206
|
+
symbols = []
|
|
207
|
+
global_par = {}
|
|
208
|
+
for rec in data[1:]:
|
|
209
|
+
local_par = self._create_symbol_instructions(rec)
|
|
210
|
+
is_symbol = len(local_par) > 0
|
|
211
|
+
for idx, h in enumerate(header[3:]):
|
|
212
|
+
key = self._key_map(h, index_parameter_map)
|
|
213
|
+
value = rec[idx + 3]
|
|
214
|
+
if isinstance(value, str):
|
|
215
|
+
value = value.strip()
|
|
216
|
+
params = {}
|
|
217
|
+
if key is None: # parse arbitrary key-value pairs
|
|
218
|
+
if value is not None:
|
|
219
|
+
params = self._parse_key_value(value, index_parameter_map)
|
|
220
|
+
elif len(key) == 0:
|
|
221
|
+
continue
|
|
222
|
+
elif value is not None:
|
|
223
|
+
params = {key: self._value_map(key, value, index_parameter_map)}
|
|
224
|
+
|
|
225
|
+
for k, v in params.items():
|
|
226
|
+
if is_symbol:
|
|
227
|
+
if self._trace > 1:
|
|
228
|
+
self._cdb.print_log(
|
|
229
|
+
f"Adding option >{k}: {v}< for symbol >{local_par['name']}<."
|
|
230
|
+
)
|
|
231
|
+
local_par[k] = v
|
|
232
|
+
else:
|
|
233
|
+
if self._trace > 1:
|
|
234
|
+
self._cdb.print_log(f"\nAdding root option >{k}: {v}<.")
|
|
235
|
+
global_par[k] = v
|
|
236
|
+
|
|
237
|
+
if is_symbol:
|
|
238
|
+
sym = global_par.copy()
|
|
239
|
+
sym.update(local_par)
|
|
240
|
+
symbols.append(sym)
|
|
241
|
+
return symbols
|
|
242
|
+
|
|
243
|
+
def sheet_by_name(self, sheet, wb, clear_sheet=False, create_missing=False):
|
|
244
|
+
for idx, s in enumerate(wb.sheetnames):
|
|
245
|
+
if sheet.lower() == s.lower():
|
|
246
|
+
if clear_sheet:
|
|
247
|
+
wb.delete_sheet(s)
|
|
248
|
+
return wb.create_sheet(s, idx)
|
|
249
|
+
return wb.get_sheet(s)
|
|
250
|
+
if create_missing:
|
|
251
|
+
return wb.create_sheet(sheet)
|
|
252
|
+
else:
|
|
253
|
+
self._connect_error(f"Sheet >{sheet}< not found.")
|
|
254
|
+
|
|
255
|
+
def _parse_rows_range(self, rng):
|
|
256
|
+
"""
|
|
257
|
+
Parse a range string in the format 'start:end' and return a list of all integers in the range.
|
|
258
|
+
e.g. 3:7 -> [3, 4, 5, 6, 7]
|
|
259
|
+
"""
|
|
260
|
+
r_components = rng.split(":")
|
|
261
|
+
r_components = [comp.strip() for comp in r_components]
|
|
262
|
+
if len(r_components) != 2:
|
|
263
|
+
self._connect_error(
|
|
264
|
+
f"Invalid range in ignoreRows >{rng}<. Must be specified in the format 'start:end'"
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
if not all(x.isnumeric() for x in r_components):
|
|
268
|
+
self._connect_error(
|
|
269
|
+
f"Invalid range in ignoreRows >{rng}<. Both 'start' and 'end' must be integers in 'start:end'"
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
r_from_to = list(map(int, r_components))
|
|
273
|
+
|
|
274
|
+
if r_from_to[0] > r_from_to[1]:
|
|
275
|
+
self._connect_error(
|
|
276
|
+
f"Invalid range in ignoreRows >{rng}<. 'start' >{r_components[0]}< must be less than or equal to 'end' >{r_components[1]}< in 'start:end'"
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
r_all = list(range(r_from_to[0], r_from_to[1] + 1))
|
|
280
|
+
return r_all
|
|
281
|
+
|
|
282
|
+
def _parse_columns_range(self, rng):
|
|
283
|
+
"""
|
|
284
|
+
Parse a range string in the format 'start:end' and return a list of all integers in the range.
|
|
285
|
+
e.g. C:G -> [3, 4, 5, 6, 7] , 2 : E -> [2, 3, 4, 5] , D :7 -> [4, 5, 6, 7]
|
|
286
|
+
"""
|
|
287
|
+
r_components = rng.split(":")
|
|
288
|
+
r_components = [comp.strip() for comp in r_components]
|
|
289
|
+
if len(r_components) != 2:
|
|
290
|
+
self._connect_error(
|
|
291
|
+
f"Invalid range in ignoreColumns >{rng}<. Must be specified in the format 'start:end'"
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
if not all(x.isnumeric() or x.isalpha() for x in r_components):
|
|
295
|
+
self._connect_error(
|
|
296
|
+
f"Invalid range in ignoreColumns >{rng}<. Both 'start' and 'end' must be either integers or letters in 'start:end'"
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
r_components = [
|
|
300
|
+
(column_index_from_string(comp) if comp.isalpha() else int(comp))
|
|
301
|
+
for comp in r_components
|
|
302
|
+
]
|
|
303
|
+
|
|
304
|
+
if r_components[0] > r_components[1]:
|
|
305
|
+
self._connect_error(
|
|
306
|
+
f"Invalid range in ignoreColumns >{rng}<. 'start' >{r_components[0]}< must be less than or equal to 'end' >{r_components[1]}< in 'start:end'"
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
r_from_to = list(map(int, r_components))
|
|
310
|
+
|
|
311
|
+
r_all = list(range(r_from_to[0], r_from_to[1] + 1))
|
|
312
|
+
return r_all
|
|
@@ -0,0 +1,155 @@
|
|
|
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 sys
|
|
27
|
+
import numpy as np
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class Workbook:
|
|
31
|
+
def __init__(self, file=None, engine="openpyxl", read_only=False, data_only=False):
|
|
32
|
+
self._engine = engine
|
|
33
|
+
self._file = file
|
|
34
|
+
|
|
35
|
+
if self._engine == "xlwings":
|
|
36
|
+
import xlwings
|
|
37
|
+
|
|
38
|
+
self._app = xlwings.App(visible=False, add_book=False)
|
|
39
|
+
self._wb = self._app.books.open(self._file, read_only=read_only)
|
|
40
|
+
elif self._engine == "openpyxl":
|
|
41
|
+
import openpyxl
|
|
42
|
+
|
|
43
|
+
if self._file is None:
|
|
44
|
+
self._wb = openpyxl.Workbook()
|
|
45
|
+
# remove default sheet
|
|
46
|
+
self._wb.remove(self._wb.active)
|
|
47
|
+
else:
|
|
48
|
+
self._wb = openpyxl.load_workbook(
|
|
49
|
+
self._file, read_only=read_only, data_only=data_only
|
|
50
|
+
)
|
|
51
|
+
else:
|
|
52
|
+
raise Exception("Invalid engine.")
|
|
53
|
+
|
|
54
|
+
def close(self):
|
|
55
|
+
if self._engine == "xlwings":
|
|
56
|
+
if self._app is not None:
|
|
57
|
+
self._app.quit()
|
|
58
|
+
elif self._engine == "openpyxl":
|
|
59
|
+
if self._wb is not None:
|
|
60
|
+
self._wb.close()
|
|
61
|
+
else:
|
|
62
|
+
raise Exception("Invalid engine.")
|
|
63
|
+
|
|
64
|
+
def save(self, path):
|
|
65
|
+
if self._engine == "xlwings":
|
|
66
|
+
self._wb.save(path)
|
|
67
|
+
elif self._engine == "openpyxl":
|
|
68
|
+
self._wb.save(path)
|
|
69
|
+
else:
|
|
70
|
+
raise Exception("Invalid engine.")
|
|
71
|
+
|
|
72
|
+
def get_sheet(self, sheet_name):
|
|
73
|
+
if self._engine == "xlwings":
|
|
74
|
+
return self._wb.sheets[sheet_name]
|
|
75
|
+
elif self._engine == "openpyxl":
|
|
76
|
+
return self._wb[sheet_name]
|
|
77
|
+
else:
|
|
78
|
+
raise Exception("Invalid engine.")
|
|
79
|
+
|
|
80
|
+
def index(self, worksheet):
|
|
81
|
+
if self._engine == "xlwings":
|
|
82
|
+
raise Exception("Not implemented.")
|
|
83
|
+
elif self._engine == "openpyxl":
|
|
84
|
+
return self._wb.index(worksheet)
|
|
85
|
+
else:
|
|
86
|
+
raise Exception("Invalid engine.")
|
|
87
|
+
|
|
88
|
+
def move_sheet(self, sheet, offset=0):
|
|
89
|
+
if self._engine == "xlwings":
|
|
90
|
+
raise Exception("Not implemented.")
|
|
91
|
+
elif self._engine == "openpyxl":
|
|
92
|
+
self._wb.move_sheet(sheet, offset)
|
|
93
|
+
else:
|
|
94
|
+
raise Exception("Invalid engine.")
|
|
95
|
+
|
|
96
|
+
def get_sheet_data(self, sheet):
|
|
97
|
+
if self._engine == "xlwings":
|
|
98
|
+
last_cell = sheet.used_range.last_cell
|
|
99
|
+
full_range = sheet.range(sheet.range("A1"), last_cell)
|
|
100
|
+
return full_range.options(
|
|
101
|
+
np.array,
|
|
102
|
+
ndim=2,
|
|
103
|
+
dtype=object,
|
|
104
|
+
empty=None,
|
|
105
|
+
err_to_str=True,
|
|
106
|
+
).value
|
|
107
|
+
elif self._engine == "openpyxl":
|
|
108
|
+
return np.array(
|
|
109
|
+
list(sheet.values), dtype=object
|
|
110
|
+
) # dtype=object is required to not convert int values (e.g. 1) to float automatically (e.g. 1.0)
|
|
111
|
+
else:
|
|
112
|
+
raise Exception("Invalid engine.")
|
|
113
|
+
|
|
114
|
+
def delete_sheet(self, sheet_name):
|
|
115
|
+
if self._engine == "xlwings":
|
|
116
|
+
self._wb.sheets[sheet_name].delete()
|
|
117
|
+
elif self._engine == "openpyxl":
|
|
118
|
+
del self._wb[sheet_name]
|
|
119
|
+
else:
|
|
120
|
+
raise Exception("Invalid engine.")
|
|
121
|
+
|
|
122
|
+
def create_sheet(self, sheet_name, index=None):
|
|
123
|
+
if self._engine == "xlwings":
|
|
124
|
+
raise Exception("Not imlemented.")
|
|
125
|
+
elif self._engine == "openpyxl":
|
|
126
|
+
return self._wb.create_sheet(sheet_name, index)
|
|
127
|
+
else:
|
|
128
|
+
raise Exception("Invalid engine.")
|
|
129
|
+
|
|
130
|
+
def resolve_named_range(self, sym_range):
|
|
131
|
+
if self._engine == "xlwings":
|
|
132
|
+
nr = self._wb.names[sym_range].refers_to_range
|
|
133
|
+
return [(nr.sheet.name, nr.address)]
|
|
134
|
+
elif self._engine == "openpyxl":
|
|
135
|
+
return list(self.defined_names[sym_range].destinations)
|
|
136
|
+
else:
|
|
137
|
+
raise Exception("Invalid engine.")
|
|
138
|
+
|
|
139
|
+
@property
|
|
140
|
+
def defined_names(self):
|
|
141
|
+
if self._engine == "xlwings":
|
|
142
|
+
return [x.name for x in self._wb.names]
|
|
143
|
+
elif self._engine == "openpyxl":
|
|
144
|
+
return self._wb.defined_names
|
|
145
|
+
else:
|
|
146
|
+
raise Exception("Invalid engine.")
|
|
147
|
+
|
|
148
|
+
@property
|
|
149
|
+
def sheetnames(self):
|
|
150
|
+
if self._engine == "xlwings":
|
|
151
|
+
return [s.name for s in self._wb.sheets]
|
|
152
|
+
elif self._engine == "openpyxl":
|
|
153
|
+
return self._wb.sheetnames
|
|
154
|
+
else:
|
|
155
|
+
raise Exception("Invalid engine.")
|
|
@@ -0,0 +1,42 @@
|
|
|
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
|
+
from gams.connect.agents._sqlconnectors._accesshandler import AccessConnector
|
|
27
|
+
from gams.connect.agents._sqlconnectors._mysqlhandler import MySQLConnector
|
|
28
|
+
from gams.connect.agents._sqlconnectors._postgreshandler import PostgresConnector
|
|
29
|
+
from gams.connect.agents._sqlconnectors._pyodbchandler import PyodbcConnector
|
|
30
|
+
from gams.connect.agents._sqlconnectors._sqlalchemyhandler import SQLAlchemyConnector
|
|
31
|
+
from gams.connect.agents._sqlconnectors._sqlitehandler import SQLiteConnector
|
|
32
|
+
from gams.connect.agents._sqlconnectors._sqlserverhandler import SQLServerConnector
|
|
33
|
+
|
|
34
|
+
__all__ = [
|
|
35
|
+
"AccessConnector",
|
|
36
|
+
"MySQLConnector",
|
|
37
|
+
"PostgresConnector",
|
|
38
|
+
"PyodbcConnector",
|
|
39
|
+
"SQLAlchemyConnector",
|
|
40
|
+
"SQLiteConnector",
|
|
41
|
+
"SQLServerConnector",
|
|
42
|
+
]
|