Skip to content

Commit c9749f3

Browse files
authored
Merge pull request #43 from brain-bican/schema_title
CAS json export list values fixes
2 parents 10ede93 + 70d0950 commit c9749f3

File tree

4 files changed

+86
-4
lines changed

4 files changed

+86
-4
lines changed

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
setup(
1010
name="tdta",
11-
version="0.1.0.dev13",
11+
version="0.1.0.dev14",
1212
description="The aim of this project is to provide taxonomy development tools custom actions.",
1313
long_description=README,
1414
long_description_content_type="text/markdown",

src/tdta/tdt_export.py

+25-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
import sqlite3
33
import ast
44
import json
5+
import typing
6+
from typing import Union, List
57
from contextlib import closing
68
from pathlib import Path
79
from datetime import datetime
@@ -193,6 +195,7 @@ def parse_review_data(cta, sqlite_db, table_name):
193195
else:
194196
filtered_annotations[0].reviews = [ar]
195197

198+
196199
def get_table_names(sqlite_db):
197200
"""
198201
Queries 'table' table to get all CAS related table names
@@ -222,7 +225,7 @@ def auto_fill_object_from_row(obj, columns, row):
222225
if hasattr(obj, column):
223226
value = row[columns.index(column)]
224227
if value:
225-
if isinstance(type(getattr(obj, column)), list):
228+
if is_list(obj, column):
226229
if value.strip().startswith("\"") and value.strip().endswith("\""):
227230
value = value.strip()[1:-1].strip()
228231
elif value.strip().startswith("'") and value.strip().endswith("'"):
@@ -245,3 +248,24 @@ def auto_fill_object_from_row(obj, columns, row):
245248
if msg["column"] in columns:
246249
setattr(obj, msg["column"], msg["value"])
247250

251+
252+
def is_list(obj, field):
253+
"""
254+
Checks if the field of the object is a list or has list typing.
255+
Parameters:
256+
obj: object
257+
field: field name
258+
Returns: True if the field is a list or has list typing, False otherwise
259+
"""
260+
is_list_instance = isinstance(getattr(obj, field), list)
261+
type_hint = typing.get_type_hints(obj).get(field)
262+
if type_hint:
263+
# is List
264+
is_list_typing = typing.get_origin(type_hint) is list
265+
# is Optional[List] or is Optional[List[str]]
266+
is_optional_list_typed = typing.get_origin(type_hint) is Union and any(typing.get_origin(e) is list for e in typing.get_args(type_hint))
267+
268+
is_list_typing = is_list_typing or is_optional_list_typed
269+
else:
270+
is_list_typing = False
271+
return is_list_instance or is_list_typing

src/test/tdt_export_test.py

+60-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import unittest
22
import os
3-
import shutil
4-
from tdta.tdt_export import export_cas_data
3+
from typing import List, Optional
4+
from tdta.tdt_export import export_cas_data, is_list
55

66
TEST_DATA_FOLDER = os.path.join(os.path.dirname(os.path.realpath(__file__)), "./test_data/")
77
TEST_OUTPUT = os.path.join(TEST_DATA_FOLDER, "cas_output.json")
88
TEST_DB = os.path.join(TEST_DATA_FOLDER, "nanobot.db")
9+
TEST_DB_SILETTI = os.path.join(TEST_DATA_FOLDER, "nanobot_siletti_nn.db")
910

1011

1112
class CASExportTests(unittest.TestCase):
@@ -63,3 +64,60 @@ def test_export(self):
6364
# self.assertEqual('incorrect', test_annotation["reviews"][0]['explanation'])
6465
# print(test_annotation["reviews"][0]['datestamp'])
6566
# self.assertEqual('2024-05-29T08:10:11.126Z', test_annotation["reviews"][0]['datestamp'])
67+
68+
def test_export_siletti_nn(self):
69+
cas = export_cas_data(TEST_DB_SILETTI, TEST_OUTPUT, TEST_DATA_FOLDER)
70+
self.assertTrue(os.path.exists(TEST_OUTPUT))
71+
72+
self.assertTrue(cas)
73+
result = cas.to_dict()
74+
75+
self.assertTrue("annotations" in result)
76+
test_annotation = [x for x in result["annotations"] if x["cell_label"] == "VendC_15"][0]
77+
self.assertEqual("CS202210140_16", test_annotation["cell_set_accession"])
78+
self.assertTrue("marker_gene_evidence" in test_annotation)
79+
print(test_annotation["marker_gene_evidence"])
80+
self.assertEqual(4, len(test_annotation["marker_gene_evidence"]))
81+
self.assertTrue("FLT1" in test_annotation["marker_gene_evidence"])
82+
self.assertTrue("CLDN5" in test_annotation["marker_gene_evidence"])
83+
self.assertTrue("PECAM1" in test_annotation["marker_gene_evidence"])
84+
self.assertTrue("MFSD2A" in test_annotation["marker_gene_evidence"])
85+
86+
def test_list_instance(self):
87+
samples = AttributeSamples()
88+
89+
import inspect
90+
members = inspect.getmembers(samples)
91+
92+
for name, value in members:
93+
if not name.startswith('__'): # Skip built-in attributes
94+
print(name, value, type(value))
95+
96+
self.assertTrue(is_list(samples, "field1"))
97+
self.assertTrue(is_list(samples, "field2"))
98+
self.assertTrue(is_list(samples, "field3"))
99+
self.assertTrue(is_list(samples, "field4"))
100+
self.assertTrue(is_list(samples, "field5"))
101+
self.assertTrue(is_list(samples, "field6"))
102+
self.assertTrue(is_list(samples, "field7"))
103+
104+
self.assertFalse(is_list(samples, "field8"))
105+
self.assertFalse(is_list(samples, "field9"))
106+
self.assertFalse(is_list(samples, "field10"))
107+
108+
109+
class AttributeSamples:
110+
111+
field1 = list()
112+
field2: Optional[List[str]] = None
113+
field3: List[str] = []
114+
field4: List[str] = ["a", "b", "c"]
115+
field5: Optional[List[str]] = ["a", "b", "c"]
116+
field6: Optional[List[int]] = None
117+
field7: List = None
118+
119+
field8: str = None
120+
field9: Optional[str] = None
121+
field10 = None
122+
123+
284 KB
Binary file not shown.

0 commit comments

Comments
 (0)