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
LOGS/LOGS.py
ADDED
|
@@ -0,0 +1,1436 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
A library to access the LOGS API via Python
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
from typing import (
|
|
9
|
+
TYPE_CHECKING,
|
|
10
|
+
Any,
|
|
11
|
+
Dict,
|
|
12
|
+
List,
|
|
13
|
+
Optional,
|
|
14
|
+
Sequence,
|
|
15
|
+
Type,
|
|
16
|
+
TypeVar,
|
|
17
|
+
Union,
|
|
18
|
+
cast,
|
|
19
|
+
overload,
|
|
20
|
+
)
|
|
21
|
+
from uuid import UUID
|
|
22
|
+
|
|
23
|
+
from LOGS.Auxiliary import (
|
|
24
|
+
Constants,
|
|
25
|
+
EntityCreatingException,
|
|
26
|
+
EntityDeletingException,
|
|
27
|
+
EntityNotFoundException,
|
|
28
|
+
EntityUpdatingException,
|
|
29
|
+
LOGSException,
|
|
30
|
+
Tools,
|
|
31
|
+
)
|
|
32
|
+
from LOGS.Auxiliary.CustomEntityClassGenerator import CustomEntityClassGenerator
|
|
33
|
+
from LOGS.Entities.Attachment import Attachment
|
|
34
|
+
from LOGS.Entities.AttachmentRequestParameter import AttachmentRequestParameter
|
|
35
|
+
from LOGS.Entities.Attachments import Attachments
|
|
36
|
+
from LOGS.Entities.Bridge import Bridge
|
|
37
|
+
from LOGS.Entities.BridgeRequestParameter import BridgeRequestParameter
|
|
38
|
+
from LOGS.Entities.Bridges import Bridges
|
|
39
|
+
from LOGS.Entities.CustomField import CustomField
|
|
40
|
+
from LOGS.Entities.CustomFieldRequestParameter import CustomFieldRequestParameter
|
|
41
|
+
from LOGS.Entities.CustomFields import CustomFields
|
|
42
|
+
from LOGS.Entities.CustomType import CustomType
|
|
43
|
+
from LOGS.Entities.CustomTypeRequestParameter import CustomTypeRequestParameter
|
|
44
|
+
from LOGS.Entities.CustomTypes import CustomTypes
|
|
45
|
+
from LOGS.Entities.DataFormat import DataFormat
|
|
46
|
+
from LOGS.Entities.DataFormatInstrument import DataFormatInstrument
|
|
47
|
+
from LOGS.Entities.DataFormatInstrumentRequestParameter import (
|
|
48
|
+
DataFormatInstrumentRequestParameter,
|
|
49
|
+
)
|
|
50
|
+
from LOGS.Entities.DataFormatInstruments import DataFormatInstruments
|
|
51
|
+
from LOGS.Entities.DataFormatRequestParameter import DataFormatRequestParameter
|
|
52
|
+
from LOGS.Entities.DataFormats import DataFormats
|
|
53
|
+
from LOGS.Entities.Dataset import Dataset
|
|
54
|
+
from LOGS.Entities.DatasetCreator import DatasetCreator
|
|
55
|
+
from LOGS.Entities.DatasetMatching import DatasetMatching
|
|
56
|
+
from LOGS.Entities.DatasetMatchTypes import DatasetsUpdatableFiles
|
|
57
|
+
from LOGS.Entities.DatasetRequestParameter import DatasetRequestParameter
|
|
58
|
+
from LOGS.Entities.Datasets import Datasets
|
|
59
|
+
from LOGS.Entities.DataSource import DataSource
|
|
60
|
+
from LOGS.Entities.DataSourceRequestParameter import DataSourceRequestParameter
|
|
61
|
+
from LOGS.Entities.DataSources import DataSources
|
|
62
|
+
from LOGS.Entities.Entities import Entities
|
|
63
|
+
from LOGS.Entities.EntitiesRequestParameter import EntitiesRequestParameter
|
|
64
|
+
from LOGS.Entities.EntityOriginWriteModelWithId import EntityOriginWriteModelWithId
|
|
65
|
+
from LOGS.Entities.FileEntry import FileEntry
|
|
66
|
+
from LOGS.Entities.InventoryItem import InventoryItem
|
|
67
|
+
from LOGS.Entities.InventoryItemRequestParameter import InventoryItemRequestParameter
|
|
68
|
+
from LOGS.Entities.InventoryItems import InventoryItems
|
|
69
|
+
from LOGS.Entities.LabNotebook import LabNotebook
|
|
70
|
+
from LOGS.Entities.LabNotebookEntries import LabNotebookEntries
|
|
71
|
+
from LOGS.Entities.LabNotebookEntry import LabNotebookEntry
|
|
72
|
+
from LOGS.Entities.LabNotebookEntryRequestParameter import (
|
|
73
|
+
LabNotebookEntryRequestParameter,
|
|
74
|
+
)
|
|
75
|
+
from LOGS.Entities.LabNotebookExperiment import LabNotebookExperiment
|
|
76
|
+
from LOGS.Entities.LabNotebookExperimentRequestParameter import (
|
|
77
|
+
LabNotebookExperimentRequestParameter,
|
|
78
|
+
)
|
|
79
|
+
from LOGS.Entities.LabNotebookExperiments import LabNotebookExperiments
|
|
80
|
+
from LOGS.Entities.LabNotebookRequestParameter import LabNotebookRequestParameter
|
|
81
|
+
from LOGS.Entities.LabNotebooks import LabNotebooks
|
|
82
|
+
from LOGS.Entities.LabNotebookTemplate import LabNotebookTemplate
|
|
83
|
+
from LOGS.Entities.LabNotebookTemplateRequestParameter import (
|
|
84
|
+
LabNotebookTemplateRequestParameter,
|
|
85
|
+
)
|
|
86
|
+
from LOGS.Entities.LabNotebookTemplates import LabNotebookTemplates
|
|
87
|
+
from LOGS.Entities.Method import Method
|
|
88
|
+
from LOGS.Entities.MethodRequestParameter import MethodRequestParameter
|
|
89
|
+
from LOGS.Entities.Methods import Methods
|
|
90
|
+
from LOGS.Entities.Origin import Origin
|
|
91
|
+
from LOGS.Entities.OriginRequestParameter import OriginRequestParameter
|
|
92
|
+
from LOGS.Entities.Origins import Origins
|
|
93
|
+
from LOGS.Entities.Person import Person
|
|
94
|
+
from LOGS.Entities.PersonRequestParameter import PersonRequestParameter
|
|
95
|
+
from LOGS.Entities.Persons import Persons
|
|
96
|
+
from LOGS.Entities.Project import Project
|
|
97
|
+
from LOGS.Entities.ProjectRequestParameter import ProjectRequestParameter
|
|
98
|
+
from LOGS.Entities.Projects import Projects
|
|
99
|
+
from LOGS.Entities.Role import Role
|
|
100
|
+
from LOGS.Entities.RoleRequestParameter import RoleRequestParameter
|
|
101
|
+
from LOGS.Entities.Roles import Roles
|
|
102
|
+
from LOGS.Entities.Sample import Sample
|
|
103
|
+
from LOGS.Entities.SampleRequestParameter import SampleRequestParameter
|
|
104
|
+
from LOGS.Entities.Samples import Samples
|
|
105
|
+
from LOGS.Entities.SharedContent import SharedContent
|
|
106
|
+
from LOGS.Entities.SharedContentRequestParameter import SharedContentRequestParameter
|
|
107
|
+
from LOGS.Entities.SharedContents import SharedContents
|
|
108
|
+
from LOGS.Entities.Vendor import Vendor
|
|
109
|
+
from LOGS.Entities.VendorRequestParameter import VendorRequestParameter
|
|
110
|
+
from LOGS.Entities.Vendors import Vendors
|
|
111
|
+
from LOGS.Entity import Entity, EntityIterator
|
|
112
|
+
from LOGS.Entity.ConnectedEntity import ConnectedEntity
|
|
113
|
+
from LOGS.Interfaces.ISoftDeletable import ISoftDeletable
|
|
114
|
+
from LOGS.Interfaces.ITypedEntity import ITypedEntity
|
|
115
|
+
from LOGS.Interfaces.IUniqueEntity import IUniqueEntity
|
|
116
|
+
from LOGS.LOGSConnection import LOGSConnection
|
|
117
|
+
from LOGS.LOGSOptions import LOGSOptions
|
|
118
|
+
from LOGS.ServerMetaData import ServerMetaData
|
|
119
|
+
|
|
120
|
+
if TYPE_CHECKING:
|
|
121
|
+
from LOGS.Entities.DataFormatMinimal import DataFormatMinimal
|
|
122
|
+
from LOGS.Entities.ProjectMinimal import ProjectMinimal
|
|
123
|
+
|
|
124
|
+
_T = TypeVar("_T", bound=Union[Constants.ENTITIES, Entity])
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class test:
|
|
128
|
+
pass
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class LOGS:
|
|
132
|
+
"""Python class to access the LOGS web API"""
|
|
133
|
+
|
|
134
|
+
_connection: LOGSConnection
|
|
135
|
+
_entities: Sequence[Type[Constants.ENTITIES]] = [
|
|
136
|
+
Bridge,
|
|
137
|
+
CustomField,
|
|
138
|
+
CustomType,
|
|
139
|
+
Dataset,
|
|
140
|
+
DataSource,
|
|
141
|
+
InventoryItem,
|
|
142
|
+
LabNotebook,
|
|
143
|
+
LabNotebookEntry,
|
|
144
|
+
LabNotebookExperiment,
|
|
145
|
+
Origin,
|
|
146
|
+
Person,
|
|
147
|
+
Project,
|
|
148
|
+
Sample,
|
|
149
|
+
DataFormat,
|
|
150
|
+
Role,
|
|
151
|
+
Vendor,
|
|
152
|
+
DataFormatInstrument,
|
|
153
|
+
Method,
|
|
154
|
+
Attachment,
|
|
155
|
+
]
|
|
156
|
+
_entityByName = {t.__name__: t for t in _entities}
|
|
157
|
+
_defaultConfigFile: str = "logs.json"
|
|
158
|
+
_currentUser: Person
|
|
159
|
+
_cacheDir: Optional[str] = None
|
|
160
|
+
|
|
161
|
+
def __init__(
|
|
162
|
+
self,
|
|
163
|
+
url: Optional[str] = None,
|
|
164
|
+
apiKey: Optional[str] = None,
|
|
165
|
+
configFile: Optional[str] = None,
|
|
166
|
+
options: Optional[LOGSOptions] = None,
|
|
167
|
+
verify: bool = True,
|
|
168
|
+
):
|
|
169
|
+
"""Checks the connection to the server on creation
|
|
170
|
+
|
|
171
|
+
:param url: URL to specific LOGS group (e.g. https://mylogs/mygroup or https://mylogs:80/mygroup/api/0.1)
|
|
172
|
+
:param api_key: The API key that grants access to LOGS (you need to generate on in LOGS and copy it)
|
|
173
|
+
:param verbose: If set you see some information about the server connection. Defaults to False.
|
|
174
|
+
|
|
175
|
+
:raises: Exception: URL does not defined or is invalid.
|
|
176
|
+
:raises: Exception: The URL does not define a group.
|
|
177
|
+
:raises: Exception: Server cannot be reached.
|
|
178
|
+
"""
|
|
179
|
+
self._options = Tools.checkAndConvert(
|
|
180
|
+
options, LOGSOptions, "options", initOnNone=True
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
_url = url
|
|
184
|
+
_apiKey = apiKey
|
|
185
|
+
|
|
186
|
+
if not configFile and os.path.isfile(self._defaultConfigFile):
|
|
187
|
+
configFile = self._defaultConfigFile
|
|
188
|
+
|
|
189
|
+
if configFile:
|
|
190
|
+
config = self._readConfig(configFile)
|
|
191
|
+
if "url" in config:
|
|
192
|
+
_url = config["url"]
|
|
193
|
+
if "apiKey" in config:
|
|
194
|
+
_apiKey = config["apiKey"]
|
|
195
|
+
if "proxyTargetUrl" in config:
|
|
196
|
+
self._options.proxyTargetUrl = config["proxyTargetUrl"]
|
|
197
|
+
|
|
198
|
+
if url:
|
|
199
|
+
_url = url
|
|
200
|
+
|
|
201
|
+
if apiKey:
|
|
202
|
+
_apiKey = apiKey
|
|
203
|
+
|
|
204
|
+
if not _url:
|
|
205
|
+
raise LOGSException("The url to the LOGS server must be provided.")
|
|
206
|
+
|
|
207
|
+
if not _apiKey:
|
|
208
|
+
raise LOGSException(
|
|
209
|
+
"The API key to access the server %a must be provided" % _url
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
self.promptPrefix = "LOGSAPI>"
|
|
213
|
+
|
|
214
|
+
self._connection = LOGSConnection(
|
|
215
|
+
url=_url, apiKey=_apiKey, options=self._options, verify=verify
|
|
216
|
+
)
|
|
217
|
+
self._currentUser = self._fetchCurrentUser()
|
|
218
|
+
|
|
219
|
+
def _fetchCurrentUser(self) -> Person:
|
|
220
|
+
data, responseError = self._connection.getEndpoint(["session"])
|
|
221
|
+
if responseError:
|
|
222
|
+
raise LOGSException(responseError=responseError)
|
|
223
|
+
|
|
224
|
+
if not isinstance(data, dict):
|
|
225
|
+
raise LOGSException(
|
|
226
|
+
"Unexpected response from session endpoint. Could not get current user."
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
person = None
|
|
230
|
+
if "person" in data:
|
|
231
|
+
personClass = self.getTypedEntityClass(None, Person)
|
|
232
|
+
person = personClass(data["person"], connection=self._connection)
|
|
233
|
+
|
|
234
|
+
if not person or not person.id:
|
|
235
|
+
raise LOGSException(
|
|
236
|
+
"Unexpected response from session endpoint. Could not get current user."
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
return person
|
|
240
|
+
|
|
241
|
+
def _readConfig(self, path: str) -> dict:
|
|
242
|
+
if not os.path.isfile(path):
|
|
243
|
+
raise LOGSException("Could not find config file %a" % path)
|
|
244
|
+
|
|
245
|
+
with open(path, "r") as f:
|
|
246
|
+
try:
|
|
247
|
+
config = json.load(f)
|
|
248
|
+
except json.JSONDecodeError as e:
|
|
249
|
+
raise LOGSException(
|
|
250
|
+
"Could not read config from file %a: %s" % (path, str(e))
|
|
251
|
+
)
|
|
252
|
+
return config
|
|
253
|
+
|
|
254
|
+
@classmethod
|
|
255
|
+
def getHumanReadableSize(cls, size: float, suffix="B"):
|
|
256
|
+
for unit in Constants.byteUnits:
|
|
257
|
+
if abs(size) < 1024.0:
|
|
258
|
+
return "%3.1f%s%s" % (size, unit, suffix)
|
|
259
|
+
size /= 1024.0
|
|
260
|
+
return "%.1f%s%s" % (size, "Yi", suffix)
|
|
261
|
+
|
|
262
|
+
def getDatasetDir(self, dataset: Dataset):
|
|
263
|
+
if self.cacheDir:
|
|
264
|
+
if not os.path.isdir(self.cacheDir):
|
|
265
|
+
raise LOGSException(
|
|
266
|
+
f"Specified cache directory '{self.cacheDir}' cannot be opened or is not a directory."
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
dataDir = os.path.join(self.cacheDir, dataset.cacheId)
|
|
270
|
+
if dataDir and not os.path.exists(dataDir):
|
|
271
|
+
os.mkdir(dataDir)
|
|
272
|
+
return dataDir
|
|
273
|
+
return None
|
|
274
|
+
|
|
275
|
+
def _fetchEntity(self, entityType: Type[_T], id: Union[int, str]) -> _T:
|
|
276
|
+
e = cast(Type[Entity], entityType)(id=id, connection=self._connection)
|
|
277
|
+
if isinstance(e, Dataset):
|
|
278
|
+
e.cacheDir = self.getDatasetDir(e)
|
|
279
|
+
e.fetch()
|
|
280
|
+
if isinstance(e, ITypedEntity):
|
|
281
|
+
e = e._getTypedInstance()
|
|
282
|
+
|
|
283
|
+
return cast(_T, e)
|
|
284
|
+
|
|
285
|
+
def _restoreEntitiesByTypeName(self, typeDict: Dict[str, Any]):
|
|
286
|
+
for typeName, entities in typeDict.items():
|
|
287
|
+
if not entities:
|
|
288
|
+
continue
|
|
289
|
+
t = self._entityByName.get(typeName, None)
|
|
290
|
+
if not t:
|
|
291
|
+
continue
|
|
292
|
+
self._restoreEntities(cast(Any, t), entities)
|
|
293
|
+
|
|
294
|
+
def _restoreEntities(
|
|
295
|
+
self, entityType: Type[Entity], entities: List[Constants.ENTITIES]
|
|
296
|
+
):
|
|
297
|
+
if not entityType._endpoint:
|
|
298
|
+
raise NotImplementedError(
|
|
299
|
+
"Restoring of entity type %a is not implemented."
|
|
300
|
+
% (
|
|
301
|
+
type(self).__name__
|
|
302
|
+
if type(self).__name__ != Entity.__name__
|
|
303
|
+
else "unknown"
|
|
304
|
+
)
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
if len(entities) < 1:
|
|
308
|
+
return
|
|
309
|
+
elif len(entities) == 1:
|
|
310
|
+
if not entities[0].id:
|
|
311
|
+
raise EntityNotFoundException(entities[0])
|
|
312
|
+
|
|
313
|
+
data, responseError = self._connection.postEndpoint(
|
|
314
|
+
entityType._endpoint + ["restore", str(entities[0].id)],
|
|
315
|
+
data=entities[0].toDict(),
|
|
316
|
+
)
|
|
317
|
+
if (
|
|
318
|
+
isinstance(data, dict)
|
|
319
|
+
and "results" in data
|
|
320
|
+
and isinstance(data["results"], list)
|
|
321
|
+
and len(data["results"]) > 0
|
|
322
|
+
):
|
|
323
|
+
entities[0].override(data["results"][0])
|
|
324
|
+
else:
|
|
325
|
+
data, responseError = self._connection.postEndpoint(
|
|
326
|
+
entityType._endpoint + ["bulk_restore"],
|
|
327
|
+
data=[e.id for e in entities],
|
|
328
|
+
)
|
|
329
|
+
if (
|
|
330
|
+
isinstance(data, dict)
|
|
331
|
+
and "results" in data
|
|
332
|
+
and isinstance(data["results"], list)
|
|
333
|
+
):
|
|
334
|
+
for i, d in enumerate(data["results"]):
|
|
335
|
+
entities[i].override(d)
|
|
336
|
+
|
|
337
|
+
if responseError:
|
|
338
|
+
raise EntityUpdatingException(entity=entities, responseError=responseError)
|
|
339
|
+
|
|
340
|
+
def _updateEntitiesByTypeName(self, typeDict: Dict[str, Any]):
|
|
341
|
+
for typeName, entities in typeDict.items():
|
|
342
|
+
if not entities:
|
|
343
|
+
continue
|
|
344
|
+
t = self._entityByName.get(typeName, None)
|
|
345
|
+
if not t:
|
|
346
|
+
continue
|
|
347
|
+
self._updateEntities(cast(Any, t), entities)
|
|
348
|
+
|
|
349
|
+
def _updateEntities(
|
|
350
|
+
self, entityType: Type[Entity], entities: List[Constants.ENTITIES]
|
|
351
|
+
):
|
|
352
|
+
if not entityType._endpoint:
|
|
353
|
+
raise NotImplementedError(
|
|
354
|
+
"Updating of entity type %a is not implemented."
|
|
355
|
+
% (
|
|
356
|
+
type(self).__name__
|
|
357
|
+
if type(self).__name__ != Entity.__name__
|
|
358
|
+
else "unknown"
|
|
359
|
+
)
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
if len(entities) < 1:
|
|
363
|
+
return
|
|
364
|
+
elif len(entities) == 1:
|
|
365
|
+
if not entities[0].id:
|
|
366
|
+
raise EntityNotFoundException(entities[0])
|
|
367
|
+
|
|
368
|
+
data, responseError = self._connection.putEndpoint(
|
|
369
|
+
entityType._endpoint + [str(entities[0].id)],
|
|
370
|
+
data=entities[0]._toDictWithSlack(),
|
|
371
|
+
)
|
|
372
|
+
if (
|
|
373
|
+
isinstance(data, dict)
|
|
374
|
+
and "results" in data
|
|
375
|
+
and isinstance(data["results"], list)
|
|
376
|
+
and len(data["results"]) > 0
|
|
377
|
+
):
|
|
378
|
+
entities[0].override(data["results"][0])
|
|
379
|
+
else:
|
|
380
|
+
data, responseError = self._connection.postEndpoint(
|
|
381
|
+
entityType._endpoint + ["bulk_edit"],
|
|
382
|
+
data=[e._toDictWithSlack() for e in entities],
|
|
383
|
+
)
|
|
384
|
+
if (
|
|
385
|
+
isinstance(data, dict)
|
|
386
|
+
and "results" in data
|
|
387
|
+
and isinstance(data["results"], list)
|
|
388
|
+
):
|
|
389
|
+
for i, d in enumerate(data["results"]):
|
|
390
|
+
entities[i].override(d)
|
|
391
|
+
|
|
392
|
+
if responseError:
|
|
393
|
+
raise EntityUpdatingException(entity=entities, responseError=responseError)
|
|
394
|
+
|
|
395
|
+
def _createDataset(self, dataset: Union[Dataset, Attachment]):
|
|
396
|
+
data = DatasetCreator(connection=self._connection, dataset=dataset).create()
|
|
397
|
+
# TODO: The following is not optimal. DatasetCreator should directly set the dataset properties (add dataset write model to multipart)
|
|
398
|
+
if (
|
|
399
|
+
"results" in data
|
|
400
|
+
and isinstance(data["results"], list)
|
|
401
|
+
and len(data["results"]) == 1
|
|
402
|
+
):
|
|
403
|
+
dataset._connection = self._connection
|
|
404
|
+
dataset.override(data["results"][0])
|
|
405
|
+
|
|
406
|
+
def _createEntitiesByTypeName(self, typeDict: Dict[str, Entity]):
|
|
407
|
+
for typeName, entities in typeDict.items():
|
|
408
|
+
if not entities:
|
|
409
|
+
continue
|
|
410
|
+
t = self._entityByName.get(typeName, None)
|
|
411
|
+
|
|
412
|
+
if not t:
|
|
413
|
+
continue
|
|
414
|
+
|
|
415
|
+
self._createEntities(cast(Any, t), cast(Any, entities))
|
|
416
|
+
|
|
417
|
+
def _addOriginToEntity(
|
|
418
|
+
self, endpoint: List[str], entity: Optional[EntityOriginWriteModelWithId]
|
|
419
|
+
):
|
|
420
|
+
return self._addOriginToEntities(endpoint, [entity])
|
|
421
|
+
|
|
422
|
+
def _addOriginToEntities(
|
|
423
|
+
self,
|
|
424
|
+
endpoint: List[str],
|
|
425
|
+
entities: List[Optional[EntityOriginWriteModelWithId]],
|
|
426
|
+
):
|
|
427
|
+
entities = [e for e in entities if e]
|
|
428
|
+
if len(entities) == 1:
|
|
429
|
+
data, responseError = self._connection.postEndpoint(
|
|
430
|
+
endpoint + ["origin"], data=[e.toDict() for e in entities if e]
|
|
431
|
+
)
|
|
432
|
+
if responseError:
|
|
433
|
+
indent = Constants.exceptionIndentation
|
|
434
|
+
message = ""
|
|
435
|
+
if isinstance(data, list):
|
|
436
|
+
message = "%sCould not add origin to %s %a" % (
|
|
437
|
+
(
|
|
438
|
+
"\n" + indent
|
|
439
|
+
if responseError and len(responseError.errorStringList) > 1
|
|
440
|
+
else ""
|
|
441
|
+
),
|
|
442
|
+
Tools.plural("entity", entities),
|
|
443
|
+
Tools.eclipsesJoin(", ", [e.id for e in entities if e]),
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
# indent *= 2
|
|
447
|
+
if responseError:
|
|
448
|
+
message += ": " + responseError.errorString(indent)
|
|
449
|
+
|
|
450
|
+
raise LOGSException(message=message, responseError=responseError)
|
|
451
|
+
|
|
452
|
+
# for o in entities:
|
|
453
|
+
# print(">>>>>", o.toDict())
|
|
454
|
+
# data, errors = self._connection.postEndpoint(
|
|
455
|
+
# entityType._endpoint + ["bulk_create"],
|
|
456
|
+
# data=[e.toDict() for e in entities],
|
|
457
|
+
# )
|
|
458
|
+
|
|
459
|
+
def _createEntityOriginWriteModel(
|
|
460
|
+
self, entity: Union[Entity, IUniqueEntity]
|
|
461
|
+
) -> Optional[EntityOriginWriteModelWithId]:
|
|
462
|
+
if isinstance(entity, IUniqueEntity) and (
|
|
463
|
+
entity._foreignUid or entity._foreignOrigin
|
|
464
|
+
):
|
|
465
|
+
if isinstance(entity, Entity):
|
|
466
|
+
model = EntityOriginWriteModelWithId(
|
|
467
|
+
id=entity.id, uid=entity._foreignUid, origin=entity._foreignOrigin
|
|
468
|
+
)
|
|
469
|
+
if model.uid:
|
|
470
|
+
setattr(entity, "uid", model.uid)
|
|
471
|
+
if model.uid:
|
|
472
|
+
setattr(entity, "origin", model.origin)
|
|
473
|
+
return model
|
|
474
|
+
|
|
475
|
+
return None
|
|
476
|
+
|
|
477
|
+
def _createEntities(self, entityType: Type[Entity], entities: List[Entity]):
|
|
478
|
+
if not entityType._endpoint:
|
|
479
|
+
raise NotImplementedError(
|
|
480
|
+
"Creating of entity type %a is not implemented."
|
|
481
|
+
% (
|
|
482
|
+
entityType.__name__
|
|
483
|
+
if entityType.__name__ != Entity.__name__
|
|
484
|
+
else "unknown"
|
|
485
|
+
)
|
|
486
|
+
)
|
|
487
|
+
|
|
488
|
+
datasets = [e for e in entities if isinstance(e, Dataset)]
|
|
489
|
+
attachments = [e for e in entities if isinstance(e, Attachment)]
|
|
490
|
+
entities = [e for e in entities if not isinstance(e, (Dataset, Attachment))]
|
|
491
|
+
|
|
492
|
+
if len(datasets) > 0:
|
|
493
|
+
for dataset in datasets:
|
|
494
|
+
self._createDataset(dataset)
|
|
495
|
+
self._addOriginToEntity(
|
|
496
|
+
entityType._endpoint, self._createEntityOriginWriteModel(dataset)
|
|
497
|
+
)
|
|
498
|
+
|
|
499
|
+
if len(attachments) > 0:
|
|
500
|
+
for attachment in attachments:
|
|
501
|
+
self._createDataset(attachment)
|
|
502
|
+
self._addOriginToEntity(
|
|
503
|
+
entityType._endpoint, self._createEntityOriginWriteModel(attachment)
|
|
504
|
+
)
|
|
505
|
+
|
|
506
|
+
responseError = None
|
|
507
|
+
if len(entities) == 1:
|
|
508
|
+
data, responseError = self._connection.postEndpoint(
|
|
509
|
+
entityType._endpoint, data=entities[0].toDict()
|
|
510
|
+
)
|
|
511
|
+
if responseError:
|
|
512
|
+
raise EntityCreatingException(
|
|
513
|
+
entity=entities, responseError=responseError
|
|
514
|
+
)
|
|
515
|
+
|
|
516
|
+
entities[0]._connection = self._connection
|
|
517
|
+
entities[0].override(data)
|
|
518
|
+
self._addOriginToEntity(
|
|
519
|
+
entityType._endpoint, self._createEntityOriginWriteModel(entities[0])
|
|
520
|
+
)
|
|
521
|
+
|
|
522
|
+
elif len(entities) > 1:
|
|
523
|
+
data, responseError = self._connection.postEndpoint(
|
|
524
|
+
entityType._endpoint + ["bulk_create"],
|
|
525
|
+
data=[e.toDict() for e in entities],
|
|
526
|
+
)
|
|
527
|
+
if responseError:
|
|
528
|
+
raise EntityCreatingException(
|
|
529
|
+
entity=entities, responseError=responseError
|
|
530
|
+
)
|
|
531
|
+
|
|
532
|
+
if (
|
|
533
|
+
isinstance(data, dict)
|
|
534
|
+
and "results" in data
|
|
535
|
+
and isinstance(data["results"], list)
|
|
536
|
+
):
|
|
537
|
+
for i, d in enumerate(data["results"]):
|
|
538
|
+
entities[i]._connection = self._connection
|
|
539
|
+
entities[i].override(d)
|
|
540
|
+
self._addOriginToEntities(
|
|
541
|
+
entityType._endpoint,
|
|
542
|
+
[self._createEntityOriginWriteModel(e) for e in entities],
|
|
543
|
+
)
|
|
544
|
+
|
|
545
|
+
def _deleteEntitiesByTypeName(
|
|
546
|
+
self,
|
|
547
|
+
typeDict: Dict[str, List[Union[Constants.ID_TYPE, None]]],
|
|
548
|
+
permanently: bool = False,
|
|
549
|
+
):
|
|
550
|
+
for typeName, entities in typeDict.items():
|
|
551
|
+
if not entities:
|
|
552
|
+
continue
|
|
553
|
+
t = self._entityByName.get(typeName, None)
|
|
554
|
+
if not t:
|
|
555
|
+
continue
|
|
556
|
+
self._deleteEntities(cast(Any, t), [e for e in entities if e], permanently)
|
|
557
|
+
|
|
558
|
+
def _deleteEntities(
|
|
559
|
+
self,
|
|
560
|
+
entityType: Type[Entity],
|
|
561
|
+
entityIds: List[Constants.ID_TYPE],
|
|
562
|
+
permanently: bool = False,
|
|
563
|
+
):
|
|
564
|
+
if not entityType._endpoint:
|
|
565
|
+
raise NotImplementedError(
|
|
566
|
+
"Deleting of entity type %a is not implemented."
|
|
567
|
+
% (
|
|
568
|
+
type(self).__name__
|
|
569
|
+
if type(self).__name__ != Entity.__name__
|
|
570
|
+
else "unknown"
|
|
571
|
+
)
|
|
572
|
+
)
|
|
573
|
+
|
|
574
|
+
if len(entityIds) < 1:
|
|
575
|
+
return
|
|
576
|
+
elif len(entityIds) == 1:
|
|
577
|
+
_, responseError = self._connection.deleteEndpoint(
|
|
578
|
+
entityType._endpoint + [str(entityIds[0])],
|
|
579
|
+
parameters={"deletePermanently": permanently} if permanently else {},
|
|
580
|
+
)
|
|
581
|
+
else:
|
|
582
|
+
_, responseError = self._connection.postEndpoint(
|
|
583
|
+
entityType._endpoint + ["bulk_delete"],
|
|
584
|
+
data=[id for id in entityIds],
|
|
585
|
+
parameters={"deletePermanently": permanently} if permanently else {},
|
|
586
|
+
)
|
|
587
|
+
|
|
588
|
+
if responseError:
|
|
589
|
+
raise EntityDeletingException(
|
|
590
|
+
entityIds=entityIds, responseError=responseError
|
|
591
|
+
)
|
|
592
|
+
|
|
593
|
+
@classmethod
|
|
594
|
+
def _collectTypes(cls, entities: Sequence) -> Dict[str, Any]:
|
|
595
|
+
result: Dict[str, Any] = {k: [] for k in cls._entityByName.keys()}
|
|
596
|
+
result["unknown"] = []
|
|
597
|
+
|
|
598
|
+
for entity in entities:
|
|
599
|
+
unknown = True
|
|
600
|
+
|
|
601
|
+
for k, v in cls._entityByName.items():
|
|
602
|
+
if isinstance(entity, v):
|
|
603
|
+
result[k].append(entity)
|
|
604
|
+
unknown = False
|
|
605
|
+
break
|
|
606
|
+
|
|
607
|
+
if unknown:
|
|
608
|
+
result["unknown"].append(entity)
|
|
609
|
+
return result
|
|
610
|
+
|
|
611
|
+
def printServerStatus(self):
|
|
612
|
+
self._connection.printServerStatus()
|
|
613
|
+
|
|
614
|
+
@overload
|
|
615
|
+
def restore(self, entities: Constants.ENTITIES): ...
|
|
616
|
+
|
|
617
|
+
@overload
|
|
618
|
+
def restore(self, entities: List[Constants.ENTITIES]): ...
|
|
619
|
+
|
|
620
|
+
# Implementation of overload
|
|
621
|
+
def restore(self, entities: Any):
|
|
622
|
+
def decorator(entities: Any):
|
|
623
|
+
types = self._collectTypes(entities)
|
|
624
|
+
if len(types["unknown"]) > 0:
|
|
625
|
+
raise EntityUpdatingException(
|
|
626
|
+
types["unknown"][0],
|
|
627
|
+
errors=[
|
|
628
|
+
"Entity type %a not valid for this action."
|
|
629
|
+
% type(types["unknown"][0]).__name__
|
|
630
|
+
],
|
|
631
|
+
)
|
|
632
|
+
|
|
633
|
+
self._restoreEntitiesByTypeName(types)
|
|
634
|
+
|
|
635
|
+
if not isinstance(entities, list):
|
|
636
|
+
entities = [entities]
|
|
637
|
+
return decorator(entities)
|
|
638
|
+
|
|
639
|
+
@overload
|
|
640
|
+
def update(self, entities: Constants.ENTITIES): ...
|
|
641
|
+
|
|
642
|
+
@overload
|
|
643
|
+
def update(self, entities: List[Constants.ENTITIES]): ...
|
|
644
|
+
|
|
645
|
+
# Implementation of overload
|
|
646
|
+
def update(self, entities: Any):
|
|
647
|
+
def decorator(entities: Any):
|
|
648
|
+
types = self._collectTypes(entities)
|
|
649
|
+
if len(types["unknown"]) > 0:
|
|
650
|
+
raise EntityUpdatingException(
|
|
651
|
+
types["unknown"][0],
|
|
652
|
+
errors=[
|
|
653
|
+
"Entity type %a not valid for this action."
|
|
654
|
+
% type(types["unknown"][0]).__name__
|
|
655
|
+
],
|
|
656
|
+
)
|
|
657
|
+
|
|
658
|
+
self._updateEntitiesByTypeName(types)
|
|
659
|
+
|
|
660
|
+
if not isinstance(entities, list):
|
|
661
|
+
entities = [entities]
|
|
662
|
+
return decorator(entities)
|
|
663
|
+
|
|
664
|
+
@overload
|
|
665
|
+
def create(self, entities: Constants.ENTITIES): ...
|
|
666
|
+
|
|
667
|
+
@overload
|
|
668
|
+
def create(self, entities: Sequence[Constants.ENTITIES]): ...
|
|
669
|
+
|
|
670
|
+
# Implementation of overload
|
|
671
|
+
def create(self, entities: Any):
|
|
672
|
+
def decorator(entities: Sequence[Entity]):
|
|
673
|
+
types = self._collectTypes(entities)
|
|
674
|
+
if len(types["unknown"]) > 0:
|
|
675
|
+
raise EntityCreatingException(
|
|
676
|
+
types["unknown"][0],
|
|
677
|
+
errors=[
|
|
678
|
+
"Entity type %a not valid for this action"
|
|
679
|
+
% type(types["unknown"][0]).__name__
|
|
680
|
+
],
|
|
681
|
+
)
|
|
682
|
+
|
|
683
|
+
self._createEntitiesByTypeName(types)
|
|
684
|
+
|
|
685
|
+
if not isinstance(entities, list):
|
|
686
|
+
entities = [entities]
|
|
687
|
+
decorator(entities)
|
|
688
|
+
|
|
689
|
+
@overload
|
|
690
|
+
def delete(self, entities: Constants.ENTITIES, permanently=False): ...
|
|
691
|
+
|
|
692
|
+
@overload
|
|
693
|
+
def delete(self, entities: Sequence[Constants.ENTITIES], permanently=False): ...
|
|
694
|
+
|
|
695
|
+
# Implementation of overload
|
|
696
|
+
def delete(self, entities: Any = None, permanently=False):
|
|
697
|
+
def decorator(entities: Any):
|
|
698
|
+
types: Dict[str, List[Union[Constants.ID_TYPE, None]]] = self._collectTypes(
|
|
699
|
+
entities
|
|
700
|
+
)
|
|
701
|
+
typesIds = {
|
|
702
|
+
typeName: cast(List, [cast(Entity, e).id for e in entities if e])
|
|
703
|
+
for typeName, entities in types.items()
|
|
704
|
+
}
|
|
705
|
+
if len(types["unknown"]) > 0:
|
|
706
|
+
raise EntityDeletingException(
|
|
707
|
+
types["unknown"][0],
|
|
708
|
+
errors=[
|
|
709
|
+
"Entity type %a not valid for this action"
|
|
710
|
+
% type(types["unknown"][0]).__name__
|
|
711
|
+
],
|
|
712
|
+
)
|
|
713
|
+
|
|
714
|
+
self._deleteEntitiesByTypeName(typesIds, permanently=permanently)
|
|
715
|
+
|
|
716
|
+
for entityList in types.values():
|
|
717
|
+
for entity in entityList:
|
|
718
|
+
if permanently and isinstance(entity, ConnectedEntity):
|
|
719
|
+
entity._connection = None
|
|
720
|
+
if isinstance(entity, ISoftDeletable):
|
|
721
|
+
entity.isDeleted = True
|
|
722
|
+
|
|
723
|
+
if isinstance(entities, EntityIterator):
|
|
724
|
+
raise LOGSException(
|
|
725
|
+
"An %a cannot be used for delete. Please convert it to a list first."
|
|
726
|
+
% EntityIterator.__name__
|
|
727
|
+
)
|
|
728
|
+
elif not isinstance(entities, list):
|
|
729
|
+
entities = [entities]
|
|
730
|
+
return decorator(entities)
|
|
731
|
+
|
|
732
|
+
@overload
|
|
733
|
+
def deleteById(
|
|
734
|
+
self, entityType: Type[Constants.ENTITIES], ids: int, permanently: bool = False
|
|
735
|
+
): ...
|
|
736
|
+
|
|
737
|
+
@overload
|
|
738
|
+
def deleteById(
|
|
739
|
+
self, entityType: Type[Constants.ENTITIES], ids: str, permanently: bool = False
|
|
740
|
+
): ...
|
|
741
|
+
|
|
742
|
+
@overload
|
|
743
|
+
def deleteById(
|
|
744
|
+
self,
|
|
745
|
+
entityType: Type[Constants.ENTITIES],
|
|
746
|
+
ids: Constants.ID_TYPE,
|
|
747
|
+
permanently: bool = False,
|
|
748
|
+
): ...
|
|
749
|
+
|
|
750
|
+
@overload
|
|
751
|
+
def deleteById(
|
|
752
|
+
self,
|
|
753
|
+
entityType: Type[Constants.ENTITIES],
|
|
754
|
+
ids: List[int],
|
|
755
|
+
permanently: bool = False,
|
|
756
|
+
): ...
|
|
757
|
+
|
|
758
|
+
@overload
|
|
759
|
+
def deleteById(
|
|
760
|
+
self,
|
|
761
|
+
entityType: Type[Constants.ENTITIES],
|
|
762
|
+
ids: List[str],
|
|
763
|
+
permanently: bool = False,
|
|
764
|
+
): ...
|
|
765
|
+
|
|
766
|
+
@overload
|
|
767
|
+
def deleteById(
|
|
768
|
+
self,
|
|
769
|
+
entityType: Type[Constants.ENTITIES],
|
|
770
|
+
ids: List[Constants.ID_TYPE],
|
|
771
|
+
permanently: bool = False,
|
|
772
|
+
): ...
|
|
773
|
+
|
|
774
|
+
# Implementation of overload
|
|
775
|
+
def deleteById(self, entityType=None, ids: Any = None, permanently: bool = False):
|
|
776
|
+
if not entityType:
|
|
777
|
+
raise Exception("Parameter 'entityType' must be provided.")
|
|
778
|
+
|
|
779
|
+
if not issubclass(entityType, Entity):
|
|
780
|
+
raise Exception(
|
|
781
|
+
f"Parameter 'entityType' must be a subclass of {Entity.__name__}."
|
|
782
|
+
)
|
|
783
|
+
|
|
784
|
+
def decorator(entityType: Any):
|
|
785
|
+
self._deleteEntities(entityType, ids, permanently=permanently)
|
|
786
|
+
|
|
787
|
+
if ids and not isinstance(ids, list):
|
|
788
|
+
ids = [ids]
|
|
789
|
+
return decorator(entityType)
|
|
790
|
+
|
|
791
|
+
def getTypedEntityClass(
|
|
792
|
+
self, customTypeOrId: Optional[Union[CustomType, int]], entityType: Type[_T]
|
|
793
|
+
) -> Type[_T]:
|
|
794
|
+
if not issubclass(entityType, Entity):
|
|
795
|
+
raise Exception(
|
|
796
|
+
f"Type '{entityType.__name__}' is not an LOGS entity. (Got '{type(entityType).__name__}')"
|
|
797
|
+
)
|
|
798
|
+
|
|
799
|
+
if customTypeOrId is None:
|
|
800
|
+
return CustomEntityClassGenerator.generate(
|
|
801
|
+
None,
|
|
802
|
+
connection=self._connection,
|
|
803
|
+
limitToEntityType=entityType,
|
|
804
|
+
)
|
|
805
|
+
elif not issubclass(entityType, ITypedEntity):
|
|
806
|
+
raise Exception(
|
|
807
|
+
f"Entity type '{entityType.__name__}' is not a typed entity and cannot be used with custom types."
|
|
808
|
+
)
|
|
809
|
+
|
|
810
|
+
if isinstance(customTypeOrId, int):
|
|
811
|
+
customType = CustomEntityClassGenerator.fetchCustomType(
|
|
812
|
+
customTypeOrId, self._connection
|
|
813
|
+
)
|
|
814
|
+
elif isinstance(customTypeOrId, CustomType):
|
|
815
|
+
customType = customTypeOrId
|
|
816
|
+
else:
|
|
817
|
+
raise Exception(
|
|
818
|
+
f"Parameter 'customTypeOrId' must be of type {CustomType.__name__} or int. (Got '{type(customTypeOrId).__name__}')"
|
|
819
|
+
)
|
|
820
|
+
|
|
821
|
+
return CustomEntityClassGenerator.generate(
|
|
822
|
+
customType=customType,
|
|
823
|
+
connection=self._connection,
|
|
824
|
+
limitToEntityType=entityType,
|
|
825
|
+
)
|
|
826
|
+
|
|
827
|
+
def newSample(
|
|
828
|
+
self,
|
|
829
|
+
entityOrCustomTypeOrId: Optional[Union[CustomType, int]] = None,
|
|
830
|
+
ref=None,
|
|
831
|
+
name: str = "",
|
|
832
|
+
projects: Optional[List[Union["ProjectMinimal", "Project"]]] = None,
|
|
833
|
+
) -> Sample:
|
|
834
|
+
return self.getTypedEntityClass(entityOrCustomTypeOrId, Sample)(
|
|
835
|
+
ref=ref, connection=self._connection, name=name, projects=projects
|
|
836
|
+
)
|
|
837
|
+
|
|
838
|
+
def sample(self, id: int) -> Sample:
|
|
839
|
+
return self._fetchEntity(Sample, id)
|
|
840
|
+
|
|
841
|
+
def samples(self, parameter: Optional[SampleRequestParameter] = None) -> Samples:
|
|
842
|
+
if parameter and not isinstance(parameter, SampleRequestParameter):
|
|
843
|
+
raise LOGSException(
|
|
844
|
+
"Parameter for %s.%s must be of type %a. (Got %a)"
|
|
845
|
+
% (
|
|
846
|
+
type(self).__name__,
|
|
847
|
+
self.samples.__name__,
|
|
848
|
+
SampleRequestParameter.__name__,
|
|
849
|
+
type(parameter).__name__,
|
|
850
|
+
)
|
|
851
|
+
)
|
|
852
|
+
return Samples(connection=self._connection, parameters=parameter)
|
|
853
|
+
|
|
854
|
+
def newProject(
|
|
855
|
+
self,
|
|
856
|
+
entityOrCustomTypeOrId: Optional[Union[CustomType, int]] = None,
|
|
857
|
+
ref=None,
|
|
858
|
+
name: str = "",
|
|
859
|
+
) -> Project:
|
|
860
|
+
return self.getTypedEntityClass(entityOrCustomTypeOrId, Project)(
|
|
861
|
+
ref=ref, connection=self._connection, name=name
|
|
862
|
+
)
|
|
863
|
+
|
|
864
|
+
def project(self, id: int) -> Project:
|
|
865
|
+
return self._fetchEntity(Project, id)
|
|
866
|
+
|
|
867
|
+
def projects(self, parameter: Optional[ProjectRequestParameter] = None) -> Projects:
|
|
868
|
+
if parameter and not isinstance(parameter, ProjectRequestParameter):
|
|
869
|
+
raise LOGSException(
|
|
870
|
+
"Parameter for %s.%s must be of type %a. (Got %a)"
|
|
871
|
+
% (
|
|
872
|
+
type(self).__name__,
|
|
873
|
+
self.projects.__name__,
|
|
874
|
+
ProjectRequestParameter.__name__,
|
|
875
|
+
type(parameter).__name__,
|
|
876
|
+
)
|
|
877
|
+
)
|
|
878
|
+
return Projects(connection=self._connection, parameters=parameter)
|
|
879
|
+
|
|
880
|
+
def newDataset(
|
|
881
|
+
self,
|
|
882
|
+
entityOrCustomTypeOrId: Optional[Union[CustomType, int]] = None,
|
|
883
|
+
ref=None,
|
|
884
|
+
files: Optional[Sequence[Constants.FILE_TYPE]] = None,
|
|
885
|
+
formatOrFormatId: Optional[Union[str, "DataFormatMinimal"]] = None,
|
|
886
|
+
pathPrefixToStrip: Optional[str] = None,
|
|
887
|
+
pathPrefixToAdd: Optional[str] = None,
|
|
888
|
+
) -> Dataset:
|
|
889
|
+
return self.getTypedEntityClass(entityOrCustomTypeOrId, Dataset)(
|
|
890
|
+
ref=ref,
|
|
891
|
+
connection=self._connection,
|
|
892
|
+
files=files,
|
|
893
|
+
formatOrFormatId=formatOrFormatId,
|
|
894
|
+
pathPrefixToStrip=pathPrefixToStrip,
|
|
895
|
+
pathPrefixToAdd=pathPrefixToAdd,
|
|
896
|
+
)
|
|
897
|
+
|
|
898
|
+
def dataset(self, id: int) -> Dataset:
|
|
899
|
+
return self._fetchEntity(Dataset, id)
|
|
900
|
+
|
|
901
|
+
def datasets(self, parameter: Optional[DatasetRequestParameter] = None) -> Datasets:
|
|
902
|
+
if parameter and not isinstance(parameter, DatasetRequestParameter):
|
|
903
|
+
raise LOGSException(
|
|
904
|
+
"Parameter for %s.%s must be of type %a. (Got %a)"
|
|
905
|
+
% (
|
|
906
|
+
type(self).__name__,
|
|
907
|
+
self.datasets.__name__,
|
|
908
|
+
DatasetRequestParameter.__name__,
|
|
909
|
+
type(parameter).__name__,
|
|
910
|
+
)
|
|
911
|
+
)
|
|
912
|
+
return Datasets(connection=self._connection, parameters=parameter)
|
|
913
|
+
|
|
914
|
+
def newAttachment(
|
|
915
|
+
self,
|
|
916
|
+
ref=None,
|
|
917
|
+
files: Optional[Sequence[Constants.FILE_TYPE]] = None,
|
|
918
|
+
pathPrefixToStrip: Optional[str] = None,
|
|
919
|
+
pathPrefixToAdd: Optional[str] = None,
|
|
920
|
+
) -> Attachment:
|
|
921
|
+
return self.getTypedEntityClass(None, Attachment)(
|
|
922
|
+
ref=ref,
|
|
923
|
+
connection=self._connection,
|
|
924
|
+
files=files,
|
|
925
|
+
pathPrefixToStrip=pathPrefixToStrip,
|
|
926
|
+
pathPrefixToAdd=pathPrefixToAdd,
|
|
927
|
+
)
|
|
928
|
+
|
|
929
|
+
def attachment(self, id: int) -> Attachment:
|
|
930
|
+
return self._fetchEntity(Attachment, id)
|
|
931
|
+
|
|
932
|
+
def attachments(
|
|
933
|
+
self, parameter: Optional[AttachmentRequestParameter] = None
|
|
934
|
+
) -> Attachments:
|
|
935
|
+
if parameter and not isinstance(parameter, AttachmentRequestParameter):
|
|
936
|
+
raise LOGSException(
|
|
937
|
+
"Parameter for %s.%s must be of type %a. (Got %a)"
|
|
938
|
+
% (
|
|
939
|
+
type(self).__name__,
|
|
940
|
+
self.attachments.__name__,
|
|
941
|
+
AttachmentRequestParameter.__name__,
|
|
942
|
+
type(parameter).__name__,
|
|
943
|
+
)
|
|
944
|
+
)
|
|
945
|
+
return Attachments(connection=self._connection, parameters=parameter)
|
|
946
|
+
|
|
947
|
+
def newPerson(
|
|
948
|
+
self, entityOrCustomTypeOrId: Optional[Union[CustomType, int]] = None, ref=None
|
|
949
|
+
) -> Person:
|
|
950
|
+
return self.getTypedEntityClass(entityOrCustomTypeOrId, Person)(
|
|
951
|
+
ref=ref, connection=self._connection
|
|
952
|
+
)
|
|
953
|
+
|
|
954
|
+
def person(self, id: int) -> Person:
|
|
955
|
+
return self._fetchEntity(Person, id)
|
|
956
|
+
|
|
957
|
+
def persons(self, parameter: Optional[PersonRequestParameter] = None) -> Persons:
|
|
958
|
+
if parameter and not isinstance(parameter, PersonRequestParameter):
|
|
959
|
+
raise LOGSException(
|
|
960
|
+
"Parameter for %s.%s must be of type %a. (Got %a)"
|
|
961
|
+
% (
|
|
962
|
+
type(self).__name__,
|
|
963
|
+
self.persons.__name__,
|
|
964
|
+
PersonRequestParameter.__name__,
|
|
965
|
+
type(parameter).__name__,
|
|
966
|
+
)
|
|
967
|
+
)
|
|
968
|
+
return Persons(connection=self._connection, parameters=parameter)
|
|
969
|
+
|
|
970
|
+
def newOrigin(
|
|
971
|
+
self,
|
|
972
|
+
ref=None,
|
|
973
|
+
name: Optional[str] = None,
|
|
974
|
+
url: Optional[str] = None,
|
|
975
|
+
uid: Optional[UUID] = None,
|
|
976
|
+
) -> Origin:
|
|
977
|
+
return self.getTypedEntityClass(None, Origin)(
|
|
978
|
+
ref=ref, connection=self._connection, name=name, url=url, uid=uid
|
|
979
|
+
)
|
|
980
|
+
|
|
981
|
+
def origin(self, id: int) -> Origin:
|
|
982
|
+
return self._fetchEntity(Origin, id)
|
|
983
|
+
|
|
984
|
+
def origins(self, parameter: Optional[OriginRequestParameter] = None) -> Origins:
|
|
985
|
+
if parameter and not isinstance(parameter, OriginRequestParameter):
|
|
986
|
+
raise LOGSException(
|
|
987
|
+
"Parameter for %s.%s must be of type %a. (Got %a)"
|
|
988
|
+
% (
|
|
989
|
+
type(self).__name__,
|
|
990
|
+
self.origins.__name__,
|
|
991
|
+
OriginRequestParameter.__name__,
|
|
992
|
+
type(parameter).__name__,
|
|
993
|
+
)
|
|
994
|
+
)
|
|
995
|
+
return Origins(connection=self._connection, parameters=parameter)
|
|
996
|
+
|
|
997
|
+
def newDataFormat(self, ref=None) -> DataFormat:
|
|
998
|
+
return self.getTypedEntityClass(None, DataFormat)(
|
|
999
|
+
ref=ref, connection=self._connection
|
|
1000
|
+
)
|
|
1001
|
+
|
|
1002
|
+
def dataFormat(self, id: str) -> DataFormat:
|
|
1003
|
+
return self._fetchEntity(DataFormat, id)
|
|
1004
|
+
|
|
1005
|
+
def dataFormats(
|
|
1006
|
+
self, parameter: Optional[DataFormatRequestParameter] = None
|
|
1007
|
+
) -> DataFormats:
|
|
1008
|
+
if parameter and not isinstance(parameter, DataFormatRequestParameter):
|
|
1009
|
+
raise LOGSException(
|
|
1010
|
+
"Parameter for %s.%s must be of type %a. (Got %a)"
|
|
1011
|
+
% (
|
|
1012
|
+
type(self).__name__,
|
|
1013
|
+
self.dataFormats.__name__,
|
|
1014
|
+
DataFormatRequestParameter.__name__,
|
|
1015
|
+
type(parameter).__name__,
|
|
1016
|
+
)
|
|
1017
|
+
)
|
|
1018
|
+
return DataFormats(connection=self._connection, parameters=parameter)
|
|
1019
|
+
|
|
1020
|
+
def newRole(self, ref=None) -> Role:
|
|
1021
|
+
return self.getTypedEntityClass(None, Role)(
|
|
1022
|
+
ref=ref, connection=self._connection
|
|
1023
|
+
)
|
|
1024
|
+
|
|
1025
|
+
def role(self, id: int) -> Role:
|
|
1026
|
+
return self._fetchEntity(Role, id)
|
|
1027
|
+
|
|
1028
|
+
def roles(self, parameter: Optional[RoleRequestParameter] = None) -> Roles:
|
|
1029
|
+
if parameter and not isinstance(parameter, RoleRequestParameter):
|
|
1030
|
+
raise LOGSException(
|
|
1031
|
+
"Parameter for %s.%s must be of type %a. (Got %a)"
|
|
1032
|
+
% (
|
|
1033
|
+
type(self).__name__,
|
|
1034
|
+
self.roles.__name__,
|
|
1035
|
+
RoleRequestParameter.__name__,
|
|
1036
|
+
type(parameter).__name__,
|
|
1037
|
+
)
|
|
1038
|
+
)
|
|
1039
|
+
return Roles(connection=self._connection, parameters=parameter)
|
|
1040
|
+
|
|
1041
|
+
def newBridge(self, ref=None) -> Bridge:
|
|
1042
|
+
return self.getTypedEntityClass(None, Bridge)(
|
|
1043
|
+
ref=ref, connection=self._connection
|
|
1044
|
+
)
|
|
1045
|
+
|
|
1046
|
+
def bridge(self, id: int) -> Bridge:
|
|
1047
|
+
return self._fetchEntity(Bridge, id)
|
|
1048
|
+
|
|
1049
|
+
def bridges(self, parameter: Optional[BridgeRequestParameter] = None) -> Bridges:
|
|
1050
|
+
if parameter and not isinstance(parameter, BridgeRequestParameter):
|
|
1051
|
+
raise LOGSException(
|
|
1052
|
+
"Parameter for %s.%s must be of type %a. (Got %a)"
|
|
1053
|
+
% (
|
|
1054
|
+
type(self).__name__,
|
|
1055
|
+
self.bridges.__name__,
|
|
1056
|
+
BridgeRequestParameter.__name__,
|
|
1057
|
+
type(parameter).__name__,
|
|
1058
|
+
)
|
|
1059
|
+
)
|
|
1060
|
+
return Bridges(connection=self._connection, parameters=parameter)
|
|
1061
|
+
|
|
1062
|
+
def newDataSource(self, ref=None) -> DataSource:
|
|
1063
|
+
return self.getTypedEntityClass(None, DataSource)(
|
|
1064
|
+
ref=ref, connection=self._connection
|
|
1065
|
+
)
|
|
1066
|
+
|
|
1067
|
+
def dataSource(self, id: int) -> DataSource:
|
|
1068
|
+
return self._fetchEntity(DataSource, id)
|
|
1069
|
+
|
|
1070
|
+
def dataSources(
|
|
1071
|
+
self, parameter: Optional[DataSourceRequestParameter] = None
|
|
1072
|
+
) -> DataSources:
|
|
1073
|
+
if parameter and not isinstance(parameter, DataSourceRequestParameter):
|
|
1074
|
+
raise LOGSException(
|
|
1075
|
+
"Parameter for %s.%s must be of type %a. (Got %a)"
|
|
1076
|
+
% (
|
|
1077
|
+
type(self).__name__,
|
|
1078
|
+
self.dataSources.__name__,
|
|
1079
|
+
DataSourceRequestParameter.__name__,
|
|
1080
|
+
type(parameter).__name__,
|
|
1081
|
+
)
|
|
1082
|
+
)
|
|
1083
|
+
return DataSources(connection=self._connection, parameters=parameter)
|
|
1084
|
+
|
|
1085
|
+
def newLabNotebook(self, ref=None) -> LabNotebook:
|
|
1086
|
+
return self.getTypedEntityClass(None, LabNotebook)(
|
|
1087
|
+
ref=ref, connection=self._connection
|
|
1088
|
+
)
|
|
1089
|
+
|
|
1090
|
+
def labNotebook(self, id: int) -> LabNotebook:
|
|
1091
|
+
return self._fetchEntity(LabNotebook, id)
|
|
1092
|
+
|
|
1093
|
+
def labNotebooks(
|
|
1094
|
+
self, parameter: Optional[LabNotebookRequestParameter] = None
|
|
1095
|
+
) -> LabNotebooks:
|
|
1096
|
+
if parameter and not isinstance(parameter, LabNotebookRequestParameter):
|
|
1097
|
+
raise LOGSException(
|
|
1098
|
+
"Parameter for %s.%s must be of type %a. (Got %a)"
|
|
1099
|
+
% (
|
|
1100
|
+
type(self).__name__,
|
|
1101
|
+
self.labNotebooks.__name__,
|
|
1102
|
+
LabNotebookRequestParameter.__name__,
|
|
1103
|
+
type(parameter).__name__,
|
|
1104
|
+
)
|
|
1105
|
+
)
|
|
1106
|
+
return LabNotebooks(connection=self._connection, parameters=parameter)
|
|
1107
|
+
|
|
1108
|
+
def newLabNotebookTemplate(self, ref=None) -> LabNotebookTemplate:
|
|
1109
|
+
return self.getTypedEntityClass(None, LabNotebookTemplate)(
|
|
1110
|
+
ref=ref, connection=self._connection
|
|
1111
|
+
)
|
|
1112
|
+
|
|
1113
|
+
def labNotebookTemplate(self, id: int) -> LabNotebookTemplate:
|
|
1114
|
+
return self._fetchEntity(LabNotebookTemplate, id)
|
|
1115
|
+
|
|
1116
|
+
def labNotebookTemplates(
|
|
1117
|
+
self, parameter: Optional[LabNotebookTemplateRequestParameter] = None
|
|
1118
|
+
) -> LabNotebookTemplates:
|
|
1119
|
+
if parameter and not isinstance(parameter, LabNotebookTemplateRequestParameter):
|
|
1120
|
+
raise LOGSException(
|
|
1121
|
+
"Parameter for %s.%s must be of type %a. (Got %a)"
|
|
1122
|
+
% (
|
|
1123
|
+
type(self).__name__,
|
|
1124
|
+
self.labNotebookTemplates.__name__,
|
|
1125
|
+
LabNotebookTemplateRequestParameter.__name__,
|
|
1126
|
+
type(parameter).__name__,
|
|
1127
|
+
)
|
|
1128
|
+
)
|
|
1129
|
+
return LabNotebookTemplates(connection=self._connection, parameters=parameter)
|
|
1130
|
+
|
|
1131
|
+
def newLabNotebookExperiment(self, ref=None) -> LabNotebookExperiment:
|
|
1132
|
+
return self.getTypedEntityClass(None, LabNotebookExperiment)(
|
|
1133
|
+
ref=ref, connection=self._connection
|
|
1134
|
+
)
|
|
1135
|
+
|
|
1136
|
+
def labNotebookExperiment(self, id: int) -> LabNotebookExperiment:
|
|
1137
|
+
return self._fetchEntity(LabNotebookExperiment, id)
|
|
1138
|
+
|
|
1139
|
+
def labNotebookExperiments(
|
|
1140
|
+
self, parameter: Optional[LabNotebookExperimentRequestParameter] = None
|
|
1141
|
+
) -> LabNotebookExperiments:
|
|
1142
|
+
if parameter and not isinstance(
|
|
1143
|
+
parameter, LabNotebookExperimentRequestParameter
|
|
1144
|
+
):
|
|
1145
|
+
raise LOGSException(
|
|
1146
|
+
"Parameter for %s.%s must be of type %a. (Got %a)"
|
|
1147
|
+
% (
|
|
1148
|
+
type(self).__name__,
|
|
1149
|
+
self.labNotebookExperiments.__name__,
|
|
1150
|
+
LabNotebookExperimentRequestParameter.__name__,
|
|
1151
|
+
type(parameter).__name__,
|
|
1152
|
+
)
|
|
1153
|
+
)
|
|
1154
|
+
return LabNotebookExperiments(connection=self._connection, parameters=parameter)
|
|
1155
|
+
|
|
1156
|
+
def newLabNotebookEntry(self, ref=None) -> LabNotebookEntry:
|
|
1157
|
+
return self.getTypedEntityClass(None, LabNotebookEntry)(
|
|
1158
|
+
ref=ref, connection=self._connection
|
|
1159
|
+
)
|
|
1160
|
+
|
|
1161
|
+
def labNotebookEntry(self, id: int) -> LabNotebookEntry:
|
|
1162
|
+
return self._fetchEntity(LabNotebookEntry, id)
|
|
1163
|
+
|
|
1164
|
+
def labNotebookEntries(
|
|
1165
|
+
self, parameter: Optional[LabNotebookEntryRequestParameter] = None
|
|
1166
|
+
) -> LabNotebookEntries:
|
|
1167
|
+
if parameter and not isinstance(parameter, LabNotebookEntryRequestParameter):
|
|
1168
|
+
raise LOGSException(
|
|
1169
|
+
"Parameter for %s.%s must be of type %a. (Got %a)"
|
|
1170
|
+
% (
|
|
1171
|
+
type(self).__name__,
|
|
1172
|
+
self.labNotebookEntries.__name__,
|
|
1173
|
+
LabNotebookEntryRequestParameter.__name__,
|
|
1174
|
+
type(parameter).__name__,
|
|
1175
|
+
)
|
|
1176
|
+
)
|
|
1177
|
+
return LabNotebookEntries(connection=self._connection, parameters=parameter)
|
|
1178
|
+
|
|
1179
|
+
def newVendor(self, ref=None) -> Vendor:
|
|
1180
|
+
return self.getTypedEntityClass(None, Vendor)(
|
|
1181
|
+
ref=ref, connection=self._connection
|
|
1182
|
+
)
|
|
1183
|
+
|
|
1184
|
+
def vendor(self, id: int) -> Vendor:
|
|
1185
|
+
return self._fetchEntity(Vendor, id)
|
|
1186
|
+
|
|
1187
|
+
def vendors(self, parameter: Optional[VendorRequestParameter] = None) -> Vendors:
|
|
1188
|
+
if parameter and not isinstance(parameter, VendorRequestParameter):
|
|
1189
|
+
raise LOGSException(
|
|
1190
|
+
"Parameter for %s.%s must be of type %a. (Got %a)"
|
|
1191
|
+
% (
|
|
1192
|
+
type(self).__name__,
|
|
1193
|
+
self.vendors.__name__,
|
|
1194
|
+
VendorRequestParameter.__name__,
|
|
1195
|
+
type(parameter).__name__,
|
|
1196
|
+
)
|
|
1197
|
+
)
|
|
1198
|
+
return Vendors(connection=self._connection, parameters=parameter)
|
|
1199
|
+
|
|
1200
|
+
def newMethod(self, ref=None) -> Method:
|
|
1201
|
+
return self.getTypedEntityClass(None, Method)(
|
|
1202
|
+
ref=ref, connection=self._connection
|
|
1203
|
+
)
|
|
1204
|
+
|
|
1205
|
+
def method(self, id: int) -> Method:
|
|
1206
|
+
return self._fetchEntity(Method, id)
|
|
1207
|
+
|
|
1208
|
+
def methods(self, parameter: Optional[MethodRequestParameter] = None) -> Methods:
|
|
1209
|
+
if parameter and not isinstance(parameter, MethodRequestParameter):
|
|
1210
|
+
raise LOGSException(
|
|
1211
|
+
"Parameter for %s.%s must be of type %a. (Got %a)"
|
|
1212
|
+
% (
|
|
1213
|
+
type(self).__name__,
|
|
1214
|
+
self.methods.__name__,
|
|
1215
|
+
MethodRequestParameter.__name__,
|
|
1216
|
+
type(parameter).__name__,
|
|
1217
|
+
)
|
|
1218
|
+
)
|
|
1219
|
+
return Methods(connection=self._connection, parameters=parameter)
|
|
1220
|
+
|
|
1221
|
+
def newDataFormatInstrument(self, ref=None) -> DataFormatInstrument:
|
|
1222
|
+
return self.getTypedEntityClass(None, DataFormatInstrument)(
|
|
1223
|
+
ref=ref, connection=self._connection
|
|
1224
|
+
)
|
|
1225
|
+
|
|
1226
|
+
def dataFormatInstrument(self, id: int) -> DataFormatInstrument:
|
|
1227
|
+
return self._fetchEntity(DataFormatInstrument, id)
|
|
1228
|
+
|
|
1229
|
+
def dataFormatInstruments(
|
|
1230
|
+
self, parameter: Optional[DataFormatInstrumentRequestParameter] = None
|
|
1231
|
+
) -> DataFormatInstruments:
|
|
1232
|
+
if parameter and not isinstance(
|
|
1233
|
+
parameter, DataFormatInstrumentRequestParameter
|
|
1234
|
+
):
|
|
1235
|
+
raise LOGSException(
|
|
1236
|
+
"Parameter for %s.%s must be of type %a. (Got %a)"
|
|
1237
|
+
% (
|
|
1238
|
+
type(self).__name__,
|
|
1239
|
+
self.dataFormatInstruments.__name__,
|
|
1240
|
+
DataFormatInstrumentRequestParameter.__name__,
|
|
1241
|
+
type(parameter).__name__,
|
|
1242
|
+
)
|
|
1243
|
+
)
|
|
1244
|
+
return DataFormatInstruments(connection=self._connection, parameters=parameter)
|
|
1245
|
+
|
|
1246
|
+
def newCustomField(self, ref=None) -> CustomField:
|
|
1247
|
+
return self.getTypedEntityClass(None, CustomField)(
|
|
1248
|
+
ref=ref, connection=self._connection
|
|
1249
|
+
)
|
|
1250
|
+
|
|
1251
|
+
def customField(self, id: int) -> CustomField:
|
|
1252
|
+
return self._fetchEntity(CustomField, id)
|
|
1253
|
+
|
|
1254
|
+
def customFields(
|
|
1255
|
+
self, parameter: Optional[CustomFieldRequestParameter] = None
|
|
1256
|
+
) -> CustomFields:
|
|
1257
|
+
if parameter and not isinstance(parameter, CustomFieldRequestParameter):
|
|
1258
|
+
raise LOGSException(
|
|
1259
|
+
"Parameter for %s.%s must be of type %a. (Got %a)"
|
|
1260
|
+
% (
|
|
1261
|
+
type(self).__name__,
|
|
1262
|
+
self.customFields.__name__,
|
|
1263
|
+
CustomFieldRequestParameter.__name__,
|
|
1264
|
+
type(parameter).__name__,
|
|
1265
|
+
)
|
|
1266
|
+
)
|
|
1267
|
+
return CustomFields(connection=self._connection, parameters=parameter)
|
|
1268
|
+
|
|
1269
|
+
def newCustomType(self, ref=None) -> CustomType:
|
|
1270
|
+
return self.getTypedEntityClass(None, CustomType)(
|
|
1271
|
+
ref=ref, connection=self._connection
|
|
1272
|
+
)
|
|
1273
|
+
|
|
1274
|
+
def customType(self, id: int) -> CustomType:
|
|
1275
|
+
return self._fetchEntity(CustomType, id)
|
|
1276
|
+
|
|
1277
|
+
def customTypes(
|
|
1278
|
+
self, parameter: Optional[CustomTypeRequestParameter] = None
|
|
1279
|
+
) -> CustomTypes:
|
|
1280
|
+
if parameter and not isinstance(parameter, CustomTypeRequestParameter):
|
|
1281
|
+
raise LOGSException(
|
|
1282
|
+
"Parameter for %s.%s must be of type %a. (Got %a)"
|
|
1283
|
+
% (
|
|
1284
|
+
type(self).__name__,
|
|
1285
|
+
self.customTypes.__name__,
|
|
1286
|
+
CustomTypeRequestParameter.__name__,
|
|
1287
|
+
type(parameter).__name__,
|
|
1288
|
+
)
|
|
1289
|
+
)
|
|
1290
|
+
return CustomTypes(connection=self._connection, parameters=parameter)
|
|
1291
|
+
|
|
1292
|
+
def newInventoryItem(
|
|
1293
|
+
self, customTypeOrId: Optional[Union[CustomType, int]] = None, ref=None
|
|
1294
|
+
) -> InventoryItem:
|
|
1295
|
+
return self.getTypedEntityClass(customTypeOrId, InventoryItem)(
|
|
1296
|
+
ref=ref, connection=self._connection
|
|
1297
|
+
)
|
|
1298
|
+
|
|
1299
|
+
def inventoryItem(self, id: int) -> InventoryItem:
|
|
1300
|
+
return self._fetchEntity(InventoryItem, id)
|
|
1301
|
+
|
|
1302
|
+
def inventoryItems(
|
|
1303
|
+
self, parameter: Optional[InventoryItemRequestParameter] = None
|
|
1304
|
+
) -> InventoryItems:
|
|
1305
|
+
if parameter and not isinstance(parameter, InventoryItemRequestParameter):
|
|
1306
|
+
raise LOGSException(
|
|
1307
|
+
"Parameter for %s.%s must be of type %a. (Got %a)"
|
|
1308
|
+
% (
|
|
1309
|
+
type(self).__name__,
|
|
1310
|
+
self.inventoryItems.__name__,
|
|
1311
|
+
InventoryItemRequestParameter.__name__,
|
|
1312
|
+
type(parameter).__name__,
|
|
1313
|
+
)
|
|
1314
|
+
)
|
|
1315
|
+
return InventoryItems(connection=self._connection, parameters=parameter)
|
|
1316
|
+
|
|
1317
|
+
def newSharedContent(self, ref=None) -> SharedContent:
|
|
1318
|
+
return self.getTypedEntityClass(None, SharedContent)(
|
|
1319
|
+
ref=ref, connection=self._connection
|
|
1320
|
+
)
|
|
1321
|
+
|
|
1322
|
+
def sharedContent(self, id: int) -> SharedContent:
|
|
1323
|
+
return self._fetchEntity(SharedContent, id)
|
|
1324
|
+
|
|
1325
|
+
def sharedContents(
|
|
1326
|
+
self, parameter: Optional[SharedContentRequestParameter] = None
|
|
1327
|
+
) -> SharedContents:
|
|
1328
|
+
if parameter and not isinstance(parameter, SharedContentRequestParameter):
|
|
1329
|
+
raise LOGSException(
|
|
1330
|
+
"Parameter for %s.%s must be of type %a. (Got %a)"
|
|
1331
|
+
% (
|
|
1332
|
+
type(self).__name__,
|
|
1333
|
+
self.sharedContents.__name__,
|
|
1334
|
+
SharedContentRequestParameter.__name__,
|
|
1335
|
+
type(parameter).__name__,
|
|
1336
|
+
)
|
|
1337
|
+
)
|
|
1338
|
+
return SharedContents(connection=self._connection, parameters=parameter)
|
|
1339
|
+
|
|
1340
|
+
def entity(self, uid: str):
|
|
1341
|
+
return Entities(connection=self._connection).fetch(uid=uid)
|
|
1342
|
+
|
|
1343
|
+
def entities(
|
|
1344
|
+
self, parameter: Optional[EntitiesRequestParameter] = None
|
|
1345
|
+
) -> Entities:
|
|
1346
|
+
if parameter and not isinstance(parameter, EntitiesRequestParameter):
|
|
1347
|
+
raise LOGSException(
|
|
1348
|
+
"Parameter for %s.%s must be of type %a. (Got %a)"
|
|
1349
|
+
% (
|
|
1350
|
+
type(self).__name__,
|
|
1351
|
+
self.entities.__name__,
|
|
1352
|
+
EntitiesRequestParameter.__name__,
|
|
1353
|
+
type(parameter).__name__,
|
|
1354
|
+
)
|
|
1355
|
+
)
|
|
1356
|
+
return Entities(connection=self._connection, parameters=parameter)
|
|
1357
|
+
|
|
1358
|
+
def datasetMatching(
|
|
1359
|
+
self,
|
|
1360
|
+
files: Union[Constants.FILE_TYPE, Sequence[Constants.FILE_TYPE]],
|
|
1361
|
+
formatIds: Optional[List[str]] = None,
|
|
1362
|
+
ignoreReadErrors=False,
|
|
1363
|
+
) -> DatasetMatching:
|
|
1364
|
+
return DatasetMatching(
|
|
1365
|
+
connection=self._connection,
|
|
1366
|
+
files=files,
|
|
1367
|
+
formatIds=formatIds,
|
|
1368
|
+
ignoreReadErrors=ignoreReadErrors,
|
|
1369
|
+
)
|
|
1370
|
+
|
|
1371
|
+
def updatableDatasetFiles(
|
|
1372
|
+
self, files: Sequence[Constants.FILE_TYPE], formatIds: List[str]
|
|
1373
|
+
):
|
|
1374
|
+
datasets = Datasets(
|
|
1375
|
+
connection=self._connection, parameters=cast(DatasetRequestParameter, {})
|
|
1376
|
+
).findDatasetByFiles(files=files, formatIds=formatIds)
|
|
1377
|
+
for dataset in datasets:
|
|
1378
|
+
yield DatasetsUpdatableFiles(
|
|
1379
|
+
datasetId=dataset.logsId,
|
|
1380
|
+
files=[
|
|
1381
|
+
FileEntry(fullPath=file.fullPath, state=file.state)
|
|
1382
|
+
for file in dataset.files
|
|
1383
|
+
],
|
|
1384
|
+
)
|
|
1385
|
+
|
|
1386
|
+
@property
|
|
1387
|
+
def instanceOrigin(self) -> Origin:
|
|
1388
|
+
return Origin(name="LOGS (%s)" % self.group, url=self.url, uid=self.uid)
|
|
1389
|
+
|
|
1390
|
+
@property
|
|
1391
|
+
def url(self) -> str:
|
|
1392
|
+
return self._connection.url
|
|
1393
|
+
|
|
1394
|
+
@property
|
|
1395
|
+
def apiUrl(self) -> str:
|
|
1396
|
+
return self._connection.apiUrl
|
|
1397
|
+
|
|
1398
|
+
@property
|
|
1399
|
+
def uid(self) -> Optional[UUID]:
|
|
1400
|
+
return self._connection.metadata.uid
|
|
1401
|
+
|
|
1402
|
+
@property
|
|
1403
|
+
def group(self) -> Optional[str]:
|
|
1404
|
+
return self._connection._group
|
|
1405
|
+
|
|
1406
|
+
@property
|
|
1407
|
+
def currentUser(self) -> Person:
|
|
1408
|
+
return self._currentUser
|
|
1409
|
+
|
|
1410
|
+
@property
|
|
1411
|
+
def cacheDir(self) -> Optional[str]:
|
|
1412
|
+
return self._cacheDir
|
|
1413
|
+
|
|
1414
|
+
@cacheDir.setter
|
|
1415
|
+
def cacheDir(self, value):
|
|
1416
|
+
self._cacheDir = Tools.checkAndConvert(value, str, "cacheDir")
|
|
1417
|
+
|
|
1418
|
+
def version(self) -> Optional[str]:
|
|
1419
|
+
return self._connection.metadata.version
|
|
1420
|
+
|
|
1421
|
+
@property
|
|
1422
|
+
def metadata(self) -> ServerMetaData:
|
|
1423
|
+
return self._connection.metadata
|
|
1424
|
+
|
|
1425
|
+
|
|
1426
|
+
if __name__ == "__main__":
|
|
1427
|
+
api_key = input("Please specify api key: ")
|
|
1428
|
+
_url = input("Please specify LOGS url: ")
|
|
1429
|
+
|
|
1430
|
+
# Example input:
|
|
1431
|
+
# api_key = "8V6oQ804t2nPgGPDJIk4CuneRI5q48ERUxgEpk+YqXzX9uLuMUySycHkeXP6DefN"
|
|
1432
|
+
# url = "http://localhost:900/sandbox"
|
|
1433
|
+
|
|
1434
|
+
logs = LOGS(
|
|
1435
|
+
_url, api_key, options=LOGSOptions(showRequestUrl=True, showRequestBody=False)
|
|
1436
|
+
)
|