Repository: single-cell-data/TileDB-SOMA (language: python)

Issue:
[r] `set_metadata` method allows unnamed list
## Describe the bug

`set_metadata` method allows  unnamed list.

https://github.com/single-cell-data/TileDB-SOMA/blob/566d88926589241b866c93401f1d167864653c40/apis/r/R/TileDBArray.R#L103-L105

The root cause:

https://github.com/single-cell-data/TileDB-SOMA/blob/566d88926589241b866c93401f1d167864653c40/apis/r/R/utils-assertions.R#L19-L20

Here's the reprex:
```r
is_named_list(list(a = "foo", "hi"))
[1] TRUE
```

Setting  `allow_empty` to `FALSE` for `is_named` assertion, then we're good:
```R
is_named_list <- function(x) {
  is.list(x) && is_named(x, allow_empty = FALSE)
}

# with `allow_empty = FALSE`
is_named_list(list(a = "foo", "hi"))
[1] FALSE

is_named_list(list(a = "foo", b = "hi"))
[1] TRUE
```


[r] `set_metadata` method allows unnamed list
## Describe the bug

`set_metadata` method allows  unnamed list.

https://github.com/single-cell-data/TileDB-SOMA/blob/566d88926589241b866c93401f1d167864653c40/apis/r/R/TileDBArray.R#L103-L105

The root cause:

https://github.com/single-cell-data/TileDB-SOMA/blob/566d88926589241b866c93401f1d167864653c40/apis/r/R/utils-assertions.R#L19-L20

Here's the reprex:
```r
is_named_list(list(a = "foo", "hi"))
[1] TRUE
```

Setting  `allow_empty` to `FALSE` for `is_named` assertion, then we're good:
```R
is_named_list <- function(x) {
  is.list(x) && is_named(x, allow_empty = FALSE)
}

# with `allow_empty = FALSE`
is_named_list(list(a = "foo", "hi"))
[1] FALSE

is_named_list(list(a = "foo", b = "hi"))
[1] TRUE
```


[r] `set_metadata` method allows unnamed list
## Describe the bug

`set_metadata` method allows  unnamed list.

https://github.com/single-cell-data/TileDB-SOMA/blob/566d88926589241b866c93401f1d167864653c40/apis/r/R/TileDBArray.R#L103-L105

The root cause:

https://github.com/single-cell-data/TileDB-SOMA/blob/566d88926589241b866c93401f1d167864653c40/apis/r/R/utils-assertions.R#L19-L20

Here's the reprex:
```r
is_named_list(list(a = "foo", "hi"))
[1] TRUE
```

Setting  `allow_empty` to `FALSE` for `is_named` assertion, then we're good:
```R
is_named_list <- function(x) {
  is.list(x) && is_named(x, allow_empty = FALSE)
}

# with `allow_empty = FALSE`
is_named_list(list(a = "foo", "hi"))
[1] FALSE

is_named_list(list(a = "foo", b = "hi"))
[1] TRUE
```




Discussion / hints:

Fix patch:
diff --git a/apis/r/DESCRIPTION b/apis/r/DESCRIPTION
index ad06b7edd5..4c61f03322 100644
--- a/apis/r/DESCRIPTION
+++ b/apis/r/DESCRIPTION
@@ -6,7 +6,7 @@ Description: Interface for working with 'TileDB'-based Stack of Matrices,
     like those commonly used for single cell data analysis. It is documented at
     <https://github.com/single-cell-data>; a formal specification available is at
     <https://github.com/single-cell-data/SOMA/blob/main/abstract_specification.md>.
-Version: 1.15.99.6
+Version: 1.15.99.7
 Authors@R: c(
     person(given = "Aaron", family = "Wolen",
            role = c("cre", "aut"), email = "aaron@tiledb.com",
diff --git a/apis/r/NEWS.md b/apis/r/NEWS.md
index 30f558be41..dcad4d2cca 100644
--- a/apis/r/NEWS.md
+++ b/apis/r/NEWS.md
@@ -13,6 +13,8 @@
 * Add transitional/non-exported `parse_query_condition_new` [#3162](https://github.com/single-cell-data/TileDB-SOMA/pull/3162)
 * Apply new `parse_query_condition` [#3174](https://github.com/single-cell-data/TileDB-SOMA/pull/3174)
 * Apply new `non_empty_domain` [#3176](https://github.com/single-cell-data/TileDB-SOMA/pull/3176)
+* Support for dense current domain with core 2.27 [#3180](https://github.com/single-cell-data/TileDB-SOMA/pull/3180)
+* Fix `is_named_list` bug for half-named lists [#3183](https://github.com/single-cell-data/TileDB-SOMA/pull/3183)
 
 # tiledbsoma 1.14.1
 
diff --git a/apis/r/R/utils-assertions.R b/apis/r/R/utils-assertions.R
index 1b247a67fc..eb445249d6 100644
--- a/apis/r/R/utils-assertions.R
+++ b/apis/r/R/utils-assertions.R
@@ -17,7 +17,9 @@ is_named <- function(x, allow_empty = TRUE) {
 }
 
 is_named_list <- function(x) {
-  is.list(x) && is_named(x)
+  # Use allow_empty=FALSE otherwise "half-named" lists like list(a=1, 2)
+  # will get through. We want all slots to have names.
+  is.list(x) && is_named(x, allow_empty = FALSE)
 }
 
 is_character_or_null <- function(x) {


Test patch:
diff --git a/apis/r/tests/testthat/test-utils.R b/apis/r/tests/testthat/test-utils.R
index f37f8c7092..a5f068d301 100644
--- a/apis/r/tests/testthat/test-utils.R
+++ b/apis/r/tests/testthat/test-utils.R
@@ -82,3 +82,9 @@ test_that("validate read coords with dimension names and schema", {
   expect_equal(test_coords$int_column, 1:10)
   expect_equal(test_coords$soma_joinid, as.integer64(1:10))
 })
+
+test_that("half-named lists are not treated as named", {
+  expect_true(is_named_list(list(a=1, b=2)))
+  expect_false(is_named_list(list(a=1, 2)))
+  expect_false(is_named_list(list(1, 2)))
+})