{"id":19874180,"url":"https://github.com/pythoninthegrass/knockknock_poc","last_synced_at":"2025-03-01T01:23:12.500Z","repository":{"id":85073760,"uuid":"477861438","full_name":"pythoninthegrass/knockknock_poc","owner":"pythoninthegrass","description":null,"archived":false,"fork":false,"pushed_at":"2022-04-04T20:24:43.000Z","size":271,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-11T16:50:29.057Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pythoninthegrass.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["pythoninthegrass"]}},"created_at":"2022-04-04T20:24:41.000Z","updated_at":"2022-04-04T20:24:46.000Z","dependencies_parsed_at":"2023-03-08T20:00:55.723Z","dependency_job_id":null,"html_url":"https://github.com/pythoninthegrass/knockknock_poc","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":"pythoninthegrass/python_template","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pythoninthegrass%2Fknockknock_poc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pythoninthegrass%2Fknockknock_poc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pythoninthegrass%2Fknockknock_poc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pythoninthegrass%2Fknockknock_poc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pythoninthegrass","download_url":"https://codeload.github.com/pythoninthegrass/knockknock_poc/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241301840,"owners_count":19940719,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-12T16:22:08.126Z","updated_at":"2025-03-01T01:23:12.482Z","avatar_url":"https://github.com/pythoninthegrass.png","language":"Python","readme":"# python_template\n\n![\"It's dangerous to go alone! Take this.\"](zelda.jpg)\n\u003c!-- \u003cimg src=\"https://user-images.githubusercontent.com/4097471/144654508-823c6e31-5e10-404c-9f9f-0d6b9d6ce617.jpg\" width=\"300\"\u003e --\u003e\n\n## Summary\nOftentimes the initial setup of a Python repo can take a few minutes to a couple hours.\nBy laying the foundation to rapidly implement an idea, can focus on the good bits instead of\ndevops drudgery.\n\n### Caveat Emptor\nVery little of this gets tested on Windows hosts. Windows Subsystem for Linux (WSL) is used where necessary with the default Ubuntu LTS install.\n\nBe the change et al if Windows is your main and you wanna raise a PR with broad instructions on getting tooling working under Windows (e.g., docker, poetry, playwright.)\n\n**Table of Contents**\n* [python_template](#python_template)\n  * [Summary](#summary)\n    * [Caveat Emptor](#caveat-emptor)\n  * [Setup](#setup)\n  * [Usage](#usage)\n    * [Mac and Linux users](#mac-and-linux-users)\n    * [Windows Subsytem for Linux (wsl)](#windows-subsytem-for-linux-wsl)\n    * [asdf](#asdf)\n    * [Python pip](#python-pip)\n    * [Poetry](#poetry)\n    * [Docker](#docker)\n      * [Docker Troubleshooting](#docker-troubleshooting)\n    * [Playwright](#playwright)\n    * [Django](#django)\n  * [GitHub Actions](#github-actions)\n    * [Update submodules recursively](#update-submodules-recursively)\n  * [Debugging](#debugging)\n    * [asdf](#asdf-1)\n    * [PATH](#path)\n  * [TODO](#todo)\n  * [Further Reading](#further-reading)\n\n## Setup\n* Install \n    * [editorconfig](https://editorconfig.org/)\n    * [wsl](https://docs.microsoft.com/en-us/windows/wsl/setup/environment)\n    * [asdf](https://asdf-vm.com/manage/core.html#installation-setup)\n    * [poetry](https://python-poetry.org/docs/)\n    * [docker-compose](https://docs.docker.com/compose/install/)\n    * [playwright](https://playwright.dev/python/docs/intro#installation)\n\n## Usage\n### Mac and Linux users\nDevelopment environments and tooling are first-class citizens on macOS and *nix. For Windows faithfuls, please setup WSL below.\n\n### Windows Subsytem for Linux (wsl)\nWSL allows Windows users to run Linux (Unix) [locally at a system-level](https://docs.microsoft.com/en-us/windows/wsl/compare-versions). All of the standard tooling is used and community guides can be followed without standard Windows caveats (e.g., escaping file paths, GNU utilities missing, etc.) \n* Install from the [Setup](#setup) section\n* Enable\n  * Start Menu \u003e search for \"Turn Windows Features On\" \u003e open \u003e toggle \"Windows Subsystem for Linux\"\n  * Restart\n* M1 Macs only (Intel Macs and native Windows boxes need not apply)\n  * Revert WSL 2 to WSL 1 due to nested virtualization not being available at a hardware level\n    ```bash\n    wsl --set-default-version 1\n    ```\n  * Docker won't run without paravirtualization enabled, but the rest of the development environment will work as expected\n* Install Ubuntu\n  ```bash\n  # enable default distribution (Ubuntu)\n  wsl --install ubuntu\n  ```\n* Start Linux and prep for environment setup\n    ```bash\n    # launch Ubuntu\n    ubuntu\n\n    # upgrade packages (as root: `sudo -s`)\n    apt update \u0026\u0026 apt upgrade -y\n\n    # install the community python repo (PPA)\n\n\n    # create standard user\n    adduser \u003cusername\u003e\n    visudo\n\n    # search for 'Allow root to run any commands anywhere', then append identical line with new user\n    root            ALL=(ALL)       ALL\n    \u003cusername\u003e      ALL=(ALL)       ALL\n\n    # Allow members of group sudo to execute any command\n    %sudo  ALL=(ALL) NOPASSWD: ALL\n    ```\n* Additional configuration options\n  * Configuration locations\n    * WSL 1: `/etc/wsl.conf`\n    * WSL 2: `~/.wslconfig`\n      ```bash\n        # set default user\n        [user]\n        default=\u003cusername\u003e\n\n        # mounts host drive at /mnt/c/\n        [automount]\n        enabled = true\n        options = \"uid=1000,gid=1000\"\n\n        # WSL2-specific options\n        [wsl2]\n        memory = 8GB   # Limits VM memory in WSL 2\n        processors = 6 # Makes the WSL 2 VM use two virtual processors\n        ```\n  * After making changes to the configuration file, WSL needs to be shutdown for [8 seconds](https://docs.microsoft.com/en-us/windows/wsl/wsl-config#the-8-second-rule)\n    * `wsl --shutdown`\n  * **OPTIONAL**: Change home directory to host Windows' home\n    ```bash\n    # copy dotfiles to host home directory\n    cp $HOME/.* /mnt/c/Users/\u003cusername\u003e\n\n    # edit /etc/passwd\n    \u003cusername\u003e:x:1000:1000:,,,:/mnt/c/Users/\u003cusername\u003e:/bin/bash\n    ```\n\n### asdf\n* Install from the [Setup](#setup) section\n* WSL/Ubuntu Linux dependencies\n    ```bash\n    sudo apt install \\\n    make build-essential libssl-dev zlib1g-dev \\\n    libbz2-dev libreadline-dev libsqlite3-dev wget \\\n    curl llvm libncursesw5-dev xz-utils tk-dev \\\n    libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev\n    ```\n* All operating systems\n    ```bash\n    # add python plugin\n    asdf plugin-add python\n\n    # install stable python\n    asdf install python latest\n\n    # uninstall version\n    asdf uninstall python 3.9.6\n\n    # refresh symlinks for installed python runtimes\n    asdf reshim python\n\n    # set stable to system python\n    asdf global python latest\n\n    # optional: local python (e.g., python 3.9.10)\n    cd $work_dir\n    asdf list-all python 3.9\n    asdf install python 3.9.10\n    asdf local python 3.9.10\n\n    # verify python shim in use\n    asdf current\n\n    # check installed python\n    asdf list python\n    ```\n\n### Python pip\nIf a basic virtual environment (`venv`) and `requirements.txt` are all that's needed, can use built-in tools.\n```bash\n# create a virtual environment via python\npython3 -m venv .venv\n\n# activate virtual environment\nsource .venv/bin/activate\n\n# install dependencies\npython3 -m pip install requests inquirer\n\n# generate requirements.txt\npython3 -m pip freeze \u003e requirements.txt\n\n# exit virtual environment\ndeactivate\n```\n\n### Poetry\n* **NOTE**: it's possible to use the built-in `.venv` virtual environment (e.g., troubleshooting `SolverProblemError` dependency hell)\n    ```bash\n    poetry env use .venv/bin/python\n    ```\n* Install from the [Setup](#setup) section\n* Normal usage\n    ```bash\n    # Install (modifies $PATH)\n    curl -sSL https://install.python-poetry.org | $(which python3) - # append `--no-modify-path` to EOL if you know what you're doing \n\n    # Change config\n    poetry config virtualenvs.in-project true           # .venv in `pwd`\n    poetry config experimental.new-installer false      # fixes JSONDecodeError on Python3.10\n\n    # Activate virtual environment (venv)\n    poetry shell\n\n    # Deactivate venv\n    exit  # ctrl-d\n\n    # Install multiple libraries\n    poetry add google-auth google-api-python-client\n\n    # Initialize existing project\n    poetry init\n\n    # Run script and exit environment\n    poetry run python your_script.py\n\n    # Install from requirements.txt\n    poetry add `cat requirements.txt`\n\n    # Update dependencies\n    poetry update\n\n    # Remove library\n    poetry remove google-auth\n\n    # Generate requirements.txt\n    poetry export -f requirements.txt --output requirements.txt --without-hashes\n\n    # Uninstall Poetry (e.g., troubleshooting)\n    POETRY_UNINSTALL=1 bash -c 'curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py' | $(which python3) -\n    ```\n\n### Docker\n* Install from the [Setup](#setup) section\n* Usage\n    ```bash\n    # clean build (remove `--no-cache` for speed)\n    docker-compose build --no-cache --parallel\n\n    # start container\n    docker-compose up --remove-orphans -d\n\n    # exec into container\n    docker attach hello\n\n    # run command inside container\n    python hello.py\n\n    # destroy container\n    docker-compose down\n    ```\n\n#### Docker Troubleshooting\n* Watch logs in real-time: `docker-compose logs -tf --tail=\"50\" hello`\n* Check exit code\n    ```bash\n    $ docker-compose ps\n    Name                          Command               State    Ports\n    ------------------------------------------------------------------------------\n    docker_python      python manage.py runserver ...   Exit 0\n    ```\n\n### Playwright\n* Install from the [Setup](#setup) section\n* Usage\n    ```bash\n    # install\n    pip install --upgrade pip\n    pip install playwright\n    playwright install\n\n    # download new browsers (chromedriver, gecko)\n    npx playwright install\n\n    # generate code via macro\n    playwright codegen wikipedia.org\n    ```\n\n### Django\n* Follow the official [Django Docker Compose article](https://docs.docker.com/samples/django/)\n    * `cd django`\n    * Generate the server boilerplate code\n        ```bash\n        docker-compose run web django-admin startproject composeexample .\n        ```\n    * Fix upstream import bug and whitelist all hosts/localhost\n        ```bash\n        $ vim composeexample/settings.py\n        import os\n        ...\n        ALLOWED_HOSTS = [\"*\"]\n        ```\n    * Profit\n        ```bash\n        docker-compose up\n        ```\n    * **Optional**: Comment out Django exclusions for future commits\n        * Assumed if extracting Django boilerplate from template and creating a new repo\n        ```bash\n        # .gitignore\n        # ETC\n        # django/composeexample/\n        # django/data/\n        # django/manage.py\n        ```\n\n## GitHub Actions\n### Update submodules recursively\n* Add the submodule to the downstream repo\n    ```bash\n    git submodule add https://github.com/pythoninthegrass/automate_boring_stuff.git\n    git commit -m \"automate_boring_stuff submodule\"\n    git push\n    ```\n* Create a personal access token called `PRIVATE_TOKEN_GITHUB` with `repo` permissions on the downstream repo\n    * `repo:status`\n    * `repo_deployment`\n    * `public_repo`\n* Add that key to the original repo\n    * Settings \u003e Security \u003e Secrets \u003e Actions\n    * New repository secret\n* Setup a new Action workflow\n    * Actions \u003e New Workflow\n    * Choose a workflow \u003e set up a workflow yourself\n    ```bash\n    # main.yml\n    # SOURCE: https://stackoverflow.com/a/68213855\n    name: Send submodule updates to parent repo\n\n    on:\n    push:\n        branches: \n        - main\n        - master\n\n    jobs:\n    update:\n        runs-on: ubuntu-latest\n\n        steps:\n        - uses: actions/checkout@v2\n            with: \n            repository: username/repo_name\n            token: ${{ secrets.PRIVATE_TOKEN_GITHUB }}\n\n        - name: Pull \u0026 update submodules recursively\n            run: |\n            git submodule update --init --recursive\n            git submodule update --recursive --remote\n        - name: Commit\n            run: |\n            git config user.email \"actions@github.com\"\n            git config user.name \"GitHub Actions - update submodules\"\n            git add --all\n            git commit -m \"Update submodules\" || echo \"No changes to commit\"\n            git push\n    ```\n\n## Debugging\n### asdf\n**No version set for command python**\n* Make sure `python` or `python3` isn't aliased in `~/.bashrc` or `~/.zshrc`\n\n[bash - Is it possible to check where an alias was defined? - Unix \u0026 Linux Stack Exchange](https://unix.stackexchange.com/questions/322459/is-it-possible-to-check-where-an-alias-was-defined/544970#544970)\n\n### PATH\n* `asdf`, `poetry`, and `python` all need to be sourced in your shell `$PATH` in a specific order\n  * `asdf` stores its Python shims in `~/.asdf/shims`\n  * `poetry` lives in `~/.local/bin`\n    ```bash\n    export ASDF_DIR=\"$HOME/.asdf\"\n    export PATH=\"$ASDF_DIR/shims:$HOME/.local/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin\"\n    ```\n* Furthermore, any aliases or alias files need to be sourced as well\n    ```bash\n    . \"$ASDF_DIR/asdf.sh\"\n    . \"$ASDF_DIR/completions/asdf.bash\"\n    . /usr/local/etc/profile.d/poetry.bash-completion\n    ```\n\n## TODO\n* ~~Add boilerplate to hello.py~~\n* ~~Poetry~~\n* ~~Dockerfile~~\n* ~~Playwright~~\n* ~~Django~~\n    * Merge with [docker_python](https://github.com/pythoninthegrass/docker_python) and put the latter on an ice float\n    * ~~Break out into separate folder~~\n* Flask\n    * Bonus points for [Svelte](https://svelte.dev/blog/the-easiest-way-to-get-started) front-end ❤️\n    * Break out into separate folder\n* ~~asdf~~\n* terraform\n* k8s\n* wsl\n    * ~~enable~~\n    * ~~`.wslconfig` options~~\n    * ~~install `ppa:deadsnakes/ppa`~~\n      * precluded by `asdf` (née `pyenv`)\n    * VSCode\n        * Remote WSL install and usage\n            * Or at least further reading nods\n* Debugging\n   * ~~`$PATH`~~\n   * Dependencies\n   * script itself via [icecream](https://github.com/gruns/icecream)\n\n## Further Reading\n[Basic writing and formatting syntax - GitHub Docs](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax)\n\n[venv — Creation of virtual environments — Python 3.7.2 documentation](https://docs.python.org/3/library/venv.html)\n\n[pip freeze - pip documentation v22.0.3](https://pip.pypa.io/en/stable/cli/pip_freeze/)\n\n[Introduction | Documentation | Poetry - Python dependency management and packaging made easy](https://python-poetry.org/docs/)\n\n[Commands | Documentation | Poetry - Python dependency management and packaging made easy](https://python-poetry.org/docs/cli#export)\n\n[Overview of Docker Compose | Docker Documentation](https://docs.docker.com/compose/)\n\n[Compose file version 3 reference | Docker Documentation](https://docs.docker.com/compose/compose-file/compose-file-v3/)\n\n[Getting started | Playwright Python | codegen macro](https://playwright.dev/python/docs/intro)\n\n[Install WSL | Microsoft Docs](https://docs.microsoft.com/en-us/windows/wsl/install)\n\n[Set up a WSL development environment | Microsoft Docs](https://docs.microsoft.com/en-us/windows/wsl/setup/environment)\n\n[Advanced settings configuration in WSL | Microsoft Docs](https://docs.microsoft.com/en-us/windows/wsl/wsl-config)\n\n[Understanding The Python Path Environment Variable in Python](https://www.simplilearn.com/tutorials/python-tutorial/python-path)\n","funding_links":["https://github.com/sponsors/pythoninthegrass"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpythoninthegrass%2Fknockknock_poc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpythoninthegrass%2Fknockknock_poc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpythoninthegrass%2Fknockknock_poc/lists"}