├── .github └── workflows │ ├── on_commit_do_all_unittests.yml │ ├── on_commit_do_deploy_mkdocs.yml │ ├── on_tag_do_release_and_deploy_pypi.yml │ ├── selenium.yaml │ ├── test_platforms.yml │ └── update_version.py ├── .gitignore ├── .idx ├── dev.nix └── icon.png ├── .vscode ├── settings.json └── tasks.json ├── LICENSE ├── README.md ├── _pyscript_dev.html ├── brython ├── README.md ├── bryted.html ├── example1.html ├── example2.html └── htag.txt ├── docs ├── README.md ├── calling_an_event.md ├── concepts.md ├── creating_a_tag.md ├── hrenderer.md ├── htag.png ├── htag.svg ├── index.md ├── js_bidirectionnal.md ├── query_params.md ├── runner.md ├── runners.md ├── tag_update.md ├── tuto_create_an_input_component.md └── tutorial.md ├── examples ├── 7guis │ ├── README.md │ ├── gui1.py │ ├── gui2.py │ ├── gui3.py │ ├── gui4.py │ └── gui5.py ├── README.md ├── ace_editor.py ├── app.py ├── autoreload.py ├── bulma.py ├── calc.py ├── camshot.py ├── demo.py ├── hello_world.py ├── htag_with_state_manager.py ├── leaflet.py ├── matplot.py ├── navigate_with_hashchange.py ├── new_timer.py ├── pyscript.html ├── pyscript_demo.html ├── pyscript_htagui.html ├── pyscript_htbulma.html ├── pyscript_matplotlib.html ├── pyscript_with_hashchange.html ├── secretapp.py ├── stream.py └── todomvc.py ├── htag ├── __init__.py ├── __main__.py ├── attrs.py ├── render.py ├── runners │ ├── __init__.py │ ├── chromeappmode.py │ ├── commons │ │ └── __init__.py │ ├── pyscript.py │ ├── pywebview.py │ ├── runner.py │ └── server │ │ └── __init__.py ├── tag.py └── ui.py ├── manual_tests_base.py ├── manual_tests_event_0.100.1.py ├── manual_tests_events.py ├── manual_tests_expose.py ├── manual_tests_htbulma.py ├── manual_tests_new_InternalCall.py ├── manual_tests_persitent.py ├── manual_tests_qp.py ├── manual_tests_remove.py ├── mkdocs.yml ├── old_runners ├── README.md ├── androidapp.py ├── browserhttp.py ├── browserstarlettehttp.py ├── browserstarlettews.py ├── browsertornadohttp.py ├── chromeapp.py ├── devapp.py └── winapp.py ├── pyproject.toml ├── selenium ├── app1.py ├── app2.py ├── app3.py ├── app4.py ├── app_all_bindings.py ├── hclient.py ├── run.py └── tests.py ├── test_attrs.py ├── test_callbacks.py ├── test_constructors.py ├── test_dom.py ├── test_init_render.py ├── test_interactions.py ├── test_main.py ├── test_new_events.py ├── test_placeholder.py ├── test_renderer.py ├── test_runners.py ├── test_session_persitent.py ├── test_simple.py ├── test_states_guesser.py ├── test_statics.py ├── test_tag_tech.py └── test_update.py /.github/workflows/on_commit_do_all_unittests.yml: -------------------------------------------------------------------------------- 1 | # This workflow will install Python dependencies, run tests and lint with a variety of Python versions 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions 3 | 4 | name: Run tests 5 | 6 | on: 7 | push: 8 | branches: 9 | - main 10 | 11 | jobs: 12 | build: 13 | 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | python-version: [ 3.8, 3.9, "3.10","3.11","3.12" ] 18 | 19 | steps: 20 | - uses: actions/checkout@v2 21 | - name: Set up Python ${{ matrix.python-version }} 22 | uses: actions/setup-python@v2 23 | with: 24 | python-version: ${{ matrix.python-version }} 25 | - name: Install dependencies 26 | run: | 27 | python -m pip install --upgrade pip 28 | python -m pip install pytest pytest-asyncio 29 | python -m pip install uvicorn starlette tornado kivy pywebview fake-winreg 30 | if [ -f requirements.txt ]; then pip install -r requirements.txt; fi 31 | if [ -f requirements-dev.txt ]; then pip install -r requirements-dev.txt; fi 32 | - name: Test with pytest 33 | run: | 34 | pytest . 35 | -------------------------------------------------------------------------------- /.github/workflows/on_commit_do_deploy_mkdocs.yml: -------------------------------------------------------------------------------- 1 | name: Publish mkdocs pages 2 | on: 3 | push: 4 | branches: 5 | - main 6 | 7 | jobs: 8 | build: 9 | name: Deploy docs 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout main 13 | uses: actions/checkout@v2 14 | 15 | - name: Deploy docs 16 | uses: mhausenblas/mkdocs-deploy-gh-pages@master 17 | env: 18 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 19 | CONFIG_FILE: mkdocs.yml 20 | EXTRA_PACKAGES: build-base 21 | -------------------------------------------------------------------------------- /.github/workflows/on_tag_do_release_and_deploy_pypi.yml: -------------------------------------------------------------------------------- 1 | name: "On Tag -> Deploy a release to pypi" 2 | 3 | #TODO: in the future, try to do that : https://mestrak.com/blog/semantic-release-with-python-poetry-github-actions-20nn 4 | 5 | on: 6 | push: 7 | tags: 8 | - 'v*.*.*' 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | 15 | - name: Set up Python 16 | uses: actions/setup-python@v4 17 | with: 18 | python-version: '3.10' 19 | 20 | - name: Patch Sources with "tag version ref" 21 | run: python .github/workflows/update_version.py ${{github.ref_name}} 22 | 23 | - name: Install dependencies # could be done by poetry ;-) 24 | run: | 25 | python -m pip install --upgrade pip 26 | python -m pip install pytest pytest-asyncio 27 | python -m pip install uvicorn starlette tornado kivy pywebview fake-winreg 28 | 29 | - name: Test htag pytests 30 | run: | 31 | python3 -m pytest . 32 | 33 | - name: Create htag artifact from source versionned 34 | uses: actions/upload-artifact@v4 35 | with: 36 | name: htag_release_sources_${{github.ref_name}} 37 | path: | 38 | htag/* 39 | 40 | - name: Build and publish to pypi 41 | uses: JRubics/poetry-publish@v1.12 42 | with: 43 | pypi_token: ${{ secrets.PYPI_TOKEN }} 44 | 45 | -------------------------------------------------------------------------------- /.github/workflows/selenium.yaml: -------------------------------------------------------------------------------- 1 | # taken from https://github.com/jsoma/selenium-github-actions 2 | name: Selenium GUI Tests 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | # every day at 3:00 AM 7 | - cron: '0 3 * * *' 8 | jobs: 9 | selenium: 10 | runs-on: ubuntu-latest 11 | strategy: 12 | matrix: 13 | app: [app1, app2, app3, app4, app_all_bindings] 14 | steps: 15 | - name: Check out this repo 16 | uses: actions/checkout@v3 17 | - name: Set up Python 18 | uses: actions/setup-python@v4 19 | with: 20 | python-version: '3.11' 21 | - name: Installed package list 22 | run: apt list --installed 23 | - name: Remove Chrome 24 | run: sudo apt purge google-chrome-stable 25 | - name: Remove default Chromium 26 | run: sudo apt purge chromium-browser 27 | - name: Install a new Chromium 28 | run: sudo apt install -y chromium-browser 29 | - name: Install selenium/poetry packages 30 | run: pip install webdriver-manager selenium poetry 31 | - name: pip list 32 | run: pip list 33 | 34 | 35 | ############################################################################# 36 | ## test the basic Runner (WS MODE) 37 | ############################################################################# 38 | - name: Run Tests Runner/WS ${{ matrix.app }} 39 | run: | 40 | python selenium/run.py WS ${{ matrix.app }} & 41 | python selenium/tests.py 8000 ${{ matrix.app }} 42 | 43 | ############################################################################# 44 | ## test the basic Runner (HTTP MODE) 45 | ############################################################################# 46 | - name: Run Tests Runner/HTTP ${{ matrix.app }} 47 | run: | 48 | python selenium/run.py HTTP ${{ matrix.app }} & 49 | python selenium/tests.py 8000 ${{ matrix.app }} 50 | 51 | ############################################################################# 52 | ## test with PyScript Runner 53 | ############################################################################# 54 | - name: Build WHL for pyscript tests 55 | run: poetry build 56 | 57 | - name: Run Tests PyScript (can't exit itself) ${{ matrix.app }} 58 | run: | 59 | python selenium/run.py PyScript ${{ matrix.app }} 8001 & 60 | python selenium/tests.py 8001 ${{ matrix.app }} 61 | killall python 62 | 63 | -------------------------------------------------------------------------------- /.github/workflows/test_platforms.yml: -------------------------------------------------------------------------------- 1 | name: test platforms 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | ci: 8 | strategy: 9 | fail-fast: false 10 | matrix: 11 | # python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] 12 | # os: [ubuntu-latest, macos-latest, windows-latest] 13 | python-version: ["3.9"] 14 | os: [windows-latest] 15 | poetry-version: ["1.2.1"] 16 | runs-on: ${{ matrix.os }} 17 | steps: 18 | - uses: actions/checkout@v2 19 | - uses: actions/setup-python@v2 20 | with: 21 | python-version: ${{ matrix.python-version }} 22 | - name: Run image 23 | uses: abatilo/actions-poetry@v2 24 | with: 25 | poetry-version: ${{ matrix.poetry-version }} 26 | - name: poetry run pytest 27 | run: | 28 | poetry lock 29 | poetry install 30 | poetry run pytest 31 | -------------------------------------------------------------------------------- /.github/workflows/update_version.py: -------------------------------------------------------------------------------- 1 | import sys,re 2 | 3 | 4 | def patch_init(v): 5 | file="htag/__init__.py" 6 | content = re.sub(r'__version__ = [^#]*',f'__version__ = "{v}" ',open(file,'r+').read(),1) 7 | assert v in content 8 | with open(file,'w+') as fid: 9 | fid.write( content ) 10 | return file 11 | 12 | def patch_pyproject(v): 13 | file="pyproject.toml" 14 | content = re.sub(r'version = [^#]*',f'version = "{v}" ',open(file,'r+').read(),1) 15 | assert v in content 16 | with open(file,'w+') as fid: 17 | fid.write( content ) 18 | return file 19 | 20 | if __name__=="__main__": 21 | v=sys.argv[1] 22 | assert v.lower().startswith("v"), "version should start with 'v' (was '%s')" %v 23 | assert v.count(".")==2, "version is not semver (was '%s')" %v 24 | version=v[1:] # remove 'v' 25 | f1=patch_init(version) 26 | f2=patch_pyproject(version) 27 | print(f"Files '{f1}' & '{f2}' updated to version '{version}' !") -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | AEFF* 132 | -------------------------------------------------------------------------------- /.idx/dev.nix: -------------------------------------------------------------------------------- 1 | # To learn more about how to use Nix to configure your environment 2 | # see: https://developers.google.com/idx/guides/customize-idx-env 3 | { pkgs, ... }: { 4 | # Which nixpkgs channel to use. 5 | channel = "stable-23.11"; # or "unstable" 6 | 7 | # Use https://search.nixos.org/packages to find packages 8 | packages = [ 9 | pkgs.poetry 10 | pkgs.python311Packages.pytest 11 | # pkgs.go 12 | # pkgs.python311 13 | # pkgs.python311Packages.pip 14 | # pkgs.nodejs_20 15 | # pkgs.nodePackages.nodemon 16 | ]; 17 | 18 | # Sets environment variables in the workspace 19 | env = {}; 20 | idx = { 21 | # Search for the extensions you want on https://open-vsx.org/ and use "publisher.id" 22 | extensions = [ 23 | # "vscodevim.vim" 24 | ]; 25 | 26 | # Enable previews 27 | previews = { 28 | enable = true; 29 | previews = { 30 | # web = { 31 | # # Example: run "npm run dev" with PORT set to IDX's defined port for previews, 32 | # # and show it in IDX's web preview panel 33 | # command = ["npm" "run" "dev"]; 34 | # manager = "web"; 35 | # env = { 36 | # # Environment variables to set for your server 37 | # PORT = "$PORT"; 38 | # }; 39 | # }; 40 | }; 41 | }; 42 | 43 | # Workspace lifecycle hooks 44 | workspace = { 45 | # Runs when a workspace is first created 46 | onCreate = { 47 | # Example: install JS dependencies from NPM 48 | # npm-install = 'npm install'; 49 | }; 50 | onStart = { 51 | # Example: start a background task to watch and re-build backend code 52 | # watch-backend = "npm run watch-backend"; 53 | }; 54 | }; 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /.idx/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manatlan/htag/13b4aa77173b9036594b49c761b66c45720abf91/.idx/icon.png -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.testing.pytestArgs": [ 3 | ".","-s","-v" 4 | ], 5 | "python.testing.unittestEnabled": false, 6 | "python.testing.pytestEnabled": true, 7 | "editor.wordWrap": "off", 8 | "python.linting.pylintEnabled": true, 9 | "python.linting.enabled": true, 10 | 11 | "python.analysis.diagnosticSeverityOverrides": { 12 | "reportUnusedExpression": "none", 13 | }, 14 | "IDX.aI.enableInlineCompletion": true, 15 | "IDX.aI.enableCodebaseIndexing": true, 16 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Test Coverage", 8 | "type": "shell", 9 | "command": "python3 -m pytest --cov-report html --cov=htag . && google-chrome htmlcov/index.html", 10 | "problemMatcher": [], 11 | "presentation": { 12 | "panel": "new", 13 | "focus": true 14 | } 15 | }, 16 | { 17 | "label": "clean repo", 18 | "type": "shell", 19 | "command": "rm -rf build __pycache__ htag/__pycache__ htag/runners/__pycache__ .pytest_cache .coverage htmlcov", 20 | "problemMatcher": [], 21 | "presentation": { 22 | "panel": "new", 23 | "focus": true 24 | } 25 | }, 26 | { 27 | "label": "Build zip with all", 28 | "type": "shell", 29 | "command": "rm -rf build __pycache__ htag/__pycache__ htag/runners/__pycache__ .pytest_cache .coverage htmlcov; zip -r src.zip htag examples test_*", 30 | "problemMatcher": [], 31 | "presentation": { 32 | "panel": "new", 33 | "focus": true 34 | } 35 | }, 36 | ] 37 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 manatlan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /_pyscript_dev.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 19 | 20 | 21 | loading (recent/2024) pyscript ;-) 22 | 23 | 24 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /brython/README.md: -------------------------------------------------------------------------------- 1 | # HTag for Brython 2 | 3 | [Brython](https://brython.info/) is a marvelous implementation of py3 in javascript, and here is an **htag.Tag** implem for brython. 4 | The goal of this side htag project, is to provide a brython's htag way to create components whose could be compatibles with **htag** and **brython**. 5 | 6 | In fact, it's just It's a class helper, to facilitate the creation of html element. 7 | 8 | In this repo, you will find : 9 | 10 | - [htag.txt](https://github.com/manatlan/htag/blob/main/brython/htag.txt) : the minimal implementation (to use with brython) 11 | - `htagfull.txt` : a more complete implem ... **when it will be ready** ;-) 12 | - somes examples 13 | - [bryted](https://raw.githack.com/manatlan/htag/main/brython/bryted.html) : an online editor to test brython'htag components (made with brython'htag) **PREVERSION** 14 | 15 | 16 | ## Instructions 17 | Put this line in your html file : 18 | ```html 19 | 20 | ``` 21 | In a ` 10 | 15 | 16 | 17 | 18 | 31 | 32 | 33 | 34 | 35 | 77 | 78 | 79 | 80 | 81 | 82 | 83 |