diff --git a/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/common/EntityRetriever.java b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/common/EntityRetriever.java index 916481ae4e87baeb62662592d6ab5c465554a254..e06ea3716ef0158b652cd2088a1e1a2018a31d9d 100644 --- a/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/common/EntityRetriever.java +++ b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/common/EntityRetriever.java @@ -133,6 +133,7 @@ public class EntityRetriever implements IEntityRetriever Node<Project> prjNode = new Node<Project>(project); graph.addNode(prjNode); addExperiments(prjNode); + addSamplesForProject(prjNode); } // add space samples @@ -164,8 +165,11 @@ public class EntityRetriever implements IEntityRetriever private void addSpaceSamples(String spaceCode) { + // Add samples that are connected with a space only (i.e. have project == null and experiment == null). + SampleSearchCriteria criteria = new SampleSearchCriteria(); criteria.withSpace().withCode().thatEquals(spaceCode); + criteria.withoutProject(); criteria.withoutExperiment(); criteria.withAndOperator(); @@ -195,6 +199,8 @@ public class EntityRetriever implements IEntityRetriever { for (Sample sample : expNode.getEntity().getSamples()) { + // Add samples that are connected with an experiment and optionally a project. + Node<Sample> sampleNode = new Node<Sample>(sample); graph.addEdge(expNode, sampleNode, new Edge(CONNECTION)); @@ -203,6 +209,23 @@ public class EntityRetriever implements IEntityRetriever } } + private void addSamplesForProject(Node<Project> prjNode) + { + for (Sample sample : prjNode.getEntity().getSamples()) + { + // Add samples that are connected with a project only (i.e. have experiment == null). + + if (sample.getExperiment() == null) + { + Node<Sample> sampleNode = new Node<Sample>(sample); + graph.addEdge(prjNode, sampleNode, new Edge(CONNECTION)); + + addDataSetsForSample(sampleNode); + addChildAndComponentSamples(sampleNode); + } + } + } + private void addDataSetsForExperiment(Node<Experiment> expNode) { for (DataSet dataSet : expNode.getEntity().getDataSets()) @@ -339,6 +362,7 @@ public class EntityRetriever implements IEntityRetriever fo.withSpace(); fo.withAttachments(); fo.withExperimentsUsing(createExperimentFetchOptions()); + fo.withSamplesUsing(createSampleFetchOptions()); return fo; } @@ -361,6 +385,7 @@ public class EntityRetriever implements IEntityRetriever fo.withDataSets(); fo.withType(); fo.withExperiment(); + fo.withProject(); fo.withSpace(); fo.withAttachments(); fo.withChildrenUsing(fo); diff --git a/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/common/entitygraph/Node.java b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/common/entitygraph/Node.java index 0468aba9952ee15d0961387a00cfa2b8d0d384e7..45e219ceb0198a89983009ad52074c0c79e1dfc6 100644 --- a/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/common/entitygraph/Node.java +++ b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/common/entitygraph/Node.java @@ -142,7 +142,9 @@ public class Node<T extends IModificationDateHolder & IModifierHolder & IRegistr { return null; } - return ((IProjectHolder) entity).getProject().getCode(); + + Project project = ((IProjectHolder) entity).getProject(); + return project != null ? project.getCode() : null; } public Sample getSampleOrNull() diff --git a/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/harvester/synchronizer/MasterDataParser.java b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/harvester/synchronizer/MasterDataParser.java index 551fc823ebeb9dc906d4ae145d4ecafc2aa7457d..74cf84519b789a979573c04cd6c8047e5bb7533e 100644 --- a/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/harvester/synchronizer/MasterDataParser.java +++ b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/harvester/synchronizer/MasterDataParser.java @@ -190,7 +190,7 @@ public class MasterDataParser String entityKind = getAttribute(pluginElement, "entityKind").trim(); plugin.setScriptType(ScriptType.valueOf(getAttribute(pluginElement, "type"))); plugin.setPluginType(PluginType.JYTHON); - plugin.setEntityKind(entityKind.equals("") ? null : new EntityKind[] { EntityKind.valueOf(entityKind) }); + plugin.setEntityKind((entityKind.equals("") || entityKind.equals("All")) ? null : new EntityKind[] { EntityKind.valueOf(entityKind) }); plugin.setScript(pluginElement.getTextContent()); validationPlugins.put(plugin.getName(), plugin); } diff --git a/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/harvester/synchronizer/ResourceListParser.java b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/harvester/synchronizer/ResourceListParser.java index e1fa5a6b8882e5a8a0b949e4269c9ecc524c0a6e..c30c27c08ae014662223098b2f345b94e5f4e494 100644 --- a/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/harvester/synchronizer/ResourceListParser.java +++ b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/harvester/synchronizer/ResourceListParser.java @@ -183,8 +183,7 @@ public class ResourceListParser if (uri.endsWith("MASTER_DATA/MASTER_DATA/M")) { parseMasterData(doc, xpath, uri); - } - else if (uri.endsWith("/M")) + } else if (uri.endsWith("/M")) { list.add(uri); } @@ -218,20 +217,16 @@ public class ResourceListParser if (SyncEntityKind.PROJECT.getLabel().equals(entityKind)) { parseProjectMetaData(xpath, extractPermIdFromURI(uri), xdNode, lastModificationDate); - } - else if (SyncEntityKind.EXPERIMENT.getLabel().equals(entityKind)) + } else if (SyncEntityKind.EXPERIMENT.getLabel().equals(entityKind)) { parseExperimentMetaData(xpath, extractPermIdFromURI(uri), xdNode, lastModificationDate); - } - else if (SyncEntityKind.SAMPLE.getLabel().equals(entityKind)) + } else if (SyncEntityKind.SAMPLE.getLabel().equals(entityKind)) { parseSampleMetaData(xpath, extractPermIdFromURI(uri), xdNode, lastModificationDate); - } - else if (SyncEntityKind.DATA_SET.getLabel().equals(entityKind)) + } else if (SyncEntityKind.DATA_SET.getLabel().equals(entityKind)) { parseDataSetMetaData(xpath, extractDataSetCodeFromURI(uri), xdNode, lastModificationDate); - } - else if (SyncEntityKind.MATERIAL.getLabel().equals(entityKind)) + } else if (SyncEntityKind.MATERIAL.getLabel().equals(entityKind)) { parseMaterialMetaData(xpath, extractMaterialCodeFromURI(uri), xdNode, lastModificationDate); } @@ -287,13 +282,11 @@ public class ResourceListParser { ds = new NewContainerDataSet(); ds.setDataSetKind(ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetKind.CONTAINER); - } - else if (dsKind.equals(DataSetKind.PHYSICAL.toString())) + } else if (dsKind.equals(DataSetKind.PHYSICAL.toString())) { ds = new NewExternalData(); ds.setDataSetKind(ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetKind.PHYSICAL); - } - else + } else { throw new IllegalArgumentException(dsKind + " data sets are currently not supported"); } @@ -318,13 +311,11 @@ public class ResourceListParser if (nullAllowed == false) { throw new IllegalArgumentException(attrName + " cannot be empty in Resource List"); - } - else + } else { return null; } - } - else + } else { return val.trim(); } @@ -349,7 +340,16 @@ public class ResourceListParser SampleIdentifier sampleIdentifier = SampleIdentifierFactory.parse(sampleIdentifierStr); SpaceIdentifier spaceLevel = sampleIdentifier.getSpaceLevel(); String originalSpaceCode = spaceLevel.getSpaceCode(); - return new SampleIdentifier(new SpaceIdentifier(nameTranslator.translate(originalSpaceCode)), sampleIdentifier.getSampleCode()); + SpaceIdentifier translatedSpaceIdentifier = new SpaceIdentifier(nameTranslator.translate(originalSpaceCode)); + + if (sampleIdentifier.isProjectLevel()) + { + return new SampleIdentifier(new ProjectIdentifier(translatedSpaceIdentifier, sampleIdentifier.getProjectLevel().getProjectCode()), + sampleIdentifier.getSampleCode()); + } else + { + return new SampleIdentifier(translatedSpaceIdentifier, sampleIdentifier.getSampleCode()); + } } private ExperimentIdentifier getExperimentIdentifier(String experimentIdentifierStr) @@ -392,14 +392,20 @@ public class ResourceListParser return new ProjectIdentifier(createSpaceIdentifier(space), code); } - private SampleIdentifier createSampleIdentifier(String code, String space) + private SampleIdentifier createSampleIdentifier(String code, String project, String space) { if (space == null) { return new SampleIdentifier(nameTranslator.translate(code)); + } else if (project == null) + { + SpaceIdentifier spaceIdentifier = createSpaceIdentifier(space); + return new SampleIdentifier(spaceIdentifier, code); + } else + { + ProjectIdentifier projectIdentifier = createProjectIdentifier(project, space); + return new SampleIdentifier(projectIdentifier, code); } - SpaceIdentifier spaceIdentifier = createSpaceIdentifier(space); - return new SampleIdentifier(spaceIdentifier, code); } private SpaceIdentifier createSpaceIdentifier(String space) @@ -499,7 +505,7 @@ public class ResourceListParser val = nameTranslator.translate(val); val = translateMaterialIdentifier(val); } - + } propertyType.setCode(translatedCode); property.setPropertyType(propertyType); @@ -507,7 +513,8 @@ public class ResourceListParser return property; } - private String translateMaterialIdentifier(String value) { + private String translateMaterialIdentifier(String value) + { if (StringUtils.isBlank(value)) { return null; @@ -526,6 +533,7 @@ public class ResourceListParser } return new MaterialIdentifier(code, typeCode).toString(); } + private void parseExperimentMetaData(XPath xpath, String permId, Node xdNode, Date lastModificationDate) { String code = extractCode(xdNode); @@ -547,14 +555,21 @@ public class ResourceListParser String code = extractCode(xdNode); String type = extractType(xdNode); String experiment = extractAttribute(xdNode, "experiment", true); + String project = extractAttribute(xdNode, "project", true); String space = extractSpace(xdNode, true); SampleType sampleType = new SampleType(); sampleType.setCode(type); - - SampleIdentifier identifier = createSampleIdentifier(code, space); + + if (false == StringUtils.isBlank(project) && StringUtils.isBlank(space)) + { + throw new IllegalArgumentException("Sample with perm id '" + permId + "' has 'project' attribute specified but 'space' attribute empty"); + } + + SampleIdentifier identifier = createSampleIdentifier(code, project, space); String expIdentifier = null; ExperimentIdentifier experimentIdentifier = getExperimentIdentifier(experiment); - if (experimentIdentifier != null) { + if (experimentIdentifier != null) + { expIdentifier = experimentIdentifier.toString(); } NewSample newSample = new NewSample(identifier.toString(), sampleType, null, null, @@ -565,6 +580,10 @@ public class ResourceListParser { newSample.setDefaultSpaceIdentifier(null); } + if (space != null && project != null) + { + newSample.setProjectIdentifier(createProjectIdentifier(project, space).toString()); + } IncomingSample incomingSample = data.new IncomingSample(newSample, lastModificationDate); data.getSamplesToProcess().put(permId, incomingSample); incomingSample.setHasAttachments(hasAttachments(xpath, xdNode)); @@ -618,4 +637,3 @@ public class ResourceListParser // System.out.print(url_node.item(ji).getNodeName() + ":" + url_node.item(ji).getAttributes().getNamedItem("kind")); // System.out.println(); // } - diff --git a/integration-tests/source/systemtest/testcase.py b/integration-tests/source/systemtest/testcase.py index 46f88c94aa3bacbaba1dc152bdf25905666041d8..98057ed32855f9c67840bcbaddf79fe05bc985e7 100644 --- a/integration-tests/source/systemtest/testcase.py +++ b/integration-tests/source/systemtest/testcase.py @@ -500,6 +500,9 @@ class OpenbisController(_Controller): def setDssMaxHeapSize(self, maxHeapSize): self._setMaxHeapSize("datastore_server/etc/datastore_server.conf", maxHeapSize) + def enableProjectSamples(self): + self.asProperties['project-samples-enabled'] = "true" + def assertFileExist(self, pathRelativeToInstallPath): """ Asserts that the specified path (relative to the installation path) exists. diff --git a/integration-tests/templates/test_openbis_sync/core-plugins/openbis1/1/dss/drop-boxes/entity-reg/dropbox.py b/integration-tests/templates/test_openbis_sync/core-plugins/openbis1/1/dss/drop-boxes/entity-reg/dropbox.py index 40ffc6e2d65caf072711bbc061a818c5e1fd1998..444da915f9977ea78e1967e1351798ffe01cdaff 100644 --- a/integration-tests/templates/test_openbis_sync/core-plugins/openbis1/1/dss/drop-boxes/entity-reg/dropbox.py +++ b/integration-tests/templates/test_openbis_sync/core-plugins/openbis1/1/dss/drop-boxes/entity-reg/dropbox.py @@ -9,9 +9,9 @@ def process(transaction): spaceCode = "SYNC" p1 = transaction.createNewProject("/%s/P1" % spaceCode) exp1 = transaction.createNewExperiment(p1.getProjectIdentifier() + "/E1", "UNKNOWN") - container_smp = transaction.createNewSample("/%s/S1" % spaceCode, "UNKNOWN") + container_smp = transaction.createNewSample(p1.getProjectIdentifier() + "/S1", "UNKNOWN") container_smp.setExperiment(exp1) - component_samp = transaction.createNewSample("/%s/S2" % spaceCode, "UNKNOWN") + component_samp = transaction.createNewSample(p1.getProjectIdentifier() + "/S2", "UNKNOWN") component_samp.setContainer(container_smp) component_samp.setExperiment(exp1) diff --git a/integration-tests/templates/test_openbis_sync/openbis_test_openbis_sync_openbis1.sql b/integration-tests/templates/test_openbis_sync/openbis_test_openbis_sync_openbis1.sql index b6a61ef663522be2d35a2945a346df9d1edb9a84..b55da16f6110a504198363e951ba3148a92bcb3b 100644 --- a/integration-tests/templates/test_openbis_sync/openbis_test_openbis_sync_openbis1.sql +++ b/integration-tests/templates/test_openbis_sync/openbis_test_openbis_sync_openbis1.sql @@ -3181,7 +3181,7 @@ SELECT pg_catalog.setval('experiment_code_seq', 1, false); -- Name: experiment_id_seq; Type: SEQUENCE SET; Schema: public; Owner: - -- -SELECT pg_catalog.setval('experiment_id_seq', 2, true); +SELECT pg_catalog.setval('experiment_id_seq', 3, true); -- @@ -3261,6 +3261,7 @@ COPY experiment_types (id, code, description, modification_timestamp, validation COPY experiments_all (id, perm_id, code, exty_id, pers_id_registerer, registration_timestamp, modification_timestamp, proj_id, del_id, orig_del, is_public, pers_id_modifier, version) FROM stdin; 1 20161010123907442-1 DEFAULT 1 1 2016-10-10 12:39:07.442524+02 2016-10-10 12:39:07.442524+02 1 \N \N f \N 0 2 20161010125004951-1 DEMO-EXP-HCS 2 3 2016-10-10 12:50:06.971812+02 2016-10-10 12:50:06.971812+02 2 \N \N f 3 0 +3 20180901153109866-10 SYNC_EXPERIMENT 1 2 2018-09-01 15:31:09.866062+02 2018-09-01 15:31:59.013934+02 3 \N \N f 2 0 \. @@ -3496,7 +3497,7 @@ SELECT pg_catalog.setval('operation_executions_id_seq', 1, false); -- Name: perm_id_seq; Type: SEQUENCE SET; Schema: public; Owner: - -- -SELECT pg_catalog.setval('perm_id_seq', 8, true); +SELECT pg_catalog.setval('perm_id_seq', 14, true); -- @@ -3539,7 +3540,7 @@ SELECT pg_catalog.setval('post_registration_dataset_queue_id_seq', 3, true); -- Name: project_id_seq; Type: SEQUENCE SET; Schema: public; Owner: - -- -SELECT pg_catalog.setval('project_id_seq', 2, true); +SELECT pg_catalog.setval('project_id_seq', 3, true); -- @@ -3568,6 +3569,7 @@ SELECT pg_catalog.setval('project_relationships_history_id_seq', 4, true); COPY projects (id, perm_id, code, space_id, pers_id_leader, description, pers_id_registerer, registration_timestamp, modification_timestamp, pers_id_modifier, version) FROM stdin; 1 20161010123907442-1 DEFAULT 1 \N \N 1 2016-10-10 12:39:07.442524+02 2016-10-10 12:39:07.442524+02 \N 0 2 20161010125006971-8 TEST-PROJECT 2 \N A demo project 3 2016-10-10 12:50:06.971812+02 2016-10-10 12:50:06.971812+02 3 0 +3 20180901153055950-9 SYNC_PROJECT 3 \N \N 2 2018-09-01 15:30:55.950159+02 2018-09-01 15:31:59.013934+02 2 0 \. @@ -3660,7 +3662,7 @@ SELECT pg_catalog.setval('sample_code_seq', 1, false); -- Name: sample_id_seq; Type: SEQUENCE SET; Schema: public; Owner: - -- -SELECT pg_catalog.setval('sample_id_seq', 2, true); +SELECT pg_catalog.setval('sample_id_seq', 12, true); -- @@ -3757,8 +3759,12 @@ COPY sample_types (id, code, description, is_listable, generated_from_depth, par -- COPY samples_all (id, perm_id, code, expe_id, saty_id, registration_timestamp, modification_timestamp, pers_id_registerer, del_id, orig_del, space_id, samp_id_part_of, pers_id_modifier, code_unique_check, subcode_unique_check, version, proj_id) FROM stdin; -1 20161010123907442-1 DEFAULT 1 1 2016-10-10 12:39:07.442524+02 2016-10-10 12:39:07.442524+02 1 \N \N 1 \N \N DEFAULT,-1,-1,1 \N 0 \N -2 20161010125004966-2 PLATE 2 4 2016-10-10 12:50:06.971812+02 2016-10-10 12:50:06.971812+02 3 \N \N 2 \N 3 PLATE,-1,-1,2 \N 0 \N +1 20161010123907442-1 DEFAULT 1 1 2016-10-10 12:39:07.442524+02 2016-10-10 12:39:07.442524+02 1 \N \N 1 \N \N DEFAULT,-1,1,1 \N 0 1 +2 20161010125004966-2 PLATE 2 4 2016-10-10 12:50:06.971812+02 2016-10-10 12:50:06.971812+02 3 \N \N 2 \N 3 PLATE,-1,2,2 \N 0 2 +9 20180901153134072-11 SYNC_SPACE_SAMPLE \N 1 2018-09-01 15:31:34.072585+02 2018-09-01 15:31:34.072585+02 2 \N \N 3 \N 2 SYNC_SPACE_SAMPLE,-1,-1,3 \N 0 \N +10 20180901153144176-12 SYNC_PROJECT_SAMPLE \N 1 2018-09-01 15:31:44.176582+02 2018-09-01 15:31:44.176582+02 2 \N \N 3 \N 2 SYNC_PROJECT_SAMPLE,-1,3,3 \N 0 3 +11 20180901153159013-13 SYNC_EXPERIMENT_SAMPLE 3 1 2018-09-01 15:31:59.013934+02 2018-09-01 15:31:59.013934+02 2 \N \N 3 \N 2 SYNC_EXPERIMENT_SAMPLE,-1,3,3 \N 0 3 +12 20180901153310961-14 SHARED_SAMPLE \N 1 2018-09-01 15:33:10.961996+02 2018-09-01 15:33:10.961996+02 2 \N \N \N \N 2 SHARED_SAMPLE,-1,-1,-1 \N 0 \N \. diff --git a/integration-tests/test_openbis_sync.py b/integration-tests/test_openbis_sync.py index 2d5c3850b9ee64b485cc0979475d81d0da7143c1..a8604bd721b0c92ab420cc19172b4a1a8ba8fd98 100755 --- a/integration-tests/test_openbis_sync.py +++ b/integration-tests/test_openbis_sync.py @@ -38,6 +38,7 @@ class TestCase(systemtest.testcase.TestCase): '''create data source openbis (openbis1)''' self.installOpenbis(instanceName ='openbis1', technologies = ['screening']) openbis1 = self.createOpenbisController('openbis1') + openbis1.enableProjectSamples() openbis1.setDummyAuthentication() openbis1.setDataStoreServerUsername('etlserver1') openbis1.setDataStoreServerProperty("host-address", "https://localhost") @@ -63,6 +64,7 @@ class TestCase(systemtest.testcase.TestCase): '''create harvester openbis (openbis2)''' self.installOpenbis(instanceName ='openbis2', technologies = ['screening', 'proteomics']) openbis2 = self.createOpenbisController('openbis2', port = openbis2_port) + openbis2.enableProjectSamples() openbis2.setDummyAuthentication() openbis2.setDataStoreServerUsername('etlserver2') openbis2.setDataStoreServerPort(openbis2_dss_port) @@ -113,6 +115,7 @@ class TestCase(systemtest.testcase.TestCase): openbis2_dss_port = '8446' openbis1=self.createOpenbisController(instanceName = 'openbis1', dropDatabases=False) + openbis1.enableProjectSamples() openbis1.setDummyAuthentication() self.installDataSourcePlugin(openbis1, openbis1_dss_port) @@ -133,6 +136,7 @@ class TestCase(systemtest.testcase.TestCase): # openbis1.dropAndWait("ENTITY_REGISTRATION", "openbis-sync-entity-reg") openbis2 = self.createOpenbisController(instanceName = 'openbis2', port = openbis2_port, dropDatabases=False) + openbis2.enableProjectSamples() openbis2.setDataStoreServerPort(openbis2_dss_port) openbis2.setOpenbisPortDataStoreServer(openbis2_port) openbis2.setDataStoreServerProperty("host-address", "https://localhost") diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/sample/Sample.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/sample/Sample.java index 1bef10b2218321f49cb247db70a3fec53e4d0177..134a4500a4f011bd85a31e61ace6fcff34db5e68 100644 --- a/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/sample/Sample.java +++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/sample/Sample.java @@ -27,6 +27,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.interfaces.IModificationD import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.interfaces.IModifierHolder; import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.interfaces.IParentChildrenHolder; import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.interfaces.IPermIdHolder; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.interfaces.IProjectHolder; import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.interfaces.IPropertiesHolder; import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.interfaces.IRegistrationDateHolder; import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.interfaces.IRegistratorHolder; @@ -60,7 +61,7 @@ import java.util.Set; * Class automatically generated with DtoGenerator */ @JsonObject("as.dto.sample.Sample") -public class Sample implements Serializable, IAttachmentsHolder, ICodeHolder, IDataSetsHolder, IEntityTypeHolder, IExperimentHolder, IIdentifierHolder, IMaterialPropertiesHolder, IModificationDateHolder, IModifierHolder, IParentChildrenHolder<Sample>, IPermIdHolder, IPropertiesHolder, IRegistrationDateHolder, IRegistratorHolder, ISpaceHolder, ITagsHolder +public class Sample implements Serializable, IAttachmentsHolder, ICodeHolder, IDataSetsHolder, IEntityTypeHolder, IExperimentHolder, IIdentifierHolder, IMaterialPropertiesHolder, IModificationDateHolder, IModifierHolder, IParentChildrenHolder<Sample>, IPermIdHolder, IProjectHolder, IPropertiesHolder, IRegistrationDateHolder, IRegistratorHolder, ISpaceHolder, ITagsHolder { private static final long serialVersionUID = 1L; @@ -236,6 +237,7 @@ public class Sample implements Serializable, IAttachmentsHolder, ICodeHolder, ID // Method automatically generated with DtoGenerator @JsonIgnore + @Override public Project getProject() { if (getFetchOptions() != null && getFetchOptions().hasProject()) diff --git a/pybis/src/python/HOWTO_UPLOAD_TO_PYPI b/pybis/src/python/HOWTO_UPLOAD_TO_PYPI new file mode 100644 index 0000000000000000000000000000000000000000..ce852ad73ea5793e70c0a3c0331cefff0d373ed1 --- /dev/null +++ b/pybis/src/python/HOWTO_UPLOAD_TO_PYPI @@ -0,0 +1,15 @@ +# create a python2 / python 3 universal distribution +python setup.py bdist_wheel --universal + +# create a pure python distribution, which only works for a specific python version +python setup.py bdist_wheel + +# create a source-distribution +python setup.py sdist + +# see distributions +ls -la dist/ + +# upload distribution(s) to pypi +twine upload dist/* + diff --git a/pybis/src/python/dist/PyBIS-1.6.7.tar.gz b/pybis/src/python/dist/PyBIS-1.6.7.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..87450e47cc59ec49207dbd9aeb369c9ddb3c16b5 Binary files /dev/null and b/pybis/src/python/dist/PyBIS-1.6.7.tar.gz differ diff --git a/pybis/src/python/pybis/__init__.py b/pybis/src/python/pybis/__init__.py index 6ff689482a5d6c51cdc7a8550c2e4d39d9c2491e..80b8b723b85e0929352d6dde571590a859c97c69 100644 --- a/pybis/src/python/pybis/__init__.py +++ b/pybis/src/python/pybis/__init__.py @@ -1,6 +1,6 @@ __author__ = 'Swen Vermeul' __email__ = 'swen@ethz.ch' -__version__ = '1.6.5' +__version__ = '1.6.7' from . import pybis from .pybis import Openbis diff --git a/pybis/src/python/pybis/semantic_annotation.py b/pybis/src/python/pybis/semantic_annotation.py index 657ca773f80bfe2fbd42c3377c62a82dd41fb30e..73d5152c9e1c85173a5f4ad37a29687983994043 100644 --- a/pybis/src/python/pybis/semantic_annotation.py +++ b/pybis/src/python/pybis/semantic_annotation.py @@ -116,6 +116,33 @@ class SemanticAnnotation(): self._openbis.delete_entity(entity='SemanticAnnotation', id=self.permId, reason=reason) if VERBOSE: print("Semantic annotation successfully deleted.") + def _repr_html_(self): + attrs = [ 'permId', 'entityType', 'propertyType', 'predicateOntologyId', 'predicateOntologyVersion', 'predicateAccessionId', 'descriptorOntologyId', 'descriptorOntologyVersion', 'descriptorAccessionId', 'creationDate', + ] + + html = """ + <table border="1" class="dataframe"> + <thead> + <tr style="text-align: right;"> + <th>attribute</th> + <th>value</th> + </tr> + </thead> + <tbody> + """ + + for attr in attrs: + html += "<tr> <td>{}</td> <td>{}</td> </tr>".format( + attr, getattr(self, attr, '') + ) + + html += """ + </tbody> + </table> + """ + return html + + def __repr__(self): headers = ['attribute', 'value'] lines = [] diff --git a/pybis/src/python/setup.py b/pybis/src/python/setup.py index 3c4803574588c1c7d397833dcb1f201bbecc7ec4..99dce1042463091561987bf5b0cb895d2d1d616d 100644 --- a/pybis/src/python/setup.py +++ b/pybis/src/python/setup.py @@ -9,7 +9,7 @@ from setuptools import setup setup( name='PyBIS', - version= '1.6.5', + version= '1.6.7', description='openBIS connection and interaction, optimized for using with Jupyter', url='https://sissource.ethz.ch/sispub/pybis/', author='Swen Vermeul | ID SIS | ETH Zürich',