Example #1
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)
Example #2
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])
Example #3
0
 def test_element_children(self):
     sequence_one = Sequence(elements=[Element(), Element()])
     sequence_two = Sequence(max_occurs=2, elements=[Element(), Element()])
     restriction = Restriction(
         enumerations=[Enumeration(value=x) for x in "abc"], sequence=sequence_two,
     )
     complex_type = ComplexType(
         attributes=[Attribute(), Attribute()],
         sequence=sequence_one,
         simple_content=SimpleContent(restriction=Restriction()),
         complex_content=ComplexContent(restriction=restriction,),
     )
     restrictions = Restrictions.from_element(complex_type)
     children = self.builder.element_children(complex_type, restrictions)
     expected = [
         (sequence_two.elements[0], Restrictions.from_element(sequence_two)),
         (sequence_two.elements[1], Restrictions.from_element(sequence_two)),
         (restriction.enumerations[0], Restrictions.from_element(restriction)),
         (restriction.enumerations[1], Restrictions.from_element(restriction)),
         (restriction.enumerations[2], Restrictions.from_element(restriction)),
         (sequence_one.elements[0], Restrictions.from_element(sequence_one)),
         (sequence_one.elements[1], Restrictions.from_element(sequence_one)),
         (complex_type.attributes[0], Restrictions.from_element(complex_type)),
         (complex_type.attributes[1], Restrictions.from_element(complex_type)),
     ]
     self.assertIsInstance(children, GeneratorType)
     self.assertEqual(expected, list(children))
Example #4
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())
Example #5
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))
Example #6
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)
Example #7
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)
Example #8
0
    def element_children(
        cls, obj: ElementBase, parent_restrictions: Restrictions
    ) -> Iterator[Tuple[ElementBase, Restrictions]]:
        """Recursively find and return all child elements that are qualified to
        be class attributes, with all their restrictions."""

        for child in obj.children():
            if child.is_attribute:
                yield child, parent_restrictions
            else:
                restrictions = parent_restrictions.clone()
                restrictions.merge(Restrictions.from_element(child))
                yield from cls.element_children(child, restrictions)
Example #9
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])
Example #10
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)
Example #11
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)
Example #12
0
    def build_class_attribute(
        cls, target: Class, obj: ElementBase, parent_restrictions: Restrictions
    ):
        """Generate and append an attribute field to the target class."""

        target.ns_map.update(obj.ns_map)
        types = cls.build_class_attribute_types(target, obj)
        restrictions = Restrictions.from_element(obj)

        if obj.class_name in (Tag.ELEMENT, Tag.ANY):
            restrictions.merge(parent_restrictions)

        if restrictions.prohibited:
            return

        name = obj.real_name
        target.attrs.append(
            Attr(
                index=obj.index,
                name=name,
                local_name=name,
                default=obj.default_value,
                fixed=obj.is_fixed,
                types=types,
                tag=obj.class_name,
                help=obj.display_help,
                namespace=cls.element_namespace(obj, target.qname.namespace),
                restrictions=restrictions,
            )
        )
Example #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]),
        ])
Example #14
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)
Example #15
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(),
     )
Example #16
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),
     )
    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)
Example #18
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,
     )
Example #19
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,
            ),
        )
Example #20
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),
     )
Example #21
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)
Example #22
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)
Example #23
0
    def build_class_attributes(cls, obj: ElementBase, target: Class):
        """Build the target class attributes from the given ElementBase
        children."""

        restrictions = Restrictions.from_element(obj)
        for child, restrictions in cls.element_children(obj, restrictions):
            cls.build_class_attribute(target, child, restrictions)

        target.attrs.sort(key=lambda x: x.index)
Example #24
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, []))
Example #25
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(),
     )
Example #26
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,
     )
Example #27
0
    def test_asdict_with_types(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,
        )

        expected = {
            "explicit_timezone": "+1",
            "fraction_digits": 2,
            "length": 5,
            "max_exclusive": 1.0,  # str -> float
            "max_inclusive": 1.1,  # str -> float
            "max_length": 10,
            "max_occurs": 1,
            "min_exclusive": 1.1,  # str -> float
            "min_inclusive": 1.0,  # str -> float
            "min_length": 1,
            "min_occurs": 1,
            "nillable": True,
            "pattern": "[A-Z]",
            "required": True,
            "total_digits": 333,
            "white_space": "collapse",
        }
        self.assertEqual(expected, restrictions.asdict(types=[float]))
Example #28
0
    def element_children(
        self, obj: ElementBase, restrictions: Restrictions
    ) -> Iterator[Tuple[ElementBase, Restrictions]]:
        """Recursively find and return all child elements that are qualified to
        be class attributes."""

        for child in obj.children():
            if child.is_attribute:
                yield child, restrictions
            else:
                yield from self.element_children(
                    child, restrictions=Restrictions.from_element(child)
                )
Example #29
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)
Example #30
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())