sqlalchemy-iris 0.15.5__py3-none-any.whl → 0.15.6b1__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.
- intersystems_iris/dbapi/_Column.py +3 -0
- intersystems_iris/dbapi/_DBAPI.py +38 -4
- intersystems_iris/dbapi/_IRISStream.py +2 -0
- intersystems_iris/dbapi/_ResultSetRow.py +1 -1
- intersystems_iris/dbapi/preparser/_PreParser.py +52 -3
- intersystems_iris/dbapi/preparser/_Token.py +3 -0
- intersystems_iris/dbapi/preparser/_TokenList.py +3 -0
- sqlalchemy_iris/base.py +62 -3
- sqlalchemy_iris/information_schema.py +2 -1
- sqlalchemy_iris/requirements.py +16 -0
- {sqlalchemy_iris-0.15.5.dist-info → sqlalchemy_iris-0.15.6b1.dist-info}/METADATA +3 -2
- {sqlalchemy_iris-0.15.5.dist-info → sqlalchemy_iris-0.15.6b1.dist-info}/RECORD +16 -22
- {sqlalchemy_iris-0.15.5.dist-info → sqlalchemy_iris-0.15.6b1.dist-info}/WHEEL +1 -1
- {sqlalchemy_iris-0.15.5.dist-info → sqlalchemy_iris-0.15.6b1.dist-info}/top_level.txt +0 -1
- iris/__init__.py +0 -66
- iris/__init__.pyi +0 -236
- iris/_cli.py +0 -75
- iris/iris_ipm.py +0 -40
- iris/iris_ipm.pyi +0 -17
- iris/iris_utils.py +0 -336
- {sqlalchemy_iris-0.15.5.dist-info → sqlalchemy_iris-0.15.6b1.dist-info}/LICENSE +0 -0
- {sqlalchemy_iris-0.15.5.dist-info → sqlalchemy_iris-0.15.6b1.dist-info}/entry_points.txt +0 -0
@@ -54,3 +54,6 @@ class _Column(intersystems_iris.dbapi._Descriptor._Descriptor):
|
|
54
54
|
self.isKeyColumn,
|
55
55
|
self.isRowId]
|
56
56
|
return _Column(self.name, self.type, self.precision, self.scale, self.nullable, self.label, self.tableName, self.schema, self.catalog, additionalData, self.slotPosition)
|
57
|
+
|
58
|
+
def __repr__(self) -> str:
|
59
|
+
return f"<Column name='{self.name}' type='{self.type}'>"
|
@@ -14,7 +14,7 @@ from ._ResultSetRow import _ResultSetRow
|
|
14
14
|
import intersystems_iris.dbapi._ParameterCollection
|
15
15
|
import intersystems_iris.dbapi.preparser._PreParser
|
16
16
|
from intersystems_iris.dbapi._Parameter import ParameterMode
|
17
|
-
from intersystems_iris.dbapi.preparser._PreParser import StatementType, MultiValuesInsert
|
17
|
+
from intersystems_iris.dbapi.preparser._PreParser import StatementType, MultiValuesInsert, InsertWithReturning
|
18
18
|
from intersystems_iris._IRISConnection import Feature
|
19
19
|
from intersystems_iris._InStream import _InStream
|
20
20
|
from intersystems_iris.dbapi._IRISStream import (
|
@@ -252,6 +252,11 @@ class _BaseCursor:
|
|
252
252
|
self._cleanup()
|
253
253
|
try:
|
254
254
|
self._preparse()
|
255
|
+
except InsertWithReturning as ex:
|
256
|
+
ids = intersystems_iris._ListWriter._ListWriter()
|
257
|
+
self.execute(ex.insert_query, params)
|
258
|
+
ids._set(self.lastrowid)
|
259
|
+
return self.execute(ex.select_query, bytes(ids._get_buffer()))
|
255
260
|
except MultiValuesInsert as ex:
|
256
261
|
# convert to executemany
|
257
262
|
params = params or ex.params
|
@@ -269,6 +274,7 @@ class _BaseCursor:
|
|
269
274
|
|
270
275
|
self._execute()
|
271
276
|
return self._rowcount
|
277
|
+
# return self.execute(returning_query)
|
272
278
|
|
273
279
|
def add_batch(self):
|
274
280
|
self._is_alive()
|
@@ -321,7 +327,17 @@ class _BaseCursor:
|
|
321
327
|
self._cleanup()
|
322
328
|
self._is_batch_update = True
|
323
329
|
|
324
|
-
|
330
|
+
try:
|
331
|
+
self._preparse()
|
332
|
+
except InsertWithReturning as ex:
|
333
|
+
ids = intersystems_iris._ListWriter._ListWriter()
|
334
|
+
for params in seq_of_params:
|
335
|
+
self.execute(ex.insert_query, params)
|
336
|
+
ids._set(self.lastrowid)
|
337
|
+
self.execute(ex.select_query, bytes(ids._get_buffer()))
|
338
|
+
raise
|
339
|
+
except Exception:
|
340
|
+
raise
|
325
341
|
self._prepare()
|
326
342
|
|
327
343
|
for row_num, param_row in enumerate(seq_of_params):
|
@@ -389,6 +405,8 @@ class _BaseCursor:
|
|
389
405
|
)
|
390
406
|
try:
|
391
407
|
pOut = parser.PreParse(self.statement, self._params)
|
408
|
+
except InsertWithReturning:
|
409
|
+
raise
|
392
410
|
except MultiValuesInsert:
|
393
411
|
raise
|
394
412
|
except Exception as e:
|
@@ -1182,6 +1200,8 @@ class Cursor(_BaseCursor):
|
|
1182
1200
|
sets = self._parameter_sets or 1
|
1183
1201
|
self.params = list(self.params).copy()
|
1184
1202
|
param_types = [param.type for param in self._params._params_list]
|
1203
|
+
if not self.params:
|
1204
|
+
return
|
1185
1205
|
|
1186
1206
|
for i in range(sets):
|
1187
1207
|
params = self._params.collect(i)
|
@@ -1949,7 +1969,12 @@ class Cursor(_BaseCursor):
|
|
1949
1969
|
self._closed = True
|
1950
1970
|
|
1951
1971
|
def executemany(self, operation, seq_of_params):
|
1952
|
-
|
1972
|
+
try:
|
1973
|
+
super().executemany(operation, seq_of_params)
|
1974
|
+
except InsertWithReturning:
|
1975
|
+
return
|
1976
|
+
except Exception:
|
1977
|
+
raise
|
1953
1978
|
self._rowcount = 0
|
1954
1979
|
for i in range(len(self.params)):
|
1955
1980
|
self._rowcount += self._in_message.wire._get()
|
@@ -2263,13 +2288,21 @@ class EmbdeddedCursor(_BaseCursor):
|
|
2263
2288
|
def __del__(self):
|
2264
2289
|
try:
|
2265
2290
|
self.close()
|
2266
|
-
except:
|
2291
|
+
except Exception:
|
2267
2292
|
pass
|
2268
2293
|
return
|
2269
2294
|
|
2270
2295
|
def _get_cached_info(self):
|
2271
2296
|
return False
|
2272
2297
|
|
2298
|
+
def executemany(self, operation, seq_of_params):
|
2299
|
+
try:
|
2300
|
+
super().executemany(operation, seq_of_params)
|
2301
|
+
except InsertWithReturning:
|
2302
|
+
return
|
2303
|
+
except Exception:
|
2304
|
+
raise
|
2305
|
+
|
2273
2306
|
def _get_parameters(self, params_set=0):
|
2274
2307
|
params = self._params.collect(params_set)
|
2275
2308
|
# None = '', '' = b'\x00'
|
@@ -2394,6 +2427,7 @@ class EmbdeddedCursor(_BaseCursor):
|
|
2394
2427
|
sqlcode = 0
|
2395
2428
|
message = None
|
2396
2429
|
try:
|
2430
|
+
print("!!!! _send_direct_query_request:params", [statement, params])
|
2397
2431
|
self._result_set = self._sql.exec(statement, *params)
|
2398
2432
|
self._rowcount = self._result_set.ResultSet._ROWCOUNT
|
2399
2433
|
self._get_column_info()
|
@@ -162,7 +162,7 @@ class _ResultSetRow:
|
|
162
162
|
self._list_item.next_offset = self._offsets[key]
|
163
163
|
_DBList._get_list_element(self._list_item)
|
164
164
|
item = _DBList._get(self._list_item, self._locale)
|
165
|
-
_column: _Column = self._columns[
|
165
|
+
_column: _Column = self._columns[key]
|
166
166
|
ctype = _column.type
|
167
167
|
value_type = self._types[ctype] if ctype in self._types else None
|
168
168
|
try:
|
@@ -11,6 +11,7 @@ from intersystems_iris.dbapi._Parameter import ParameterMode
|
|
11
11
|
from intersystems_iris.dbapi.preparser._Token import TOKEN
|
12
12
|
from intersystems_iris.dbapi.preparser._Scanner import ParseToken
|
13
13
|
|
14
|
+
|
14
15
|
class MultiValuesInsert(Exception):
|
15
16
|
|
16
17
|
def __init__(self, *args: object, query: str, rows: int, params=None) -> None:
|
@@ -20,6 +21,15 @@ class MultiValuesInsert(Exception):
|
|
20
21
|
self.params = params
|
21
22
|
|
22
23
|
|
24
|
+
class InsertWithReturning(Exception):
|
25
|
+
|
26
|
+
def __init__(self, *args: object, insert_query: str, insert_params, select_query: str) -> None:
|
27
|
+
super().__init__(*args)
|
28
|
+
self.insert_query = insert_query
|
29
|
+
self.insert_params = insert_params
|
30
|
+
self.select_query = select_query
|
31
|
+
|
32
|
+
|
23
33
|
# May want to move to its own file eventually
|
24
34
|
# SQL Statement Types
|
25
35
|
class StatementType(enum.IntEnum):
|
@@ -480,6 +490,11 @@ class _PreParser(object):
|
|
480
490
|
if found_insert:
|
481
491
|
self.Tokenize(t_query)
|
482
492
|
|
493
|
+
_, t_query, t_select_query = self.InsertReturning(t_query)
|
494
|
+
if t_select_query:
|
495
|
+
raise InsertWithReturning(insert_query=t_query, insert_params=p_Parameters, select_query=t_select_query)
|
496
|
+
self.Tokenize(t_query)
|
497
|
+
|
483
498
|
# Resolve the tokens and determine output
|
484
499
|
return self.Resolve(t_query, p_Parameters)
|
485
500
|
|
@@ -549,9 +564,39 @@ class _PreParser(object):
|
|
549
564
|
new_query += _query(False)
|
550
565
|
|
551
566
|
return found, new_query
|
552
|
-
except:
|
567
|
+
except Exception:
|
553
568
|
return False, query
|
554
|
-
|
569
|
+
|
570
|
+
def InsertReturning(self, query):
|
571
|
+
plain_query = ''
|
572
|
+
|
573
|
+
tokens = self.m_Tokens.GetEnumerator()
|
574
|
+
keywords = list(self.s_StatementTable.keys()) + list(self.s_ParsedStatements.keys()) + list(self.s_TransactionStatements.keys())
|
575
|
+
while tokens.MoveNext() and not tokens.Current().UpperOnOf(keywords):
|
576
|
+
plain_query += tokens.Current().Lexeme + ' '
|
577
|
+
if tokens.AtEnd() or not tokens.Current().UpperEquals("INSERT"):
|
578
|
+
return False, query, None
|
579
|
+
|
580
|
+
if not tokens.MoveNext() or not tokens.Current().UpperEquals("INTO"):
|
581
|
+
return False, query, None
|
582
|
+
plain_query += 'INSERT INTO '
|
583
|
+
table_name = ""
|
584
|
+
while tokens.MoveNext() and not tokens.Current().UpperOnOf(["(", "SET", "VALUES", "DEFAULT"]):
|
585
|
+
table_name += tokens.Current().Lexeme + ' '
|
586
|
+
plain_query += table_name + ' ' + tokens.Current().Lexeme + ' '
|
587
|
+
while tokens.MoveNext() and not tokens.Current().UpperEquals("RETURNING"):
|
588
|
+
plain_query += tokens.Current().Lexeme + ' '
|
589
|
+
|
590
|
+
select_query = None
|
591
|
+
if not tokens.AtEnd():
|
592
|
+
select_query = 'SELECT '
|
593
|
+
while tokens.MoveNext():
|
594
|
+
select_query += tokens.Current().Lexeme + ' '
|
595
|
+
select_query += "FROM " + table_name
|
596
|
+
select_query += " WHERE %ID %INLIST ?"
|
597
|
+
|
598
|
+
return False, plain_query, select_query
|
599
|
+
|
555
600
|
def InsertMultiValues(self, query):
|
556
601
|
new_query = ''
|
557
602
|
values_list = []
|
@@ -580,7 +625,10 @@ class _PreParser(object):
|
|
580
625
|
break
|
581
626
|
if token.TokenType is TOKEN.CONSTANT:
|
582
627
|
values += '?'
|
583
|
-
|
628
|
+
param = token.Lexeme
|
629
|
+
if param.__len__ and param[0] == "'" and param[0] == param[-1]:
|
630
|
+
param = param[1: -1]
|
631
|
+
params += [param]
|
584
632
|
else:
|
585
633
|
values += token.Lexeme
|
586
634
|
values += ' '
|
@@ -1047,6 +1095,7 @@ class _PreParser(object):
|
|
1047
1095
|
nParamIndex += 1
|
1048
1096
|
if nParamIndex == length + 1:
|
1049
1097
|
break
|
1098
|
+
|
1050
1099
|
return pOut
|
1051
1100
|
|
1052
1101
|
# '?' represents a parameter; adds a parameter to p_Parameters if none were provided
|
@@ -76,6 +76,9 @@ It records the classification of the token as well as retaining the original str
|
|
76
76
|
def UpperEquals(self, p_str):
|
77
77
|
return self.UpperLexeme == p_str
|
78
78
|
|
79
|
+
def UpperOnOf(self, p_str_list):
|
80
|
+
return self.UpperLexeme in p_str_list
|
81
|
+
|
79
82
|
def UpperContains(self, p_str):
|
80
83
|
return p_str in self.UpperLexeme
|
81
84
|
|
sqlalchemy_iris/base.py
CHANGED
@@ -653,6 +653,20 @@ class IRISDDLCompiler(sql.compiler.DDLCompiler):
|
|
653
653
|
def visit_check_constraint(self, constraint, **kw):
|
654
654
|
pass
|
655
655
|
|
656
|
+
def create_table_constraints(self, table, **kw):
|
657
|
+
description = ""
|
658
|
+
comment = table.comment
|
659
|
+
if comment:
|
660
|
+
# hack to keep \r, kind of
|
661
|
+
comment = comment.replace('\r', '\n\t')
|
662
|
+
literal = self.sql_compiler.render_literal_value(comment, sqltypes.String())
|
663
|
+
description = "%DESCRIPTION " + literal
|
664
|
+
|
665
|
+
constraints = super().create_table_constraints(table, **kw)
|
666
|
+
if constraints and description:
|
667
|
+
description = ", \n\t" + description
|
668
|
+
return constraints + description
|
669
|
+
|
656
670
|
def visit_add_constraint(self, create, **kw):
|
657
671
|
if isinstance(create.element, schema.CheckConstraint):
|
658
672
|
raise exc.CompileError("Can't add CHECK constraint")
|
@@ -701,6 +715,7 @@ class IRISDDLCompiler(sql.compiler.DDLCompiler):
|
|
701
715
|
|
702
716
|
comment = column.comment
|
703
717
|
if comment is not None:
|
718
|
+
comment = comment.replace('\r', '\n\t')
|
704
719
|
literal = self.sql_compiler.render_literal_value(comment, sqltypes.String())
|
705
720
|
colspec.append("%DESCRIPTION " + literal)
|
706
721
|
|
@@ -883,6 +898,12 @@ class IRISDialect(default.DefaultDialect):
|
|
883
898
|
type_compiler = IRISTypeCompiler
|
884
899
|
execution_ctx_cls = IRISExecutionContext
|
885
900
|
|
901
|
+
insert_returning = True
|
902
|
+
insert_executemany_returning = True
|
903
|
+
insert_executemany_returning_sort_by_parameter_order = True
|
904
|
+
update_executemany_returning = False
|
905
|
+
delete_executemany_returning = False
|
906
|
+
|
886
907
|
construct_arguments = [
|
887
908
|
(schema.Index, {"include": None}),
|
888
909
|
]
|
@@ -1105,6 +1126,38 @@ There are no access to %Dictionary, may be required for some advanced features,
|
|
1105
1126
|
return "SQLUser"
|
1106
1127
|
return schema
|
1107
1128
|
|
1129
|
+
@reflection.cache
|
1130
|
+
def get_table_options(self, connection, table_name, schema=None, **kw):
|
1131
|
+
if not self.has_table(connection=connection, table_name=table_name, schema=schema):
|
1132
|
+
raise exc.NoSuchTableError(
|
1133
|
+
f"{schema}.{table_name}" if schema else table_name
|
1134
|
+
) from None
|
1135
|
+
return {}
|
1136
|
+
|
1137
|
+
@reflection.cache
|
1138
|
+
def get_table_comment(self, connection, table_name, schema=None, **kw):
|
1139
|
+
if not self.has_table(connection=connection, table_name=table_name, schema=schema):
|
1140
|
+
raise exc.NoSuchTableError(
|
1141
|
+
f"{schema}.{table_name}" if schema else table_name
|
1142
|
+
) from None
|
1143
|
+
|
1144
|
+
tables = ischema.tables
|
1145
|
+
schema_name = self.get_schema(schema)
|
1146
|
+
|
1147
|
+
s = sql.select(tables.c.description).where(
|
1148
|
+
sql.and_(
|
1149
|
+
tables.c.table_schema == str(schema_name),
|
1150
|
+
tables.c.table_name == str(table_name),
|
1151
|
+
)
|
1152
|
+
)
|
1153
|
+
comment = connection.execute(s).scalar()
|
1154
|
+
if comment:
|
1155
|
+
# make it as \r
|
1156
|
+
comment = comment.replace(' \t\t\t\t', '\r')
|
1157
|
+
# restore \n
|
1158
|
+
comment = comment.replace(' \t\t\t', '\n')
|
1159
|
+
return {"text": comment}
|
1160
|
+
|
1108
1161
|
@reflection.cache
|
1109
1162
|
def get_schema_names(self, connection, **kw):
|
1110
1163
|
s = sql.select(ischema.schemata.c.schema_name).order_by(
|
@@ -1131,7 +1184,7 @@ There are no access to %Dictionary, may be required for some advanced features,
|
|
1131
1184
|
return table_names
|
1132
1185
|
|
1133
1186
|
@reflection.cache
|
1134
|
-
def get_temp_table_names(self, connection,
|
1187
|
+
def get_temp_table_names(self, connection, **kw):
|
1135
1188
|
tables = ischema.tables
|
1136
1189
|
s = (
|
1137
1190
|
sql.select(tables.c.table_name)
|
@@ -1598,6 +1651,7 @@ There are no access to %Dictionary, may be required for some advanced features,
|
|
1598
1651
|
columns.c.column_default,
|
1599
1652
|
columns.c.collation_name,
|
1600
1653
|
columns.c.auto_increment,
|
1654
|
+
columns.c.description,
|
1601
1655
|
)
|
1602
1656
|
.select_from(columns)
|
1603
1657
|
.where(
|
@@ -1650,7 +1704,12 @@ There are no access to %Dictionary, may be required for some advanced features,
|
|
1650
1704
|
sqlComputeCode = row[property.c.SqlComputeCode]
|
1651
1705
|
calculated = row[property.c.Calculated]
|
1652
1706
|
transient = row[property.c.Transient]
|
1653
|
-
|
1707
|
+
comment = row[columns.c.description]
|
1708
|
+
if comment:
|
1709
|
+
# make it as \r
|
1710
|
+
comment = comment.replace(' \t\t\t\t', '\r')
|
1711
|
+
# restore \n
|
1712
|
+
comment = comment.replace(' \t\t\t', '\n')
|
1654
1713
|
|
1655
1714
|
coltype = self.ischema_names.get(type_, None)
|
1656
1715
|
|
@@ -1696,7 +1755,7 @@ There are no access to %Dictionary, may be required for some advanced features,
|
|
1696
1755
|
"nullable": nullable,
|
1697
1756
|
"default": default,
|
1698
1757
|
"autoincrement": autoincrement,
|
1699
|
-
|
1758
|
+
"comment": comment,
|
1700
1759
|
}
|
1701
1760
|
if sqlComputeCode and "set {*} = " in sqlComputeCode.lower():
|
1702
1761
|
sqltext = sqlComputeCode
|
@@ -44,6 +44,7 @@ tables = Table(
|
|
44
44
|
Column("TABLE_NAME", String, key="table_name"),
|
45
45
|
Column("TABLE_TYPE", String, key="table_type"),
|
46
46
|
Column("CLASSNAME", String, key="classname"),
|
47
|
+
Column("DESCRIPTION", String, key="description"),
|
47
48
|
schema="INFORMATION_SCHEMA",
|
48
49
|
)
|
49
50
|
|
@@ -69,7 +70,7 @@ columns = Table(
|
|
69
70
|
Column("AUTO_INCREMENT", YESNO, key="auto_increment"),
|
70
71
|
Column("UNIQUE_COLUMN", YESNO, key="unique_column"),
|
71
72
|
Column("PRIMARY_KEY", YESNO, key="primary_key"),
|
72
|
-
Column("
|
73
|
+
Column("DESCRIPTION", String, key="description"),
|
73
74
|
schema="INFORMATION_SCHEMA",
|
74
75
|
)
|
75
76
|
property_definition = Table(
|
sqlalchemy_iris/requirements.py
CHANGED
@@ -58,6 +58,22 @@ class Requirements(SuiteRequirements, AlembicRequirements):
|
|
58
58
|
|
59
59
|
return exclusions.open()
|
60
60
|
|
61
|
+
@property
|
62
|
+
def reflect_table_options(self):
|
63
|
+
return exclusions.open()
|
64
|
+
|
65
|
+
@property
|
66
|
+
def comment_reflection(self):
|
67
|
+
return exclusions.open()
|
68
|
+
|
69
|
+
@property
|
70
|
+
def insert_returning(self):
|
71
|
+
return exclusions.open()
|
72
|
+
|
73
|
+
@property
|
74
|
+
def unusual_column_name_characters(self):
|
75
|
+
return exclusions.open()
|
76
|
+
|
61
77
|
@property
|
62
78
|
def computed_columns(self):
|
63
79
|
"Supports computed columns"
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.2
|
2
2
|
Name: sqlalchemy-iris
|
3
|
-
Version: 0.15.
|
3
|
+
Version: 0.15.6b1
|
4
4
|
Summary: InterSystems IRIS for SQLAlchemy
|
5
5
|
Home-page: https://github.com/caretdev/sqlalchemy-iris
|
6
6
|
Maintainer: CaretDev
|
@@ -23,6 +23,7 @@ Requires-Python: >=3.8
|
|
23
23
|
Description-Content-Type: text/markdown
|
24
24
|
License-File: LICENSE
|
25
25
|
Requires-Dist: SQLAlchemy>=1.3
|
26
|
+
Dynamic: requires-dist
|
26
27
|
|
27
28
|
sqlalchemy-iris
|
28
29
|
===
|
@@ -32,20 +32,20 @@ intersystems_iris/_PythonGateway.py,sha256=miV92LhCqsuBIRpLix1oqFjl5SCw9Df-GMTD6
|
|
32
32
|
intersystems_iris/_SharedMemorySocket.py,sha256=2iUaS1FdJNSCUEaE-VT0O_dxF6NRwqZSxlyLfwhT9_E,4330
|
33
33
|
intersystems_iris/__init__.py,sha256=Tk1tD28LwvF6X3yXQsJFLE1Bc-PR3gUJWcX5UnNYOdY,1773
|
34
34
|
intersystems_iris/__main__.py,sha256=rCtINTfJcADMAsw1ja-MEO7Q-XekrWthYowzWV8xGIQ,218
|
35
|
-
intersystems_iris/dbapi/_Column.py,sha256=
|
36
|
-
intersystems_iris/dbapi/_DBAPI.py,sha256=
|
35
|
+
intersystems_iris/dbapi/_Column.py,sha256=WgrqlZru9KxHveErKv6qzs8RSTeYlidK9DvuVkjpvIk,2632
|
36
|
+
intersystems_iris/dbapi/_DBAPI.py,sha256=UEZmr5pHF6TUqtqZiM91750SNrBP-qQdWtVF2Tcd8f4,104356
|
37
37
|
intersystems_iris/dbapi/_Descriptor.py,sha256=IjyITxvjygDrhpk-0lGhdqQPh91SG6nTb1vi-AqyJNI,1391
|
38
|
-
intersystems_iris/dbapi/_IRISStream.py,sha256=
|
38
|
+
intersystems_iris/dbapi/_IRISStream.py,sha256=M3d0SUfE7vyqCxbquSNaRc43J4Xc9i0XGWJnIJzUVVA,2173
|
39
39
|
intersystems_iris/dbapi/_Message.py,sha256=jpLG3HZElqp981iNPFW8UNRO3NbHf6poEv6yywX0Ssw,4076
|
40
40
|
intersystems_iris/dbapi/_Parameter.py,sha256=lvPlQkoLlyEjg5J_a9t2I_6vRDkAav6kN1fGyukH4DY,5293
|
41
41
|
intersystems_iris/dbapi/_ParameterCollection.py,sha256=kcgNiGv2nH5AwuA6LlPpM4dWqhSqRyD3VtwqHqDGRGU,5541
|
42
|
-
intersystems_iris/dbapi/_ResultSetRow.py,sha256=
|
42
|
+
intersystems_iris/dbapi/_ResultSetRow.py,sha256=enLGhY7FEZr1VGG-i8vojow2QJxOm-XDM93F1eHtu3U,13777
|
43
43
|
intersystems_iris/dbapi/_SQLType.py,sha256=IlDacXwQzUMWaJ02Zsu2bUfvUC3-5mBx-m6mE0Yp7ts,557
|
44
44
|
intersystems_iris/dbapi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
45
|
-
intersystems_iris/dbapi/preparser/_PreParser.py,sha256=
|
45
|
+
intersystems_iris/dbapi/preparser/_PreParser.py,sha256=CjvU6uQjIo4t-HvvoxERpc_wZZkqDCM8U6GOFVLWr3c,80925
|
46
46
|
intersystems_iris/dbapi/preparser/_Scanner.py,sha256=xA8rkKsaVba_mAgoXEeliyuMxNKe4vVmmw_klukdf_U,16163
|
47
|
-
intersystems_iris/dbapi/preparser/_Token.py,sha256=
|
48
|
-
intersystems_iris/dbapi/preparser/_TokenList.py,sha256=
|
47
|
+
intersystems_iris/dbapi/preparser/_Token.py,sha256=6hecLgne6ErgFIF4-dP_CLqsGBBDdlf3tXeQQfdI_uE,2388
|
48
|
+
intersystems_iris/dbapi/preparser/_TokenList.py,sha256=ae2kwIJP9-o7BOfaEuuQ5pHWYil7o18Mm40oIEyWIAM,6819
|
49
49
|
intersystems_iris/dbapi/preparser/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
50
50
|
intersystems_iris/pex/_BusinessHost.py,sha256=arBAUZetLPhJY2on3BK5BJOZXXjLVJ3gr_VvkncbWDs,4370
|
51
51
|
intersystems_iris/pex/_BusinessOperation.py,sha256=gEyPF6A04si6UqVUY_75ulYzjMBhe337GTkcbK2OGfA,5241
|
@@ -61,27 +61,21 @@ intersystems_iris/pex/_InboundAdapter.py,sha256=gZlWl7afumamkj8pNbpLyKFSzhaTAiAX
|
|
61
61
|
intersystems_iris/pex/_Message.py,sha256=Ugaa_lsEYke__pI5kdC7phAuyPQ7rxXUcROJL4cUxVQ,320
|
62
62
|
intersystems_iris/pex/_OutboundAdapter.py,sha256=ao2Ubbta2DcrQGdzDUD_j1Zsk8bvUfcZNKTZkzPTNBU,1628
|
63
63
|
intersystems_iris/pex/__init__.py,sha256=l_I1dpnluWawbFrGMDC0GLHpuHwjbpd-nho8otFX6TE,1379
|
64
|
-
iris/__init__.py,sha256=i0PK20mjoWOnFPQM0pHF8wMjjmh-5i1xLEduy4r-q9o,2036
|
65
|
-
iris/__init__.pyi,sha256=HPv6Lot6yZt8XXj3Rb0CrVO9ChDbKVpE3ID1SIqAlwU,9766
|
66
|
-
iris/_cli.py,sha256=HsmaY22h2a9EofCLcm_CU-ZikQNqFPDlH5xDvLon-Ko,1983
|
67
|
-
iris/iris_ipm.py,sha256=Q0jcNItjywlqOPZr0hgdTFSeLPNEmB-tcICOI_cXnaY,790
|
68
|
-
iris/iris_ipm.pyi,sha256=j7CNUZcjeDu5sgeWUZJO_Qi4vQmHh6aD-jPWv8OdoUs,374
|
69
|
-
iris/iris_utils.py,sha256=kg80O3yRpHIutM-mCyr4xCeTvKWPE-Kai-b6Dxw4vQ4,9882
|
70
64
|
irisnative/_IRISNative.py,sha256=HQ4nBhc8t8_5OtxdMG-kx1aa-T1znf2I8obZOPLOPzg,665
|
71
65
|
irisnative/__init__.py,sha256=6YmvBLQSURsCPKaNg7LK-xpo4ipDjrlhKuwdfdNb3Kg,341
|
72
66
|
sqlalchemy_iris/__init__.py,sha256=2bckDQ0AJJ9DfuAc20VVQNiK-YBhpYJMdo_C0qJwPHQ,1183
|
73
67
|
sqlalchemy_iris/alembic.py,sha256=L58qBIj6HwLmtU6FS5RXKW0gHr1mNTrBSChEllSh1n0,6607
|
74
|
-
sqlalchemy_iris/base.py,sha256=
|
68
|
+
sqlalchemy_iris/base.py,sha256=xkAYNo6TFIF7f6cvP2h_7TSiEJBbprmYrmpXM0FkWAM,54679
|
75
69
|
sqlalchemy_iris/embedded.py,sha256=5WZ78PIYB_pPyaLrK4E7kHUsGBRiwzYHjsTDiNYHUGg,819
|
76
|
-
sqlalchemy_iris/information_schema.py,sha256=
|
70
|
+
sqlalchemy_iris/information_schema.py,sha256=FUL3z_viGjjOvDA71Mbk5k94dUGcLV4dW1xHxBgM1rk,6188
|
77
71
|
sqlalchemy_iris/iris.py,sha256=Of0Ruc9W2c5ll5sjAy1xRo4tf1m0l_ab0vAdacTv3Yw,276
|
78
72
|
sqlalchemy_iris/irisasync.py,sha256=7Kmso-RGjxQi9Y4x-zQaUk1ylDQ7TDvpvlZh_syJtGw,312
|
79
73
|
sqlalchemy_iris/provision.py,sha256=drorbIgNO770Ws0XiCRXY_sDbQGIy2_zzNK3KYrDetY,198
|
80
|
-
sqlalchemy_iris/requirements.py,sha256=
|
74
|
+
sqlalchemy_iris/requirements.py,sha256=X0e_aeO83ucg3iwnX5n_CPUcwmav_SqLbaxj82_-MiU,7901
|
81
75
|
sqlalchemy_iris/types.py,sha256=mtm5wQQuA4pE6WB4EUHzAcpdBCLfZKHrY9qOcdllc7E,11077
|
82
|
-
sqlalchemy_iris-0.15.
|
83
|
-
sqlalchemy_iris-0.15.
|
84
|
-
sqlalchemy_iris-0.15.
|
85
|
-
sqlalchemy_iris-0.15.
|
86
|
-
sqlalchemy_iris-0.15.
|
87
|
-
sqlalchemy_iris-0.15.
|
76
|
+
sqlalchemy_iris-0.15.6b1.dist-info/LICENSE,sha256=RQmigqltsLq8lfOBc_KwtL0gkODyUCNpU-0ZiZwGlho,1075
|
77
|
+
sqlalchemy_iris-0.15.6b1.dist-info/METADATA,sha256=kSvVGiMAB7_YFkA9RedFo5IxT0RS0bqHl2YglBqiKS0,2379
|
78
|
+
sqlalchemy_iris-0.15.6b1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
79
|
+
sqlalchemy_iris-0.15.6b1.dist-info/entry_points.txt,sha256=zjOwyJPXHsNAeQP0n6l2_pav2U__rTAiS_Bk_IEmSlU,184
|
80
|
+
sqlalchemy_iris-0.15.6b1.dist-info/top_level.txt,sha256=QRY18YUXUJrRde4aayj_brj0lr2LBRVZS1ZoVoDFVS0,45
|
81
|
+
sqlalchemy_iris-0.15.6b1.dist-info/RECORD,,
|
iris/__init__.py
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
import sys
|
3
|
-
import importlib
|
4
|
-
|
5
|
-
from .iris_ipm import ipm
|
6
|
-
from .iris_utils import update_dynalib_path
|
7
|
-
|
8
|
-
# check for install dir in environment
|
9
|
-
# environment to check is IRISINSTALLDIR
|
10
|
-
# if not found, raise exception and exit
|
11
|
-
# ISC_PACKAGE_INSTALLDIR - defined by default in Docker images
|
12
|
-
installdir = os.environ.get('IRISINSTALLDIR') or os.environ.get('ISC_PACKAGE_INSTALLDIR')
|
13
|
-
if installdir is None:
|
14
|
-
raise Exception("""Cannot find InterSystems IRIS installation directory
|
15
|
-
Please set IRISINSTALLDIR environment variable to the InterSystems IRIS installation directory""")
|
16
|
-
|
17
|
-
__sysversion_info = sys.version_info
|
18
|
-
__syspath = sys.path
|
19
|
-
__osname = os.name
|
20
|
-
|
21
|
-
# join the install dir with the bin directory
|
22
|
-
__syspath.append(os.path.join(installdir, 'bin'))
|
23
|
-
# also append lib/python
|
24
|
-
__syspath.append(os.path.join(installdir, 'lib', 'python'))
|
25
|
-
|
26
|
-
# update the dynalib path
|
27
|
-
update_dynalib_path(os.path.join(installdir, 'bin'))
|
28
|
-
|
29
|
-
# save working directory
|
30
|
-
__ospath = os.getcwd()
|
31
|
-
|
32
|
-
__irispythonint = None
|
33
|
-
|
34
|
-
if __osname=='nt':
|
35
|
-
if __sysversion_info.minor==9:
|
36
|
-
__irispythonint = 'pythonint39'
|
37
|
-
elif __sysversion_info.minor==10:
|
38
|
-
__irispythonint = 'pythonint310'
|
39
|
-
elif __sysversion_info.minor==11:
|
40
|
-
__irispythonint = 'pythonint311'
|
41
|
-
elif __sysversion_info.minor==12:
|
42
|
-
__irispythonint = 'pythonint312'
|
43
|
-
elif __sysversion_info.minor==13:
|
44
|
-
__irispythonint = 'pythonint313'
|
45
|
-
else:
|
46
|
-
__irispythonint = 'pythonint'
|
47
|
-
|
48
|
-
if __irispythonint is not None:
|
49
|
-
# equivalent to from pythonint import *
|
50
|
-
try:
|
51
|
-
__irispythonintmodule = importlib.import_module(__irispythonint)
|
52
|
-
except ImportError:
|
53
|
-
__irispythonint = 'pythonint'
|
54
|
-
__irispythonintmodule = importlib.import_module(__irispythonint)
|
55
|
-
globals().update(vars(__irispythonintmodule))
|
56
|
-
|
57
|
-
# restore working directory
|
58
|
-
os.chdir(__ospath)
|
59
|
-
|
60
|
-
# TODO: Figure out how to hide __syspath and __ospath from anyone that
|
61
|
-
# imports iris. Tried __all__ but that only applies to this:
|
62
|
-
# from iris import *
|
63
|
-
|
64
|
-
#
|
65
|
-
# End-of-file
|
66
|
-
#
|
iris/__init__.pyi
DELETED
@@ -1,236 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
from typing import Any
|
3
|
-
from iris.iris_ipm import ipm
|
4
|
-
from . import iris_ipm
|
5
|
-
__all__ = [ 'check_status', 'cls', 'execute', 'gref', 'ipm', 'iris_ipm', 'lock', 'os', 'ref', 'routine', 'sql', 'system', 'tcommit', 'tlevel', 'trollback', 'trollbackone', 'tstart', 'unlock', 'utils']
|
6
|
-
def check_status(self, status):
|
7
|
-
"""
|
8
|
-
Raises an exception on an error status, or returns None if no error condition occurs.
|
9
|
-
Example: iris.check_status(st) checks the status code st to see if it contains an error.
|
10
|
-
"""
|
11
|
-
def cls(self, class_name):
|
12
|
-
"""
|
13
|
-
Returns a reference to an InterSystems IRIS class.
|
14
|
-
Example: iris.cls("%SYSTEM.INetInfo").LocalHostName() calls a method in the class %SYSTEM.INetInfo.
|
15
|
-
"""
|
16
|
-
def execute(self, statements):
|
17
|
-
"""
|
18
|
-
execute IRIS statements.
|
19
|
-
Example: iris.execute("set x="Hello"\nw x,!\n") returns nothing.
|
20
|
-
"""
|
21
|
-
def gref(self, global_name) -> global_ref:
|
22
|
-
"""
|
23
|
-
Returns a reference to an InterSystems IRIS global.
|
24
|
-
Example: g = iris.gref("^foo") sets g to a reference to global ^foo
|
25
|
-
"""
|
26
|
-
def lock(self, lock_list, timeout_value, locktype):
|
27
|
-
"""
|
28
|
-
Sets locks, given a list of lock names, an optional timeout value (in seconds), and an optional locktype.
|
29
|
-
Example: iris.lock(["^foo","^bar"], 30, "S") sets locks "^foo" and "^bar", waiting up to 30 seconds, and using shared locks.
|
30
|
-
"""
|
31
|
-
def ref(self, value):
|
32
|
-
"""
|
33
|
-
Creates an iris.ref object with a specified value.
|
34
|
-
Example: iris.ref("hello") creates an iris.ref object with the value "hello"
|
35
|
-
"""
|
36
|
-
def routine(self, routine, args):
|
37
|
-
"""
|
38
|
-
Invokes an InterSystems IRIS routine, optionally at a given tag.
|
39
|
-
Example: iris.routine("Stop^SystemPerformance", "20211221_160620_test") calls tag Stop in routine ^SystemPerformance.
|
40
|
-
"""
|
41
|
-
def tcommit(self):
|
42
|
-
"""
|
43
|
-
Marks a successful end of an InterSystems IRIS transaction.
|
44
|
-
Example: iris.commit() marks the successful end of a transaction and decrements the nesting level by 1
|
45
|
-
"""
|
46
|
-
def tlevel(self):
|
47
|
-
"""
|
48
|
-
Detects whether a transaction is currently in progress and returns the nesting level. Zero means not in a transaction.
|
49
|
-
Example: iris.tlevel() returns the current transaction nesting level, or zero if not in a transaction
|
50
|
-
"""
|
51
|
-
def trollback(self):
|
52
|
-
"""
|
53
|
-
Terminates the current transaction and restores all journaled database values to their values at the start of the transaction.
|
54
|
-
Example: iris.trollback() rolls back all current transactions in progress and resets the transaction nesting level to 0
|
55
|
-
"""
|
56
|
-
def trollbackone(self):
|
57
|
-
"""
|
58
|
-
Rolls back the current level of nested transactions, that is, the one initiated by the most recent tstart().
|
59
|
-
Example: iris.trollbackone() rolls back the current level of nested transactions and decrements the nesting level by 1
|
60
|
-
"""
|
61
|
-
def tstart(self):
|
62
|
-
"""
|
63
|
-
Starts an InterSystems IRIS transaction.
|
64
|
-
Example: iris.tstart() marks the beginning of a transaction.
|
65
|
-
"""
|
66
|
-
def unlock(self, lock_list, timout_value, locktype):
|
67
|
-
"""
|
68
|
-
Removes locks, given a list of lock names, an optional timeout value (in seconds), and an optional locktype.
|
69
|
-
Example: iris.unlock(["^foo","^bar"], 30, "S") removes locks "^foo" and "^bar", waiting up to 30 seconds, and using shared locks.
|
70
|
-
"""
|
71
|
-
def utils(self):
|
72
|
-
"""
|
73
|
-
Returns a reference to the InterSystems IRIS utilities class.
|
74
|
-
Example: iris.utils().$Job() returns the current job number.
|
75
|
-
"""
|
76
|
-
# Stubs for the gref object
|
77
|
-
class global_ref:
|
78
|
-
def data(self, key):
|
79
|
-
"""
|
80
|
-
Checks if a node of a global contains data and/or has descendants. The key of the node is passed as a list. Passing a key with the
|
81
|
-
value None (or an empty list) indicates the root node of the global.\n
|
82
|
-
You can use data() to inspect a node to see if it contains data before attempting to access that data and possibly encountering an error.
|
83
|
-
The method returns 0 if the node is undefined (contains no data), 1 if the node is defined (contains data), 10 if the node is undefined
|
84
|
-
but has descendants, or 11 if the node is defined and has descendants.
|
85
|
-
"""
|
86
|
-
def get(self, key):
|
87
|
-
"""
|
88
|
-
Gets the value stored at a node of a global. The key of the node is passed as a list. Passing a key with the value None (or an empty list)
|
89
|
-
indicates the root node of the global.
|
90
|
-
"""
|
91
|
-
def getAsBytes(self, key):
|
92
|
-
"""
|
93
|
-
Gets a string value stored at a node of a global and converts it to the Python bytes data type. The key of the node is passed as a list.
|
94
|
-
Passing a key with the value None (or an empty list) indicates the root node of the global.
|
95
|
-
"""
|
96
|
-
def keys(self, key):
|
97
|
-
"""
|
98
|
-
Returns the keys of a global, starting from a given key. The starting key is passed as a list. Passing an empty list indicates the root node of the global.
|
99
|
-
"""
|
100
|
-
def kill(self, key):
|
101
|
-
"""
|
102
|
-
Deletes the node of a global, if it exists. The key of the node is passed as a list. This also deletes any descendants of the node.
|
103
|
-
Passing a key with the value None (or an empty list) indicates the root node of the global.
|
104
|
-
"""
|
105
|
-
def order(self, key):
|
106
|
-
"""
|
107
|
-
Returns the next key in that level of the global, starting from a given key. The starting key is passed as a list.
|
108
|
-
If no key follows the starting key, order() returns None.
|
109
|
-
"""
|
110
|
-
def orderiter(self, key):
|
111
|
-
"""
|
112
|
-
Returns the keys and values of a global, starting from a given key, down to the next leaf node.
|
113
|
-
The starting key is passed as a list. Passing an empty list indicates the root node of the global.
|
114
|
-
"""
|
115
|
-
def query(self, key):
|
116
|
-
"""
|
117
|
-
Traverses a global starting at the specified key, returning each key and value.
|
118
|
-
The starting key is passed as a list. Passing an empty list indicates the root node of the global.
|
119
|
-
"""
|
120
|
-
def set(self, key, value):
|
121
|
-
"""
|
122
|
-
Sets a node in a global to a given value. The key of the node is passed as a list, and value is the value to be stored.
|
123
|
-
Passing a key with the value None (or an empty list) indicates the root node of the global.
|
124
|
-
"""
|
125
|
-
# stubs for the sql object
|
126
|
-
class sql:
|
127
|
-
"""
|
128
|
-
The sql object provides access to the InterSystems IRIS SQL API.
|
129
|
-
"""
|
130
|
-
def exec(self, query: str) -> Any:
|
131
|
-
"""
|
132
|
-
Execute a query
|
133
|
-
"""
|
134
|
-
def prepare(self, query: str) -> PreparedQuery:
|
135
|
-
"""
|
136
|
-
Prepare a query
|
137
|
-
"""
|
138
|
-
class PreparedQuery:
|
139
|
-
def execute(self, **kwargs) -> Any:
|
140
|
-
"""
|
141
|
-
Execute a prepared query, you can pass values
|
142
|
-
"""
|
143
|
-
# stubs for the system object
|
144
|
-
class system:
|
145
|
-
"""
|
146
|
-
The system object provides access to the InterSystems IRIS system API.
|
147
|
-
The following classes are available:
|
148
|
-
'DocDB', 'Encryption', 'Error', 'Event', 'Monitor', 'Process', 'Python', 'SQL', 'SYS', 'Security', 'Semaphore', 'Status', 'Util', 'Version'
|
149
|
-
"""
|
150
|
-
class DocDB:
|
151
|
-
"""
|
152
|
-
The DocDB class provides access to the InterSystems IRIS Document Database API.
|
153
|
-
The following methods are available:
|
154
|
-
'CreateDatabase', 'DropAllDatabases', 'DropDatabase', 'Exists', 'GetAllDatabases', 'GetDatabase', 'Help'
|
155
|
-
"""
|
156
|
-
def CreateDatabase(self, name: str, path: str, **kwargs) -> Any:
|
157
|
-
"""
|
158
|
-
Create a database
|
159
|
-
"""
|
160
|
-
def DropAllDatabases(self) -> Any:
|
161
|
-
"""
|
162
|
-
Drop all databases
|
163
|
-
"""
|
164
|
-
def DropDatabase(self, name: str) -> Any:
|
165
|
-
"""
|
166
|
-
Drop a database
|
167
|
-
"""
|
168
|
-
def Exists(self, name: str) -> Any:
|
169
|
-
"""
|
170
|
-
Check if a database exists
|
171
|
-
"""
|
172
|
-
def GetAllDatabases(self) -> Any:
|
173
|
-
"""
|
174
|
-
Get all databases
|
175
|
-
"""
|
176
|
-
def GetDatabase(self, name: str) -> Any:
|
177
|
-
"""
|
178
|
-
Get a database
|
179
|
-
"""
|
180
|
-
def Help(self) -> Any:
|
181
|
-
"""
|
182
|
-
Get help
|
183
|
-
"""
|
184
|
-
def Encryption(self) -> Any:
|
185
|
-
"""
|
186
|
-
The Encryption class provides access to the InterSystems IRIS Encryption API.
|
187
|
-
"""
|
188
|
-
def Error(self) -> Any:
|
189
|
-
"""
|
190
|
-
The Error class provides access to the InterSystems IRIS Error API.
|
191
|
-
"""
|
192
|
-
def Event(self) -> Any:
|
193
|
-
"""
|
194
|
-
The Event class provides access to the InterSystems IRIS Event API.
|
195
|
-
"""
|
196
|
-
def Monitor(self) -> Any:
|
197
|
-
"""
|
198
|
-
The Monitor class provides access to the InterSystems IRIS Monitor API.
|
199
|
-
"""
|
200
|
-
def Process(self) -> Any:
|
201
|
-
"""
|
202
|
-
The Process class provides access to the InterSystems IRIS Process API.
|
203
|
-
"""
|
204
|
-
def Python(self) -> Any:
|
205
|
-
"""
|
206
|
-
The Python class provides access to the InterSystems IRIS Python API.
|
207
|
-
"""
|
208
|
-
def SQL(self) -> Any:
|
209
|
-
"""
|
210
|
-
The SQL class provides access to the InterSystems IRIS SQL API.
|
211
|
-
"""
|
212
|
-
def SYS(self) -> Any:
|
213
|
-
"""
|
214
|
-
The SYS class provides access to the InterSystems IRIS SYS API.
|
215
|
-
"""
|
216
|
-
def Security(self) -> Any:
|
217
|
-
"""
|
218
|
-
The Security class provides access to the InterSystems IRIS Security API.
|
219
|
-
"""
|
220
|
-
def Semaphore(self) -> Any:
|
221
|
-
"""
|
222
|
-
The Semaphore class provides access to the InterSystems IRIS Semaphore API.
|
223
|
-
"""
|
224
|
-
def Status(self) -> Any:
|
225
|
-
"""
|
226
|
-
The Status class provides access to the InterSystems IRIS Status API.
|
227
|
-
"""
|
228
|
-
def Util(self) -> Any:
|
229
|
-
"""
|
230
|
-
The Util class provides access to the InterSystems IRIS Util API.
|
231
|
-
"""
|
232
|
-
def Version(self) -> Any:
|
233
|
-
"""
|
234
|
-
The Version class provides access to the InterSystems IRIS Version API.
|
235
|
-
"""
|
236
|
-
|
iris/_cli.py
DELETED
@@ -1,75 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
import sys
|
3
|
-
import argparse
|
4
|
-
import logging
|
5
|
-
|
6
|
-
from . import iris_utils
|
7
|
-
import iris
|
8
|
-
|
9
|
-
logging.basicConfig(level=logging.INFO)
|
10
|
-
|
11
|
-
VENV_BACKUP_GREF = "^Venv.BackUp"
|
12
|
-
|
13
|
-
def bind():
|
14
|
-
parser = argparse.ArgumentParser()
|
15
|
-
parser.add_argument("--namespace", default="")
|
16
|
-
args = parser.parse_args()
|
17
|
-
|
18
|
-
iris_gref = iris.gref(VENV_BACKUP_GREF)
|
19
|
-
|
20
|
-
path = ""
|
21
|
-
|
22
|
-
libpython = iris_utils.find_libpython()
|
23
|
-
if not libpython:
|
24
|
-
logging.error("libpython not found")
|
25
|
-
raise RuntimeError("libpython not found")
|
26
|
-
|
27
|
-
iris.system.Process.SetNamespace("%SYS")
|
28
|
-
|
29
|
-
config = iris.cls("Config.config").Open()
|
30
|
-
|
31
|
-
# Set the new libpython path
|
32
|
-
iris_gref["PythonRuntimeLibrary"] = config.PythonRuntimeLibrary
|
33
|
-
|
34
|
-
config.PythonRuntimeLibrary = libpython
|
35
|
-
|
36
|
-
if "VIRTUAL_ENV" in os.environ:
|
37
|
-
# we are not in a virtual environment
|
38
|
-
path = os.path.join(os.environ["VIRTUAL_ENV"], "lib", "python" + sys.version[:4], "site-packages")
|
39
|
-
|
40
|
-
iris_gref["PythonPath"] = config.PythonPath
|
41
|
-
|
42
|
-
config.PythonPath = path
|
43
|
-
|
44
|
-
config._Save()
|
45
|
-
|
46
|
-
log_config_changes(libpython, path)
|
47
|
-
|
48
|
-
def unbind():
|
49
|
-
iris.system.Process.SetNamespace("%SYS")
|
50
|
-
config = iris.cls("Config.config").Open()
|
51
|
-
|
52
|
-
iris_gref = iris.gref(VENV_BACKUP_GREF)
|
53
|
-
|
54
|
-
if iris_gref["PythonRuntimeLibrary"]:
|
55
|
-
config.PythonRuntimeLibrary = iris_gref["PythonRuntimeLibrary"]
|
56
|
-
else:
|
57
|
-
config.PythonRuntimeLibrary = ""
|
58
|
-
|
59
|
-
if iris_gref["PythonPath"]:
|
60
|
-
config.PythonPath = iris_gref["PythonPath"]
|
61
|
-
else:
|
62
|
-
config.PythonPath = ""
|
63
|
-
|
64
|
-
config._Save()
|
65
|
-
|
66
|
-
del iris_gref["PythonRuntimeLibrary"]
|
67
|
-
del iris_gref["PythonPath"]
|
68
|
-
del iris_gref[None]
|
69
|
-
|
70
|
-
log_config_changes(config.PythonRuntimeLibrary, config.PythonPath)
|
71
|
-
|
72
|
-
def log_config_changes(libpython, path):
|
73
|
-
logging.info("PythonRuntimeLibrary path set to %s", libpython)
|
74
|
-
logging.info("PythonPath set to %s", path)
|
75
|
-
logging.info("To iris instance %s", iris.cls("%SYS.System").GetUniqueInstanceName())
|
iris/iris_ipm.py
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
def ipm(cmd, *args):
|
2
|
-
"""
|
3
|
-
Executes shell command with IPM:
|
4
|
-
Parameters
|
5
|
-
----------
|
6
|
-
cmd : str
|
7
|
-
The command to execute
|
8
|
-
Examples
|
9
|
-
--------
|
10
|
-
`ipm('help')`
|
11
|
-
`ipm('load /home/irisowner/dev -v')`
|
12
|
-
`ipm('install webterminal')`
|
13
|
-
"""
|
14
|
-
|
15
|
-
import multiprocessing
|
16
|
-
import iris
|
17
|
-
|
18
|
-
def shell(cmd, status):
|
19
|
-
|
20
|
-
|
21
|
-
status.put(True)
|
22
|
-
|
23
|
-
res = iris.cls("%ZPM.PackageManager").Shell(cmd)
|
24
|
-
print('')
|
25
|
-
if res != 1:
|
26
|
-
status.get()
|
27
|
-
status.put(False)
|
28
|
-
|
29
|
-
manager = multiprocessing.Manager()
|
30
|
-
status = manager.Queue()
|
31
|
-
process = multiprocessing.Process(
|
32
|
-
target=shell,
|
33
|
-
args=(
|
34
|
-
cmd,
|
35
|
-
status,
|
36
|
-
),
|
37
|
-
)
|
38
|
-
process.start()
|
39
|
-
process.join()
|
40
|
-
return status.get()
|
iris/iris_ipm.pyi
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
__all__ = ['ipm']
|
3
|
-
def ipm(cmd, *args):
|
4
|
-
"""
|
5
|
-
|
6
|
-
Executes shell command with IPM:
|
7
|
-
Parameters
|
8
|
-
----------
|
9
|
-
cmd : str
|
10
|
-
The command to execute
|
11
|
-
Examples
|
12
|
-
--------
|
13
|
-
`ipm('help')`
|
14
|
-
`ipm('load /home/irisowner/dev -v')`
|
15
|
-
`ipm('install webterminal')`
|
16
|
-
|
17
|
-
"""
|
iris/iris_utils.py
DELETED
@@ -1,336 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Locate libpython associated with this Python executable.
|
3
|
-
"""
|
4
|
-
|
5
|
-
# License
|
6
|
-
#
|
7
|
-
# Copyright 2018, Takafumi Arakaki
|
8
|
-
#
|
9
|
-
# Permission is hereby granted, free of charge, to any person obtaining
|
10
|
-
# a copy of this software and associated documentation files (the
|
11
|
-
# "Software"), to deal in the Software without restriction, including
|
12
|
-
# without limitation the rights to use, copy, modify, merge, publish,
|
13
|
-
# distribute, sublicense, and/or sell copies of the Software, and to
|
14
|
-
# permit persons to whom the Software is furnished to do so, subject to
|
15
|
-
# the following conditions:
|
16
|
-
#
|
17
|
-
# The above copyright notice and this permission notice shall be
|
18
|
-
# included in all copies or substantial portions of the Software.
|
19
|
-
#
|
20
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
21
|
-
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22
|
-
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
23
|
-
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
24
|
-
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
25
|
-
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
26
|
-
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27
|
-
|
28
|
-
from __future__ import print_function, absolute_import
|
29
|
-
|
30
|
-
from logging import getLogger
|
31
|
-
import ctypes.util
|
32
|
-
import functools
|
33
|
-
import os
|
34
|
-
import sys
|
35
|
-
import sysconfig
|
36
|
-
import re
|
37
|
-
|
38
|
-
logger = getLogger("find_libpython")
|
39
|
-
|
40
|
-
is_windows = os.name == "nt"
|
41
|
-
is_apple = sys.platform == "darwin"
|
42
|
-
|
43
|
-
SHLIB_SUFFIX = sysconfig.get_config_var("SHLIB_SUFFIX")
|
44
|
-
if SHLIB_SUFFIX is None:
|
45
|
-
if is_windows:
|
46
|
-
SHLIB_SUFFIX = ".dll"
|
47
|
-
else:
|
48
|
-
SHLIB_SUFFIX = ".so"
|
49
|
-
if is_apple:
|
50
|
-
# sysconfig.get_config_var("SHLIB_SUFFIX") can be ".so" in macOS.
|
51
|
-
# Let's not use the value from sysconfig.
|
52
|
-
SHLIB_SUFFIX = ".dylib"
|
53
|
-
|
54
|
-
|
55
|
-
def linked_libpython():
|
56
|
-
"""
|
57
|
-
Find the linked libpython using dladdr (in *nix).
|
58
|
-
|
59
|
-
Calling this in Windows always return `None` at the moment.
|
60
|
-
|
61
|
-
Returns
|
62
|
-
-------
|
63
|
-
path : str or None
|
64
|
-
A path to linked libpython. Return `None` if statically linked.
|
65
|
-
"""
|
66
|
-
if is_windows:
|
67
|
-
return None
|
68
|
-
return _linked_libpython_unix()
|
69
|
-
|
70
|
-
|
71
|
-
class Dl_info(ctypes.Structure):
|
72
|
-
_fields_ = [
|
73
|
-
("dli_fname", ctypes.c_char_p),
|
74
|
-
("dli_fbase", ctypes.c_void_p),
|
75
|
-
("dli_sname", ctypes.c_char_p),
|
76
|
-
("dli_saddr", ctypes.c_void_p),
|
77
|
-
]
|
78
|
-
|
79
|
-
|
80
|
-
def _linked_libpython_unix():
|
81
|
-
libdl = ctypes.CDLL(ctypes.util.find_library("dl"))
|
82
|
-
libdl.dladdr.argtypes = [ctypes.c_void_p, ctypes.POINTER(Dl_info)]
|
83
|
-
libdl.dladdr.restype = ctypes.c_int
|
84
|
-
|
85
|
-
dlinfo = Dl_info()
|
86
|
-
retcode = libdl.dladdr(
|
87
|
-
ctypes.cast(ctypes.pythonapi.Py_GetVersion, ctypes.c_void_p),
|
88
|
-
ctypes.pointer(dlinfo))
|
89
|
-
if retcode == 0: # means error
|
90
|
-
return None
|
91
|
-
path = os.path.realpath(dlinfo.dli_fname.decode())
|
92
|
-
if path == os.path.realpath(sys.executable):
|
93
|
-
return None
|
94
|
-
return path
|
95
|
-
|
96
|
-
|
97
|
-
def library_name(name, suffix=SHLIB_SUFFIX, is_windows=is_windows):
|
98
|
-
"""
|
99
|
-
Convert a file basename `name` to a library name (no "lib" and ".so" etc.)
|
100
|
-
|
101
|
-
>>> library_name("libpython3.7m.so") # doctest: +SKIP
|
102
|
-
'python3.7m'
|
103
|
-
>>> library_name("libpython3.7m.so", suffix=".so", is_windows=False)
|
104
|
-
'python3.7m'
|
105
|
-
>>> library_name("libpython3.7m.dylib", suffix=".dylib", is_windows=False)
|
106
|
-
'python3.7m'
|
107
|
-
>>> library_name("python37.dll", suffix=".dll", is_windows=True)
|
108
|
-
'python37'
|
109
|
-
"""
|
110
|
-
if not is_windows and name.startswith("lib"):
|
111
|
-
name = name[len("lib"):]
|
112
|
-
if suffix and name.endswith(suffix):
|
113
|
-
name = name[:-len(suffix)]
|
114
|
-
return name
|
115
|
-
|
116
|
-
|
117
|
-
def append_truthy(list, item):
|
118
|
-
if item:
|
119
|
-
list.append(item)
|
120
|
-
|
121
|
-
|
122
|
-
def uniquifying(items):
|
123
|
-
"""
|
124
|
-
Yield items while excluding the duplicates and preserving the order.
|
125
|
-
|
126
|
-
>>> list(uniquifying([1, 2, 1, 2, 3]))
|
127
|
-
[1, 2, 3]
|
128
|
-
"""
|
129
|
-
seen = set()
|
130
|
-
for x in items:
|
131
|
-
if x not in seen:
|
132
|
-
yield x
|
133
|
-
seen.add(x)
|
134
|
-
|
135
|
-
|
136
|
-
def uniquified(func):
|
137
|
-
""" Wrap iterator returned from `func` by `uniquifying`. """
|
138
|
-
@functools.wraps(func)
|
139
|
-
def wrapper(*args, **kwds):
|
140
|
-
return uniquifying(func(*args, **kwds))
|
141
|
-
return wrapper
|
142
|
-
|
143
|
-
|
144
|
-
@uniquified
|
145
|
-
def candidate_names(suffix=SHLIB_SUFFIX):
|
146
|
-
"""
|
147
|
-
Iterate over candidate file names of libpython.
|
148
|
-
|
149
|
-
Yields
|
150
|
-
------
|
151
|
-
name : str
|
152
|
-
Candidate name libpython.
|
153
|
-
"""
|
154
|
-
LDLIBRARY = sysconfig.get_config_var("LDLIBRARY")
|
155
|
-
if LDLIBRARY:
|
156
|
-
yield LDLIBRARY
|
157
|
-
|
158
|
-
LIBRARY = sysconfig.get_config_var("LIBRARY")
|
159
|
-
if LIBRARY:
|
160
|
-
yield os.path.splitext(LIBRARY)[0] + suffix
|
161
|
-
|
162
|
-
dlprefix = "" if is_windows else "lib"
|
163
|
-
sysdata = dict(
|
164
|
-
v=sys.version_info,
|
165
|
-
# VERSION is X.Y in Linux/macOS and XY in Windows:
|
166
|
-
VERSION=(sysconfig.get_config_var("VERSION") or
|
167
|
-
"{v.major}.{v.minor}".format(v=sys.version_info)),
|
168
|
-
ABIFLAGS=(sysconfig.get_config_var("ABIFLAGS") or
|
169
|
-
sysconfig.get_config_var("abiflags") or ""),
|
170
|
-
)
|
171
|
-
|
172
|
-
for stem in [
|
173
|
-
"python{VERSION}{ABIFLAGS}".format(**sysdata),
|
174
|
-
"python{VERSION}".format(**sysdata),
|
175
|
-
"python{v.major}".format(**sysdata),
|
176
|
-
"python",
|
177
|
-
]:
|
178
|
-
yield dlprefix + stem + suffix
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
@uniquified
|
183
|
-
def candidate_paths(suffix=SHLIB_SUFFIX):
|
184
|
-
"""
|
185
|
-
Iterate over candidate paths of libpython.
|
186
|
-
|
187
|
-
Yields
|
188
|
-
------
|
189
|
-
path : str or None
|
190
|
-
Candidate path to libpython. The path may not be a fullpath
|
191
|
-
and may not exist.
|
192
|
-
"""
|
193
|
-
|
194
|
-
yield linked_libpython()
|
195
|
-
|
196
|
-
# List candidates for directories in which libpython may exist
|
197
|
-
lib_dirs = []
|
198
|
-
append_truthy(lib_dirs, sysconfig.get_config_var('LIBPL'))
|
199
|
-
append_truthy(lib_dirs, sysconfig.get_config_var('srcdir'))
|
200
|
-
append_truthy(lib_dirs, sysconfig.get_config_var("LIBDIR"))
|
201
|
-
|
202
|
-
# LIBPL seems to be the right config_var to use. It is the one
|
203
|
-
# used in python-config when shared library is not enabled:
|
204
|
-
# https://github.com/python/cpython/blob/v3.7.0/Misc/python-config.in#L55-L57
|
205
|
-
#
|
206
|
-
# But we try other places just in case.
|
207
|
-
|
208
|
-
if is_windows:
|
209
|
-
lib_dirs.append(os.path.join(os.path.dirname(sys.executable)))
|
210
|
-
else:
|
211
|
-
lib_dirs.append(os.path.join(
|
212
|
-
os.path.dirname(os.path.dirname(sys.executable)),
|
213
|
-
"lib"))
|
214
|
-
|
215
|
-
# For macOS:
|
216
|
-
append_truthy(lib_dirs, sysconfig.get_config_var("PYTHONFRAMEWORKPREFIX"))
|
217
|
-
|
218
|
-
lib_dirs.append(sys.exec_prefix)
|
219
|
-
lib_dirs.append(os.path.join(sys.exec_prefix, "lib"))
|
220
|
-
|
221
|
-
lib_basenames = list(candidate_names(suffix=suffix))
|
222
|
-
|
223
|
-
for directory in lib_dirs:
|
224
|
-
for basename in lib_basenames:
|
225
|
-
yield os.path.join(directory, basename)
|
226
|
-
|
227
|
-
# In macOS and Windows, ctypes.util.find_library returns a full path:
|
228
|
-
for basename in lib_basenames:
|
229
|
-
yield ctypes.util.find_library(library_name(basename))
|
230
|
-
|
231
|
-
# Possibly useful links:
|
232
|
-
# * https://packages.ubuntu.com/bionic/amd64/libpython3.6/filelist
|
233
|
-
# * https://github.com/Valloric/ycmd/issues/518
|
234
|
-
# * https://github.com/Valloric/ycmd/pull/519
|
235
|
-
|
236
|
-
|
237
|
-
def normalize_path(path, suffix=SHLIB_SUFFIX, is_apple=is_apple):
|
238
|
-
"""
|
239
|
-
Normalize shared library `path` to a real path.
|
240
|
-
|
241
|
-
If `path` is not a full path, `None` is returned. If `path` does
|
242
|
-
not exists, append `SHLIB_SUFFIX` and check if it exists.
|
243
|
-
Finally, the path is canonicalized by following the symlinks.
|
244
|
-
|
245
|
-
Parameters
|
246
|
-
----------
|
247
|
-
path : str ot None
|
248
|
-
A candidate path to a shared library.
|
249
|
-
"""
|
250
|
-
if not path:
|
251
|
-
return None
|
252
|
-
if not os.path.isabs(path):
|
253
|
-
return None
|
254
|
-
if os.path.exists(path):
|
255
|
-
return os.path.realpath(path)
|
256
|
-
if os.path.exists(path + suffix):
|
257
|
-
return os.path.realpath(path + suffix)
|
258
|
-
if is_apple:
|
259
|
-
return normalize_path(_remove_suffix_apple(path),
|
260
|
-
suffix=".so", is_apple=False)
|
261
|
-
return None
|
262
|
-
|
263
|
-
|
264
|
-
def _remove_suffix_apple(path):
|
265
|
-
"""
|
266
|
-
Strip off .so or .dylib.
|
267
|
-
|
268
|
-
>>> _remove_suffix_apple("libpython.so")
|
269
|
-
'libpython'
|
270
|
-
>>> _remove_suffix_apple("libpython.dylib")
|
271
|
-
'libpython'
|
272
|
-
>>> _remove_suffix_apple("libpython3.7")
|
273
|
-
'libpython3.7'
|
274
|
-
"""
|
275
|
-
if path.endswith(".dylib"):
|
276
|
-
return path[:-len(".dylib")]
|
277
|
-
if path.endswith(".so"):
|
278
|
-
return path[:-len(".so")]
|
279
|
-
return path
|
280
|
-
|
281
|
-
|
282
|
-
@uniquified
|
283
|
-
def finding_libpython():
|
284
|
-
"""
|
285
|
-
Iterate over existing libpython paths.
|
286
|
-
|
287
|
-
The first item is likely to be the best one.
|
288
|
-
|
289
|
-
Yields
|
290
|
-
------
|
291
|
-
path : str
|
292
|
-
Existing path to a libpython.
|
293
|
-
"""
|
294
|
-
logger.debug("is_windows = %s", is_windows)
|
295
|
-
logger.debug("is_apple = %s", is_apple)
|
296
|
-
for path in candidate_paths():
|
297
|
-
logger.debug("Candidate: %s", path)
|
298
|
-
normalized = normalize_path(path)
|
299
|
-
if normalized:
|
300
|
-
logger.debug("Found: %s", normalized)
|
301
|
-
yield normalized
|
302
|
-
else:
|
303
|
-
logger.debug("Not found.")
|
304
|
-
|
305
|
-
|
306
|
-
def find_libpython():
|
307
|
-
"""
|
308
|
-
Return a path (`str`) to libpython or `None` if not found.
|
309
|
-
|
310
|
-
Parameters
|
311
|
-
----------
|
312
|
-
path : str or None
|
313
|
-
Existing path to the (supposedly) correct libpython.
|
314
|
-
"""
|
315
|
-
for path in finding_libpython():
|
316
|
-
return os.path.realpath(path)
|
317
|
-
|
318
|
-
def update_dynalib_path(dynalib_path):
|
319
|
-
# Determine the environment variable based on the operating system
|
320
|
-
env_var = 'PATH'
|
321
|
-
if not sys.platform.startswith('win'):
|
322
|
-
if sys.platform == 'darwin':
|
323
|
-
env_var = 'DYLD_LIBRARY_PATH'
|
324
|
-
else:
|
325
|
-
env_var = 'LD_LIBRARY_PATH'
|
326
|
-
|
327
|
-
# Get the current value of the environment variable
|
328
|
-
current_paths = os.environ.get(env_var, '')
|
329
|
-
|
330
|
-
# Update the environment variable by appending the dynalib path
|
331
|
-
# Note: You can prepend instead by reversing the order in the join
|
332
|
-
new_paths = f"{current_paths}:{dynalib_path}" if current_paths else dynalib_path
|
333
|
-
|
334
|
-
# Update the environment variable
|
335
|
-
os.environ[env_var] = new_paths
|
336
|
-
|
File without changes
|
File without changes
|