Repository: RustPython/RustPython (language: rust)

Issue:
docs.rs cannot generate the documentation for rustpython-parser
rustpython-parser 0.2.0 has just been published on crates.io, unfortunately docs.rs appears to be [unable to generate the documentation](https://docs.rs/crate/rustpython-parser/0.2.0). The relevant line in [the log](https://docs.rs/crate/rustpython-parser/0.2.0/builds/718461) appears to be:

> [INFO] [stderr]   thread 'main' panicked at 'running lalrpop failed. Os { code: 30, kind: ReadOnlyFilesystem, message: "Read-only file system" }', build.rs:79:9

Quoting the [docs.rs documentation](https://docs.rs/about/builds#read-only-directories):

> Most of the sandbox is a read-only file system, including the source directory of your crate and its dependencies. If your build.rs generates files that are relevant for documentation, consider writing to the [cargo output directory](https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates), passed in the environment variable OUT_DIR.

So the [compiler/parser/build.rs](https://github.com/RustPython/RustPython/blob/main/compiler/parser/build.rs) script should be updated accordingly. I'll try to make a PR :)


Discussion / hints:

Fix patch:
diff --git a/.gitignore b/.gitignore
index 3b098f1c89..23facc8e6e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,5 +19,3 @@ flamescope.json
 
 extra_tests/snippets/resources
 extra_tests/not_impl.py
-
-compiler/parser/python.rs
diff --git a/compiler/parser/build.rs b/compiler/parser/build.rs
index 4559f2630f..f9a3439b3d 100644
--- a/compiler/parser/build.rs
+++ b/compiler/parser/build.rs
@@ -1,22 +1,22 @@
 use std::fmt::Write as _;
 use std::fs::File;
 use std::io::{BufRead, BufReader, BufWriter, Write};
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 use tiny_keccak::{Hasher, Sha3};
 
 fn main() -> anyhow::Result<()> {
     const SOURCE: &str = "python.lalrpop";
-    const TARGET: &str = "python.rs";
+    let out_dir = PathBuf::from(std::env::var_os("OUT_DIR").unwrap());
 
     println!("cargo:rerun-if-changed={SOURCE}");
 
-    try_lalrpop(SOURCE, TARGET)?;
-    gen_phf();
+    try_lalrpop(SOURCE, &out_dir.join("python.rs"))?;
+    gen_phf(&out_dir);
 
     Ok(())
 }
 
-fn requires_lalrpop(source: &str, target: &str) -> Option<String> {
+fn requires_lalrpop(source: &str, target: &Path) -> Option<String> {
     let Ok(target) = File::open(target) else {
         return Some("python.rs doesn't exist. regenerate.".to_owned());
     };
@@ -68,16 +68,22 @@ fn requires_lalrpop(source: &str, target: &str) -> Option<String> {
     None
 }
 
-fn try_lalrpop(source: &str, target: &str) -> anyhow::Result<()> {
+fn try_lalrpop(source: &str, target: &Path) -> anyhow::Result<()> {
     let Some(_message) = requires_lalrpop(source, target) else {
         return Ok(());
     };
 
     #[cfg(feature = "lalrpop")]
-    lalrpop::process_root().unwrap_or_else(|e| {
-        println!("cargo:warning={_message}");
-        panic!("running lalrpop failed. {e:?}");
-    });
+    // We are not using lalrpop::process_root() or Configuration::process_current_dir()
+    // because of https://github.com/lalrpop/lalrpop/issues/699.
+    lalrpop::Configuration::new()
+        .use_cargo_dir_conventions()
+        .set_in_dir(Path::new("."))
+        .process()
+        .unwrap_or_else(|e| {
+            println!("cargo:warning={_message}");
+            panic!("running lalrpop failed. {e:?}");
+        });
 
     #[cfg(not(feature = "lalrpop"))]
     {
@@ -98,8 +104,7 @@ fn sha_equal(expected_sha3_str: &str, actual_sha3: &[u8; 32]) -> bool {
     *actual_sha3 == expected_sha3
 }
 
-fn gen_phf() {
-    let out_dir = PathBuf::from(std::env::var_os("OUT_DIR").unwrap());
+fn gen_phf(out_dir: &Path) {
     let mut kwds = phf_codegen::Map::new();
     let kwds = kwds
         // Alphabetical keywords:
diff --git a/compiler/parser/src/python.rs b/compiler/parser/src/python.rs
index e38af9b734..a00274d6c4 100644
--- a/compiler/parser/src/python.rs
+++ b/compiler/parser/src/python.rs
@@ -1,3 +1,3 @@
 #![allow(clippy::all)]
 #![allow(unused)]
-include!("../python.rs");
+include!(concat!(env!("OUT_DIR"), "/python.rs"));


Test patch: