Skip to main content

An extremely fast Python linter, written in Rust.

Project description

ruff

Actions status PyPI version

An extremely fast Python linter, written in Rust.

Bar chart with benchmark results

Linting the CPython codebase from scratch.

  • ⚡️ 10-100x faster than existing linters
  • 🐍 Installable via pip
  • 🤝 Python 3.10 compatibility
  • 🛠️ pyproject.toml support
  • 📦 ESLint-inspired cache support
  • 🔧 ESLint-inspired --fix support
  • 👀 TypeScript-inspired --watch support

ruff is a proof-of-concept and not yet intended for production use. It supports only a small subset of the Flake8 rules, and may crash on your codebase.

Read the launch blog post.

Installation and usage

Installation

Available as ruff on PyPI:

pip install ruff

Usage

To run ruff, try any of the following:

ruff path/to/code/to/check.py
ruff path/to/code/
ruff path/to/code/*.py

You can run ruff in --watch mode to automatically re-run on-change:

ruff path/to/code/ --watch

ruff also works with Pre-Commit (requires Cargo on system):

repos:
- repo: https://github.com/charliermarsh/ruff
  rev: v0.0.29
  hooks:
    - id: lint

Configuration

ruff is configurable both via pyproject.toml and the command line.

For example, you could configure ruff to only enforce a subset of rules with:

[tool.ruff]
line-length = 88
select = [
    "F401",
    "F403",
]

Alternatively, on the command-line:

ruff path/to/code/ --select F401 F403

See ruff --help for more:

ruff (v0.0.29)
An extremely fast Python linter.

USAGE:
    ruff [OPTIONS] <FILES>...

ARGS:
    <FILES>...

OPTIONS:
    -e, --exit-zero             Exit with status code "0", even upon detecting errors
    -f, --fix                   Attempt to automatically fix lint errors
    -h, --help                  Print help information
        --ignore <IGNORE>...    Comma-separated list of error codes to ignore
    -n, --no-cache              Disable cache reads
    -q, --quiet                 Disable all logging (but still exit with status code "1" upon
                                detecting errors)
        --select <SELECT>...    Comma-separated list of error codes to enable
    -v, --verbose               Enable verbose logging
    -w, --watch                 Run in watch mode by re-running whenever files change

Compatibility with Black

ruff is intended to be compatible with Black, and should be compatible out-of-the-box as long as the line-length setting is consistent between the two.

As a project, ruff is designed to be used alongside Black and, as such, will defer implementing lint rules that are obviated by Black (e.g., stylistic rules).

Rules

Code Name Message
E402 ModuleImportNotAtTopOfFile Module level import not at top of file
E501 LineTooLong Line too long
E711 NoneComparison Comparison to None should be cond is None
E712 TrueFalseComparison Comparison to True should be cond is True
E713 NotInTest Test for membership should be not in
E714 NotIsTest Test for object identity should be is not
E731 DoNotAssignLambda Do not assign a lambda expression, use a def
E902 IOError No such file or directory: ...
F401 UnusedImport ... imported but unused
F403 ImportStarUsage Unable to detect undefined names
F541 FStringMissingPlaceholders f-string without any placeholders
F631 AssertTuple Assert test is a non-empty tuple, which is always True
F634 IfTuple If test is a tuple, which is always True
F704 YieldOutsideFunction a yield or yield from statement outside of a function/method
F706 ReturnOutsideFunction a return statement outside of a function/method
F707 DefaultExceptNotLast an except: block as not the last exception handler
F821 UndefinedName Undefined name ...
F822 UndefinedExport Undefined name ... in __all__
F823 UndefinedLocal Local variable ... referenced before assignment
F831 DuplicateArgumentName Duplicate argument name in function definition
F841 UnusedVariable Local variable ... is assigned to but never used
F901 RaiseNotImplemented raise NotImplemented should be raise NotImplementedError
R001 UselessObjectInheritance Class ... inherits from object
R002 NoAssertEquals assertEquals is deprecated, use assertEqual instead

Development

ruff is written in Rust (1.63.0). You'll need to install the Rust toolchain for development.

Assuming you have cargo installed, you can run:

cargo run resources/test/fixtures
cargo fmt
cargo clippy
cargo test

Deployment

ruff is distributed on PyPI, and published via maturin.

See: .github/workflows/release.yaml.

Benchmarking

First, clone CPython. It's a large and diverse Python codebase, which makes it a good target for benchmarking.

git clone --branch 3.10 https://github.com/python/cpython.git resources/test/cpython

Add this pyproject.toml to the CPython directory:

[tool.linter]
line-length = 88
exclude = [
    "Lib/lib2to3/tests/data/bom.py",
    "Lib/lib2to3/tests/data/crlf.py",
    "Lib/lib2to3/tests/data/different_encoding.py",
    "Lib/lib2to3/tests/data/false_encoding.py",
    "Lib/lib2to3/tests/data/py2_test_grammar.py",
    "Lib/test/bad_coding2.py",
    "Lib/test/badsyntax_3131.py",
    "Lib/test/badsyntax_pep3120.py",
    "Lib/test/encoded_modules/module_iso_8859_1.py",
    "Lib/test/encoded_modules/module_koi8_r.py",
    "Lib/test/test_fstring.py",
    "Lib/test/test_grammar.py",
    "Lib/test/test_importlib/test_util.py",
    "Lib/test/test_named_expressions.py",
    "Lib/test/test_patma.py",
    "Lib/test/test_source_encoding.py",
    "Tools/c-analyzer/c_parser/parser/_delim.py",
    "Tools/i18n/pygettext.py",
    "Tools/test2to3/maintest.py",
    "Tools/test2to3/setup.py",
    "Tools/test2to3/test/test_foo.py",
    "Tools/test2to3/test2to3/hello.py",
]

Next, to benchmark the release build:

cargo build --release

hyperfine --ignore-failure --warmup 1 \
  "./target/release/ruff ./resources/test/cpython/ --no-cache" \
  "./target/release/ruff ./resources/test/cpython/"

Benchmark 1: ./target/release/ruff ./resources/test/cpython/ --no-cache
  Time (mean ± σ):     353.6 ms ±   7.6 ms    [User: 2868.8 ms, System: 171.5 ms]
  Range (min  max):   344.4 ms  367.3 ms    10 runs

Benchmark 2: ./target/release/ruff ./resources/test/cpython/
  Time (mean ± σ):      59.6 ms ±   2.5 ms    [User: 36.4 ms, System: 345.6 ms]
  Range (min  max):    55.9 ms   67.0 ms    48 runs

To benchmark against the ecosystem's existing tools:

hyperfine --ignore-failure --warmup 5 \
  "./target/release/ruff ./resources/test/cpython/ --no-cache" \
  "pylint --recursive=y resources/test/cpython/" \
  "pyflakes resources/test/cpython" \
  "autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython" \
  "pycodestyle resources/test/cpython" \
  "pycodestyle --select E501 resources/test/cpython" \
  "flake8 resources/test/cpython" \
  "flake8 --select=F831,F541,F634,F403,F706,F901,E501 resources/test/cpython" \
  "python -m scripts.run_flake8 resources/test/cpython" \
  "python -m scripts.run_flake8 resources/test/cpython --select=F831,F541,F634,F403,F706,F901,E501"

In order, these evaluate:

  • ruff
  • Pylint
  • PyFlakes
  • autoflake
  • pycodestyle
  • pycodestyle, limited to the checks supported by ruff
  • Flake8
  • Flake8, limited to the checks supported by ruff
  • Flake8, with a hack to enable multiprocessing on macOS
  • Flake8, with a hack to enable multiprocessing on macOS, limited to the checks supported by ruff

(You can poetry install from ./scripts to create a working environment for the above.)

Benchmark 1: ./target/release/ruff ./resources/test/cpython/ --no-cache
  Time (mean ± σ):     469.3 ms ±  16.3 ms    [User: 2663.0 ms, System: 972.5 ms]
  Range (min  max):   445.2 ms  494.8 ms    10 runs

Benchmark 2: pylint --recursive=y resources/test/cpython/
  Time (mean ± σ):     27.211 s ±  0.097 s    [User: 26.405 s, System: 0.799 s]
  Range (min  max):   27.056 s  27.349 s    10 runs

Benchmark 3: pyflakes resources/test/cpython
  Time (mean ± σ):     27.309 s ±  0.033 s    [User: 27.137 s, System: 0.169 s]
  Range (min  max):   27.267 s  27.372 s    10 runs

Benchmark 4: autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython
  Time (mean ± σ):      8.027 s ±  0.024 s    [User: 74.255 s, System: 0.953 s]
  Range (min  max):    7.969 s   8.052 s    10 runs

Benchmark 5: pycodestyle resources/test/cpython
  Time (mean ± σ):     41.666 s ±  0.266 s    [User: 41.531 s, System: 0.132 s]
  Range (min  max):   41.295 s  41.980 s    10 runs

Benchmark 6: pycodestyle --select E501 resources/test/cpython
  Time (mean ± σ):     14.547 s ±  0.077 s    [User: 14.466 s, System: 0.079 s]
  Range (min  max):   14.429 s  14.695 s    10 runs

Benchmark 7: flake8 resources/test/cpython
  Time (mean ± σ):     75.700 s ±  0.152 s    [User: 75.254 s, System: 0.440 s]
  Range (min  max):   75.513 s  76.014 s    10 runs

Benchmark 8: flake8 --select=F831,F541,F634,F403,F706,F901,E501 resources/test/cpython
  Time (mean ± σ):     75.122 s ±  0.532 s    [User: 74.677 s, System: 0.440 s]
  Range (min  max):   74.130 s  75.606 s    10 runs

Benchmark 9: python -m scripts.run_flake8 resources/test/cpython
  Time (mean ± σ):     12.794 s ±  0.147 s    [User: 90.792 s, System: 0.738 s]
  Range (min  max):   12.606 s  13.030 s    10 runs

Benchmark 10: python -m scripts.run_flake8 resources/test/cpython --select=F831,F541,F634,F403,F706,F901,E501
  Time (mean ± σ):     12.487 s ±  0.118 s    [User: 90.052 s, System: 0.714 s]
  Range (min  max):   12.265 s  12.665 s    10 runs

Summary
  './target/release/ruff ./resources/test/cpython/ --no-cache' ran
   17.10 ± 0.60 times faster than 'autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython'
   26.60 ± 0.96 times faster than 'python -m scripts.run_flake8 resources/test/cpython --select=F831,F541,F634,F403,F706,F901,E501'
   27.26 ± 1.00 times faster than 'python -m scripts.run_flake8 resources/test/cpython'
   30.99 ± 1.09 times faster than 'pycodestyle --select E501 resources/test/cpython'
   57.98 ± 2.03 times faster than 'pylint --recursive=y resources/test/cpython/'
   58.19 ± 2.02 times faster than 'pyflakes resources/test/cpython'
   88.77 ± 3.14 times faster than 'pycodestyle resources/test/cpython'
  160.06 ± 5.68 times faster than 'flake8 --select=F831,F541,F634,F403,F706,F901,E501 resources/test/cpython'
  161.29 ± 5.61 times faster than 'flake8 resources/test/cpython'

License

MIT

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ruff-0.0.29.tar.gz (89.0 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

ruff-0.0.29-py3-none-win_amd64.whl (2.5 MB view details)

Uploaded Python 3Windows x86-64

ruff-0.0.29-py3-none-win32.whl (2.4 MB view details)

Uploaded Python 3Windows x86

ruff-0.0.29-py3-none-musllinux_1_2_x86_64.whl (2.7 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

ruff-0.0.29-py3-none-musllinux_1_2_i686.whl (2.6 MB view details)

Uploaded Python 3musllinux: musl 1.2+ i686

ruff-0.0.29-py3-none-musllinux_1_2_armv7l.whl (2.4 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARMv7l

ruff-0.0.29-py3-none-musllinux_1_2_aarch64.whl (2.5 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

ruff-0.0.29-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl (2.2 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ s390x

ruff-0.0.29-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (2.0 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ppc64le

ruff-0.0.29-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl (2.1 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ppc64

ruff-0.0.29-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.8 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARMv7l

ruff-0.0.29-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.5 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

ruff-0.0.29-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.whl (2.6 MB view details)

Uploaded Python 3manylinux: glibc 2.12+ x86-64

ruff-0.0.29-py3-none-manylinux_2_12_i686.manylinux2010_i686.whl (2.7 MB view details)

Uploaded Python 3manylinux: glibc 2.12+ i686

ruff-0.0.29-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl (5.0 MB view details)

Uploaded Python 3macOS 10.9+ universal2 (ARM64, x86-64)macOS 10.9+ x86-64macOS 11.0+ ARM64

ruff-0.0.29-py3-none-macosx_10_7_x86_64.whl (2.6 MB view details)

Uploaded Python 3macOS 10.7+ x86-64

File details

Details for the file ruff-0.0.29.tar.gz.

File metadata

  • Download URL: ruff-0.0.29.tar.gz
  • Upload date:
  • Size: 89.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.8.10

File hashes

Hashes for ruff-0.0.29.tar.gz
Algorithm Hash digest
SHA256 c58c6056112d9147819526fd1e51d98fd0341530e5ed95e1aeb4c268eff9a36e
MD5 00af0d64c34667393c4e509e0a781d98
BLAKE2b-256 921cc876959699a7d59f19685e120ec5b785daa50127f8b4a0f92f2b41bba9da

See more details on using hashes here.

File details

Details for the file ruff-0.0.29-py3-none-win_amd64.whl.

File metadata

  • Download URL: ruff-0.0.29-py3-none-win_amd64.whl
  • Upload date:
  • Size: 2.5 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.8.10

File hashes

Hashes for ruff-0.0.29-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 23f73aa750ca3bb4a603775ce72fe2346e34bcca6110aa25f2ebc47586652e1f
MD5 dcc0cb4a3b0ed933cbcb336352129f0a
BLAKE2b-256 4d8746a4cbeec2442df0c6f3c6a55487539d158dd47f6042ed93a3bdf1259057

See more details on using hashes here.

File details

Details for the file ruff-0.0.29-py3-none-win32.whl.

File metadata

  • Download URL: ruff-0.0.29-py3-none-win32.whl
  • Upload date:
  • Size: 2.4 MB
  • Tags: Python 3, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.8.10

File hashes

Hashes for ruff-0.0.29-py3-none-win32.whl
Algorithm Hash digest
SHA256 b0e197e43bcaafe1bab7352eee7284c2b48baed74b26a0092f463da1608faa86
MD5 3d62727578bfa26dfb3d502236d07ab9
BLAKE2b-256 fe63d69814109452e4a3c5b229af7d24e6abcb9807b47641f31bde6648e8e543

See more details on using hashes here.

File details

Details for the file ruff-0.0.29-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for ruff-0.0.29-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 fd79aead1c86e6c77cd6dbc56365fec84b470a789eb98d4ba54ad7f44147eefd
MD5 3c018ec544bf0c59cd616dfa7264d89f
BLAKE2b-256 aedb42fd2c9c9dc9d8580c1aa7f762938b8cc1e2f70faf2bf146ef5616b844c1

See more details on using hashes here.

File details

Details for the file ruff-0.0.29-py3-none-musllinux_1_2_i686.whl.

File metadata

  • Download URL: ruff-0.0.29-py3-none-musllinux_1_2_i686.whl
  • Upload date:
  • Size: 2.6 MB
  • Tags: Python 3, musllinux: musl 1.2+ i686
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.8.10

File hashes

Hashes for ruff-0.0.29-py3-none-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 923b8a9f2f76a4b46237008e9d88db5219f6d2980766fd3daca2b250e81662c0
MD5 f5cc4b888de44d6688938db689f61523
BLAKE2b-256 19569cbf4187e67652e1ae99747d34d41d8553614a17b622536edbb187f9252f

See more details on using hashes here.

File details

Details for the file ruff-0.0.29-py3-none-musllinux_1_2_armv7l.whl.

File metadata

File hashes

Hashes for ruff-0.0.29-py3-none-musllinux_1_2_armv7l.whl
Algorithm Hash digest
SHA256 139af0a1251bfc80325de67b59e523e8053a74d92c0908634fd1c6849ea0ddad
MD5 beb2962f13f702fc32692bf79f187db3
BLAKE2b-256 d5436bdaff695de417ac910ba8f4279cc1b5915a5c292ef568b8369dd6dab33b

See more details on using hashes here.

File details

Details for the file ruff-0.0.29-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for ruff-0.0.29-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 37244146c52852ef4c016c49d4701944d68a2e5af6dd7a68a1fe8651c8f870f9
MD5 78863418f224f1ac160ca3fc9ccea387
BLAKE2b-256 e64acaa415e1f771bbfef3e699d0e117d52caacc68650c67056d6f59468e2f9d

See more details on using hashes here.

File details

Details for the file ruff-0.0.29-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl.

File metadata

File hashes

Hashes for ruff-0.0.29-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl
Algorithm Hash digest
SHA256 b7a068515fc287ab84ba41fa16c89888417b068a4c368be0e154cc157d9408a4
MD5 0ee2d78889cc210a2be2f36e7a2d9a7b
BLAKE2b-256 05d3347fb87b2ef5272e6adf6c5d4606301bc1df63c1bd2c6804f2e1bf37eba8

See more details on using hashes here.

File details

Details for the file ruff-0.0.29-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl.

File metadata

File hashes

Hashes for ruff-0.0.29-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl
Algorithm Hash digest
SHA256 e2d32edead39d692762fa540a8bbc537bed4ee2f43edf646f25eee280880cac4
MD5 8f835da8c4a8e1f3f41d365d0404fc10
BLAKE2b-256 77bcb554b1ac337401ef871e4b488900db4db9f50bcd80fa05665b4a859c7439

See more details on using hashes here.

File details

Details for the file ruff-0.0.29-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl.

File metadata

File hashes

Hashes for ruff-0.0.29-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl
Algorithm Hash digest
SHA256 4dcd4ce4a3b5a7213139ad17596cb1adc383de8df71d88f6f1af5be33d1ccbdf
MD5 0e8d6c4077a4c8adbce5c0846f5c24a5
BLAKE2b-256 2a3a93eda69c9a67105aa88dff0e1a903f58eeb510b42016b2900a91ee9b7a88

See more details on using hashes here.

File details

Details for the file ruff-0.0.29-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for ruff-0.0.29-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 0ae617a9cef14190f2c724e9289d73b24af11cfc7c4c554e331e131211237f8b
MD5 738156c617dd2f214c94f41d243e34c4
BLAKE2b-256 f2fb2b3fd4c5ac1a4c6ebfe61f88275dd409855987fa4018ef752fe3aeb5a1b7

See more details on using hashes here.

File details

Details for the file ruff-0.0.29-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for ruff-0.0.29-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 fd65a1c92b3995b1bd337728b64f09b94644683d078804720e9aa6f771e1b535
MD5 9b13fcfb4faa6bc224859b12e5a3200f
BLAKE2b-256 db526c8813f026b720a199f82c68f9bfc683efc326319cc0d8f87c40ea4e2e1e

See more details on using hashes here.

File details

Details for the file ruff-0.0.29-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.whl.

File metadata

File hashes

Hashes for ruff-0.0.29-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 a3a48b27326f6df08ebbfedd043631f8cad952b767da3cab90874818d6b55896
MD5 7ec5ef6938d0ad3563acec0838c3cb56
BLAKE2b-256 d798f098f9f620bd62f1bd044e87a86132aaa83fb390cf5fc1ae41954b84709b

See more details on using hashes here.

File details

Details for the file ruff-0.0.29-py3-none-manylinux_2_12_i686.manylinux2010_i686.whl.

File metadata

File hashes

Hashes for ruff-0.0.29-py3-none-manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 d73d8a3c1203e66278a6501db1bbfb08572c8e54f9a6c476f5b024afddcc790a
MD5 47d63734c3547777b61f017b58f4c8a0
BLAKE2b-256 0c83ca0ff53e4d989df2c59faefa81bfc6c59a7965554e2a6f186e7abd5c0a43

See more details on using hashes here.

File details

Details for the file ruff-0.0.29-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for ruff-0.0.29-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 273921105e6e1e9bfa090341d02903c291bf6b82e48c7abfa751d679f4700da2
MD5 f10e09275c281271ba9f8687a4197583
BLAKE2b-256 7cb8b3769ffa6f25ae3813e22896347f1464daf63c5de779f1b73f911bbc161c

See more details on using hashes here.

File details

Details for the file ruff-0.0.29-py3-none-macosx_10_7_x86_64.whl.

File metadata

File hashes

Hashes for ruff-0.0.29-py3-none-macosx_10_7_x86_64.whl
Algorithm Hash digest
SHA256 14c07ecc8986c51b7e7b4a8cd26a89e601856ca2674f5b90ac538b87c576e9bb
MD5 432032717ea73ba875db93b071a08231
BLAKE2b-256 9afd3e6079e632c69827bc400a23bc8089e5c64b28fbc6bbd2b14a6ed6d7a649

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page