Package: domonic
𖤐 domonic 𖤐A DOM for making HTML with python 3! (and more)Installpython3-mpipinstalldomonic# python3 -m pip install domonic --upgradeCreating HTML with Python 3fromdomonic.htmlimport*print(html(body(h1('Hello, World!'))))# <html><body><h1>Hello, World!</h1></body></html>or to pretty format and insert the doctype, use an f-string:mydom=html(body(h1('Hello, World!'),a("somelink",_href="somepage.html")))print(f"{mydom}")<!DOCTYPE html><html><body><h1>Hello, World!</h1><ahref="somepage.html">somelink</a></body></html>parsing htmlBasic useage...fromdomonicimportdomonicmydom=domonic.parseString('<somehtml...')To quickly parse a webapge try the window module...fromdomonic.windowimportwindow
window.location="http://www.google.com"print(window.document.title)Also try the xpath or css selectors on command line...domonic-xhttps://google.com'//a'|uniq|sortMorehtml: Generate html with python 3 😎dom: DOM API in python 3 😲javascript: js API in python 3 😳 + (dQuery,d3)JSON : utils for loading / decorating / transformingSVG || mathml || aframe || x3d tags - generators for popular tagsterminal || cmd : call terminal commands with python3 😱See thedocs/codefor more features...or examples in therepo...NamespaceUse the tags packaage if you want a namespace. i.e.importdomonic.tagsprint(domonic.tags.h1)# orimportdomonic.tagsastagsstr(tags.div)# orimportdomonic.tagsashtmlprint(html.span)or just import what you need...fromdomonicimportdiv,span,inputasmyinput,htmlasroothtml attributesprepend attributes with an underscore ( avoids clashing with python keywords )test=label(_class='classname',_for="someinput")print(test)<labelclass="classname"for="someinput"></label>rendering DOM objectsdomonic is a pure python dom whos tree is composed of objects. i.ediv()# <domonic.html.div object at 0x106b0e6b0>cast str() on any element to render it without formatting.el=str(div())print(el)# <div></div>There's also a render method that takes 2 parameters, some domonic and an optional output file.page=div(span('Hello World'))render(f"{page}",'index.html')# notice use of f-string to pretty print the htmlThere's a few new rendering options. See DOMConfig.fromdomonic.domimportDOMConfigprint(DOMConfig.GLOBAL_AUTOESCAPE)# Default Falseprint(DOMConfig.RENDER_OPTIONAL_CLOSING_TAGS)# Default Trueprint(DOMConfig.RENDER_OPTIONAL_CLOSING_SLASH)# Defaults Trueprint(DOMConfig.SPACE_BEFORE_OPTIONAL_CLOSING_SLASH)# Default FalseDOMDOM manipulation with python.createElementto create your own elements use the DOM APIfromdomonic.domimport*site=html()el=document.createElement('myelement')site.appendChild(el)print(site)# <html><myelement></myelement></html>There's an evolving DOM API. To learn more about the webAPIclick here.And check thecode/docsto see what's currently been implemented.mysite.querySelectorAll('button')mysite.querySelectorAll("a[rel=nofollow]")mysite.querySelectorAll("a[href='#services']")mysite.querySelectorAll("a[href$='technology']")mysite.querySelectorAll('.fa-twitter')somelinks=mysite.querySelectorAll("a[href*='twitter']")forlinsomelinks:print(l.href)To use the DOM either reference your root 'html' node or import the dom modules global 'document'# access the document via the html tagmydom=html()# mydom.getElementbyID...# or by importing the document globalfromdomonic.domimportdocument# document.createElement...print(document)javascriptThere is a javascript package that mimics the js API:fromdomonic.javascriptimportMathprint(Math.random())fromdomonic.javascriptimportArraymyArr=Array(1,2,3)print(myArr.splice(1))# [2, 3]fromdomonic.javascriptimportURLurl=URL('https://somesite.com/blog/article-one#some-hash')print(url.protocol)# httpsprint(url.host)# somesite.comprint(url.pathname)# /blog/article-oneprint(url.hash)# #some-hash# Use Global class to import all the js methods from the global namespace i.e# from domonic.javascript import Global# Global.decodeURIComponent(...# Global.encodeComponent(...# Global.setInterval(...# from domonic.javascript import Date, String, Number# etc..Use setInterval and clearInterval with paramsfromdomonic.javascriptimportsetInterval,clearIntervalx=0defhi(inc):globalxx=x+incprint(x)test=setInterval(hi,1000,2)importtimetime.sleep(5)clearInterval(test)print(f"Final value of x:{x}")Or for a single delayed function call use setTimeout, clearTimeoutfromdomonic.javascriptimportsetTimeout,clearTimeouttimeoutID=setTimeout(hi,1000)You can call()on a stringvar to transform it into a Nodefromdomonic.javascriptimportStringtest=String("Hi there!")test('div',_style="font-color:red;")str(test('div',_style="font-color:red;"))# <div style="font-color:red;">Hi there!</div>a-tags inherit URL:fromdomonic.htmlimport*atag=a(_href="https://somesite.com:8000/blog/article-one#some-hash")print('href:',atag.href)# href: https://somesite.com:8000/blog/article-one#some-hashprint('protocol:',atag.protocol)# protocol: https:print('port:',atag.port)# port: 8000atag.protocol="http"atag.port=8983print(atag)# <a href="http://somesite.com:8983/blog/article-one#some-hash">For writing and using regular javascript, load from a src...script(_src="/docs/5.0/dist/js/bootstrap.bundle.min.js",_integrity="sha384-1234",_crossorigin="anonymous"),# <script src="/docs/5.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-1234" crossorigin="anonymous"></script>or do inline js by opening triple quotes...script("""let itbe = """""),StylingStyling is supported. Styles get passed to the style tag on render...mytag=div("hi",_id="test")mytag.style.backgroundColor="black"mytag.style.fontSize="12px"print(mytag)# <div id="test" style="background-color:black;font-size:12px;">hi</div>To use css use a link tag as you usually would...link(_href="styles.css",_rel="stylesheet"),or use triple quotes to open style tag...style(""".placeholder-img {-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;}"""),decoratorsuse decorators to wrap elements around function resultsfromdomonic.decoratorsimportel@el(html,True)@el(body)@el(div)deftest():return'hi!'print(test())# <html><body><div>hi!</div></body></html># returns pyml objects so call str to renderassertstr(test())=='<html><body><div>hi!</div></body></html>'It returns the tag object by default. You can pass True as a second param to the decorator to return a rendered string instead. Also accepts strings as first param i.e. custom tags.data-tagspython doesn't allow hyphens in parameter names. so use variable keyword argument syntax for custom data-tagsdiv("test",**{"_data-test":"test"})# <div data-test="test">test</div>or for example a colon...t=div(**{"_:test":"something"})str(t)# <div :test="something"></div>JSON (utils)decorate any function that returns python objects to return json insteadfromdomonic.decoratorsimportas_jsonimportdomonic.JSONasJSON@as_jsondefsomefunc():myObj={"hi":[1,2,3]}returnmyObjprint(somefunc())# {"hi":[1,2,3]}print(JSON.is_json(somefunc()))# Trueconvert json arrays into html tables...importdomonic.JSONasJSON# i.e. containting flat json array of dicts... [{"id":"01","name": "some item"},{"id":"02","name": "some other item"}]json_data=JSON.parse_file('somefile.json')mytable=JSON.tablify(json_data)print(mytable)convert json arrays into csv files...importdomonic.JSONasJSONjson_data=JSON.parse_file('somefile.json')JSON.csvify(json_data,'data.csv')convert csv files to json...importdomonic.JSONasJSONjson_data=JSON.csv2json("data.csv")print(json_data)more to come...SVGAll tags extend 'Element'. So will have DOM and magic methods available to them. See thedocs.circ=svg(circle(_cx="50",_cy="50",_r="40",_stroke="green",**{"_stroke-width":"4"},_fill="yellow"),_width="100",_height="100",)mysvg=svg()mysvg.appendChild(circ/10)print(mysvg)TweeningTween values with the tween library:fromdomonic.lerpy.easingimport*fromdomonic.lerpy.tweenimport*someObj={'x':0,'y':0,'z':0}twn=Tween(someObj,{'x':10,'y':5,'z':3},6,Linear.easeIn)twn.start()aframe / x3d3d tags can be used if you import the jsfromdomonic.htmlimport*fromdomonic.xml.aframeimport*fromdomonic.CDNimport*_scene=scene(box(_position="-1 0.5 -3",_rotation="0 45 0",_color="#4CC3D9"),sphere(_position="0 1.25 -5",_radius="1.25",_color="#EF2D5E"),cylinder(_position="1 0.75 -3",_radius="0.5",_height="1.5",_color="#FFC65D"),plane(_position="0 0 -4",_rotation="-90 0 0",_width="4",_height="4",_color="#7BC8A4"),sky(_color="#ECECEC"))_webpage=html(head(),body(script(_src=CDN_JS.AFRAME_1_2),# < NOTICE you need to import aframe to use itstr(_scene)))render(_webpage,'hello.html')dQuery (NEW)dQuery uses the º symbol (alt+0).fromdomonic.htmlimport*fromdomonic.dQueryimportºd=html(head(body(li(_class='things'),div(_id="test"))))print(º('#test'))# <div id="test">print(º('.things'))# <li class="things">mydiv=º('<div class="test2"></div>')# <domonic.dQuery.o object at 0x107d5c9a0>b=º('#test').append(mydiv)print(b)# <div id="test"><div class="test2"></div></div>Only recently started so check to see what's implemented.terminalThere is a command line package that can call bash/unix/posix and other apps on the command line:This package only works on nix systems as it effectively just passes stuff off to subprocess.fromdomonic.terminalimport*print(ls())print(ls("-al"))print(ls("../"))print(pwd())print(mkdir('somedir'))print(touch('somefile'))print(git('status'))forfileinls("-al"):print("Line : ",file)forfinls():try:print(f)print(cat(f))exceptExceptionase:passfori,linenumerate(cat('LICENSE.txt')):print(i,l)print(man("ls"))print(echo('test'))print(df())print(du())forthingindu():print(thing)print(find('.'))# print(ping('eventual.technology'))# < TODO - need to strean outputprint(cowsay('moo'))# print(wget('eventual.technology'))print(date())print(cal())or just run arbitrary commands...fromdomonic.terminalimportcommandcommand.run("echo hi")Take a look at the code in 'terminal.py' to see all the commands as there's loads. (Disclaimer: not all tested.)Windows users can use now use cmd.fromdomonic.cmdimport*print(dir())print(dir("..\\"))DOCShttps://domonic.readthedocs.io/CLIUse the command line interface to help you out.To view the online the docs:domonic-hTo see the version:domonic-vTo quickly create a domonic project for prototyping:domonic-pmyprojectTo evaluate some domonic pyml:domonic-e'html(head(),body(div()))'To use xpath on a website from the command line:domonic-xhttps://google.com'//a'To use css selectors on a website from the command line:domonic-qhttps://google.com'a'EXAMPLE PROJECTSBlueberry: A browser based file OS. Working example of how components can work.ezcron: A cron viewerbombdisposer: A basic gamehtmlx: A low dependency lightweight (DOM only) version of domonicCheckoutthe docsfor more examples i.e. generating sitemaps or using domonic with server frameworks like flask, django, sanic, fastapi and others.There's also several useage examples in the repo so pull and have a look.Join-InFeel free to contribute if you find it useful. (I'd be grateful for help on all fronts)Email me, message me directly if you like or create a discussion on here. Or join thediscord.If there are any methods you want that are missing or not complete yet or you think you can help make it better just update the code and send a pull request. I'll merge and releaese asap.In the repo there's a requirements-dev.txt which is mostly the libs used in the examples.requirements.txt are the libs used for packaging just the lib.See also the CONTRIBUTING.mdrunning examples.venv/bin/activate
pipinstall-rrequirements-dev.txtcdexamples
pythonlifecalendar.pyrun testsThere are tests used during dev. They are useful as code examples and to see what still needs doing.See Makefile to run all tests:maketest# default tests ubuntu. so will fail on window when terminal test runs. comment out locally if that's the caseor to test a single function:python-munittesttests.test_javascript.TestCase.test_javascript_array
python-munittesttests.test_dQuery.TestCase.test_addClass
python-munittesttests.test_geom.TestCase.test_vec2
python3-munittesttests.test_cmd.TestCase.test_cmd_dir# only windowsor to test a whole modulepython-munittesttests.test_html
python-munittesttests.test_CDNto see coveragecoveragerun-munittestdiscovertests/
coveragereportor...pipinstallpytest
pytesttestsDisclaimerThere's several more widely supported libraries doing HTML generation, DOM reading/manipulation, terminal wrappers etc. Maybe use one of those for production due to strictness and support.This is more of a fast prototyping library.