Package: pydivkit
PyDIVKit examplesThis library is designed to work withDivKitwith python.Features:Declarative and imperative DivKit blocks definitionNative Type-hints supportComplete object-oriented APIIDE type checks and suggestionsObject constructionThe main idea is to provide a tool for creating blocks using Python objects.importjsonimportpydivkitasdkcontainer=dk.DivContainer(items=[dk.DivGallery(items=[dk.DivText(text="Hello from pydivkit")])])print(json.dumps(container.dict(),indent=1))# {#  "type": "container",#  "items": [#   {#    "type": "gallery",#    "items": [#     {#      "type": "text",#      "text": "Hello from pydivkit"#     }#    ]#   }#  ]# }Slider exampleFollowing code is a rewritten slider example using pydivkit.importpydivkitasdkslider=dk.DivData(log_id="sample_card",states=[dk.DivDataState(state_id=0,div=dk.DivSlider(width=dk.DivMatchParentSize(),max_value=10,min_value=1,thumb_style=dk.DivShapeDrawable(color="#00b300",stroke=dk.DivStroke(color="#ffffff",width=3,),shape=dk.DivRoundedRectangleShape(item_width=dk.DivFixedSize(value=32),item_height=dk.DivFixedSize(value=32),corner_radius=dk.DivFixedSize(value=100)),),track_active_style=dk.DivShapeDrawable(color="#00b300",shape=dk.DivRoundedRectangleShape(item_height=dk.DivFixedSize(value=6))),track_inactive_style=dk.DivShapeDrawable(color="#20000000",shape=dk.DivRoundedRectangleShape(item_height=dk.DivFixedSize(value=6)))))])This example might be serialised like this:importjsonprint(json.dumps(slider.dict(),indent=1))# {#  "log_id": "sample_card",#  "states": [#   {#    "div": {#     "type": "slider",#     "max_value": 10,#     "min_value": 1,#     "thumb_style": {#      "type": "shape_drawable",#      "color": "#00b300",#      "shape": {#       "type": "rounded_rectangle",#       "corner_radius": {#        "type": "fixed",#        "value": 100#       },#       "item_height": {#        "type": "fixed",#        "value": 32#       },#       "item_width": {#        "type": "fixed",#        "value": 32#       }#      },#      "stroke": {#       "color": "#ffffff",#       "width": 3#      }#     },#     "track_active_style": {#      "type": "shape_drawable",#      "color": "#00b300",#      "shape": {#       "type": "rounded_rectangle",#       "item_height": {#        "type": "fixed",#        "value": 6#       }#      }#     },#     "track_inactive_style": {#      "type": "shape_drawable",#      "color": "#20000000",#      "shape": {#       "type": "rounded_rectangle",#       "item_height": {#        "type": "fixed",#        "value": 6#       }#      }#     },#     "width": {#      "type": "match_parent"#     }#    },#    "state_id": 0#   }#  ]# }Templating and DRYOf course, manually building blocks from your code every time is boring.
So, the first idea is to move the initialization of DivKit objects
into functions.# Naive DRY example which strictly non-recommendedimportpydivkitasdkdefget_size(value:int=32)->dk.DivFixedSize:returndk.DivFixedSize(value=value)defget_shape()->dk.DivShape:returndk.DivShape(item_width=get_size(),item_height=get_size(),corner_radius=get_size(100))slider_shape=get_shape()slider=dk.DivData(log_id="sample_card",states=[dk.DivDataState(# other argumentsdiv=dk.DivSlider(thumb_style=dk.DivShapeDrawable(shape=slider_shape,# other arguments),# other arguments))])Looks a little better, but this approach doesn't scale well. To simplify layout
and save traffic, DivKit has templates. This is a way to layout similar elements
without having to declare the complete json, but just declare a template and use
this many times in similar items.PyDivKit supports defining templates through the inheritance.Let's define an example card:importjsonimportpydivkitasdkclassCategoriesItem(dk.DivContainer):"""Class inherited from dk.DivContainer will have a template"""# Special object for mark this fields a DivKit field in templateicon_url:str=dk.Field()text:str=dk.Field()# Set defaults layout for in the templatewidth=dk.DivWrapContentSize()background=[dk.DivSolidBackground(color="#f0f0f0")]content_alignment_vertical=dk.DivAlignmentVertical.CENTERorientation=dk.DivContainerOrientation.HORIZONTALpaddings=dk.DivEdgeInsets(left=12,right=12,top=10,bottom=10)border=dk.DivBorder(corner_radius=12)items=[dk.DivImage(width=dk.DivFixedSize(value=20),height=dk.DivFixedSize(value=20),margins=dk.DivEdgeInsets(right=6),# Special object Ref it's a reference for Field propertyimage_url=dk.Ref(icon_url),),dk.DivText(width=dk.DivWrapContentSize(),max_lines=1,# Special object Ref it's a reference for Field propertytext=dk.Ref(text),),]BASE_URL="https://leonardo.edadeal.io/dyn/re/segments/level1/96"# So after class definition you might use all the `Field` marked property# names as an argument.gallery=dk.DivGallery(items=[CategoriesItem(text="Food",icon_url=f"{BASE_URL}/food.png",),CategoriesItem(text="Alcohol",icon_url=f"{BASE_URL}/alcohol.png",),CategoriesItem(text="Household",icon_url=f"{BASE_URL}/household.png",),])print(json.dumps(dk.make_div(gallery),indent=1,ensure_ascii=False))# {#  "templates": {#   "__main__.CategoriesItem": {#    "type": "container",#    "background": [#     {#      "type": "solid",#      "color": "#f0f0f0"#     }#    ],#    "border": {#     "corner_radius": 12#    },#    "content_alignment_vertical": "center",#    "items": [#     {#      "type": "image",#      "height": {#       "type": "fixed",#       "value": 20#      },#      "$image_url": "icon_url",#      "margins": {#       "right": 6#      },#      "width": {#       "type": "fixed",#       "value": 20#      }#     },#     {#      "type": "text",#      "max_lines": 1,#      "$text": "text",#      "width": {#       "type": "wrap_content"#      }#     }#    ],#    "orientation": "horizontal",#    "paddings": {#     "bottom": 10,#     "left": 12,#     "right": 12,#     "top": 10#    },#    "width": {#     "type": "wrap_content"#    }#   }#  },#  "card": {#   "log_id": "card",#   "states": [#    {#     "div": {#      "type": "gallery",#      "items": [#       {#        "type": "__main__.CategoriesItem",#        "icon_url": "https://leonardo.edadeal.io/dyn/re/segments/level1/96/food.png",#        "text": "Food"#       },#       {#        "type": "__main__.CategoriesItem",#        "icon_url": "https://leonardo.edadeal.io/dyn/re/segments/level1/96/alcohol.png",#        "text": "Alcohol"#       },#       {#        "type": "__main__.CategoriesItem",#        "icon_url": "https://leonardo.edadeal.io/dyn/re/segments/level1/96/household.png",#        "text": "Household"#       }#      ]#     },#     "state_id": 0#    }#   ]#  }# }Template namesBy default, templates are collecting by the metaclass into shared storage when
the class is declaring at import time, and have the
format{module_name}.{class_name}.The following example, sure will not occur in the wild, shows a warning if
suddenly the names of the classes, and hence the templates, conflict.importpydivkitasdkclassMyTemplate(dk.DivContainer):width=dk.DivWrapContentSize()classMyTemplate(dk.DivContainer):pass# RuntimeWarning: Template 'test.MyTemplate' already defined in# <class 'test.MyTemplate'> and will be replaced to <class 'test.MyTemplate'>Also, if you do not want to show the structure of your project to the outside,
or for some reason you need to make the example above clean, you can rename the
template by declaring a special attribute__template_name__importpydivkitasdkclassMyTemplate(dk.DivContainer):width=dk.DivWrapContentSize()print(MyTemplate.template_name)# >>> test.MyTemplateclassMyTemplate(dk.DivContainer):__template_name__="MyTemplate2"print(MyTemplate.template_name)# >>> MyTemplate2