Skip to content

Commit

Permalink
Merge branch 'main' into issue-8203
Browse files Browse the repository at this point in the history
  • Loading branch information
bmmtstb authored Jan 20, 2024
2 parents b91db30 + 6f0deb9 commit 9b92fd2
Show file tree
Hide file tree
Showing 55 changed files with 248 additions and 132 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/build-wheels-aarch64-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ on:
- v[0-9]+.[0-9]+.[0-9]+-rc[0-9]+
workflow_dispatch:

permissions:
id-token: write
contents: read

jobs:
generate-matrix:
uses: pytorch/test-infra/.github/workflows/generate_binary_build_matrix.yml@main
Expand Down Expand Up @@ -48,6 +52,3 @@ jobs:
trigger-event: ${{ github.event_name }}
architecture: aarch64
setup-miniconda: false
secrets:
AWS_PYTORCH_UPLOADER_ACCESS_KEY_ID: ${{ secrets.AWS_PYTORCH_UPLOADER_ACCESS_KEY_ID }}
AWS_PYTORCH_UPLOADER_SECRET_ACCESS_KEY: ${{ secrets.AWS_PYTORCH_UPLOADER_SECRET_ACCESS_KEY }}
7 changes: 4 additions & 3 deletions .github/workflows/build-wheels-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ on:
- v[0-9]+.[0-9]+.[0-9]+-rc[0-9]+
workflow_dispatch:

permissions:
id-token: write
contents: read

jobs:
generate-matrix:
uses: pytorch/test-infra/.github/workflows/generate_binary_build_matrix.yml@main
Expand Down Expand Up @@ -45,6 +49,3 @@ jobs:
package-name: ${{ matrix.package-name }}
smoke-test-script: ${{ matrix.smoke-test-script }}
trigger-event: ${{ github.event_name }}
secrets:
AWS_PYTORCH_UPLOADER_ACCESS_KEY_ID: ${{ secrets.AWS_PYTORCH_UPLOADER_ACCESS_KEY_ID }}
AWS_PYTORCH_UPLOADER_SECRET_ACCESS_KEY: ${{ secrets.AWS_PYTORCH_UPLOADER_SECRET_ACCESS_KEY }}
7 changes: 4 additions & 3 deletions .github/workflows/build-wheels-m1.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ on:
- v[0-9]+.[0-9]+.[0-9]+-rc[0-9]+
workflow_dispatch:

permissions:
id-token: write
contents: read

jobs:
generate-matrix:
uses: pytorch/test-infra/.github/workflows/generate_binary_build_matrix.yml@main
Expand Down Expand Up @@ -46,6 +50,3 @@ jobs:
runner-type: macos-m1-12
smoke-test-script: ${{ matrix.smoke-test-script }}
trigger-event: ${{ github.event_name }}
secrets:
AWS_PYTORCH_UPLOADER_ACCESS_KEY_ID: ${{ secrets.AWS_PYTORCH_UPLOADER_ACCESS_KEY_ID }}
AWS_PYTORCH_UPLOADER_SECRET_ACCESS_KEY: ${{ secrets.AWS_PYTORCH_UPLOADER_SECRET_ACCESS_KEY }}
7 changes: 4 additions & 3 deletions .github/workflows/build-wheels-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ on:
- v[0-9]+.[0-9]+.[0-9]+-rc[0-9]+
workflow_dispatch:

permissions:
id-token: write
contents: read

jobs:
generate-matrix:
uses: pytorch/test-infra/.github/workflows/generate_binary_build_matrix.yml@main
Expand Down Expand Up @@ -46,6 +50,3 @@ jobs:
runner-type: macos-12
smoke-test-script: ${{ matrix.smoke-test-script }}
trigger-event: ${{ github.event_name }}
secrets:
AWS_PYTORCH_UPLOADER_ACCESS_KEY_ID: ${{ secrets.AWS_PYTORCH_UPLOADER_ACCESS_KEY_ID }}
AWS_PYTORCH_UPLOADER_SECRET_ACCESS_KEY: ${{ secrets.AWS_PYTORCH_UPLOADER_SECRET_ACCESS_KEY }}
7 changes: 4 additions & 3 deletions .github/workflows/build-wheels-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ on:
- v[0-9]+.[0-9]+.[0-9]+-rc[0-9]+
workflow_dispatch:

permissions:
id-token: write
contents: read

jobs:
generate-matrix:
uses: pytorch/test-infra/.github/workflows/generate_binary_build_matrix.yml@main
Expand Down Expand Up @@ -47,6 +51,3 @@ jobs:
package-name: ${{ matrix.package-name }}
smoke-test-script: ${{ matrix.smoke-test-script }}
trigger-event: ${{ github.event_name }}
secrets:
AWS_PYTORCH_UPLOADER_ACCESS_KEY_ID: ${{ secrets.AWS_PYTORCH_UPLOADER_ACCESS_KEY_ID }}
AWS_PYTORCH_UPLOADER_SECRET_ACCESS_KEY: ${{ secrets.AWS_PYTORCH_UPLOADER_SECRET_ACCESS_KEY }}
2 changes: 1 addition & 1 deletion .github/workflows/pr-labels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:

- name: Process commit and find merger responsible for labeling
id: commit
run: echo "::set-output name=merger::$(python .github/process_commit.py ${{ github.sha }})"
run: echo "merger=$(python .github/process_commit.py ${{ github.sha }})" >> $GITHUB_OUTPUT

- name: Ping merger responsible for labeling if necessary
if: ${{ steps.commit.outputs.merger != '' }}
Expand Down
10 changes: 7 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ clear and has sufficient instructions to be able to reproduce the issue.
### Dependencies

Start by installing the **nightly** build of PyTorch following the [official
instructions](https://pytorch.org/get-started/locally/).
instructions](https://pytorch.org/get-started/locally/). Note that the official
instructions may ask you to install torchvision itself. If you are doing development
on torchvision, you should not install prebuilt torchvision packages.

**Optionally**, install `libpng` and `libjpeg-turbo` if you want to enable
support for
Expand Down Expand Up @@ -69,10 +71,10 @@ building GPU support by setting `FORCE_CUDA=1` environment variable, which is us
We don't officially support building from source using `pip`, but _if_ you do, you'll need to use the
`--no-build-isolation` flag.

Other development dependencies include:
#### Other development dependencies (some of these are needed to run tests):

```
pip install flake8 typing mypy pytest pytest-mock scipy
pip install expecttest flake8 typing mypy pytest pytest-mock scipy
```

## Development Process
Expand Down Expand Up @@ -145,6 +147,8 @@ mypy --config-file mypy.ini

### Unit tests

Before running tests make sure to install [test dependencies](#other-development-dependencies-some-of-these-are-needed-to-run-tests).

If you have modified the code by adding a new feature or a bug-fix, please add unit tests for that. To run a specific
test:
```bash
Expand Down
2 changes: 1 addition & 1 deletion docs/source/models/ssdlite.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ SSDlite
The SSDLite model is based on the `SSD: Single Shot MultiBox Detector
<https://arxiv.org/abs/1512.02325>`__, `Searching for MobileNetV3
<https://arxiv.org/abs/1905.02244>`__ and `MobileNetV2: Inverted Residuals and Linear
Bottlenecks <https://arxiv.org/abs/1801.04381>__` papers.
Bottlenecks <https://arxiv.org/abs/1801.04381>`__ papers.

.. betastatus:: detection module

Expand Down
35 changes: 29 additions & 6 deletions test/test_datasets_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,11 @@ def test_get_redirect_url_max_hops_exceeded(self, mocker):
assert mock.call_count == 1
assert mock.call_args[0][0].full_url == url

def test_check_md5(self):
@pytest.mark.parametrize("use_pathlib", (True, False))
def test_check_md5(self, use_pathlib):
fpath = TEST_FILE
if use_pathlib:
fpath = pathlib.Path(fpath)
correct_md5 = "9c0bb82894bb3af7f7675ef2b3b6dcdc"
false_md5 = ""
assert utils.check_md5(fpath, correct_md5)
Expand Down Expand Up @@ -116,7 +119,8 @@ def test_detect_file_type_incompatible(self, file):
utils._detect_file_type(file)

@pytest.mark.parametrize("extension", [".bz2", ".gz", ".xz"])
def test_decompress(self, extension, tmpdir):
@pytest.mark.parametrize("use_pathlib", (True, False))
def test_decompress(self, extension, tmpdir, use_pathlib):
def create_compressed(root, content="this is the content"):
file = os.path.join(root, "file")
compressed = f"{file}{extension}"
Expand All @@ -128,6 +132,8 @@ def create_compressed(root, content="this is the content"):
return compressed, file, content

compressed, file, content = create_compressed(tmpdir)
if use_pathlib:
compressed = pathlib.Path(compressed)

utils._decompress(compressed)

Expand All @@ -140,7 +146,8 @@ def test_decompress_no_compression(self):
with pytest.raises(RuntimeError):
utils._decompress("foo.tar")

def test_decompress_remove_finished(self, tmpdir):
@pytest.mark.parametrize("use_pathlib", (True, False))
def test_decompress_remove_finished(self, tmpdir, use_pathlib):
def create_compressed(root, content="this is the content"):
file = os.path.join(root, "file")
compressed = f"{file}.gz"
Expand All @@ -151,10 +158,20 @@ def create_compressed(root, content="this is the content"):
return compressed, file, content

compressed, file, content = create_compressed(tmpdir)
print(f"{type(compressed)=}")
if use_pathlib:
compressed = pathlib.Path(compressed)
tmpdir = pathlib.Path(tmpdir)

utils.extract_archive(compressed, tmpdir, remove_finished=True)
extracted_dir = utils.extract_archive(compressed, tmpdir, remove_finished=True)

assert not os.path.exists(compressed)
if use_pathlib:
assert isinstance(extracted_dir, pathlib.Path)
assert isinstance(compressed, pathlib.Path)
else:
assert isinstance(extracted_dir, str)
assert isinstance(compressed, str)

@pytest.mark.parametrize("extension", [".gz", ".xz"])
@pytest.mark.parametrize("remove_finished", [True, False])
Expand All @@ -167,7 +184,8 @@ def test_extract_archive_defer_to_decompress(self, extension, remove_finished, m

mocked.assert_called_once_with(file, filename, remove_finished=remove_finished)

def test_extract_zip(self, tmpdir):
@pytest.mark.parametrize("use_pathlib", (True, False))
def test_extract_zip(self, tmpdir, use_pathlib):
def create_archive(root, content="this is the content"):
file = os.path.join(root, "dst.txt")
archive = os.path.join(root, "archive.zip")
Expand All @@ -177,6 +195,8 @@ def create_archive(root, content="this is the content"):

return archive, file, content

if use_pathlib:
tmpdir = pathlib.Path(tmpdir)
archive, file, content = create_archive(tmpdir)

utils.extract_archive(archive, tmpdir)
Expand All @@ -189,7 +209,8 @@ def create_archive(root, content="this is the content"):
@pytest.mark.parametrize(
"extension, mode", [(".tar", "w"), (".tar.gz", "w:gz"), (".tgz", "w:gz"), (".tar.xz", "w:xz")]
)
def test_extract_tar(self, extension, mode, tmpdir):
@pytest.mark.parametrize("use_pathlib", (True, False))
def test_extract_tar(self, extension, mode, tmpdir, use_pathlib):
def create_archive(root, extension, mode, content="this is the content"):
src = os.path.join(root, "src.txt")
dst = os.path.join(root, "dst.txt")
Expand All @@ -203,6 +224,8 @@ def create_archive(root, extension, mode, content="this is the content"):

return archive, dst, content

if use_pathlib:
tmpdir = pathlib.Path(tmpdir)
archive, file, content = create_archive(tmpdir, extension, mode)

utils.extract_archive(archive, tmpdir)
Expand Down
23 changes: 18 additions & 5 deletions test/test_internet.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,48 @@
"""

import os
import pathlib
from urllib.error import URLError

import pytest
import torchvision.datasets.utils as utils


class TestDatasetUtils:
def test_download_url(self, tmpdir):
@pytest.mark.parametrize("use_pathlib", (True, False))
def test_download_url(self, tmpdir, use_pathlib):
if use_pathlib:
tmpdir = pathlib.Path(tmpdir)
url = "http://github.com/pytorch/vision/archive/master.zip"
try:
utils.download_url(url, tmpdir)
assert len(os.listdir(tmpdir)) != 0
except URLError:
pytest.skip(f"could not download test file '{url}'")

def test_download_url_retry_http(self, tmpdir):
@pytest.mark.parametrize("use_pathlib", (True, False))
def test_download_url_retry_http(self, tmpdir, use_pathlib):
if use_pathlib:
tmpdir = pathlib.Path(tmpdir)
url = "https://github.com/pytorch/vision/archive/master.zip"
try:
utils.download_url(url, tmpdir)
assert len(os.listdir(tmpdir)) != 0
except URLError:
pytest.skip(f"could not download test file '{url}'")

def test_download_url_dont_exist(self, tmpdir):
@pytest.mark.parametrize("use_pathlib", (True, False))
def test_download_url_dont_exist(self, tmpdir, use_pathlib):
if use_pathlib:
tmpdir = pathlib.Path(tmpdir)
url = "http://github.com/pytorch/vision/archive/this_doesnt_exist.zip"
with pytest.raises(URLError):
utils.download_url(url, tmpdir)

def test_download_url_dispatch_download_from_google_drive(self, mocker, tmpdir):
@pytest.mark.parametrize("use_pathlib", (True, False))
def test_download_url_dispatch_download_from_google_drive(self, mocker, tmpdir, use_pathlib):
if use_pathlib:
tmpdir = pathlib.Path(tmpdir)
url = "https://drive.google.com/file/d/1GO-BHUYRuvzr1Gtp2_fqXRsr9TIeYbhV/view"

id = "1GO-BHUYRuvzr1Gtp2_fqXRsr9TIeYbhV"
Expand All @@ -44,7 +57,7 @@ def test_download_url_dispatch_download_from_google_drive(self, mocker, tmpdir):
mocked = mocker.patch("torchvision.datasets.utils.download_file_from_google_drive")
utils.download_url(url, tmpdir, filename, md5)

mocked.assert_called_once_with(id, tmpdir, filename, md5)
mocked.assert_called_once_with(id, os.path.expanduser(tmpdir), filename, md5)


if __name__ == "__main__":
Expand Down
20 changes: 10 additions & 10 deletions test/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,14 +210,11 @@ def test_draw_segmentation_masks(colors, alpha, device):
num_masks, h, w = 2, 100, 100
dtype = torch.uint8
img = torch.randint(0, 256, size=(3, h, w), dtype=dtype, device=device)
masks = torch.randint(0, 2, (num_masks, h, w), dtype=torch.bool, device=device)
masks = torch.zeros((num_masks, h, w), dtype=torch.bool, device=device)
masks[0, 10:20, 10:20] = True
masks[1, 15:25, 15:25] = True

# For testing we enforce that there's no overlap between the masks. The
# current behaviour is that the last mask's color will take priority when
# masks overlap, but this makes testing slightly harder, so we don't really
# care
overlap = masks[0] & masks[1]
masks[:, overlap] = False

out = utils.draw_segmentation_masks(img, masks, colors=colors, alpha=alpha)
assert out.dtype == dtype
Expand All @@ -239,12 +236,15 @@ def test_draw_segmentation_masks(colors, alpha, device):
color = torch.tensor(color, dtype=dtype, device=device)

if alpha == 1:
assert (out[:, mask] == color[:, None]).all()
assert (out[:, mask & ~overlap] == color[:, None]).all()
elif alpha == 0:
assert (out[:, mask] == img[:, mask]).all()
assert (out[:, mask & ~overlap] == img[:, mask & ~overlap]).all()

interpolated_color = (img[:, mask] * (1 - alpha) + color[:, None] * alpha).to(dtype)
torch.testing.assert_close(out[:, mask], interpolated_color, rtol=0.0, atol=1.0)
interpolated_color = (img[:, mask & ~overlap] * (1 - alpha) + color[:, None] * alpha).to(dtype)
torch.testing.assert_close(out[:, mask & ~overlap], interpolated_color, rtol=0.0, atol=1.0)

interpolated_overlap = (img[:, overlap] * (1 - alpha)).to(dtype)
torch.testing.assert_close(out[:, overlap], interpolated_overlap, rtol=0.0, atol=1.0)


def test_draw_segmentation_masks_dtypes():
Expand Down
11 changes: 2 additions & 9 deletions torchvision/csrc/io/decoder/stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,8 @@ int Stream::openCodec(std::vector<DecoderMetadata>* metadata, int num_threads) {
codecCtx_->thread_count = num_threads;
} else {
// otherwise set sensible defaults
// with the special case for the different MPEG4 codecs
// that don't have threading context functions
if (codecCtx_->codec->capabilities & AV_CODEC_CAP_INTRA_ONLY) {
codecCtx_->thread_type = FF_THREAD_FRAME;
codecCtx_->thread_count = 2;
} else {
codecCtx_->thread_count = 8;
codecCtx_->thread_type = FF_THREAD_SLICE;
}
codecCtx_->thread_count = 8;
codecCtx_->thread_type = FF_THREAD_SLICE;
}

int ret;
Expand Down
4 changes: 2 additions & 2 deletions torchvision/datasets/caltech.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class Caltech101(VisionDataset):
target types. ``category`` represents the target class, and
``annotation`` is a list of points from a hand-generated outline.
Defaults to ``category``.
transform (callable, optional): A function/transform that takes in an PIL image
transform (callable, optional): A function/transform that takes in a PIL image
and returns a transformed version. E.g, ``transforms.RandomCrop``
target_transform (callable, optional): A function/transform that takes in the
target and transforms it.
Expand Down Expand Up @@ -151,7 +151,7 @@ class Caltech256(VisionDataset):
Args:
root (string): Root directory of dataset where directory
``caltech256`` exists or will be saved to if download is set to True.
transform (callable, optional): A function/transform that takes in an PIL image
transform (callable, optional): A function/transform that takes in a PIL image
and returns a transformed version. E.g, ``transforms.RandomCrop``
target_transform (callable, optional): A function/transform that takes in the
target and transforms it.
Expand Down
2 changes: 1 addition & 1 deletion torchvision/datasets/celeba.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class CelebA(VisionDataset):
Defaults to ``attr``. If empty, ``None`` will be returned as target.
transform (callable, optional): A function/transform that takes in an PIL image
transform (callable, optional): A function/transform that takes in a PIL image
and returns a transformed version. E.g, ``transforms.PILToTensor``
target_transform (callable, optional): A function/transform that takes in the
target and transforms it.
Expand Down
2 changes: 1 addition & 1 deletion torchvision/datasets/cifar.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class CIFAR10(VisionDataset):
``cifar-10-batches-py`` exists or will be saved to if download is set to True.
train (bool, optional): If True, creates dataset from training set, otherwise
creates from test set.
transform (callable, optional): A function/transform that takes in an PIL image
transform (callable, optional): A function/transform that takes in a PIL image
and returns a transformed version. E.g, ``transforms.RandomCrop``
target_transform (callable, optional): A function/transform that takes in the
target and transforms it.
Expand Down
Loading

0 comments on commit 9b92fd2

Please sign in to comment.