logs-py 4.0.7__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.
- LOGS/Auxiliary/CheckClassName.py +1075 -0
- LOGS/Auxiliary/Constants.py +99 -0
- LOGS/Auxiliary/CustomEntityClassGenerator.py +254 -0
- LOGS/Auxiliary/CustomFieldClassGenerator.py +115 -0
- LOGS/Auxiliary/CustomFieldValueTypeChecker.py +168 -0
- LOGS/Auxiliary/CustomSectionClassGenerator.py +113 -0
- LOGS/Auxiliary/CustomTypeClassGenerator.py +147 -0
- LOGS/Auxiliary/DateTimeConverter.py +66 -0
- LOGS/Auxiliary/Decorators.py +109 -0
- LOGS/Auxiliary/Exceptions.py +341 -0
- LOGS/Auxiliary/LOGSErrorResponse.py +89 -0
- LOGS/Auxiliary/MinimalModelGenerator.py +236 -0
- LOGS/Auxiliary/ParameterHelper.py +56 -0
- LOGS/Auxiliary/ReplaceMessage.py +13 -0
- LOGS/Auxiliary/Tools.py +432 -0
- LOGS/Auxiliary/__init__.py +15 -0
- LOGS/Converter/Conversion.py +248 -0
- LOGS/Converter/Converter.py +96 -0
- LOGS/Converter/ConverterParameter.py +88 -0
- LOGS/Converter/DateTimeRange.py +58 -0
- LOGS/Converter/ExportParameters.py +89 -0
- LOGS/Converter/__init__.py +13 -0
- LOGS/Entities/Attachment.py +84 -0
- LOGS/Entities/AttachmentMinimal.py +8 -0
- LOGS/Entities/AttachmentRequestParameter.py +42 -0
- LOGS/Entities/Attachments.py +53 -0
- LOGS/Entities/AutoloadFileInfo.py +12 -0
- LOGS/Entities/AutoloadStatusError.py +7 -0
- LOGS/Entities/AxisNaming.py +33 -0
- LOGS/Entities/AxisZoom.py +33 -0
- LOGS/Entities/Bridge.py +165 -0
- LOGS/Entities/BridgeClientInfo.py +93 -0
- LOGS/Entities/BridgeMinimal.py +8 -0
- LOGS/Entities/BridgeRequestParameter.py +49 -0
- LOGS/Entities/BridgeType.py +7 -0
- LOGS/Entities/Bridges.py +12 -0
- LOGS/Entities/CustomField.py +243 -0
- LOGS/Entities/CustomFieldMinimal.py +8 -0
- LOGS/Entities/CustomFieldModels.py +111 -0
- LOGS/Entities/CustomFieldRequestParameter.py +69 -0
- LOGS/Entities/CustomFieldSearchQuery.py +40 -0
- LOGS/Entities/CustomFields.py +12 -0
- LOGS/Entities/CustomType.py +212 -0
- LOGS/Entities/CustomTypeMinimal.py +8 -0
- LOGS/Entities/CustomTypeRequestParameter.py +60 -0
- LOGS/Entities/CustomTypeSection.py +63 -0
- LOGS/Entities/CustomTypes.py +12 -0
- LOGS/Entities/DataFormat.py +97 -0
- LOGS/Entities/DataFormatInstrument.py +18 -0
- LOGS/Entities/DataFormatInstrumentMinimal.py +8 -0
- LOGS/Entities/DataFormatInstrumentRequestParameter.py +17 -0
- LOGS/Entities/DataFormatInstruments.py +16 -0
- LOGS/Entities/DataFormatMinimal.py +18 -0
- LOGS/Entities/DataFormatRequestParameter.py +21 -0
- LOGS/Entities/DataFormats.py +12 -0
- LOGS/Entities/DataSource.py +218 -0
- LOGS/Entities/DataSourceConnectionStatus.py +12 -0
- LOGS/Entities/DataSourceMinimal.py +8 -0
- LOGS/Entities/DataSourceRequestParameter.py +57 -0
- LOGS/Entities/DataSourceStatus.py +108 -0
- LOGS/Entities/DataSourceStatusIterator.py +16 -0
- LOGS/Entities/DataSourceStatusRequestParameter.py +31 -0
- LOGS/Entities/DataSources.py +12 -0
- LOGS/Entities/Dataset.py +439 -0
- LOGS/Entities/DatasetBase.py +196 -0
- LOGS/Entities/DatasetCreator.py +148 -0
- LOGS/Entities/DatasetInfo.py +147 -0
- LOGS/Entities/DatasetMatchTypes.py +157 -0
- LOGS/Entities/DatasetMatching.py +196 -0
- LOGS/Entities/DatasetMinimal.py +8 -0
- LOGS/Entities/DatasetModels.py +33 -0
- LOGS/Entities/DatasetRequestParameter.py +92 -0
- LOGS/Entities/DatasetTemplate.py +23 -0
- LOGS/Entities/DatasetUploadParameter.py +14 -0
- LOGS/Entities/Datasets.py +142 -0
- LOGS/Entities/Datatrack.py +179 -0
- LOGS/Entities/DatatrackFormattedTable.py +25 -0
- LOGS/Entities/DatatrackGeneric.py +34 -0
- LOGS/Entities/DatatrackImage.py +25 -0
- LOGS/Entities/DatatrackNumericArray.py +30 -0
- LOGS/Entities/DatatrackNumericMatrix.py +98 -0
- LOGS/Entities/Entities.py +71 -0
- LOGS/Entities/EntitiesRequestParameter.py +18 -0
- LOGS/Entities/EntityOriginWriteModelWithId.py +15 -0
- LOGS/Entities/FileEntry.py +138 -0
- LOGS/Entities/FileExcludePattern.py +8 -0
- LOGS/Entities/FormatMetaData.py +56 -0
- LOGS/Entities/FormattedTable/DatatypeFormattedTable.py +135 -0
- LOGS/Entities/FormattedTable/DatatypeFormattedTableCell.py +108 -0
- LOGS/Entities/FormattedTable/DatatypeFormattedTableSettings.py +11 -0
- LOGS/Entities/FormattedTable/__init__.py +9 -0
- LOGS/Entities/HierarchyLeaf.py +15 -0
- LOGS/Entities/HierarchyNode.py +40 -0
- LOGS/Entities/ILiteraryTypedEntity.py +19 -0
- LOGS/Entities/InventoryItem.py +102 -0
- LOGS/Entities/InventoryItemMinimal.py +25 -0
- LOGS/Entities/InventoryItemRequestParameter.py +58 -0
- LOGS/Entities/InventoryItems.py +12 -0
- LOGS/Entities/LabNotebook.py +33 -0
- LOGS/Entities/LabNotebookEntries.py +16 -0
- LOGS/Entities/LabNotebookEntry.py +106 -0
- LOGS/Entities/LabNotebookEntryContent/BasicAttribute.py +15 -0
- LOGS/Entities/LabNotebookEntryContent/EntityAttribute.py +85 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentBlockquote.py +13 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentBulletList.py +17 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentCallout.py +40 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentContentPlaceholderNode.py +31 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentConverter.py +207 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentDocument.py +8 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentEntity.py +13 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentEntityMention.py +31 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentHeading.py +33 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentHorizontalRule.py +12 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentItem.py +37 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentListItem.py +49 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentOrderedList.py +31 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentParagraph.py +13 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentTable.py +17 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentTableCell.py +40 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentTableRow.py +8 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentTaskList.py +17 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentTaskListItem.py +31 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentText.py +33 -0
- LOGS/Entities/LabNotebookEntryContent/IEntryContentWithAttribute.py +23 -0
- LOGS/Entities/LabNotebookEntryContent/IEntryContentWithContent.py +38 -0
- LOGS/Entities/LabNotebookEntryContent/IEntryContentWithTextAttribute.py +16 -0
- LOGS/Entities/LabNotebookEntryContent/TextAttribute.py +46 -0
- LOGS/Entities/LabNotebookEntryContent/TextMarkAtributes.py +64 -0
- LOGS/Entities/LabNotebookEntryContent/TextMarkConverter.py +45 -0
- LOGS/Entities/LabNotebookEntryContent/TextMarks.py +71 -0
- LOGS/Entities/LabNotebookEntryContent/__init__.py +34 -0
- LOGS/Entities/LabNotebookEntryMinimal.py +8 -0
- LOGS/Entities/LabNotebookEntryRequestParameter.py +59 -0
- LOGS/Entities/LabNotebookExperiment.py +58 -0
- LOGS/Entities/LabNotebookExperimentMinimal.py +8 -0
- LOGS/Entities/LabNotebookExperimentRequestParameter.py +52 -0
- LOGS/Entities/LabNotebookExperiments.py +16 -0
- LOGS/Entities/LabNotebookMinimal.py +8 -0
- LOGS/Entities/LabNotebookModels.py +14 -0
- LOGS/Entities/LabNotebookRequestParameter.py +42 -0
- LOGS/Entities/LabNotebookTemplate.py +42 -0
- LOGS/Entities/LabNotebookTemplateMinimal.py +8 -0
- LOGS/Entities/LabNotebookTemplateRequestParameter.py +38 -0
- LOGS/Entities/LabNotebookTemplates.py +16 -0
- LOGS/Entities/LabNotebooks.py +12 -0
- LOGS/Entities/Method.py +66 -0
- LOGS/Entities/MethodMinimal.py +8 -0
- LOGS/Entities/MethodRequestParameter.py +16 -0
- LOGS/Entities/Methods.py +12 -0
- LOGS/Entities/Origin.py +53 -0
- LOGS/Entities/OriginMinimal.py +8 -0
- LOGS/Entities/OriginRequestParameter.py +28 -0
- LOGS/Entities/Origins.py +12 -0
- LOGS/Entities/ParserLog.py +49 -0
- LOGS/Entities/Permission.py +9 -0
- LOGS/Entities/Person.py +145 -0
- LOGS/Entities/PersonCategory.py +12 -0
- LOGS/Entities/PersonMinimal.py +8 -0
- LOGS/Entities/PersonRequestParameter.py +58 -0
- LOGS/Entities/Persons.py +12 -0
- LOGS/Entities/Project.py +52 -0
- LOGS/Entities/ProjectMinimal.py +8 -0
- LOGS/Entities/ProjectPersonPermission.py +102 -0
- LOGS/Entities/ProjectRequestParameter.py +58 -0
- LOGS/Entities/Projects.py +12 -0
- LOGS/Entities/Role.py +94 -0
- LOGS/Entities/RoleMinimal.py +8 -0
- LOGS/Entities/RoleRequestParameter.py +40 -0
- LOGS/Entities/Roles.py +12 -0
- LOGS/Entities/RunState.py +9 -0
- LOGS/Entities/Sample.py +53 -0
- LOGS/Entities/SampleMinimal.py +8 -0
- LOGS/Entities/SampleRequestParameter.py +54 -0
- LOGS/Entities/Samples.py +12 -0
- LOGS/Entities/SharedContent.py +87 -0
- LOGS/Entities/SharedContentMinimal.py +8 -0
- LOGS/Entities/SharedContentRequestParameter.py +38 -0
- LOGS/Entities/SharedContents.py +12 -0
- LOGS/Entities/Signature.py +60 -0
- LOGS/Entities/Track.py +93 -0
- LOGS/Entities/TrackData.py +20 -0
- LOGS/Entities/TrackImage.py +21 -0
- LOGS/Entities/TrackImageData.py +20 -0
- LOGS/Entities/TrackMatrix.py +28 -0
- LOGS/Entities/TrackMatrixData.py +22 -0
- LOGS/Entities/TrackSettings.py +55 -0
- LOGS/Entities/TrackTable.py +21 -0
- LOGS/Entities/TrackTableData.py +22 -0
- LOGS/Entities/TrackXY.py +40 -0
- LOGS/Entities/TrackXYComplex.py +51 -0
- LOGS/Entities/TrackXYComplexData.py +50 -0
- LOGS/Entities/TrackXYData.py +31 -0
- LOGS/Entities/Vendor.py +40 -0
- LOGS/Entities/VendorMinimal.py +8 -0
- LOGS/Entities/VendorRequestParameter.py +17 -0
- LOGS/Entities/Vendors.py +12 -0
- LOGS/Entities/__init__.py +118 -0
- LOGS/Entity/ConnectedEntity.py +170 -0
- LOGS/Entity/Entity.py +203 -0
- LOGS/Entity/EntityConnector.py +70 -0
- LOGS/Entity/EntityIterator.py +263 -0
- LOGS/Entity/EntityMinimal.py +141 -0
- LOGS/Entity/EntityMinimalWithIntId.py +36 -0
- LOGS/Entity/EntityMinimalWithStrId.py +36 -0
- LOGS/Entity/EntityMinimalWithType.py +47 -0
- LOGS/Entity/EntityRequestParameter.py +104 -0
- LOGS/Entity/EntitySortBy.py +69 -0
- LOGS/Entity/EntityWithIntId.py +26 -0
- LOGS/Entity/EntityWithStrId.py +26 -0
- LOGS/Entity/IGenericEntityOrderBy.py +55 -0
- LOGS/Entity/IdIterator.py +207 -0
- LOGS/Entity/SerializableContent.py +834 -0
- LOGS/Entity/__init__.py +23 -0
- LOGS/Interfaces/ICustomFieldValue.py +92 -0
- LOGS/Interfaces/ICustomSectionValue.py +161 -0
- LOGS/Interfaces/ICustomTypeValue.py +152 -0
- LOGS/Interfaces/ICustomValue.py +28 -0
- LOGS/Interfaces/IEntityInterface.py +7 -0
- LOGS/Interfaces/IEntryRecord.py +57 -0
- LOGS/Interfaces/IHierarchicalEntity.py +41 -0
- LOGS/Interfaces/IHierarchyType.py +63 -0
- LOGS/Interfaces/ILockableEntity.py +52 -0
- LOGS/Interfaces/IModificationRecord.py +56 -0
- LOGS/Interfaces/INamedEntity.py +25 -0
- LOGS/Interfaces/IOwnedEntity.py +27 -0
- LOGS/Interfaces/IPaginationRequest.py +11 -0
- LOGS/Interfaces/IPermissionedEntity.py +72 -0
- LOGS/Interfaces/IProjectBased.py +27 -0
- LOGS/Interfaces/ISessionedEntity.py +59 -0
- LOGS/Interfaces/ISignableEntity.py +49 -0
- LOGS/Interfaces/ISoftDeletable.py +28 -0
- LOGS/Interfaces/ITypedEntity.py +129 -0
- LOGS/Interfaces/IUniqueEntity.py +61 -0
- LOGS/Interfaces/IVersionedEntity.py +39 -0
- LOGS/Interfaces/__init__.py +7 -0
- LOGS/LOGS.py +1436 -0
- LOGS/LOGSConnection.py +647 -0
- LOGS/LOGSOptions.py +11 -0
- LOGS/Parameters/Color.py +92 -0
- LOGS/Parameters/ParameterBase.py +55 -0
- LOGS/Parameters/ParameterConverter.py +24 -0
- LOGS/Parameters/ParameterElement.py +99 -0
- LOGS/Parameters/ParameterList.py +52 -0
- LOGS/Parameters/ParameterTable.py +64 -0
- LOGS/Parameters/__init__.py +13 -0
- LOGS/ServerMetaData.py +120 -0
- LOGS/__init__.py +12 -0
- logs_py-4.0.7.dist-info/METADATA +51 -0
- logs_py-4.0.7.dist-info/RECORD +251 -0
- logs_py-4.0.7.dist-info/WHEEL +5 -0
- logs_py-4.0.7.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import Optional, cast
|
|
3
|
+
|
|
4
|
+
from LOGS.Auxiliary.Exceptions import EntityIncompleteException
|
|
5
|
+
from LOGS.Entities.Datatrack import Datatrack
|
|
6
|
+
from LOGS.Entities.FormattedTable.DatatypeFormattedTable import DatatypeFormattedTable
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DatatrackFormattedTable(Datatrack):
|
|
10
|
+
_type = "formatted_table"
|
|
11
|
+
_data: Optional[DatatypeFormattedTable] = None
|
|
12
|
+
|
|
13
|
+
def _fetchData(self):
|
|
14
|
+
super()._fetchData()
|
|
15
|
+
|
|
16
|
+
if self._data is not None:
|
|
17
|
+
# s = cast(bytes, self._data).decode("utf-8")
|
|
18
|
+
b = cast(bytes, self._data).split(b"\x00")[0]
|
|
19
|
+
self._data = DatatypeFormattedTable(json.loads(b.decode("utf-8")))
|
|
20
|
+
|
|
21
|
+
@property
|
|
22
|
+
def data(self) -> Optional[DatatypeFormattedTable]:
|
|
23
|
+
if self._incomplete:
|
|
24
|
+
raise EntityIncompleteException(self)
|
|
25
|
+
return self._data
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from typing import Optional, cast
|
|
2
|
+
|
|
3
|
+
from LOGS.Auxiliary.Exceptions import EntityIncompleteException
|
|
4
|
+
from LOGS.Entities.Datatrack import Datatrack
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class DatatrackGeneric(Datatrack):
|
|
8
|
+
_type = "formatted_table"
|
|
9
|
+
_data: Optional[str] = None
|
|
10
|
+
|
|
11
|
+
def _fetchData(self):
|
|
12
|
+
super()._fetchData()
|
|
13
|
+
|
|
14
|
+
if self._data is not None:
|
|
15
|
+
s = cast(bytes, self._data)
|
|
16
|
+
try:
|
|
17
|
+
self._data = s.decode()
|
|
18
|
+
return
|
|
19
|
+
except:
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
self._data = s.decode("latin-1")
|
|
24
|
+
return
|
|
25
|
+
except:
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
self._data = None
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def data(self) -> Optional[str]:
|
|
32
|
+
if self._incomplete:
|
|
33
|
+
raise EntityIncompleteException(self)
|
|
34
|
+
return self._data
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from io import BytesIO
|
|
2
|
+
from typing import Optional, cast
|
|
3
|
+
|
|
4
|
+
import PIL.Image
|
|
5
|
+
from PIL.Image import Image
|
|
6
|
+
|
|
7
|
+
from LOGS.Auxiliary.Exceptions import EntityIncompleteException
|
|
8
|
+
from LOGS.Entities.Datatrack import Datatrack
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class DatatrackImage(Datatrack):
|
|
12
|
+
_type = "image"
|
|
13
|
+
_data: Optional[Image] = None
|
|
14
|
+
|
|
15
|
+
def _fetchData(self):
|
|
16
|
+
super()._fetchData()
|
|
17
|
+
|
|
18
|
+
if self._data:
|
|
19
|
+
self._data = PIL.Image.open(BytesIO(cast(bytes, self._data)))
|
|
20
|
+
|
|
21
|
+
@property
|
|
22
|
+
def data(self) -> Optional[Image]:
|
|
23
|
+
if self._incomplete:
|
|
24
|
+
raise EntityIncompleteException(self)
|
|
25
|
+
return self._data
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from typing import Optional, cast
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from LOGS.Auxiliary.Exceptions import EntityIncompleteException
|
|
6
|
+
from LOGS.Entities.Datatrack import Datatrack
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DatatrackNumericArray(Datatrack):
|
|
10
|
+
_type = "numeric_array"
|
|
11
|
+
_data: Optional[np.ndarray] = None
|
|
12
|
+
|
|
13
|
+
def __iter__(self):
|
|
14
|
+
if self._incomplete:
|
|
15
|
+
raise EntityIncompleteException(self)
|
|
16
|
+
if self._data is not None:
|
|
17
|
+
for x in self._data:
|
|
18
|
+
yield x
|
|
19
|
+
|
|
20
|
+
def _fetchData(self):
|
|
21
|
+
super()._fetchData()
|
|
22
|
+
|
|
23
|
+
if self._data:
|
|
24
|
+
self._data = np.frombuffer(cast(bytes, self._data), dtype=np.double)
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def data(self) -> Optional[np.ndarray]:
|
|
28
|
+
if self._incomplete:
|
|
29
|
+
raise EntityIncompleteException(self)
|
|
30
|
+
return self._data
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
from typing import Optional, Tuple, cast
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from LOGS.Auxiliary.Exceptions import EntityIncompleteException
|
|
6
|
+
from LOGS.Entities.Datatrack import Datatrack
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DatatrackNumericMatrix(Datatrack):
|
|
10
|
+
_type = "numeric_matrix"
|
|
11
|
+
_data: Optional[np.ndarray] = None
|
|
12
|
+
|
|
13
|
+
def __iter__(self):
|
|
14
|
+
if self._incomplete:
|
|
15
|
+
raise EntityIncompleteException(self)
|
|
16
|
+
|
|
17
|
+
if self.size is None:
|
|
18
|
+
raise ValueError("Datatrack has no size defined.")
|
|
19
|
+
|
|
20
|
+
if self._data is not None:
|
|
21
|
+
for x in range(self.size[0]):
|
|
22
|
+
for y in range(self.size[1]):
|
|
23
|
+
yield x, y
|
|
24
|
+
|
|
25
|
+
def _fetchData(self):
|
|
26
|
+
super()._fetchData()
|
|
27
|
+
|
|
28
|
+
if self._data and self.size and len(self.size) > 1:
|
|
29
|
+
self._data = np.frombuffer(cast(bytes, self._data), dtype=np.double)
|
|
30
|
+
self._data = self._data.reshape((self.size[1], self.size[0]))
|
|
31
|
+
self._data = self._data.T
|
|
32
|
+
|
|
33
|
+
def getCoordinate(self, index: Tuple[int, int]):
|
|
34
|
+
if self._incomplete:
|
|
35
|
+
raise EntityIncompleteException(self)
|
|
36
|
+
if self.min is None or self.max is None or self.size is None:
|
|
37
|
+
return None
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
self.min[0] + index[0] * (self.max[0] - self.min[0]) / self.size[0],
|
|
41
|
+
self.min[1] + index[1] * (self.max[1] - self.min[1]) / self.size[1],
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
def getIndex(
|
|
45
|
+
self, coord: Tuple[float, float], keepInBounds: bool = False
|
|
46
|
+
) -> Tuple[int, int]:
|
|
47
|
+
if self._incomplete:
|
|
48
|
+
raise EntityIncompleteException(self)
|
|
49
|
+
if self.min is None or self.max is None or self.size is None:
|
|
50
|
+
raise ValueError("Datatrack has no min, max or size defined.")
|
|
51
|
+
|
|
52
|
+
index = (
|
|
53
|
+
int((coord[0] - self.min[0]) * self.size[0] / (self.max[0] - self.min[0])),
|
|
54
|
+
int((coord[1] - self.min[1]) * self.size[1] / (self.max[1] - self.min[1])),
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
if keepInBounds:
|
|
58
|
+
index = (
|
|
59
|
+
max(0, min(index[0], self.size[0] - 1)),
|
|
60
|
+
max(0, min(index[1], self.size[1] - 1)),
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
return index
|
|
64
|
+
|
|
65
|
+
def getValueFromCoordinate(
|
|
66
|
+
self, coord: Tuple[float, float], keepInBounds: bool = True
|
|
67
|
+
):
|
|
68
|
+
if self._incomplete:
|
|
69
|
+
raise EntityIncompleteException(self)
|
|
70
|
+
if self._data is None:
|
|
71
|
+
return None
|
|
72
|
+
|
|
73
|
+
return self.getValueFromIndex(self.getIndex(coord, keepInBounds=keepInBounds))
|
|
74
|
+
|
|
75
|
+
def getValueFromIndex(self, index: Tuple[int, int]):
|
|
76
|
+
if self._incomplete:
|
|
77
|
+
raise EntityIncompleteException(self)
|
|
78
|
+
if self._data is None:
|
|
79
|
+
return None
|
|
80
|
+
|
|
81
|
+
if self.size is None:
|
|
82
|
+
raise ValueError("Datatrack has no size defined.")
|
|
83
|
+
|
|
84
|
+
if (
|
|
85
|
+
index[0] < 0
|
|
86
|
+
or index[0] >= self.size[0]
|
|
87
|
+
or index[1] < 0
|
|
88
|
+
or index[1] >= self.size[1]
|
|
89
|
+
):
|
|
90
|
+
raise ValueError("Index out of bounds.")
|
|
91
|
+
|
|
92
|
+
return self._data[index]
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def data(self) -> Optional[np.ndarray]:
|
|
96
|
+
if self._incomplete:
|
|
97
|
+
raise EntityIncompleteException(self)
|
|
98
|
+
return self._data
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from typing import Any, Optional, cast
|
|
2
|
+
|
|
3
|
+
from LOGS.Auxiliary.Decorators import Endpoint
|
|
4
|
+
from LOGS.Auxiliary.Exceptions import LOGSException
|
|
5
|
+
from LOGS.Auxiliary.MinimalModelGenerator import MinimalModelGenerator
|
|
6
|
+
from LOGS.Auxiliary.Tools import Tools
|
|
7
|
+
from LOGS.Entities.EntitiesRequestParameter import EntitiesRequestParameter
|
|
8
|
+
from LOGS.Entity.Entity import Entity
|
|
9
|
+
from LOGS.Entity.EntityIterator import EntityIterator
|
|
10
|
+
from LOGS.Entity.EntityMinimalWithType import EntityMinimalWithType
|
|
11
|
+
from LOGS.Entity.EntityRequestParameter import EntityRequestParameter
|
|
12
|
+
from LOGS.LOGSConnection import LOGSConnection
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@Endpoint("entities")
|
|
16
|
+
class Entities(EntityIterator[Entity, EntityRequestParameter]):
|
|
17
|
+
"""LOGS connected multi Entity iterator"""
|
|
18
|
+
|
|
19
|
+
_generatorType = EntityMinimalWithType # type: ignore
|
|
20
|
+
_parameterType = EntitiesRequestParameter # type: ignore
|
|
21
|
+
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
connection: Optional[LOGSConnection],
|
|
25
|
+
parameters: Optional[EntitiesRequestParameter] = None,
|
|
26
|
+
):
|
|
27
|
+
super().__init__(connection=connection, parameters=cast(Any, parameters))
|
|
28
|
+
|
|
29
|
+
def _convertToEntity(self, entity: EntityMinimalWithType):
|
|
30
|
+
return MinimalModelGenerator.MinimalFromSingle(
|
|
31
|
+
entity.toDict(), entity.type, None, connection=self._getConnection()
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
def __next__(self) -> EntityMinimalWithType:
|
|
35
|
+
entity = cast(EntityMinimalWithType, super().__next__())
|
|
36
|
+
result = self._convertToEntity(entity)
|
|
37
|
+
if not result:
|
|
38
|
+
raise LOGSException(
|
|
39
|
+
"Unknown entity %a of type %a." % (str(entity), entity.type)
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
return result
|
|
43
|
+
|
|
44
|
+
def fetch(self, uid: str):
|
|
45
|
+
self._entityIterator = 0
|
|
46
|
+
|
|
47
|
+
if not self._connection:
|
|
48
|
+
raise LOGSException(
|
|
49
|
+
"Entity connector %a is not connected" % type(self).__name__
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
if not self._endpoint:
|
|
53
|
+
raise NotImplementedError(
|
|
54
|
+
"Endpoint missing for of entity type %a."
|
|
55
|
+
% (
|
|
56
|
+
type(self).__name__
|
|
57
|
+
if type(self).__name__ != Entity.__name__
|
|
58
|
+
else "unknown"
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
ref, responseError = self._connection.getEndpoint(self._endpoint + [str(uid)])
|
|
63
|
+
if responseError:
|
|
64
|
+
raise LOGSException(
|
|
65
|
+
message="Could not fetch entity with uid %a: %s"
|
|
66
|
+
% (uid, responseError.errorString()),
|
|
67
|
+
responseError=responseError,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
entity = Tools.checkAndConvert(ref, EntityMinimalWithType)
|
|
71
|
+
return self._convertToEntity(entity)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from typing import List, Optional, Sequence, Type, Union
|
|
3
|
+
from uuid import UUID
|
|
4
|
+
|
|
5
|
+
from LOGS.Entity.EntityRequestParameter import (
|
|
6
|
+
DefaultSortingOptions,
|
|
7
|
+
EntityRequestParameter,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class EntitiesRequestParameter(EntityRequestParameter[DefaultSortingOptions]):
|
|
13
|
+
_orderByType: Type[DefaultSortingOptions] = field(
|
|
14
|
+
default=DefaultSortingOptions, init=False
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
uids: Optional[Sequence[Union[str, UUID]]] = None
|
|
18
|
+
names: Optional[List[str]] = None
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from typing import List, Optional
|
|
3
|
+
from uuid import UUID
|
|
4
|
+
|
|
5
|
+
from LOGS.Auxiliary.Constants import Constants
|
|
6
|
+
from LOGS.Entities.OriginMinimal import OriginMinimal
|
|
7
|
+
from LOGS.Entity.SerializableContent import SerializableClass
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class EntityOriginWriteModelWithId(SerializableClass):
|
|
12
|
+
_noSerialize: List[str] = field(default_factory=lambda: ["asString"])
|
|
13
|
+
id: Optional[Constants.ID_TYPE] = None
|
|
14
|
+
uid: Optional[UUID] = None
|
|
15
|
+
origin: Optional[OriginMinimal] = None
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import os
|
|
3
|
+
import uuid
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from hashlib import sha256
|
|
6
|
+
from typing import Any, List, Literal, Optional, Sequence, Union, cast
|
|
7
|
+
|
|
8
|
+
from LOGS.Auxiliary.Constants import Constants
|
|
9
|
+
from LOGS.Entity.SerializableContent import SerializableClass
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class FingerprintFragment(SerializableClass):
|
|
13
|
+
offset: int = 0
|
|
14
|
+
length: int = 0
|
|
15
|
+
bytes: str = ""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class FileFragment(SerializableClass):
|
|
19
|
+
_typeMapper = {"fragments": FingerprintFragment}
|
|
20
|
+
id: str = ""
|
|
21
|
+
fragments: List[FingerprintFragment] = []
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
FormatFileState = Literal["NEW", "UNCHANGED", "NEEDSUPDATE", "DELETE"]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class FileEntry(SerializableClass):
|
|
28
|
+
_typeMapper = {"fragments": FingerprintFragment}
|
|
29
|
+
_noSerialize = ["isDir", "name"]
|
|
30
|
+
id: Optional[str] = None
|
|
31
|
+
# The naming here is confusing. FullPath is part of the LOGS API but it refers
|
|
32
|
+
# to the full path in LOGS and not the actual file path.
|
|
33
|
+
fullPath: str = ""
|
|
34
|
+
path: str = ""
|
|
35
|
+
isDir: bool = False
|
|
36
|
+
name: str = ""
|
|
37
|
+
fragments: Optional[List[FingerprintFragment]] = None
|
|
38
|
+
hash: Optional[str] = None
|
|
39
|
+
state: Optional[FormatFileState] = None
|
|
40
|
+
mtime: Optional[datetime] = None
|
|
41
|
+
|
|
42
|
+
def __init__(
|
|
43
|
+
self,
|
|
44
|
+
ref: Any = None,
|
|
45
|
+
fullPath: Optional[str] = None,
|
|
46
|
+
state: Optional[FormatFileState] = None,
|
|
47
|
+
):
|
|
48
|
+
if isinstance(ref, FileEntry):
|
|
49
|
+
super().__init__(self._fieldsFromPath(ref.path))
|
|
50
|
+
self.fullPath = ref.fullPath
|
|
51
|
+
self.state = ref.state
|
|
52
|
+
elif isinstance(ref, os.DirEntry) and ref.path:
|
|
53
|
+
super().__init__(self._fieldsFromPath(ref.path))
|
|
54
|
+
elif isinstance(ref, str) or fullPath is not None:
|
|
55
|
+
super().__init__(
|
|
56
|
+
self._fieldsFromPath(str(ref if fullPath is None else fullPath))
|
|
57
|
+
)
|
|
58
|
+
else:
|
|
59
|
+
super().__init__(ref)
|
|
60
|
+
|
|
61
|
+
if fullPath is not None:
|
|
62
|
+
self.fullPath = fullPath
|
|
63
|
+
if state is not None:
|
|
64
|
+
self.state = state
|
|
65
|
+
|
|
66
|
+
@classmethod
|
|
67
|
+
def _fieldsFromPath(cls, path: str):
|
|
68
|
+
_path = os.path.realpath(path)
|
|
69
|
+
return {
|
|
70
|
+
"id": uuid.uuid4().hex,
|
|
71
|
+
"fullPath": _path,
|
|
72
|
+
"path": _path,
|
|
73
|
+
"isDir": os.path.isdir(_path),
|
|
74
|
+
"name": os.path.basename(_path),
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
def __str__(self):
|
|
78
|
+
return "<%s %s%a>" % (
|
|
79
|
+
type(self).__name__,
|
|
80
|
+
("<dir> " if self.isDir else ""),
|
|
81
|
+
self.path,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
def addFragment(self, fragments: List[FingerprintFragment]):
|
|
85
|
+
with open(self.path, "rb") as read:
|
|
86
|
+
if self.fragments is None:
|
|
87
|
+
self.fragments = []
|
|
88
|
+
for fragment in fragments:
|
|
89
|
+
read.seek(fragment.offset)
|
|
90
|
+
fragment.bytes = base64.b64encode(read.read(fragment.length)).decode(
|
|
91
|
+
"utf-8"
|
|
92
|
+
)
|
|
93
|
+
self.fragments.append(fragment)
|
|
94
|
+
|
|
95
|
+
def addHash(self):
|
|
96
|
+
with open(self.path, "rb") as read:
|
|
97
|
+
self.hash = sha256(read.read()).hexdigest()
|
|
98
|
+
|
|
99
|
+
def addMtime(self):
|
|
100
|
+
self.mtime = datetime.fromtimestamp(os.path.getmtime(self.path))
|
|
101
|
+
|
|
102
|
+
@classmethod
|
|
103
|
+
def entriesFromFiles(
|
|
104
|
+
cls,
|
|
105
|
+
files: Union[Constants.FILE_TYPE, Sequence[Constants.FILE_TYPE]],
|
|
106
|
+
ignoreReadErrors=False,
|
|
107
|
+
):
|
|
108
|
+
if files == None:
|
|
109
|
+
raise FileNotFoundError("Could not read file or directory from 'None' path")
|
|
110
|
+
if not isinstance(files, list):
|
|
111
|
+
files = [cast(Constants.FILE_TYPE, files)]
|
|
112
|
+
|
|
113
|
+
result: List[FileEntry] = []
|
|
114
|
+
|
|
115
|
+
while len(files) > 0:
|
|
116
|
+
file = files.pop(0)
|
|
117
|
+
if isinstance(file, (str, os.DirEntry, FileEntry)):
|
|
118
|
+
f = FileEntry(file)
|
|
119
|
+
if f.isDir:
|
|
120
|
+
with os.scandir(f.path) as entries:
|
|
121
|
+
files.extend(entries)
|
|
122
|
+
else:
|
|
123
|
+
if not os.path.isfile(f.path) or not os.access(f.path, os.R_OK):
|
|
124
|
+
if not ignoreReadErrors:
|
|
125
|
+
raise PermissionError("Could not read file %a" % f.path)
|
|
126
|
+
else:
|
|
127
|
+
f.id = uuid.uuid4().hex
|
|
128
|
+
result.append(f)
|
|
129
|
+
|
|
130
|
+
return result
|
|
131
|
+
|
|
132
|
+
def modifyPathPrefix(
|
|
133
|
+
self, prefixToStrip: Optional[str] = None, prefixToAdd: Optional[str] = None
|
|
134
|
+
):
|
|
135
|
+
if prefixToStrip and self.fullPath.startswith(prefixToStrip):
|
|
136
|
+
self.fullPath = self.fullPath[len(prefixToStrip) :]
|
|
137
|
+
if prefixToAdd and not self.fullPath.startswith(prefixToAdd):
|
|
138
|
+
self.fullPath = os.path.join(prefixToAdd, self.fullPath)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, List, Optional
|
|
2
|
+
|
|
3
|
+
from LOGS.Auxiliary.MinimalModelGenerator import MinimalModelGenerator
|
|
4
|
+
from LOGS.Entity.ConnectedEntity import ConnectedEntity
|
|
5
|
+
from LOGS.LOGSConnection import LOGSConnection
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from LOGS.Entities.DataFormatInstrumentMinimal import DataFormatInstrumentMinimal
|
|
9
|
+
from LOGS.Entities.MethodMinimal import MethodMinimal
|
|
10
|
+
from LOGS.Entities.VendorMinimal import VendorMinimal
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class FormatMetaData(ConnectedEntity):
|
|
14
|
+
_vendor: List["VendorMinimal"]
|
|
15
|
+
_method: List["MethodMinimal"]
|
|
16
|
+
_instrument: List["DataFormatInstrumentMinimal"]
|
|
17
|
+
|
|
18
|
+
def __init__(self, ref=None, connection: Optional[LOGSConnection] = None):
|
|
19
|
+
self._vendor = []
|
|
20
|
+
self._method = []
|
|
21
|
+
self._format = []
|
|
22
|
+
self._instrument = []
|
|
23
|
+
super().__init__(ref=ref, connection=connection)
|
|
24
|
+
|
|
25
|
+
@property
|
|
26
|
+
def vendor(self) -> List["VendorMinimal"]:
|
|
27
|
+
return self._vendor
|
|
28
|
+
|
|
29
|
+
@vendor.setter
|
|
30
|
+
def vendor(self, value):
|
|
31
|
+
self._vendor = MinimalModelGenerator.MinimalFromList(
|
|
32
|
+
value, "VendorMinimal", "vendor", connection=self._getConnection()
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def method(self) -> List["MethodMinimal"]:
|
|
37
|
+
return self._method
|
|
38
|
+
|
|
39
|
+
@method.setter
|
|
40
|
+
def method(self, value):
|
|
41
|
+
self._method = MinimalModelGenerator.MinimalFromList(
|
|
42
|
+
value, "MethodMinimal", "method", connection=self._getConnection()
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def instrument(self) -> List["DataFormatInstrumentMinimal"]:
|
|
47
|
+
return self._instrument
|
|
48
|
+
|
|
49
|
+
@instrument.setter
|
|
50
|
+
def instrument(self, value):
|
|
51
|
+
self._instrument = MinimalModelGenerator.MinimalFromList(
|
|
52
|
+
value,
|
|
53
|
+
"DataFormatInstrumentMinimal",
|
|
54
|
+
"instrument",
|
|
55
|
+
connection=self._getConnection(),
|
|
56
|
+
)
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from typing import Dict, List, Literal, Optional, Union
|
|
3
|
+
|
|
4
|
+
from LOGS.Entities.FormattedTable.DatatypeFormattedTableCell import (
|
|
5
|
+
DatatypeFormattedTableCell,
|
|
6
|
+
)
|
|
7
|
+
from LOGS.Entity.SerializableContent import SerializableContent
|
|
8
|
+
|
|
9
|
+
_VTypeType = Literal["int", "float", "str", "bool"]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class DatatypeFormattedTable(SerializableContent):
|
|
13
|
+
_type: str = "formatted_table"
|
|
14
|
+
_name: Optional[str] = None
|
|
15
|
+
_id = ""
|
|
16
|
+
|
|
17
|
+
_cells: List[DatatypeFormattedTableCell] = []
|
|
18
|
+
|
|
19
|
+
_rowRange: List[int] = [sys.maxsize, -1]
|
|
20
|
+
_columnRange: List[int] = [sys.maxsize, -1]
|
|
21
|
+
|
|
22
|
+
_cellIds: Dict[str, int] = {}
|
|
23
|
+
|
|
24
|
+
_fixedRow: Optional[int] = None
|
|
25
|
+
_fixedColumn: Optional[int] = None
|
|
26
|
+
|
|
27
|
+
def appendCell(
|
|
28
|
+
self,
|
|
29
|
+
cell: Union[_VTypeType, DatatypeFormattedTableCell],
|
|
30
|
+
row: int = -1,
|
|
31
|
+
column: int = -1,
|
|
32
|
+
) -> DatatypeFormattedTableCell:
|
|
33
|
+
c = self.checkAndConvert(
|
|
34
|
+
cell, fieldName="cell", fieldType=DatatypeFormattedTableCell
|
|
35
|
+
)
|
|
36
|
+
if row >= 0:
|
|
37
|
+
c.row = row
|
|
38
|
+
if column >= 0:
|
|
39
|
+
c.column = column
|
|
40
|
+
|
|
41
|
+
id = c.id
|
|
42
|
+
index = self.getCell(id)
|
|
43
|
+
if index >= 0:
|
|
44
|
+
self.cells[index] = c
|
|
45
|
+
else:
|
|
46
|
+
self._cellIds[id] = len(self.cells)
|
|
47
|
+
self.cells.append(c)
|
|
48
|
+
|
|
49
|
+
# self.reorganizeCells()
|
|
50
|
+
|
|
51
|
+
return c
|
|
52
|
+
|
|
53
|
+
def getCell(self, id: str) -> int:
|
|
54
|
+
if id in self._cellIds:
|
|
55
|
+
return self._cellIds[id]
|
|
56
|
+
return -1
|
|
57
|
+
|
|
58
|
+
# def addCellId(self, cell: DatatypeFormattedTableCell):
|
|
59
|
+
# self.cells.sort(key=lambda c: (c.row, c.column))
|
|
60
|
+
# self._cellIds = {c.id: i for i, c in enumerate(self.cells)}
|
|
61
|
+
# self._cellIds[cell.id] = cell
|
|
62
|
+
|
|
63
|
+
def reorganizeCells(self):
|
|
64
|
+
self.cells.sort(key=lambda c: c.column)
|
|
65
|
+
self._columnRange = [self.cells[0].column, self.cells[-1].column]
|
|
66
|
+
self.cells.sort(key=lambda c: (c.row, c.column))
|
|
67
|
+
self._rowRange = [self.cells[0].row, self.cells[-1].row]
|
|
68
|
+
self._cellIds = {c.id: i for i, c in enumerate(self.cells)}
|
|
69
|
+
|
|
70
|
+
def toDict(self, validate=False):
|
|
71
|
+
self.reorganizeCells()
|
|
72
|
+
return super().toDict()
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def type(self) -> str:
|
|
76
|
+
return self._type
|
|
77
|
+
|
|
78
|
+
@type.setter
|
|
79
|
+
def type(self, value):
|
|
80
|
+
self._type = value
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def id(self) -> str:
|
|
84
|
+
return self._id
|
|
85
|
+
|
|
86
|
+
@id.setter
|
|
87
|
+
def id(self, value):
|
|
88
|
+
self._id = value
|
|
89
|
+
|
|
90
|
+
@property
|
|
91
|
+
def name(self) -> Optional[str]:
|
|
92
|
+
return self._name
|
|
93
|
+
|
|
94
|
+
@name.setter
|
|
95
|
+
def name(self, value):
|
|
96
|
+
self._name = value
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def cells(self) -> List[DatatypeFormattedTableCell]:
|
|
100
|
+
return self._cells
|
|
101
|
+
|
|
102
|
+
@cells.setter
|
|
103
|
+
def cells(self, value):
|
|
104
|
+
self._cells = self.checkListAndConvert(
|
|
105
|
+
value, fieldName="cells", fieldType=DatatypeFormattedTableCell
|
|
106
|
+
)
|
|
107
|
+
self.reorganizeCells()
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def rowRange(self) -> List[int]:
|
|
111
|
+
return self._rowRange
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def columnRange(self) -> List[int]:
|
|
115
|
+
return self._columnRange
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def fixedRow(self) -> Optional[int]:
|
|
119
|
+
return self._fixedRow
|
|
120
|
+
|
|
121
|
+
@fixedRow.setter
|
|
122
|
+
def fixedRow(self, value):
|
|
123
|
+
self._fixedRow = self.checkAndConvert(
|
|
124
|
+
value, fieldName="fixedRow", fieldType=int, allowNone=True
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
@property
|
|
128
|
+
def fixedColumn(self) -> Optional[int]:
|
|
129
|
+
return self._fixedColumn
|
|
130
|
+
|
|
131
|
+
@fixedColumn.setter
|
|
132
|
+
def fixedColumn(self, value):
|
|
133
|
+
self._fixedColumn = self.checkAndConvert(
|
|
134
|
+
value, fieldName="fixedColumn", fieldType=int, allowNone=True
|
|
135
|
+
)
|