Skip to content

Commit 1d8386c

Browse files
authored
Merge pull request #668 from MesserLab/fix_666
shift the migrant flag from metadata to the flags column
2 parents 98ed022 + 04f4051 commit 1d8386c

10 files changed

Lines changed: 106 additions & 78 deletions

File tree

VERSIONS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ multitrait branch:
212212
however, we do not rely on the derived state being anything when reading in a .trees file
213213
in-memory, the binary derived state info remains in the derived state column and the mutation table metadata is kept empty, as before
214214
the schema for the mutation table metadata now encodes an array (of length determined by the metadata itself) of int64_t SLiM mutation IDs
215+
fix #666, remove `flags` from individual metadata (shifting the migrant flag, now named SLIM_TSK_INDIVIDUAL_MIGRATED, over to the flags column of the individual table)
216+
note this entails changes to the individual table flags column, the individual table metadata and schema, and SLiM's provenance entries (to add a description of the flag)
215217

216218

217219
version 5.2 (Eidos version 4.2):

core/slim_globals.cpp

Lines changed: 29 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2284,7 +2284,6 @@ const std::string gSLiM_tsk_individual_metadata_schema_FORMAT_SOURCE = R"V0G0N({
22842284
"examples": [
22852285
{
22862286
"age": -1,
2287-
"flags": 0,
22882287
"pedigree_id": 123,
22892288
"pedigree_p1": 12,
22902289
"pedigree_p2": 23,
@@ -2310,12 +2309,6 @@ const std::string gSLiM_tsk_individual_metadata_schema_FORMAT_SOURCE = R"V0G0N({
23102309
"tagL4": false
23112310
}
23122311
],
2313-
"flags": {
2314-
"SLIM_INDIVIDUAL_METADATA_MIGRATED": {
2315-
"description": "Whether this individual was a migrant, either in the tick when the tree sequence was written out (if the individual was alive then), or in the tick of the last time they were Remembered (if not).",
2316-
"value": 1
2317-
}
2318-
},
23192312
"properties": {
23202313
"pedigree_id": {
23212314
"index": 1,
@@ -2335,104 +2328,98 @@ const std::string gSLiM_tsk_individual_metadata_schema_FORMAT_SOURCE = R"V0G0N({
23352328
"binaryFormat": "q",
23362329
"description": "The 'pedigree ID' of this individual's second parent in SLiM."
23372330
},
2331+
"tag": {
2332+
"index": 4,
2333+
"type": "integer",
2334+
"binaryFormat": "q",
2335+
"description": "The `tag` property of this individual; INT64_MIN if unset."
2336+
},
2337+
"tagF": {
2338+
"index": 5,
2339+
"type": "number",
2340+
"binaryFormat": "d",
2341+
"description": "The `tagF` property of this individual; -DBL_MAX if unset."
2342+
},
23382343
"age": {
2339-
"index": 4,
2344+
"index": 6,
23402345
"type": "integer",
23412346
"binaryFormat": "i",
23422347
"description": "The age of this individual, either when the tree sequence was written out (if the individual was alive then), or the last time they were Remembered (if not)."
23432348
},
23442349
"subpopulation": {
2345-
"index": 5,
2350+
"index": 7,
23462351
"type": "integer",
23472352
"binaryFormat": "i",
23482353
"description": "The ID of the subpopulation the individual was part of, either when the tree sequence was written out (if the individual was alive then), or the last time they were Remembered (if not)."
23492354
},
23502355
"sex": {
2351-
"index": 6,
2356+
"index": 8,
23522357
"type": "integer",
2353-
"binaryFormat": "i",
2358+
"binaryFormat": "h",
23542359
"description": "The sex of the individual (0 for female, 1 for male, -1 for hermaphrodite)."
23552360
},
2356-
"flags": {
2357-
"index": 7,
2358-
"type": "integer",
2359-
"binaryFormat": "I",
2360-
"description": "Other information about the individual: see 'flags'."
2361-
},
2362-
"tag": {
2363-
"index": 8,
2364-
"type": "integer",
2365-
"binaryFormat": "q",
2366-
"description": "The `tag` property of this individual; INT64_MIN if unset."
2367-
},
2368-
"tagF": {
2369-
"index": 9,
2370-
"type": "number",
2371-
"binaryFormat": "d",
2372-
"description": "The `tagF` property of this individual; -DBL_MAX if unset."
2373-
},
23742361
"tagL0_set": {
2375-
"index": 10,
2362+
"index": 9,
23762363
"type": "boolean",
23772364
"binaryFormat": "?",
23782365
"description": "A flag indicating whether the `tagL0` property is set; if false, accessing `tagL0` is invalid."
23792366
},
23802367
"tagL0": {
2381-
"index": 11,
2368+
"index": 10,
23822369
"type": "boolean",
23832370
"binaryFormat": "?",
23842371
"description": "The `tagL0` property of this individual; only valid if `tagL0_set` is true."
23852372
},
23862373
"tagL1_set": {
2387-
"index": 12,
2374+
"index": 11,
23882375
"type": "boolean",
23892376
"binaryFormat": "?",
23902377
"description": "A flag indicating whether the `tagL1` property is set; if false, accessing `tagL1` is invalid."
23912378
},
23922379
"tagL1": {
2393-
"index": 13,
2380+
"index": 12,
23942381
"type": "boolean",
23952382
"binaryFormat": "?",
23962383
"description": "The `tagL1` property of this individual; only valid if `tagL1_set` is true."
23972384
},
23982385
"tagL2_set": {
2399-
"index": 14,
2386+
"index": 13,
24002387
"type": "boolean",
24012388
"binaryFormat": "?",
24022389
"description": "A flag indicating whether the `tagL2` property is set; if false, accessing `tagL2` is invalid."
24032390
},
24042391
"tagL2": {
2405-
"index": 15,
2392+
"index": 14,
24062393
"type": "boolean",
24072394
"binaryFormat": "?",
24082395
"description": "The `tagL2` property of this individual; only valid if `tagL2_set` is true."
24092396
},
24102397
"tagL3_set": {
2411-
"index": 16,
2398+
"index": 15,
24122399
"type": "boolean",
24132400
"binaryFormat": "?",
24142401
"description": "A flag indicating whether the `tagL3` property is set; if false, accessing `tagL3` is invalid."
24152402
},
24162403
"tagL3": {
2417-
"index": 17,
2404+
"index": 16,
24182405
"type": "boolean",
24192406
"binaryFormat": "?",
24202407
"description": "The `tagL3` property of this individual; only valid if `tagL3_set` is true."
24212408
},
24222409
"tagL4_set": {
2423-
"index": 18,
2410+
"index": 17,
24242411
"type": "boolean",
24252412
"binaryFormat": "?",
24262413
"description": "A flag indicating whether the `tagL4` property is set; if false, accessing `tagL4` is invalid."
24272414
},
24282415
"tagL4": {
2429-
"index": 19,
2416+
"index": 18,
24302417
"type": "boolean",
24312418
"binaryFormat": "?",
24322419
"description": "The `tagL4` property of this individual; only valid if `tagL4_set` is true."
24332420
},
24342421
"per_trait": {
2435-
"index": 20,
2422+
"index": 19,
24362423
"type": "array",
24372424
"length": "%d",
24382425
"items": {
@@ -2464,11 +2451,11 @@ const std::string gSLiM_tsk_individual_metadata_schema_FORMAT_SOURCE = R"V0G0N({
24642451
"pedigree_id",
24652452
"pedigree_p1",
24662453
"pedigree_p2",
2454+
"tag",
2455+
"tagF",
24672456
"age",
24682457
"subpopulation",
24692458
"sex",
2470-
"tag",
2471-
"tagF",
24722459
"tagL0_set",
24732460
"tagL0",
24742461
"tagL1_set",
@@ -2479,7 +2466,6 @@ const std::string gSLiM_tsk_individual_metadata_schema_FORMAT_SOURCE = R"V0G0N({
24792466
"tagL3",
24802467
"tagL4_set",
24812468
"tagL4",
2482-
"flags",
24832469
"per_trait"
24842470
]
24852471
})V0G0N";

core/slim_globals.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,7 @@ extern EidosPalette *gEidos_Palette_MutationLogisticEffect;
717717
#define SLIM_TSK_INDIVIDUAL_ALIVE ((tsk_flags_t)(1 << 16))
718718
#define SLIM_TSK_INDIVIDUAL_REMEMBERED ((tsk_flags_t)(1 << 17))
719719
#define SLIM_TSK_INDIVIDUAL_RETAINED ((tsk_flags_t)(1 << 18))
720+
#define SLIM_TSK_INDIVIDUAL_MIGRATED ((tsk_flags_t)(1 << 19))
720721

721722
extern const std::string *gSLiM_tsk_metadata_JSON_schema;
722723
extern const std::string *gSLiM_tsk_metadata_binary_schema_FORMAT;

core/species.cpp

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9018,8 +9018,9 @@ void Species::AddIndividualsToTable(Individual * const *p_individual, size_t p_n
90189018
if (ind_pos == p_individuals_hash->end()) {
90199019
// This individual is not already in the tables.
90209020
tsk_id_t tsk_individual = tsk_individual_table_add_row(&p_tables->individuals,
9021-
p_flags, location.data(), (uint32_t)location.size(),
9022-
NULL, 0, // individual parents
9021+
p_flags | (ind->migrant_ ? SLIM_TSK_INDIVIDUAL_MIGRATED : 0), // add migrant flag if needed
9022+
location.data(), (uint32_t)location.size(),
9023+
NULL, 0, // individual parents; fixed later by AddParentsColumnForOutput()
90239024
(char *)&metadata_rec, (uint32_t)total_metadata_size);
90249025
if (tsk_individual < 0) handle_error("tsk_individual_table_add_row", tsk_individual);
90259026

@@ -9054,24 +9055,37 @@ void Species::AddIndividualsToTable(Individual * const *p_individual, size_t p_n
90549055
// It could have been previously inserted but not with the SLIM_TSK_INDIVIDUAL_REMEMBERED
90559056
// flag: if so, it now needs adding to the list of remembered nodes
90569057
tsk_id_t tsk_node_id_base = ind->TskitNodeIdBase();
9058+
tsk_flags_t &individual_row_flags = p_tables->individuals.flags[tsk_individual];
90579059

9058-
if (((p_tables->individuals.flags[tsk_individual] & SLIM_TSK_INDIVIDUAL_REMEMBERED) == 0)
9060+
if (((individual_row_flags & SLIM_TSK_INDIVIDUAL_REMEMBERED) == 0)
90599061
&& (p_flags & SLIM_TSK_INDIVIDUAL_REMEMBERED))
90609062
{
90619063
remembered_nodes_.emplace_back(tsk_node_id_base);
90629064
remembered_nodes_.emplace_back(tsk_node_id_base + 1);
90639065
}
9064-
9066+
90659067
memcpy(p_tables->individuals.location
90669068
+ p_tables->individuals.location_offset[tsk_individual],
90679069
location.data(), location.size() * sizeof(double));
90689070
memcpy(p_tables->individuals.metadata
90699071
+ p_tables->individuals.metadata_offset[tsk_individual],
90709072
&metadata_rec, total_metadata_size);
9071-
p_tables->individuals.flags[tsk_individual] |= p_flags;
9073+
9074+
// BCH 8/26/2026: Note that we OR flags in here, and never clear flags, because of the way this
9075+
// method is called; individuals that get remembered/retained get set with only that flag, and
9076+
// then we call this method again later for alive individuals and want to just add the alive flag.
9077+
individual_row_flags |= p_flags;
9078+
9079+
// BCH 8/26/2026: We have to fix the `migrant` flag, which might have changed value since this
9080+
// individual was last recorded. This used to be done by the memcpy() of the metadata above,
9081+
// but now the `migrant` flag is kept in the flags column, not the metadata.
9082+
if (ind->migrant_)
9083+
individual_row_flags |= SLIM_TSK_INDIVIDUAL_MIGRATED;
9084+
else
9085+
individual_row_flags &= ~SLIM_TSK_INDIVIDUAL_MIGRATED;
90729086

90739087
// Check node table
9074-
assert(ind->TskitNodeIdBase() + 1 < (tsk_id_t) p_tables->nodes.num_rows); // base and base+1 must both be in range
9088+
assert(tsk_node_id_base + 1 < (tsk_id_t) p_tables->nodes.num_rows); // base and base+1 must both be in range
90759089

90769090
// BCH 4/29/2019: These asserts are, we think, not technically necessary – the code
90779091
// would work even if they were violated. But they're a nice invariant to guarantee,
@@ -9885,6 +9899,7 @@ void Species::WriteProvenanceTable(tsk_table_collection_t *p_tables, bool p_use_
98859899

98869900
// BCH 3/10/2024: Moving from schema version 1.0.0 to 1.1.0, which I believe shipped in tskit 0.5.9.
98879901
// This adds the optional `resources` key. See https://github.com/MesserLab/SLiM/issues/478.
9902+
// See https://tskit.dev/tskit/docs/stable/provenance.html#full-schema for the current provenance schema.
98889903
j["schema_version"] = "1.1.0";
98899904

98909905
struct utsname name;
@@ -10042,6 +10057,8 @@ void Species::WriteProvenanceTable(tsk_table_collection_t *p_tables, bool p_use_
1004210057
j["metadata"]["individuals"]["flags"]["17"]["description"] = "the individual was requested by the user to be permanently remembered";
1004310058
j["metadata"]["individuals"]["flags"]["18"]["name"] = "SLIM_TSK_INDIVIDUAL_RETAINED";
1004410059
j["metadata"]["individuals"]["flags"]["18"]["description"] = "the individual was requested by the user to be retained only if its nodes continue to exist in the tree sequence";
10060+
j["metadata"]["individuals"]["flags"]["19"]["name"] = "SLIM_TSK_INDIVIDUAL_MIGRATED";
10061+
j["metadata"]["individuals"]["flags"]["19"]["description"] = "the individual is a recent migrant between subpopulations";
1004510062

1004610063
// We save this information out only for runs at the command line. This data might not be available on
1004710064
// all platforms; when it is unavailable, the key will be omitted. We always have elapsed wall time.
@@ -11064,34 +11081,33 @@ void Species::MetadataForIndividual(Individual *p_individual, IndividualMetadata
1106411081
// We check the struct size here to detect changes that would need to be responded to here; but it is
1106511082
// very important to note that the caller guarantees that the actual size of p_metadata is large enough
1106611083
// to accommodate all of the per-trait metadata, which is variable-length!
11067-
static_assert(sizeof(IndividualMetadataRec) == 66, "IndividualMetadataRec has changed size; this code probably needs to be updated");
11084+
static_assert(sizeof(IndividualMetadataRec) == 60, "IndividualMetadataRec has changed size; this code probably needs to be updated");
1106811085

1106911086
#if DEBUG
1107011087
if (!p_individual || !p_metadata)
1107111088
EIDOS_TERMINATION << "ERROR (Species::MetadataForIndividual): (internal error) bad parameters to MetadataForIndividual()." << EidosTerminate();
1107211089
#endif
1107311090

11091+
// Note: tag values were added to the individual metadata in SLiM 6.0; we write false for
11092+
// unset values to avoid accessing unwritten memory, which would be flagged by UBSan
11093+
1107411094
p_metadata->pedigree_id_ = p_individual->PedigreeID();
1107511095
p_metadata->pedigree_p1_ = p_individual->Parent1PedigreeID();
1107611096
p_metadata->pedigree_p2_ = p_individual->Parent2PedigreeID();
11097+
p_metadata->tag_ = p_individual->tag_value_;
11098+
p_metadata->tagF_ = p_individual->tagF_value_;
11099+
1107711100
p_metadata->age_ = p_individual->age_;
1107811101
p_metadata->subpopulation_id_ = p_individual->subpopulation_->subpopulation_id_;
11079-
p_metadata->sex_ = (int32_t)p_individual->sex_; // IndividualSex, but int32_t in the record
1108011102

11081-
p_metadata->flags_ = 0;
11082-
if (p_individual->migrant_)
11083-
p_metadata->flags_ |= SLIM_INDIVIDUAL_METADATA_MIGRATED;
11084-
11085-
// tag values added to the metadata in SLiM 6.0; we write false for unset values
11086-
// to avoid accessing unwritten memory, which would be flagged by UBSan
11087-
p_metadata->tag_ = p_individual->tag_value_;
11088-
p_metadata->tagF_ = p_individual->tagF_value_;
11103+
p_metadata->sex_ = (int16_t)p_individual->sex_; // IndividualSex, but int16_t in the record
1108911104
p_metadata->tagL0_set_ = p_individual->tagL0_set_;
1109011105
p_metadata->tagL0_ = p_individual->tagL0_set_ ? p_individual->tagL0_value_ : false;
1109111106
p_metadata->tagL1_set_ = p_individual->tagL1_set_;
1109211107
p_metadata->tagL1_ = p_individual->tagL1_set_ ? p_individual->tagL1_value_ : false;
1109311108
p_metadata->tagL2_set_ = p_individual->tagL2_set_;
1109411109
p_metadata->tagL2_ = p_individual->tagL2_set_ ? p_individual->tagL2_value_ : false;
11110+
1109511111
p_metadata->tagL3_set_ = p_individual->tagL3_set_;
1109611112
p_metadata->tagL3_ = p_individual->tagL3_set_ ? p_individual->tagL3_value_ : false;
1109711113
p_metadata->tagL4_set_ = p_individual->tagL4_set_;
@@ -11911,6 +11927,7 @@ void Species::__RemapSubpopulationIDs(SUBPOP_REMAP_HASH &p_subpop_map, TreeSeqIn
1191111927
typedef struct ts_subpop_info {
1191211928
slim_popsize_t countMH_ = 0, countF_ = 0;
1191311929
std::vector<tsk_id_t> nodes_;
11930+
std::vector<bool> migrant_flags_; // true for each individual if SLIM_TSK_INDIVIDUAL_MIGRATED is set
1191411931
std::vector<const double*> spatial_positions_; // points into the locations column of the individual table
1191511932
std::vector<const IndividualMetadataRec*> metadata_; // points into the metadata column of the individual table
1191611933
} ts_subpop_info;
@@ -11993,6 +12010,10 @@ void Species::__TabulateSubpopulationsFromTreeSequence(std::unordered_map<slim_o
1199312010

1199412011
ts_subpop_info &subpop_info = subpop_info_iter->second;
1199512012

12013+
// remember the SLIM_TSK_INDIVIDUAL_MIGRATED flag from the flags column of the individual table
12014+
// this used to be in metadata, but now that it is in the flags column we need to keep it separately
12015+
subpop_info.migrant_flags_.push_back(!!(individual.flags & SLIM_TSK_INDIVIDUAL_MIGRATED));
12016+
1199612017
// remember our metadata pointer, we will fetch information from it later; below we check metadata for
1199712018
// correctness, and even edit it, but we do not copy its values, we just keep the metadata pointer
1199812019
subpop_info.metadata_.push_back(metadata);
@@ -12260,8 +12281,7 @@ void Species::__CreateSubpopulationsFromTabulation(std::unordered_map<slim_objec
1226012281

1226112282
individual->SetParentPedigreeID(ind_metadata->pedigree_p1_, ind_metadata->pedigree_p2_);
1226212283

12263-
uint32_t flags = ind_metadata->flags_;
12264-
if (flags & SLIM_INDIVIDUAL_METADATA_MIGRATED)
12284+
if (subpop_info.migrant_flags_[tabulation_index])
1226512285
individual->migrant_ = true;
1226612286

1226712287
individual->age_ = ind_metadata->age_;
@@ -12480,8 +12500,7 @@ void Species::__CreateSubpopulationsFromTabulation_SECONDARY(std::unordered_map<
1248012500
(individual->Parent2PedigreeID() != ind_metadata->pedigree_p2_))
1248112501
EIDOS_TERMINATION << "ERROR (Species::__CreateSubpopulationsFromTabulation_SECONDARY): parent pedigree id mismatch between chromosomes read." << EidosTerminate();
1248212502

12483-
uint32_t flags = ind_metadata->flags_;
12484-
if ((flags & SLIM_INDIVIDUAL_METADATA_MIGRATED) && !individual->migrant_)
12503+
if (subpop_info.migrant_flags_[tabulation_index] != individual->migrant_)
1248512504
EIDOS_TERMINATION << "ERROR (Species::__CreateSubpopulationsFromTabulation_SECONDARY): individual migrant flag mismatch between chromosomes read." << EidosTerminate();
1248612505

1248712506
if (individual->age_ != ind_metadata->age_)

core/species.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -145,37 +145,37 @@ typedef struct __attribute__((__packed__)) {
145145
slim_pedigreeid_t pedigree_id_; // 8 bytes (int64_t): the SLiM pedigree ID for this individual, assigned by pedigree rec
146146
slim_pedigreeid_t pedigree_p1_; // 8 bytes (int64_t): the SLiM pedigree ID for this individual's parent 1
147147
slim_pedigreeid_t pedigree_p2_; // 8 bytes (int64_t): the SLiM pedigree ID for this individual's parent 2
148-
slim_age_t age_; // 4 bytes (int32_t): the age of the individual (-1 for WF models)
149-
slim_objectid_t subpopulation_id_; // 4 bytes (int32_t): the subpopulation the individual belongs to
150-
int32_t sex_; // 4 bytes (int32_t): the sex of the individual, as defined by the IndividualSex enum
151-
uint32_t flags_; // 4 bytes (uint32_t): assorted flags, see below
152148
int64_t tag_; // 8 bytes (int64_t): the `tag` property value
153149
double tagF_; // 8 bytes (double): the `tagF` property value
150+
151+
slim_age_t age_; // 4 bytes (int32_t): the age of the individual (-1 for WF models)
152+
slim_objectid_t subpopulation_id_; // 4 bytes (int32_t): the subpopulation the individual belongs to
153+
154+
int16_t sex_; // 2 bytes (int16_t): the sex of the individual, as defined by the IndividualSex enum
154155
uint8_t tagL0_set_; // 1 byte (uint8_t): a flag indicating whether `tagL0` is set
155156
uint8_t tagL0_; // 1 byte (uint8_t): the `tagL0` property value
156157
uint8_t tagL1_set_; // 1 byte (uint8_t): a flag indicating whether `tagL1` is set
157158
uint8_t tagL1_; // 1 byte (uint8_t): the `tagL1` property value
158159
uint8_t tagL2_set_; // 1 byte (uint8_t): a flag indicating whether `tagL2` is set
159160
uint8_t tagL2_; // 1 byte (uint8_t): the `tagL2` property value
161+
160162
uint8_t tagL3_set_; // 1 byte (uint8_t): a flag indicating whether `tagL3` is set
161163
uint8_t tagL3_; // 1 byte (uint8_t): the `tagL3` property value
162164
uint8_t tagL4_set_; // 1 byte (uint8_t): a flag indicating whether `tagL4` is set
163165
uint8_t tagL4_; // 1 byte (uint8_t): the `tagL4` property value
164166

165-
// NOTE: after this point the packed struct is only aligned to a two-byte boundary!
167+
// NOTE: after this point the packed struct is only aligned to a four-byte boundary!
166168

167169
_IndividualPerTraitMetadata per_trait_[]; // 16 bytes per entry: 0 or more per-trait entries (count determined by the schema!)
168170
} IndividualMetadataRec;
169171

170-
#define SLIM_INDIVIDUAL_METADATA_MIGRATED 0x01 // set if the individual has migrated in this cycle
171-
172172
// We double-check the size of these records to make sure we understand what they contain and how they're packed
173173
// BCH 2/11/2026: Note that all of these metadata structs are now actually variable-length; this is just a base.
174174
static_assert(sizeof(_MutationPerTraitMetadata) == 12, "_MutationPerTraitMetadata is not 12 bytes!");
175175
static_assert(sizeof(MutationTableMetadataRec) == 36, "MutationTableMetadataRec is not 36 bytes!");
176176
static_assert(sizeof(HaplosomeMetadataRec) == 9, "HaplosomeMetadataRec is not 9 bytes!");
177177
static_assert(sizeof(_IndividualPerTraitMetadata) == 16, "_IndividualPerTraitMetadata is not 16 bytes!");
178-
static_assert(sizeof(IndividualMetadataRec) == 66, "IndividualMetadataRec is not 66 bytes!");
178+
static_assert(sizeof(IndividualMetadataRec) == 60, "IndividualMetadataRec is not 60 bytes!");
179179

180180
// We check endianness on the platform we're building on; we assume little-endianness in our read/write code, I think.
181181
#if defined(__BYTE_ORDER__)

treerec/tests/.python-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.13

0 commit comments

Comments
 (0)