polyxml 0.34.0__tar.gz → 0.34.2__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 (84) hide show
  1. {polyxml-0.34.0 → polyxml-0.34.2}/Cargo.lock +6 -6
  2. {polyxml-0.34.0 → polyxml-0.34.2}/Cargo.toml +1 -1
  3. {polyxml-0.34.0 → polyxml-0.34.2}/PKG-INFO +1 -1
  4. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/codegen/csharp/mod.rs +6 -0
  5. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/codegen/python/mod.rs +1 -1
  6. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/codegen/rust/mod.rs +5 -3
  7. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/schema_parser/mod.rs +7 -1
  8. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_csharp_codegen.rs +1 -0
  9. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_python_codegen.rs +29 -0
  10. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_rust_codegen.rs +54 -0
  11. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_schema_audit.rs +27 -0
  12. {polyxml-0.34.0 → polyxml-0.34.2}/pyproject.toml +1 -1
  13. {polyxml-0.34.0 → polyxml-0.34.2}/README.md +0 -0
  14. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/Cargo.toml +0 -0
  15. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/README.md +0 -0
  16. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/benches/core_benchmarks.rs +0 -0
  17. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/benches/support/tag_dispatch_fixtures.rs +0 -0
  18. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/benches/tag_dispatch.rs +0 -0
  19. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/codegen/cpp/mod.rs +0 -0
  20. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/codegen/go/mod.rs +0 -0
  21. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/codegen/java/codec.rs +0 -0
  22. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/codegen/java/mod.rs +0 -0
  23. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/codegen/java/models.rs +0 -0
  24. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/codegen/mod.rs +0 -0
  25. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/codegen/python/aot.rs +0 -0
  26. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/codegen/typescript/mod.rs +0 -0
  27. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/converters.rs +0 -0
  28. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/error.rs +0 -0
  29. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/integer.rs +0 -0
  30. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/ir/chunker.rs +0 -0
  31. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/ir/mod.rs +0 -0
  32. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/ir/particle.rs +0 -0
  33. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/ir/tarjan.rs +0 -0
  34. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/json.rs +0 -0
  35. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/lib.rs +0 -0
  36. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/parser.rs +0 -0
  37. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/schema.rs +0 -0
  38. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/schema_parser/upa.rs +0 -0
  39. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/serializer.rs +0 -0
  40. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/transcoder.rs +0 -0
  41. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/src/value.rs +0 -0
  42. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/fixtures/lexical_union.xsd +0 -0
  43. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/fixtures/mixed_content.xsd +0 -0
  44. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/fixtures/ts_mixed_content_inheritance.xsd +0 -0
  45. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_adversarial_identifiers.rs +0 -0
  46. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_any_attribute.rs +0 -0
  47. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_any_element.rs +0 -0
  48. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_conformance.rs +0 -0
  49. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_core.rs +0 -0
  50. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_cpp_codegen.rs +0 -0
  51. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_go_codegen.rs +0 -0
  52. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_java_codegen.rs +0 -0
  53. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_json.rs +0 -0
  54. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_lexical_lists.rs +0 -0
  55. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_lexical_union_codegen.rs +0 -0
  56. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_mixed_content.rs +0 -0
  57. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_pattern_codegen.rs +0 -0
  58. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_qualified_attributes.rs +0 -0
  59. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_rust_codecs.rs +0 -0
  60. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_schema_ir.rs +0 -0
  61. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_security.rs +0 -0
  62. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_temporal_union.rs +0 -0
  63. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_transcoder.rs +0 -0
  64. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_ts_codegen.rs +0 -0
  65. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_ubl_csharp.rs +0 -0
  66. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_unbounded_choice.rs +0 -0
  67. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_upa.rs +0 -0
  68. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_value_constraints.rs +0 -0
  69. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-core/tests/test_xsi_type.rs +0 -0
  70. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-python/Cargo.toml +0 -0
  71. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-python/README.md +0 -0
  72. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-python/benches/aot_vs_dataclass.py +0 -0
  73. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-python/src/lib.rs +0 -0
  74. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-python/tests/test_conformance.py +0 -0
  75. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-python/tests/test_generated_models.py +0 -0
  76. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-python/tests/test_json.py +0 -0
  77. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-python/tests/test_mixed_content.py +0 -0
  78. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-python/tests/test_polyxml.py +0 -0
  79. {polyxml-0.34.0 → polyxml-0.34.2}/crates/polyxml-python/tests/test_xsi_type.py +0 -0
  80. {polyxml-0.34.0 → polyxml-0.34.2}/python/polyxml/AGENT_GUIDE.md +0 -0
  81. {polyxml-0.34.0 → polyxml-0.34.2}/python/polyxml/__init__.py +0 -0
  82. {polyxml-0.34.0 → polyxml-0.34.2}/python/polyxml/compat/__init__.py +0 -0
  83. {polyxml-0.34.0 → polyxml-0.34.2}/python/polyxml/compat/xsdata.py +0 -0
  84. {polyxml-0.34.0 → polyxml-0.34.2}/python/polyxml/py.typed +0 -0
@@ -608,7 +608,7 @@ dependencies = [
608
608
 
609
609
  [[package]]
610
610
  name = "polyxml"
611
- version = "0.34.0"
611
+ version = "0.34.2"
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.34.0"
632
+ version = "0.34.2"
633
633
  dependencies = [
634
634
  "polyxml",
635
635
  ]
636
636
 
637
637
  [[package]]
638
638
  name = "polyxml-cli"
639
- version = "0.34.0"
639
+ version = "0.34.2"
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.34.0"
653
+ version = "0.34.2"
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.34.0"
663
+ version = "0.34.2"
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.34.0"
673
+ version = "0.34.2"
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.34.0"
6
+ version = "0.34.2"
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.34.0
3
+ Version: 0.34.2
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -114,6 +114,12 @@ pub fn to_csharp_property_name(raw: &str, enclosing_type: Option<&str>) -> Strin
114
114
  };
115
115
 
116
116
  let sanitized = sanitize_keyword(&safe, "csharp");
117
+ // Positional record members cannot shadow the synthesized equality methods.
118
+ let sanitized = if matches!(sanitized.as_str(), "Equals" | "GetHashCode" | "ToString") {
119
+ format!("{sanitized}Value")
120
+ } else {
121
+ sanitized
122
+ };
117
123
  if let Some(enclosing) = enclosing_type {
118
124
  if sanitized == enclosing || sanitized.trim_start_matches('@') == enclosing {
119
125
  return format!("{}Value", sanitized);
@@ -36,7 +36,7 @@ fn write_python_docstring(out: &mut String, indent: &str, doc: &str) {
36
36
  let escaped = doc
37
37
  .trim()
38
38
  .replace('\\', "\\\\")
39
- .replace("\"\"\"", "\\\"\\\"\\\"")
39
+ .replace('"', "\\\"")
40
40
  .replace('\r', "");
41
41
  let _ = writeln!(out, "{indent}\"\"\"{escaped}\"\"\"");
42
42
  }
@@ -16,7 +16,7 @@ use crate::ir::{
16
16
  /// Options configuring Rust 2021/2024 code generation.
17
17
  #[derive(Debug, Clone, Serialize, Deserialize)]
18
18
  pub struct RustOptions {
19
- /// Use zero-copy Cow<'a, str> and Cow<'a, [u8]> (default: true).
19
+ /// Use zero-copy Cow<'a, str> for XML lexical values (default: true).
20
20
  pub zero_copy: bool,
21
21
  /// Derive serde::{Serialize, Deserialize} (default: true).
22
22
  pub derive_serde: bool,
@@ -147,11 +147,13 @@ impl LanguageContext for RustLanguageContext {
147
147
  PrimitiveType::UnsignedShort => "u16",
148
148
  PrimitiveType::UnsignedByte => "u8",
149
149
 
150
+ // XML carries hex/base64 lexical text, just as the runtime schema does.
151
+ // Preserve that spelling; callers can explicitly decode binary payloads.
150
152
  PrimitiveType::HexBinary | PrimitiveType::Base64Binary => {
151
153
  if self.zero_copy {
152
- "Cow<'a, [u8]>"
154
+ "Cow<'a, str>"
153
155
  } else {
154
- "Vec<u8>"
156
+ "String"
155
157
  }
156
158
  }
157
159
  }
@@ -2554,7 +2554,13 @@ fn collect_chain_patterns(ir: &SchemaIR, q: &QName, visited: &mut HashSet<QName>
2554
2554
  }
2555
2555
 
2556
2556
  fn merge_ir(dest: &mut SchemaIR, src: SchemaIR) {
2557
- dest.upa_documents.extend(src.upa_documents);
2557
+ // Diamond include graphs can replay the same transitive document many times.
2558
+ // Validate each identical source model once; chameleon copies differ by namespace.
2559
+ for document in src.upa_documents {
2560
+ if !dest.upa_documents.contains(&document) {
2561
+ dest.upa_documents.push(document);
2562
+ }
2563
+ }
2558
2564
  dest.abstract_elements.extend(src.abstract_elements);
2559
2565
  dest.ordered_types.extend(src.ordered_types);
2560
2566
  dest.content_models.extend(src.content_models);
@@ -79,6 +79,7 @@ static DOTNET_LOCK: Mutex<()> = Mutex::new(());
79
79
  #[test]
80
80
  fn particle_wire_structure_round_trips() {
81
81
  for (schema, root, documents) in [
82
+ (r#"<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"><xs:element name="Query"><xs:complexType><xs:sequence><xs:element name="Equals" type="xs:string"/><xs:element name="EqualsValue" type="xs:string"/><xs:element name="GetHashCode" type="xs:string"/><xs:element name="ToString" type="xs:string"/></xs:sequence></xs:complexType></xs:element></xs:schema>"#, "Query", vec!["<Query><Equals>a</Equals><EqualsValue>b</EqualsValue><GetHashCode>c</GetHashCode><ToString>d</ToString></Query>"]),
82
83
  (include_str!("../../../research/fixtures/nested_sequence_choice.xsd"), "Root", vec!["<Root><First>A</First><Second>B</Second></Root>", "<Root><Alternative>C</Alternative></Root>"]),
83
84
  (include_str!("../../../research/fixtures/repeated_sequence.xsd"), "Root", vec!["<Root><First>A1</First><Second>B1</Second><First>A2</First><Second>B2</Second></Root>"]),
84
85
  (include_str!("../../../research/fixtures/substitution_group.xsd"), "Portfolio", vec!["<Portfolio xmlns='urn:audit:substitution'><Bond>A1</Bond><Equity>B1</Equity><Bond>A2</Bond></Portfolio>"]),
@@ -793,3 +793,32 @@ fn test_python_sequence_nested_inside_choice_codegen() {
793
793
  assert!(code.contains("first: str | None = field("));
794
794
  assert!(code.contains("second: str | None = field("));
795
795
  }
796
+
797
+ #[test]
798
+ fn quoted_docstrings_preserve_text_and_remain_valid_python() {
799
+ let ir = XsdParser::new().parse_str(r#"<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"><xs:simpleType name="Direction"><xs:annotation><xs:documentation>Default is "Outbound"</xs:documentation></xs:annotation><xs:restriction base="xs:string"><xs:enumeration value="Outbound"/></xs:restriction></xs:simpleType><xs:complexType name="Record"><xs:annotation><xs:documentation>Literal \path, "quotes" and """triples"""</xs:documentation></xs:annotation><xs:sequence><xs:element name="direction" type="Direction"/></xs:sequence></xs:complexType></xs:schema>"#).unwrap();
800
+ for backend in [PythonBackend::Dataclass, PythonBackend::Pydantic] {
801
+ let dir = tempfile::tempdir().unwrap();
802
+ let path = dir.path().join("models.py");
803
+ std::fs::write(
804
+ &path,
805
+ PythonCodegen::new(PythonOptions {
806
+ backend,
807
+ ..Default::default()
808
+ })
809
+ .generate_module(&ir),
810
+ )
811
+ .unwrap();
812
+ let expected = serde_json::to_string(&vec![
813
+ "Default is \"Outbound\"",
814
+ r#"Literal \path, "quotes" and """triples""""#,
815
+ ])
816
+ .unwrap();
817
+ let output = std::process::Command::new("python3").arg("-c").arg("import ast,json,sys; tree=ast.parse(open(sys.argv[1]).read()); docs=[ast.get_docstring(n) for n in tree.body if isinstance(n,ast.ClassDef) and ast.get_docstring(n) is not None]; assert docs==json.loads(sys.argv[2]),docs").arg(path).arg(expected).output().unwrap();
818
+ assert!(
819
+ output.status.success(),
820
+ "{}",
821
+ String::from_utf8_lossy(&output.stderr)
822
+ );
823
+ }
824
+ }
@@ -1310,3 +1310,57 @@ fn test_rust_digit_prefixed_module_sanitization() {
1310
1310
  assert!(mod_file.1.contains("pub mod _17_report;"));
1311
1311
  assert!(mod_file.1.contains("pub use _17_report::*;"));
1312
1312
  }
1313
+
1314
+ #[test]
1315
+ fn binary_lexical_values_compile_and_round_trip_in_owned_and_borrowed_modes() {
1316
+ let schema = r#"<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
1317
+ <xs:complexType name="BinaryText"><xs:simpleContent><xs:extension base="xs:hexBinary"/></xs:simpleContent></xs:complexType>
1318
+ <xs:complexType name="Payload"><xs:sequence>
1319
+ <xs:element name="required" type="xs:hexBinary"/>
1320
+ <xs:element name="optional" type="xs:base64Binary" minOccurs="0"/>
1321
+ <xs:element name="repeated" type="xs:hexBinary" maxOccurs="unbounded"/>
1322
+ </xs:sequence><xs:attribute name="encoded" type="xs:base64Binary"/></xs:complexType>
1323
+ <xs:complexType name="Alternative"><xs:choice><xs:element name="hex" type="xs:hexBinary"/><xs:element name="base64" type="xs:base64Binary"/></xs:choice></xs:complexType>
1324
+ </xs:schema>"#;
1325
+ let ir = XsdParser::new().parse_str(schema).unwrap();
1326
+ let core = std::path::Path::new(env!("CARGO_MANIFEST_DIR"));
1327
+ for zero_copy in [true, false] {
1328
+ let dir = tempfile::tempdir().unwrap();
1329
+ std::fs::create_dir(dir.path().join("src")).unwrap();
1330
+ std::fs::write(dir.path().join("Cargo.toml"), format!("[package]\nname=\"binary-lexical-test\"\nversion=\"0.0.0\"\nedition=\"2021\"\n[dependencies]\npolyxml={{path={core:?}}}\nquick-xml={{version=\"0.42\",features=[\"serialize\"]}}\nserde={{version=\"1\",features=[\"derive\"]}}\nserde_json=\"1\"\nregex=\"1\"\n")).unwrap();
1331
+ let code = RustCodegen::new(RustOptions {
1332
+ zero_copy,
1333
+ ..Default::default()
1334
+ })
1335
+ .generate_module(&ir);
1336
+ std::fs::write(dir.path().join("src/models.rs"), code).unwrap();
1337
+ std::fs::write(dir.path().join("src/main.rs"), r#"mod models;
1338
+ use models::*;
1339
+ fn main() {
1340
+ let xml="<Payload encoded=\"YWI=\"><required>0aFF</required><optional>YWI=</optional><repeated>00</repeated><repeated>FE</repeated></Payload>";
1341
+ let value=Payload::from_xml(xml).unwrap();
1342
+ assert_eq!(&*value.required,"0aFF"); assert_eq!(&*value.optional.as_ref().unwrap(),"YWI=");
1343
+ assert_eq!(&*value.repeated[1],"FE"); assert_eq!(&*value.encoded.as_ref().unwrap(),"YWI=");
1344
+ assert_eq!(value.to_xml_string().unwrap(),xml);
1345
+ let text=BinaryText::from_xml("<BinaryText>0AFF</BinaryText>").unwrap();
1346
+ assert_eq!(text.to_xml_string().unwrap(),"<BinaryText>0AFF</BinaryText>");
1347
+ for xml in ["<hex>0AFF</hex>","<base64>YWI=</base64>"] { let value=Alternative::from_xml(xml).unwrap(); assert_eq!(value.to_xml_string().unwrap(),xml); }
1348
+ }
1349
+ "#).unwrap();
1350
+ let output = std::process::Command::new("cargo")
1351
+ .args(["run", "--quiet", "--offline"])
1352
+ .env(
1353
+ "CARGO_TARGET_DIR",
1354
+ core.join("../../target/binary-lexical-tests"),
1355
+ )
1356
+ .current_dir(dir.path())
1357
+ .output()
1358
+ .unwrap();
1359
+ assert!(
1360
+ output.status.success(),
1361
+ "zero_copy={zero_copy}: {}\n{}",
1362
+ String::from_utf8_lossy(&output.stdout),
1363
+ String::from_utf8_lossy(&output.stderr)
1364
+ );
1365
+ }
1366
+ }
@@ -576,3 +576,30 @@ fn restricted_simple_types_emit_named_aliases() {
576
576
  let csharp = CSharpCodegen::new(CSharpOptions::default()).generate_module(&ir);
577
577
  assert!(csharp.contains("BicCode"), "csharp type missing:\n{csharp}");
578
578
  }
579
+
580
+ #[test]
581
+ fn diamond_includes_do_not_duplicate_upa_source_documents() {
582
+ let dir = tempdir().unwrap();
583
+ for index in 0usize..16 {
584
+ let includes = (index.saturating_sub(2)..index)
585
+ .map(|previous| format!("<xs:include schemaLocation=\"{previous}.xsd\"/>"))
586
+ .collect::<String>();
587
+ fs::write(dir.path().join(format!("{index}.xsd")), format!("<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">{includes}<xs:complexType name=\"T{index}\"><xs:sequence><xs:element name=\"item{index}\" type=\"xs:string\"/></xs:sequence></xs:complexType></xs:schema>")).unwrap();
588
+ }
589
+ let mut parser = XsdParser::new();
590
+ let ir = parser.parse_file(dir.path().join("15.xsd")).unwrap();
591
+ assert_eq!(ir.types.len(), 16);
592
+ assert_eq!(
593
+ ir.upa_documents.len(),
594
+ 16,
595
+ "each unique source document is retained once"
596
+ );
597
+ assert_eq!(
598
+ parser
599
+ .parse_file(dir.path().join("15.xsd"))
600
+ .unwrap()
601
+ .upa_documents
602
+ .len(),
603
+ 16
604
+ );
605
+ }
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "polyxml"
7
- version = "0.34.0"
7
+ version = "0.34.2"
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