diff --git a/Cargo.lock b/Cargo.lock index 095a3dca37..30cd2978a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1473,12 +1473,6 @@ dependencies = [ "malachite-nz", ] -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - [[package]] name = "matches" version = "0.1.10" @@ -2383,8 +2377,8 @@ dependencies = [ name = "rustpython-derive-impl" version = "0.4.0" dependencies = [ + "indexmap", "itertools 0.14.0", - "maplit", "proc-macro2", "quote", "rustpython-compiler-core", diff --git a/derive-impl/Cargo.toml b/derive-impl/Cargo.toml index 66ed67cef8..6d9e3772a5 100644 --- a/derive-impl/Cargo.toml +++ b/derive-impl/Cargo.toml @@ -16,11 +16,11 @@ rustpython-doc = { workspace = true } itertools = { workspace = true } syn = { workspace = true, features = ["full", "extra-traits"] } -maplit = "1.0.2" proc-macro2 = { workspace = true } quote = { workspace = true } syn-ext = { version = "0.5.0", features = ["full"] } textwrap = { version = "0.16.1", default-features = false } +indexmap = { workspace = true } [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/derive-impl/src/compile_bytecode.rs b/derive-impl/src/compile_bytecode.rs index fc349a7ed4..29c90fa947 100644 --- a/derive-impl/src/compile_bytecode.rs +++ b/derive-impl/src/compile_bytecode.rs @@ -14,130 +14,187 @@ //! ``` use crate::Diagnostic; +use crate::util::{check_duplicate, check_duplicate_msg}; use proc_macro2::{Span, TokenStream}; use quote::quote; use rustpython_compiler_core::{Mode, bytecode::CodeObject, frozen}; use std::sync::LazyLock; use std::{ - collections::HashMap, + collections::BTreeMap, env, fs, path::{Path, PathBuf}, }; +use syn::Token; use syn::{ self, LitByteStr, LitStr, Macro, parse::{ParseStream, Parser, Result as ParseResult}, + punctuated::Punctuated, spanned::Spanned, }; static CARGO_MANIFEST_DIR: LazyLock = LazyLock::new(|| { PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR is not present")) }); +fn resolve_path(path: &Path) -> std::borrow::Cow<'_, Path> { + if path.is_absolute() { + path.into() + } else { + CARGO_MANIFEST_DIR.join(path).into() + } +} -enum CompilationSourceKind { - /// Source is a File (Path) - File(PathBuf), +enum CompilationSource { + /// Source is a single module + Path(PathBuf), /// Direct Raw source code SourceCode(String), - /// Source is a directory - Dir(PathBuf), + /// Source is a directory of modules + LibPath(PathBuf), } +#[derive(Clone)] struct CompiledModule { code: CodeObject, package: bool, } -struct CompilationSource { - kind: CompilationSourceKind, - span: (Span, Span), -} - -pub trait Compiler { +pub trait Compiler: Sync { fn compile( &self, source: &str, mode: Mode, - module_name: String, + source_path: String, ) -> Result>; } impl CompilationSource { - fn compile_string D>( - &self, + fn compile_string( source: &str, mode: Mode, - module_name: String, + module_name: &str, compiler: &dyn Compiler, - origin: F, - ) -> Result { - compiler.compile(source, mode, module_name).map_err(|err| { - Diagnostic::spans_error( - self.span, - format!("Python compile error from {}: {}", origin(), err), - ) - }) + ) -> Result> { + compiler.compile(source, mode, format!("")) } fn compile( &self, mode: Mode, module_name: String, + excludes: &[pattern::ModulePattern], compiler: &dyn Compiler, - ) -> Result, Diagnostic> { - match &self.kind { - CompilationSourceKind::Dir(rel_path) => self.compile_dir( - &CARGO_MANIFEST_DIR.join(rel_path), - String::new(), - mode, - compiler, - ), - _ => Ok(hashmap! { - module_name.clone() => CompiledModule { - code: self.compile_single(mode, module_name, compiler)?, + ) -> Result, String> { + let mut dir = DirWalker::new(excludes); + match self { + CompilationSource::LibPath(path) => dir.walk(&resolve_path(path), "")?, + CompilationSource::Path(path) => dir.add_entry(resolve_path(path).into(), "")?, + CompilationSource::SourceCode(_) => { + let module = CompiledModule { + code: self.compile_single(mode, &module_name, compiler)?, package: false, - }, - }), + }; + return Ok(vec![(module_name, module)]); + } + } + let do_compile = |(module_name, (path, package)): (String, (PathBuf, _))| { + let code = Self::compile_file(&path, mode, &module_name, compiler)?; + Ok((module_name, CompiledModule { code, package })) + }; + if dir.modules.len() > 32 { + par_map(dir.modules, do_compile).collect() + } else { + dir.modules.into_iter().map(do_compile).collect() } } + fn compile_file( + path: &Path, + mode: Mode, + module_name: &str, + compiler: &dyn Compiler, + ) -> Result { + let compile_path = |src_path: &Path| { + let source = fs::read_to_string(resolve_path(src_path)) + .map_err(|err| format!("Error reading file {path:?}: {err}"))?; + Self::compile_string(&source, mode, module_name, compiler).map_err(|err| { + let rel_path = path.strip_prefix(&*CARGO_MANIFEST_DIR).unwrap_or(path); + format!("Python compile error in {}: {err}", rel_path.display()) + }) + }; + compile_path(path).or_else(|e| { + if cfg!(windows) { + if let Ok(real_path) = fs::read_to_string(path.canonicalize().unwrap()) { + let joined = path.parent().unwrap().join(real_path.trim()); + if joined.exists() { + return compile_path(&joined); + } else { + return Err(e); + } + } + } + Err(e) + }) + } + fn compile_single( &self, mode: Mode, - module_name: String, + module_name: &str, compiler: &dyn Compiler, - ) -> Result { - match &self.kind { - CompilationSourceKind::File(rel_path) => { - let path = CARGO_MANIFEST_DIR.join(rel_path); - let source = fs::read_to_string(&path).map_err(|err| { - Diagnostic::spans_error( - self.span, - format!("Error reading file {path:?}: {err}"), - ) - })?; - self.compile_string(&source, mode, module_name, compiler, || rel_path.display()) + ) -> Result { + match self { + CompilationSource::Path(path) => Self::compile_file(path, mode, module_name, compiler), + CompilationSource::SourceCode(code) => { + Self::compile_string(&textwrap::dedent(code), mode, module_name, compiler) + .map_err(|err| format!("Python compile error in string literal: {err}")) } - CompilationSourceKind::SourceCode(code) => self.compile_string( - &textwrap::dedent(code), - mode, - module_name, - compiler, - || "string literal", - ), - CompilationSourceKind::Dir(_) => { - unreachable!("Can't use compile_single with directory source") + CompilationSource::LibPath(_) => { + unreachable!("Can't use compile_single with lib source") } } } +} - fn compile_dir( - &self, - path: &Path, - parent: String, - mode: Mode, - compiler: &dyn Compiler, - ) -> Result, Diagnostic> { - let mut code_map = HashMap::new(); +fn par_map(it: I, f: F) -> impl Iterator +where + I: IntoIterator, + F: Fn(T) -> U + Sync, + U: Send, +{ + let it = it.into_iter(); + let mut out = Vec::from_iter(std::iter::repeat_with(|| None).take(it.len())); + let it = std::sync::Mutex::new(std::iter::zip(&mut out, it)); + let task = || { + while let Some((out, x)) = { it.lock().unwrap().next() } { + *out = Some(f(x)); + } + }; + std::thread::scope(|s| { + let nproc = std::thread::available_parallelism().unwrap().get(); + for _ in 0..nproc { + std::thread::Builder::new() + .stack_size(4 * 1024 * 1024) + .spawn_scoped(s, task) + .unwrap(); + } + }); + out.into_iter().map(Option::unwrap) +} + +#[derive(Default)] +struct DirWalker<'a> { + excludes: &'a [pattern::ModulePattern], + modules: BTreeMap, +} + +impl<'a> DirWalker<'a> { + fn new(excludes: &'a [pattern::ModulePattern]) -> Self { + Self { + excludes, + modules: BTreeMap::new(), + } + } + fn walk(&mut self, path: &Path, parent: &str) -> Result<(), String> { let paths = fs::read_dir(path) .or_else(|e| { if cfg!(windows) { @@ -147,152 +204,101 @@ impl CompilationSource { } Err(e) }) - .map_err(|err| { - Diagnostic::spans_error(self.span, format!("Error listing dir {path:?}: {err}")) - })?; + .map_err(|err| format!("Error listing dir {path:?}: {err}"))?; for path in paths { - let path = path.map_err(|err| { - Diagnostic::spans_error(self.span, format!("Failed to list file: {err}")) - })?; - let path = path.path(); - let file_name = path.file_name().unwrap().to_str().ok_or_else(|| { - Diagnostic::spans_error(self.span, format!("Invalid UTF-8 in file name {path:?}")) - })?; - if path.is_dir() { - code_map.extend(self.compile_dir( - &path, - if parent.is_empty() { - file_name.to_string() - } else { - format!("{parent}.{file_name}") - }, - mode, - compiler, - )?); - } else if file_name.ends_with(".py") { - let stem = path.file_stem().unwrap().to_str().unwrap(); - let is_init = stem == "__init__"; - let module_name = if is_init { - parent.clone() - } else if parent.is_empty() { - stem.to_owned() - } else { - format!("{parent}.{stem}") - }; - - let compile_path = |src_path: &Path| { - let source = fs::read_to_string(src_path).map_err(|err| { - Diagnostic::spans_error( - self.span, - format!("Error reading file {path:?}: {err}"), - ) - })?; - self.compile_string(&source, mode, module_name.clone(), compiler, || { - path.strip_prefix(&*CARGO_MANIFEST_DIR) - .ok() - .unwrap_or(&path) - .display() - }) - }; - let code = compile_path(&path).or_else(|e| { - if cfg!(windows) { - if let Ok(real_path) = fs::read_to_string(path.canonicalize().unwrap()) { - let joined = path.parent().unwrap().join(real_path.trim()); - if joined.exists() { - return compile_path(&joined); - } else { - return Err(e); - } - } - } - Err(e) - }); - - let code = match code { - Ok(code) => code, - Err(_) - if stem.starts_with("badsyntax_") - | parent.ends_with(".encoded_modules") => - { - // TODO: handle with macro arg rather than hard-coded path - continue; - } - Err(e) => return Err(e), - }; + let path = path.map_err(|err| format!("Failed to list file: {err}"))?; + self.add_entry(path.path(), parent)?; + } + Ok(()) + } + fn add_entry(&mut self, path: PathBuf, parent: &str) -> Result<(), String> { + let file_name = path + .file_name() + .unwrap() + .to_str() + .ok_or_else(|| format!("Invalid UTF-8 in file name {path:?}"))?; + if path.is_dir() { + if parent.is_empty() { + self.walk(&path, file_name)? + } else { + self.walk(&path, &[parent, ".", file_name].concat())? + } + } else if file_name.ends_with(".py") { + let stem = path.file_stem().unwrap().to_str().unwrap(); + let is_init = stem == "__init__"; + let module_name = if is_init { + parent.to_owned() + } else if parent.is_empty() { + stem.to_owned() + } else { + [parent, ".", stem].concat() + }; - code_map.insert( - module_name, - CompiledModule { - code, - package: is_init, - }, - ); + if !self.excludes.iter().any(|pat| pat.matches(&module_name)) { + self.modules.insert(module_name, (path, is_init)); } } - Ok(code_map) + Ok(()) } } impl PyCompileArgs { - fn parse(input: TokenStream, allow_dir: bool) -> Result { + fn parse(input: TokenStream, allow_lib: bool) -> Result { let mut module_name = None; let mut mode = None; let mut source: Option = None; + let mut source_span = (Span::call_site(), Span::call_site()); let mut crate_name = None; - - fn assert_source_empty(source: &Option) -> Result<(), syn::Error> { - if let Some(source) = source { - Err(syn::Error::new( - source.span.0, - "Cannot have more than one source", - )) - } else { - Ok(()) - } - } + let mut exclude = None; syn::meta::parser(|meta| { + let assert_source_empty = + || check_duplicate_msg(&meta, &source, "Cannot have more than one source"); + let ident = meta .path .get_ident() .ok_or_else(|| meta.error("unknown arg"))?; let check_str = || meta.value()?.call(parse_str); if ident == "mode" { + check_duplicate(&meta, &mode)?; let s = check_str()?; match s.value().parse() { Ok(mode_val) => mode = Some(mode_val), Err(e) => bail_span!(s, "{}", e), } } else if ident == "module_name" { + check_duplicate(&meta, &module_name)?; module_name = Some(check_str()?.value()) } else if ident == "source" { - assert_source_empty(&source)?; + assert_source_empty()?; let code = check_str()?.value(); - source = Some(CompilationSource { - kind: CompilationSourceKind::SourceCode(code), - span: (ident.span(), meta.input.cursor().span()), - }); - } else if ident == "file" { - assert_source_empty(&source)?; - let path = check_str()?.value().into(); - source = Some(CompilationSource { - kind: CompilationSourceKind::File(path), - span: (ident.span(), meta.input.cursor().span()), - }); - } else if ident == "dir" { - if !allow_dir { - bail_span!(ident, "py_compile doesn't accept dir") + source_span = (ident.span(), code.span()); + source = Some(CompilationSource::SourceCode(code)); + } else if ident == "path" { + assert_source_empty()?; + let path = check_str()?; + source_span = (ident.span(), path.span()); + source = Some(CompilationSource::Path(path.value().into())); + } else if ident == "lib_path" { + if !allow_lib { + bail_span!(ident, "py_compile doesn't accept lib_path") } - assert_source_empty(&source)?; - let path = check_str()?.value().into(); - source = Some(CompilationSource { - kind: CompilationSourceKind::Dir(path), - span: (ident.span(), meta.input.cursor().span()), - }); + assert_source_empty()?; + let path = check_str()?; + source_span = (ident.span(), path.span()); + source = Some(CompilationSource::LibPath(path.value().into())); } else if ident == "crate_name" { + check_duplicate(&meta, &crate_name)?; let name = check_str()?.parse()?; crate_name = Some(name); + } else if ident == "exclude" { + check_duplicate(&meta, &exclude)?; + let input = meta.value()?; + let content; + syn::bracketed!(content in input); + exclude = Some(Punctuated::parse_terminated(&content)?); } else { return Err(meta.error("unknown attr")); } @@ -309,9 +315,11 @@ impl PyCompileArgs { Ok(PyCompileArgs { source, + source_span, mode: mode.unwrap_or(Mode::Exec), module_name: module_name.unwrap_or_else(|| "frozen".to_owned()), crate_name: crate_name.unwrap_or_else(|| syn::parse_quote!(::rustpython_vm)), + exclude: exclude.unwrap_or_default(), }) } } @@ -329,9 +337,11 @@ fn parse_str(input: ParseStream<'_>) -> ParseResult { struct PyCompileArgs { source: CompilationSource, + source_span: (Span, Span), mode: Mode, module_name: String, crate_name: syn::Path, + exclude: Punctuated, } pub fn impl_py_compile( @@ -343,7 +353,8 @@ pub fn impl_py_compile( let crate_name = args.crate_name; let code = args .source - .compile_single(args.mode, args.module_name, compiler)?; + .compile_single(args.mode, &args.module_name, compiler) + .map_err(|msg| Diagnostic::spans_error(args.source_span, msg))?; let frozen = frozen::FrozenCodeObject::encode(&code); let bytes = LitByteStr::new(&frozen.bytes, Span::call_site()); @@ -361,8 +372,17 @@ pub fn impl_py_freeze( ) -> Result { let args = PyCompileArgs::parse(input, true)?; + let excludes = args + .exclude + .into_iter() + .map(|s| s.value().parse().map_err(|e| syn::Error::new(s.span(), e))) + .collect::, _>>()?; + let crate_name = args.crate_name; - let code_map = args.source.compile(args.mode, args.module_name, compiler)?; + let code_map = args + .source + .compile(args.mode, args.module_name, &excludes, compiler) + .map_err(|msg| Diagnostic::spans_error(args.source_span, msg))?; let data = frozen::FrozenLib::encode(code_map.iter().map(|(k, v)| { let v = frozen::FrozenModule { @@ -379,3 +399,148 @@ pub fn impl_py_freeze( Ok(output) } + +mod pattern { + pub struct ModulePattern { + tokens: Vec, + } + + #[derive(Copy, Clone, Debug)] + enum Token { + DoubleStar, + Star, + Char(char), + } + + #[derive(Debug)] + pub enum PatternError { + BadDoubleStar, + } + impl std::fmt::Display for PatternError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PatternError::BadDoubleStar => { + f.write_str("`**` must be alone in a path component") + } + } + } + } + + impl std::str::FromStr for ModulePattern { + type Err = PatternError; + fn from_str(s: &str) -> Result { + let mut chars = s.chars().peekable(); + let mut was_dot = true; + let tokens = std::iter::from_fn(|| { + chars.next().map(|c| match c { + '*' if chars.peek() == Some(&'*') => { + chars.next(); + if was_dot && matches!(chars.next(), None | Some('.')) { + Ok(Token::DoubleStar) + } else { + Err(PatternError::BadDoubleStar) + } + } + '*' => Ok(Token::Star), + c => { + was_dot = c == '.'; + Ok(Token::Char(c)) + } + }) + }); + let tokens = tokens.collect::>()?; + Ok(Self { tokens }) + } + } + + impl ModulePattern { + pub fn matches(&self, s: &str) -> bool { + self.matches_from(true, s.chars(), 0) == MatchResult::Match + } + // vaguely based off glob's matches_from + fn matches_from( + &self, + mut follows_separator: bool, + mut path: std::str::Chars<'_>, + i: usize, + ) -> MatchResult { + for (ti, &token) in self.tokens[i..].iter().enumerate() { + match token { + Token::Star | Token::DoubleStar => { + // Empty match + match self.matches_from(follows_separator, path.clone(), i + ti + 1) { + MatchResult::SubPatternDoesntMatch => {} // keep trying + m => return m, + } + + while let Some(c) = path.next() { + follows_separator = c == '.'; + match token { + Token::DoubleStar if !follows_separator => continue, + Token::Star if follows_separator => { + return MatchResult::SubPatternDoesntMatch; + } + _ => {} + } + match self.matches_from(follows_separator, path.clone(), i + ti + 1) { + MatchResult::SubPatternDoesntMatch => {} // keep trying + m => return m, + } + } + } + Token::Char(exp) => { + let Some(c) = path.next() else { + return MatchResult::EntirePatternDoesntMatch; + }; + if c != exp { + return MatchResult::SubPatternDoesntMatch; + } + follows_separator = c == '.'; + } + } + } + + // Iter is fused. + if path.next().is_none() { + MatchResult::Match + } else { + MatchResult::SubPatternDoesntMatch + } + } + } + + #[derive(PartialEq, Eq, Debug)] + enum MatchResult { + Match, + SubPatternDoesntMatch, + EntirePatternDoesntMatch, + } + + #[cfg(test)] + #[test] + fn test_pattern() { + let pattern: ModulePattern = "x.bar.foo_*.a".parse().unwrap(); + assert!(pattern.matches("x.bar.foo_asdf.a")); + assert!(pattern.matches("x.bar.foo_bazzzz.a")); + assert!(pattern.matches("x.bar.foo_.a")); + assert!(!pattern.matches("x.bar.foo_")); + assert!(!pattern.matches("x.bar.foo_quxxx")); + assert!(!pattern.matches("foo_b.a")); + + let pattern: ModulePattern = "**.foo.**".parse().unwrap(); + assert!(pattern.matches("ba.bazzz.foo.quux")); + + let pattern: ModulePattern = "*.foo.**".parse().unwrap(); + assert!(pattern.matches("ba.foo.baz.quux")); + assert!(pattern.matches("asdf.foo.barrr")); + + let pattern: ModulePattern = "foo.**".parse().unwrap(); + assert!(pattern.matches("foo.baaar.qx")); + assert!(!pattern.matches("asdf.foo.brrrr")); + + let pattern: ModulePattern = "foo.**.bar*".parse().unwrap(); + assert!(pattern.matches("foo.quuxxx.barbaz")); + assert!(pattern.matches("foo.quux.asdf.barp")); + assert!(!pattern.matches("asdf.foo.barbaz")); + } +} diff --git a/derive-impl/src/lib.rs b/derive-impl/src/lib.rs index a1f97c96b0..fd57b5675a 100644 --- a/derive-impl/src/lib.rs +++ b/derive-impl/src/lib.rs @@ -4,9 +4,6 @@ extern crate proc_macro; -#[macro_use] -extern crate maplit; - #[macro_use] mod error; #[macro_use] diff --git a/derive-impl/src/pyclass.rs b/derive-impl/src/pyclass.rs index b704e083c6..592474db0e 100644 --- a/derive-impl/src/pyclass.rs +++ b/derive-impl/src/pyclass.rs @@ -4,9 +4,10 @@ use crate::util::{ ItemMeta, ItemMetaInner, ItemNursery, SimpleItemMeta, format_doc, pyclass_ident_and_attrs, pyexception_ident_and_attrs, text_signature, }; +use indexmap::IndexMap; use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree}; use quote::{ToTokens, quote, quote_spanned}; -use std::collections::{HashMap, HashSet}; +use std::collections::{BTreeMap, HashMap, HashSet}; use std::str::FromStr; use syn::{Attribute, Ident, Item, Result, parse_quote, spanned::Spanned}; use syn_ext::ext::*; @@ -1028,7 +1029,7 @@ impl ToTokens for MethodNursery { #[derive(Default)] #[allow(clippy::type_complexity)] struct GetSetNursery { - map: HashMap<(String, Vec), (Option, Option, Option)>, + map: IndexMap<(String, Vec), (Option, Option, Option)>, validated: bool, } @@ -1121,7 +1122,7 @@ impl ToTokens for GetSetNursery { #[derive(Default)] #[allow(clippy::type_complexity)] struct MemberNursery { - map: HashMap<(String, MemberKind), (Option, Option)>, + map: BTreeMap<(String, MemberKind), (Option, Option)>, validated: bool, } @@ -1130,7 +1131,7 @@ enum MemberItemKind { Set, } -#[derive(Eq, PartialEq, Hash)] +#[derive(Eq, PartialEq, Ord, PartialOrd)] enum MemberKind { Bool, ObjectEx, diff --git a/derive-impl/src/pymodule.rs b/derive-impl/src/pymodule.rs index eb1e4bba9e..e7662d7234 100644 --- a/derive-impl/src/pymodule.rs +++ b/derive-impl/src/pymodule.rs @@ -6,7 +6,8 @@ use crate::util::{ }; use proc_macro2::{Delimiter, Group, TokenStream, TokenTree}; use quote::{ToTokens, quote, quote_spanned}; -use std::{collections::HashSet, str::FromStr}; +use std::collections::{BTreeSet, HashSet}; +use std::str::FromStr; use syn::{Attribute, Ident, Item, Result, parse_quote, spanned::Spanned}; use syn_ext::ext::*; use syn_ext::types::PunctuatedNestedMeta; @@ -472,7 +473,7 @@ impl ModuleItem for FunctionItem { if self.py_attrs.is_empty() { vec![py_name] } else { - let mut py_names = HashSet::new(); + let mut py_names = BTreeSet::new(); py_names.insert(py_name); for attr_index in self.py_attrs.iter().rev() { let mut loop_unit = || { diff --git a/derive-impl/src/util.rs b/derive-impl/src/util.rs index 7e0eb96fb0..1343055d5a 100644 --- a/derive-impl/src/util.rs +++ b/derive-impl/src/util.rs @@ -743,3 +743,21 @@ fn func_sig(sig: &Signature) -> String { pub(crate) fn format_doc(sig: &str, doc: &str) -> String { format!("{sig}\n--\n\n{doc}") } + +pub(crate) fn check_duplicate_msg( + meta: &syn::meta::ParseNestedMeta<'_>, + x: &Option, + msg: &str, +) -> syn::Result<()> { + if x.is_some() { + Err(meta.error(msg)) + } else { + Ok(()) + } +} +pub(crate) fn check_duplicate( + meta: &syn::meta::ParseNestedMeta<'_>, + x: &Option, +) -> syn::Result<()> { + check_duplicate_msg(meta, x, "duplicate attribute") +} diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 2a7b3d68fc..4d7e54ecb8 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -243,10 +243,10 @@ impl derive_impl::Compiler for Compiler { &self, source: &str, mode: rustpython_compiler::Mode, - module_name: String, + source_path: String, ) -> Result> { use rustpython_compiler::{CompileOpts, compile}; - Ok(compile(source, mode, &module_name, CompileOpts::default())?) + Ok(compile(source, mode, &source_path, CompileOpts::default())?) } } diff --git a/examples/freeze/main.rs b/examples/freeze/main.rs index 4899112907..4ce3618138 100644 --- a/examples/freeze/main.rs +++ b/examples/freeze/main.rs @@ -9,7 +9,7 @@ fn run(vm: &vm::VirtualMachine) -> vm::PyResult<()> { // the file parameter is relative to the directory where the crate's Cargo.toml is located, see $CARGO_MANIFEST_DIR: // https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates - let module = vm::py_compile!(file = "examples/freeze/freeze.py"); + let module = vm::py_compile!(path = "examples/freeze/freeze.py"); let res = vm.run_code_obj(vm.ctx.new_code(module), scope); diff --git a/pylib/src/lib.rs b/pylib/src/lib.rs index f8a47ba67d..856dc0b666 100644 --- a/pylib/src/lib.rs +++ b/pylib/src/lib.rs @@ -10,5 +10,8 @@ pub const LIB_PATH: &str = match option_env!("win_lib_path") { }; #[cfg(feature = "freeze-stdlib")] -pub const FROZEN_STDLIB: &rustpython_compiler_core::frozen::FrozenLib = - rustpython_derive::py_freeze!(dir = "./Lib", crate_name = "rustpython_compiler_core"); +pub const FROZEN_STDLIB: &rustpython_compiler_core::frozen::FrozenLib = rustpython_derive::py_freeze!( + lib_path = "./Lib", + crate_name = "rustpython_compiler_core", + exclude = ["test.**.badsyntax_*", "test.encoded_modules.**"], +); diff --git a/vm/src/import.rs b/vm/src/import.rs index 90aadbdbf2..bb7ec9a358 100644 --- a/vm/src/import.rs +++ b/vm/src/import.rs @@ -177,7 +177,9 @@ fn remove_importlib_frames_inner( let (inner_tb, mut now_in_importlib) = remove_importlib_frames_inner(vm, traceback.next.lock().clone(), always_trim); - if file_name == "_frozen_importlib" || file_name == "_frozen_importlib_external" { + if file_name == "" + || file_name == "" + { if traceback.frame.code.obj_name.as_str() == "_call_with_frames_removed" { now_in_importlib = true; } diff --git a/vm/src/vm/mod.rs b/vm/src/vm/mod.rs index 08fbff94f9..c365db8a5a 100644 --- a/vm/src/vm/mod.rs +++ b/vm/src/vm/mod.rs @@ -1006,7 +1006,7 @@ fn core_frozen_inits() -> impl Iterator { // Includes _importlib_bootstrap and _importlib_bootstrap_external ext_modules!( iter, - dir = "./Lib/python_builtins", + lib_path = "./Lib/python_builtins", crate_name = "rustpython_compiler_core" ); @@ -1017,7 +1017,7 @@ fn core_frozen_inits() -> impl Iterator { // #[cfg(not(feature = "freeze-stdlib"))] ext_modules!( iter, - dir = "./Lib/core_modules", + lib_path = "./Lib/core_modules", crate_name = "rustpython_compiler_core" ); @@ -1030,7 +1030,9 @@ fn test_nested_frozen() { vm::Interpreter::with_init(Default::default(), |vm| { // vm.add_native_modules(rustpython_stdlib::get_module_inits()); - vm.add_frozen(rustpython_vm::py_freeze!(dir = "../extra_tests/snippets")); + vm.add_frozen(rustpython_vm::py_freeze!( + lib_path = "../extra_tests/snippets" + )); }) .enter(|vm| { let scope = vm.new_scope_with_builtins(); diff --git a/wasm/lib/src/browser_module.rs b/wasm/lib/src/browser_module.rs index f8d1b2ebc3..cccdd55eb2 100644 --- a/wasm/lib/src/browser_module.rs +++ b/wasm/lib/src/browser_module.rs @@ -259,5 +259,5 @@ mod _browser { pub fn setup_browser_module(vm: &mut VirtualMachine) { vm.add_native_module("_browser".to_owned(), Box::new(make_module)); - vm.add_frozen(py_freeze!(dir = "Lib")); + vm.add_frozen(py_freeze!(lib_path = "Lib")); }