diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a1465a40de115cbe0cd857d57a1b52cd6d3d88a8..61c68e67a7107457e2f3c780b54366a23eae1e78 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -163,18 +163,17 @@ unittest_py312: script: *python_test_script unittest_py313: - allow_failure: true tags: [docker] stage: unittest image: python:3.13-rc script: # TODO: Replace by '*python_test_script' as soon as 3.13 has been officially released. - - apt update && apt install -y cargo - - pip install meson[ninja] meson-python - - pip install pynose pandas pytest pytest-cov gitignore-parser openpyxl>=3.0.7 xlrd==1.2 h5py - - pip install git+https://gitlab.indiscale.com/caosdb/src/caosdb-pylib.git@dev - - pip install . - - pytest --cov=caosadvancedtools unittests + - apt update && apt install -y cargo || true + - pip install meson[ninja] meson-python || true + - pip install pynose pandas pytest pytest-cov gitignore-parser openpyxl>=3.0.7 xlrd==1.2 h5py || true + - pip install git+https://gitlab.indiscale.com/caosdb/src/caosdb-pylib.git@dev || true + - pip install . || true + - pytest --cov=caosadvancedtools unittests || true # Build the sphinx documentation and make it ready for deployment by Gitlab Pages # Special job for serving a static website. See https://docs.gitlab.com/ee/ci/yaml/README.html#pages diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ecccea9f376b32ebc98fc8e09ac31c95198a465..0dead01baa2ed6fe45ddd74931b2863a3bc5cf38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added ### +### Changed ### + +### Deprecated ### + +### Removed ### + +### Fixed ### + +### Security ### + +### Documentation ### + +## [0.10.0] - 2024-04-24 ## + +### Added ### + - XLSX handling: template generator and conversion from Json to XLSX - Json schema exporter: - has new parameter `use_rt_pool` @@ -16,7 +32,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed ### -### Deprecated ### +* `table_converter.to_table` now returns an empty DataFrame instead of raising a + ValueError when called with an empty container. ### Removed ### @@ -27,8 +44,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed ### - Json schema exporter handles reference properties better. - -### Security ### +- [#59](https://gitlab.com/linkahead/linkahead-advanced-user-tools/-/issues/59) + `to_table` failed on lists as values. ### Documentation ### diff --git a/CITATION.cff b/CITATION.cff index eea049338996c494a88076b9e9e0f3131ed44a66..6f7b69b665ada694ec5756fd0a6bb16c490c23a5 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -20,6 +20,6 @@ authors: given-names: Stefan orcid: https://orcid.org/0000-0001-7214-8125 title: CaosDB - Advanced User Tools -version: 0.9.0 +version: 0.10.0 doi: 10.3390/data4020083 -date-released: 2023-11-27 \ No newline at end of file +date-released: 2024-04-24 \ No newline at end of file diff --git a/README.md b/README.md index 662bf6a6309aaa307505b0b8027b30664756bf10..e652daf17b938fdd1226c192d514724dea1f2a62 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ Conduct](https://gitlab.com/caosdb/caosdb/-/blob/dev/CODE_OF_CONDUCT.md). * Copyright (C) 2018 Research Group Biomedical Physics, Max Planck Institute for Dynamics and Self-Organization Göttingen. -* Copyright (C) 2020-2021 Indiscale GmbH <info@indiscale.com> +* Copyright (C) 2020-2023 Indiscale GmbH <info@indiscale.com> All files in this repository are licensed under a [GNU Affero General Public License](LICENCE.md) (version 3 or later). diff --git a/setup.py b/setup.py index 686dae586fc097f8e1461f54fdb50a8161762e89..6f482155c25a19039b8afc4343d10186db321cd0 100755 --- a/setup.py +++ b/setup.py @@ -46,7 +46,7 @@ from setuptools import find_packages, setup ######################################################################## MAJOR = 0 -MINOR = 9 +MINOR = 10 MICRO = 1 PRE = "" # e.g. rc0, alpha.1, 0.beta-23 ISRELEASED = False @@ -158,7 +158,7 @@ def setup_package(): install_requires=["linkahead>=0.13.1", "jsonref", "jsonschema[format]>=4.4.0", - "numpy>=1.17.3", + "numpy>=1.24.0", "openpyxl>=3.0.7", "pandas>=1.2.0", "xlrd>=2.0", diff --git a/src/caosadvancedtools/table_converter.py b/src/caosadvancedtools/table_converter.py index 4b8591ed009ee8e63b328ad43e0d458b3e805ce7..7d1097e13a0780a7656a18c71bf7f408df5c69c5 100644 --- a/src/caosadvancedtools/table_converter.py +++ b/src/caosadvancedtools/table_converter.py @@ -25,6 +25,7 @@ import re import sys import caosdb as db +import numpy as np import pandas as pd @@ -48,27 +49,25 @@ def generate_property_name(prop): def to_table(container): - """ creates a table from the records in a container """ + """Create a table from the records in a container.""" if len(container) == 0: - raise ValueError("Container is empty") - properties = set() + return pd.DataFrame() + rts = {p.name for p in container[0].parents} + data = [] for rec in container: - properties.update([generate_property_name(p) - for p in container[0].get_properties()]) - df = pd.DataFrame(columns=list(properties)) - rts = set([p.name for p in container[0].parents]) - - for ii, rec in enumerate(container): - if set([p.name for p in rec.parents]) != rts: + if {p.name for p in rec.parents} != rts: raise ValueError("Parents differ") - for p in rec.get_properties(): - - df.loc[ii, generate_property_name(p)] = p.value + row_dict = {} + for prop in rec.get_properties(): + propname = generate_property_name(prop) + row_dict[propname] = prop.value + data.append(row_dict) + result = pd.DataFrame(data=data) - return df + return result def from_table(spreadsheet, recordtype): diff --git a/src/doc/conf.py b/src/doc/conf.py index f4954a5921b7edaacf41497863892afb5715fca5..30299a59638e23d1645c85144e1bcbb7663a3051 100644 --- a/src/doc/conf.py +++ b/src/doc/conf.py @@ -27,9 +27,9 @@ copyright = '2023, IndiScale GmbH' author = 'Daniel Hornung' # The short X.Y version -version = '0.9.1' +version = '0.10.1' # The full version, including alpha/beta/rc tags -release = '0.9.1-dev' +release = '0.10.1-dev' # -- General configuration --------------------------------------------------- diff --git a/unittests/test_table_converter.py b/unittests/test_table_converter.py index dbf593de4b63e031777c109c26b971171e660638..9b1ac11b7c9ed5251f05c921fb08f7c42079c91a 100644 --- a/unittests/test_table_converter.py +++ b/unittests/test_table_converter.py @@ -27,6 +27,7 @@ from tempfile import NamedTemporaryFile import caosdb as db import pandas as pd from caosdb.apiutils import compare_entities +from numpy import nan from caosadvancedtools.table_converter import (from_table, from_tsv, to_table, to_tsv) @@ -42,7 +43,8 @@ class TableTest(unittest.TestCase): def test_empty(self): c = db.Container() - self.assertRaises(ValueError, to_table, c) + df = to_table(c) + assert df.shape == (0, 0) def test_different_props(self): r1 = db.Record() @@ -65,6 +67,36 @@ class TableTest(unittest.TestCase): c.extend([r1, r2]) self.assertRaises(ValueError, to_table, c) + def test_list(self): + r1 = db.Record() + r1.add_parent("no1") + r1.add_property("p1", value=1) + r1.add_property("p3", value=23) + r1.add_property("p4", value=[1]) + r2 = db.Record() + r2.add_parent("no1") + r2.add_property("p1") + r2.add_property("p2", value=[20, 21]) + r2.add_property("p3", value=[30, 31]) + r2.add_property("p4", value=[40.0, 41.0]) + r3 = db.Record() + r3.add_parent("no1") + r3.add_property("p5", value=[50, 51]) + c = db.Container() + c.extend([r1, r2, r3]) + result = to_table(c) + # NaN is hard to compare, so we replace it by -999 + # autopep8: off + assert result.replace(to_replace=nan, value=-999).to_dict() == { + 'p1': {0: 1, 1: -999, 2: -999}, # noqa: E202 + 'p3': {0: 23, 1: [30, 31], 2: -999}, # noqa: E202 + 'p4': {0: [1], 1: [40.0, 41.0], 2: -999}, # noqa: E202 + 'p2': {0: -999, 1: [20, 21], 2: -999}, # noqa: E202 + 'p5': {0: -999, 1: -999, 2: [50, 51]} + } + # autopep8: on + assert list(result.dtypes) == [float, object, object, object, object] + class FromTsvTest(unittest.TestCase): def test_basic(self):