sinapsis-aperturedb 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
File without changes
File without changes
@@ -0,0 +1,60 @@
1
+ # -*- coding: utf-8 -*-
2
+ from typing import Any
3
+
4
+ from pydantic import BaseModel
5
+ from sinapsis_core.utils.env_var_keys import EnvVarEntry, doc_str, return_docs_for_vars
6
+
7
+
8
+ class _ApertureDBEnvVars(BaseModel):
9
+ """Env vars for ApertureDB."""
10
+
11
+ APERTUREDB_API_KEY: EnvVarEntry = EnvVarEntry(
12
+ var_name="APERTUREDB_API_KEY",
13
+ default_value="",
14
+ allowed_values=None,
15
+ description="set api key for ApertureDB",
16
+ )
17
+ APERTUREDB_HOST: EnvVarEntry = EnvVarEntry(
18
+ var_name="APERTUREDB_HOST",
19
+ default_value="localhost",
20
+ allowed_values=None,
21
+ description="set host for ApertureDB",
22
+ )
23
+ APERTUREDB_USER: EnvVarEntry = EnvVarEntry(
24
+ var_name="APERTUREDB_USER",
25
+ default_value="",
26
+ allowed_values=None,
27
+ description="set user for ApertureDB",
28
+ )
29
+ APERTUREDB_PASSWORD: EnvVarEntry = EnvVarEntry(
30
+ var_name="APERTUREDB_PASSWORD",
31
+ default_value="",
32
+ allowed_values=None,
33
+ description="set password for ApertureDB",
34
+ )
35
+ APERTUREDB_PORT: EnvVarEntry = EnvVarEntry(
36
+ var_name="APERTUREDB_PORT",
37
+ default_value="55555",
38
+ allowed_values=None,
39
+ description="set port for ApertureDB",
40
+ )
41
+
42
+
43
+ ApertureDBEnvVars = _ApertureDBEnvVars()
44
+
45
+ doc_str = return_docs_for_vars(
46
+ ApertureDBEnvVars,
47
+ docs=doc_str,
48
+ string_for_doc="""ApertureDB env vars available: \n""",
49
+ )
50
+ __doc__ = doc_str
51
+
52
+
53
+ def __getattr__(name: str) -> Any:
54
+ if name in ApertureDBEnvVars.model_fields:
55
+ return ApertureDBEnvVars.model_fields[name].default.value
56
+
57
+ raise AttributeError(f"Agent does not have `{name}` env var")
58
+
59
+
60
+ _all__ = (*list(ApertureDBEnvVars.model_fields.keys()), "ApertureDBEnvVars")
@@ -0,0 +1,34 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from pydantic import Field
4
+
5
+ from sinapsis_aperturedb.helpers.query_base_models.base import (
6
+ ConstraintsType,
7
+ CreateConnectionType,
8
+ DateType,
9
+ QueryParameters,
10
+ ReferenceType,
11
+ )
12
+
13
+
14
+ class BaseAddParameters(QueryParameters):
15
+ """Base class for Add_ commands parameters.
16
+
17
+ [optional] _ref: reference to be used within the transaction.
18
+ [optional] properties: key-value pairs associated with objects (Entity, Image, Video, Descriptor, etc) and connections.
19
+ [optional] if_not_found: When using if_not_found, an Add* command (AddEntity, etc) will become a "conditional add"
20
+ the object will be inserted into the database if and only if there is no other element of the same type that
21
+ fulfills the specified constraints
22
+ [optional] connect
23
+ """
24
+
25
+ ref: ReferenceType | None = Field(alias="_ref", default=None)
26
+ properties: dict[str, int | float | str | bool | DateType] | None = None
27
+ if_not_found: ConstraintsType | None = None
28
+ connect: CreateConnectionType | None = None
29
+
30
+
31
+ class AddEntityParameters(BaseAddParameters):
32
+ """AddEntity class: name of entity class."""
33
+
34
+ class_: str = Field(alias="class")
@@ -0,0 +1,165 @@
1
+ # -*- coding: utf-8 -*-
2
+ from typing import Annotated, Any, Literal, Tuple
3
+
4
+ from pydantic import BaseModel, Field
5
+
6
+
7
+ class ConnectionParams(BaseModel):
8
+ """Model to store connection parameters to ApertureDB server."""
9
+
10
+ host: str | None = None
11
+ user: str | None = None
12
+ port: int | None = None
13
+ password: str | None = None
14
+ key: str | None = None
15
+ use_ssl: bool | None = None
16
+
17
+ def get_connection_params(self) -> dict[str, Any]:
18
+ """Get connection parameters as a dictionary, excluding None and unset values."""
19
+ conn_params = self.model_dump(exclude_none=True, exclude_unset=True)
20
+ return conn_params
21
+
22
+
23
+ class QueryParameters(BaseModel):
24
+ """Base class for query parameters."""
25
+
26
+ def get_parameters(self) -> dict[str, Any]:
27
+ """Format parameters as a dictionary. Excludes any not set."""
28
+ dumped_model = self.model_dump(mode="json", by_alias=True, exclude_unset=True, exclude_none=True)
29
+ return self.remove_empty_dicts(dumped_model)
30
+
31
+ @staticmethod
32
+ def remove_empty_dicts(data: dict) -> dict:
33
+ """Remove empty dictionaries and lists from the input dictionary.
34
+
35
+ Parameters
36
+ ----------
37
+ data (dict): Dictionary to filter.
38
+
39
+ Returns:
40
+ -------
41
+ dict: Dictionary with None values and empty dicts/lists removed.
42
+ """
43
+ return {k: v for k, v in data.items() if v is not None and (not isinstance(v, (dict, list)) or len(v) > 0)}
44
+
45
+
46
+ class Query(BaseModel):
47
+ """Query base model."""
48
+
49
+ command: str
50
+ parameters: QueryParameters
51
+ blobs: list[bytes] | None = None
52
+
53
+ def prepare_query(self) -> Tuple[dict[str, Any], list[bytes]]:
54
+ """Format the query as a dictionary required by ApertureDB.
55
+
56
+ A query is composed of:
57
+ a string representing a JSON array of one or more commands, and
58
+ [optional] an "array of blobs".
59
+
60
+ """
61
+ query = {self.command: self.parameters.get_parameters()}
62
+ if self.blobs:
63
+ return query, self.blobs
64
+ return query, []
65
+
66
+
67
+ class Response(BaseModel):
68
+ """Base model to store ApertureDB responses.
69
+
70
+ The JSON response is an array of objects where each member gives information about how a particular command executed.
71
+
72
+ status: Indicates execution status (e.g., 0 for success).
73
+ returned: Indicates the number of entities, connections, or blobs returned. If the user requests only aggregated values (e.g., sum, average) or uses _ref without requesting any properties, "returned" will be 0.
74
+ entities/connections [Optional]: Included only when the user explicitly requests property values.
75
+ blobs_start[Optional]: Included only if blobs=true was set in the query. Indicates the 0-based index in the return vector where blob data for this command begins.
76
+ _blob_index[Optional]: Included in each entity only if blobs=true. Indicates the blob's position relative to the full return vector.
77
+
78
+ """
79
+
80
+ status: int
81
+ info: str | None = None
82
+ returned: int | None = None
83
+ entities: list[dict[str, Any]] | dict[str, Any] | None = None
84
+ connections: list[dict[str, Any]] | dict[str, Any] | None = None
85
+ blobs_start: int | None = None
86
+ command: str | None = Field(exclude=True, default=None)
87
+
88
+ def format_response_dict(self) -> dict[str, Any]:
89
+ """Format the response as a dictionary.
90
+
91
+ If a command is set, returns a dictionary with the command as the key.
92
+ Otherwise, returns the response dictionary directly.
93
+
94
+ Returns:
95
+ -------
96
+ dict[str, Any]: Formatted response dictionary.
97
+ """
98
+ response_dict = self.model_dump(mode="json", exclude_unset=True)
99
+ if self.command is not None:
100
+ return {self.command: response_dict}
101
+ return response_dict
102
+
103
+
104
+ # ------------Parameter types
105
+ ReferenceType = Annotated[int, Field(ge=1, le=100000)]
106
+ ConstraintsType = list[Any] | dict[str, Any] | None
107
+ ImageFormatType = Literal["jpg", "png"]
108
+ EngineType = Literal["Flat", "IVF", "HNSW"]
109
+ MetricType = Literal["L2", "IP", "CS"]
110
+
111
+
112
+ class ConnectionRef(BaseModel):
113
+ ref: ReferenceType | None = None
114
+ connection_class: str | None = None
115
+ constraints: ConstraintsType = None
116
+
117
+
118
+ class IsConnectedTo(BaseModel):
119
+ ref: ReferenceType | None = None
120
+ connection_class: str | None = None
121
+ constraints: ConstraintsType | None = None
122
+ any: list[ConnectionRef] | None = None
123
+ in_: list[ConnectionRef] | None = Field(alias="in", default=None)
124
+ out: list[ConnectionRef] | None = None
125
+
126
+
127
+ class ResultsType(BaseModel):
128
+ list_: list[str] | None = Field(alias="list", default=None)
129
+ all_properties: bool | None = None
130
+ count: bool | None = None
131
+ sum: str | list[str] | None = None
132
+ average: str | list[str] | None = None
133
+ min: str | list[str] | None = None
134
+ max: str | list[str] | None = None
135
+ group: list[str] | None = None
136
+
137
+
138
+ class BatchType(BaseModel):
139
+ batches: int | None = None
140
+ batch_size: int | None = None
141
+ batch_id: int | None = None
142
+
143
+
144
+ class DateType(BaseModel):
145
+ """datetime (ISO 8601 representation)."""
146
+
147
+ date: str = Field(alias="_date")
148
+
149
+
150
+ class CreateConnectionType(BaseModel):
151
+ """ref: Reference to other objects within the transaction.
152
+
153
+ [optional] class: Name of the class that is used to describe the relationship between the objects.
154
+ [optional] direction: [in, out]. Default is "out. "in" indicates that the relationship actually ends at the object
155
+ (object) in the Add*.
156
+ """
157
+
158
+ ref: ReferenceType
159
+ class_: str | None = Field(alias="class", default=None)
160
+ direction: Literal["in", "out"] | None = None
161
+
162
+
163
+ class GetSchemaParameters(QueryParameters):
164
+ ref: ReferenceType | None = None
165
+ type: Literal["entities", "connections", "both"] | None = None
@@ -0,0 +1,38 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+
4
+ from sinapsis_aperturedb.helpers.query_base_models.base import (
5
+ ConstraintsType,
6
+ QueryParameters,
7
+ ReferenceType,
8
+ )
9
+
10
+
11
+ class BaseDeleteParameters(QueryParameters):
12
+ """Base parameters for Delete_ commands.
13
+
14
+ [optional] ref: Reference to other entity objects within the transaction.
15
+ [optional] constraints
16
+ """
17
+
18
+ ref: ReferenceType | None = None
19
+ constraints: ConstraintsType | None = None
20
+
21
+
22
+ class DeleteEntityParameters(BaseDeleteParameters):
23
+ """Parameters for DeleteEntity command.
24
+
25
+ [optional] with_class: Specifies the entity class.
26
+ """
27
+
28
+ with_class: str | None = None
29
+
30
+
31
+ class DeleteDescriptorSetParameters(BaseDeleteParameters):
32
+ """Parameters for DeleteDescriptorSet command.
33
+
34
+ [optional] background: Differs deletion of the set and associated descriptions as a background task.
35
+ Defaults to false.
36
+ """
37
+
38
+ set: str
@@ -0,0 +1,52 @@
1
+ # -*- coding: utf-8 -*-
2
+ from pydantic import Field
3
+
4
+ from sinapsis_aperturedb.helpers.query_base_models.base import (
5
+ BatchType,
6
+ ConstraintsType,
7
+ IsConnectedTo,
8
+ QueryParameters,
9
+ ReferenceType,
10
+ ResultsType,
11
+ )
12
+
13
+
14
+ class BaseFindParameters(QueryParameters):
15
+ """Base parameters for Find_ commands.
16
+
17
+ [optional] _ref: Reference to be used within the transaction.
18
+ [optional] unique: Indicates whether a single object is expected to satisfy the constraints.
19
+ [optional] constraints: used to specify search/filter criteria over the properties defined for objects
20
+ [optional] is_connected_to: specifies one or more connection-based constraints that must be satisfied in a Find* command
21
+ [optional] group_by_source: specifies in a Find* command the result is a set of objects connected to the referenced
22
+ Find* command by connections as defined by the is_connected_to parameter
23
+ [optional] results: Defines the information returned in the JSON response as a result of a Find* command
24
+ [optional] batch: specify a query that can be used by multiple workers to retrieve a portion of the results
25
+ [optional] sort: specifies how the results will be sorted on the response, and which properties will be used for sorting
26
+ [optional] limit: specifies the maximum number of elements that will be returned.
27
+ [optional] offset: specifies the number of results that will be skipped
28
+ [optional] uniqueids: indicates whether unique ids will be returned as part of the response (Default: false).
29
+
30
+
31
+ """
32
+
33
+ ref: ReferenceType | None = Field(alias="_ref", default=None)
34
+ unique: bool | None = None
35
+ constraints: ConstraintsType | None = Field(default=None)
36
+ is_connected_to: IsConnectedTo = Field(default_factory=dict)
37
+ group_by_source: bool | None = None
38
+ results: ResultsType = Field(default_factory=dict)
39
+ batch: BatchType = Field(default_factory=dict)
40
+ sort: str | dict[str, str] | list[dict[str, str]] | None = None
41
+ limit: int | None = None
42
+ offset: int | None = None
43
+ uniqueids: bool | None = None
44
+
45
+
46
+ class FindEntityParameters(BaseFindParameters):
47
+ """Parameters for FindEntity command.
48
+
49
+ [optional] with_class: Name of entity class.
50
+ """
51
+
52
+ with_class: str | None = None
@@ -0,0 +1,72 @@
1
+ # -*- coding: utf-8 -*-
2
+ from sinapsis_aperturedb.helpers.query_base_models.base import (
3
+ ConstraintsType,
4
+ DateType,
5
+ QueryParameters,
6
+ RectangleType,
7
+ ReferenceType,
8
+ )
9
+
10
+
11
+ class BaseUpdateParameters(QueryParameters):
12
+ """Base parameters for Update_ commands.
13
+
14
+ [optional] ref: Reference to other entities within the transaction.
15
+ [optional] constraints: used to specify search/filter criteria over the properties defined for objects
16
+ [optional] properties: key-value pairs associated with objects (Entity, Image, Video, Descriptor, etc) and connections.
17
+ [optional] remove_props: list of property keys that will be removed as part of an Update* command.
18
+ """
19
+
20
+ ref: ReferenceType | None = None
21
+ constraints: ConstraintsType | None = None
22
+ properties: dict[str, int | float | str | bool | DateType] | None = None
23
+ remove_props: list[str] | None = None
24
+
25
+
26
+ class UpdateEntityParameters(BaseUpdateParameters):
27
+ """Parameters for UpdateEntity command.
28
+
29
+ [optional] with_class: name of entity class.
30
+ """
31
+
32
+ with_class: str | None = None
33
+
34
+
35
+ class UpdateBoundingBoxParameters(BaseUpdateParameters):
36
+ """Parameters for UpdateBoundingBox command.
37
+
38
+ [optional] rectangle
39
+ [optional] label
40
+ """
41
+
42
+ rectangle: RectangleType | None = None
43
+ label: str | None = None
44
+
45
+
46
+ class UpdatePolygonParameters(BaseUpdateParameters):
47
+ """Parameters for UpdatePolygon command.
48
+
49
+ [optional] polygons
50
+ [optional] label
51
+ """
52
+
53
+ polygons: list[list[list[int | float]]] | None = None
54
+ label: str | None = None
55
+
56
+
57
+ class UpdateDescriptorSetParameters(BaseUpdateParameters):
58
+ """Parameters for UpdateDescriptorSet command.
59
+
60
+ [optional] with_name: name of the set.
61
+ """
62
+
63
+ with_name: str | None = None
64
+
65
+
66
+ class UpdateDescriptorParameters(BaseUpdateParameters):
67
+ """Parameters for UpdateDescriptor command.
68
+
69
+ [optional] with_name: name of the set.
70
+ """
71
+
72
+ label: str | None = None
@@ -0,0 +1,7 @@
1
+ # -*- coding: utf-8 -*-
2
+ from enum import Enum
3
+
4
+
5
+ class Tags(Enum):
6
+ DATABASE = "database"
7
+ JSON = "json"
@@ -0,0 +1,22 @@
1
+ # -*- coding: utf-8 -*-
2
+ import importlib
3
+ from typing import Callable, cast
4
+
5
+ _root_lib_path = "sinapsis_aperturedb.templates"
6
+
7
+ _template_lookup: dict = {
8
+ "ApertureDBGetStatus": f"{_root_lib_path}.aperturedb_client_base",
9
+ "ApertureDBFindEntities": f"{_root_lib_path}.aperturedb_find_in_table",
10
+ "ApertureDBAddEntitiesFromCSV": f"{_root_lib_path}.aperturedb_add_to_table",
11
+ "ApertureDBGetSchema": f"{_root_lib_path}.aperturedb_database_info",
12
+ }
13
+
14
+
15
+ def __getattr__(name: str) -> Callable:
16
+ if name in _template_lookup:
17
+ module = importlib.import_module(_template_lookup[name])
18
+ return cast(Callable, getattr(module, name))
19
+ raise AttributeError(f"template `{name}` not found in {_root_lib_path}")
20
+
21
+
22
+ __all__ = list(_template_lookup.keys())
@@ -0,0 +1,72 @@
1
+ # -*- coding: utf-8 -*-
2
+ import pandas as pd
3
+ from pydantic.dataclasses import dataclass
4
+ from sinapsis_core.data_containers.data_packet import DataContainer
5
+
6
+ from sinapsis_aperturedb.helpers.query_base_models.add import (
7
+ AddEntityParameters,
8
+ )
9
+ from sinapsis_aperturedb.helpers.query_base_models.base import (
10
+ Query,
11
+ )
12
+ from sinapsis_aperturedb.templates.aperturedb_client_base import (
13
+ ApertureDBClientQuery,
14
+ ApertureDBClientQueryAttributes,
15
+ )
16
+
17
+
18
+ @dataclass
19
+ class ApertureDBAddEntitiesFromCSVKeys:
20
+ records: str = "records"
21
+ class_: str = "class"
22
+ properties: str = "properties"
23
+
24
+
25
+ class ApertureDBAddEntitiesFromCSV(ApertureDBClientQuery):
26
+ """Template to add Entities from a CSV file.
27
+
28
+ This template receives a CSV as a pandas dataframe within the DataContainer, then
29
+ creates queries to add Entities from the CSV with one of the columns' names to be used as
30
+ the Entity class name.
31
+ """
32
+
33
+ COMMAND = "AddEntity"
34
+
35
+ class ApertureDBAddEntitiesFromCSVAttributes(ApertureDBClientQueryAttributes):
36
+ """Attributes for ApertureDBAddEntity template.
37
+
38
+ class_column: name of the column which will be used as class name. Case sensitive
39
+ """
40
+
41
+ class_column: str
42
+ generic_key: str
43
+
44
+ AttributesBaseModel = ApertureDBAddEntitiesFromCSVAttributes
45
+
46
+ def execute(self, container: DataContainer) -> DataContainer:
47
+ """Gets CSV data from the pandas dataframe and creates an AddEntity query for each row.
48
+
49
+ Args:
50
+ container (DataContainer): The container holding the input data packets.
51
+
52
+ Returns:
53
+ DataContainer: The updated container with responses
54
+ """
55
+ csv_dataframe: pd.DataFrame = self._get_generic_data(container)
56
+
57
+ if not isinstance(csv_dataframe, pd.DataFrame):
58
+ self.logger.warning("Received CSV data must be a pandas dataframe object. Returning input datacontainer.")
59
+ return container
60
+
61
+ queries = []
62
+ for record in csv_dataframe.to_dict(ApertureDBAddEntitiesFromCSVKeys.records):
63
+ entity = {}
64
+ class_value = record.pop(self.attributes.class_column)
65
+ entity[ApertureDBAddEntitiesFromCSVKeys.class_] = class_value
66
+ entity[ApertureDBAddEntitiesFromCSVKeys.properties] = record
67
+ parameters = AddEntityParameters(**entity)
68
+ query_base_model = Query(command=self.COMMAND, parameters=parameters)
69
+ queries.append(query_base_model.prepare_query()[0])
70
+
71
+ self.process_query_list(queries, container)
72
+ return container