diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c6c8b36 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/CHANGELOG.md b/CHANGELOG.md index 2872932..cf76b4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog ## v0.7.8 TBC +### Fixed +- Fix accessing attributes of committed datatype with `my_datafile.attrs`. +- Fix calling `get_attribute_names` method of Module API on committed datatype. ### Changed - Mark optional parameters as such in the TypeScript declarations of the following `H5Module` methods: `open`, `create_dataset`, `create_group`, `create_vlen_str_dataset` and `get_keys_vector`. ## v0.7.7 2024-08-28 diff --git a/src/hdf5_hl.d.ts b/src/hdf5_hl.d.ts index 0315314..cab8905 100644 --- a/src/hdf5_hl.d.ts +++ b/src/hdf5_hl.d.ts @@ -39,6 +39,7 @@ declare enum OBJECT_TYPE { REFERENCE = "Reference", REGION_REFERENCE = "RegionReference" } +export declare type Entity = Dataset | Group | BrokenSoftLink | ExternalLink | Datatype | Reference | RegionReference; export declare class BrokenSoftLink { target: string; type: OBJECT_TYPE; @@ -50,13 +51,6 @@ export declare class ExternalLink { type: OBJECT_TYPE; constructor(filename: string, obj_path: string); } -export declare class Datatype { - file_id: bigint; - path: string; - type: OBJECT_TYPE; - constructor(file_id: bigint, path: string); - get metadata(): Metadata; -} export declare class Reference { ref_data: Uint8Array; constructor(ref_data: Uint8Array); @@ -81,9 +75,7 @@ declare abstract class HasAttrs { file_id: bigint; path: string; type: OBJECT_TYPE; - get attrs(): { - [key: string]: Attribute; - }; + get attrs(): Record; get root(): Group; get parent(): Group; get_attribute(name: string, json_compatible: true): JSONCompatibleOutputData; @@ -91,20 +83,25 @@ declare abstract class HasAttrs { create_attribute(name: string, data: GuessableDataTypes, shape?: number[] | null, dtype?: string | null): void; delete_attribute(name: string): number; create_reference(): Reference; - dereference(ref: Reference | RegionReference): BrokenSoftLink | ExternalLink | Datatype | Group | Dataset | DatasetRegion | null; + dereference(ref: RegionReference): DatasetRegion; + dereference(ref: Reference | RegionReference): DatasetRegion | Entity | null; +} +export declare class Datatype extends HasAttrs { + constructor(file_id: bigint, path: string); + get metadata(): Metadata; } export declare class Group extends HasAttrs { constructor(file_id: bigint, path: string); - keys(): Array; - values(): Generator; - items(): Generator<(string | BrokenSoftLink | ExternalLink | Datatype | Group | Dataset | null)[], void, unknown>; + keys(): string[]; + values(): Generator; + items(): Generator<[string, Entity | null], void, never>; get_type(obj_path: string): number; get_link(obj_path: string): string; get_external_link(obj_path: string): { filename: string; obj_path: string; }; - get(obj_name: string): BrokenSoftLink | ExternalLink | Datatype | Group | Dataset | null; + get(obj_name: string): Entity | null; create_group(name: string, track_order?: boolean): Group; create_dataset(args: { name: string; diff --git a/src/hdf5_hl.ts b/src/hdf5_hl.ts index f34f717..28844b3 100644 --- a/src/hdf5_hl.ts +++ b/src/hdf5_hl.ts @@ -504,6 +504,8 @@ enum OBJECT_TYPE { REGION_REFERENCE = 'RegionReference', } +export type Entity = Dataset | Group | BrokenSoftLink | ExternalLink | Datatype | Reference | RegionReference; + export class BrokenSoftLink { // only used for broken links... target: string; @@ -523,20 +525,6 @@ export class ExternalLink { } } -export class Datatype { - file_id: bigint; - path: string; - type: OBJECT_TYPE = OBJECT_TYPE.DATATYPE - constructor(file_id: bigint, path: string) { - this.file_id = file_id; - this.path = path; - } - - get metadata() { - return Module.get_datatype_metadata(this.file_id, this.path); - } -} - export class Reference { ref_data: Uint8Array; constructor(ref_data: Uint8Array) { @@ -598,7 +586,7 @@ abstract class HasAttrs { get attrs() { let attr_names = Module.get_attribute_names(this.file_id, this.path) as string[]; - let attrs: {[key: string]: Attribute} = {}; + let attrs: Record = {}; const { file_id, path } = this; for (let name of attr_names) { Object.defineProperty(attrs, name, { @@ -607,7 +595,6 @@ abstract class HasAttrs { }); } return attrs; - } get root() { @@ -677,7 +664,9 @@ abstract class HasAttrs { return new Reference(ref_data); } - dereference(ref: Reference | RegionReference) { + dereference(ref: RegionReference): DatasetRegion; + dereference(ref: Reference | RegionReference): DatasetRegion | Entity | null; + dereference(ref: Reference | RegionReference): DatasetRegion | Entity | null { const is_region = (ref instanceof RegionReference); const name = Module.get_referenced_name(this.file_id, ref.ref_data, !is_region); const target = this.root.get(name); @@ -685,6 +674,19 @@ abstract class HasAttrs { } } +export class Datatype extends HasAttrs { + constructor(file_id: bigint, path: string) { + super(); + this.file_id = file_id; + this.path = path; + this.type = OBJECT_TYPE.DATATYPE; + } + + get metadata() { + return Module.get_datatype_metadata(this.file_id, this.path); + } +} + export class Group extends HasAttrs { constructor(file_id: bigint, path: string) { super(); @@ -693,22 +695,22 @@ export class Group extends HasAttrs { this.type = OBJECT_TYPE.GROUP; } - keys(): Array { - return Module.get_names(this.file_id, this.path, false) as string[]; + keys(): string[] { + return Module.get_names(this.file_id, this.path, false); } - * values() { + * values(): Generator { for (let name of this.keys()) { yield this.get(name); } - return + return; } - * items() { + * items(): Generator<[string, Entity | null], void, never> { for (let name of this.keys()) { yield [name, this.get(name)]; } - return + return; } get_type(obj_path: string) { @@ -723,7 +725,7 @@ export class Group extends HasAttrs { return Module.get_external_link(this.file_id, obj_path); } - get(obj_name: string) { + get(obj_name: string): Entity | null { let fullpath = (/^\//.test(obj_name)) ? obj_name : this.path + "/" + obj_name; fullpath = normalizePath(fullpath); diff --git a/src/hdf5_util.cc b/src/hdf5_util.cc index 4bc79ad..3f2b620 100644 --- a/src/hdf5_util.cc +++ b/src/hdf5_util.cc @@ -246,6 +246,10 @@ val get_attribute_names(hid_t loc_id, const std::string& obj_name_string) { ocpl_id = H5Gget_create_plist(obj_id); } + else if (obj_type == H5O_TYPE_NAMED_DATATYPE) + { + ocpl_id = H5Tget_create_plist(obj_id); + } else { ocpl_id = H5Dget_create_plist(obj_id); diff --git a/test/array.h5 b/test/array.h5 index 813b325..28148ce 100644 Binary files a/test/array.h5 and b/test/array.h5 differ diff --git a/test/compressed.h5 b/test/compressed.h5 index d034046..b135571 100644 Binary files a/test/compressed.h5 and b/test/compressed.h5 differ diff --git a/test/datatype_test.mjs b/test/datatype_test.mjs index 7e52344..857770c 100644 --- a/test/datatype_test.mjs +++ b/test/datatype_test.mjs @@ -18,6 +18,10 @@ async function datatype_test() { littleEndian: false, size: 10 }); + + assert.deepEqual(Object.keys(datatype.attrs), ['named_dtype_attr']); + assert.deepEqual(datatype.attrs['named_dtype_attr'].value, + 'An attribute of a named datatype'); } export const tests = [ diff --git a/test/make_test_files.py b/test/make_test_files.py index b50a45a..56c0f84 100644 --- a/test/make_test_files.py +++ b/test/make_test_files.py @@ -17,6 +17,7 @@ f.create_dataset("bool", data=[[False, True], [True, False]], shape=(2,2)) f.create_dataset("bigint", data=np.arange(8).reshape(2,2,2), dtype="