sintetic-library 0.2.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.
- sintetic_library-0.2.0/PKG-INFO +115 -0
- sintetic_library-0.2.0/README.md +94 -0
- sintetic_library-0.2.0/pyproject.toml +38 -0
- sintetic_library-0.2.0/setup.cfg +4 -0
- sintetic_library-0.2.0/setup.py +3 -0
- sintetic_library-0.2.0/src/sintetic_library/__init__.py +13 -0
- sintetic_library-0.2.0/src/sintetic_library/core.py +447 -0
- sintetic_library-0.2.0/src/sintetic_library.egg-info/PKG-INFO +115 -0
- sintetic_library-0.2.0/src/sintetic_library.egg-info/SOURCES.txt +11 -0
- sintetic_library-0.2.0/src/sintetic_library.egg-info/dependency_links.txt +1 -0
- sintetic_library-0.2.0/src/sintetic_library.egg-info/requires.txt +8 -0
- sintetic_library-0.2.0/src/sintetic_library.egg-info/top_level.txt +1 -0
- sintetic_library-0.2.0/tests/test_core.py +1 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sintetic_library
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Python client for Sintetic Project. This library provides a simple interface to interact with the Sintetic API, allowing users to manage and retrieve data related to synthetic datasets. For more information, visit https://sinteticproject.eu/
|
|
5
|
+
Author-email: Leandro Rocchi <leandro.rocchi@cnr.it>
|
|
6
|
+
Project-URL: Homepage, https://github.com/n3tmaster/sintetic-client
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/n3tmaster/sintetic-client/issues
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Requires-Python: >=3.6
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
Requires-Dist: requests>=2.25.0
|
|
15
|
+
Requires-Dist: pytz>=2021.1
|
|
16
|
+
Provides-Extra: dev
|
|
17
|
+
Requires-Dist: pytest>=6.0; extra == "dev"
|
|
18
|
+
Requires-Dist: pytest-cov>=2.0; extra == "dev"
|
|
19
|
+
Requires-Dist: black>=21.0; extra == "dev"
|
|
20
|
+
Requires-Dist: mypy>=0.900; extra == "dev"
|
|
21
|
+
|
|
22
|
+
# Contents of `README.md`
|
|
23
|
+
|
|
24
|
+
# Sintetic Library
|
|
25
|
+
|
|
26
|
+
## Description
|
|
27
|
+
|
|
28
|
+
Python client for Sintetic Project. This library provides a simple interface to interact with the Sintetic API, allowing users to manage and retrieve data related to synthetic datasets.
|
|
29
|
+
For more information, visit https://sinteticproject.eu/
|
|
30
|
+
|
|
31
|
+
## Intallation
|
|
32
|
+
|
|
33
|
+
To install the library, you can use pip:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install sintetic_library
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Use case
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from sintetic_library import SinteticClient
|
|
44
|
+
|
|
45
|
+
# Create istance of SinteticClient using your Sintetic account
|
|
46
|
+
client = SinteticClient(
|
|
47
|
+
email="XXXXXX",
|
|
48
|
+
password="YYYYYYY"
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# Call method for retrieving list of tree processors
|
|
52
|
+
result = client.get_list_tree_processors ()
|
|
53
|
+
|
|
54
|
+
# Retrieve list of forest properties
|
|
55
|
+
result = client.get_list_forest_properties ()
|
|
56
|
+
|
|
57
|
+
# Retrieve list of forest properties
|
|
58
|
+
result = client.get_list_forest_properties ()
|
|
59
|
+
|
|
60
|
+
# Create tree processor id for given data
|
|
61
|
+
data = { "name" : "Test Tree Processor",
|
|
62
|
+
"type" : "harvester"
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
id_tree_processor = client.create_tree_processor(data)
|
|
66
|
+
|
|
67
|
+
# Create new forest operation from given data
|
|
68
|
+
#
|
|
69
|
+
data = { "name" : "Test Forest Operation",
|
|
70
|
+
"status" : "planned",
|
|
71
|
+
"location": {
|
|
72
|
+
"type": "Point",
|
|
73
|
+
"coordinates": [10.2, 45.2]
|
|
74
|
+
},
|
|
75
|
+
"start_date" : "2025-06-19",
|
|
76
|
+
"end_date" : "2025-06-19",
|
|
77
|
+
"area": 100,
|
|
78
|
+
"forest_property_id": "XXXXXXXX-YYYY-ZZZZ-XXXX-ZZZZZZZZZZZZ"
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
id_forest_operation = client.create_forest_operation(data)
|
|
82
|
+
|
|
83
|
+
# Retrieve list of Stan4D files
|
|
84
|
+
response = client.get_stan4d_list()
|
|
85
|
+
|
|
86
|
+
# Save new Stan4D file
|
|
87
|
+
with open("./stan4d_file.hpr", "rb") as f:
|
|
88
|
+
xml_content = f.read()
|
|
89
|
+
|
|
90
|
+
response = client.save_stan4d_object(
|
|
91
|
+
filename=os.path.basename(f.name),
|
|
92
|
+
xml_content=xml_content,
|
|
93
|
+
tree_processor_id=id_tree_processor,
|
|
94
|
+
forest_operation_id=id_forest_operation
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
# Extract Stan4D file ID
|
|
98
|
+
stand4d_id = response.json()["id"]
|
|
99
|
+
|
|
100
|
+
# Get Stan4D file using related ID
|
|
101
|
+
response = client.get_stan4d_file(fileid=stand4d_id)
|
|
102
|
+
|
|
103
|
+
# Delete Stan4D file using related ID
|
|
104
|
+
response = client.delete_stan4d_file(fileid=stand4d_id)
|
|
105
|
+
|
|
106
|
+
# Delete Forest Operation using related ID
|
|
107
|
+
response = client.delete_forest_operation(forest_operation_id=id_forest_operation)
|
|
108
|
+
|
|
109
|
+
# Delete Tree Processor using related ID
|
|
110
|
+
response = client.delete_tree_processor(tree_processor_id=id_tree_processor)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## License
|
|
114
|
+
|
|
115
|
+
This library is freely provided for use within the Sintetic project
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Contents of `README.md`
|
|
2
|
+
|
|
3
|
+
# Sintetic Library
|
|
4
|
+
|
|
5
|
+
## Description
|
|
6
|
+
|
|
7
|
+
Python client for Sintetic Project. This library provides a simple interface to interact with the Sintetic API, allowing users to manage and retrieve data related to synthetic datasets.
|
|
8
|
+
For more information, visit https://sinteticproject.eu/
|
|
9
|
+
|
|
10
|
+
## Intallation
|
|
11
|
+
|
|
12
|
+
To install the library, you can use pip:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pip install sintetic_library
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Use case
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
from sintetic_library import SinteticClient
|
|
23
|
+
|
|
24
|
+
# Create istance of SinteticClient using your Sintetic account
|
|
25
|
+
client = SinteticClient(
|
|
26
|
+
email="XXXXXX",
|
|
27
|
+
password="YYYYYYY"
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
# Call method for retrieving list of tree processors
|
|
31
|
+
result = client.get_list_tree_processors ()
|
|
32
|
+
|
|
33
|
+
# Retrieve list of forest properties
|
|
34
|
+
result = client.get_list_forest_properties ()
|
|
35
|
+
|
|
36
|
+
# Retrieve list of forest properties
|
|
37
|
+
result = client.get_list_forest_properties ()
|
|
38
|
+
|
|
39
|
+
# Create tree processor id for given data
|
|
40
|
+
data = { "name" : "Test Tree Processor",
|
|
41
|
+
"type" : "harvester"
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
id_tree_processor = client.create_tree_processor(data)
|
|
45
|
+
|
|
46
|
+
# Create new forest operation from given data
|
|
47
|
+
#
|
|
48
|
+
data = { "name" : "Test Forest Operation",
|
|
49
|
+
"status" : "planned",
|
|
50
|
+
"location": {
|
|
51
|
+
"type": "Point",
|
|
52
|
+
"coordinates": [10.2, 45.2]
|
|
53
|
+
},
|
|
54
|
+
"start_date" : "2025-06-19",
|
|
55
|
+
"end_date" : "2025-06-19",
|
|
56
|
+
"area": 100,
|
|
57
|
+
"forest_property_id": "XXXXXXXX-YYYY-ZZZZ-XXXX-ZZZZZZZZZZZZ"
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
id_forest_operation = client.create_forest_operation(data)
|
|
61
|
+
|
|
62
|
+
# Retrieve list of Stan4D files
|
|
63
|
+
response = client.get_stan4d_list()
|
|
64
|
+
|
|
65
|
+
# Save new Stan4D file
|
|
66
|
+
with open("./stan4d_file.hpr", "rb") as f:
|
|
67
|
+
xml_content = f.read()
|
|
68
|
+
|
|
69
|
+
response = client.save_stan4d_object(
|
|
70
|
+
filename=os.path.basename(f.name),
|
|
71
|
+
xml_content=xml_content,
|
|
72
|
+
tree_processor_id=id_tree_processor,
|
|
73
|
+
forest_operation_id=id_forest_operation
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Extract Stan4D file ID
|
|
77
|
+
stand4d_id = response.json()["id"]
|
|
78
|
+
|
|
79
|
+
# Get Stan4D file using related ID
|
|
80
|
+
response = client.get_stan4d_file(fileid=stand4d_id)
|
|
81
|
+
|
|
82
|
+
# Delete Stan4D file using related ID
|
|
83
|
+
response = client.delete_stan4d_file(fileid=stand4d_id)
|
|
84
|
+
|
|
85
|
+
# Delete Forest Operation using related ID
|
|
86
|
+
response = client.delete_forest_operation(forest_operation_id=id_forest_operation)
|
|
87
|
+
|
|
88
|
+
# Delete Tree Processor using related ID
|
|
89
|
+
response = client.delete_tree_processor(tree_processor_id=id_tree_processor)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## License
|
|
93
|
+
|
|
94
|
+
This library is freely provided for use within the Sintetic project
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=45", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "sintetic_library"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "Python client for Sintetic Project. This library provides a simple interface to interact with the Sintetic API, allowing users to manage and retrieve data related to synthetic datasets. For more information, visit https://sinteticproject.eu/"
|
|
9
|
+
authors = [
|
|
10
|
+
{name = "Leandro Rocchi", email = "leandro.rocchi@cnr.it"},
|
|
11
|
+
]
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
requires-python = ">=3.6"
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
"Development Status :: 3 - Alpha",
|
|
19
|
+
]
|
|
20
|
+
dependencies = [
|
|
21
|
+
"requests>=2.25.0",
|
|
22
|
+
"pytz>=2021.1",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.urls]
|
|
26
|
+
Homepage = "https://github.com/n3tmaster/sintetic-client"
|
|
27
|
+
"Bug Tracker" = "https://github.com/n3tmaster/sintetic-client/issues"
|
|
28
|
+
|
|
29
|
+
[tool.setuptools]
|
|
30
|
+
package-dir = {"" = "src"}
|
|
31
|
+
|
|
32
|
+
[project.optional-dependencies]
|
|
33
|
+
dev = [
|
|
34
|
+
"pytest>=6.0",
|
|
35
|
+
"pytest-cov>=2.0",
|
|
36
|
+
"black>=21.0",
|
|
37
|
+
"mypy>=0.900",
|
|
38
|
+
]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Sintetic Client Library
|
|
3
|
+
Una libreria Python per interfacciarsi con i servizi REST di Sintetic GeoDB
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from .core import SinteticClient
|
|
7
|
+
|
|
8
|
+
__version__ = "0.1.0"
|
|
9
|
+
__author__ = "Leandro Rocchi"
|
|
10
|
+
__email__ = "leandro.rocchi@cnr.it"
|
|
11
|
+
|
|
12
|
+
# Rendi disponibili le classi principali a livello di pacchetto
|
|
13
|
+
__all__ = ["SinteticClient"]
|
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
# Sintetic Management Client
|
|
2
|
+
# This module provides a client for interacting with the Sintetic GeoDB API
|
|
3
|
+
# with handling authentication and requests.
|
|
4
|
+
|
|
5
|
+
import requests
|
|
6
|
+
import json
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
import pytz
|
|
9
|
+
from typing import Optional, Dict, Any
|
|
10
|
+
import uuid
|
|
11
|
+
|
|
12
|
+
# Sintetic API Endpoints
|
|
13
|
+
# These endpoints are used to interact with the Sintetic GeoDB API.
|
|
14
|
+
SINTETIC_ENDPOINTS = {
|
|
15
|
+
"AUTH_LOGIN": "/auth/login",
|
|
16
|
+
"STAN_FOR_D": "/stanford_attachments",
|
|
17
|
+
"TREE_PROCESSORS": "/tree_processors",
|
|
18
|
+
"FOREST_OPERATIONS": "/forest_operations",
|
|
19
|
+
"FOREST_PROPERTIES": "/forest_properties",
|
|
20
|
+
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class SinteticClient:
|
|
25
|
+
# SinteticClient Class constructor
|
|
26
|
+
def __init__(self, email: str, password: str, base_url: str = "https://api.geodb-staging.sintetic.iit.cnr.it"):
|
|
27
|
+
self.base_url = base_url
|
|
28
|
+
self.email = email
|
|
29
|
+
self.password = password
|
|
30
|
+
self.token: Optional[str] = None
|
|
31
|
+
self.token_expiry: Optional[datetime] = None
|
|
32
|
+
|
|
33
|
+
# Check if the token is valid
|
|
34
|
+
def _check_token_validity(self) -> bool:
|
|
35
|
+
|
|
36
|
+
if not self.token or not self.token_expiry:
|
|
37
|
+
return False
|
|
38
|
+
|
|
39
|
+
now = datetime.now(pytz.UTC)
|
|
40
|
+
return now < self.token_expiry
|
|
41
|
+
|
|
42
|
+
# Login method to authenticate and obtain a new token
|
|
43
|
+
def _login(self) -> None:
|
|
44
|
+
|
|
45
|
+
login_url = f"{self.base_url}{SINTETIC_ENDPOINTS['AUTH_LOGIN']}"
|
|
46
|
+
login_data = {
|
|
47
|
+
"login": {
|
|
48
|
+
"email": self.email,
|
|
49
|
+
"password": self.password
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
try:
|
|
54
|
+
# Perform login request
|
|
55
|
+
response = requests.post(login_url, json=login_data)
|
|
56
|
+
response.raise_for_status()
|
|
57
|
+
|
|
58
|
+
data = response.json()
|
|
59
|
+
self.token = data["login"]["token"]
|
|
60
|
+
self.token_expiry = datetime.strptime(
|
|
61
|
+
data["login"]["expiry"],
|
|
62
|
+
"%Y-%m-%dT%H:%M:%SZ"
|
|
63
|
+
).replace(tzinfo=pytz.UTC)
|
|
64
|
+
|
|
65
|
+
except requests.exceptions.RequestException as e:
|
|
66
|
+
raise Exception(f"Exeption on: {str(e)}")
|
|
67
|
+
# Get headers with authentication token
|
|
68
|
+
def _get_headers(self) -> Dict[str, str]:
|
|
69
|
+
|
|
70
|
+
if not self._check_token_validity():
|
|
71
|
+
self._login()
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
"Authorization": f"Bearer {self.token}",
|
|
75
|
+
"Content-Type": "application/json"
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
# Make a generic request to the Sintetic API
|
|
79
|
+
def make_request(self, method: str, endpoint: str, **kwargs) -> Any:
|
|
80
|
+
"""
|
|
81
|
+
Perform a generic https request to the Sintetic API
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
method: Metodo HTTP (get, post, put, delete, etc.)
|
|
85
|
+
endpoint: Endpoint of API
|
|
86
|
+
**kwargs: Optional parameters for the request, such as data or params
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
JSON response from the API
|
|
90
|
+
"""
|
|
91
|
+
|
|
92
|
+
url = f"{self.base_url}{endpoint}"
|
|
93
|
+
|
|
94
|
+
headers = self._get_headers()
|
|
95
|
+
|
|
96
|
+
if "headers" in kwargs:
|
|
97
|
+
headers.update(kwargs["headers"])
|
|
98
|
+
kwargs["headers"] = headers
|
|
99
|
+
|
|
100
|
+
try:
|
|
101
|
+
|
|
102
|
+
response = requests.request(method, url, **kwargs)
|
|
103
|
+
response.raise_for_status()
|
|
104
|
+
return response
|
|
105
|
+
except requests.exceptions.RequestException as e:
|
|
106
|
+
raise Exception(f"Exception on: {str(e)}")
|
|
107
|
+
|
|
108
|
+
# Get Stand4D Attachments list
|
|
109
|
+
# Returns:
|
|
110
|
+
# List of attachments with created_at, name and url
|
|
111
|
+
def get_stan4d_list(self, **kwargs) -> Any:
|
|
112
|
+
|
|
113
|
+
url = f"{self.base_url}{SINTETIC_ENDPOINTS['STAN_FOR_D']}"
|
|
114
|
+
headers = self._get_headers()
|
|
115
|
+
|
|
116
|
+
if "headers" in kwargs:
|
|
117
|
+
headers.update(kwargs["headers"])
|
|
118
|
+
kwargs["headers"] = headers
|
|
119
|
+
|
|
120
|
+
try:
|
|
121
|
+
method="GET"
|
|
122
|
+
response = requests.request(method, url, **kwargs)
|
|
123
|
+
response.raise_for_status()
|
|
124
|
+
|
|
125
|
+
response_data = response.json()
|
|
126
|
+
#extract a subset of data composed by created_at, name and url
|
|
127
|
+
filtered_data = [
|
|
128
|
+
{
|
|
129
|
+
"id": item.get("id", ""),
|
|
130
|
+
"created_at": item.get("created_at", ""),
|
|
131
|
+
"name": item.get("name", ""),
|
|
132
|
+
"url": item.get("url", "")
|
|
133
|
+
}
|
|
134
|
+
for item in response_data
|
|
135
|
+
]
|
|
136
|
+
return filtered_data
|
|
137
|
+
except requests.exceptions.RequestException as e:
|
|
138
|
+
raise Exception(f"Exception on: {str(e)}")
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
# Get Stand4D Attachment object from given ID
|
|
142
|
+
# Returns:
|
|
143
|
+
# XML object of the attachment with given ID
|
|
144
|
+
def get_stan4d_file(self, fileid: str, **kwargs) -> Any:
|
|
145
|
+
"""
|
|
146
|
+
Get Stand4D Attachment XML file from given ID
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
fileid: ID of the attachment to retrieve
|
|
150
|
+
**kwargs: Optional parameters for the request
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
str: XML content of the attachment
|
|
154
|
+
"""
|
|
155
|
+
url = f"{self.base_url}{SINTETIC_ENDPOINTS['STAN_FOR_D']}/files/{fileid}"
|
|
156
|
+
headers = self._get_headers()
|
|
157
|
+
|
|
158
|
+
if "headers" in kwargs:
|
|
159
|
+
headers.update(kwargs["headers"])
|
|
160
|
+
kwargs["headers"] = headers
|
|
161
|
+
|
|
162
|
+
try:
|
|
163
|
+
method="GET"
|
|
164
|
+
response = requests.request(method, url, **kwargs)
|
|
165
|
+
response.raise_for_status()
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
return response.text
|
|
169
|
+
except requests.exceptions.RequestException as e:
|
|
170
|
+
raise Exception(f"Exception on: {str(e)}")
|
|
171
|
+
|
|
172
|
+
# Get Stand4D Attachment object from given ID
|
|
173
|
+
# Returns:
|
|
174
|
+
# XML object of the attachment with given ID
|
|
175
|
+
def save_stan4d_object(self, filename: str, xml_content: bytes, tree_processor_id: str,
|
|
176
|
+
forest_operation_id: str, **kwargs) -> Any:
|
|
177
|
+
"""
|
|
178
|
+
Get Stand4D Attachment XML file from given ID
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
fileid: ID of the attachment to retrieve
|
|
182
|
+
**kwargs: Optional parameters for the request
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
str: XML content of the attachment
|
|
186
|
+
"""
|
|
187
|
+
url = f"{self.base_url}{SINTETIC_ENDPOINTS['STAN_FOR_D']}"
|
|
188
|
+
|
|
189
|
+
data = {
|
|
190
|
+
"attachment:tree_processor_id": tree_processor_id,
|
|
191
|
+
"attachment:forest_operation_id": forest_operation_id,
|
|
192
|
+
"attachment:id": str(uuid.uuid4())
|
|
193
|
+
}
|
|
194
|
+
files = {
|
|
195
|
+
"attachment:file": (filename, xml_content, "application/xml")
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
headers = self._get_headers()
|
|
200
|
+
headers.pop("Content-Type", None) # requests set Content-Type for MultiPart
|
|
201
|
+
|
|
202
|
+
if "headers" in kwargs:
|
|
203
|
+
headers.update(kwargs["headers"])
|
|
204
|
+
kwargs["headers"] = headers
|
|
205
|
+
# --- STAMPA DETTAGLI DELLA CHIAMATA ---
|
|
206
|
+
if kwargs:
|
|
207
|
+
print("Altri kwargs:", kwargs)
|
|
208
|
+
try:
|
|
209
|
+
response = requests.post(
|
|
210
|
+
url,
|
|
211
|
+
data=data,
|
|
212
|
+
files=files,
|
|
213
|
+
**kwargs
|
|
214
|
+
)
|
|
215
|
+
response.raise_for_status()
|
|
216
|
+
return response
|
|
217
|
+
|
|
218
|
+
except requests.exceptions.RequestException as e:
|
|
219
|
+
raise Exception(f"Exception on: {str(e)}")
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
# Get list forest operations
|
|
223
|
+
# Returns:
|
|
224
|
+
# json array of forest operations with created_at, name and url
|
|
225
|
+
def get_list_forest_operations(self, **kwargs) -> Any:
|
|
226
|
+
"""
|
|
227
|
+
Get list of forest operations
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
**kwargs: Optional parameters for the request
|
|
231
|
+
|
|
232
|
+
Returns:
|
|
233
|
+
List of forest operations with created_at, name and url
|
|
234
|
+
"""
|
|
235
|
+
url = f"{self.base_url}{SINTETIC_ENDPOINTS['FOREST_OPERATIONS']}"
|
|
236
|
+
headers = self._get_headers()
|
|
237
|
+
|
|
238
|
+
if "headers" in kwargs:
|
|
239
|
+
headers.update(kwargs["headers"])
|
|
240
|
+
kwargs["headers"] = headers
|
|
241
|
+
|
|
242
|
+
try:
|
|
243
|
+
method="GET"
|
|
244
|
+
response = requests.request(method, url, **kwargs)
|
|
245
|
+
response.raise_for_status()
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
return response.text
|
|
249
|
+
except requests.exceptions.RequestException as e:
|
|
250
|
+
raise Exception(f"Exception on: {str(e)}")
|
|
251
|
+
|
|
252
|
+
# Get list forest properties
|
|
253
|
+
def get_list_forest_properties(self, **kwargs) -> Any:
|
|
254
|
+
"""
|
|
255
|
+
Get list of forest properties
|
|
256
|
+
Args:
|
|
257
|
+
**kwargs: Optional parameters for the request
|
|
258
|
+
Returns:
|
|
259
|
+
List of forest properties with created_at, name and url
|
|
260
|
+
"""
|
|
261
|
+
url = f"{self.base_url}{SINTETIC_ENDPOINTS['FOREST_PROPERTIES']}"
|
|
262
|
+
headers = self._get_headers()
|
|
263
|
+
|
|
264
|
+
if "headers" in kwargs:
|
|
265
|
+
headers.update(kwargs["headers"])
|
|
266
|
+
kwargs["headers"] = headers
|
|
267
|
+
|
|
268
|
+
try:
|
|
269
|
+
method="GET"
|
|
270
|
+
response = requests.request(method, url, **kwargs)
|
|
271
|
+
response.raise_for_status()
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
return response.text
|
|
275
|
+
except requests.exceptions.RequestException as e:
|
|
276
|
+
raise Exception(f"Exception on: {str(e)}")
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
# Get list tree processors
|
|
280
|
+
# Returns:
|
|
281
|
+
# json array of tree processors with created_at, name and url
|
|
282
|
+
def get_list_tree_processors(self, **kwargs) -> Any:
|
|
283
|
+
"""
|
|
284
|
+
Get list of tree processors
|
|
285
|
+
|
|
286
|
+
Args:
|
|
287
|
+
**kwargs: Optional parameters for the request
|
|
288
|
+
|
|
289
|
+
Returns:
|
|
290
|
+
List of tree processors with created_at, name and url
|
|
291
|
+
"""
|
|
292
|
+
url = f"{self.base_url}{SINTETIC_ENDPOINTS['TREE_PROCESSORS']}"
|
|
293
|
+
headers = self._get_headers()
|
|
294
|
+
|
|
295
|
+
if "headers" in kwargs:
|
|
296
|
+
headers.update(kwargs["headers"])
|
|
297
|
+
kwargs["headers"] = headers
|
|
298
|
+
|
|
299
|
+
try:
|
|
300
|
+
method="GET"
|
|
301
|
+
response = requests.request(method, url, **kwargs)
|
|
302
|
+
response.raise_for_status()
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
return response.text
|
|
306
|
+
except requests.exceptions.RequestException as e:
|
|
307
|
+
raise Exception(f"Exception on: {str(e)}")
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
# Create a new tree processor
|
|
311
|
+
def create_tree_processor(self, data: dict, **kwargs) -> Any:
|
|
312
|
+
"""
|
|
313
|
+
Create a new tree processor
|
|
314
|
+
Args:
|
|
315
|
+
data: Dictionary containing the tree processor data
|
|
316
|
+
**kwargs: Optional parameters for the request
|
|
317
|
+
Returns:
|
|
318
|
+
JSON response from the API
|
|
319
|
+
"""
|
|
320
|
+
|
|
321
|
+
# Generate a unique ID for the tree processor
|
|
322
|
+
data["id"] = str(uuid.uuid4())
|
|
323
|
+
url = f"{self.base_url}{SINTETIC_ENDPOINTS['TREE_PROCESSORS']}"
|
|
324
|
+
headers = self._get_headers()
|
|
325
|
+
headers["Content-Type"] = "application/json"
|
|
326
|
+
|
|
327
|
+
try:
|
|
328
|
+
response = requests.post(
|
|
329
|
+
url=url,
|
|
330
|
+
headers=headers,
|
|
331
|
+
json=data # requests gestirà automaticamente la serializzazione in JSON
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
response.raise_for_status()
|
|
335
|
+
return data["id"]
|
|
336
|
+
except requests.exceptions.RequestException as e:
|
|
337
|
+
raise Exception(f"Exception on: {str(e)}")
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
# Create a new forest operation
|
|
341
|
+
def create_forest_operation(self, data: dict, **kwargs) -> Any:
|
|
342
|
+
"""
|
|
343
|
+
Create a new forest operation
|
|
344
|
+
Args:
|
|
345
|
+
data: Dictionary containing the forest operation data
|
|
346
|
+
**kwargs: Optional parameters for the request
|
|
347
|
+
Returns:
|
|
348
|
+
JSON response from the API
|
|
349
|
+
"""
|
|
350
|
+
|
|
351
|
+
url = f"{self.base_url}{SINTETIC_ENDPOINTS['FOREST_OPERATIONS']}"
|
|
352
|
+
headers = self._get_headers()
|
|
353
|
+
headers["Content-Type"] = "application/json"
|
|
354
|
+
data["id"] = str(uuid.uuid4())
|
|
355
|
+
print("Data to create forest operation:", data)
|
|
356
|
+
try:
|
|
357
|
+
response = requests.post(
|
|
358
|
+
url=url,
|
|
359
|
+
headers=headers,
|
|
360
|
+
json=data # requests gestirà automaticamente la serializzazione in JSON
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
response.raise_for_status()
|
|
364
|
+
return data["id"]
|
|
365
|
+
except requests.exceptions.RequestException as e:
|
|
366
|
+
raise Exception(f"Exception on: {str(e)}")
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
# Delete a new tree processor
|
|
370
|
+
def delete_stan4d_file(self, fileid: str, **kwargs) -> Any:
|
|
371
|
+
|
|
372
|
+
""" Delete a Stand4D file by its ID
|
|
373
|
+
Args:
|
|
374
|
+
fileid: ID of the Stand4D file to delete
|
|
375
|
+
**kwargs: Optional parameters for the request
|
|
376
|
+
Returns:
|
|
377
|
+
int: HTTP status code of the response
|
|
378
|
+
"""
|
|
379
|
+
|
|
380
|
+
url = f"{self.base_url}{SINTETIC_ENDPOINTS['STAN_FOR_D']}/{fileid}"
|
|
381
|
+
headers = self._get_headers()
|
|
382
|
+
headers["Content-Type"] = "application/json"
|
|
383
|
+
|
|
384
|
+
try:
|
|
385
|
+
response = requests.delete(
|
|
386
|
+
url=url,
|
|
387
|
+
headers=headers,
|
|
388
|
+
|
|
389
|
+
)
|
|
390
|
+
|
|
391
|
+
response.raise_for_status()
|
|
392
|
+
return response.status_code
|
|
393
|
+
except requests.exceptions.RequestException as e:
|
|
394
|
+
raise Exception(f"Exception on: {str(e)}")
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
# Delete a forest operation
|
|
398
|
+
# Args:
|
|
399
|
+
# forest_operation_id: ID of the forest operation to delete
|
|
400
|
+
# Returns:
|
|
401
|
+
# int: HTTP status code of the response
|
|
402
|
+
def delete_forest_operation(self, forest_operation_id: str, **kwargs) -> Any:
|
|
403
|
+
|
|
404
|
+
url = f"{SINTETIC_ENDPOINTS['FOREST_OPERATIONS']}/{forest_operation_id}"
|
|
405
|
+
headers = self._get_headers()
|
|
406
|
+
|
|
407
|
+
if "headers" in kwargs:
|
|
408
|
+
headers.update(kwargs["headers"])
|
|
409
|
+
kwargs["headers"] = headers
|
|
410
|
+
|
|
411
|
+
try:
|
|
412
|
+
|
|
413
|
+
response = self.make_request("DELETE", url, **kwargs)
|
|
414
|
+
|
|
415
|
+
return response.status_code
|
|
416
|
+
except requests.exceptions.RequestException as e:
|
|
417
|
+
raise Exception(f"Exception on: {str(e)}")
|
|
418
|
+
|
|
419
|
+
# Delete a tree processor
|
|
420
|
+
# Args:
|
|
421
|
+
# forest_operation_id: ID of the forest operation to delete
|
|
422
|
+
# Returns:
|
|
423
|
+
# int: HTTP status code of the response
|
|
424
|
+
def delete_tree_processor(self, tree_processor_id: str, **kwargs) -> Any:
|
|
425
|
+
"""
|
|
426
|
+
Get list of forest operations
|
|
427
|
+
|
|
428
|
+
Args:
|
|
429
|
+
**kwargs: Optional parameters for the request
|
|
430
|
+
|
|
431
|
+
Returns:
|
|
432
|
+
List of forest operations with created_at, name and url
|
|
433
|
+
"""
|
|
434
|
+
url = f"{SINTETIC_ENDPOINTS['TREE_PROCESSORS']}/{tree_processor_id}"
|
|
435
|
+
headers = self._get_headers()
|
|
436
|
+
|
|
437
|
+
if "headers" in kwargs:
|
|
438
|
+
headers.update(kwargs["headers"])
|
|
439
|
+
kwargs["headers"] = headers
|
|
440
|
+
|
|
441
|
+
try:
|
|
442
|
+
response = self.make_request("DELETE", url, **kwargs)
|
|
443
|
+
|
|
444
|
+
return response.status_code
|
|
445
|
+
except requests.exceptions.RequestException as e:
|
|
446
|
+
raise Exception(f"Exception on: {str(e)}")
|
|
447
|
+
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sintetic_library
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Python client for Sintetic Project. This library provides a simple interface to interact with the Sintetic API, allowing users to manage and retrieve data related to synthetic datasets. For more information, visit https://sinteticproject.eu/
|
|
5
|
+
Author-email: Leandro Rocchi <leandro.rocchi@cnr.it>
|
|
6
|
+
Project-URL: Homepage, https://github.com/n3tmaster/sintetic-client
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/n3tmaster/sintetic-client/issues
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Requires-Python: >=3.6
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
Requires-Dist: requests>=2.25.0
|
|
15
|
+
Requires-Dist: pytz>=2021.1
|
|
16
|
+
Provides-Extra: dev
|
|
17
|
+
Requires-Dist: pytest>=6.0; extra == "dev"
|
|
18
|
+
Requires-Dist: pytest-cov>=2.0; extra == "dev"
|
|
19
|
+
Requires-Dist: black>=21.0; extra == "dev"
|
|
20
|
+
Requires-Dist: mypy>=0.900; extra == "dev"
|
|
21
|
+
|
|
22
|
+
# Contents of `README.md`
|
|
23
|
+
|
|
24
|
+
# Sintetic Library
|
|
25
|
+
|
|
26
|
+
## Description
|
|
27
|
+
|
|
28
|
+
Python client for Sintetic Project. This library provides a simple interface to interact with the Sintetic API, allowing users to manage and retrieve data related to synthetic datasets.
|
|
29
|
+
For more information, visit https://sinteticproject.eu/
|
|
30
|
+
|
|
31
|
+
## Intallation
|
|
32
|
+
|
|
33
|
+
To install the library, you can use pip:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install sintetic_library
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Use case
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from sintetic_library import SinteticClient
|
|
44
|
+
|
|
45
|
+
# Create istance of SinteticClient using your Sintetic account
|
|
46
|
+
client = SinteticClient(
|
|
47
|
+
email="XXXXXX",
|
|
48
|
+
password="YYYYYYY"
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# Call method for retrieving list of tree processors
|
|
52
|
+
result = client.get_list_tree_processors ()
|
|
53
|
+
|
|
54
|
+
# Retrieve list of forest properties
|
|
55
|
+
result = client.get_list_forest_properties ()
|
|
56
|
+
|
|
57
|
+
# Retrieve list of forest properties
|
|
58
|
+
result = client.get_list_forest_properties ()
|
|
59
|
+
|
|
60
|
+
# Create tree processor id for given data
|
|
61
|
+
data = { "name" : "Test Tree Processor",
|
|
62
|
+
"type" : "harvester"
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
id_tree_processor = client.create_tree_processor(data)
|
|
66
|
+
|
|
67
|
+
# Create new forest operation from given data
|
|
68
|
+
#
|
|
69
|
+
data = { "name" : "Test Forest Operation",
|
|
70
|
+
"status" : "planned",
|
|
71
|
+
"location": {
|
|
72
|
+
"type": "Point",
|
|
73
|
+
"coordinates": [10.2, 45.2]
|
|
74
|
+
},
|
|
75
|
+
"start_date" : "2025-06-19",
|
|
76
|
+
"end_date" : "2025-06-19",
|
|
77
|
+
"area": 100,
|
|
78
|
+
"forest_property_id": "XXXXXXXX-YYYY-ZZZZ-XXXX-ZZZZZZZZZZZZ"
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
id_forest_operation = client.create_forest_operation(data)
|
|
82
|
+
|
|
83
|
+
# Retrieve list of Stan4D files
|
|
84
|
+
response = client.get_stan4d_list()
|
|
85
|
+
|
|
86
|
+
# Save new Stan4D file
|
|
87
|
+
with open("./stan4d_file.hpr", "rb") as f:
|
|
88
|
+
xml_content = f.read()
|
|
89
|
+
|
|
90
|
+
response = client.save_stan4d_object(
|
|
91
|
+
filename=os.path.basename(f.name),
|
|
92
|
+
xml_content=xml_content,
|
|
93
|
+
tree_processor_id=id_tree_processor,
|
|
94
|
+
forest_operation_id=id_forest_operation
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
# Extract Stan4D file ID
|
|
98
|
+
stand4d_id = response.json()["id"]
|
|
99
|
+
|
|
100
|
+
# Get Stan4D file using related ID
|
|
101
|
+
response = client.get_stan4d_file(fileid=stand4d_id)
|
|
102
|
+
|
|
103
|
+
# Delete Stan4D file using related ID
|
|
104
|
+
response = client.delete_stan4d_file(fileid=stand4d_id)
|
|
105
|
+
|
|
106
|
+
# Delete Forest Operation using related ID
|
|
107
|
+
response = client.delete_forest_operation(forest_operation_id=id_forest_operation)
|
|
108
|
+
|
|
109
|
+
# Delete Tree Processor using related ID
|
|
110
|
+
response = client.delete_tree_processor(tree_processor_id=id_tree_processor)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## License
|
|
114
|
+
|
|
115
|
+
This library is freely provided for use within the Sintetic project
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
setup.py
|
|
4
|
+
src/sintetic_library/__init__.py
|
|
5
|
+
src/sintetic_library/core.py
|
|
6
|
+
src/sintetic_library.egg-info/PKG-INFO
|
|
7
|
+
src/sintetic_library.egg-info/SOURCES.txt
|
|
8
|
+
src/sintetic_library.egg-info/dependency_links.txt
|
|
9
|
+
src/sintetic_library.egg-info/requires.txt
|
|
10
|
+
src/sintetic_library.egg-info/top_level.txt
|
|
11
|
+
tests/test_core.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
sintetic_library
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#Empty file
|