polyxml 0.30.5__tar.gz → 0.30.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. {polyxml-0.30.5 → polyxml-0.30.7}/Cargo.lock +6 -6
  2. {polyxml-0.30.5 → polyxml-0.30.7}/Cargo.toml +1 -1
  3. {polyxml-0.30.5 → polyxml-0.30.7}/PKG-INFO +1 -1
  4. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/schema_parser/mod.rs +34 -5
  5. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/test_schema_ir.rs +80 -0
  6. {polyxml-0.30.5 → polyxml-0.30.7}/pyproject.toml +1 -1
  7. {polyxml-0.30.5 → polyxml-0.30.7}/README.md +0 -0
  8. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/Cargo.toml +0 -0
  9. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/README.md +0 -0
  10. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/benches/core_benchmarks.rs +0 -0
  11. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/benches/support/tag_dispatch_fixtures.rs +0 -0
  12. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/benches/tag_dispatch.rs +0 -0
  13. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/codegen/cpp/mod.rs +0 -0
  14. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/codegen/csharp/mod.rs +0 -0
  15. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/codegen/go/mod.rs +0 -0
  16. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/codegen/java/codec.rs +0 -0
  17. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/codegen/java/mod.rs +0 -0
  18. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/codegen/java/models.rs +0 -0
  19. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/codegen/mod.rs +0 -0
  20. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/codegen/python/aot.rs +0 -0
  21. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/codegen/python/mod.rs +0 -0
  22. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/codegen/rust/mod.rs +0 -0
  23. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/codegen/typescript/mod.rs +0 -0
  24. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/converters.rs +0 -0
  25. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/error.rs +0 -0
  26. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/ir/mod.rs +0 -0
  27. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/ir/tarjan.rs +0 -0
  28. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/json.rs +0 -0
  29. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/lib.rs +0 -0
  30. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/parser.rs +0 -0
  31. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/schema.rs +0 -0
  32. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/serializer.rs +0 -0
  33. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/transcoder.rs +0 -0
  34. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/src/value.rs +0 -0
  35. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/fixtures/lexical_union.xsd +0 -0
  36. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/fixtures/mixed_content.xsd +0 -0
  37. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/fixtures/ts_mixed_content_inheritance.xsd +0 -0
  38. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/test_adversarial_identifiers.rs +0 -0
  39. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/test_conformance.rs +0 -0
  40. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/test_core.rs +0 -0
  41. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/test_cpp_codegen.rs +0 -0
  42. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/test_csharp_codegen.rs +0 -0
  43. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/test_go_codegen.rs +0 -0
  44. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/test_java_codegen.rs +0 -0
  45. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/test_json.rs +0 -0
  46. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/test_lexical_union_codegen.rs +0 -0
  47. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/test_mixed_content.rs +0 -0
  48. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/test_pattern_codegen.rs +0 -0
  49. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/test_python_codegen.rs +0 -0
  50. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/test_rust_codecs.rs +0 -0
  51. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/test_rust_codegen.rs +0 -0
  52. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/test_schema_audit.rs +0 -0
  53. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/test_security.rs +0 -0
  54. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/test_transcoder.rs +0 -0
  55. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/test_ts_codegen.rs +0 -0
  56. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/test_unbounded_choice.rs +0 -0
  57. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-core/tests/test_xsi_type.rs +0 -0
  58. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-python/Cargo.toml +0 -0
  59. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-python/README.md +0 -0
  60. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-python/benches/aot_vs_dataclass.py +0 -0
  61. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-python/src/lib.rs +0 -0
  62. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-python/tests/test_conformance.py +0 -0
  63. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-python/tests/test_generated_models.py +0 -0
  64. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-python/tests/test_json.py +0 -0
  65. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-python/tests/test_mixed_content.py +0 -0
  66. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-python/tests/test_polyxml.py +0 -0
  67. {polyxml-0.30.5 → polyxml-0.30.7}/crates/polyxml-python/tests/test_xsi_type.py +0 -0
  68. {polyxml-0.30.5 → polyxml-0.30.7}/python/polyxml/AGENT_GUIDE.md +0 -0
  69. {polyxml-0.30.5 → polyxml-0.30.7}/python/polyxml/__init__.py +0 -0
  70. {polyxml-0.30.5 → polyxml-0.30.7}/python/polyxml/compat/__init__.py +0 -0
  71. {polyxml-0.30.5 → polyxml-0.30.7}/python/polyxml/compat/xsdata.py +0 -0
  72. {polyxml-0.30.5 → polyxml-0.30.7}/python/polyxml/py.typed +0 -0
@@ -608,7 +608,7 @@ dependencies = [
608
608
 
609
609
  [[package]]
610
610
  name = "polyxml"
611
- version = "0.30.5"
611
+ version = "0.30.7"
612
612
  dependencies = [
613
613
  "criterion",
614
614
  "heck",
@@ -629,14 +629,14 @@ dependencies = [
629
629
 
630
630
  [[package]]
631
631
  name = "polyxml-c"
632
- version = "0.30.5"
632
+ version = "0.30.7"
633
633
  dependencies = [
634
634
  "polyxml",
635
635
  ]
636
636
 
637
637
  [[package]]
638
638
  name = "polyxml-cli"
639
- version = "0.30.5"
639
+ version = "0.30.7"
640
640
  dependencies = [
641
641
  "clap",
642
642
  "glob",
@@ -650,7 +650,7 @@ dependencies = [
650
650
 
651
651
  [[package]]
652
652
  name = "polyxml-js"
653
- version = "0.30.5"
653
+ version = "0.30.7"
654
654
  dependencies = [
655
655
  "napi",
656
656
  "napi-build",
@@ -660,7 +660,7 @@ dependencies = [
660
660
 
661
661
  [[package]]
662
662
  name = "polyxml-python"
663
- version = "0.30.5"
663
+ version = "0.30.7"
664
664
  dependencies = [
665
665
  "lexical-core",
666
666
  "polyxml",
@@ -670,7 +670,7 @@ dependencies = [
670
670
 
671
671
  [[package]]
672
672
  name = "polyxml-wasm"
673
- version = "0.30.5"
673
+ version = "0.30.7"
674
674
  dependencies = [
675
675
  "polyxml",
676
676
  "quick-xml",
@@ -3,7 +3,7 @@ resolver = "2"
3
3
  members = ["crates/polyxml-core", "crates/polyxml-python"]
4
4
 
5
5
  [workspace.package]
6
- version = "0.30.5"
6
+ version = "0.30.7"
7
7
  edition = "2021"
8
8
  rust-version = "1.80"
9
9
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: polyxml
3
- Version: 0.30.5
3
+ Version: 0.30.7
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -189,7 +189,12 @@ impl XsdParser {
189
189
 
190
190
  let mut ir = SchemaIR::new();
191
191
  let mut target_namespace = None;
192
- let mut prefixes = HashMap::new();
192
+ // The `xml` prefix is bound by XML itself, even when the schema omits
193
+ // an explicit xmlns:xml declaration (as Dublin Core's dc.xsd does).
194
+ let mut prefixes = HashMap::from([(
195
+ "xml".to_string(),
196
+ "http://www.w3.org/XML/1998/namespace".to_string(),
197
+ )]);
193
198
  let mut buf = Vec::new();
194
199
 
195
200
  // Pass 1: Parse root schema attributes and build prefix table
@@ -255,6 +260,11 @@ impl XsdParser {
255
260
  }
256
261
  }
257
262
  merge_ir(&mut ir, sub_ir);
263
+ } else {
264
+ return Err(SchemaError::Resolution(format!(
265
+ "included schema not found: {}",
266
+ inc_path.display()
267
+ )));
258
268
  }
259
269
  }
260
270
  }
@@ -366,6 +376,11 @@ impl XsdParser {
366
376
  }
367
377
  }
368
378
  merge_ir(&mut ir, sub_ir);
379
+ } else {
380
+ return Err(SchemaError::Resolution(format!(
381
+ "included schema not found: {}",
382
+ inc_path.display()
383
+ )));
369
384
  }
370
385
  }
371
386
  }
@@ -688,7 +703,10 @@ impl XsdParser {
688
703
  if frame.kind == CompositorKind::Choice {
689
704
  let choice_is_unbounded = frame.is_unbounded
690
705
  || compositor_stack.iter().any(|c| c.is_unbounded);
691
- if choice_is_unbounded && !frame.choice_branches.is_empty() {
706
+ if (choice_is_unbounded
707
+ || (compositor_stack.is_empty() && base_type.is_some()))
708
+ && !frame.choice_branches.is_empty()
709
+ {
692
710
  let choice_name =
693
711
  unique_type_name(ir, target_ns, &format!("{}Choice", name));
694
712
  let choice_qname = QName::new(target_ns, choice_name);
@@ -700,10 +718,15 @@ impl XsdParser {
700
718
  ir.add_type(TypeDef::Union(choice_def));
701
719
 
702
720
  fields.truncate(frame.fields_start);
703
- let mut item_field_name = "items".to_string();
721
+ let field_base = if choice_is_unbounded {
722
+ "items"
723
+ } else {
724
+ "choice"
725
+ };
726
+ let mut item_field_name = field_base.to_string();
704
727
  let mut counter = 2;
705
728
  while fields.iter().any(|f| f.name == item_field_name) {
706
- item_field_name = format!("items_{}", counter);
729
+ item_field_name = format!("{field_base}_{counter}");
707
730
  counter += 1;
708
731
  }
709
732
  fields.push(FieldDef {
@@ -712,7 +735,13 @@ impl XsdParser {
712
735
  namespace: None,
713
736
  kind: FieldKind::Element,
714
737
  type_ref: TypeRef::Named(choice_qname),
715
- cardinality: Cardinality::unbounded(frame.min_occurs),
738
+ cardinality: if choice_is_unbounded {
739
+ Cardinality::unbounded(frame.min_occurs)
740
+ } else if frame.min_occurs == 0 {
741
+ Cardinality::optional_one()
742
+ } else {
743
+ Cardinality::required_one()
744
+ },
716
745
  nillable: false,
717
746
  default_value: None,
718
747
  fixed_value: None,
@@ -6,6 +6,30 @@ use polyxml::ir::{
6
6
  TypeDef, TypeRef,
7
7
  };
8
8
  use polyxml::schema_parser::XsdParser;
9
+ use tempfile::tempdir;
10
+
11
+ #[test]
12
+ fn missing_included_schema_is_an_error() {
13
+ let dir = tempdir().unwrap();
14
+ for (name, include) in [
15
+ ("empty.xsd", r#"<xs:include schemaLocation="missing.xsd"/>"#),
16
+ (
17
+ "start.xsd",
18
+ r#"<xs:include schemaLocation="missing.xsd"></xs:include>"#,
19
+ ),
20
+ ] {
21
+ let path = dir.path().join(name);
22
+ std::fs::write(
23
+ &path,
24
+ format!(
25
+ r#"<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">{include}</xs:schema>"#
26
+ ),
27
+ )
28
+ .unwrap();
29
+ let error = XsdParser::new().parse_file(&path).unwrap_err();
30
+ assert!(error.to_string().contains("missing.xsd"), "{error}");
31
+ }
32
+ }
9
33
 
10
34
  #[test]
11
35
  fn consumed_child_subtrees_do_not_swallow_following_types() {
@@ -68,6 +92,62 @@ fn global_attribute_reference_uses_declared_type() {
68
92
  );
69
93
  }
70
94
 
95
+ #[test]
96
+ fn xml_prefix_is_available_without_explicit_declaration() {
97
+ let dir = tempdir().unwrap();
98
+ std::fs::write(
99
+ dir.path().join("xml.xsd"),
100
+ r#"<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.w3.org/XML/1998/namespace">
101
+ <xs:attribute name="lang" type="xs:language"/>
102
+ </xs:schema>"#,
103
+ )
104
+ .unwrap();
105
+ let main = dir.path().join("dc.xsd");
106
+ std::fs::write(
107
+ &main,
108
+ r#"<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:dc">
109
+ <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="xml.xsd"/>
110
+ <xs:complexType name="SimpleLiteral"><xs:attribute ref="xml:lang"/></xs:complexType>
111
+ </xs:schema>"#,
112
+ )
113
+ .unwrap();
114
+ let ir = XsdParser::new().parse_file(&main).unwrap();
115
+ let TypeDef::Struct(literal) = &ir.types[&QName::new(Some("urn:dc"), "SimpleLiteral")] else {
116
+ panic!("expected SimpleLiteral struct");
117
+ };
118
+ assert_eq!(
119
+ literal.fields[0].type_ref,
120
+ TypeRef::Primitive(PrimitiveType::Language)
121
+ );
122
+ }
123
+
124
+ #[test]
125
+ fn derived_complex_type_keeps_base_and_bounded_choice() {
126
+ let xsd = r#"<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="urn:test" targetNamespace="urn:test">
127
+ <xs:complexType name="Base"><xs:attribute name="id" type="xs:string"/></xs:complexType>
128
+ <xs:complexType name="Node"><xs:complexContent><xs:extension base="t:Base"><xs:choice>
129
+ <xs:element name="left" type="xs:string"/><xs:element name="right" type="xs:int"/>
130
+ </xs:choice></xs:extension></xs:complexContent></xs:complexType>
131
+ <xs:complexType name="Child"><xs:complexContent><xs:extension base="t:Node">
132
+ <xs:attribute name="flag" type="xs:boolean"/>
133
+ </xs:extension></xs:complexContent></xs:complexType>
134
+ </xs:schema>"#;
135
+ let ir = XsdParser::new().parse_str(xsd).unwrap();
136
+ let TypeDef::Struct(node) = &ir.types[&QName::new(Some("urn:test"), "Node")] else {
137
+ panic!("derived choice must remain a struct");
138
+ };
139
+ assert_eq!(node.base_type, Some(QName::new(Some("urn:test"), "Base")));
140
+ assert_eq!(node.fields.len(), 1);
141
+ assert_eq!(node.fields[0].name, "choice");
142
+ let TypeRef::Named(choice_name) = &node.fields[0].type_ref else {
143
+ panic!("choice field must refer to a union");
144
+ };
145
+ let TypeDef::Union(choice) = &ir.types[choice_name] else {
146
+ panic!("choice field must refer to a union");
147
+ };
148
+ assert_eq!(choice.branches.len(), 2);
149
+ }
150
+
71
151
  #[test]
72
152
  fn test_parse_lexical_union_member_types_and_inline_members() {
73
153
  let xsd = r#"<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="urn:test" targetNamespace="urn:test">
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "polyxml"
7
- version = "0.30.5"
7
+ version = "0.30.7"
8
8
  description = "High-performance, polyglot XML data-binding engine built in Rust"
9
9
  authors = [
10
10
  { name = "Bailey Nguyen", email = "bailey.tan.nguyen@gmail.com" }
File without changes