Пример #1
0
 def table_fixture(self, table_, _shape_factory_):
     shapes = SlideShapes(element('p:spTree'), None)
     rows, cols, x, y, cx, cy = 1, 2, 10, 11, 12, 13
     _shape_factory_.return_value = table_
     expected_xml = (
         '<p:spTree xmlns:p="http://schemas.openxmlformats.org/presentati'
         'onml/2006/main">\n  <p:graphicFrame xmlns:a="http://schemas.ope'
         'nxmlformats.org/drawingml/2006/main">\n    <p:nvGraphicFramePr>'
         '\n      <p:cNvPr id="1" name="Table 0"/>\n      <p:cNvGraphicFr'
         'amePr>\n        <a:graphicFrameLocks noGrp="1"/>\n      </p:cNv'
         'GraphicFramePr>\n      <p:nvPr/>\n    </p:nvGraphicFramePr>\n  '
         '  <p:xfrm>\n      <a:off x="10" y="11"/>\n      <a:ext cx="12" '
         'cy="13"/>\n    </p:xfrm>\n    <a:graphic>\n      <a:graphicData'
         ' uri="http://schemas.openxmlformats.org/drawingml/2006/table">'
         '\n        <a:tbl>\n          <a:tblPr firstRow="1" bandRow="1">'
         '\n            <a:tableStyleId>{5C22544A-7EE6-4342-B048-85BDC9FD'
         '1C3A}</a:tableStyleId>\n          </a:tblPr>\n          <a:tblG'
         'rid>\n            <a:gridCol w="6"/>\n            <a:gridCol w='
         '"6"/>\n          </a:tblGrid>\n          <a:tr h="13">\n       '
         '     <a:tc>\n              <a:txBody>\n                <a:bodyP'
         'r/>\n                <a:lstStyle/>\n                <a:p/>\n   '
         '           </a:txBody>\n              <a:tcPr/>\n            </'
         'a:tc>\n            <a:tc>\n              <a:txBody>\n          '
         '      <a:bodyPr/>\n                <a:lstStyle/>\n             '
         '   <a:p/>\n              </a:txBody>\n              <a:tcPr/>\n'
         '            </a:tc>\n          </a:tr>\n        </a:tbl>\n     '
         ' </a:graphicData>\n    </a:graphic>\n  </p:graphicFrame>\n</p:s'
         'pTree>'
     )
     return shapes, rows, cols, x, y, cx, cy, table_, expected_xml
Пример #2
0
 def title_fixture(self, request, _shape_factory_, shape_):
     spTree_cxml, found = request.param
     spTree = element(spTree_cxml)
     shapes = SlideShapes(spTree, None)
     calls = [call(shapes, spTree.xpath('p:sp')[1])] if found else []
     _shape_ = shape_ if found else None
     return shapes, _shape_factory_, calls, _shape_
Пример #3
0
 def picture_fixture(
         self, picture_, part_prop_, image_part_, _shape_factory_):
     shapes = SlideShapes(element('p:spTree'), None)
     image_file, x, y, cx, cy = 'foobar.png', 1, 2, 3, 4
     expected_xml = (
         '<p:spTree xmlns:p="http://schemas.openxmlformats.org/presentati'
         'onml/2006/main">\n  <p:pic xmlns:a="http://schemas.openxmlforma'
         'ts.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlform'
         'ats.org/officeDocument/2006/relationships">\n    <p:nvPicPr>\n '
         '     <p:cNvPr id="1" name="Picture 0" descr="Image Description"'
         '/>\n      <p:cNvPicPr>\n        <a:picLocks noChangeAspect="1"/'
         '>\n      </p:cNvPicPr>\n      <p:nvPr/>\n    </p:nvPicPr>\n    '
         '<p:blipFill>\n      <a:blip r:embed="rId42"/>\n      <a:stretch'
         '>\n        <a:fillRect/>\n      </a:stretch>\n    </p:blipFill>'
         '\n    <p:spPr>\n      <a:xfrm>\n        <a:off x="1" y="2"/>\n '
         '       <a:ext cx="101" cy="102"/>\n      </a:xfrm>\n      <a:pr'
         'stGeom prst="rect">\n        <a:avLst/>\n      </a:prstGeom>\n '
         '   </p:spPr>\n  </p:pic>\n</p:spTree>'
     )
     slide_part_ = part_prop_.return_value
     get_or_add_image_part_ = slide_part_.get_or_add_image_part
     get_or_add_image_part_.return_value = image_part_, 'rId42'
     image_part_.scale.return_value = 101, 102
     image_part_.desc = 'Image Description'
     _shape_factory_.return_value = picture_
     return (
         shapes, image_file, x, y, cx, cy, picture_, expected_xml
     )
Пример #4
0
 def ph_name_fixture(self, request):
     ph_type, sp_id, orient, expected_name = request.param
     spTree = element(
         'p:spTree/(p:cNvPr{name=Title 1},p:cNvPr{name=Table Placeholder '
         '3})'
     )
     shapes = SlideShapes(spTree, None)
     return shapes, ph_type, sp_id, orient, expected_name
Пример #5
0
 def index_fixture(self, request, shape_):
     idx = request.param
     spTree = element('p:spTree/(p:sp,p:sp,p:sp)')
     sps = spTree.xpath('p:sp')
     shapes = SlideShapes(spTree, None)
     shape_.element = sps[idx]
     expected_value = idx
     return shapes, shape_, expected_value
Пример #6
0
 def clone_fixture(
         self, slide_layout_, _clone_layout_placeholder_, placeholder_):
     shapes = SlideShapes(None, None)
     calls = [call(shapes, placeholder_)]
     slide_layout_.iter_cloneable_placeholders.return_value = (
         iter([placeholder_])
     )
     return shapes, slide_layout_, calls
Пример #7
0
    def sp_fixture(self, _left_prop_, _top_prop_, _width_prop_, _height_prop_):
        origin_x, origin_y = 42, 24
        spTree = element("p:spTree")
        shapes = SlideShapes(spTree, None)
        _left_prop_.return_value, _top_prop_.return_value = 12, 34
        _width_prop_.return_value, _height_prop_.return_value = 56, 78

        builder = FreeformBuilder(shapes, None, None, None, None)
        expected_xml = snippet_seq("freeform")[0]
        return builder, origin_x, origin_y, spTree, expected_xml
Пример #8
0
 def add_chart_fixture(
         self, chart_data_, _add_chart_graphic_frame_, graphic_frame_,
         part_prop_):
     shapes = SlideShapes(None, None)
     chart_type = 0
     rId, x, y, cx, cy = 'rId42', 1, 2, 3, 4
     part_prop_.return_value.add_chart_part.return_value = rId
     return (
         shapes, chart_type, x, y, cx, cy, chart_data_, rId,
         graphic_frame_
     )
Пример #9
0
def change_shapes(collection, change, data, handler, **kwargs):
    '''
    Apply changes to a collection of shapes in the context of data.
    ``collection`` is a slide.shapes or group shapes.
    ``change`` is typically a dict of <shape-name>: commands.
    ``data`` is a dictionary passed to the template engine.
    '''
    prs = kwargs.get('prs')
    new_slide = kwargs.get('new_slide')
    copy_slide = kwargs.get('copy_slide', False)
    source_slide = kwargs.get('source_slide')

    dest = prs.slides.add_slide(new_slide) if copy_slide else None
    mapping = {}
    for shape in collection:
        if shape.name not in change:
            copy_slide_elem(shape, dest)
            continue

        spec = change[shape.name]
        if shape.name not in mapping:
            mapping[shape.name] = 0

        if spec.get('data'):
            if not isinstance(spec['data'], (dict,)):
                spec['data'] = {'function': '{}'.format(spec['data']) if not isinstance(
                    spec['data'], (str, six.string_types,)) else spec['data']}
            shape_data = build_transform(
                spec['data'], vars={'data': None, 'handler': None})(data=data, handler=handler)[0]
        else:
            if isinstance(data, (dict, AttrDict,)) and 'handler' in data:
                data.pop('handler')
            shape_data = copy.deepcopy(data)

        if isinstance(shape_data, (dict, AttrDict,)):
            shape_data['handler'] = handler

        if spec.get('stack'):
            shape_data = shape_data[mapping[shape.name]]
        mapping[shape.name] = mapping[shape.name] + 1
        # If the shape is a group, apply spec to each sub-shape
        if is_group(shape):
            sub_shapes = SlideShapes(shape.element, collection)
            change_shapes(sub_shapes, spec, shape_data, handler)
        # Add args to shape_data
        if hasattr(handler, 'args'):
            args = {k: v[0] for k, v in handler.args.items() if len(v) > 0}
            shape_data['args'] = args
        # Run commands in the spec
        for cmd, method in COMMANDS_LIST.items():
            if cmd in spec:
                method(shape, spec, shape_data)
        copy_slide_elem(shape, dest)
    add_new_slide(dest, source_slide)
Пример #10
0
 def connector_fixture(self, _add_cxnSp_, _shape_factory_, connector_):
     shapes = SlideShapes(element('p:spTree'), None)
     connector_type = MSO_CONNECTOR.STRAIGHT
     begin_x, begin_y, end_x, end_y = 1, 2, 3, 4
     cxnSp = element('p:cxnSp')
     _add_cxnSp_.return_value = cxnSp
     _shape_factory_.return_value = connector_
     return (
         shapes, connector_type, begin_x, begin_y, end_x, end_y, cxnSp,
         connector_
     )
Пример #11
0
def apply_commands(rule: Dict[str, dict], shapes, data: dict):
    '''
    Apply commands in rule to change shapes using data.

    :arg dict rule: a dict of shape names, and commands to apply on each.
        e.g. ``{"Oval 1": {"fill": "red"}, "Oval 2": {"text": "OK"}}``
    :arg Shapes shapes: a slide.shapes or group.shapes object on which the rule should be applied
    :arg dict data: data context for the commands in the rule
    '''
    # Apply every rule to every pattern -- as long as the rule key matches the shape name
    for pattern, spec in rule.items():
        if pattern in rule_cmdlist:
            continue
        shape_matched = False
        for shape in shapes:
            if not fnmatchcase(shape.name, pattern):
                continue
            shape_matched = True
            # Clone all slides into the `clones` list BEFORE applying any command. Ensures that
            # commands applied to the shape don't propagate into its clones
            clones = []
            clone_seq = iterate_on(spec.get('clone-shape', [None]), data)
            parent_clone = data.get('clone', None)
            for i, (clone_key, clone_val) in enumerate(clone_seq):
                if i > 0:
                    # This copies only a shape, group or image. Not table, chart, media, equation,
                    # or zoom. But we don't see a need for these yet.
                    el = copy.deepcopy(shape.element)
                    shape.element.addnext(el)
                    shape = pptx.shapes.autoshape.Shape(el, None)
                clones.append(AttrDict(pos=i, key=clone_key, val=clone_val, shape=shape,
                                       parent=parent_clone))
            # Run commands in the spec on all cloned shapes
            is_group = shape.element.tag.endswith('}grpSp')
            for i, clone in enumerate(clones):
                # Include shape-level `data:`. Add shape, clone as variables
                shape_data = load_data(
                    spec.get('data', {}), _default_key='function', shape=shape, clone=clone,
                    **{k: v for k, v in data.items() if k not in {'shape', 'clone'}})
                for cmd in spec:
                    if cmd in commands.cmdlist:
                        commands.cmdlist[cmd](clone.shape, spec[cmd], shape_data)
                    # Warn on unknown commands. But don't warn on groups -- they have sub-shapes
                    elif cmd not in special_cmdlist and not is_group:
                        app_log.warn('pptgen2: Unknown command: %s on shape: %s', cmd, pattern)
                # If the shape is a group, apply spec to each sub-shape
                if is_group:
                    apply_commands(spec, SlideShapes(clone.shape.element, shapes), shape_data)
        # Warn if the pattern is neither a shape nor a command
        if (not shape_matched and pattern not in special_cmdlist and
                pattern not in commands.cmdlist):
            app_log.warn('pptgen2: No shape matches pattern: %s', pattern)
Пример #12
0
 def add_cxnSp_fixture(self, request):
     begin_x, begin_y, end_x, end_y, spPr_cxml = request.param
     shapes = SlideShapes(element('p:spTree'), None)
     connector_type = MSO_CONNECTOR.STRAIGHT
     tmpl_cxml = (
         'p:cxnSp/(p:nvCxnSpPr/(p:cNvPr{id=1,name=Connector 0},p:cNvCxnSp'
         'Pr,p:nvPr),%s,a:prstGeom{prst=line}/a:avLst),p:style/(a:lnRef{i'
         'dx=2}/a:schemeClr{val=accent1},a:fillRef{idx=0}/a:schemeClr{val'
         '=accent1},a:effectRef{idx=1}/a:schemeClr{val=accent1},a:fontRef'
         '{idx=minor}/a:schemeClr{val=tx1}))'
     )
     expected_xml = xml(tmpl_cxml % spPr_cxml)
     return (
         shapes, connector_type, begin_x, begin_y, end_x, end_y,
         expected_xml
     )
Пример #13
0
 def clone_ph_fixture(self, placeholder_):
     shapes = SlideShapes(element('p:spTree'), None)
     expected_xml = (
         '<p:spTree xmlns:p="http://schemas.openxmlformats.org/presentati'
         'onml/2006/main">\n  <p:sp xmlns:a="http://schemas.openxmlformat'
         's.org/drawingml/2006/main">\n    <p:nvSpPr>\n      <p:cNvPr id='
         '"1" name="Vertical Chart Placeholder 0"/>\n      <p:cNvSpPr>\n '
         '       <a:spLocks noGrp="1"/>\n      </p:cNvSpPr>\n      <p:nvP'
         'r>\n        <p:ph type="chart" idx="42" orient="vert" sz="half"'
         '/>\n      </p:nvPr>\n    </p:nvSpPr>\n    <p:spPr/>\n  </p:sp>'
         '\n</p:spTree>'
     )
     placeholder_.ph_type = PP_PLACEHOLDER.CHART
     placeholder_.idx = 42
     placeholder_.orient = 'vert'
     placeholder_.sz = 'half'
     return shapes, placeholder_, expected_xml
Пример #14
0
 def textbox_fixture(self, textbox_, _shape_factory_):
     shapes = SlideShapes(element('p:spTree'), None)
     x, y, cx, cy = 1, 2, 3, 4
     expected_xml = (
         '<p:spTree xmlns:p="http://schemas.openxmlformats.org/presentati'
         'onml/2006/main">\n  <p:sp xmlns:a="http://schemas.openxmlformat'
         's.org/drawingml/2006/main">\n    <p:nvSpPr>\n      <p:cNvPr id='
         '"1" name="TextBox 0"/>\n      <p:cNvSpPr txBox="1"/>\n      <p:'
         'nvPr/>\n    </p:nvSpPr>\n    <p:spPr>\n      <a:xfrm>\n        '
         '<a:off x="1" y="2"/>\n        <a:ext cx="3" cy="4"/>\n      </a'
         ':xfrm>\n      <a:prstGeom prst="rect">\n        <a:avLst/>\n   '
         '   </a:prstGeom>\n      <a:noFill/>\n    </p:spPr>\n    <p:txBo'
         'dy>\n      <a:bodyPr wrap="none">\n        <a:spAutoFit/>\n    '
         '  </a:bodyPr>\n      <a:lstStyle/>\n      <a:p/>\n    </p:txBod'
         'y>\n  </p:sp>\n</p:spTree>'
     )
     _shape_factory_.return_value = textbox_
     return shapes, x, y, cx, cy, textbox_, expected_xml
Пример #15
0
 def add_cht_gr_frm_fixture(self, graphic_frame_, _shape_factory_):
     shapes = SlideShapes(element('p:spTree'), None)
     rId, x, y, cx, cy = 'rId42', 1, 2, 3, 4
     expected_xml = (
         '<p:spTree xmlns:p="http://schemas.openxmlformats.org/presentati'
         'onml/2006/main">\n  <p:graphicFrame xmlns:a="http://schemas.ope'
         'nxmlformats.org/drawingml/2006/main">\n    <p:nvGraphicFramePr>'
         '\n      <p:cNvPr id="1" name="Chart 0"/>\n      <p:cNvGraphicFr'
         'amePr>\n        <a:graphicFrameLocks noGrp="1"/>\n      </p:cNv'
         'GraphicFramePr>\n      <p:nvPr/>\n    </p:nvGraphicFramePr>\n  '
         '  <p:xfrm>\n      <a:off x="1" y="2"/>\n      <a:ext cx="3" cy='
         '"4"/>\n    </p:xfrm>\n    <a:graphic>\n      <a:graphicData uri'
         '="http://schemas.openxmlformats.org/drawingml/2006/chart">\n   '
         '     <c:chart xmlns:c="http://schemas.openxmlformats.org/drawin'
         'gml/2006/chart" xmlns:r="http://schemas.openxmlformats.org/offi'
         'ceDocument/2006/relationships" r:id="rId42"/>\n      </a:graphi'
         'cData>\n    </a:graphic>\n  </p:graphicFrame>\n</p:spTree>'
     )
     _shape_factory_.return_value = graphic_frame_
     return shapes, rId, x, y, cx, cy, graphic_frame_, expected_xml
Пример #16
0
 def test_group_and_image(self):
     # Test case for group objects.
     for img in [
             self.image,
             'https://gramener.com/uistatic/img/store-supply-chain.png'
     ]:
         try:
             target = pptgen.pptgen(source=self.input,
                                    only=5,
                                    group_test={
                                        'slide-title': 'Group Test',
                                        'Group 1': {
                                            'Caption': {
                                                'text': 'New caption'
                                            },
                                            'Picture': {
                                                'image': img
                                            }
                                        }
                                    })
         except requests.ConnectionError:
             raise SkipTest(
                 'No internet connection. Skipping HTTPS image test')
         eq_(len(target.slides), 1)
         grp_shape = self.get_shape(target, 'Group 1')[0]
         for shape in SlideShapes(grp_shape.element, grp_shape):
             if shape.name == 'Caption':
                 eq_(shape.text, 'New caption')
             if shape.name == 'Picture':
                 if urlparse(img).netloc:
                     r = requests.get(img)
                     with tempfile.NamedTemporaryFile(
                             delete=False) as handle:
                         handle.write(r.content)
                     with open(handle.name, 'rb') as f:
                         blob = f.read()
                     os.unlink(handle.name)
                 else:
                     with open(img, 'rb') as f:
                         blob = f.read()
                 eq_(shape.image.blob, blob)
Пример #17
0
 def autoshape_fixture(self, _shape_factory_, shape_):
     shapes = SlideShapes(element('p:spTree'), None)
     autoshape_type_id = MSO_AUTO_SHAPE_TYPE.ROUNDED_RECTANGLE
     x, y, cx, cy = 1, 2, 3, 4
     expected_xml = (
         '<p:spTree xmlns:p="http://schemas.openxmlformats.org/presentati'
         'onml/2006/main">\n  <p:sp xmlns:a="http://schemas.openxmlformat'
         's.org/drawingml/2006/main">\n    <p:nvSpPr>\n      <p:cNvPr id='
         '"1" name="Rounded Rectangle 0"/>\n      <p:cNvSpPr/>\n      <p:'
         'nvPr/>\n    </p:nvSpPr>\n    <p:spPr>\n      <a:xfrm>\n        '
         '<a:off x="1" y="2"/>\n        <a:ext cx="3" cy="4"/>\n      </a'
         ':xfrm>\n      <a:prstGeom prst="roundRect">\n        <a:avLst/>'
         '\n      </a:prstGeom>\n    </p:spPr>\n    <p:style>\n      <a:l'
         'nRef idx="1">\n        <a:schemeClr val="accent1"/>\n      </a:'
         'lnRef>\n      <a:fillRef idx="3">\n        <a:schemeClr val="ac'
         'cent1"/>\n      </a:fillRef>\n      <a:effectRef idx="2">\n    '
         '    <a:schemeClr val="accent1"/>\n      </a:effectRef>\n      <'
         'a:fontRef idx="minor">\n        <a:schemeClr val="lt1"/>\n     '
         ' </a:fontRef>\n    </p:style>\n    <p:txBody>\n      <a:bodyPr '
         'rtlCol="0" anchor="ctr"/>\n      <a:lstStyle/>\n      <a:p>\n  '
         '      <a:pPr algn="ctr"/>\n      </a:p>\n    </p:txBody>\n  </p'
         ':sp>\n</p:spTree>'
     )
     return shapes, autoshape_type_id, x, y, cx, cy, shape_, expected_xml
Пример #18
0
 def index_raises_fixture(self, shape_):
     spTree = element('p:spTree/(p:sp,p:sp,p:sp)')
     shapes = SlideShapes(spTree, None)
     shape_.element = element('p:sp')
     return shapes, shape_
Пример #19
0
 def shapes(self):
     """
     Instance of |SlideShapes| containing sequence of shape objects
     appearing on this slide.
     """
     return SlideShapes(self._element.spTree, self)
Пример #20
0
 def factory_fixture(self, SlideShapeFactory_, shape_):
     shapes = SlideShapes(None, None)
     sp = element('p:sp')
     return shapes, sp, SlideShapeFactory_, shape_