diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 000000000..1207566e1 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,42 @@ +name: "CodeQL" + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + schedule: + - cron: "31 5 * * 5" + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ python ] + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + queries: +security-and-quality + config-file: codeql.yml + + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{ matrix.language }}" diff --git a/codeql.yml b/codeql.yml new file mode 100644 index 000000000..796f8a6da --- /dev/null +++ b/codeql.yml @@ -0,0 +1,4 @@ +paths-ignore: + - dandi/_version.py + - dandi/due.py + - versioneer.py diff --git a/dandi/cli/tests/test_command.py b/dandi/cli/tests/test_command.py index 5cad750c5..55e023b35 100644 --- a/dandi/cli/tests/test_command.py +++ b/dandi/cli/tests/test_command.py @@ -46,9 +46,11 @@ def test_no_heavy_imports(): [ sys.executable, "-c", - "import sys; " - "import dandi.cli.command; " - "print(','.join(set(m.split('.')[0] for m in sys.modules)));", + ( + "import sys; " + "import dandi.cli.command; " + "print(','.join(set(m.split('.')[0] for m in sys.modules)));" + ), ], env=env, stdout=PIPE, diff --git a/dandi/cli/tests/test_ls.py b/dandi/cli/tests/test_ls.py index 27a43367e..da08bac92 100644 --- a/dandi/cli/tests/test_ls.py +++ b/dandi/cli/tests/test_ls.py @@ -91,8 +91,10 @@ def test_ls_path_url(): [ "-f", "yaml", - "https://api.dandiarchive.org/api/dandisets/000027/versions/draft" - "/assets/?path=sub-RAT123/", + ( + "https://api.dandiarchive.org/api/dandisets/000027/versions/draft" + "/assets/?path=sub-RAT123/" + ), ], ) assert r.exit_code == 0, r.output diff --git a/dandi/dandiapi.py b/dandi/dandiapi.py index 7510a9cb7..253a457c7 100644 --- a/dandi/dandiapi.py +++ b/dandi/dandiapi.py @@ -1250,7 +1250,7 @@ def __str__(self) -> str: @classmethod def from_base_data( - self, + cls, client: "DandiAPIClient", data: Dict[str, Any], metadata: Optional[Dict[str, Any]] = None, diff --git a/dandi/support/pyout.py b/dandi/support/pyout.py index 90b422428..a137cb69b 100644 --- a/dandi/support/pyout.py +++ b/dandi/support/pyout.py @@ -36,11 +36,11 @@ def naturalsize(v): return humanize.naturalsize(v) -def datefmt(v, fmt=u"%Y-%m-%d/%H:%M:%S"): +def datefmt(v, fmt="%Y-%m-%d/%H:%M:%S"): if isinstance(v, datetime.datetime): return v.strftime(fmt) else: - time.strftime(fmt, time.localtime(v)) + return time.strftime(fmt, time.localtime(v)) # def empty_for_none(v): @@ -71,8 +71,8 @@ def counts(values): color=dict( interval=[ [0, 1024, "blue"], - [1024, 1024 ** 2, "green"], - [1024 ** 2, None, "red"], + [1024, 1024**2, "green"], + [1024**2, None, "red"], ] ), aggregate=lambda x: naturalsize(sum(x)), diff --git a/dandi/tests/fixtures.py b/dandi/tests/fixtures.py index a48e8c6b3..76c02e64f 100644 --- a/dandi/tests/fixtures.py +++ b/dandi/tests/fixtures.py @@ -8,7 +8,6 @@ import re import shutil from subprocess import DEVNULL, check_output, run -import tempfile from time import sleep from typing import TYPE_CHECKING, Any, Callable, Dict, Iterator, List, Optional, Union from uuid import uuid4 @@ -246,30 +245,19 @@ def get_gitrepo_fixture( url: str, committish: Optional[str] = None, scope: Scope = "session", -) -> Callable[[], Iterator[str]]: +) -> Callable[[pytest.TempPathFactory], str]: if committish: raise NotImplementedError() @pytest.fixture(scope=scope) - def fixture() -> Iterator[str]: + def fixture(tmp_path_factory: pytest.TempPathFactory) -> str: skipif.no_network() skipif.no_git() - - path = tempfile.mktemp() # not using pytest's tmpdir fixture to not - # collide in different scopes etc. But we - # would need to remove it ourselves + path = str(tmp_path_factory.mktemp("gitrepo")) lgr.debug("Cloning %r into %r", url, path) - try: - runout = run(["git", "clone", "--depth=1", url, path]) - if runout.returncode: - raise RuntimeError(f"Failed to clone {url} into {path}") - yield path - finally: - try: - shutil.rmtree(path) - except BaseException as exc: - lgr.warning("Failed to remove %s - using Windows?: %s", path, exc) + run(["git", "clone", "--depth=1", url, path], check=True) + return path return fixture