Skip to content

Commit cd0bee7

Browse files
committed
Merge remote-tracking branch 'upstream/main' into dev
2 parents 17250e1 + bbeb650 commit cd0bee7

29 files changed

+520
-129
lines changed

.readthedocs.yaml

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,10 @@ build:
99
- asdf plugin add uv
1010
- asdf install uv latest
1111
- asdf global uv latest
12-
# Turn `python -m virtualenv` into `python -c pass`
13-
- truncate --size 0 $( dirname $( uv python find ) )/../lib/python3*/site-packages/virtualenv/__main__.py
14-
post_create_environment:
12+
create_environment:
1513
- uv venv $READTHEDOCS_VIRTUALENV_PATH
16-
# Turn `python -m pip` into `python -c pass`
17-
- truncate --size 0 $( ls -d $READTHEDOCS_VIRTUALENV_PATH/lib/python3* )/site-packages/pip.py
18-
# Use a cache dir in the same mount to halve the install time
19-
- VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH uv pip install --cache-dir $READTHEDOCS_VIRTUALENV_PATH/../../uv_cache --upgrade sphinx
20-
post_install:
14+
install:
2115
- VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH uv pip install --cache-dir $READTHEDOCS_VIRTUALENV_PATH/../../uv_cache -r docs/requirements.txt
16+
17+
sphinx:
18+
configuration: docs/conf.py

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
<a id='changelog-2.0.1'></a>
3+
# 2.0.1 — 2024-12-10
4+
5+
## Fixed
6+
7+
- Improve handling of `.bidsignore` files in the web validator.
8+
Ignores matching directories but not the files they contained could fail to match.
9+
(#113)
10+
11+
- Resolve issue with parsing headers of NIfTI files with large extensions.
12+
Fixes [issue 126].
13+
14+
[issue 126]: https://github.com/bids-standard/bids-validator/issues/126
15+
16+
## Infrastructure
17+
18+
- Adopting [scriv](https://scriv.readthedocs.io/en/latest/) for changelog
19+
management.

README.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
The BIDS Validator is a web application, command-line utility,
99
and Javascript/Typescript library for assessing compliance with the
10-
[Brain Imaging Data Structure][BIDS] standard.
10+
[Brain Imaging Data Structure (BIDS)][BIDS] standard.
1111

1212
## Getting Started
1313

@@ -23,7 +23,7 @@ The web validator runs in-browser, and does not transfer data to any remote serv
2323

2424
In some contexts, such as when working on a remote server,
2525
it may be easier to use the command-line.
26-
The BIDS Validator can be run with the [Deno] runtime
26+
The BIDS Validator can be run with the [Deno][] runtime
2727
(see [Deno - Installation][] for detailed installation instructions):
2828

2929
```shell
@@ -80,9 +80,14 @@ To modify the schema a clone of bids-standard/bids-specification will need to be
8080

8181
After changes to the schema have been made to a local copy the dereferenced single json file used by the validator will need to be built. The `bidsschematools` python package does this. It can be installed from pypi via pip or a local installation can be made. It lives in the specification repository here https://github.com/bids-standard/bids-specification/tree/master/tools/schemacode
8282

83-
The command to compile a dereferenced schema is `bst -v export --output src/schema.json` (this assumes you are in the root of the bids-specification repo). Once compiled it can be passed to the validator via the `-s` flag, `./bids-validator-deno -s <path to schema> <path to dataset>`
83+
The command to compile a dereferenced schema is `bst -v export --schema src/schema --output src/schema.json` (this assumes you are in the root of the bids-specification repo). Once compiled it can be passed to the validator via the `-s` flag, `./bids-validator-deno -s <path to schema> <path to dataset>`
8484

8585

8686
## Documentation
8787

88-
The BIDS validator documentation is available on [Read the Docs](https://bids-validator.readthedocs.io/en/latest/).
88+
The BIDS validator documentation is available on [Read the Docs](https://bids-validator.readthedocs.io/en/latest/).
89+
90+
[BIDS]: https://bids.neuroimaging.io
91+
[BIDS Validator]: https://bids-standard.github.io/bids-validator/
92+
[Deno]: https://deno.com/
93+
[Deno - Installation]: https://docs.deno.com/runtime/getting_started/installation/

deno.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"@cliffy/command": "jsr:@effigies/[email protected]",
3333
"@cliffy/table": "jsr:@effigies/[email protected]",
3434
"@hed/validator": "npm:[email protected]",
35-
"@ignore": "npm:ignore@6.0.2",
35+
"@ignore": "npm:ignore@7.0.3",
3636
"@libs/xml": "jsr:@libs/[email protected]",
3737
"@mango/nifti": "npm:@bids/[email protected]",
3838
"@std/assert": "jsr:@std/[email protected]",
@@ -41,6 +41,7 @@
4141
"@std/io": "jsr:@std/[email protected]",
4242
"@std/log": "jsr:@std/[email protected]",
4343
"@std/path": "jsr:@std/[email protected]",
44+
"@std/streams": "jsr:@std/[email protected]",
4445
"@std/yaml": "jsr:@std/yaml@^1.0.4"
4546
},
4647
"tasks": {

deno.lock

Lines changed: 29 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
The BIDS Validator is a web application, command-line utility,
44
and Javascript/Typescript library for assessing compliance with the
5-
[Brain Imaging Data Structure][BIDS] standard.
5+
[Brain Imaging Data Structure (BIDS)][BIDS] standard.
66

77
## Getting Started
88

@@ -18,7 +18,7 @@ The web validator runs in-browser, and does not transfer data to any remote serv
1818

1919
In some contexts, such as when working on a remote server,
2020
it may be easier to use the command-line.
21-
The BIDS Validator can be run with the [Deno] runtime
21+
The BIDS Validator can be run with the [Deno][] runtime
2222
(see [Deno - Installation][] for detailed installation instructions):
2323

2424
```shell

docs/user_guide/command-line.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ warnings, errors or ignored.
8484
}
8585
```
8686

87+
When a configuration specifies `location` without leading `/` it is interpreted
88+
as a glob pattern following gitignore syntax.
8789
The issues are partial matches of the [Issues] that the validator accumulates.
8890
Pass the `--json` flag to see the issues in detail.
8991

src/files/deno.test.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { readAll, readerFromStreamReader } from '@std/io'
33
import { basename, dirname, fromFileUrl, join } from '@std/path'
44
import { EOL } from '@std/fs'
55
import type { FileTree } from '../types/filetree.ts'
6-
import { BIDSFileDeno, readFileTree, UnicodeDecodeError } from './deno.ts'
6+
import { BIDSFileDeno, readFileTree } from './deno.ts'
7+
import { UnicodeDecodeError } from './streams.ts'
78
import { requestReadPermission } from '../setup/requestPermissions.ts'
89
import { FileIgnoreRules } from './ignore.ts'
910

@@ -12,9 +13,11 @@ await requestReadPermission()
1213
// Use this file for testing file behavior
1314
const testUrl = import.meta.url
1415
const testPath = fromFileUrl(testUrl)
15-
const testDir = dirname(testPath)
16+
const testDir = dirname(testPath) // $REPO/src/files
1617
const testFilename = basename(testPath)
18+
const repoRoot = dirname(dirname(dirname(testPath)))
1719
const ignore = new FileIgnoreRules([])
20+
const prune = new FileIgnoreRules(['derivatives'], false)
1821

1922
Deno.test('Deno implementation of BIDSFile', async (t) => {
2023
await t.step('implements basic file properties', () => {
@@ -53,7 +56,7 @@ Deno.test('Deno implementation of BIDSFile', async (t) => {
5356
'strips BOM characters when reading UTF-8 via .text()',
5457
async () => {
5558
// BOM is invalid in JSON but shows up often from certain tools, so abstract handling it
56-
const bomDir = join(testPath, '..', '..', 'tests')
59+
const bomDir = join(repoRoot, 'src', 'tests')
5760
const bomFilename = 'bom-utf8.json'
5861
const file = new BIDSFileDeno(bomDir, bomFilename, ignore)
5962
const text = await file.text()
@@ -75,4 +78,16 @@ Deno.test('Deno implementation of FileTree', async (t) => {
7578
assert(testObj !== undefined)
7679
assertEquals(testObj.path, `/${parent}/${testFilename}`)
7780
})
81+
82+
await t.step('implements pruning', async () => {
83+
const dsDir = join(repoRoot, 'tests', 'data', 'valid_dataset')
84+
const derivFile =
85+
'derivatives/fmriprep/sub-01/ses-01/func/sub-01_ses-01_task-rest_confounds.tsv.gz'
86+
87+
const fullTree = await readFileTree(dsDir)
88+
assert(fullTree.get(derivFile))
89+
90+
const prunedTree = await readFileTree(dsDir, prune)
91+
assert(!prunedTree.get(derivFile))
92+
})
7893
})

src/files/deno.ts

Lines changed: 22 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,9 @@ import { type BIDSFile, FileTree } from '../types/filetree.ts'
77
import { requestReadPermission } from '../setup/requestPermissions.ts'
88
import { FileIgnoreRules, readBidsIgnore } from './ignore.ts'
99
import { logger } from '../utils/logger.ts'
10+
import { createUTF8Stream } from './streams.ts'
1011
export { type BIDSFile, FileTree }
1112

12-
/**
13-
* Thrown when a text file is decoded as UTF-8 but contains UTF-16 characters
14-
*/
15-
export class UnicodeDecodeError extends Error {
16-
constructor(message: string) {
17-
super(message)
18-
this.name = 'UnicodeDecode'
19-
}
20-
}
21-
2213
/**
2314
* Deno implementation of BIDSFile
2415
*/
@@ -67,27 +58,17 @@ export class BIDSFileDeno implements BIDSFile {
6758
* Read the entire file and decode as utf-8 text
6859
*/
6960
async text(): Promise<string> {
70-
const streamReader = this.stream
71-
.pipeThrough(new TextDecoderStream('utf-8'))
72-
.getReader()
73-
let data = ''
61+
const reader = this.stream.pipeThrough(createUTF8Stream()).getReader()
62+
const chunks: string[] = []
7463
try {
75-
// Read once to check for unicode issues
76-
const { done, value } = await streamReader.read()
77-
// Check for UTF-16 BOM
78-
if (value && value.startsWith('\uFFFD')) {
79-
throw new UnicodeDecodeError('This file appears to be UTF-16')
80-
}
81-
if (done) return data
82-
data += value
83-
// Continue reading the rest of the file if no unicode issues were found
8464
while (true) {
85-
const { done, value } = await streamReader.read()
86-
if (done) return data
87-
data += value
65+
const { done, value } = await reader.read()
66+
if (done) break
67+
chunks.push(value)
8868
}
69+
return chunks.join('')
8970
} finally {
90-
streamReader.releaseLock()
71+
reader.releaseLock()
9172
}
9273
}
9374

@@ -120,17 +101,22 @@ async function _readFileTree(
120101
rootPath: string,
121102
relativePath: string,
122103
ignore: FileIgnoreRules,
104+
prune: FileIgnoreRules,
123105
parent?: FileTree,
124106
): Promise<FileTree> {
125107
await requestReadPermission()
126108
const name = basename(relativePath)
127109
const tree = new FileTree(relativePath, name, parent, ignore)
128110

129111
for await (const dirEntry of Deno.readDir(join(rootPath, relativePath))) {
112+
const thisPath = posix.join(relativePath, dirEntry.name)
113+
if (prune.test(thisPath)) {
114+
continue
115+
}
130116
if (dirEntry.isFile || dirEntry.isSymlink) {
131117
const file = new BIDSFileDeno(
132118
rootPath,
133-
posix.join(relativePath, dirEntry.name),
119+
thisPath,
134120
ignore,
135121
)
136122
file.parent = tree
@@ -139,8 +125,9 @@ async function _readFileTree(
139125
if (dirEntry.isDirectory) {
140126
const dirTree = await _readFileTree(
141127
rootPath,
142-
posix.join(relativePath, dirEntry.name),
128+
thisPath,
143129
ignore,
130+
prune,
144131
tree,
145132
)
146133
tree.directories.push(dirTree)
@@ -152,9 +139,13 @@ async function _readFileTree(
152139
/**
153140
* Read in the target directory structure and return a FileTree
154141
*/
155-
export async function readFileTree(rootPath: string): Promise<FileTree> {
142+
export async function readFileTree(
143+
rootPath: string,
144+
prune?: FileIgnoreRules,
145+
): Promise<FileTree> {
146+
prune ??= new FileIgnoreRules([], false)
156147
const ignore = new FileIgnoreRules([])
157-
const tree = await _readFileTree(rootPath, '/', ignore)
148+
const tree = await _readFileTree(rootPath, '/', ignore, prune)
158149
const bidsignore = tree.get('.bidsignore')
159150
if (bidsignore) {
160151
try {

0 commit comments

Comments
 (0)