Beispiel #1
0
    def test_process_attribute_restrictions(self):
        restrictions = [
            Restrictions(min_occurs=0, max_occurs=0, required=True),
            Restrictions(min_occurs=0, max_occurs=1, required=True),
            Restrictions(min_occurs=1, max_occurs=1, required=False),
            Restrictions(max_occurs=2, required=True),
            Restrictions(min_occurs=2, max_occurs=2, required=True),
        ]
        expected = [
            {},
            {},
            {
                "required": True
            },
            {
                "max_occurs": 2,
                "min_occurs": 0
            },
            {
                "max_occurs": 2,
                "min_occurs": 2
            },
        ]

        for idx, res in enumerate(restrictions):
            attr = AttrFactory.create(restrictions=res)
            self.sanitizer.process_attribute_restrictions(attr)
            self.assertEqual(expected[idx], res.asdict())
Beispiel #2
0
    def test_add_default_attribute(self):
        xs_string = AttrTypeFactory.native(DataType.STRING)
        extension = ExtensionFactory.create(xs_string,
                                            Restrictions(required=True))
        item = ClassFactory.elements(1, extensions=[extension])

        ClassExtensionHandler.add_default_attribute(item, extension)
        expected = AttrFactory.create(name="@value",
                                      default=None,
                                      types=[xs_string],
                                      tag=Tag.EXTENSION)

        self.assertEqual(2, len(item.attrs))
        self.assertEqual(0, len(item.extensions))
        self.assertEqual(expected, item.attrs[0])

        xs_int = AttrTypeFactory.native(DataType.INT)
        extension = ExtensionFactory.create(xs_int, Restrictions(tokens=True))
        item.extensions.append(extension)
        ClassExtensionHandler.add_default_attribute(item, extension)

        expected.types.append(xs_int)
        expected_restrictions = Restrictions(tokens=True,
                                             required=True,
                                             min_occurs=1,
                                             max_occurs=1)

        self.assertEqual(2, len(item.attrs))
        self.assertEqual(0, len(item.extensions))
        self.assertEqual(expected, item.attrs[0])
        self.assertEqual(expected_restrictions, item.attrs[0].restrictions)
Beispiel #3
0
    def test_create_default_attribute_with_any_type(self):
        extension = ExtensionFactory.create(
            type=AttrTypeFactory.xs_any(),
            restrictions=Restrictions(min_occurs=1,
                                      max_occurs=1,
                                      required=True),
        )
        item = ClassFactory.create(extensions=[extension])

        ClassExtensionHandler.create_default_attribute(item, extension)
        expected = AttrFactory.create(
            name="any_element",
            index=0,
            default=None,
            types=[extension.type.clone()],
            tag=Tag.ANY,
            namespace="##any",
            restrictions=Restrictions(min_occurs=1,
                                      max_occurs=1,
                                      required=True),
        )

        self.assertEqual(1, len(item.attrs))
        self.assertEqual(0, len(item.extensions))
        self.assertEqual(expected, item.attrs[0])
Beispiel #4
0
    def test_merge(self):
        source = Restrictions(min_length=2, max_length=10)
        target = Restrictions(min_length=1, pattern=r"[A-Z]")

        target.merge(source)

        self.assertEqual(2, target.min_length)
        self.assertEqual(10, target.max_length)
        self.assertEqual(r"[A-Z]", target.pattern)
Beispiel #5
0
    def test_merge_ignore_nillable(self):
        parent = Restrictions(nillable=True)
        child = Restrictions()

        child.merge(parent)
        self.assertIsNone(child.nillable)

        child.nillable = False
        child.merge(parent)
        self.assertFalse(child.nillable)
Beispiel #6
0
    def test_field_choices(self):
        attr = AttrFactory.create(choices=[
            AttrFactory.element(
                namespace="foo",
                types=[type_float],
                restrictions=Restrictions(max_exclusive="10"),
            ),
            AttrFactory.element(namespace="bar"),
            AttrFactory.any(namespace="##other"),
            AttrFactory.element(name="bar", default="aa"),
            AttrFactory.element(name="tok",
                                restrictions=Restrictions(tokens=True)),
        ])

        actual = self.filters.field_choices(attr, "foo", ["a", "b"])
        expected = (
            {
                "name": "attr_B",
                "type": "Type[float]",
                "max_exclusive": 10.0
            },
            {
                "name": "attr_C",
                "namespace": "bar",
                "type": "Type[str]"
            },
            {
                "namespace": "##other",
                "wildcard": True,
                "type": "Type[object]",
            },
            {
                "default": '"aa"',
                "name": "bar",
                "type": "Type[str]"
            },
            {
                "default_factory": "list",
                "name": "tok",
                "tokens": True,
                "type": "Type[List[str]]",
            },
        )

        self.assertEqual(expected, actual)

        self.filters.docstring_style = DocstringStyle.ACCESSIBLE
        attr.choices[0].help = "help"
        actual = self.filters.field_choices(attr, None, [])
        self.assertEqual(attr.choices[0].help, actual[0]["doc"])
        self.assertNotIn("doc", actual[1])
Beispiel #7
0
    def test_clone_attribute(self):
        attr = AttrFactory.create(
            restrictions=Restrictions(length=1),
            types=[
                AttrTypeFactory.create(qname="x"),
                AttrTypeFactory.create(qname="y"),
                AttrTypeFactory.xs_int(),
            ],
        )
        restrictions = Restrictions(length=2)

        clone = ClassUtils.clone_attribute(attr, restrictions)

        self.assertEqual(2, clone.restrictions.length)
        self.assertIsNot(attr, clone)
Beispiel #8
0
 def build_class_extension(cls, target: Class, name: str,
                           restrictions: Dict) -> Extension:
     """Create an extension for the target class."""
     return Extension(
         type=cls.build_data_type(target, name),
         restrictions=Restrictions(**restrictions),
     )
Beispiel #9
0
 def create(
     cls,
     name: Optional[str] = None,
     index: Optional[int] = None,
     types: Optional[List[AttrType]] = None,
     choices: Optional[List[Attr]] = None,
     tag: Optional[str] = None,
     namespace: Optional[str] = None,
     default: Any = None,
     fixed: bool = False,
     mixed: bool = False,
     restrictions: Optional[Restrictions] = None,
     **kwargs: Any,
 ) -> Attr:
     name = name or f"attr_{cls.next_letter()}"
     return Attr(
         name=name,
         index=cls.counter if index is None else index,
         types=types or [AttrTypeFactory.native(DataType.STRING)],
         choices=choices or [],
         tag=tag or random.choice(cls.tags),
         namespace=namespace or None,
         default=default or None,
         fixed=fixed,
         mixed=mixed,
         restrictions=restrictions or Restrictions(),
         **kwargs,
     )
    def process(cls, target: Class):
        """Add or update an existing an xs:anyType derived attribute if the
        target class supports mixed content."""

        if not target.mixed:
            return

        wildcard = first(attr for attr in target.attrs if attr.tag == Tag.ANY)

        if wildcard:
            wildcard.mixed = True
            if not wildcard.is_list:
                wildcard.restrictions.min_occurs = 0
                wildcard.restrictions.max_occurs = sys.maxsize
        else:
            attr = Attr(
                name="content",
                types=[AttrType(qname=str(DataType.ANY_TYPE), native=True)],
                tag=Tag.ANY,
                mixed=True,
                namespace=NamespaceType.ANY_NS,
                restrictions=Restrictions(min_occurs=0,
                                          max_occurs=sys.maxsize),
            )
            target.attrs.insert(0, attr)
Beispiel #11
0
    def group_fields(self, target: Class, attrs: List[Attr]):
        """Group attributes into a new compound field."""

        pos = target.attrs.index(attrs[0])
        names = []
        choices = []
        min_occurs = []
        max_occurs = []
        for attr in attrs:
            target.attrs.remove(attr)
            names.append(attr.local_name)
            min_occurs.append(attr.restrictions.min_occurs)
            max_occurs.append(attr.restrictions.max_occurs)
            choices.append(self.build_attr_choice(attr))

        name = "choice" if len(names) > 3 else "_Or_".join(names)
        target.attrs.insert(
            pos,
            Attr(
                name=name,
                index=0,
                types=[AttrType(qname=str(DataType.ANY_TYPE), native=True)],
                tag=Tag.CHOICE,
                restrictions=Restrictions(
                    min_occurs=min((x for x in min_occurs if x is not None),
                                   default=0),
                    max_occurs=max((x for x in max_occurs if x is not None),
                                   default=0),
                ),
                choices=choices,
            ),
        )
Beispiel #12
0
    def test_sanitize_attribute_sequence(self):
        def len_sequential(target: Class):
            return len([
                attr for attr in target.attrs if attr.restrictions.sequential
            ])

        restrictions = Restrictions(max_occurs=2, sequential=True)
        target = ClassFactory.create(attrs=[
            AttrFactory.create(restrictions=restrictions.clone()),
            AttrFactory.create(restrictions=restrictions.clone()),
        ])

        attrs_clone = [attr.clone() for attr in target.attrs]

        self.sanitizer.process_attribute_sequence(target, target.attrs[0])
        self.assertEqual(2, len_sequential(target))

        target.attrs[0].restrictions.sequential = False
        self.sanitizer.process_attribute_sequence(target, target.attrs[0])
        self.assertEqual(1, len_sequential(target))

        self.sanitizer.process_attribute_sequence(target, target.attrs[1])
        self.assertEqual(0, len_sequential(target))

        target.attrs = attrs_clone
        target.attrs[1].restrictions.sequential = False
        self.sanitizer.process_attribute_sequence(target, target.attrs[0])
        self.assertEqual(0, len_sequential(target))

        target.attrs[0].restrictions.sequential = True
        target.attrs[0].restrictions.max_occurs = 0
        target.attrs[1].restrictions.sequential = True
        self.sanitizer.process_attribute_sequence(target, target.attrs[0])
        self.assertEqual(1, len_sequential(target))
Beispiel #13
0
    def test_copy_attribute_properties(self, mock_copy_inner_class):
        source = ClassFactory.elements(1, qname="Foobar")
        source.attrs[0].restrictions.max_length = 100
        source.attrs[0].restrictions.min_length = 1
        source.attrs[0].help = "foo"
        source.attrs[0].types = [
            AttrTypeFactory.create(qname="first"),
            AttrTypeFactory.create(qname="second"),
        ]

        target = ClassFactory.elements(1)
        attr = target.attrs[0]
        attr.restrictions.min_length = 2
        attr.types.clear()
        attr.types.append(AttrTypeFactory.create(qname=source.name))

        self.assertEqual("Foobar", attr.types[0].name)
        self.processor.copy_attribute_properties(source, target, attr,
                                                 attr.types[0])

        self.assertEqual("first", attr.types[0].name)
        self.assertEqual("second", attr.types[1].name)
        self.assertEqual("foo", attr.help)
        self.assertEqual(Restrictions(min_length=2, max_length=100),
                         attr.restrictions)
        mock_copy_inner_class.assert_has_calls([
            mock.call(source, target, attr, source.attrs[0].types[0]),
            mock.call(source, target, attr, source.attrs[0].types[1]),
        ])
Beispiel #14
0
 def create(
     cls,
     name=None,
     index=None,
     types=None,
     choices=None,
     tag=None,
     namespace=None,
     help=None,
     default=None,
     fixed=False,
     mixed=False,
     restrictions=None,
 ):
     name = name or f"attr_{cls.next_letter()}"
     return cls.model(
         name=name,
         index=cls.counter if index is None else index,
         types=types or [AttrTypeFactory.xs_string()],
         choices=choices or [],
         tag=tag or random.choice(cls.types).__name__,
         namespace=namespace or None,
         help=help or None,
         default=default or None,
         fixed=fixed,
         mixed=mixed,
         restrictions=restrictions or Restrictions(),
     )
Beispiel #15
0
    def test_group_fields(self):
        target = ClassFactory.create(attrs=AttrFactory.list(2))
        target.attrs[0].restrictions.min_occurs = 10
        target.attrs[0].restrictions.max_occurs = 15
        target.attrs[1].restrictions.min_occurs = 5
        target.attrs[1].restrictions.max_occurs = 20

        expected = AttrFactory.create(
            name="attr_B_Or_attr_C",
            tag="Choice",
            index=0,
            types=[AttrTypeFactory.xs_any()],
            choices=[
                AttrFactory.create(
                    tag=target.attrs[0].tag,
                    name="attr_B",
                    types=target.attrs[0].types,
                ),
                AttrFactory.create(
                    tag=target.attrs[1].tag,
                    name="attr_C",
                    types=target.attrs[1].types,
                ),
            ],
        )
        expected_res = Restrictions(min_occurs=5, max_occurs=20)

        self.sanitizer.group_fields(target, list(target.attrs))
        self.assertEqual(1, len(target.attrs))
        self.assertEqual(expected, target.attrs[0])
        self.assertEqual(expected_res, target.attrs[0].restrictions)
Beispiel #16
0
 def build_class_extension(
     self, target: Class, name: str, index: int, restrictions: Dict
 ) -> Extension:
     """Create an extension for the target class."""
     return Extension(
         type=self.build_data_type(target, name, index=index),
         restrictions=Restrictions(**restrictions),
     )
Beispiel #17
0
    def test_build_class_attribute(
        self,
        mock_real_name,
        mock_display_help,
        mock_prefix,
        mock_default_value,
        mock_is_fixed,
        mock_get_restrictions,
        mock_element_namespace,
        mock_build_class_attribute_types,
    ):
        item = ClassFactory.create(ns_map={"bar": "foo"})

        mock_build_class_attribute_types.return_value = AttrTypeFactory.list(
            1, qname="int")
        mock_real_name.return_value = item.name
        mock_display_help.return_value = "sos"
        mock_prefix.return_value = "com"
        mock_default_value.return_value = "default"
        mock_is_fixed.return_value = True
        mock_element_namespace.return_value = "http://something/common"
        mock_get_restrictions.return_value = {"required": True}

        attribute = Attribute(default="false")
        attribute.index = 66
        attribute.ns_map["foo"] = "bar"

        SchemaMapper.build_class_attribute(item, attribute, Restrictions())
        expected = AttrFactory.create(
            name=mock_real_name.return_value,
            types=mock_build_class_attribute_types.return_value,
            tag=Tag.ATTRIBUTE,
            namespace=mock_element_namespace.return_value,
            help=mock_display_help.return_value,
            default=mock_default_value.return_value,
            fixed=mock_is_fixed.return_value,
            index=66,
            restrictions=Restrictions(required=True),
        )
        self.assertEqual(expected, item.attrs[0])
        self.assertEqual({"bar": "foo", "foo": "bar"}, item.ns_map)
        mock_build_class_attribute_types.assert_called_once_with(
            item, attribute)
        mock_element_namespace.assert_called_once_with(attribute,
                                                       item.target_namespace)
Beispiel #18
0
    def test_property_is_list(self):
        restrictions = Restrictions()
        self.assertFalse(restrictions.is_list)

        restrictions.max_occurs = 1
        self.assertFalse(restrictions.is_list)

        restrictions.max_occurs = 2
        self.assertTrue(restrictions.is_list)
Beispiel #19
0
    def test_field_type_with_token_attr(self):
        attr = AttrFactory.create(
            types=AttrTypeFactory.list(1, qname="foo_bar"),
            restrictions=Restrictions(tokens=True),
        )
        self.assertEqual("List[FooBar]", self.filters.field_type(attr, []))

        attr.restrictions.max_occurs = 2
        self.assertEqual("List[List[FooBar]]", self.filters.field_type(attr, []))
Beispiel #20
0
 def create(
     cls,
     attr_type: Optional[AttrType] = None,
     restrictions: Optional[Restrictions] = None,
     **kwargs: Any,
 ) -> Extension:
     return Extension(
         type=attr_type or AttrTypeFactory.create(),
         restrictions=restrictions or Restrictions(),
     )
Beispiel #21
0
    def test_asdict_with_implied_types(self):
        restrictions = Restrictions(min_occurs=1, max_occurs=4)
        self.assertEqual({
            "max_occurs": 4,
            "min_occurs": 1
        }, restrictions.asdict())

        restrictions.min_occurs = 0
        self.assertEqual({"max_occurs": 4}, restrictions.asdict())

        restrictions.max_occurs = sys.maxsize
        self.assertEqual({}, restrictions.asdict())
Beispiel #22
0
    def test_process(self):
        one = AttrFactory.attribute(fixed=True)
        one_clone = one.clone()
        restrictions = Restrictions(min_occurs=10, max_occurs=15)
        two = AttrFactory.element(restrictions=restrictions, fixed=True)
        two_clone = two.clone()
        two_clone.restrictions.min_occurs = 5
        two_clone.restrictions.max_occurs = 5
        two_clone_two = two.clone()
        two_clone_two.restrictions.min_occurs = 4
        two_clone_two.restrictions.max_occurs = 4
        three = AttrFactory.element()
        four = AttrFactory.enumeration()
        four_clone = four.clone()
        five = AttrFactory.element()
        five_clone = five.clone()
        five_clone_two = five.clone()

        target = ClassFactory.create(
            attrs=[
                one,
                one_clone,
                two,
                two_clone,
                two_clone_two,
                three,
                four,
                four_clone,
                five,
                five_clone,
                five_clone_two,
            ]
        )

        winners = [one, two, three, four, five]

        self.processor.process(target)
        self.assertEqual(winners, target.attrs)

        self.assertTrue(one.fixed)
        self.assertIsNone(one.restrictions.min_occurs)
        self.assertIsNone(one.restrictions.max_occurs)
        self.assertFalse(two.fixed)
        self.assertEqual(4, two.restrictions.min_occurs)
        self.assertEqual(24, two.restrictions.max_occurs)
        self.assertIsNone(three.restrictions.min_occurs)
        self.assertIsNone(three.restrictions.max_occurs)
        self.assertIsNone(four.restrictions.min_occurs)
        self.assertIsNone(four.restrictions.max_occurs)
        self.assertEqual(0, five.restrictions.min_occurs)
        self.assertEqual(3, five.restrictions.max_occurs)
Beispiel #23
0
    def test_group_fields_with_effective_choices_sums_occurs(self):
        target = ClassFactory.create(attrs=AttrFactory.list(2))
        target.attrs[0].restrictions.choice = "effective_1"
        target.attrs[1].restrictions.choice = "effective_1"
        target.attrs[0].restrictions.min_occurs = 1
        target.attrs[0].restrictions.max_occurs = 2
        target.attrs[1].restrictions.min_occurs = 3
        target.attrs[1].restrictions.max_occurs = 4

        expected_res = Restrictions(min_occurs=4, max_occurs=6)

        self.sanitizer.group_fields(target, list(target.attrs))
        self.assertEqual(1, len(target.attrs))
        self.assertEqual(expected_res, target.attrs[0].restrictions)
Beispiel #24
0
    def test_element_children_with_parents_restrictions(self):
        choice = Choice(elements=[Element(name="elem1")])
        complex_type = ComplexType(
            sequence=Sequence(choices=[choice], min_occurs=0, max_occurs=3))
        parent_restrictions = Restrictions.from_element(complex_type)
        children = SchemaMapper.element_children(complex_type,
                                                 parent_restrictions)

        child, restrictions = next(children)
        expected = Restrictions(min_occurs=0,
                                max_occurs=3,
                                sequential=True,
                                choice=str(id(choice)))
        self.assertEqual(expected, restrictions)
Beispiel #25
0
    def test_build_class_attribute_from_list(self):
        target = ClassFactory.create()
        data = [1, True, 1.1]

        DictMapper.build_class_attribute(target, "a", data)

        expected = AttrFactory.create(
            name="a",
            tag=Tag.ELEMENT,
            types=[
                AttrTypeFactory.native(DataType.SHORT, tag=Tag.ELEMENT),
                AttrTypeFactory.native(DataType.BOOLEAN, tag=Tag.ELEMENT),
                AttrTypeFactory.native(DataType.FLOAT, tag=Tag.ELEMENT),
            ],
        )
        restrictions = Restrictions(max_occurs=sys.maxsize)
        self.assertEqual(expected, target.attrs[0])
        self.assertEqual(restrictions, target.attrs[0].restrictions)
Beispiel #26
0
    def test_process_simple_dependency(self, mock_copy_inner_classes):
        source = ClassFactory.elements(1, qname="Foobar")
        source.attrs[0].restrictions.max_length = 100
        source.attrs[0].restrictions.min_length = 1

        target = ClassFactory.elements(1)
        attr = target.attrs[0]
        attr.restrictions.min_length = 2
        attr.types.clear()
        attr.types.append(AttrTypeFactory.create(qname=source.name))

        self.assertEqual("Foobar", attr.types[0].name)
        self.processor.process_simple_dependency(source, target, attr,
                                                 attr.types[0])

        self.assertEqual("string", attr.types[0].name)
        self.assertEqual(Restrictions(min_length=2, max_length=100),
                         attr.restrictions)
        mock_copy_inner_classes.assert_called_once_with(source, target)
Beispiel #27
0
 def build_attr(
     cls,
     name: str,
     qname: str,
     native: bool = False,
     forward: bool = False,
     namespace: Optional[str] = None,
     default: Optional[str] = None,
 ) -> Attr:
     """Builder method for attributes."""
     occurs = 1 if default is not None else None
     return Attr(
         tag=Tag.ELEMENT,
         name=name,
         namespace=namespace,
         default=default,
         types=[AttrType(qname=qname, forward=forward, native=native)],
         restrictions=Restrictions(min_occurs=occurs, max_occurs=occurs),
     )
Beispiel #28
0
    def test_build_attr_choice(self):
        attr = AttrFactory.create(name="a",
                                  namespace="xsdata",
                                  default="123",
                                  help="help",
                                  fixed=True)
        attr.local_name = "aaa"
        attr.restrictions = Restrictions(
            required=True,
            prohibited=None,
            min_occurs=1,
            max_occurs=1,
            min_exclusive="1.1",
            min_inclusive="1",
            min_length=1,
            max_exclusive="1",
            max_inclusive="1.1",
            max_length=10,
            total_digits=333,
            fraction_digits=2,
            length=5,
            white_space="collapse",
            pattern=r"[A-Z]",
            explicit_timezone="+1",
            nillable=True,
            choice="abc",
            sequential=True,
        )
        expected_res = attr.restrictions.clone()
        expected_res.min_occurs = None
        expected_res.max_occurs = None
        expected_res.sequential = None

        actual = self.sanitizer.build_attr_choice(attr)

        self.assertEqual(attr.local_name, actual.name)
        self.assertEqual(attr.namespace, actual.namespace)
        self.assertEqual(attr.default, actual.default)
        self.assertEqual(attr.tag, actual.tag)
        self.assertEqual(attr.types, actual.types)
        self.assertEqual(expected_res, actual.restrictions)
        self.assertEqual(attr.help, actual.help)
        self.assertFalse(actual.fixed)
Beispiel #29
0
    def test_build_class_extensions(self, mock_children_extensions):
        bar_type = AttrTypeFactory.create(qname="bar")
        foo_type = AttrTypeFactory.create(qname="foo")
        some_type = AttrTypeFactory.create(qname="{xsdata}something")

        bar = ExtensionFactory.create(type=bar_type)
        double = ExtensionFactory.create(type=bar_type)
        foo = ExtensionFactory.create(type=foo_type)

        mock_children_extensions.return_value = [bar, double, foo]
        self_ext = ExtensionFactory.create(type=some_type,
                                           restrictions=Restrictions(
                                               min_occurs=1, max_occurs=1))

        item = ClassFactory.create()
        element = Element(type="something")
        SchemaMapper.build_class_extensions(element, item)

        self.assertEqual(3, len(item.extensions))
        self.assertCountEqual([bar, self_ext, foo], item.extensions)
Beispiel #30
0
 def setUp(self) -> None:
     self.restrictions = Restrictions(
         required=True,
         prohibited=None,
         min_occurs=1,
         max_occurs=1,
         min_exclusive="1.1",
         min_inclusive="1",
         min_length=1,
         max_exclusive="1",
         max_inclusive="1.1",
         max_length=10,
         total_digits=333,
         fraction_digits=2,
         length=5,
         white_space="collapse",
         pattern=r"[A-Z]",
         explicit_timezone="+1",
         nillable=True,
     )