sip-python 0.0.1__cp310-cp310-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.
sip_python/__init__.py ADDED
@@ -0,0 +1,13 @@
1
+ """""" # start delvewheel patch
2
+ def _delvewheel_patch_1_10_1():
3
+ import os
4
+ if os.path.isdir(libs_dir := os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir, 'sip_python.libs'))):
5
+ os.add_dll_directory(libs_dir)
6
+
7
+
8
+ _delvewheel_patch_1_10_1()
9
+ del _delvewheel_patch_1_10_1
10
+ # end delvewheel patch
11
+
12
+ from .sip_python_ext import *
13
+ from .helpers import get_kkt_perm_inv, get_kkt_and_L_nnzs
sip_python/helpers.py ADDED
@@ -0,0 +1,89 @@
1
+ import warnings
2
+
3
+ import numpy as np
4
+ from scipy import sparse as spa
5
+
6
+ from .sip_python_ext import getLnnz
7
+
8
+
9
+ _cvxopt_available = False
10
+ try:
11
+ from cvxopt import amd, spmatrix
12
+
13
+ _cvxopt_available = True
14
+ except ImportError:
15
+ from scipy.sparse.csgraph import reverse_cuthill_mckee
16
+
17
+
18
+ def _get_K(P, A, G):
19
+ # K = [ P + r1 I_x A.T G.T ]
20
+ # [ A -r2 * I_y 0 ]
21
+ # [ G 0 -r3 I_z ]
22
+
23
+ if isinstance(P, np.ndarray):
24
+ P = spa.csc_matrix(P)
25
+
26
+ if isinstance(A, np.ndarray):
27
+ A = spa.csr_matrix(A)
28
+
29
+ if isinstance(G, np.ndarray):
30
+ G = spa.csr_matrix(G)
31
+
32
+ x_dim = P.shape[0]
33
+ s_dim = G.shape[0]
34
+ y_dim = A.shape[0]
35
+
36
+ mod_P = spa.csc_matrix.copy(P)
37
+ mod_P.data[:] = 1.0
38
+
39
+ Z = spa.csc_matrix((y_dim, s_dim))
40
+
41
+ K = spa.block_array(
42
+ blocks=[
43
+ [mod_P + spa.eye(x_dim), A.T, G.T],
44
+ [A, -spa.eye(y_dim), Z],
45
+ [G, Z.T, -spa.eye(s_dim)],
46
+ ],
47
+ format="coo",
48
+ )
49
+
50
+ return K
51
+
52
+
53
+ def _get_kkt_perm(P, A, G, verbose):
54
+ K = _get_K(P=P, A=A, G=G)
55
+
56
+ if _cvxopt_available:
57
+ K_cvxopt = spmatrix(
58
+ I=K.row,
59
+ J=K.col,
60
+ V=K.data,
61
+ )
62
+ return np.array(list(amd.order(K_cvxopt)))
63
+ if verbose:
64
+ warnings.warn(
65
+ "cvxopt not installed; using reverse Cuthill-McKee (RCM) "
66
+ "instead of approximate minimum degree (AMD)."
67
+ )
68
+ return reverse_cuthill_mckee(spa.csc_matrix(K))
69
+
70
+
71
+ def get_kkt_perm_inv(P, A, G, verbose=True):
72
+ perm = _get_kkt_perm(P=P, A=A, G=G, verbose=verbose)
73
+
74
+ perm_inv = np.empty_like(perm)
75
+ perm_inv[perm] = np.arange(perm_inv.shape[0])
76
+
77
+ return perm_inv
78
+
79
+
80
+ def get_kkt_and_L_nnzs(P, A, G, perm_inv):
81
+ K = _get_K(P=P, A=A, G=G)
82
+
83
+ permuted_K = spa.coo_matrix.copy(K)
84
+ permuted_K.row = perm_inv[permuted_K.row]
85
+ permuted_K.col = perm_inv[permuted_K.col]
86
+
87
+ kkt_L_nnz = getLnnz(spa.triu(permuted_K))
88
+
89
+ return K.nnz, kkt_L_nnz
sip_python/py.typed ADDED
File without changes
Binary file
@@ -0,0 +1,400 @@
1
+ from collections.abc import Callable
2
+ import enum
3
+ from typing import Annotated
4
+
5
+ from numpy.typing import ArrayLike
6
+ import scipy.sparse
7
+
8
+
9
+ FAILED_CHECK: Status = Status.FAILED_CHECK
10
+
11
+ ITERATION_LIMIT: Status = Status.ITERATION_LIMIT
12
+
13
+ LINE_SEARCH_FAILURE: Status = Status.LINE_SEARCH_FAILURE
14
+
15
+ LINE_SEARCH_ITERATION_LIMIT: Status = Status.LINE_SEARCH_ITERATION_LIMIT
16
+
17
+ class ModelCallbackInput:
18
+ def __init__(self, problem_dimensions: ProblemDimensions) -> None: ...
19
+
20
+ @property
21
+ def x(self) -> Annotated[ArrayLike, dict(dtype='float64', shape=(None))]: ...
22
+
23
+ @property
24
+ def y(self) -> Annotated[ArrayLike, dict(dtype='float64', shape=(None))]: ...
25
+
26
+ @property
27
+ def z(self) -> Annotated[ArrayLike, dict(dtype='float64', shape=(None))]: ...
28
+
29
+ class ModelCallbackOutput:
30
+ def __init__(self) -> None: ...
31
+
32
+ @property
33
+ def f(self) -> float: ...
34
+
35
+ @f.setter
36
+ def f(self, arg: float, /) -> None: ...
37
+
38
+ @property
39
+ def gradient_f(self) -> Annotated[ArrayLike, dict(dtype='float64', shape=(None))]: ...
40
+
41
+ @gradient_f.setter
42
+ def gradient_f(self, arg: Annotated[ArrayLike, dict(dtype='float64', shape=(None))], /) -> None: ...
43
+
44
+ @property
45
+ def upper_hessian_lagrangian(self) -> scipy.sparse.csc_matrix[float]: ...
46
+
47
+ @upper_hessian_lagrangian.setter
48
+ def upper_hessian_lagrangian(self, arg: scipy.sparse.csc_matrix[float], /) -> None: ...
49
+
50
+ @property
51
+ def c(self) -> Annotated[ArrayLike, dict(dtype='float64', shape=(None))]: ...
52
+
53
+ @c.setter
54
+ def c(self, arg: Annotated[ArrayLike, dict(dtype='float64', shape=(None))], /) -> None: ...
55
+
56
+ @property
57
+ def jacobian_c(self) -> scipy.sparse.csr_matrix[float]: ...
58
+
59
+ @jacobian_c.setter
60
+ def jacobian_c(self, arg: scipy.sparse.csr_matrix[float], /) -> None: ...
61
+
62
+ @property
63
+ def g(self) -> Annotated[ArrayLike, dict(dtype='float64', shape=(None))]: ...
64
+
65
+ @g.setter
66
+ def g(self, arg: Annotated[ArrayLike, dict(dtype='float64', shape=(None))], /) -> None: ...
67
+
68
+ @property
69
+ def jacobian_g(self) -> scipy.sparse.csr_matrix[float]: ...
70
+
71
+ @jacobian_g.setter
72
+ def jacobian_g(self, arg: scipy.sparse.csr_matrix[float], /) -> None: ...
73
+
74
+ class OutputStatus:
75
+ def __init__(self) -> None: ...
76
+
77
+ @property
78
+ def exit_status(self) -> Status: ...
79
+
80
+ @property
81
+ def num_iterations(self) -> int: ...
82
+
83
+ @property
84
+ def max_primal_violation(self) -> float: ...
85
+
86
+ @property
87
+ def max_dual_violation(self) -> float: ...
88
+
89
+ class ProblemDimensions:
90
+ def __init__(self) -> None: ...
91
+
92
+ @property
93
+ def x_dim(self) -> int: ...
94
+
95
+ @x_dim.setter
96
+ def x_dim(self, arg: int, /) -> None: ...
97
+
98
+ @property
99
+ def s_dim(self) -> int: ...
100
+
101
+ @s_dim.setter
102
+ def s_dim(self, arg: int, /) -> None: ...
103
+
104
+ @property
105
+ def y_dim(self) -> int: ...
106
+
107
+ @y_dim.setter
108
+ def y_dim(self, arg: int, /) -> None: ...
109
+
110
+ @property
111
+ def upper_hessian_lagrangian_nnz(self) -> int: ...
112
+
113
+ @upper_hessian_lagrangian_nnz.setter
114
+ def upper_hessian_lagrangian_nnz(self, arg: int, /) -> None: ...
115
+
116
+ @property
117
+ def jacobian_c_nnz(self) -> int: ...
118
+
119
+ @jacobian_c_nnz.setter
120
+ def jacobian_c_nnz(self, arg: int, /) -> None: ...
121
+
122
+ @property
123
+ def jacobian_g_nnz(self) -> int: ...
124
+
125
+ @jacobian_g_nnz.setter
126
+ def jacobian_g_nnz(self, arg: int, /) -> None: ...
127
+
128
+ @property
129
+ def kkt_nnz(self) -> int: ...
130
+
131
+ @kkt_nnz.setter
132
+ def kkt_nnz(self, arg: int, /) -> None: ...
133
+
134
+ @property
135
+ def kkt_L_nnz(self) -> int: ...
136
+
137
+ @kkt_L_nnz.setter
138
+ def kkt_L_nnz(self, arg: int, /) -> None: ...
139
+
140
+ @property
141
+ def is_jacobian_c_transposed(self) -> bool: ...
142
+
143
+ @is_jacobian_c_transposed.setter
144
+ def is_jacobian_c_transposed(self, arg: bool, /) -> None: ...
145
+
146
+ @property
147
+ def is_jacobian_g_transposed(self) -> bool: ...
148
+
149
+ @is_jacobian_g_transposed.setter
150
+ def is_jacobian_g_transposed(self, arg: bool, /) -> None: ...
151
+
152
+ class QDLDLSettings:
153
+ def __init__(self) -> None: ...
154
+
155
+ @property
156
+ def permute_kkt_system(self) -> bool: ...
157
+
158
+ @permute_kkt_system.setter
159
+ def permute_kkt_system(self, arg: bool, /) -> None: ...
160
+
161
+ @property
162
+ def kkt_pinv(self) -> Annotated[ArrayLike, dict(dtype='int32', shape=(None))]: ...
163
+
164
+ @kkt_pinv.setter
165
+ def kkt_pinv(self, arg: Annotated[ArrayLike, dict(dtype='int32', shape=(None))], /) -> None: ...
166
+
167
+ SOLVED: Status = Status.SOLVED
168
+
169
+ class Settings:
170
+ def __init__(self) -> None: ...
171
+
172
+ @property
173
+ def max_iterations(self) -> int: ...
174
+
175
+ @max_iterations.setter
176
+ def max_iterations(self, arg: int, /) -> None: ...
177
+
178
+ @property
179
+ def max_ls_iterations(self) -> int: ...
180
+
181
+ @max_ls_iterations.setter
182
+ def max_ls_iterations(self, arg: int, /) -> None: ...
183
+
184
+ @property
185
+ def min_iterations_for_convergence(self) -> int: ...
186
+
187
+ @min_iterations_for_convergence.setter
188
+ def min_iterations_for_convergence(self, arg: int, /) -> None: ...
189
+
190
+ @property
191
+ def num_iterative_refinement_steps(self) -> int: ...
192
+
193
+ @num_iterative_refinement_steps.setter
194
+ def num_iterative_refinement_steps(self, arg: int, /) -> None: ...
195
+
196
+ @property
197
+ def max_aug_kkt_violation(self) -> float: ...
198
+
199
+ @max_aug_kkt_violation.setter
200
+ def max_aug_kkt_violation(self, arg: float, /) -> None: ...
201
+
202
+ @property
203
+ def max_merit_slope(self) -> float: ...
204
+
205
+ @max_merit_slope.setter
206
+ def max_merit_slope(self, arg: float, /) -> None: ...
207
+
208
+ @property
209
+ def tau(self) -> float: ...
210
+
211
+ @tau.setter
212
+ def tau(self, arg: float, /) -> None: ...
213
+
214
+ @property
215
+ def start_ls_with_alpha_s_max(self) -> bool: ...
216
+
217
+ @start_ls_with_alpha_s_max.setter
218
+ def start_ls_with_alpha_s_max(self, arg: bool, /) -> None: ...
219
+
220
+ @property
221
+ def initial_mu(self) -> float: ...
222
+
223
+ @initial_mu.setter
224
+ def initial_mu(self, arg: float, /) -> None: ...
225
+
226
+ @property
227
+ def mu_update_factor(self) -> float: ...
228
+
229
+ @mu_update_factor.setter
230
+ def mu_update_factor(self, arg: float, /) -> None: ...
231
+
232
+ @property
233
+ def mu_min(self) -> float: ...
234
+
235
+ @mu_min.setter
236
+ def mu_min(self, arg: float, /) -> None: ...
237
+
238
+ @property
239
+ def initial_penalty_parameter(self) -> float: ...
240
+
241
+ @initial_penalty_parameter.setter
242
+ def initial_penalty_parameter(self, arg: float, /) -> None: ...
243
+
244
+ @property
245
+ def min_acceptable_constraint_violation_ratio(self) -> float: ...
246
+
247
+ @min_acceptable_constraint_violation_ratio.setter
248
+ def min_acceptable_constraint_violation_ratio(self, arg: float, /) -> None: ...
249
+
250
+ @property
251
+ def penalty_parameter_increase_factor(self) -> float: ...
252
+
253
+ @penalty_parameter_increase_factor.setter
254
+ def penalty_parameter_increase_factor(self, arg: float, /) -> None: ...
255
+
256
+ @property
257
+ def penalty_parameter_decrease_factor(self) -> float: ...
258
+
259
+ @penalty_parameter_decrease_factor.setter
260
+ def penalty_parameter_decrease_factor(self, arg: float, /) -> None: ...
261
+
262
+ @property
263
+ def max_penalty_parameter(self) -> float: ...
264
+
265
+ @max_penalty_parameter.setter
266
+ def max_penalty_parameter(self, arg: float, /) -> None: ...
267
+
268
+ @property
269
+ def armijo_factor(self) -> float: ...
270
+
271
+ @armijo_factor.setter
272
+ def armijo_factor(self, arg: float, /) -> None: ...
273
+
274
+ @property
275
+ def line_search_factor(self) -> float: ...
276
+
277
+ @line_search_factor.setter
278
+ def line_search_factor(self, arg: float, /) -> None: ...
279
+
280
+ @property
281
+ def line_search_min_step_size(self) -> float: ...
282
+
283
+ @line_search_min_step_size.setter
284
+ def line_search_min_step_size(self, arg: float, /) -> None: ...
285
+
286
+ @property
287
+ def min_merit_slope_to_skip_line_search(self) -> float: ...
288
+
289
+ @min_merit_slope_to_skip_line_search.setter
290
+ def min_merit_slope_to_skip_line_search(self, arg: float, /) -> None: ...
291
+
292
+ @property
293
+ def enable_elastics(self) -> bool: ...
294
+
295
+ @enable_elastics.setter
296
+ def enable_elastics(self, arg: bool, /) -> None: ...
297
+
298
+ @property
299
+ def elastic_var_cost_coeff(self) -> float: ...
300
+
301
+ @elastic_var_cost_coeff.setter
302
+ def elastic_var_cost_coeff(self, arg: float, /) -> None: ...
303
+
304
+ @property
305
+ def enable_line_search_failures(self) -> bool: ...
306
+
307
+ @enable_line_search_failures.setter
308
+ def enable_line_search_failures(self, arg: bool, /) -> None: ...
309
+
310
+ @property
311
+ def print_logs(self) -> bool: ...
312
+
313
+ @print_logs.setter
314
+ def print_logs(self, arg: bool, /) -> None: ...
315
+
316
+ @property
317
+ def print_line_search_logs(self) -> bool: ...
318
+
319
+ @print_line_search_logs.setter
320
+ def print_line_search_logs(self, arg: bool, /) -> None: ...
321
+
322
+ @property
323
+ def print_search_direction_logs(self) -> bool: ...
324
+
325
+ @print_search_direction_logs.setter
326
+ def print_search_direction_logs(self, arg: bool, /) -> None: ...
327
+
328
+ @property
329
+ def print_derivative_check_logs(self) -> bool: ...
330
+
331
+ @print_derivative_check_logs.setter
332
+ def print_derivative_check_logs(self, arg: bool, /) -> None: ...
333
+
334
+ @property
335
+ def only_check_search_direction_slope(self) -> bool: ...
336
+
337
+ @only_check_search_direction_slope.setter
338
+ def only_check_search_direction_slope(self, arg: bool, /) -> None: ...
339
+
340
+ @property
341
+ def assert_checks_pass(self) -> bool: ...
342
+
343
+ @assert_checks_pass.setter
344
+ def assert_checks_pass(self, arg: bool, /) -> None: ...
345
+
346
+ class Solver:
347
+ def __init__(self, sip_settings: Settings, qdldl_settings: QDLDLSettings, problem_dimension: ProblemDimensions, model_callback: Callable[[ModelCallbackInput], ModelCallbackOutput]) -> None: ...
348
+
349
+ def solve(self, arg: Variables, /) -> OutputStatus: ...
350
+
351
+ class Status(enum.Enum):
352
+ SOLVED = 0
353
+
354
+ ITERATION_LIMIT = 1
355
+
356
+ LINE_SEARCH_ITERATION_LIMIT = 2
357
+
358
+ LINE_SEARCH_FAILURE = 3
359
+
360
+ TIMEOUT = 4
361
+
362
+ FAILED_CHECK = 5
363
+
364
+ TIMEOUT: Status = Status.TIMEOUT
365
+
366
+ class Variables:
367
+ def __init__(self, problem_dimensions: ProblemDimensions) -> None: ...
368
+
369
+ @property
370
+ def x(self) -> Annotated[ArrayLike, dict(dtype='float64', shape=(None))]: ...
371
+
372
+ @x.setter
373
+ def x(self, arg: Annotated[ArrayLike, dict(dtype='float64', shape=(None))], /) -> None: ...
374
+
375
+ @property
376
+ def s(self) -> Annotated[ArrayLike, dict(dtype='float64', shape=(None))]: ...
377
+
378
+ @s.setter
379
+ def s(self, arg: Annotated[ArrayLike, dict(dtype='float64', shape=(None))], /) -> None: ...
380
+
381
+ @property
382
+ def e(self) -> Annotated[ArrayLike, dict(dtype='float64', shape=(None))]: ...
383
+
384
+ @e.setter
385
+ def e(self, arg: Annotated[ArrayLike, dict(dtype='float64', shape=(None))], /) -> None: ...
386
+
387
+ @property
388
+ def y(self) -> Annotated[ArrayLike, dict(dtype='float64', shape=(None))]: ...
389
+
390
+ @y.setter
391
+ def y(self, arg: Annotated[ArrayLike, dict(dtype='float64', shape=(None))], /) -> None: ...
392
+
393
+ @property
394
+ def z(self) -> Annotated[ArrayLike, dict(dtype='float64', shape=(None))]: ...
395
+
396
+ @z.setter
397
+ def z(self, arg: Annotated[ArrayLike, dict(dtype='float64', shape=(None))], /) -> None: ...
398
+
399
+ def getLnnz(arg: scipy.sparse.csc_matrix[float], /) -> int:
400
+ """Computes L's nnz for an L D L^T decomposition."""
@@ -0,0 +1,2 @@
1
+ Version: 1.10.1
2
+ Arguments: ['C:\\hostedtoolcache\\windows\\Python\\3.13.3\\x64\\Scripts\\delvewheel', 'repair', '-w', 'C:\\Users\\runneradmin\\AppData\\Local\\Temp\\cibw-run-b55lr07d\\cp310-win_amd64\\repaired_wheel', 'C:\\Users\\runneradmin\\AppData\\Local\\Temp\\cibw-run-b55lr07d\\cp310-win_amd64\\built_wheel\\sip_python-0.0.1-cp310-cp310-win_amd64.whl']
@@ -0,0 +1,21 @@
1
+ Metadata-Version: 2.4
2
+ Name: sip_python
3
+ Version: 0.0.1
4
+ Summary: Python bindings for the SIP solver.
5
+ Author-email: João Sousa-Pinto <joaospinto@gmail.com>
6
+ Project-URL: Homepage, https://github.com/joaospinto/sip_python
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Operating System :: OS Independent
9
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
10
+ Requires-Python: >=3.10
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: numpy
14
+ Requires-Dist: scipy
15
+ Dynamic: license-file
16
+
17
+ # sip_python
18
+ [![pip](https://github.com/joaospinto/sip_python/actions/workflows/pip.yml/badge.svg)](https://github.com/joaospinto/sip_python/actions?query=workflow%3Apip)
19
+ [![wheels](https://github.com/joaospinto/sip_python/actions/workflows/wheels.yml/badge.svg)](https://github.com/joaospinto/sip_python/actions?query=workflow%3Awheels)
20
+
21
+ Python bindings for the [SIP](https://github.com/joaospinto/sip) solver.
@@ -0,0 +1,12 @@
1
+ sip_python/helpers.py,sha256=44t4P3BhlxAEIr0Lmw-Zt4YkYssHA-jCuyA6Q445zd4,2098
2
+ sip_python/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ sip_python/sip_python_ext.pyd,sha256=CHrPTX5muPpO7TANaw9OJo4L0pfGIm_9HAQOOIYERn8,305664
4
+ sip_python/sip_python_ext.pyi,sha256=hYmztEDaaPINBGa7REg5QOnwrQLWY9uskXdx1kjgugw,11336
5
+ sip_python/__init__.py,sha256=gokroSC0YGqyBN8dqZL2ni488eipzH_Yg7_sOJz8LhE,422
6
+ sip_python-0.0.1.dist-info/DELVEWHEEL,sha256=lzDj30VBORigyz0aE4BRqAUOB4uOTfZ_8E9vmibF4pQ,359
7
+ sip_python-0.0.1.dist-info/METADATA,sha256=J68kGdF84fbOctIci3t4QcodGwoJLsLmXHKGVTVJbug,956
8
+ sip_python-0.0.1.dist-info/RECORD,,
9
+ sip_python-0.0.1.dist-info/top_level.txt,sha256=5QmJfOhrh7J2oFyurVi_u8iADQdBrS2anrclo5fn0Bg,11
10
+ sip_python-0.0.1.dist-info/WHEEL,sha256=AVu1DavlWPCypqX8sBQ58NLvImUaO9Rw16t7hIak0pw,101
11
+ sip_python-0.0.1.dist-info/licenses/LICENSE,sha256=jPWDEHod2x7776vWNSNBO1hb1it373Jo5LQWtASxXTw,1095
12
+ sip_python.libs/msvcp140-2f8cc3346207715d602d6abb85136fdb.dll,sha256=pMIim9wqKmMKzcCVtNhgCOXD47x3cxdDVPPaT1vrnN4,575056
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.1.0)
3
+ Root-Is-Purelib: false
4
+ Tag: cp310-cp310-win_amd64
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 João Sousa Pinto
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ sip_python