ellipsis 1.2.17__tar.gz → 3.3.0__tar.gz
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.
- ellipsis-3.3.0/LICENSE +19 -0
- ellipsis-3.3.0/PKG-INFO +50 -0
- ellipsis-3.3.0/README.md +36 -0
- ellipsis-3.3.0/ellipsis/__init__.py +12 -0
- ellipsis-3.3.0/ellipsis/account/__init__.py +4 -0
- ellipsis-3.3.0/ellipsis/account/accessToken/__init__.py +1 -0
- ellipsis-3.3.0/ellipsis/account/accessToken/root.py +38 -0
- ellipsis-3.3.0/ellipsis/account/root.py +60 -0
- ellipsis-3.3.0/ellipsis/apiManager.py +183 -0
- ellipsis-3.3.0/ellipsis/compute/__init__.py +1 -0
- ellipsis-3.3.0/ellipsis/compute/root.py +180 -0
- ellipsis-3.3.0/ellipsis/path/__init__.py +13 -0
- ellipsis-3.3.0/ellipsis/path/bookmark/__init__.py +2 -0
- ellipsis-3.3.0/ellipsis/path/bookmark/root.py +39 -0
- ellipsis-3.3.0/ellipsis/path/file/__init__.py +2 -0
- ellipsis-3.3.0/ellipsis/path/file/root.py +155 -0
- ellipsis-3.3.0/ellipsis/path/folder/__init__.py +4 -0
- ellipsis-3.3.0/ellipsis/path/folder/root.py +52 -0
- ellipsis-3.3.0/ellipsis/path/hashtag/__init__.py +1 -0
- ellipsis-3.3.0/ellipsis/path/hashtag/root.py +25 -0
- ellipsis-3.3.0/ellipsis/path/invite/__init__.py +1 -0
- ellipsis-3.3.0/ellipsis/path/invite/root.py +54 -0
- ellipsis-3.3.0/ellipsis/path/member/__init__.py +1 -0
- ellipsis-3.3.0/ellipsis/path/member/root.py +31 -0
- ellipsis-3.3.0/ellipsis/path/pointCloud/__init__.py +5 -0
- ellipsis-3.3.0/ellipsis/path/pointCloud/root.py +16 -0
- ellipsis-3.3.0/ellipsis/path/pointCloud/timestamp/__init__.py +13 -0
- ellipsis-3.3.0/ellipsis/path/pointCloud/timestamp/file/__init__.py +2 -0
- ellipsis-3.3.0/ellipsis/path/pointCloud/timestamp/file/root.py +96 -0
- ellipsis-3.3.0/ellipsis/path/pointCloud/timestamp/order/__init__.py +2 -0
- ellipsis-3.3.0/ellipsis/path/pointCloud/timestamp/order/root.py +32 -0
- ellipsis-3.3.0/ellipsis/path/pointCloud/timestamp/root.py +178 -0
- ellipsis-3.3.0/ellipsis/path/pointCloud/timestamp/util.py +76 -0
- ellipsis-3.3.0/ellipsis/path/raster/__init__.py +8 -0
- ellipsis-3.3.0/ellipsis/path/raster/root.py +38 -0
- ellipsis-3.3.0/ellipsis/path/raster/style/__init__.py +1 -0
- ellipsis-3.3.0/ellipsis/path/raster/style/root.py +38 -0
- ellipsis-3.3.0/ellipsis/path/raster/timestamp/__init__.py +17 -0
- ellipsis-3.3.0/ellipsis/path/raster/timestamp/file/__init__.py +2 -0
- ellipsis-3.3.0/ellipsis/path/raster/timestamp/file/root.py +100 -0
- ellipsis-3.3.0/ellipsis/path/raster/timestamp/order/__init__.py +2 -0
- ellipsis-3.3.0/ellipsis/path/raster/timestamp/order/root.py +33 -0
- ellipsis-3.3.0/ellipsis/path/raster/timestamp/root.py +460 -0
- ellipsis-3.3.0/ellipsis/path/raster/timestamp/util.py +76 -0
- ellipsis-3.3.0/ellipsis/path/root.py +218 -0
- ellipsis-3.3.0/ellipsis/path/setUpTask/__init__.py +2 -0
- ellipsis-3.3.0/ellipsis/path/setUpTask/root.py +50 -0
- ellipsis-3.3.0/ellipsis/path/usage/__init__.py +1 -0
- ellipsis-3.3.0/ellipsis/path/usage/root.py +48 -0
- ellipsis-3.3.0/ellipsis/path/vector/__init__.py +10 -0
- ellipsis-3.3.0/ellipsis/path/vector/featureProperty/__init__.py +2 -0
- ellipsis-3.3.0/ellipsis/path/vector/featureProperty/root.py +57 -0
- ellipsis-3.3.0/ellipsis/path/vector/root.py +45 -0
- ellipsis-3.3.0/ellipsis/path/vector/style/__init__.py +2 -0
- ellipsis-3.3.0/ellipsis/path/vector/style/root.py +46 -0
- ellipsis-3.3.0/ellipsis/path/vector/timestamp/__init__.py +6 -0
- ellipsis-3.3.0/ellipsis/path/vector/timestamp/feature/__init__.py +4 -0
- ellipsis-3.3.0/ellipsis/path/vector/timestamp/feature/message/__init__.py +2 -0
- ellipsis-3.3.0/ellipsis/path/vector/timestamp/feature/message/root.py +92 -0
- ellipsis-3.3.0/ellipsis/path/vector/timestamp/feature/root.py +184 -0
- ellipsis-3.3.0/ellipsis/path/vector/timestamp/feature/series/__init__.py +3 -0
- ellipsis-3.3.0/ellipsis/path/vector/timestamp/feature/series/root.py +173 -0
- ellipsis-3.3.0/ellipsis/path/vector/timestamp/file/__init__.py +2 -0
- ellipsis-3.3.0/ellipsis/path/vector/timestamp/file/root.py +115 -0
- ellipsis-3.3.0/ellipsis/path/vector/timestamp/order/__init__.py +2 -0
- ellipsis-3.3.0/ellipsis/path/vector/timestamp/order/root.py +34 -0
- ellipsis-3.3.0/ellipsis/path/vector/timestamp/root.py +270 -0
- ellipsis-3.3.0/ellipsis/sanitize.py +372 -0
- ellipsis-3.3.0/ellipsis/user/__init__.py +1 -0
- ellipsis-3.3.0/ellipsis/user/root.py +22 -0
- ellipsis-3.3.0/ellipsis/util/__init__.py +25 -0
- ellipsis-3.3.0/ellipsis/util/root.py +704 -0
- ellipsis-3.3.0/ellipsis.egg-info/PKG-INFO +50 -0
- ellipsis-3.3.0/ellipsis.egg-info/SOURCES.txt +78 -0
- {ellipsis-1.2.17 → ellipsis-3.3.0}/ellipsis.egg-info/requires.txt +13 -9
- {ellipsis-1.2.17 → ellipsis-3.3.0}/setup.py +10 -6
- ellipsis-3.3.0/test/test.py +651 -0
- ellipsis-1.2.17/PKG-INFO +0 -19
- ellipsis-1.2.17/README.md +0 -4
- ellipsis-1.2.17/ellipsis/__init__.py +0 -1587
- ellipsis-1.2.17/ellipsis.egg-info/PKG-INFO +0 -19
- ellipsis-1.2.17/ellipsis.egg-info/SOURCES.txt +0 -8
- {ellipsis-1.2.17 → ellipsis-3.3.0}/ellipsis.egg-info/dependency_links.txt +0 -0
- {ellipsis-1.2.17 → ellipsis-3.3.0}/ellipsis.egg-info/top_level.txt +0 -0
- {ellipsis-1.2.17 → ellipsis-3.3.0}/setup.cfg +0 -0
ellipsis-3.3.0/LICENSE
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright (c) 2018 The Python Packaging Authority
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
+
SOFTWARE.
|
ellipsis-3.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: ellipsis
|
|
3
|
+
Version: 3.3.0
|
|
4
|
+
Summary: Package to interact with the Ellipsis API
|
|
5
|
+
Home-page: https://github.com/ellipsis-drive-internal/python-package
|
|
6
|
+
Author: Daniel van der Maas
|
|
7
|
+
Author-email: daniel@ellipsis-drive.com
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.6
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
|
|
15
|
+
# Ellipsis Drive Python Package
|
|
16
|
+
|
|
17
|
+
This package is meant to help you interact with the Ellipsis API.
|
|
18
|
+
|
|
19
|
+
You can install this package using
|
|
20
|
+
|
|
21
|
+
`pip install ellipsis`
|
|
22
|
+
|
|
23
|
+
For documentation see https://ellipsis-package.readthedocs.io
|
|
24
|
+
|
|
25
|
+
This package is meant to ease the use of the Ellipsis Drive API in your Python projects.
|
|
26
|
+
|
|
27
|
+
# Examples
|
|
28
|
+
|
|
29
|
+
Below are some code examples.
|
|
30
|
+
|
|
31
|
+
import ellipsis as el
|
|
32
|
+
|
|
33
|
+
# log in
|
|
34
|
+
token = el.account.logIn("username", "password")
|
|
35
|
+
|
|
36
|
+
# retrieve all maps in "My Drive"
|
|
37
|
+
maps = el.account.listRoot("myDrive", pathType='layer',
|
|
38
|
+
token=token)
|
|
39
|
+
|
|
40
|
+
Another example
|
|
41
|
+
|
|
42
|
+
import ellipsis as el
|
|
43
|
+
|
|
44
|
+
folderId = '46e1e919-8b73-42a3-a575-25c6d45fd93b'
|
|
45
|
+
|
|
46
|
+
token = el.account.logIn("username", "password")
|
|
47
|
+
|
|
48
|
+
info = el.path.get(folderId, token)
|
|
49
|
+
layers = el.path.listPath(folderId, pathType='layer', token = token, listAll = True)
|
|
50
|
+
folders = el.path.listPath(folderId, pathType='folder', token = token, listAll = True)
|
ellipsis-3.3.0/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Ellipsis Drive Python Package
|
|
2
|
+
|
|
3
|
+
This package is meant to help you interact with the Ellipsis API.
|
|
4
|
+
|
|
5
|
+
You can install this package using
|
|
6
|
+
|
|
7
|
+
`pip install ellipsis`
|
|
8
|
+
|
|
9
|
+
For documentation see https://ellipsis-package.readthedocs.io
|
|
10
|
+
|
|
11
|
+
This package is meant to ease the use of the Ellipsis Drive API in your Python projects.
|
|
12
|
+
|
|
13
|
+
# Examples
|
|
14
|
+
|
|
15
|
+
Below are some code examples.
|
|
16
|
+
|
|
17
|
+
import ellipsis as el
|
|
18
|
+
|
|
19
|
+
# log in
|
|
20
|
+
token = el.account.logIn("username", "password")
|
|
21
|
+
|
|
22
|
+
# retrieve all maps in "My Drive"
|
|
23
|
+
maps = el.account.listRoot("myDrive", pathType='layer',
|
|
24
|
+
token=token)
|
|
25
|
+
|
|
26
|
+
Another example
|
|
27
|
+
|
|
28
|
+
import ellipsis as el
|
|
29
|
+
|
|
30
|
+
folderId = '46e1e919-8b73-42a3-a575-25c6d45fd93b'
|
|
31
|
+
|
|
32
|
+
token = el.account.logIn("username", "password")
|
|
33
|
+
|
|
34
|
+
info = el.path.get(folderId, token)
|
|
35
|
+
layers = el.path.listPath(folderId, pathType='layer', token = token, listAll = True)
|
|
36
|
+
folders = el.path.listPath(folderId, pathType='folder', token = token, listAll = True)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#python3 setup.py sdist bdist_wheel
|
|
2
|
+
#twine upload --repository pypi dist/*
|
|
3
|
+
|
|
4
|
+
from ellipsis import account
|
|
5
|
+
from ellipsis import user
|
|
6
|
+
from ellipsis import path
|
|
7
|
+
from ellipsis import util
|
|
8
|
+
from ellipsis import compute
|
|
9
|
+
__version__ = '3.3.0'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from ellipsis.account.accessToken.root import create, revoke, get
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from ellipsis import apiManager, sanitize
|
|
2
|
+
from ellipsis.util.root import recurse
|
|
3
|
+
|
|
4
|
+
def create(description, accessList, token, validFor= None):
|
|
5
|
+
token = sanitize.validString('token', token, True)
|
|
6
|
+
description = sanitize.validString('description', description, True)
|
|
7
|
+
accessList = sanitize.validObject('accessList', accessList, True)
|
|
8
|
+
validFor = sanitize.validInt('validFor', validFor, False)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
return apiManager.post('/account/security/accessToken', {
|
|
13
|
+
'description': description,
|
|
14
|
+
'validFor': validFor,
|
|
15
|
+
'accessList': accessList,
|
|
16
|
+
'scope': 'all'
|
|
17
|
+
}, token)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def revoke(accessTokenId, token):
|
|
21
|
+
accessTokenId = sanitize.validUuid('accessTokenId', accessTokenId, True)
|
|
22
|
+
token = sanitize.validString('token', token, True)
|
|
23
|
+
|
|
24
|
+
return apiManager.delete(f'/account/security/accessToken/{accessTokenId}', None, token)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get(token, pageStart = None, listAll = False):
|
|
28
|
+
pageStart = sanitize.validObject('pageStart', pageStart, False)
|
|
29
|
+
token = sanitize.validString('token', token, True)
|
|
30
|
+
listAll = sanitize.validBool('listAll', listAll, True)
|
|
31
|
+
|
|
32
|
+
body = {'pageStart':pageStart}
|
|
33
|
+
|
|
34
|
+
def f(body):
|
|
35
|
+
return apiManager.get('/account/security/accessToken', body, token)
|
|
36
|
+
|
|
37
|
+
r = recurse(f, body, listAll)
|
|
38
|
+
return r
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from ellipsis import apiManager
|
|
2
|
+
from ellipsis import sanitize
|
|
3
|
+
from ellipsis.util.root import recurse
|
|
4
|
+
import requests
|
|
5
|
+
|
|
6
|
+
def logIn(username, password, validFor = None):
|
|
7
|
+
|
|
8
|
+
username = sanitize.validString('username', username, True)
|
|
9
|
+
password = sanitize.validString('password', password, True)
|
|
10
|
+
validFor = sanitize.validInt('validFor', validFor, False)
|
|
11
|
+
|
|
12
|
+
json = {'username': username, 'password': password, 'validFor': validFor}
|
|
13
|
+
|
|
14
|
+
r = apiManager.call(requests.post,'/account/login', body=json, token=None, crash=False)
|
|
15
|
+
if r.status_code == 400:
|
|
16
|
+
x = r.json()
|
|
17
|
+
if x['message'] == "No password configured.":
|
|
18
|
+
raise ValueError("You cannot login with your Google credentials in the Python module. You need to configure an Ellipsis Drive specific password. You can do this on https://app.ellipsis-drive.com/account-settings/security")
|
|
19
|
+
if r.status_code != 200:
|
|
20
|
+
raise ValueError(r.text)
|
|
21
|
+
|
|
22
|
+
r = r.json()
|
|
23
|
+
token = r['token']
|
|
24
|
+
|
|
25
|
+
return(token)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def getInfo(token):
|
|
29
|
+
token = sanitize.validString('token', token, True)
|
|
30
|
+
|
|
31
|
+
r = apiManager.get( '/account', body={}, token=token)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
return r
|
|
35
|
+
|
|
36
|
+
def listRoot(rootName, token, pathTypes= None, pageStart = None, listAll = True):
|
|
37
|
+
token = sanitize.validString('token', token, True)
|
|
38
|
+
rootName = sanitize.validString('rootName', rootName, True)
|
|
39
|
+
pageStart = sanitize.validUuid('pageStart', pageStart, False)
|
|
40
|
+
listAll = sanitize.validBool('listAll', listAll, True)
|
|
41
|
+
pathTypes = sanitize.validObject('pathTypes', pathTypes, False)
|
|
42
|
+
if type(pathTypes) == type(None):
|
|
43
|
+
pathTypes = ['folder', 'raster', 'vector', 'file']
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
url = "/account/root/" + rootName
|
|
47
|
+
body = {"type": pathTypes, "pageStart": pageStart}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def f(body):
|
|
51
|
+
r = apiManager.get(url, body, token)
|
|
52
|
+
return r
|
|
53
|
+
|
|
54
|
+
r = recurse(f, body, listAll)
|
|
55
|
+
|
|
56
|
+
return r
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
import json
|
|
3
|
+
import urllib
|
|
4
|
+
import os
|
|
5
|
+
import time
|
|
6
|
+
from requests_toolbelt import MultipartEncoder
|
|
7
|
+
|
|
8
|
+
baseUrl = 'https://api.ellipsis-drive.com/v3'
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def filterNone(body, toString= False):
|
|
12
|
+
if type(body) == type(None):
|
|
13
|
+
return body
|
|
14
|
+
|
|
15
|
+
params = {}
|
|
16
|
+
for k in body.keys():
|
|
17
|
+
if type(body[k]) != type(None):
|
|
18
|
+
if toString:
|
|
19
|
+
if str(type(body[k])) != str(type('x')):
|
|
20
|
+
params[k] = json.dumps(body[k])
|
|
21
|
+
else:
|
|
22
|
+
params[k] = body[k]
|
|
23
|
+
|
|
24
|
+
else:
|
|
25
|
+
params[k] = body[k]
|
|
26
|
+
return params
|
|
27
|
+
|
|
28
|
+
def get(url, body = None, token = None, crash = True, parseJson = True):
|
|
29
|
+
if body == None:
|
|
30
|
+
body = {'token': token}
|
|
31
|
+
else:
|
|
32
|
+
body['token'] = token
|
|
33
|
+
body = filterNone(body)
|
|
34
|
+
|
|
35
|
+
for k in body.keys():
|
|
36
|
+
if type(body[k]) != type('x') :
|
|
37
|
+
body[k] = json.dumps(body[k])
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
body = urllib.parse.urlencode(body)
|
|
41
|
+
|
|
42
|
+
url = url + '?' + body
|
|
43
|
+
|
|
44
|
+
r = call( method = requests.get, url = url, body = None, token = token, crash = crash, parseJson = parseJson )
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
return r
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def post(url, body, token=None):
|
|
51
|
+
r = call(method=requests.post, url=url, body=body, token=token)
|
|
52
|
+
return r
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def put(url, body, token=None):
|
|
56
|
+
r = call(method=requests.put, url=url, body=body, token=token)
|
|
57
|
+
return r
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def patch(url, body, token=None):
|
|
61
|
+
r = call(method=requests.patch, url=url, body=body, token=token)
|
|
62
|
+
return r
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def delete(url, body, token = None):
|
|
66
|
+
r = call( method = requests.delete, url = url, body = body, token = token )
|
|
67
|
+
return r
|
|
68
|
+
|
|
69
|
+
RETRIES = 10
|
|
70
|
+
WAIT = 2
|
|
71
|
+
def call(method, url, body = None, token = None, crash = True, parseJson = True):
|
|
72
|
+
tried = 0
|
|
73
|
+
while tried <RETRIES:
|
|
74
|
+
try:
|
|
75
|
+
r = actualCall(method, url, body, token)
|
|
76
|
+
break
|
|
77
|
+
except Exception as ex:
|
|
78
|
+
print('time out detected, retrying request')
|
|
79
|
+
print('url', url)
|
|
80
|
+
print('error',ex)
|
|
81
|
+
time.sleep(WAIT)
|
|
82
|
+
tried = tried +1
|
|
83
|
+
if tried >= RETRIES:
|
|
84
|
+
raise ValueError('Could not reach server')
|
|
85
|
+
if crash:
|
|
86
|
+
if r.status_code != 200:
|
|
87
|
+
raise ValueError(r.text)
|
|
88
|
+
|
|
89
|
+
if parseJson:
|
|
90
|
+
try:
|
|
91
|
+
r = r.json()
|
|
92
|
+
except:
|
|
93
|
+
r = r.text
|
|
94
|
+
|
|
95
|
+
return r
|
|
96
|
+
else:
|
|
97
|
+
return r
|
|
98
|
+
|
|
99
|
+
TIMEOUTTIME = 20
|
|
100
|
+
def actualCall(method, url, body, token):
|
|
101
|
+
body = filterNone(body)
|
|
102
|
+
if type(body) != type(None) and type(body) != type({}):
|
|
103
|
+
raise ValueError(
|
|
104
|
+
'body of an API call must be of type dict or noneType')
|
|
105
|
+
|
|
106
|
+
if type(token) != type(None) and type(token) != type('x'):
|
|
107
|
+
raise ValueError('Token must be of type string or noneType')
|
|
108
|
+
|
|
109
|
+
if token == None:
|
|
110
|
+
r = method(baseUrl + url, json=body, timeout=TIMEOUTTIME)
|
|
111
|
+
else:
|
|
112
|
+
if not 'Bearer' in token:
|
|
113
|
+
token = 'Bearer ' + token
|
|
114
|
+
r = method(baseUrl + url, json=body, headers={"Authorization": token}, timeout=TIMEOUTTIME)
|
|
115
|
+
|
|
116
|
+
return r
|
|
117
|
+
|
|
118
|
+
def upload(url, filePath, body, token, key = 'data', memfile= None):
|
|
119
|
+
body['debug'] = True
|
|
120
|
+
body = filterNone(body, toString=True)
|
|
121
|
+
|
|
122
|
+
seperator = os.path.sep
|
|
123
|
+
fileName = filePath.split(seperator)[len(filePath.split(seperator))-1 ]
|
|
124
|
+
|
|
125
|
+
if str(type(memfile)) == str(type(None)):
|
|
126
|
+
conn_file = open(filePath, 'rb')
|
|
127
|
+
else:
|
|
128
|
+
conn_file = memfile
|
|
129
|
+
|
|
130
|
+
payload = MultipartEncoder(fields = {**body, key: (fileName, conn_file, 'application/octet-stream')})
|
|
131
|
+
if not 'Bearer' in token:
|
|
132
|
+
token = 'Bearer ' + token
|
|
133
|
+
|
|
134
|
+
r = requests.post(baseUrl + url, headers = {"Authorization":token, "Content-Type": payload.content_type}, data=payload, verify=False)
|
|
135
|
+
|
|
136
|
+
if str(type(memfile)) == str(type(None)):
|
|
137
|
+
conn_file.close()
|
|
138
|
+
|
|
139
|
+
if r.status_code != 200:
|
|
140
|
+
raise ValueError(r.text)
|
|
141
|
+
return r.json()
|
|
142
|
+
|
|
143
|
+
def download(url, filePath=None, token = None, memfile = None):
|
|
144
|
+
if type(token) == type(None):
|
|
145
|
+
with requests.get(baseUrl + url, stream=True) as r:
|
|
146
|
+
r.raise_for_status()
|
|
147
|
+
if str(type(memfile)) == str(type(None)):
|
|
148
|
+
with open(filePath, 'wb') as f:
|
|
149
|
+
for chunk in r.iter_content(chunk_size=8192):
|
|
150
|
+
# If you have chunk encoded response uncomment if
|
|
151
|
+
# and set chunk_size parameter to None.
|
|
152
|
+
#if chunk:
|
|
153
|
+
f.write(chunk)
|
|
154
|
+
else:
|
|
155
|
+
for chunk in r.iter_content(chunk_size=8192):
|
|
156
|
+
# If you have chunk encoded response uncomment if
|
|
157
|
+
# and set chunk_size parameter to None.
|
|
158
|
+
#if chunk:
|
|
159
|
+
memfile.write(chunk)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
else:
|
|
164
|
+
token = 'Bearer ' + token
|
|
165
|
+
with requests.get(baseUrl + url, stream=True, headers={"Authorization": token}) as r:
|
|
166
|
+
r.raise_for_status()
|
|
167
|
+
if str(type(memfile)) == str(type(None)):
|
|
168
|
+
with open(filePath, 'wb') as f:
|
|
169
|
+
for chunk in r.iter_content(chunk_size=8192):
|
|
170
|
+
# If you have chunk encoded response uncomment if
|
|
171
|
+
# and set chunk_size parameter to None.
|
|
172
|
+
#if chunk:
|
|
173
|
+
f.write(chunk)
|
|
174
|
+
else:
|
|
175
|
+
for chunk in r.iter_content(chunk_size=8192):
|
|
176
|
+
# If you have chunk encoded response uncomment if
|
|
177
|
+
# and set chunk_size parameter to None.
|
|
178
|
+
#if chunk:
|
|
179
|
+
memfile.write(chunk)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from ellipsis.compute.root import createCompute, listComputes, execute, terminateCompute, terminateAll, addToLayer
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import dill
|
|
2
|
+
import base64
|
|
3
|
+
import time
|
|
4
|
+
|
|
5
|
+
from ellipsis.util.root import recurse
|
|
6
|
+
from ellipsis import sanitize
|
|
7
|
+
from ellipsis.account import getInfo
|
|
8
|
+
from ellipsis import apiManager
|
|
9
|
+
from ellipsis.path.raster.timestamp.file import add as addFile
|
|
10
|
+
from ellipsis.path.raster.timestamp import activate
|
|
11
|
+
from io import BytesIO
|
|
12
|
+
|
|
13
|
+
def createCompute(layers, token, files = None, nodes=None, interpreter='python3.12', requirements= [], awaitTillStarted = True, largeResult = False):
|
|
14
|
+
layers = sanitize.validDictArray('layers', layers, True)
|
|
15
|
+
files = sanitize.validUuidArray('files', files, False)
|
|
16
|
+
token = sanitize.validString('token', token, True)
|
|
17
|
+
nodes = sanitize.validInt('nodes', nodes, False)
|
|
18
|
+
interpreter = sanitize.validString('interpreter', interpreter, True)
|
|
19
|
+
requirements = sanitize.validStringArray('requirements', requirements, False)
|
|
20
|
+
largeResult = sanitize.validBool('largeResult', largeResult, True)
|
|
21
|
+
if type(nodes) == type(None):
|
|
22
|
+
info = getInfo(token=token)
|
|
23
|
+
nodes = info['plan']['maxComputeNodes']
|
|
24
|
+
if nodes == 0:
|
|
25
|
+
raise ValueError('You have no compute nodes in your plan. Please update your subscription')
|
|
26
|
+
|
|
27
|
+
requirements = "\n".join(requirements)
|
|
28
|
+
|
|
29
|
+
body = {'layers':layers, 'files':files, 'interpreter':interpreter, 'nodes':nodes, 'requirements':requirements, 'largeResult': largeResult}
|
|
30
|
+
r = apiManager.post('/compute', body, token)
|
|
31
|
+
|
|
32
|
+
computeId = r['id']
|
|
33
|
+
while awaitTillStarted:
|
|
34
|
+
print('waiting')
|
|
35
|
+
res = listComputes(token=token)['result']
|
|
36
|
+
r = [x for x in res if x['id'] == computeId][0]
|
|
37
|
+
if r['status'] == 'available':
|
|
38
|
+
break
|
|
39
|
+
if r['status'] == 'errored':
|
|
40
|
+
raise ValueError(r['message'])
|
|
41
|
+
|
|
42
|
+
time.sleep(1)
|
|
43
|
+
|
|
44
|
+
return {'id':computeId}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def execute(computeId, f, token, awaitTillCompleted=True, writeToLayer = None):
|
|
48
|
+
computeId = sanitize.validUuid('computeId', computeId, True)
|
|
49
|
+
token = sanitize.validString('token', token, True)
|
|
50
|
+
writeToLayer = sanitize.validObject('writeToLayer', writeToLayer, False)
|
|
51
|
+
awaitTillCompleted = sanitize.validBool('awaitTillCompleted', awaitTillCompleted, False)
|
|
52
|
+
|
|
53
|
+
if str(type(f)) != "<class 'function'>":
|
|
54
|
+
raise ValueError('parameter f must be a function')
|
|
55
|
+
if type(writeToLayer) != type(None):
|
|
56
|
+
if not 'file' in writeToLayer:
|
|
57
|
+
writeToLayer['file'] = {'format':'tif'}
|
|
58
|
+
f_bytes = dill.dumps(f)
|
|
59
|
+
f_string = base64.b64encode( f_bytes )
|
|
60
|
+
f_string = str(f_string)[2: -1]
|
|
61
|
+
body = { 'file':f_string, 'writeToLayer':writeToLayer}
|
|
62
|
+
apiManager.post('/compute/' + computeId + '/execute', body, token)
|
|
63
|
+
|
|
64
|
+
while awaitTillCompleted:
|
|
65
|
+
res = listComputes(token=token)['result']
|
|
66
|
+
r = [x for x in res if x['id'] == computeId][0]
|
|
67
|
+
print('waiting')
|
|
68
|
+
if r['status'] == 'completed':
|
|
69
|
+
break
|
|
70
|
+
if r['status'] == 'errored':
|
|
71
|
+
raise ValueError(str(r['message']))
|
|
72
|
+
time.sleep(1)
|
|
73
|
+
|
|
74
|
+
for x in r['result']:
|
|
75
|
+
if x['type'] == 'exception':
|
|
76
|
+
raise x['value']
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
values = [ '/compute/' + computeId + '/file/'+ x['value'] if x['type'] == 'file' else x['value'] for x in r['result']]
|
|
80
|
+
return values
|
|
81
|
+
|
|
82
|
+
def parseResults(r):
|
|
83
|
+
results = []
|
|
84
|
+
for x in r:
|
|
85
|
+
x = base64.b64decode(x)
|
|
86
|
+
x = dill.loads(x)
|
|
87
|
+
results = results + x
|
|
88
|
+
|
|
89
|
+
return results
|
|
90
|
+
|
|
91
|
+
def terminateCompute(computeId, token, awaitTillTerminated = True):
|
|
92
|
+
computeId = sanitize.validUuid('computeId', computeId, True)
|
|
93
|
+
token = sanitize.validString('token', token, True)
|
|
94
|
+
sanitize.validBool('awaitTillTerminated',awaitTillTerminated, True)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
r = apiManager.post('/compute/' + computeId + '/terminate', {}, token)
|
|
98
|
+
|
|
99
|
+
while awaitTillTerminated:
|
|
100
|
+
res = listComputes(token=token)['result']
|
|
101
|
+
z = [x for x in res if x['id'] == computeId][0]
|
|
102
|
+
if z['status'] == 'stopped':
|
|
103
|
+
break
|
|
104
|
+
time.sleep(1)
|
|
105
|
+
|
|
106
|
+
return r
|
|
107
|
+
|
|
108
|
+
def terminateAll(token, awaitTillTerminated = True ):
|
|
109
|
+
token = sanitize.validString('token', token, True)
|
|
110
|
+
sanitize.validBool('awaitTillTerminated',awaitTillTerminated, True)
|
|
111
|
+
|
|
112
|
+
res = listComputes(token = token)['result']
|
|
113
|
+
|
|
114
|
+
for x in res:
|
|
115
|
+
if x['status'] != 'stopped' and x['status'] != 'errored' and x['status'] != 'stopping':
|
|
116
|
+
|
|
117
|
+
apiManager.post('/compute/' + x['id'] + '/terminate', {}, token)
|
|
118
|
+
|
|
119
|
+
while awaitTillTerminated:
|
|
120
|
+
res = listComputes(token=token)['result']
|
|
121
|
+
z = [x for x in res if x['id'] == x['id']][0]
|
|
122
|
+
if z['status'] == 'stopped':
|
|
123
|
+
break
|
|
124
|
+
time.sleep(1)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def getComputeInfo(computeId, token):
|
|
129
|
+
res = listComputes(token=token)['result']
|
|
130
|
+
r = [x for x in res if x['id'] == computeId]
|
|
131
|
+
if len(r) ==0:
|
|
132
|
+
raise ValueError('No compute found for given id')
|
|
133
|
+
return r[0]
|
|
134
|
+
|
|
135
|
+
def listComputes(token, pageStart = None, listAll = True):
|
|
136
|
+
token = sanitize.validString('token', token, True)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
body = { 'pageStart':pageStart }
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def f(body):
|
|
143
|
+
return apiManager.get('/compute', body, token)
|
|
144
|
+
|
|
145
|
+
r = recurse(f, body, listAll)
|
|
146
|
+
for i in range(len(r['result'])):
|
|
147
|
+
if 'result' in r['result'][i]:
|
|
148
|
+
r['result'][i]['result'] = parseResults(r['result'][i]['result'])
|
|
149
|
+
return r
|
|
150
|
+
|
|
151
|
+
def addToLayer(response, pathId, timestampId, token):
|
|
152
|
+
pathId = sanitize.validUuid('pathId', pathId, True)
|
|
153
|
+
timestampId = sanitize.validUuid('timestampId', timestampId, True)
|
|
154
|
+
token = sanitize.validString('token', token, True)
|
|
155
|
+
|
|
156
|
+
for url in response:
|
|
157
|
+
print('fetching file ' + url.split('/')[-1])
|
|
158
|
+
memfile = BytesIO()
|
|
159
|
+
memfile = downloadFile(url, token, memfile=memfile)
|
|
160
|
+
print('read file ' + url.split('/')[-1])
|
|
161
|
+
print('adding file ' + url.split('/')[-1])
|
|
162
|
+
addFile(pathId = pathId, timestampId=timestampId, token = token, fileFormat='tif', memFile=memfile, name= url.split('/')[-1] + '.tif' )
|
|
163
|
+
print('file ' + url.split('/')[-1] + ' added to layer')
|
|
164
|
+
activate(pathId=pathId, timestampId=timestampId, token=token)
|
|
165
|
+
print('layer can now be found at ' + apiManager.baseUrl + '/drive/me?pathId=' + pathId )
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def downloadFile(url, token, filePath = None, memfile = None):
|
|
170
|
+
|
|
171
|
+
url = sanitize.validString('url', url, True)
|
|
172
|
+
token = sanitize.validString('token', token, True)
|
|
173
|
+
filePath = sanitize.validString('filePath', filePath, False)
|
|
174
|
+
if memfile == None and filePath == None:
|
|
175
|
+
raise ValueError('Either memfile or filePath is required')
|
|
176
|
+
|
|
177
|
+
apiManager.download(url = url, filePath=filePath, memfile=memfile, token = token)
|
|
178
|
+
|
|
179
|
+
if memfile != None:
|
|
180
|
+
return memfile
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from ellipsis.path.root import search, favorite, unfavorite, editPublicAccess, delete, editMetadata, move, rename, trash, recover, get
|
|
2
|
+
from ellipsis.path import hashtag
|
|
3
|
+
from ellipsis.path import invite
|
|
4
|
+
from ellipsis.path import member
|
|
5
|
+
from ellipsis.path import raster
|
|
6
|
+
from ellipsis.path import vector
|
|
7
|
+
from ellipsis.path import pointCloud
|
|
8
|
+
from ellipsis.path import usage
|
|
9
|
+
from ellipsis.path import folder
|
|
10
|
+
from ellipsis.path import file
|
|
11
|
+
from ellipsis.path import bookmark
|
|
12
|
+
from ellipsis.path import setUpTask
|
|
13
|
+
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from ellipsis import apiManager
|
|
2
|
+
from ellipsis import sanitize
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def get(pathId, token=None):
|
|
6
|
+
token = sanitize.validString('token', token, False)
|
|
7
|
+
pathId = sanitize.validUuid('pathId', pathId, True)
|
|
8
|
+
|
|
9
|
+
r = apiManager.get('/path/' + pathId + '/bookmark', {}, token)
|
|
10
|
+
|
|
11
|
+
return r
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def add(name, bookmark, token, parentId = None, publicAccess = None, metadata=None):
|
|
16
|
+
token = sanitize.validString('token', token, True)
|
|
17
|
+
bookmark = sanitize.validObject('bookmark', bookmark, True)
|
|
18
|
+
name = sanitize.validString('pathId', name, False)
|
|
19
|
+
metadata = sanitize.validObject('metadata', metadata, False)
|
|
20
|
+
publicAccess = sanitize.validObject('publicAccess', publicAccess, False)
|
|
21
|
+
parentId = sanitize.validUuid('parentId', parentId, False)
|
|
22
|
+
|
|
23
|
+
r = apiManager.post('/path/bookmark', {'name':name, 'bookmark':bookmark , 'parentId':parentId, 'publicAccess':publicAccess, 'metadata':metadata}, token)
|
|
24
|
+
|
|
25
|
+
return r
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def edit(pathId, token, layers=None, dems=None):
|
|
29
|
+
layers = sanitize.validObject('layers', layers, False)
|
|
30
|
+
dems = sanitize.validObject('dems', dems, False)
|
|
31
|
+
pathId = sanitize.validUuid('pathId', pathId, True)
|
|
32
|
+
|
|
33
|
+
r = apiManager.patch('/path/' + pathId + '/bookmark', {'layers':layers, 'dems':dems}, token)
|
|
34
|
+
|
|
35
|
+
return r
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|