Generate HTML using python 3 with an API that follows the DOM standard specfication.

domonic: generate html with python 3!
domonic
Generate html with python 3! (and much more)

PyPI version Downloads Python version Build status Python package

Contains several evolving packages:

html : Generate html with python 3 😎
dom : DOM API in python 3 😲
javascript : js API in python 3 😳
dQuery - utils for querying domonic. (alt + 0 for the º symbol)
• terminal || cmd : call terminal commands with python3 😱 (see at the end)
• JSON : utils for loading / decorating / transforming
• SVG : Generate svg using python (untested)
• aframe || x3d tags : auto generate 3d worlds with aframe. (see examples folder)

See the docs/code for more features... https://domonic.readthedocs.io/

or examples in the repo...

(small footprint. with only a few common lightweight dependencies)

HTML Templating with Python 3

from domonic.html import *
print(html(body(h1('Hello, World!'))))
<html><body><h1>Hello, World!h1>body>html>

or to format it and insert the doctype use an f-string:

mydom = html(body(h1('Hello, World!')))
print(f"{mydom}")
>
<html>
    <body>
        <h1>Hello, World!h1>
    body>
html>

install

python3 -m pip install domonic

or if you had it before upgrade:

python3 -m pip install domonic --upgrade

attributes

prepend attributes with an underscore ( avoids clashing with python keywords )

test = label(_class='classname', _for="someinput")
print(test)
">
<label class="classname" for="someinput">label>

rendering

cast str() on any element to render it without formatting.

el_string = str(div())
print(el_string)

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 html

Now try building your own static site generator!

decorators

use decorators to wrap elements around function results

from domonic.decorators import el

@el(html, True)
@el(body)
@el(div)
def test():
    return 'hi!'

print(test())
# 
   
hi!
# returns pyml objects so call str to render assert str(test()) == '
hi!
'

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-tags

python doesn't allow hyphens in parameter names. so use variable keyword argument syntax for custom data-tags

div("test", **{"_data-test":"test"} )

or for example a colon...

t = div( **{"_:test":"something"} )
str(t)

DOM

DOM manipulation with python.

createElement

to create your own elements use the DOM API

from domonic.dom import *

site = html()
el = document.createElement('myelement')
site.appendChild(el)
print(site)

There's an evolving DOM API. To learn more about the webAPI go here.

https://developer.mozilla.org/en-US/docs/Web/API

And check the code/docs to 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']")
for l in somelinks:
    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 tag
mydom = html()
# mydom.getElementbyID...

# or by importing the document global
from domonic.dom import document
# document.createElement...
print(document)

javascript

There is a javascript package that mimics the js API:

from domonic.javascript import Math
print(Math.random())

from domonic.javascript import Array
myArr=Array(1,2,3)
print(myArr.splice(1))

from domonic.javascript import URL
url = URL('https://somesite.com/blog/article-one#some-hash')
print(url.protocol)
print(url.host)
print(url.pathname)
print(url.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 params

from domonic.javascript import setInterval, clearInterval

x=0

def hi(inc):
    global x
    x = x+inc
    print(x)

test = setInterval(hi, 1000, 2)
import time
time.sleep(5)
clearInterval(test)
print(f"Final value of x:{x}")

Or for a single delayed function call use setTimeout, clearTimeout

from domonic.javascript import setTimeout, clearTimeout

timeoutID = setTimeout(hi, 1000)

call () on a stringvar to transform it into a Node

>> test('div', _style="font-color:red;") >>> str(test('div', _style="font-color:red;")) ">
    >>> from domonic.javascript import String

	>>> test = String("Hi there!")
	>>> test('div', _style="font-color:red;")
	>>> str(test('div', _style="font-color:red;"))

passing it the tag and attributes...

a-tags inherit URL:

from domonic.html import *

atag = a(_href="https://somesite.com:8000/blog/article-one#some-hash")
print('href:', atag.href)
print('protocol:', atag.protocol)
print('port:', atag.port)

atag.protocol = "http"
atag.port = 8983
print(atag)

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"),

or do inline js by opening triple quotes...

script("""
let itbe = ""
"""),

Styling

Styling is supported. Styles get passed to the style tag on render...

hi
">
mytag = div("hi", _id="test")
mytag.style.backgroundColor = "black"
mytag.style.fontSize = "12px"
print(mytag)
# 
  
hi

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;
}
"""),

JSON (utils)

decorate any function that returns python objects to return json instead

from domonic.JSON import *

@return_json
def somefunc():
    myObj = {"hi":[1,2,3]}
    return myObj

print( somefunc() )
print( is_json(somefunc()) )

convert json arrays into html tables...

from domonic.JSON import *

# 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...

from domonic.JSON import *

json_data = JSON.parse_file('somefile.json')
JSON.csvify(json_data, 'data.csv')

convert csv files to json...

from domonic.JSON import *

json_data =JSON.csv2json("data.csv")
print(json_data)

more to come...

SVG

All tags extend 'Node' and 'tag'. So will have DOM and magic methods available to them. see the docs.

        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)

Tweening

Tween values with the tween library:

from domonic.lerpy.easing import *
from domonic.lerpy.tween import *

someObj = {'x':0,'y':0,'z':0}
twn = Tween( someObj, { 'x':10, 'y':5, 'z':3 }, 6, Linear.easeIn )
twn.start()

aframe / x3d

3d tags can be used if you import the js

from domonic.html import *
from domonic.xml.aframe import *
from domonic.CDN import *

_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 it
    str(_scene)
    )
)

render( _webpage, 'hello.html' )

dQuery (NEW)

dQuery uses the º symbol (alt+0).

') print( a ) b = º('#test').append(a) print(b) ">
    d = html(head(body(li(_class='things'), div(_id="test"))))
    
    º(d) # you need to init a dom first. i.e. a html element

    # now you can use it
    print( º('#test') )
    print( º('.things') )
    a = º('
  
'
) print( a ) b = º('#test').append(a) print(b)

Only recently started so check to see what's implemented.

terminal

There 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.

from domonic.terminal import *

print(ls())
print(ls("-al"))
print(ls("../"))
print(pwd())
print(mkdir('somedir'))
print(touch('somefile'))
print(git('status'))

for file in ls( "-al" ):
    print("Line : ", file)

for f in ls():
    try:
        print(f)
        print(cat(f))
    except Exception as e:
        pass

for i, l in enumerate(cat('LICENSE.txt')):
    print(i,l)

print(man("ls"))
print(echo('test'))
print(df())
print(du())

for thing in du():
    print(thing)

print(find('.'))
# print(ping('eventual.technology'))# < TODO - need to strean output
print(cowsay('moo'))
print(wget('eventual.technology'))
print(date())
print(cal())

or just run arbitrary commands...

from domonic.terminal import command
command.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.

from domonic.cmd import *
print(dir())
print(dir("..\\")) 

parsing

domonic can work with other Treebuilders

There's a builtin ext to tap into html5lib. And also fork of the c++ htmlparser (see parsing ticket)

To use the pure python htm5lib with domonic you need to install it

pip install html5lib

Then use the domonic treebuilder instead of any of the html5lib treebuilders.

import requests
import html5lib
from domonic.ext.html5lib_ import getTreeBuilder


r = requests.get("https://google.com")
parser = html5lib.HTMLParser(tree=getTreeBuilder())
page = parser.parse(r.content.decode("utf-8"))

# print the page with formatting
# print(f'{page}')

'''
links = page.getElementsByTagName('a')
for l in links:
    try:
        print(l.href)
    except Exception as e:
        # no href on this tag
        pass
'''

# turn the downloaded site into .pyml ;)
print(page.__pyml__())

For a quick parse try the window module...

from domonic.window import *
window.location = "http://www.google.com"
print(window.document.title)

DOCS

https://domonic.readthedocs.io/

notes on templating

while you can create a div with content like :

div("some content")

python doesn't allow named params before unamed ones. So you can't do this:

div(_class="container", p("Some content") )

or it will complain the params are in the wrong order. You have to instead put content before attributes:

div( p("Some content"), _class="container")

which is annoying when a div gets long.

You can get around this by using 'html' which is available on every Element:

div( _class="container" ).html("Some content")

This is NOT like jQuery html func that returns just the inner content. use innerHTML for that.

It is used specifically for rendering.

Common Errors

If templates are typed incorrectly they will not work.

There's a small learning curve getting .pyml templates correct. Usually (1) a missing comma between tags, (2) an underscore missing on an attribute or (3) params in the wrong order. Use this reference when starting out as a reminder when you get an error.

Here are the 4 solutions to those common errors when creating large templates... ( i.e. see bootstrap5 examples in test_domonic.py )

IndexError: list index out of range - You most likely didn't put a underscore on an attribute.

SyntaxError: invalid syntax - You are Missing a comma between attributes

SyntaxError: positional argument follows keyword argument - You have to pass attributes LAST. and strings and objects first. see notes on templating above

TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'dict' - You are Missing a comma between attributes. before the **{}

CLI

Use the command line interface to help you out.

To launch the docs for a quick reference to the APIs use:

python3 -m domonic -h

EXAMPLE PROJECTS

A browser based file browser. Working example of how components can work: Blueberry

A cron viewer: ezcron

A basic game: https://github.com/byteface/bombdisposer/

checkout the docs for examples on how to easily make sitemaps with python. or for example how to use domonic with flask, django, sanic and other server frameworks.

docs: https://domonic.readthedocs.io/

There's also several useage examples in the repo so pull and have a look.

Join-In

Feel 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 the discord.

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.

running examples

. venv/bin/activate
pip install -r requirements-dev.txt
cd examples
python lifecalendar.py

run tests

There are tests used during dev. They are useful as code examples and to see what still needs doing.

See Makefile to run all tests:

make test  # default tests ubuntu. so will fail on window when terminal test runs. comment out locally if that's the case

or to test a single function:

python -m unittest tests.test_javascript.TestCase.test_javascript_array
python -m unittest tests.test_dQuery.TestCase.test_addClass
python -m unittest tests.test_geom.TestCase.test_vec2

python3 -m unittest tests.test_cmd.TestCase.test_cmd_dir  # only windows

or to test a whole module

python -m unittest tests.test_html
python -m unittest tests.test_CDN

to see coverage

coverage run -m unittest discover tests/
coverage report

rebuild docs

See Makefile:

. venv/bin/activate
cd docs
make html

Disclaimer

There'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.

Comments
  • requirements upper bounds

    requirements upper bounds

    I've been enjoying your library, it has some of the better implementations in an easy to implement way (ex. _methods)

    One thing I've noticed is that you have specified that your requirements are all static (requests/urllib for example).

    Because your implementation of those requirements are not really integrated into your library, would it not make more sense to create a major version upper limit?

    my rec:

    requests~=2.26
    urllib3~=1.26
    

    Im of course ready to be corrected on this.

  • Add slots for tag class

    Add slots for tag class

    It looks like issue #21 mentions that you wanted to use __slots__ in this project. I'm not familiar with the structure of the project or where all the classes are defined, so this PR only adds __slots__ for the one class that had the todo comment for it.

    All of the rest of the classes should be just as simple. You just have to list out all of the expected instance attributes for each class. If a class is simple and just assigns all of it's attributes normally with self.<name> = ... in it's __init__ or elsewhere, then you can just search for self.\w+ = to locate names easily.

    Using __slots__ instead of the default __dict__ for attributes is pretty straightforward unless you have classes where instance attributes are dynamically set (not just appear to be set with a __getattr__ or __getattribute__ that intercepts attribute access).

    I'm not sure this change warrants any extra tests since the existing test suite covers all of the attribute assignments in the tag class

    $ coverage run -m unittest discover tests
    <lots of output, enough lines with just hi to fill up my entire terminal history>
    ...
    ----------------------------------------------------------------------
    Ran 259 tests in 19.748s
    
    OK
    $ coverage report -m | grep html
    Name                                                                                Stmts   Miss  Cover   Missing
    -----------------------------------------------------------------------------------------------------------------
    domonic/html.py                                                                       294     45    85%   65-66, 72-78, 103-104, 121-122, 130-131, 155-158, 169-172, 178-181, 187-190, 194-196, 225-227, 265, 272, 322, 487, 490, 493, 512, 515
    tests/test_html.py                                                                     77     25    68%   47-56, 60-91, 95-133, 137-358, 362-532, 537-805, 845
    
  • feature request: boolean attributes

    feature request: boolean attributes

    In HTML5, there are a number of boolean attributes, e.g. async, checked and disabled. It would be nice if these could be recognized and simply output as their short form. Currently, as a workaround, you can give them an empty string or their own name as value, e.g.

    _script(_src="foo.js", _async="async")
    

    gives

    <script src="foo.js" async="async"/>
    

    but would be nice if we could have

    <script src="foo.js" async/>
    
  • Exception: unable to update parent 'Comment' object has no attribute 'args'

    Exception: unable to update parent 'Comment' object has no attribute 'args'

    When instantiating a domonic.html.comment (or a dom.Comment, same same) object in a Sanic response, I'm getting the exception unable to update parent 'Comment' object has no attribute 'args' (from dom.py line 193) seven to eleven times in my log. I can't reproduce it in a REPL session. I also can't figure out why I get any particular number of exceptions, but they are the same number from page load to page load.

    @app.route("/test_comment")
    async def test_comment(req):
        return response.html(f"{html(head(), body(comment('foo')))}")
    
    [2021-10-11 12:39:04 +0200] [9197] [INFO] Starting worker [9197]
    unable to update parent 'Comment' object has no attribute 'args'
    unable to update parent 'Comment' object has no attribute 'args'
    unable to update parent 'Comment' object has no attribute 'args'
    unable to update parent 'Comment' object has no attribute 'args'
    unable to update parent 'Comment' object has no attribute 'args'
    unable to update parent 'Comment' object has no attribute 'args'
    unable to update parent 'Comment' object has no attribute 'args'
    unable to update parent 'Comment' object has no attribute 'args'
    unable to update parent 'Comment' object has no attribute 'args'
    unable to update parent 'Comment' object has no attribute 'args'
    unable to update parent 'Comment' object has no attribute 'args'
    [2021-10-11 12:39:15 +0200] [9197] [DEBUG] KeepAlive Timeout. Closing connection.
    
  • f-string response includes closing tags for void elements

    f-string response includes closing tags for void elements

    When converting the html object with str and returning it as a response, closing tags for void elements like meta are correctly omitted.

    When converting it in an f-string and returning it as a response, closing tags are erroneously included. Example of a simple Sanic route:

    @app.route("/404.html")
    async def not_found(req: request.Request) -> response.HTTPResponse:
        four_oh_four = html(
            head(
                meta(_charset="utf-8")
            ),
            body(
                h1("Page Not Found"),
                p("Sorry, but the page you were trying to view does not exist."),
            ),
            _lang="en"
        )
        return response.html(f"{four_oh_four}")
    

    which generates the following HTML:

    <!DOCTYPE html>
    <html lang="en">
    	<head>
    		<meta charset="utf-8">
    		</meta>
    	</head>
    	<body>
    		<h1>Page Not Found</h1>
    		<p>Sorry, but the page you were trying to view does not exist.</p>
    	</body>
    </html>
    

    Note the errant </meta> on line 5. For comparison, the output with return response.html(str(four_oh_four)) is

    <html lang="en"><head><meta charset="utf-8" /></head><body><h1>Page Not Found</h1><p>Sorry, but the page you were trying to view does not exist.</p></body></html>
    

    but then I don't get the doctype element.

  • timeouts -

    timeouts -

    currently missing decent setTimout and clearTimeout methods.

    I'd like these to work 2 ways. async and not. so a flag needs to be added to make async=True. currently i doubled up and 2 new ones to 'Global' so the old implementations could be left alone. (not that they worked. its just a sleep.)

    ideally somehow utilise the SetInterval work that was done in the past. I had avoided ayncio due to api changes between python versions. I'd get setInterval to work in one version but it would fail in another so went to 'threads' for the Job class. howeer this is only async atm. should it block during exec?

    for now I can't see me getting to this for a while. so making a ticket not to use setTimeout and clearTimeout as they aren't done. But will be once I get time and can think about how I resolve these issues.

  • d3 - polygon

    d3 - polygon

    porting d3 polygon across:

    reference... https://github.com/d3/d3-polygon

    @FrackOverflow - if you want you can assign this to yourself. free free to make tickets also if you see anything else you want to take on.

  • Implement Global.setTimeout

    Implement Global.setTimeout

    This should be a working implementation for setTimeout and clearTimeout as mentioned in #11.

    I'm not familiar enough with the project to know how to integrate it with SetInterval mentioned in the issue, but threading.Timer is a python builtin that provides pretty much exactly the same functionality as setTimeout and clearTimeout does in javascript.

    I've also added two tests for this. One that checks that the callback is actually called, and the other that checks that a callback can be canceled properly.

  • queryselectors need updating

    queryselectors need updating

    we have a new replacement method that can do complex css queries but for some reason it doesn't do simple ones i.e. single tags. so they needed to be merged however an issue arose as the new one used getElementByID which was using querySelctor. fuck. So I losts a ton of fucking time and broke a branch (that had my an attempt at dict setters for attribs in it). anyways. will have another attempts at merging these together to work properly again another time. Or unless someone really really complains.

  • Bump ujson from 4.0.2 to 5.1.0

    Bump ujson from 4.0.2 to 5.1.0

    Bumps ujson from 4.0.2 to 5.1.0.

    Release notes

    Sourced from ujson's releases.

    5.1.0

    Changed

    5.0.0

    Added

    Removed

    Fixed

    4.3.0

    Added

    4.2.0

    Added

    Changed

    4.1.0

    Added

    Changed

    ... (truncated)

    Commits
    • 682c660 Merge pull request #493 from bwoodsend/strip-binaries
    • c1d5b6d [pre-commit.ci] auto fixes from pre-commit.com hooks
    • b9275f7 Strip debugging symbols from Linux binaries.
    • e3ccc5a Merge pull request #492 from hugovk/deploy-twine
    • 243d49b Install Twine to upload to PyPI
    • 269621b Merge pull request #490 from hugovk/rm-3.6
    • cccde3f Drop support for EOL Python 3.6
    • b55049f Merge pull request #491 from bwoodsend/switch-to-ci-build-wheels
    • 04286a6 Drop wheels for Python 3.6. (#490)
    • ab32d48 CI/CD: Ensure that sdists are uploaded last.
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

  • Bump sanic from 22.3.2 to 22.6.1

    Bump sanic from 22.3.2 to 22.6.1

    Bumps sanic from 22.3.2 to 22.6.1.

    Release notes

    Sourced from sanic's releases.

    Version 22.6.1

    Resolves #2477 and #2478 See also #2495 and https://github.com/sanic-org/sanic/security/advisories/GHSA-8cw9-5hmv-77w6

    Full Changelog: https://github.com/sanic-org/sanic/compare/v22.6.0...v22.6.1

    Version 22.6.0

    Features

    • #2378 Introduce HTTP/3 and autogeneration of TLS certificates in DEBUG mode
      • 👶 EARLY RELEASE FEATURE: Serving Sanic over HTTP/3 is an early release feature. It does not yet fully cover the HTTP/3 spec, but instead aims for feature parity with Sanic's existing HTTP/1.1 server. Websockets, WebTransport, push responses are examples of some features not yet implemented.
      • 📦 EXTRA REQUIREMENT: Not all HTTP clients are capable of interfacing with HTTP/3 servers. You may need to install a HTTP/3 capable client.
      • 📦 EXTRA REQUIREMENT: In order to use TLS autogeneration, you must install either mkcert or trustme.
    • #2416 Add message to task.cancel
    • #2420 Add exception aliases for more consistent naming with standard HTTP response types (BadRequest, MethodNotAllowed, RangeNotSatisfiable)
    • #2432 Expose ASGI scope as a property on the Request object
    • #2438 Easier access to websocket class for annotation: from sanic import Websocket
    • #2439 New API for reading form values with options: Request.get_form
    • #2445 Add custom loads function
    • #2447, #2486 Improved API to support setting cache control headers
    • #2453 Move verbosity filtering to logger
    • #2475 Expose getter for current request using Request.get_current()

    Bugfixes

    • #2448 Fix to allow running with pythonw.exe or places where there is no sys.stdout
    • #2451 Trigger http.lifecycle.request signal in ASGI mode
    • #2455 Resolve typing of stacked route definitions
    • #2463 Properly catch websocket CancelledError in websocket handler in Python 3.7

    Deprecations and Removals

    • #2487 v22.6 deprecations and changes
      1. Optional application registry
      2. Execution of custom handlers after some part of response was sent
      3. Configuring fallback handlers on the ErrorHandler
      4. Custom LOGO setting
      5. sanic.response.stream
      6. AsyncioServer.init

    Developer infrastructure

    • #2449 Clean up black and isort config
    • #2479 Fix some flappy tests

    Improved Documentation

    • #2461 Update example to match current application naming standards
    • #2466 Better type annotation for Extend
    • #2485 Improved help messages in CLI

    New Contributors

    ... (truncated)

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

  • Bump ujson from 5.2.0 to 5.4.0

    Bump ujson from 5.2.0 to 5.4.0

    Bumps ujson from 5.2.0 to 5.4.0.

    Release notes

    Sourced from ujson's releases.

    5.4.0

    Added

    Fixed

    5.3.0

    Added

    Changed

    Fixed

    Commits
    • 9c20de0 Merge pull request from GHSA-fm67-cv37-96ff
    • b21da40 Fix double free on string decoding if realloc fails
    • 67ec071 Merge pull request #555 from JustAnotherArchivist/fix-decode-surrogates-2
    • bc7bdff Replace wchar_t string decoding implementation with a uint32_t-based one
    • cc70119 Merge pull request #548 from JustAnotherArchivist/arbitrary-ints
    • 4b5cccc Merge pull request #553 from bwoodsend/pypy-ci
    • abe26fc Merge pull request #551 from bwoodsend/bye-bye-travis
    • 3efb5cc Delete old TravisCI workflow and references.
    • 404de1a xfail test_decode_surrogate_characters() on Windows PyPy.
    • f7e66dc Switch to musl docker base images.
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

  • import domonic.html

    import domonic.html

    Hi, I'm trying to get a handle on domonic.html module via import domonic.html or from domonic import html as opposed to from domonic.html import * (to be able to do html.span("hello") instead of span("hello")). However, domonic.html is ambiguous with the value "html" that gets imported in domonic/__init__.py . I think the star import there is responsible but I'm no expert. Given that import, all of html's exports are accessible by dom; i.e. you can write dom.span("html") which would seem to accomplish my needs but I don't think was intended in the design of these modules; that is I can confusingly write import domonic as html when I want import domonic.html.

  • d3 - Tile

    d3 - Tile

    Tile was unfinished but ended up in the repo.

    @FrackOverflow If you enjoyed fixing my polygon d3 has a tons of fun stuff. i.e d3 - heirachy

    and some real beauties if you dig around. i.e. https://github.com/d3/d3-plugins/tree/master/superformula

    FYI my reason for porting d3 was to create 'real world' test cases for the use of Javascript.py class in domonic.

    Just so you know it was mainly done to help me evolved the Javascript class. It makes it useful for quickly porting stuff. But ideally we'd do it all in proper python as swap out the js-like useage. Just incase you wonder why the code in the d3 section in strange.

  • MutationObserver

    MutationObserver

    While answering a question on stackoverflow today i realised that domonics mutationobserver is still commented out as TODO but also querySelectorAll is supposed to be 'not live'...

    https://stackoverflow.com/questions/69975232/track-changes-within-dom-element-with-mutationobserver-python/69987634?noredirect=1#comment123721040_69987634

    I have a feeling ours will be live. so should be returning node copies instead? It may not be and passing by value so I'll have to check.

    If anyone is keen to dev this bit up then take it away. Otherwise will leave as a ticket for now til i get time.

Dominate is a Python library for creating and manipulating HTML documents using an elegant DOM API

Dominate Dominate is a Python library for creating and manipulating HTML documents using an elegant DOM API. It allows you to write HTML pages in pure

Dec 5, 2022
A HTML-code compiler-thing that lets you reuse HTML code.

RHTML RHTML stands for Reusable-Hyper-Text-Markup-Language, and is pronounced "Rech-tee-em-el" despite how its abbreviation is. As the name stands, RH

Nov 15, 2021
That project takes as input special TXT File, divides its content into lsit of HTML objects and then creates HTML file from them.

That project takes as input special TXT File, divides its content into lsit of HTML objects and then creates HTML file from them.

Jan 10, 2022
A library for converting HTML into PDFs using ReportLab

XHTML2PDF The current release of xhtml2pdf is xhtml2pdf 0.2.5. Release Notes can be found here: Release Notes As with all open-source software, its us

Nov 25, 2022
Standards-compliant library for parsing and serializing HTML documents and fragments in Python

html5lib html5lib is a pure-python library for parsing HTML. It is designed to conform to the WHATWG HTML specification, as is implemented by all majo

Nov 30, 2022
A python HTML builder library.

PyML A python HTML builder library. Goals Fully functional html builder similar to the javascript node manipulation. Implement an html parser that ret

Jul 4, 2022
Bleach is an allowed-list-based HTML sanitizing library that escapes or strips markup and attributes

Bleach Bleach is an allowed-list-based HTML sanitizing library that escapes or strips markup and attributes. Bleach can also linkify text safely, appl

Dec 1, 2022
Safely add untrusted strings to HTML/XML markup.

MarkupSafe MarkupSafe implements a text object that escapes characters so it is safe to use in HTML and XML. Characters that have special meanings are

Nov 25, 2022
Pythonic HTML Parsing for Humans™
Pythonic HTML Parsing for Humans™

Requests-HTML: HTML Parsing for Humans™ This library intends to make parsing HTML (e.g. scraping the web) as simple and intuitive as possible. When us

Nov 29, 2022
Modded MD conversion to HTML

MDPortal A module to convert a md-eqsue lang to html Basically I ruined md in an attempt to convert it to html Overview Here is a demo file from parse

Nov 27, 2021
A jquery-like library for python

pyquery: a jquery-like library for python pyquery allows you to make jquery queries on xml documents. The API is as much as possible the similar to jq

Dec 5, 2022
Converts XML to Python objects

untangle Documentation Converts XML to a Python object. Siblings with similar names are grouped into a list. Children can be accessed with parent.chil

Nov 30, 2022
Python module that makes working with XML feel like you are working with JSON

xmltodict xmltodict is a Python module that makes working with XML feel like you are working with JSON, as in this "spec": >>> print(json.dumps(xmltod

Dec 2, 2022
The lxml XML toolkit for Python

What is lxml? lxml is the most feature-rich and easy-to-use library for processing XML and HTML in the Python language. It's also very fast and memory

Dec 2, 2022
Python binding to Modest engine (fast HTML5 parser with CSS selectors).

A fast HTML5 parser with CSS selectors using Modest engine. Installation From PyPI using pip: pip install selectolax Development version from github:

Dec 1, 2022
Lektor-html-pretify - Lektor plugin to pretify the HTML DOM using Beautiful Soup

html-pretify Lektor plugin to pretify the HTML DOM using Beautiful Soup. How doe

Nov 8, 2022
Dominate is a Python library for creating and manipulating HTML documents using an elegant DOM API

Dominate Dominate is a Python library for creating and manipulating HTML documents using an elegant DOM API. It allows you to write HTML pages in pure

Dec 5, 2022
Fully Automated YouTube Channel ▶️with Added Extra Features.

Fully Automated Youtube Channel ▒█▀▀█ █▀▀█ ▀▀█▀▀ ▀▀█▀▀ █░░█ █▀▀▄ █▀▀ █▀▀█ ▒█▀▀▄ █░░█ ░░█░░ ░▒█░░ █░░█ █▀▀▄ █▀▀ █▄▄▀ ▒█▄▄█ ▀▀▀▀ ░░▀░░ ░▒█░░ ░▀▀▀ ▀▀▀░

Dec 1, 2022
A fast JSON parser/generator for C++ with both SAX/DOM style API
A fast JSON parser/generator for C++ with both SAX/DOM style API

A fast JSON parser/generator for C++ with both SAX/DOM style API Tencent is pleased to support the open source community by making RapidJSON available

Nov 29, 2022
A Python library that tees the standard output & standard error from the current process to files on disk, while preserving terminal semantics

A Python library that tees the standard output & standard error from the current process to files on disk, while preserving terminal semantics (so breakpoint(), etc work as normal)

Nov 30, 2022