2 |
3 |
4 |
5 |
6 | Uses of Class org.bytedeco.embeddedpython.NpNdarray (javacpp-embedded-python 1.0.0-SNAPSHOT API)
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
32 |
33 | JavaScript is disabled on your browser.
34 |
35 |
36 |
37 |
38 |
39 |
56 |
57 |
60 |
66 |
67 |
77 |
78 | JavaScript is disabled on your browser.
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
91 |
92 |
93 |
94 |
97 |
167 |
168 |
214 |
215 |
216 |
--------------------------------------------------------------------------------
/docs/apidocs/org/bytedeco/embeddedpython/class-use/NpNdarrayBoolean.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Uses of Class org.bytedeco.embeddedpython.NpNdarrayBoolean (javacpp-embedded-python 1.0.0-SNAPSHOT API)
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
32 |
33 | JavaScript is disabled on your browser.
34 |
35 |
36 |
37 |
38 |
39 |
56 |
57 |
60 |
66 |
67 |
77 |
78 | JavaScript is disabled on your browser.
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
91 |
92 |
93 |
94 |
97 | No usage of org.bytedeco.embeddedpython.NpNdarrayBoolean
98 |
99 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/docs/apidocs/org/bytedeco/embeddedpython/class-use/NpNdarrayByte.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Uses of Class org.bytedeco.embeddedpython.NpNdarrayByte (javacpp-embedded-python 1.0.0-SNAPSHOT API)
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
32 |
33 | JavaScript is disabled on your browser.
34 |
35 |
36 |
37 |
38 |
39 |
56 |
57 |
60 |
66 |
67 |
77 |
78 | JavaScript is disabled on your browser.
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
91 |
92 |
93 |
94 |
97 | No usage of org.bytedeco.embeddedpython.NpNdarrayByte
98 |
99 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/docs/apidocs/org/bytedeco/embeddedpython/class-use/NpNdarrayChar.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Uses of Class org.bytedeco.embeddedpython.NpNdarrayChar (javacpp-embedded-python 1.0.0-SNAPSHOT API)
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
32 |
33 | JavaScript is disabled on your browser.
34 |
35 |
36 |
37 |
38 |
39 |
56 |
57 |
60 |
66 |
67 |
77 |
78 | JavaScript is disabled on your browser.
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
91 |
92 |
93 |
94 |
97 | No usage of org.bytedeco.embeddedpython.NpNdarrayChar
98 |
99 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/docs/apidocs/org/bytedeco/embeddedpython/class-use/NpNdarrayDouble.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Uses of Class org.bytedeco.embeddedpython.NpNdarrayDouble (javacpp-embedded-python 1.0.0-SNAPSHOT API)
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
32 |
33 | JavaScript is disabled on your browser.
34 |
35 |
36 |
37 |
38 |
39 |
56 |
57 |
60 |
66 |
67 |
77 |
78 | JavaScript is disabled on your browser.
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
91 |
92 |
93 |
94 |
97 | No usage of org.bytedeco.embeddedpython.NpNdarrayDouble
98 |
99 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/docs/apidocs/org/bytedeco/embeddedpython/class-use/NpNdarrayFloat.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Uses of Class org.bytedeco.embeddedpython.NpNdarrayFloat (javacpp-embedded-python 1.0.0-SNAPSHOT API)
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
32 |
33 | JavaScript is disabled on your browser.
34 |
35 |
36 |
37 |
38 |
39 |
56 |
57 |
60 |
66 |
67 |
77 |
78 | JavaScript is disabled on your browser.
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
91 |
92 |
93 |
94 |
97 | No usage of org.bytedeco.embeddedpython.NpNdarrayFloat
98 |
99 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/docs/apidocs/org/bytedeco/embeddedpython/class-use/NpNdarrayInstant.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Uses of Class org.bytedeco.embeddedpython.NpNdarrayInstant (javacpp-embedded-python 1.0.0-SNAPSHOT API)
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
32 |
33 | JavaScript is disabled on your browser.
34 |
35 |
36 |
37 |
38 |
39 |
56 |
57 |
60 |
66 |
67 |
77 |
78 | JavaScript is disabled on your browser.
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
91 |
92 |
93 |
94 |
97 | No usage of org.bytedeco.embeddedpython.NpNdarrayInstant
98 |
99 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/docs/apidocs/org/bytedeco/embeddedpython/class-use/NpNdarrayInt.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Uses of Class org.bytedeco.embeddedpython.NpNdarrayInt (javacpp-embedded-python 1.0.0-SNAPSHOT API)
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
32 |
33 | JavaScript is disabled on your browser.
34 |
35 |
36 |
37 |
38 |
39 |
56 |
57 |
60 |
66 |
67 |
77 |
78 | JavaScript is disabled on your browser.
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
91 |
92 |
93 |
94 |
97 | No usage of org.bytedeco.embeddedpython.NpNdarrayInt
98 |
99 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/docs/apidocs/org/bytedeco/embeddedpython/class-use/NpNdarrayLong.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Uses of Class org.bytedeco.embeddedpython.NpNdarrayLong (javacpp-embedded-python 1.0.0-SNAPSHOT API)
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
32 |
33 | JavaScript is disabled on your browser.
34 |
35 |
36 |
37 |
38 |
39 |
56 |
57 |
60 |
66 |
67 |
77 |
78 | JavaScript is disabled on your browser.
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
91 |
92 |
93 |
94 |
97 | No usage of org.bytedeco.embeddedpython.NpNdarrayLong
98 |
99 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/docs/apidocs/org/bytedeco/embeddedpython/class-use/NpNdarrayShort.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Uses of Class org.bytedeco.embeddedpython.NpNdarrayShort (javacpp-embedded-python 1.0.0-SNAPSHOT API)
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
32 |
33 | JavaScript is disabled on your browser.
34 |
35 |
36 |
37 |
38 |
39 |
56 |
57 |
60 |
66 |
67 |
77 |
78 | JavaScript is disabled on your browser.
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
91 |
92 |
93 |
94 |
97 | No usage of org.bytedeco.embeddedpython.NpNdarrayShort
98 |
99 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/docs/apidocs/org/bytedeco/embeddedpython/class-use/Pip.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Uses of Class org.bytedeco.embeddedpython.Pip (javacpp-embedded-python 1.0.0-SNAPSHOT API)
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
32 |
33 | JavaScript is disabled on your browser.
34 |
35 |
36 |
37 |
38 |
39 |
56 |
57 |
60 |
66 |
67 |
77 |
78 | JavaScript is disabled on your browser.
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
91 |
92 |
93 |
94 |
97 | No usage of org.bytedeco.embeddedpython.Pip
98 |
99 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/docs/apidocs/org/bytedeco/embeddedpython/class-use/Python.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Uses of Class org.bytedeco.embeddedpython.Python (javacpp-embedded-python 1.0.0-SNAPSHOT API)
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
32 |
33 | JavaScript is disabled on your browser.
34 |
35 |
36 |
37 |
38 |
39 |
56 |
57 |
60 |
66 |
67 |
77 |
78 | JavaScript is disabled on your browser.
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
91 |
92 |
93 |
94 |
97 | No usage of org.bytedeco.embeddedpython.Python
98 |
99 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/docs/apidocs/org/bytedeco/embeddedpython/class-use/PythonException.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Uses of Class org.bytedeco.embeddedpython.PythonException (javacpp-embedded-python 1.0.0-SNAPSHOT API)
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
32 |
33 | JavaScript is disabled on your browser.
34 |
35 |
36 |
37 |
38 |
39 |
56 |
57 |
60 |
66 |
67 |
77 |
78 | JavaScript is disabled on your browser.
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
91 |
92 |
93 |
94 |
97 | No usage of org.bytedeco.embeddedpython.PythonException
98 |
99 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/docs/apidocs/org/bytedeco/embeddedpython/package-summary.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | org.bytedeco.embeddedpython (javacpp-embedded-python 1.0.0-SNAPSHOT API)
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
32 |
33 | JavaScript is disabled on your browser.
34 |
35 |
36 |
37 |
38 |
39 |
56 |
57 |
60 |
66 |
67 |
77 |
78 | JavaScript is disabled on your browser.
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
91 |
92 |
93 |
94 |
97 |
98 |
99 |
100 |
163 |
164 |
165 |
166 | Exception Summary
167 |
168 | Exception
169 | Description
170 |
171 |
172 |
173 | PythonException
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
228 |
229 |
230 |
--------------------------------------------------------------------------------
/docs/apidocs/org/bytedeco/embeddedpython/package-tree.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | org.bytedeco.embeddedpython Class Hierarchy (javacpp-embedded-python 1.0.0-SNAPSHOT API)
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
32 |
33 | JavaScript is disabled on your browser.
34 |
35 |
36 |
37 |
38 |
39 |
56 |
57 |
60 |
66 |
67 |
77 |
78 | JavaScript is disabled on your browser.
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
91 |
92 |
93 |
94 |
97 |
98 |
99 | Class Hierarchy
100 |
101 | java.lang.Object
102 |
132 |
133 |
134 |
135 |
136 |
137 |
183 |
184 |
185 |
--------------------------------------------------------------------------------
/docs/apidocs/org/bytedeco/embeddedpython/package-use.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Uses of Package org.bytedeco.embeddedpython (javacpp-embedded-python 1.0.0-SNAPSHOT API)
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
32 |
33 | JavaScript is disabled on your browser.
34 |
35 |
36 |
37 |
38 |
39 |
56 |
57 |
60 |
66 |
67 |
77 |
78 | JavaScript is disabled on your browser.
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
91 |
92 |
93 |
94 |
97 |
120 |
121 |
167 |
168 |
169 |
--------------------------------------------------------------------------------
/docs/apidocs/overview-tree.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Class Hierarchy (javacpp-embedded-python 1.0.0-SNAPSHOT API)
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
32 |
33 | JavaScript is disabled on your browser.
34 |
35 |
36 |
37 |
38 |
39 |
56 |
57 |
60 |
66 |
67 |
77 |
78 | JavaScript is disabled on your browser.
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
91 |
92 |
93 |
94 |
101 |
102 |
103 | Class Hierarchy
104 |
105 | java.lang.Object
106 |
136 |
137 |
138 |
139 |
140 |
141 |
187 |
188 |
189 |
--------------------------------------------------------------------------------
/docs/apidocs/package-search-index.js:
--------------------------------------------------------------------------------
1 | packageSearchIndex = [{"l":"All Packages","url":"allpackages-index.html"},{"l":"org.bytedeco.embeddedpython"}]
--------------------------------------------------------------------------------
/docs/apidocs/resources/glass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bytedeco/javacpp-embedded-python/5f1188117cb8329d2d0c5bfaefd3e44b0f5ae559/docs/apidocs/resources/glass.png
--------------------------------------------------------------------------------
/docs/apidocs/resources/x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bytedeco/javacpp-embedded-python/5f1188117cb8329d2d0c5bfaefd3e44b0f5ae559/docs/apidocs/resources/x.png
--------------------------------------------------------------------------------
/docs/apidocs/script.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
3 | * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
4 | *
5 | *
6 | *
7 | *
8 | *
9 | *
10 | *
11 | *
12 | *
13 | *
14 | *
15 | *
16 | *
17 | *
18 | *
19 | *
20 | *
21 | *
22 | *
23 | *
24 | */
25 |
26 | var moduleSearchIndex;
27 | var packageSearchIndex;
28 | var typeSearchIndex;
29 | var memberSearchIndex;
30 | var tagSearchIndex;
31 | function loadScripts(doc, tag) {
32 | createElem(doc, tag, 'jquery/jszip/dist/jszip.js');
33 | createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils.js');
34 | if (window.navigator.userAgent.indexOf('MSIE ') > 0 || window.navigator.userAgent.indexOf('Trident/') > 0 ||
35 | window.navigator.userAgent.indexOf('Edge/') > 0) {
36 | createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils-ie.js');
37 | }
38 | createElem(doc, tag, 'search.js');
39 |
40 | $.get(pathtoroot + "module-search-index.zip")
41 | .done(function() {
42 | JSZipUtils.getBinaryContent(pathtoroot + "module-search-index.zip", function(e, data) {
43 | JSZip.loadAsync(data).then(function(zip){
44 | zip.file("module-search-index.json").async("text").then(function(content){
45 | moduleSearchIndex = JSON.parse(content);
46 | });
47 | });
48 | });
49 | });
50 | $.get(pathtoroot + "package-search-index.zip")
51 | .done(function() {
52 | JSZipUtils.getBinaryContent(pathtoroot + "package-search-index.zip", function(e, data) {
53 | JSZip.loadAsync(data).then(function(zip){
54 | zip.file("package-search-index.json").async("text").then(function(content){
55 | packageSearchIndex = JSON.parse(content);
56 | });
57 | });
58 | });
59 | });
60 | $.get(pathtoroot + "type-search-index.zip")
61 | .done(function() {
62 | JSZipUtils.getBinaryContent(pathtoroot + "type-search-index.zip", function(e, data) {
63 | JSZip.loadAsync(data).then(function(zip){
64 | zip.file("type-search-index.json").async("text").then(function(content){
65 | typeSearchIndex = JSON.parse(content);
66 | });
67 | });
68 | });
69 | });
70 | $.get(pathtoroot + "member-search-index.zip")
71 | .done(function() {
72 | JSZipUtils.getBinaryContent(pathtoroot + "member-search-index.zip", function(e, data) {
73 | JSZip.loadAsync(data).then(function(zip){
74 | zip.file("member-search-index.json").async("text").then(function(content){
75 | memberSearchIndex = JSON.parse(content);
76 | });
77 | });
78 | });
79 | });
80 | $.get(pathtoroot + "tag-search-index.zip")
81 | .done(function() {
82 | JSZipUtils.getBinaryContent(pathtoroot + "tag-search-index.zip", function(e, data) {
83 | JSZip.loadAsync(data).then(function(zip){
84 | zip.file("tag-search-index.json").async("text").then(function(content){
85 | tagSearchIndex = JSON.parse(content);
86 | });
87 | });
88 | });
89 | });
90 | if (!moduleSearchIndex) {
91 | createElem(doc, tag, 'module-search-index.js');
92 | }
93 | if (!packageSearchIndex) {
94 | createElem(doc, tag, 'package-search-index.js');
95 | }
96 | if (!typeSearchIndex) {
97 | createElem(doc, tag, 'type-search-index.js');
98 | }
99 | if (!memberSearchIndex) {
100 | createElem(doc, tag, 'member-search-index.js');
101 | }
102 | if (!tagSearchIndex) {
103 | createElem(doc, tag, 'tag-search-index.js');
104 | }
105 | $(window).resize(function() {
106 | $('.navPadding').css('padding-top', $('.fixedNav').css("height"));
107 | });
108 | }
109 |
110 | function createElem(doc, tag, path) {
111 | var script = doc.createElement(tag);
112 | var scriptElement = doc.getElementsByTagName(tag)[0];
113 | script.src = pathtoroot + path;
114 | scriptElement.parentNode.insertBefore(script, scriptElement);
115 | }
116 |
117 | function show(type) {
118 | count = 0;
119 | for (var key in data) {
120 | var row = document.getElementById(key);
121 | if ((data[key] & type) !== 0) {
122 | row.style.display = '';
123 | row.className = (count++ % 2) ? rowColor : altColor;
124 | }
125 | else
126 | row.style.display = 'none';
127 | }
128 | updateTabs(type);
129 | }
130 |
131 | function updateTabs(type) {
132 | for (var value in tabs) {
133 | var sNode = document.getElementById(tabs[value][0]);
134 | var spanNode = sNode.firstChild;
135 | if (value == type) {
136 | sNode.className = activeTableTab;
137 | spanNode.innerHTML = tabs[value][1];
138 | }
139 | else {
140 | sNode.className = tableTab;
141 | spanNode.innerHTML = "" + tabs[value][1] + " ";
142 | }
143 | }
144 | }
145 |
146 | function updateModuleFrame(pFrame, cFrame) {
147 | top.packageFrame.location = pFrame;
148 | top.classFrame.location = cFrame;
149 | }
150 |
--------------------------------------------------------------------------------
/docs/apidocs/type-search-index.js:
--------------------------------------------------------------------------------
1 | typeSearchIndex = [{"l":"All Classes","url":"allclasses-index.html"},{"p":"org.bytedeco.embeddedpython","l":"NpNdarray"},{"p":"org.bytedeco.embeddedpython","l":"NpNdarrayBoolean"},{"p":"org.bytedeco.embeddedpython","l":"NpNdarrayByte"},{"p":"org.bytedeco.embeddedpython","l":"NpNdarrayChar"},{"p":"org.bytedeco.embeddedpython","l":"NpNdarrayDouble"},{"p":"org.bytedeco.embeddedpython","l":"NpNdarrayFloat"},{"p":"org.bytedeco.embeddedpython","l":"NpNdarrayInstant"},{"p":"org.bytedeco.embeddedpython","l":"NpNdarrayInt"},{"p":"org.bytedeco.embeddedpython","l":"NpNdarrayLong"},{"p":"org.bytedeco.embeddedpython","l":"NpNdarrayShort"},{"p":"org.bytedeco.embeddedpython","l":"Pip"},{"p":"org.bytedeco.embeddedpython","l":"Python"},{"p":"org.bytedeco.embeddedpython","l":"PythonException"}]
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | org.bytedeco
8 | javacpp-embedded-python
9 | 1.0.0-SNAPSHOT
10 |
11 |
12 |
13 | org.bytedeco
14 | numpy
15 | 1.26.3-1.5.10
16 |
17 |
18 |
19 | org.bytedeco
20 | numpy-platform
21 | 1.26.3-1.5.10
22 | test
23 |
24 |
25 |
26 | org.scala-lang.modules
27 | scala-java8-compat_2.13
28 | 1.0.2
29 |
30 |
31 |
32 | org.junit.jupiter
33 | junit-jupiter-api
34 | 5.11.0
35 | test
36 |
37 |
38 |
39 |
40 | 8
41 | 8
42 | UTF-8
43 | UTF-8
44 |
45 |
46 |
47 | ${project.artifactId}
48 |
49 |
50 | org.apache.maven.plugins
51 | maven-compiler-plugin
52 | 3.8.1
53 |
54 | true
55 | 8
56 | 8
57 |
58 | -Xlint:unchecked
59 |
60 | true
61 | true
62 |
63 |
64 |
65 | org.apache.maven.plugins
66 | maven-jar-plugin
67 | 3.2.0
68 |
69 |
70 | org.apache.maven.plugins
71 | maven-install-plugin
72 | 3.0.0-M1
73 |
74 |
75 | org.apache.maven.plugins
76 | maven-source-plugin
77 | 3.2.1
78 |
79 |
80 | attach-source
81 |
82 | jar-no-fork
83 |
84 |
85 |
86 |
87 |
88 | org.apache.maven.plugins
89 | maven-javadoc-plugin
90 | 3.2.0
91 |
92 | -J-Duser.language=en_US
93 |
94 | -notimestamp
95 |
96 | en_US
97 | protected
98 | 8
99 |
100 |
101 |
102 | attach-javadocs
103 |
104 | jar
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 | javacpp-embedded-python
113 |
114 |
115 |
116 | Apache License, Version 2.0
117 | http://www.apache.org/licenses/LICENSE-2.0
118 | repo
119 |
120 |
121 |
122 |
123 |
124 | Yu Kobayashi
125 | yukoba@gmail.com
126 |
127 |
128 |
129 |
130 | https://github.com/bytedeco/javacpp-embedded-python
131 | scm:git:git://github.com/bytedeco/javacpp-embedded-python.git
132 | scm:git:ssh://git@github.com/bytedeco/javacpp-embedded-python.git
133 |
134 |
135 |
136 |
137 | github
138 | GitHub Packages
139 | https://maven.pkg.github.com/bytedeco/javacpp-embedded-python
140 |
141 |
142 |
143 |
--------------------------------------------------------------------------------
/src/main/java/org/bytedeco/embeddedpython/NpNdarray.java:
--------------------------------------------------------------------------------
1 | package org.bytedeco.embeddedpython;
2 |
3 | import java.io.Serializable;
4 | import java.util.Arrays;
5 |
6 | /**
7 | * Numpy np.ndarray.
8 | */
9 | public abstract class NpNdarray implements Serializable {
10 | private static final long serialVersionUID = 1L;
11 |
12 | /**
13 | * ndarray.shape
14 | */
15 | public final int[] shape;
16 | /**
17 | * The unit of Numpy ndarray.strides is bytes, but the unit of this field is element.
18 | */
19 | public final int[] strides;
20 |
21 | public NpNdarray(int[] shape, int[] strides) {
22 | if (shape.length != strides.length)
23 | throw new IllegalArgumentException(
24 | "shape.length = " + shape.length + ", strides.length = " + strides.length);
25 |
26 | this.shape = shape;
27 | this.strides = strides;
28 | }
29 |
30 | NpNdarray(int[] shape) {
31 | this.shape = shape;
32 | this.strides = toContiguousStrides(shape);
33 | }
34 |
35 | private static int[] toContiguousStrides(int[] shape) {
36 | int[] strides = new int[shape.length];
37 | int s = 1;
38 | for (int i = shape.length - 1; i >= 0; i--) {
39 | strides[i] = s;
40 | s *= shape[i];
41 | }
42 | return strides;
43 | }
44 |
45 | static int intAryProduct(int[] ary) {
46 | int s = 1;
47 | for (int j : ary) {
48 | s *= j;
49 | }
50 | return s;
51 | }
52 |
53 | /**
54 | * ndarray.ndim
55 | *
56 | * @return The length of shape.
57 | */
58 | public int ndim() {
59 | return shape.length;
60 | }
61 |
62 | /**
63 | * ndarray.itemsize
64 | *
65 | * @return The bytes of element.
66 | */
67 | public abstract int itemsize();
68 |
69 | long[] stridesInBytes() {
70 | return Arrays.stream(strides).mapToLong(s -> ((long) s) * ((long) itemsize())).toArray();
71 | }
72 |
73 | @Override
74 | public String toString() {
75 | return getClass().getSimpleName() + "{" +
76 | "shape=" + Arrays.toString(shape) +
77 | ", strides=" + Arrays.toString(strides) +
78 | '}';
79 | }
80 |
81 | @Override
82 | public boolean equals(Object o) {
83 | if (this == o) return true;
84 | if (!(o instanceof NpNdarray)) return false;
85 |
86 | NpNdarray npNdarray = (NpNdarray) o;
87 |
88 | if (!Arrays.equals(shape, npNdarray.shape)) return false;
89 | return Arrays.equals(strides, npNdarray.strides);
90 | }
91 |
92 | @Override
93 | public int hashCode() {
94 | int result = Arrays.hashCode(shape);
95 | result = 31 * result + Arrays.hashCode(strides);
96 | return result;
97 | }
98 | }
99 |
100 |
--------------------------------------------------------------------------------
/src/main/java/org/bytedeco/embeddedpython/Pip.java:
--------------------------------------------------------------------------------
1 | package org.bytedeco.embeddedpython;
2 |
3 | import org.bytedeco.javacpp.Loader;
4 |
5 | import java.io.IOException;
6 | import java.util.Arrays;
7 | import java.util.stream.Stream;
8 |
9 | /**
10 | * Pip.
11 | *
12 | * JavaCPP presets Python is installed to ~/.javacpp/cache folder.
13 | * This Pip class will install Python libraries to this folder.
14 | */
15 | public class Pip {
16 | private static final String python = Loader.load(org.bytedeco.cpython.python.class);
17 |
18 | private Pip() {
19 | }
20 |
21 | /**
22 | * Install pip packages.
23 | *
24 | * @param packages The package names to install.
25 | * @return 0 on success.
26 | * @throws IOException If an I/O error occurs.
27 | * @throws InterruptedException If the current thread is interrupted by another thread.
28 | */
29 | public static synchronized int install(String... packages) throws IOException, InterruptedException {
30 | return exec(concat(new String[]{python, "-m", "pip", "install"}, packages));
31 | }
32 |
33 | /**
34 | * Upgrade pip packages.
35 | *
36 | * @param packages The package names to upgrade.
37 | * @return 0 on success.
38 | * @throws IOException If an I/O error occurs.
39 | * @throws InterruptedException If the current thread is interrupted by another thread.
40 | */
41 | public static synchronized int upgrade(String... packages) throws IOException, InterruptedException {
42 | return exec(concat(new String[]{python, "-m", "pip", "install", "--upgrade"}, packages));
43 | }
44 |
45 | /**
46 | * Uninstall pip packages.
47 | *
48 | * @param packages The package names to uninstall.
49 | * @return 0 on success.
50 | * @throws IOException If an I/O error occurs.
51 | * @throws InterruptedException If the current thread is interrupted by another thread.
52 | */
53 | public static synchronized int uninstall(String... packages) throws IOException, InterruptedException {
54 | return exec(concat(new String[]{python, "-m", "pip", "uninstall", "-y"}, packages));
55 | }
56 |
57 | private static int exec(String[] commands) throws IOException, InterruptedException {
58 | return new ProcessBuilder(commands).inheritIO().start().waitFor();
59 | }
60 |
61 | private static String[] concat(String[] a, String[] b) {
62 | return Stream.concat(Arrays.stream(a), Arrays.stream(b)).toArray(String[]::new);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/org/bytedeco/embeddedpython/PyTypes.java:
--------------------------------------------------------------------------------
1 | package org.bytedeco.embeddedpython;
2 |
3 | import org.bytedeco.cpython.PyObject;
4 | import org.bytedeco.cpython.PyTypeObject;
5 | import org.bytedeco.cpython.global.python;
6 |
7 | import static org.bytedeco.cpython.global.python.*;
8 | import static org.bytedeco.numpy.global.numpy.*;
9 |
10 | class PyTypes {
11 | static final PyTypeObject noneType = _PyNone_Type();
12 | static final PyTypeObject boolType = PyBool_Type();
13 | static final PyTypeObject longType = PyLong_Type();
14 | static final PyTypeObject floatType = PyFloat_Type();
15 | static final PyTypeObject unicodeType = PyUnicode_Type();
16 | static final PyTypeObject bytesType = PyBytes_Type();
17 | static final PyTypeObject byteArrayType = PyByteArray_Type();
18 | static final PyTypeObject dictType = PyDict_Type();
19 | static final PyTypeObject boolArrType = PyBoolArrType_Type();
20 | static final PyTypeObject byteArrType = PyByteArrType_Type();
21 | static final PyTypeObject ushortArrType = PyUShortArrType_Type();
22 | static final PyTypeObject shortArrType = PyShortArrType_Type();
23 | static final PyTypeObject intArrType = PyIntArrType_Type();
24 | static final PyTypeObject longArrType = PyLongArrType_Type();
25 | static final PyTypeObject floatArrType = PyFloatArrType_Type();
26 | static final PyTypeObject doubleArrType = PyDoubleArrType_Type();
27 | static final PyTypeObject datetimeArrType = PyDatetimeArrType_Type();
28 | static final PyTypeObject arrayType = PyArray_Type();
29 |
30 | private PyTypes() {
31 | }
32 |
33 | static PyTypeObject Py_TYPE(PyObject ob) {
34 | return python.Py_TYPE(ob);
35 | }
36 |
37 | static boolean Py_IS_TYPE(PyObject ob, PyTypeObject type) {
38 | return Py_TYPE(ob).equals(type);
39 | }
40 |
41 | static boolean PyType_HasFeature(PyTypeObject type, long feature) {
42 | return ((type.tp_flags() & feature) != 0);
43 | }
44 |
45 | static boolean PyType_FastSubclass(PyTypeObject type, long flag) {
46 | return PyType_HasFeature(type, flag);
47 | }
48 |
49 | static boolean PyObject_TypeCheck(PyObject ob, PyTypeObject type) {
50 | return Py_IS_TYPE(ob, type) || (PyType_IsSubtype(Py_TYPE(ob), type) != 0);
51 | }
52 |
53 | static boolean PyNone_Check(PyObject x) {
54 | return Py_IS_TYPE(x, noneType);
55 | }
56 |
57 | static boolean PyBool_Check(PyObject x) {
58 | return Py_IS_TYPE(x, boolType);
59 | }
60 |
61 | static boolean PyLong_Check(PyObject op) {
62 | return PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_LONG_SUBCLASS);
63 | }
64 |
65 | static boolean PyFloat_Check(PyObject op) {
66 | return PyObject_TypeCheck(op, floatType);
67 | }
68 |
69 | static boolean PyUnicode_Check(PyObject op) {
70 | return PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_UNICODE_SUBCLASS);
71 | }
72 |
73 | static boolean PyBytes_Check(PyObject op) {
74 | return PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_BYTES_SUBCLASS);
75 | }
76 |
77 | static boolean PyByteArray_Check(PyObject op) {
78 | return PyObject_TypeCheck(op, byteArrayType);
79 | }
80 |
81 | static boolean PyDict_Check(PyObject op) {
82 | return PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_DICT_SUBCLASS);
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/java/org/bytedeco/embeddedpython/PythonException.java:
--------------------------------------------------------------------------------
1 | package org.bytedeco.embeddedpython;
2 |
3 | public class PythonException extends RuntimeException {
4 | public PythonException(String message) {
5 | super(message);
6 | }
7 |
8 | public PythonException(String message, Throwable cause) {
9 | super(message, cause);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/org/bytedeco/embeddedpython/TypeTreeBuilder.java:
--------------------------------------------------------------------------------
1 | package org.bytedeco.embeddedpython;
2 |
3 | import java.util.Collections;
4 |
5 | class TypeTreeBuilder {
6 | private final StringBuilder stringBuilder = new StringBuilder();
7 | int tab;
8 |
9 | public TypeTreeBuilder(int tab) {
10 | this.tab = tab;
11 | }
12 |
13 | void addType(String t) {
14 | stringBuilder.append(String.join("", Collections.nCopies(tab, " "))).append(t).append("\n");
15 | }
16 |
17 | public String toString() {
18 | return stringBuilder.toString();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/test/java/org/bytedeco/embeddedpython/PipTest.java:
--------------------------------------------------------------------------------
1 | package org.bytedeco.embeddedpython;
2 |
3 | import org.junit.jupiter.api.Test;
4 |
5 | import java.io.IOException;
6 |
7 | public class PipTest {
8 | @Test
9 | public void testInstall() throws IOException, InterruptedException {
10 | Pip.uninstall("pandas");
11 | Pip.install("pandas");
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/test/java/org/bytedeco/embeddedpython/PythonTest.java:
--------------------------------------------------------------------------------
1 | package org.bytedeco.embeddedpython;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import scala.Function0;
5 | import scala.Function1;
6 | import scala.Function2;
7 |
8 | import java.time.Instant;
9 | import java.util.*;
10 |
11 | import static org.junit.jupiter.api.Assertions.*;
12 |
13 | public class PythonTest {
14 | @Test
15 | public void testBasic() {
16 | double a = 355;
17 | double b = 113;
18 | Python.put("a", a);
19 | Python.put("b", b);
20 | Python.exec("v = a / b");
21 | assertEquals(a / b, Python.get("v"), 1e-10);
22 | }
23 |
24 | @Test
25 | public void testLambda() {
26 | //noinspection Convert2MethodRef
27 | Python.put("f", (Function2) (a, b) -> a + b);
28 | long v = Python.eval("f(1, 2)");
29 | assertEquals(3L, v);
30 |
31 | assertEquals("", Python.eval("str(f)"));
32 | }
33 |
34 | @Test
35 | public void testStringArray() {
36 | Python.put("v", new String[]{"foo", "bar"});
37 | ArrayList v = Python.get("v");
38 | assertEquals("foo", v.get(0));
39 | assertEquals("bar", v.get(1));
40 | }
41 |
42 | @Test
43 | public void testIterable() {
44 | Python.put("v", Arrays.asList("foo", 123));
45 | ArrayList v = Python.get("v");
46 | assertEquals("foo", v.get(0));
47 | assertEquals(123L, v.get(1));
48 | }
49 |
50 | @Test
51 | public void testMap() {
52 | LinkedHashMap> map1 = new LinkedHashMap<>();
53 | map1.put("a", Arrays.asList(1, 2));
54 | map1.put("b", Arrays.asList(3, 4));
55 | Python.put("v", map1);
56 |
57 | LinkedHashMap> map2 = Python.get("v");
58 | assertEquals(map1.keySet(), map2.keySet());
59 | assertEquals(Arrays.asList(1L, 2L), map2.get("a"));
60 | assertEquals(Arrays.asList(3L, 4L), map2.get("b"));
61 | }
62 |
63 | @Test
64 | public void testBytes() {
65 | byte[] ary1 = new byte[]{1, 2, 3};
66 | Python.put("v", ary1);
67 | byte[] ary2 = Python.get("v");
68 | assertArrayEquals(ary1, ary2);
69 | }
70 |
71 | @Test
72 | public void testByteArray() {
73 | byte[] ary1 = new byte[]{1, 2, 3};
74 | Python.put("v", ary1);
75 | byte[] ary2 = Python.eval("bytearray(v)");
76 | assertArrayEquals(ary1, ary2);
77 | }
78 |
79 | @Test
80 | public void testLongArray() {
81 | Python.exec("import numpy as np");
82 |
83 | long[] ary1 = new long[]{Long.MAX_VALUE - 1, Long.MAX_VALUE - 2};
84 | Python.put("v", ary1);
85 | NpNdarrayLong ndary2 = Python.get("v");
86 | NpNdarrayLong ndary3 = Python.eval("np.array(" + Arrays.toString(ary1) + ", dtype=np.int64)");
87 | assertArrayEquals(ary1, ndary2.toArray());
88 | assertArrayEquals(ary1, ndary3.toArray());
89 | }
90 |
91 | @Test
92 | public void testFloatArray2d() {
93 | Python.exec("import numpy as np");
94 |
95 | double v = Python.eval("10.0");
96 | assertEquals(10d, v, 1e-10d);
97 |
98 | float ndary0 = Python.eval("np.float32(10)");
99 | assertEquals(10f, ndary0, 1e-10f);
100 |
101 | NpNdarrayFloat ndary1 = Python.eval("np.arange(3, dtype=np.float32)");
102 | float[] ary1 = ndary1.toArray();
103 | assertEquals(3, ary1.length);
104 | assertEquals(2f, ary1[2], 1e-10f);
105 | assertEquals(ndary1, new NpNdarrayFloat(ary1));
106 |
107 | NpNdarrayFloat ndary2 = Python.eval("np.arange(6, dtype=np.float32).reshape([2, 3])");
108 | float[][] ary2 = ndary2.toArray2d();
109 | assertEquals(2, ary2.length);
110 | assertEquals(3, ary2[0].length);
111 | assertEquals(3f, ary2[1][0], 1e-10f);
112 | assertEquals(ndary2, new NpNdarrayFloat(ary2));
113 |
114 | NpNdarrayChar ndary3 = Python.eval("np.arange(24, dtype=np.uint16).reshape([2, 3, 4])");
115 | char[][][] ary3 = ndary3.toArray3d();
116 | assertEquals(2, ary3.length);
117 | assertEquals(3, ary3[0].length);
118 | assertEquals(4, ary3[0][0].length);
119 | assertEquals(17, ary3[1][1][1]);
120 | assertEquals(ndary3, new NpNdarrayChar(ary3));
121 | }
122 |
123 | @Test
124 | public void testBooleanNdarray() {
125 | Python.exec("import numpy as np");
126 | NpNdarrayBoolean npary = Python.eval("np.array([True, False])");
127 | assertArrayEquals(new boolean[]{true, false}, npary.toArray());
128 | }
129 |
130 | @Test
131 | public void testException() {
132 | assertThrows(PythonException.class, () -> Python.eval("aaaa + 1"));
133 | }
134 |
135 | @Test
136 | public void testSyntaxErrorEval() {
137 | assertThrows(PythonException.class, () -> Python.eval("print(Hello')"));
138 | }
139 |
140 | @Test
141 | public void testSyntaxErrorExec() {
142 | assertThrows(PythonException.class, () -> Python.exec("print(Hello')"));
143 | }
144 |
145 | @Test
146 | public void testLambdaException() {
147 | Python.put("f", (Function2) (a, b) -> {
148 | throw new RuntimeException("From lambda");
149 | });
150 | Python.exec("try:\n" +
151 | " f(1, 2)\n" +
152 | " v = Flase\n" +
153 | "except RuntimeError as e:\n" +
154 | " print(e)\n" +
155 | " v = True\n");
156 | boolean v = Python.get("v");
157 | assertTrue(v);
158 | }
159 |
160 | @Test
161 | public void testDatetime() {
162 | Python.exec("import numpy as np");
163 |
164 | NpNdarrayInstant ndary1 = Python.eval("np.array(['2021-03-01T10:02:03'], dtype='datetime64[s]')");
165 | assertEquals("2021-03-01T10:02:03Z", ndary1.toArray()[0].toString());
166 | NpNdarrayInstant ndary2 = Python.eval("np.array(['2021-03-01T10:02:03'], dtype='datetime64[ms]')");
167 | assertEquals("2021-03-01T10:02:03Z", ndary2.toArray()[0].toString());
168 | NpNdarrayInstant ndary3 = Python.eval("np.array(['2021-03-01T10:02:03'], dtype='datetime64[us]')");
169 | assertEquals("2021-03-01T10:02:03Z", ndary3.toArray()[0].toString());
170 | NpNdarrayInstant ndary4 = Python.eval("np.array(['2021-03-01T10:02:03'], dtype='datetime64[ns]')");
171 | assertEquals("2021-03-01T10:02:03Z", ndary4.toArray()[0].toString());
172 |
173 | NpNdarrayInstant ndary5 = Python.eval("np.array(['2021-03-01T10:02:03'], dtype='datetime64[m]')");
174 | assertEquals("2021-03-01T10:02:00Z", ndary5.toArray()[0].toString());
175 | NpNdarrayInstant ndary6 = Python.eval("np.array(['2021-03-01T10:02:03'], dtype='datetime64[h]')");
176 | assertEquals("2021-03-01T10:00:00Z", ndary6.toArray()[0].toString());
177 | NpNdarrayInstant ndary7 = Python.eval("np.array(['2021-03-01T10:02:03'], dtype='datetime64[D]')");
178 | assertEquals("2021-03-01T00:00:00Z", ndary7.toArray()[0].toString());
179 | NpNdarrayInstant ndary8 = Python.eval("np.array(['2021-03-01T10:02:03'], dtype='datetime64[W]')");
180 | assertEquals("2021-02-25T00:00:00Z", ndary8.toArray()[0].toString());
181 |
182 | Python.put("v", ndary4);
183 | Python.exec("print(v)");
184 | NpNdarrayInstant ndary9 = Python.get("v");
185 | assertEquals(ndary4, ndary9);
186 |
187 | Python.put("v", ndary4.data);
188 | Python.exec("print(v)");
189 | NpNdarrayInstant ndary10 = Python.get("v");
190 | assertEquals(ndary4, ndary10);
191 |
192 | Python.put("v", ndary4.data[0]);
193 | Python.exec("print(v)");
194 | Instant instant11 = Python.get("v");
195 | assertEquals(ndary4.data[0], instant11);
196 | }
197 |
198 | @Test
199 | public void testStdoutBuffering() {
200 | System.out.println("1");
201 | Python.exec("print(2)");
202 | System.out.println("3");
203 | }
204 |
205 | @Test
206 | public void testUnsupportedJavaType1() {
207 | assertThrows(PythonException.class, () -> {
208 | try {
209 | Python.put("v", UUID.randomUUID());
210 | } catch (PythonException e) {
211 | e.printStackTrace();
212 | throw e;
213 | }
214 | });
215 | }
216 |
217 | @Test
218 | public void testUnsupportedJavaType2() {
219 | assertThrows(PythonException.class, () -> {
220 | try {
221 | HashMap map = new HashMap<>();
222 | map.put("a", Arrays.asList(1, 2));
223 | map.put("b", UUID.randomUUID());
224 | Python.put("v", map);
225 | } catch (PythonException e) {
226 | e.printStackTrace();
227 | throw e;
228 | }
229 | });
230 | }
231 |
232 | @Test
233 | public void testUnsupportedJavaType3() {
234 | assertThrows(PythonException.class, () -> {
235 | try {
236 | Python.put("f", (Function0) UUID::randomUUID);
237 | Python.exec("f()");
238 | } catch (PythonException e) {
239 | e.printStackTrace();
240 | throw e;
241 | }
242 | });
243 | }
244 |
245 | @Test
246 | public void testUnsupportedPythonType1() {
247 | assertThrows(PythonException.class, () -> {
248 | try {
249 | Python.exec("import uuid\nv = uuid.uuid4()\n");
250 | Python.get("v");
251 | } catch (PythonException e) {
252 | e.printStackTrace();
253 | assertEquals(3L, (long) Python.eval("1 + 2"));
254 | throw e;
255 | }
256 | });
257 | }
258 |
259 | @Test
260 | public void testUnsupportedPythonType2() {
261 | assertThrows(PythonException.class, () -> {
262 | try {
263 | Python.exec("import uuid\nv = dict(a=[1, 2], b=uuid.uuid4())\n");
264 | Python.get("v");
265 | } catch (PythonException e) {
266 | e.printStackTrace();
267 | assertEquals(3L, (long) Python.eval("1 + 2"));
268 | throw e;
269 | }
270 | });
271 | }
272 |
273 | @Test
274 | public void testUnsupportedPythonType3() {
275 | assertThrows(PythonException.class, () -> {
276 | try {
277 | Python.put("f", (Function1) (uuid) -> null);
278 | Python.exec("import uuid\nf(uuid.uuid4())");
279 | } catch (PythonException e) {
280 | e.printStackTrace();
281 | throw e;
282 | }
283 | });
284 | }
285 |
286 | @Test
287 | public void testArgv() {
288 | Python.exec("import sys");
289 | ArrayList argv = Python.eval("sys.argv");
290 | assertEquals(1, argv.size());
291 | assertEquals("", argv.get(0));
292 | }
293 |
294 | @Test
295 | public void testSysExecutable() {
296 | Python.exec("import sys");
297 | String sysExecutable = Python.eval("sys.executable");
298 | System.out.println(sysExecutable);
299 | }
300 |
301 | @Test
302 | public void testOrderedDict() {
303 | LinkedHashMap map1 = new LinkedHashMap<>();
304 | map1.put("a", 1L);
305 | map1.put("b", 2L);
306 |
307 | Python.exec("from collections import OrderedDict");
308 | LinkedHashMap map2 = Python.eval("OrderedDict(a=1, b=2)");
309 | assertEquals(map1, map2);
310 | }
311 | }
312 |
--------------------------------------------------------------------------------