├── tests ├── __init__.py └── test_smoke.py ├── uvicorn_browser ├── __init__.py ├── py.typed ├── __main__.py ├── driver.py ├── reload.py └── main.py ├── docs ├── docs │ └── index.md └── mkdocs.yml ├── setup.py ├── main.py ├── requirements.txt ├── .github ├── dependabot.yml └── workflows │ ├── deploy-docs.yml │ └── ci.yml ├── pyproject.toml ├── Makefile ├── LICENSE ├── setup.cfg ├── README.md └── .gitignore /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /uvicorn_browser/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /uvicorn_browser/py.typed: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/docs/index.md: -------------------------------------------------------------------------------- 1 | # Welcome to the Documentation 2 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup() 4 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | 3 | app = FastAPI() 4 | -------------------------------------------------------------------------------- /docs/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: My Docs 2 | theme: 3 | name: material 4 | -------------------------------------------------------------------------------- /uvicorn_browser/__main__.py: -------------------------------------------------------------------------------- 1 | from uvicorn_browser.main import main 2 | 3 | if __name__ == "__main__": 4 | main() 5 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | flake8==4.0.1 2 | isort==5.10.1 3 | black==21.9b0 4 | pytest==6.2.5 5 | pytest-cov==3.0.0 6 | mypy==0.910 7 | -------------------------------------------------------------------------------- /tests/test_smoke.py: -------------------------------------------------------------------------------- 1 | import inspect 2 | 3 | import uvicorn_browser 4 | 5 | 6 | def test_smoke(): 7 | assert inspect.ismodule(uvicorn_browser) 8 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "pip" 4 | directory: "/" 5 | schedule: 6 | interval: "monthly" 7 | -------------------------------------------------------------------------------- /.github/workflows/deploy-docs.yml: -------------------------------------------------------------------------------- 1 | name: Publish docs via GitHub 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: docs/mkdocs.yml 20 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools >= 40.6.0", "wheel"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [tool.black] 6 | target-version = ['py38'] 7 | 8 | [tool.isort] 9 | profile = "black" 10 | 11 | [tool.mypy] 12 | show_error_codes = true 13 | follow_imports = "skip" 14 | follow_imports_for_stubs = false 15 | ignore_missing_imports = true 16 | 17 | [[tool.mypy.overrides]] 18 | module = "tests.*" 19 | allow_untyped_defs = true 20 | 21 | [tool.pytest.ini_options] 22 | addopts = """\ 23 | --strict-config 24 | --strict-markers 25 | """ 26 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: help 2 | help: ## Show this help 3 | @egrep -h '\s##\s' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' 4 | 5 | 6 | .PHONY: lint 7 | lint: ## Linter the code. 8 | @echo "🚨 Linting code" 9 | isort uvicorn_browser tests --check 10 | flake8 uvicorn_browser tests 11 | mypy uvicorn_browser 12 | black uvicorn_browser tests --check --diff 13 | 14 | 15 | .PHONY: format 16 | format: 17 | @echo "🎨 Formatting code" 18 | isort uvicorn_browser tests 19 | autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place uvicorn_browser tests --exclude=__init__.py 20 | black uvicorn_browser tests 21 | 22 | 23 | .PHONY: tests 24 | test: ## Test your code. 25 | @echo "🍜 Running pytest" 26 | pytest tests/ --cov=uvicorn_browser --cov-report=term-missing:skip-covered --cov-report=xml --cov-fail-under 100 27 | 28 | 29 | .PHONY: publish 30 | publish: ## Publish release to PyPI 31 | @echo "🔖 Publish to PyPI" 32 | python setup.py bdist_wheel 33 | twine upload dist/* 34 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | 9 | jobs: 10 | tests: 11 | name: "Python ${{ matrix.python-version }} ${{ matrix.os }}" 12 | runs-on: "${{ matrix.os }}" 13 | timeout-minutes: 30 14 | strategy: 15 | fail-fast: false 16 | matrix: 17 | python-version: ["3.8", "3.9", "3.10"] 18 | os: [windows-latest, ubuntu-latest, macos-latest] 19 | 20 | steps: 21 | - name: Checkout changes 22 | uses: actions/checkout@v2 23 | 24 | - name: Set up Python ${{ matrix.python-version }} 25 | uses: actions/setup-python@v2 26 | with: 27 | python-version: ${{ matrix.python-version }} 28 | cache: 'pip' 29 | 30 | - name: Install dependencies 31 | run: | 32 | python -m pip install --upgrade pip 33 | python -m pip install -r requirements.txt 34 | 35 | - name: Lint Python 36 | run: make lint 37 | 38 | - name: Run tests 39 | run: make tests 40 | 41 | - name: Upload coverage 42 | uses: codecov/codecov-action@v2 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Marcelo Trylesinski 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 | -------------------------------------------------------------------------------- /uvicorn_browser/driver.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from typing import Union 3 | 4 | from selenium import webdriver 5 | 6 | if sys.version_info < (3, 8): 7 | from typing_extensions import Literal 8 | else: 9 | from typing import Literal 10 | 11 | 12 | class RefreshableDriver: 13 | def __init__(self, url: str, flavour: Literal["chrome", "firefox"]): 14 | self.url = url 15 | self.driver = get_driver(flavour) 16 | 17 | def reload(self): 18 | self.driver.refresh() 19 | 20 | def load(self): 21 | self.driver.get(self.url) 22 | 23 | def close(self): 24 | self.driver.close() 25 | 26 | def quit(self): 27 | self.driver.quit() 28 | 29 | 30 | def get_driver(flavour: str) -> Union[webdriver.Firefox, webdriver.Chrome]: 31 | if flavour == "firefox": 32 | profile = webdriver.FirefoxProfile() 33 | profile.set_preference("browser.cache.disk.enable", False) 34 | profile.set_preference("browser.cache.memory.enable", False) 35 | profile.set_preference("browser.cache.offline.enable", False) 36 | profile.set_preference("network.http.use-cache", False) 37 | return webdriver.Firefox(executable_path="geckodriver", firefox_profile=profile) 38 | elif flavour == "chrome": 39 | return webdriver.Chrome(executable_path="chromedriver") 40 | 41 | raise ValueError(f"Unknown driver flavour: {flavour}") 42 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = uvicorn-browser 3 | version = 0.2.0 4 | description = Reload your Browser with code changes! :sparkles: 5 | long_description = file: README.md 6 | long_description_content_type = text/markdown 7 | url = https://github.com/Kludex/uvicorn-browser 8 | author = Marcelo Trylesinski 9 | author_email = marcelotryle@email.com 10 | license = MIT 11 | license_file = LICENSE 12 | classifiers = 13 | License :: OSI Approved :: MIT License 14 | Intended Audience :: Developers 15 | Natural Language :: English 16 | Operating System :: OS Independent 17 | Programming Language :: Python :: 3 :: Only 18 | Programming Language :: Python :: 3 19 | Programming Language :: Python :: 3.6 20 | Programming Language :: Python :: 3.7 21 | Programming Language :: Python :: 3.8 22 | Programming Language :: Python :: 3.9 23 | Programming Language :: Python :: 3.10 24 | Programming Language :: Python :: Implementation :: CPython 25 | Programming Language :: Python :: Implementation :: PyPy 26 | project_urls = 27 | Twitter = https://twitter.com/marcelotryle 28 | 29 | [options] 30 | packages = find: 31 | include_package_data = True 32 | install_requires = 33 | uvicorn==0.16.0 34 | selenium 35 | typing-extensions; python_version < '3.8' 36 | python_requires = >=3.6.1 37 | 38 | [options.entry_points] 39 | console_scripts = 40 | uvicorn = uvicorn_browser.main:main 41 | uvicorn-browser = uvicorn_browser.main:main 42 | 43 | [flake8] 44 | statistics = True 45 | max-line-length = 88 46 | ignore = E203,E501,W503 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
19 |
20 |