From 711c3aaa4329f1267fa7abbc80db57d8f5ff5d51 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 23 Apr 2024 10:21:39 +0200 Subject: [PATCH] Add lint against linking into `main` branch on GitHub (#6078) ### What While investigating recently broken links (because of https://github.com/rerun-io/rerun/pull/5966#issuecomment-2071633876) I decided to add a lint against linking to stuff on changing branches (e.g. `/blobs/main`). Unfortunately I cannot cover it all (see https://github.com/rerun-io/rerun/issues/6077 for more), but this is an OK start. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6078?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6078?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6078) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- BUILD.md | 4 +-- CHANGELOG.md | 2 +- CMakeLists.txt | 2 +- README.md | 10 +++--- .../re_log_types/src/path/natural_ordering.rs | 2 +- crates/re_renderer/shader/colormap.wgsl | 2 +- crates/re_renderer/src/colormap.rs | 2 +- crates/re_types/tests/fuzzy.rs | 8 ++--- crates/re_viewer/src/ui/rerun_menu.rs | 4 +-- crates/rerun-cli/README.md | 10 +++--- crates/rerun/README.md | 10 +++--- docs/content/reference/about.md | 2 +- examples/python/arflow/README.md | 2 +- .../arkit_scenes/download_dataset.py | 4 +-- .../huggingface_pipeline.py | 2 +- .../detect_and_track_objects.py | 4 +-- examples/rust/objectron/src/main.rs | 2 +- lychee.toml | 1 + .../docs/templates/python/material/class.html | 2 +- .../templates/python/material/function.html | 2 +- rerun_py/pyproject.toml | 2 +- rerun_py/src/arrow.rs | 2 +- scripts/lint.py | 35 +++++++++++++++++++ 23 files changed, 76 insertions(+), 40 deletions(-) diff --git a/BUILD.md b/BUILD.md index 331af5c97e41..382603a4abeb 100644 --- a/BUILD.md +++ b/BUILD.md @@ -102,8 +102,8 @@ pixi run cpp-build-all High-level documentation for rerun can be found at [http://rerun.io/docs](http://rerun.io/docs). It is built from the separate repository [rerun-docs](https://github.com/rerun-io/rerun-docs). -- 🌊 [C++ API docs](https://ref.rerun.io/docs/cpp) are built with `doxygen` and hosted on GitHub. Use `pixi run cpp-docs` to build them locally. For details on the C++ doc-system, see [Writing Docs](https://github.com/rerun-io/rerun/blob/main/rerun_cpp/docs/writing_docs.md). -- 🐍 [Python API docs](https://ref.rerun.io/docs/python) are built via `mkdocs` and hosted on GitHub. For details on the python doc-system, see [Writing Docs](https://github.com/rerun-io/rerun/blob/main/rerun_py/docs/writing_docs.md). +- 🌊 [C++ API docs](https://ref.rerun.io/docs/cpp) are built with `doxygen` and hosted on GitHub. Use `pixi run cpp-docs` to build them locally. For details on the C++ doc-system, see [Writing Docs](rerun_cpp/docs/writing_docs.md). +- 🐍 [Python API docs](https://ref.rerun.io/docs/python) are built via `mkdocs` and hosted on GitHub. For details on the python doc-system, see [Writing Docs](rerun_py/docs/writing_docs.md). - πŸ¦€ [Rust API docs](https://docs.rs/rerun/) are hosted on . You can build them locally with: `cargo doc --all-features --no-deps --open`. ## Building for the web diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fc0c44c1a94..ecdcd1f4ba21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -661,7 +661,7 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi - Much more powerful UI, allowing query ranges relative to time cursor - πŸ•ΈοΈ The viewer can now be easily embedded in your web apps via our [npm package](https://www.npmjs.com/package/@rerun-io/web-viewer) - 🐍 ⚠️ Legacy Python API now removed, check the [migration guide](https://github.com/rerun-io/rerun/issues/723) if you're not using `rr.log` yet -- πŸ¦€ The new `StoreSubscriber` trait allows to be notified of all changes in the datastore. This can be used to build custom indices and trigger systems, and serves as a foundation for upcoming performance improvements. Check out [our example](https://github.com/rerun-io/rerun/blob/main/examples/rust/custom_store_subscriber/README.md) for more information. +- πŸ¦€ The new `StoreSubscriber` trait allows to be notified of all changes in the datastore. This can be used to build custom indices and trigger systems, and serves as a foundation for upcoming performance improvements. Check out [our example](examples/rust/custom_store_subscriber/README.md) for more information. ⚠️ Known issues on Visual Time Range: - Time cursor [sometimes stops scrolling correctly](https://github.com/rerun-io/rerun/issues/4246) on plot window diff --git a/CMakeLists.txt b/CMakeLists.txt index c9918f250cdb..0b1ebab184f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -138,7 +138,7 @@ message(STATUS "Rerun version ${RERUN_VERSION}") # Loguru logging library (https://github.com/emilk/loguru): set(CMAKE_DL_LIBS "dl") # Required by Loguru for backtraces -# Loguru, see https://github.com/emilk/loguru/blob/master/loguru_cmake_example/CMakeLists.txt +# Loguru, see https://github.com/emilk/loguru/blob/4adaa185883e3c04da25913579c451d3c32cfac1/loguru_cmake_example/CMakeLists.txt include(FetchContent) FetchContent_Declare(LoguruGitRepo GIT_REPOSITORY "https://github.com/emilk/loguru" # can be a filesystem path diff --git a/README.md b/README.md index 258507526f84..85f2879e051d 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,11 @@

- PyPi - crates.io - MIT - Apache - Rerun Discord + PyPi + crates.io + MIT + Apache + Rerun Discord

# Build time aware visualizations of multimodal data diff --git a/crates/re_log_types/src/path/natural_ordering.rs b/crates/re_log_types/src/path/natural_ordering.rs index 205ef3c608f9..f0f33b2a3195 100644 --- a/crates/re_log_types/src/path/natural_ordering.rs +++ b/crates/re_log_types/src/path/natural_ordering.rs @@ -1,7 +1,7 @@ //! Implement natural ordering for strings, so that "file5" < "file10". //! //! Crates considered: -//! * `human-sort`: - overflows on large integers +//! * `human-sort`: - overflows on large integers //! * `lexical-sort`: - comes with a huge unicode->ascii table //! * `natord`: - the one we're using diff --git a/crates/re_renderer/shader/colormap.wgsl b/crates/re_renderer/shader/colormap.wgsl index 68f34e44c350..003076893d70 100644 --- a/crates/re_renderer/shader/colormap.wgsl +++ b/crates/re_renderer/shader/colormap.wgsl @@ -86,7 +86,7 @@ fn colormap_turbo_srgb(t: f32) -> vec3f { // - use nested horner representation for polynomials // - polynomials were fitted to minimize maximum error (as opposed to least squares) // -// Data fitted from https://github.com/BIDS/colormap/blob/master/colormaps.py (CC0). +// Data fitted from https://github.com/BIDS/colormap/blob/bc549477db0c12b54a5928087552ad2cf274980f/colormaps.py (CC0). /// Returns a gamma-space sRGB in 0-1 range. /// This is a polynomial approximation from Viridis color map, assuming `t` is diff --git a/crates/re_renderer/src/colormap.rs b/crates/re_renderer/src/colormap.rs index ace54dd94d72..cb09679df988 100644 --- a/crates/re_renderer/src/colormap.rs +++ b/crates/re_renderer/src/colormap.rs @@ -112,7 +112,7 @@ pub fn colormap_turbo_srgb(t: f32) -> [u8; 4] { // - use nested horner representation for polynomials // - polynomials were fitted to minimize maximum error (as opposed to least squares) // -// Data fitted from https://github.com/BIDS/colormap/blob/master/colormaps.py (CC0). +// Data fitted from https://github.com/BIDS/colormap/blob/bc549477db0c12b54a5928087552ad2cf274980f/colormaps.py (CC0). /// Returns sRGB polynomial approximation from Viridis color map, assuming `t` is normalized. pub fn colormap_viridis_srgb(t: f32) -> [u8; 4] { diff --git a/crates/re_types/tests/fuzzy.rs b/crates/re_types/tests/fuzzy.rs index 3f9c9a6867b5..71ac1435d5d4 100644 --- a/crates/re_types/tests/fuzzy.rs +++ b/crates/re_types/tests/fuzzy.rs @@ -264,7 +264,7 @@ fn roundtrip() { // eprintln!("array = {array:#?}"); if field.name == "rerun.testing.components.AffixFuzzer21" { // TODO(jleibs): Fields that contain Float16 apparently don't supported fmt - // https://github.com/jorgecarleitao/arrow2/blob/main/src/array/primitive/fmt.rs#L35 + // https://github.com/rerun-io/re_arrow2/blob/33a32000001df800e4840d92c33b03e7007311e1/src/array/primitive/fmt.rs#L39 eprintln!("{} = Can't be printed (float16 not supported)", field.name); } else { eprintln!("{} = {array:#?}", field.name); @@ -326,7 +326,7 @@ fn roundtrip() { // eprintln!("array = {array:#?}"); if field.name == "rerun.testing.components.AffixFuzzer21" { // TODO(jleibs): Fields that contain Float16 apparently don't supported fmt - // https://github.com/jorgecarleitao/arrow2/blob/main/src/array/primitive/fmt.rs#L35 + // https://github.com/rerun-io/re_arrow2/blob/33a32000001df800e4840d92c33b03e7007311e1/src/array/primitive/fmt.rs#L39 eprintln!("{} = Can't be printed (float16 not supported)", field.name); } else { eprintln!("{} = {array:#?}", field.name); @@ -380,7 +380,7 @@ fn roundtrip() { // eprintln!("array = {array:#?}"); if field.name == "rerun.testing.components.AffixFuzzer21" { // TODO(jleibs): Fields that contain Float16 apparently don't supported fmt - // https://github.com/jorgecarleitao/arrow2/blob/main/src/array/primitive/fmt.rs#L35 + // https://github.com/rerun-io/re_arrow2/blob/33a32000001df800e4840d92c33b03e7007311e1/src/array/primitive/fmt.rs#L39 eprintln!("{} = Can't be printed (float16 not supported)", field.name); } else { eprintln!("{} = {array:#?}", field.name); @@ -433,7 +433,7 @@ fn roundtrip() { // eprintln!("array = {array:#?}"); if field.name == "rerun.testing.components.AffixFuzzer21" { // TODO(jleibs): Fields that contain Float16 apparently don't supported fmt - // https://github.com/jorgecarleitao/arrow2/blob/main/src/array/primitive/fmt.rs#L35 + // https://github.com/rerun-io/re_arrow2/blob/33a32000001df800e4840d92c33b03e7007311e1/src/array/primitive/fmt.rs#L39 eprintln!("{} = Can't be printed (float16 not supported)", field.name); } else { eprintln!("{} = {array:#?}", field.name); diff --git a/crates/re_viewer/src/ui/rerun_menu.rs b/crates/re_viewer/src/ui/rerun_menu.rs index e9270b132751..dc0575c886a2 100644 --- a/crates/re_viewer/src/ui/rerun_menu.rs +++ b/crates/re_viewer/src/ui/rerun_menu.rs @@ -503,7 +503,7 @@ fn debug_menu_options_ui( } if ui.button("SEGFAULT").clicked() { - // Taken from https://github.com/EmbarkStudios/crash-handling/blob/main/sadness-generator/src/lib.rs + // Taken from https://github.com/EmbarkStudios/crash-handling/blob/065f3dd9c1c318630e539375165cf74961b44bcc/sadness-generator/src/lib.rs /// This is the fixed address used to generate a segfault. It's possible that /// this address can be mapped and writable by the your process in which case a @@ -522,7 +522,7 @@ fn debug_menu_options_ui( } if ui.button("Stack overflow").clicked() { - // Taken from https://github.com/EmbarkStudios/crash-handling/blob/main/sadness-generator/src/lib.rs + // Taken from https://github.com/EmbarkStudios/crash-handling/blob/065f3dd9c1c318630e539375165cf74961b44bcc/sadness-generator/src/lib.rs fn recurse(data: u64) -> u64 { let mut buff = [0u8; 256]; buff[..9].copy_from_slice(b"junk data"); diff --git a/crates/rerun-cli/README.md b/crates/rerun-cli/README.md index a05eadaa39ef..bc26b4659ee0 100644 --- a/crates/rerun-cli/README.md +++ b/crates/rerun-cli/README.md @@ -5,11 +5,11 @@

- Latest version - Documentation - MIT - Apache - Rerun Discord + Latest version + Documentation + MIT + Apache + Rerun Discord

## Rerun command-line tool diff --git a/crates/rerun/README.md b/crates/rerun/README.md index fbcf092ab448..ce27bba93f94 100644 --- a/crates/rerun/README.md +++ b/crates/rerun/README.md @@ -5,11 +5,11 @@

- Latest version - Documentation - MIT - Apache - Rerun Discord + Latest version + Documentation + MIT + Apache + Rerun Discord

# Rerun Rust logging SDK diff --git a/docs/content/reference/about.md b/docs/content/reference/about.md index 8c3c0abb073f..96e6c7619217 100644 --- a/docs/content/reference/about.md +++ b/docs/content/reference/about.md @@ -8,7 +8,7 @@ To learn more about Rerun, the company, visit our Website at [https://www.rerun. Code & License -------------- The Rerun SDK & Viewer are open source, all code is available on [GitHub](https://github.com/rerun-io/rerun/) and open for contributions. -Licensing is permissive, the project is dual licensed under [MIT](https://github.com/rerun-io/rerun/blob/latest/LICENSE-MIT) & [Apache 2.0](https://github.com/rerun-io/rerun/blob/latest/LICENSE-APACHE). +Licensing is permissive, the project is dual licensed under [MIT](https://github.com/rerun-io/rerun/blob/main/LICENSE-MIT) & [Apache 2.0](https://github.com/rerun-io/rerun/blob/main/LICENSE-APACHE). Under the hood diff --git a/examples/python/arflow/README.md b/examples/python/arflow/README.md index a9be17a4c53f..51e52e0abf83 100644 --- a/examples/python/arflow/README.md +++ b/examples/python/arflow/README.md @@ -26,7 +26,7 @@ Watch our demo video: ## Get started -Please check our [project repo](https://github.com/cake-lab/ARFlow/blob/main/README.md), and refer to the individual [server](https://github.com/cake-lab/ARFlow/blob/main/python/README.md) and [client](https://github.com/cake-lab/ARFlow/blob/main/unity/README.md) installation guides. +Please see [the original project repo](https://github.com/cake-lab/ARFlow/blob/main/README.md), and refer to the individual [server](https://github.com/cake-lab/ARFlow/blob/main/python/README.md) and [client](https://github.com/cake-lab/ARFlow/blob/main/unity/README.md) installation guides. ## Citation diff --git a/examples/python/arkit_scenes/arkit_scenes/download_dataset.py b/examples/python/arkit_scenes/arkit_scenes/download_dataset.py index b9e1c9d2889e..2ed6ca7797d5 100644 --- a/examples/python/arkit_scenes/arkit_scenes/download_dataset.py +++ b/examples/python/arkit_scenes/arkit_scenes/download_dataset.py @@ -1,5 +1,5 @@ -# Copied from https://github.com/apple/ARKitScenes/blob/main/download_data.py -# Licensing information: https://github.com/apple/ARKitScenes/blob/main/LICENSE +# Copied from https://github.com/apple/ARKitScenes/blob/9ec0b99c3cd55e29fc0724e1229e2e6c2909ab45/download_data.py +# Licensing information: https://github.com/apple/ARKitScenes/blob/9ec0b99c3cd55e29fc0724e1229e2e6c2909ab45/LICENSE from __future__ import annotations import math diff --git a/examples/python/depth_guided_stable_diffusion/depth_guided_stable_diffusion/huggingface_pipeline.py b/examples/python/depth_guided_stable_diffusion/depth_guided_stable_diffusion/huggingface_pipeline.py index 9928f4843ff0..bf1f82ede0f6 100644 --- a/examples/python/depth_guided_stable_diffusion/depth_guided_stable_diffusion/huggingface_pipeline.py +++ b/examples/python/depth_guided_stable_diffusion/depth_guided_stable_diffusion/huggingface_pipeline.py @@ -708,7 +708,7 @@ def __call__( plain tuple. cross_attention_kwargs (`dict`, *optional*): A kwargs dictionary that if specified is passed along to the [`AttentionProcessor`] as defined in - [`self.processor`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/attention_processor.py). + [`self.processor`](https://github.com/huggingface/diffusers/blob/fc9fecc217e58d72c0d5796575c72088251ff4df/src/diffusers/models/attention_processor.py). clip_skip (`int`, *optional*): Number of layers to be skipped from CLIP while computing the prompt embeddings. A value of 1 means that the output of the pre-final layer will be used for computing the prompt embeddings. diff --git a/examples/python/detect_and_track_objects/detect_and_track_objects.py b/examples/python/detect_and_track_objects/detect_and_track_objects.py index 5eca234340c1..6ebb9d2e7789 100755 --- a/examples/python/detect_and_track_objects/detect_and_track_objects.py +++ b/examples/python/detect_and_track_objects/detect_and_track_objects.py @@ -35,8 +35,8 @@ CACHE_DIR: Final = EXAMPLE_DIR / "cache" # panoptic_coco_categories.json comes from: -# https://github.com/cocodataset/panopticapi/blob/master/panoptic_coco_categories.json -# License: https://github.com/cocodataset/panopticapi/blob/master/license.txt +# https://github.com/cocodataset/panopticapi/blob/7bb4655548f98f3fedc07bf37e9040a992b054b0/panoptic_coco_categories.json +# License: https://github.com/cocodataset/panopticapi/blob/7bb4655548f98f3fedc07bf37e9040a992b054b0/license.txt COCO_CATEGORIES_PATH = EXAMPLE_DIR / "panoptic_coco_categories.json" DOWNSCALE_FACTOR = 2 diff --git a/examples/rust/objectron/src/main.rs b/examples/rust/objectron/src/main.rs index 678b70db72d2..587af1314c98 100644 --- a/examples/rust/objectron/src/main.rs +++ b/examples/rust/objectron/src/main.rs @@ -153,7 +153,7 @@ fn log_ar_camera( // input (1920x1440); we need to convert between the two. // See: // - https://github.com/google-research-datasets/Objectron/issues/39 - // - https://github.com/google-research-datasets/Objectron/blob/master/notebooks/objectron-3dprojection-hub-tutorial.ipynb + // - https://github.com/google-research-datasets/Objectron/blob/c06a65165a18396e1e00091981fd1652875c97b5/notebooks/objectron-3dprojection-hub-tutorial.ipynb // swap px/py use glam::Vec3Swizzles as _; intrinsics.z_axis = intrinsics.z_axis.yxz(); diff --git a/lychee.toml b/lychee.toml index 3611d82bbe7e..0d396e251977 100644 --- a/lychee.toml +++ b/lychee.toml @@ -50,6 +50,7 @@ exclude_path = [ "venv", # Actually ignored files beyond .gitignore + "scripts/lint.py", # Contains url-matching regexes that aren't actual urls "scripts/screenshot_compare/assets/templates/", ] diff --git a/rerun_py/docs/templates/python/material/class.html b/rerun_py/docs/templates/python/material/class.html index a4408aa91bae..eca79046777e 100644 --- a/rerun_py/docs/templates/python/material/class.html +++ b/rerun_py/docs/templates/python/material/class.html @@ -1,5 +1,5 @@ {# Very minimally patched from: -https://github.com/mkdocstrings/python/blob/master/src/mkdocstrings_handlers/python/templates/material/_base/class.html +https://github.com/mkdocstrings/python/blob/b0123719ae90cb2d47e9b923166ac69fdce86632/src/mkdocstrings_handlers/python/templates/material/_base/class.html See: CHANGE comments below #} diff --git a/rerun_py/docs/templates/python/material/function.html b/rerun_py/docs/templates/python/material/function.html index f1dd1ed0e6bb..dabfa64bfafb 100644 --- a/rerun_py/docs/templates/python/material/function.html +++ b/rerun_py/docs/templates/python/material/function.html @@ -1,5 +1,5 @@ {# Very minimally patched from: -https://github.com/mkdocstrings/python/blob/master/src/mkdocstrings_handlers/python/templates/material/_base/function.html +https://github.com/mkdocstrings/python/blob/b0123719ae90cb2d47e9b923166ac69fdce86632/src/mkdocstrings_handlers/python/templates/material/_base/function.html See: CHANGE comments below #} diff --git a/rerun_py/pyproject.toml b/rerun_py/pyproject.toml index bdf5f80725d2..422270d6347f 100644 --- a/rerun_py/pyproject.toml +++ b/rerun_py/pyproject.toml @@ -70,7 +70,7 @@ extend-exclude = [ # generated "examples/python/objectron/objectron/proto/objectron/proto.py", - # Copied from https://github.com/huggingface/diffusers/blob/main/src/diffusers/pipelines/stable_diffusion/pipeline_stable_diffusion_depth2img.py + # Copied from https://github.com/huggingface/diffusers/blob/fc9fecc217e58d72c0d5796575c72088251ff4df/src/diffusers/pipelines/stable_diffusion/pipeline_stable_diffusion_depth2img.py "examples/python/depth_guided_stable_diffusion/depth_guided_stable_diffusion/huggingface_pipeline.py", # Copied from https://github.com/colmap/colmap/blob/bf3e19140f491c3042bfd85b7192ef7d249808ec/scripts/python/read_write_model.py diff --git a/rerun_py/src/arrow.rs b/rerun_py/src/arrow.rs index 52d818402c86..a305cb856e33 100644 --- a/rerun_py/src/arrow.rs +++ b/rerun_py/src/arrow.rs @@ -28,7 +28,7 @@ fn array_to_rust(arrow_array: &PyAny, name: Option<&str>) -> PyResult<(Box str | None: return None +def lint_url(url: str) -> str | None: + ALLOW_LIST_URLS = { + "https://github.com/lycheeverse/lychee/blob/master/lychee.example.toml", + "https://github.com/rerun-io/documentation/blob/main/src/utils/tokens.ts", + "https://github.com/rerun-io/rerun/blob/main/ARCHITECTURE.md", + "https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md", + "https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md", + "https://github.com/rerun-io/rerun/blob/main/LICENSE-APACHE", + "https://github.com/rerun-io/rerun/blob/main/LICENSE-MIT", + } + + if url in ALLOW_LIST_URLS: + return + + if m := re.match(r"https://github.com/.*/blob/(\w+)/.*", url): + branch = m.group(1) + if branch in ("main", "master", "trunk", "latest"): + if "#L" in url: + return f"Do not link directly to a file:line on '{branch}' - it may change! Use a perma-link instead (commit hash or tag). Url: {url}" + + if "/README.md" in url: + pass # Probably fine + elif url.startswith("https://github.com/rerun-io/rerun/blob/"): + pass # TODO(#6077): figure out how we best link to our own code from our docs + else: + return f"Do not link directly to a file on '{branch}' - it may disappear! Use a commit hash or tag instead. Url: {url}" + + return None + + def lint_line( line: str, prev_line: str | None, file_extension: str = "rs", is_in_docstring: bool = False ) -> str | None: @@ -116,6 +146,11 @@ def lint_line( if m := double_word.search(line): return f"Found double word: '{m.group(0)}'" + if m := re.search(r'https?://[^ )"]+', line): + url = m.group(0) + if err := lint_url(url): + return err + if file_extension not in ("txt"): if ( ellipsis.search(line)