Compare commits
	
		
			1 Commits
		
	
	
		
			bind_excep
			...
			smoother-p
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | e0839fe130 | 
							
								
								
									
										28
									
								
								.github/workflows/coverage.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								.github/workflows/coverage.yml
									
									
									
									
										vendored
									
									
								
							| @@ -12,23 +12,29 @@ on: | ||||
|       - main | ||||
|       - current-release | ||||
|       - "*LTS" | ||||
|  | ||||
| jobs: | ||||
|   coverage: | ||||
|     name: Check coverage | ||||
|     runs-on: ubuntu-latest | ||||
|   test: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     strategy: | ||||
|       matrix: | ||||
|         python-version: [3.9] | ||||
|         os: [ubuntu-latest] | ||||
|       fail-fast: false | ||||
|  | ||||
|     steps: | ||||
|       - name: Run coverage | ||||
|         uses: sanic-org/simple-tox-action@v1 | ||||
|       - uses: actions/checkout@v2 | ||||
|       - uses: actions/setup-python@v1 | ||||
|         with: | ||||
|           python-version: "3.11" | ||||
|           tox-env: coverage | ||||
|           ignore-errors: true | ||||
|       - name: Run Codecov | ||||
|         uses: codecov/codecov-action@v3 | ||||
|           python-version: ${{ matrix.python-version }} | ||||
|  | ||||
|       - name: Install dependencies 🔨 | ||||
|         run: | | ||||
|           python -m pip install --upgrade pip | ||||
|           pip install tox | ||||
|       - name: Run coverage | ||||
|         run: tox -e coverage | ||||
|         continue-on-error: true | ||||
|       - uses: codecov/codecov-action@v2 | ||||
|         with: | ||||
|           files: ./coverage.xml | ||||
|           fail_ci_if_error: false | ||||
|   | ||||
							
								
								
									
										39
									
								
								.github/workflows/on-demand.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								.github/workflows/on-demand.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| name: On Demand Task | ||||
| on: | ||||
|   workflow_dispatch: | ||||
|     inputs: | ||||
|       python-version: | ||||
|         description: 'Version of Python to use for running Test' | ||||
|         required: false | ||||
|         default: "3.8" | ||||
|       tox-env: | ||||
|         description: 'Test Environment to Run' | ||||
|         required: true | ||||
|         default: '' | ||||
|       os: | ||||
|         description: 'Operating System to Run Test on' | ||||
|         required: false | ||||
|         default: ubuntu-latest | ||||
| jobs: | ||||
|   onDemand: | ||||
|     name: tox-${{ matrix.config.tox-env }}-on-${{ matrix.os }} | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         os: ["${{ github.event.inputs.os}}"] | ||||
|         config: | ||||
|           - { tox-env: "${{ github.event.inputs.tox-env }}", py-version: "${{ github.event.inputs.python-version }}"} | ||||
|     steps: | ||||
|       - name: Checkout Repository | ||||
|         uses: actions/checkout@v2 | ||||
|  | ||||
|       - name: Run tests | ||||
|         uses: harshanarayana/custom-actions@main | ||||
|         with: | ||||
|           python-version: ${{ matrix.config.py-version }} | ||||
|           test-infra-tool: tox | ||||
|           test-infra-version: latest | ||||
|           action: tests | ||||
|           test-additional-args: "-e=${{ matrix.config.tox-env }}" | ||||
|           experimental-ignore-error: "yes" | ||||
							
								
								
									
										37
									
								
								.github/workflows/pr-bandit.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								.github/workflows/pr-bandit.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| name: Security Analysis | ||||
| on: | ||||
|   pull_request: | ||||
|     branches: | ||||
|       - main | ||||
|       - current-release | ||||
|       - "*LTS" | ||||
|     types: [opened, synchronize, reopened, ready_for_review] | ||||
|  | ||||
| jobs: | ||||
|   bandit: | ||||
|     if: github.event.pull_request.draft == false | ||||
|     name: type-check-${{ matrix.config.python-version }} | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         os: [ubuntu-latest] | ||||
|         config: | ||||
|           - { python-version: 3.8, tox-env: security} | ||||
|           - { python-version: 3.9, tox-env: security} | ||||
|           - { python-version: "3.10", tox-env: security} | ||||
|           - { python-version: "3.11", tox-env: security} | ||||
|     steps: | ||||
|       - name: Checkout the repository | ||||
|         uses: actions/checkout@v2 | ||||
|         id: checkout-branch | ||||
|  | ||||
|       - name: Run Linter Checks | ||||
|         id: linter-check | ||||
|         uses: harshanarayana/custom-actions@main | ||||
|         with: | ||||
|           python-version: ${{ matrix.config.python-version }} | ||||
|           test-infra-tool: tox | ||||
|           test-infra-version: latest | ||||
|           action: tests | ||||
|           test-additional-args: "-e=${{ matrix.config.tox-env }}" | ||||
							
								
								
									
										33
									
								
								.github/workflows/pr-docs.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								.github/workflows/pr-docs.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| name: Document Linter | ||||
| on: | ||||
|   pull_request: | ||||
|     branches: | ||||
|       - main | ||||
|       - current-release | ||||
|       - "*LTS" | ||||
|     types: [opened, synchronize, reopened, ready_for_review] | ||||
|  | ||||
| jobs: | ||||
|   docsLinter: | ||||
|     if: github.event.pull_request.draft == false | ||||
|     name: Lint Documentation | ||||
|     runs-on: ubuntu-latest | ||||
|     strategy: | ||||
|       matrix: | ||||
|         config: | ||||
|           - {python-version: "3.10", tox-env: "docs"} | ||||
|       fail-fast: false | ||||
|  | ||||
|  | ||||
|     steps: | ||||
|       - name: Checkout repository | ||||
|         uses: actions/checkout@v2 | ||||
|  | ||||
|       - name: Run Document Linter | ||||
|         uses: harshanarayana/custom-actions@main | ||||
|         with: | ||||
|           python-version: ${{ matrix.config.python-version }} | ||||
|           test-infra-tool: tox | ||||
|           test-infra-version: latest | ||||
|           action: tests | ||||
|           test-additional-args: "-e=${{ matrix.config.tox-env }}" | ||||
							
								
								
									
										34
									
								
								.github/workflows/pr-linter.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								.github/workflows/pr-linter.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| name: Linter Checks | ||||
| on: | ||||
|   pull_request: | ||||
|     branches: | ||||
|       - main | ||||
|       - current-release | ||||
|       - "*LTS" | ||||
|     types: [opened, synchronize, reopened, ready_for_review] | ||||
|  | ||||
| jobs: | ||||
|   linter: | ||||
|     if: github.event.pull_request.draft == false | ||||
|     name: lint | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         os: [ubuntu-latest] | ||||
|         config: | ||||
|           - { python-version: "3.10", tox-env: lint} | ||||
|     steps: | ||||
|       - name: Checkout the repository | ||||
|         uses: actions/checkout@v2 | ||||
|         id: checkout-branch | ||||
|  | ||||
|       - name: Run Linter Checks | ||||
|         id: linter-check | ||||
|         uses: harshanarayana/custom-actions@main | ||||
|         with: | ||||
|           python-version: ${{ matrix.config.python-version }} | ||||
|           test-infra-tool: tox | ||||
|           test-infra-version: latest | ||||
|           action: tests | ||||
|           test-additional-args: "-e=${{ matrix.config.tox-env }}" | ||||
							
								
								
									
										41
									
								
								.github/workflows/pr-python-pypy.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								.github/workflows/pr-python-pypy.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| name: Python PyPy Tests | ||||
| on: | ||||
|   workflow_dispatch: | ||||
|     inputs: | ||||
|       tox-env: | ||||
|         description: "Tox Env to run on the PyPy Infra" | ||||
|         required: false | ||||
|         default: "pypy310" | ||||
|       pypy-version: | ||||
|         description: "Version of PyPy to use" | ||||
|         required: false | ||||
|         default: "pypy-3.10" | ||||
| jobs: | ||||
|   testPyPy: | ||||
|     name: ut-${{ matrix.config.tox-env }}-${{ matrix.os }} | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         # os: [ubuntu-latest, macos-latest] | ||||
|         os: [ubuntu-latest] | ||||
|         config: | ||||
|           - { | ||||
|               python-version: "${{ github.event.inputs.pypy-version }}", | ||||
|               tox-env: "${{ github.event.inputs.tox-env }}", | ||||
|             } | ||||
|     steps: | ||||
|       - name: Checkout the Repository | ||||
|         uses: actions/checkout@v2 | ||||
|         id: checkout-branch | ||||
|  | ||||
|       - name: Run Unit Tests | ||||
|         uses: harshanarayana/custom-actions@main | ||||
|         with: | ||||
|           python-version: ${{ matrix.config.python-version }} | ||||
|           test-infra-tool: tox | ||||
|           test-infra-version: latest | ||||
|           action: tests | ||||
|           test-additional-args: "-e=${{ matrix.config.tox-env }}" | ||||
|           experimental-ignore-error: "true" | ||||
|           command-timeout: "600000" | ||||
							
								
								
									
										48
									
								
								.github/workflows/pr-python310.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								.github/workflows/pr-python310.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| name: Python 3.10 Tests | ||||
| on: | ||||
|   pull_request: | ||||
|     branches: | ||||
|       - main | ||||
|       - current-release | ||||
|       - "*LTS" | ||||
|     types: [opened, synchronize, reopened, ready_for_review] | ||||
|  | ||||
| jobs: | ||||
|   testPy310: | ||||
|     if: github.event.pull_request.draft == false | ||||
|     name: ut-${{ matrix.config.tox-env }}-${{ matrix.os }} | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         # os: [ubuntu-latest, macos-latest] | ||||
|         os: [ubuntu-latest] | ||||
|         config: | ||||
|           - { | ||||
|               python-version: "3.10", | ||||
|               tox-env: py310, | ||||
|               ignore-error-flake: "false", | ||||
|               command-timeout: "0", | ||||
|             } | ||||
|           - { | ||||
|               python-version: "3.10", | ||||
|               tox-env: py310-no-ext, | ||||
|               ignore-error-flake: "true", | ||||
|               command-timeout: "600000", | ||||
|             } | ||||
|     steps: | ||||
|       - name: Checkout the Repository | ||||
|         uses: actions/checkout@v2 | ||||
|         id: checkout-branch | ||||
|  | ||||
|       - name: Run Unit Tests | ||||
|         uses: harshanarayana/custom-actions@main | ||||
|         with: | ||||
|           python-version: ${{ matrix.config.python-version }} | ||||
|           test-infra-tool: tox | ||||
|           test-infra-version: latest | ||||
|           action: tests | ||||
|           test-additional-args: "-e=${{ matrix.config.tox-env }},-vv=''" | ||||
|           experimental-ignore-error: "${{ matrix.config.ignore-error-flake }}" | ||||
|           command-timeout: "${{ matrix.config.command-timeout }}" | ||||
|           test-failure-retry: "3" | ||||
							
								
								
									
										48
									
								
								.github/workflows/pr-python311.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								.github/workflows/pr-python311.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| name: Python 3.11 Tests | ||||
| on: | ||||
|   pull_request: | ||||
|     branches: | ||||
|       - main | ||||
|       - current-release | ||||
|       - "*LTS" | ||||
|     types: [opened, synchronize, reopened, ready_for_review] | ||||
|  | ||||
| jobs: | ||||
|   testPy311: | ||||
|     if: github.event.pull_request.draft == false | ||||
|     name: ut-${{ matrix.config.tox-env }}-${{ matrix.os }} | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         # os: [ubuntu-latest, macos-latest] | ||||
|         os: [ubuntu-latest] | ||||
|         config: | ||||
|           - { | ||||
|               python-version: "3.11", | ||||
|               tox-env: py311, | ||||
|               ignore-error-flake: "false", | ||||
|               command-timeout: "0", | ||||
|             } | ||||
|           - { | ||||
|               python-version: "3.11", | ||||
|               tox-env: py311-no-ext, | ||||
|               ignore-error-flake: "true", | ||||
|               command-timeout: "600000", | ||||
|             } | ||||
|     steps: | ||||
|       - name: Checkout the Repository | ||||
|         uses: actions/checkout@v2 | ||||
|         id: checkout-branch | ||||
|  | ||||
|       - name: Run Unit Tests | ||||
|         uses: harshanarayana/custom-actions@main | ||||
|         with: | ||||
|           python-version: ${{ matrix.config.python-version }} | ||||
|           test-infra-tool: tox | ||||
|           test-infra-version: latest | ||||
|           action: tests | ||||
|           test-additional-args: "-e=${{ matrix.config.tox-env }},-vv=''" | ||||
|           experimental-ignore-error: "${{ matrix.config.ignore-error-flake }}" | ||||
|           command-timeout: "${{ matrix.config.command-timeout }}" | ||||
|           test-failure-retry: "3" | ||||
							
								
								
									
										36
									
								
								.github/workflows/pr-python38.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								.github/workflows/pr-python38.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| name: Python 3.8 Tests | ||||
| on: | ||||
|   pull_request: | ||||
|     branches: | ||||
|       - main | ||||
|       - current-release | ||||
|       - "*LTS" | ||||
|     types: [opened, synchronize, reopened, ready_for_review] | ||||
|  | ||||
| jobs: | ||||
|   testPy38: | ||||
|     if: github.event.pull_request.draft == false | ||||
|     name: ut-${{ matrix.config.tox-env }}-${{ matrix.os }} | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     strategy: | ||||
|       fail-fast: true | ||||
|       matrix: | ||||
|         # os: [ubuntu-latest, macos-latest] | ||||
|         os: [ubuntu-latest] | ||||
|         config: | ||||
|           - { python-version: 3.8, tox-env: py38 } | ||||
|           - { python-version: 3.8, tox-env: py38-no-ext } | ||||
|     steps: | ||||
|       - name: Checkout the Repository | ||||
|         uses: actions/checkout@v2 | ||||
|         id: checkout-branch | ||||
|  | ||||
|       - name: Run Unit Tests | ||||
|         uses: harshanarayana/custom-actions@main | ||||
|         with: | ||||
|           python-version: ${{ matrix.config.python-version }} | ||||
|           test-infra-tool: tox | ||||
|           test-infra-version: latest | ||||
|           action: tests | ||||
|           test-additional-args: "-e=${{ matrix.config.tox-env }}" | ||||
|           test-failure-retry: "3" | ||||
							
								
								
									
										48
									
								
								.github/workflows/pr-python39.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								.github/workflows/pr-python39.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| name: Python 3.9 Tests | ||||
| on: | ||||
|   pull_request: | ||||
|     branches: | ||||
|       - main | ||||
|       - current-release | ||||
|       - "*LTS" | ||||
|     types: [opened, synchronize, reopened, ready_for_review] | ||||
|  | ||||
| jobs: | ||||
|   testPy39: | ||||
|     if: github.event.pull_request.draft == false | ||||
|     name: ut-${{ matrix.config.tox-env }}-${{ matrix.os }} | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     strategy: | ||||
|       fail-fast: true | ||||
|       matrix: | ||||
|         # os: [ubuntu-latest, macos-latest] | ||||
|         os: [ubuntu-latest] | ||||
|         config: | ||||
|           - { | ||||
|               python-version: 3.9, | ||||
|               tox-env: py39, | ||||
|               ignore-error-flake: "false", | ||||
|               command-timeout: "0", | ||||
|             } | ||||
|           - { | ||||
|               python-version: 3.9, | ||||
|               tox-env: py39-no-ext, | ||||
|               ignore-error-flake: "true", | ||||
|               command-timeout: "600000", | ||||
|             } | ||||
|     steps: | ||||
|       - name: Checkout the Repository | ||||
|         uses: actions/checkout@v2 | ||||
|         id: checkout-branch | ||||
|  | ||||
|       - name: Run Unit Tests | ||||
|         uses: harshanarayana/custom-actions@main | ||||
|         with: | ||||
|           python-version: ${{ matrix.config.python-version }} | ||||
|           test-infra-tool: tox | ||||
|           test-infra-version: latest | ||||
|           action: tests | ||||
|           test-additional-args: "-e=${{ matrix.config.tox-env }},-vv=''" | ||||
|           experimental-ignore-error: "${{ matrix.config.ignore-error-flake }}" | ||||
|           command-timeout: "${{ matrix.config.command-timeout }}" | ||||
|           test-failure-retry: "3" | ||||
							
								
								
									
										37
									
								
								.github/workflows/pr-type-check.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								.github/workflows/pr-type-check.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| name: Typing Checks | ||||
| on: | ||||
|   pull_request: | ||||
|     branches: | ||||
|       - main | ||||
|       - current-release | ||||
|       - "*LTS" | ||||
|     types: [opened, synchronize, reopened, ready_for_review] | ||||
|  | ||||
| jobs: | ||||
|   typeChecking: | ||||
|     if: github.event.pull_request.draft == false | ||||
|     name: type-check-${{ matrix.config.python-version }} | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         os: [ubuntu-latest] | ||||
|         config: | ||||
|           - { python-version: 3.8, tox-env: type-checking} | ||||
|           - { python-version: 3.9, tox-env: type-checking} | ||||
|           - { python-version: "3.10", tox-env: type-checking} | ||||
|           - { python-version: "3.11", tox-env: type-checking} | ||||
|     steps: | ||||
|       - name: Checkout the repository | ||||
|         uses: actions/checkout@v2 | ||||
|         id: checkout-branch | ||||
|  | ||||
|       - name: Run Linter Checks | ||||
|         id: linter-check | ||||
|         uses: harshanarayana/custom-actions@main | ||||
|         with: | ||||
|           python-version: ${{ matrix.config.python-version }} | ||||
|           test-infra-tool: tox | ||||
|           test-infra-version: latest | ||||
|           action: tests | ||||
|           test-additional-args: "-e=${{ matrix.config.tox-env }}" | ||||
							
								
								
									
										38
									
								
								.github/workflows/pr-windows.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								.github/workflows/pr-windows.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| name: Run Unit Tests on Windows | ||||
| on: | ||||
|   pull_request: | ||||
|     branches: | ||||
|       - main | ||||
|       - current-release | ||||
|       - "*LTS" | ||||
|     types: [opened, synchronize, reopened, ready_for_review] | ||||
|  | ||||
| jobs: | ||||
|   testsOnWindows: | ||||
|     if: github.event.pull_request.draft == false | ||||
|     name: ut-${{ matrix.config.tox-env }} | ||||
|     runs-on: windows-latest | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         config: | ||||
|           - { python-version: 3.8, tox-env: py38-no-ext } | ||||
|           - { python-version: 3.9, tox-env: py39-no-ext } | ||||
|           - { python-version: "3.10", tox-env: py310-no-ext } | ||||
|           - { python-version: "3.11", tox-env: py310-no-ext } | ||||
|  | ||||
|     steps: | ||||
|       - name: Checkout Repository | ||||
|         uses: actions/checkout@v2 | ||||
|  | ||||
|       - name: Run Unit Tests | ||||
|         uses: ahopkins/custom-actions@pip-extra-args | ||||
|         with: | ||||
|           python-version: ${{ matrix.config.python-version }} | ||||
|           test-infra-tool: tox | ||||
|           test-infra-version: latest | ||||
|           action: tests | ||||
|           test-additional-args: "-e=${{ matrix.config.tox-env }}" | ||||
|           experimental-ignore-error: "true" | ||||
|           command-timeout: "600000" | ||||
|           pip-extra-args: "--user" | ||||
							
								
								
									
										48
									
								
								.github/workflows/publish-images.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								.github/workflows/publish-images.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| name: Publish Docker Images | ||||
| on: | ||||
|   workflow_run: | ||||
|     workflows: | ||||
|       - 'Publish Artifacts' | ||||
|     types: | ||||
|       - completed | ||||
|  | ||||
| jobs: | ||||
|   publishDockerImages: | ||||
|     name: Docker Image Build [${{ matrix.python-version }}] | ||||
|     runs-on: ubuntu-latest | ||||
|  | ||||
|     strategy: | ||||
|       fail-fast: true | ||||
|       matrix: | ||||
|         python-version: ["3.8", "3.9", "3.10", "3.11"] | ||||
|  | ||||
|     steps: | ||||
|       - name: Checkout repository | ||||
|         uses: actions/checkout@v2 | ||||
|  | ||||
|       - name: Build Latest Base images for ${{ matrix.python-version }} | ||||
|         uses: harshanarayana/custom-actions@main | ||||
|         with: | ||||
|           docker-image-base-name: sanicframework/sanic-build | ||||
|           ignore-python-setup: 'true' | ||||
|           dockerfile-base-dir: './docker' | ||||
|           action: 'image-publish' | ||||
|           docker-image-tag: "${{ matrix.python-version }}" | ||||
|           docker-file-suffix: "base" | ||||
|           docker-build-args: "PYTHON_VERSION=${{ matrix.python-version }}" | ||||
|           registry-auth-user: ${{ secrets.DOCKER_ACCESS_USER }} | ||||
|           registry-auth-password: ${{ secrets.DOCKER_ACCESS_TOKEN }} | ||||
|           push-images: 'true' | ||||
|  | ||||
|       - name: Publish Sanic Docker Image for ${{ matrix.python-version }} | ||||
|         uses: harshanarayana/custom-actions@main | ||||
|         with: | ||||
|           docker-image-base-name: sanicframework/sanic | ||||
|           ignore-python-setup: 'true' | ||||
|           dockerfile-base-dir: './docker' | ||||
|           action: 'image-publish' | ||||
|           docker-build-args: "BASE_IMAGE_TAG=${{ matrix.python-version }}" | ||||
|           docker-image-prefix: "${{ matrix.python-version }}" | ||||
|           registry-auth-user: ${{ secrets.DOCKER_ACCESS_USER }} | ||||
|           registry-auth-password: ${{ secrets.DOCKER_ACCESS_TOKEN }} | ||||
|           push-images: 'true' | ||||
							
								
								
									
										39
									
								
								.github/workflows/publish-package.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								.github/workflows/publish-package.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| name: Upload Python Package | ||||
|  | ||||
| on: | ||||
|   release: | ||||
|     types: [created] | ||||
|   workflow_dispatch: | ||||
| jobs: | ||||
|   build-n-publish: | ||||
|     name: Build and publish Python 🐍 distributions 📦 to PyPI and TestPyPI | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|     - uses: actions/checkout@v3 | ||||
|     - name: Set up Python | ||||
|       uses: actions/setup-python@v4 | ||||
|       with: | ||||
|         python-version: "3.x" | ||||
|     - name: Install pypa/build | ||||
|       run: >- | ||||
|         python3 -m | ||||
|         pip install | ||||
|         build | ||||
|         --user | ||||
|     - name: Build a binary wheel and a source tarball | ||||
|       run: >- | ||||
|         python3 -m | ||||
|         build | ||||
|         --sdist | ||||
|         --wheel | ||||
|         --outdir dist/ | ||||
|         . | ||||
|     # - name: Publish distribution 📦 to Test PyPI | ||||
|     #   uses: pypa/gh-action-pypi-publish@release/v1 | ||||
|     #   with: | ||||
|     #     password: ${{ secrets.SANIC_TEST_PYPI_API_TOKEN }} | ||||
|     #     repository-url: https://test.pypi.org/legacy/ | ||||
|     - name: Publish distribution 📦 to PyPI | ||||
|       uses: pypa/gh-action-pypi-publish@release/v1 | ||||
|       with: | ||||
|         password: ${{ secrets.SANIC_PYPI_API_TOKEN }} | ||||
							
								
								
									
										174
									
								
								.github/workflows/publish-release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										174
									
								
								.github/workflows/publish-release.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,174 +0,0 @@ | ||||
| name: Publish release | ||||
|  | ||||
| on: | ||||
|   release: | ||||
|     types: [created] | ||||
|  | ||||
| env: | ||||
|   IS_TEST: false | ||||
|   DOCKER_ORG_NAME: sanicframework | ||||
|   DOCKER_IMAGE_NAME: sanic | ||||
|   DOCKER_BASE_IMAGE_NAME: sanic-build | ||||
|   DOCKER_IMAGE_DOCKERFILE: ./docker/Dockerfile | ||||
|   DOCKER_BASE_IMAGE_DOCKERFILE: ./docker/Dockerfile-base | ||||
|  | ||||
| jobs: | ||||
|   generate_info: | ||||
|     name: Generate info | ||||
|     runs-on: ubuntu-latest | ||||
|     outputs: | ||||
|       docker-tags: ${{ steps.generate_docker_info.outputs.tags }} | ||||
|       pypi-version: ${{ steps.parse_version_tag.outputs.pypi-version }} | ||||
|     steps: | ||||
|       - name: Parse version tag | ||||
|         id: parse_version_tag | ||||
|         env: | ||||
|           TAG_NAME: ${{ github.event.release.tag_name }} | ||||
|         run: | | ||||
|           tag_name="${{ env.TAG_NAME }}" | ||||
|  | ||||
|           if [[ ! "${tag_name}" =~ ^v([0-9]{2})\.([0-9]{1,2})\.([0-9]+)$ ]]; then | ||||
|             echo "::error::Tag name must be in the format vYY.MM.MICRO" | ||||
|             exit 1 | ||||
|           fi | ||||
|  | ||||
|           year_output="year=${BASH_REMATCH[1]}" | ||||
|           month_output="month=${BASH_REMATCH[2]}" | ||||
|           pypi_output="pypi-version=${tag_name#v}" | ||||
|  | ||||
|           echo "${year_output}" | ||||
|           echo "${month_output}" | ||||
|           echo "${pypi_output}" | ||||
|  | ||||
|           echo "${year_output}" >> $GITHUB_OUTPUT | ||||
|           echo "${month_output}" >> $GITHUB_OUTPUT | ||||
|           echo "${pypi_output}" >> $GITHUB_OUTPUT | ||||
|  | ||||
|       - name: Get latest release | ||||
|         id: get_latest_release | ||||
|         run: | | ||||
|           latest_tag=$( | ||||
|             curl -L \ | ||||
|               -H "Accept: application/vnd.github+json" \ | ||||
|               -H "Authorization: Bearer ${{ github.token }}" \ | ||||
|               -H "X-GitHub-Api-Version: 2022-11-28" \ | ||||
|               https://api.github.com/repos/${{ github.repository }}/releases/latest \ | ||||
|               | jq -r '.tag_name' | ||||
|           ) | ||||
|           echo "latest_tag=$latest_tag" >> $GITHUB_OUTPUT | ||||
|  | ||||
|       - name: Generate Docker info | ||||
|         id: generate_docker_info | ||||
|         run: | | ||||
|           tag_year="${{ steps.parse_version_tag.outputs.year }}" | ||||
|           tag_month="${{ steps.parse_version_tag.outputs.month }}" | ||||
|           latest_tag="${{ steps.get_latest_release.outputs.latest_tag }}" | ||||
|           tag="${{ github.event.release.tag_name }}" | ||||
|  | ||||
|           tags="${tag_year}.${tag_month}" | ||||
|  | ||||
|           if [[ "${tag_month}" == "12" ]]; then | ||||
|             tags+=",LTS" | ||||
|             echo "::notice::Tag ${tag} is LTS version" | ||||
|           else | ||||
|             echo "::notice::Tag ${tag} is not LTS version" | ||||
|           fi | ||||
|  | ||||
|           if [[ "${latest_tag}" == "${{ github.event.release.tag_name }}" ]]; then | ||||
|             tags+=",latest" | ||||
|             echo "::notice::Tag ${tag} is marked as latest" | ||||
|           else | ||||
|             echo "::notice::Tag ${tag} is not marked as latest" | ||||
|           fi | ||||
|  | ||||
|           tags_output="tags=${tags}" | ||||
|  | ||||
|           echo "${tags_output}" | ||||
|           echo "${tags_output}" >> $GITHUB_OUTPUT | ||||
|  | ||||
|   publish_package: | ||||
|     name: Build and publish package | ||||
|     runs-on: ubuntu-latest | ||||
|     needs: generate_info | ||||
|     steps: | ||||
|     - name: Checkout repo | ||||
|       uses: actions/checkout@v3 | ||||
|  | ||||
|     - name: Setup Python | ||||
|       uses: actions/setup-python@v4 | ||||
|       with: | ||||
|         python-version: "3.11" | ||||
|  | ||||
|     - name: Install dependencies | ||||
|       run: pip install build twine | ||||
|  | ||||
|     - name: Update package version | ||||
|       run: | | ||||
|         echo "__version__ = \"${{ needs.generate_info.outputs.pypi-version }}\"" > sanic/__version__.py | ||||
|  | ||||
|     - name: Build a binary wheel and a source tarball | ||||
|       run: python -m build --sdist --wheel --outdir dist/ . | ||||
|  | ||||
|     - name: Publish to PyPi 🚀 | ||||
|       run: twine upload --non-interactive --disable-progress-bar dist/* | ||||
|       env: | ||||
|         TWINE_USERNAME: __token__ | ||||
|         TWINE_PASSWORD: ${{ env.IS_TEST == 'true' && secrets.SANIC_TEST_PYPI_API_TOKEN || secrets.SANIC_PYPI_API_TOKEN }} | ||||
|         TWINE_REPOSITORY: ${{ env.IS_TEST == 'true' && 'testpypi' || 'pypi' }} | ||||
|  | ||||
|   publish_docker: | ||||
|     name: Publish Docker / Python ${{ matrix.python-version }} | ||||
|     needs: [generate_info, publish_package] | ||||
|     runs-on: ubuntu-latest | ||||
|     strategy: | ||||
|       fail-fast: true | ||||
|       matrix: | ||||
|         python-version: ["3.10", "3.11"] | ||||
|     steps: | ||||
|       - name: Checkout repository | ||||
|         uses: actions/checkout@v3 | ||||
|  | ||||
|       - name: Set up Docker Buildx | ||||
|         uses: docker/setup-buildx-action@v2 | ||||
|  | ||||
|       - name: Login to Docker Hub | ||||
|         uses: docker/login-action@v2 | ||||
|         with: | ||||
|           username: ${{ secrets.DOCKER_ACCESS_USER }} | ||||
|           password: ${{ secrets.DOCKER_ACCESS_TOKEN }} | ||||
|  | ||||
|       - name: Build and push base image | ||||
|         uses: docker/build-push-action@v4 | ||||
|         with: | ||||
|           push: ${{ env.IS_TEST == 'false' }} | ||||
|           file: ${{ env.DOCKER_BASE_IMAGE_DOCKERFILE }} | ||||
|           tags: ${{ env.DOCKER_ORG_NAME }}/${{ env.DOCKER_BASE_IMAGE_NAME }}:${{ matrix.python-version }} | ||||
|           build-args: | | ||||
|             PYTHON_VERSION=${{ matrix.python-version }} | ||||
|  | ||||
|       - name: Parse tags for this Python version | ||||
|         id: parse_tags | ||||
|         run: | | ||||
|           IFS=',' read -ra tags <<< "${{ needs.generate_info.outputs.docker-tags }}" | ||||
|           tag_args="" | ||||
|  | ||||
|           for tag in "${tags[@]}"; do | ||||
|               tag_args+=",${{ env.DOCKER_ORG_NAME }}/${{ env.DOCKER_IMAGE_NAME }}:${tag}-py${{ matrix.python-version }}" | ||||
|           done | ||||
|  | ||||
|           tag_args_output="tag_args=${tag_args:1}" | ||||
|  | ||||
|           echo "${tag_args_output}" | ||||
|           echo "${tag_args_output}" >> $GITHUB_OUTPUT | ||||
|  | ||||
|       - name: Build and push Sanic image | ||||
|         uses: docker/build-push-action@v4 | ||||
|         with: | ||||
|           push: ${{ env.IS_TEST == 'false' }} | ||||
|           file: ${{ env.DOCKER_IMAGE_DOCKERFILE }} | ||||
|           tags: ${{ steps.parse_tags.outputs.tag_args }} | ||||
|           build-args: | | ||||
|             BASE_IMAGE_ORG=${{ env.DOCKER_ORG_NAME }} | ||||
|             BASE_IMAGE_NAME=${{ env.DOCKER_BASE_IMAGE_NAME }} | ||||
|             BASE_IMAGE_TAG=${{ matrix.python-version }} | ||||
|             SANIC_PYPI_VERSION=${{ needs.generate_info.outputs.pypi-version }} | ||||
							
								
								
									
										56
									
								
								.github/workflows/tests.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										56
									
								
								.github/workflows/tests.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,56 +0,0 @@ | ||||
| name: Tests | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - main | ||||
|       - current-release | ||||
|       - "*LTS" | ||||
|     tags: | ||||
|       - "!*" | ||||
|   pull_request: | ||||
|     branches: | ||||
|       - main | ||||
|       - current-release | ||||
|       - "*LTS" | ||||
|     types: [opened, synchronize, reopened, ready_for_review] | ||||
|  | ||||
| jobs: | ||||
|   run_tests: | ||||
|     name: "${{ matrix.config.platform == 'windows-latest' && 'Windows' || 'Linux' }} / Python ${{ matrix.config.python-version }} / tox -e ${{ matrix.config.tox-env }}" | ||||
|     if: github.event.pull_request.draft == false | ||||
|     runs-on: ${{ matrix.config.platform || 'ubuntu-latest' }} | ||||
|     strategy: | ||||
|       fail-fast: true | ||||
|       matrix: | ||||
|         config: | ||||
|           - { python-version: "3.8",  tox-env: security } | ||||
|           - { python-version: "3.9",  tox-env: security } | ||||
|           - { python-version: "3.10", tox-env: security } | ||||
|           - { python-version: "3.11", tox-env: security } | ||||
|           - { python-version: "3.10", tox-env: lint } | ||||
|           - { python-version: "3.10", tox-env: docs } | ||||
|           - { python-version: "3.8",  tox-env: type-checking } | ||||
|           - { python-version: "3.9",  tox-env: type-checking } | ||||
|           - { python-version: "3.10", tox-env: type-checking } | ||||
|           - { python-version: "3.11", tox-env: type-checking } | ||||
|           - { python-version: "3.8",  tox-env: py38,          max-attempts: 3 } | ||||
|           - { python-version: "3.8",  tox-env: py38-no-ext,   max-attempts: 3 } | ||||
|           - { python-version: "3.9",  tox-env: py39,          max-attempts: 3 } | ||||
|           - { python-version: "3.9",  tox-env: py39-no-ext,   max-attempts: 3 } | ||||
|           - { python-version: "3.10", tox-env: py310,         max-attempts: 3 } | ||||
|           - { python-version: "3.10", tox-env: py310-no-ext,  max-attempts: 3 } | ||||
|           - { python-version: "3.11", tox-env: py311,         max-attempts: 3 } | ||||
|           - { python-version: "3.11", tox-env: py311-no-ext,  max-attempts: 3 } | ||||
|           - { python-version: "3.8",  tox-env: py38-no-ext,   platform: windows-latest, ignore-errors: true } | ||||
|           - { python-version: "3.9",  tox-env: py39-no-ext,   platform: windows-latest, ignore-errors: true } | ||||
|           - { python-version: "3.10", tox-env: py310-no-ext,  platform: windows-latest, ignore-errors: true } | ||||
|           - { python-version: "3.11", tox-env: py310-no-ext,  platform: windows-latest, ignore-errors: true } | ||||
|     steps: | ||||
|       - name: Run tests | ||||
|         uses: sanic-org/simple-tox-action@v1 | ||||
|         with: | ||||
|           python-version: ${{ matrix.config.python-version }} | ||||
|           tox-env: ${{ matrix.config.tox-env }} | ||||
|           max-attempts: ${{ matrix.config.max-attempts || 1 }} | ||||
|           ignore-errors: ${{ matrix.config.ignore-errors || false }} | ||||
							
								
								
									
										10
									
								
								README.rst
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								README.rst
									
									
									
									
									
								
							| @@ -11,7 +11,7 @@ Sanic | Build fast. Run fast. | ||||
|     :stub-columns: 1 | ||||
|  | ||||
|     * - Build | ||||
|       - | |Tests| | ||||
|       - | |Py310Test| |Py39Test| |Py38Test| | ||||
|     * - Docs | ||||
|       - | |UserGuide| |Documentation| | ||||
|     * - Package | ||||
| @@ -27,8 +27,12 @@ Sanic | Build fast. Run fast. | ||||
|    :target: https://community.sanicframework.org/ | ||||
| .. |Discord| image:: https://img.shields.io/discord/812221182594121728?logo=discord | ||||
|    :target: https://discord.gg/FARQzAEMAA | ||||
| .. |Tests| image:: https://github.com/sanic-org/sanic/actions/workflows/tests.yml/badge.svg?branch=main | ||||
|    :target: https://github.com/sanic-org/sanic/actions/workflows/tests.yml | ||||
| .. |Py310Test| image:: https://github.com/sanic-org/sanic/actions/workflows/pr-python310.yml/badge.svg?branch=main | ||||
|    :target: https://github.com/sanic-org/sanic/actions/workflows/pr-python310.yml | ||||
| .. |Py39Test| image:: https://github.com/sanic-org/sanic/actions/workflows/pr-python39.yml/badge.svg?branch=main | ||||
|    :target: https://github.com/sanic-org/sanic/actions/workflows/pr-python39.yml | ||||
| .. |Py38Test| image:: https://github.com/sanic-org/sanic/actions/workflows/pr-python38.yml/badge.svg?branch=main | ||||
|    :target: https://github.com/sanic-org/sanic/actions/workflows/pr-python38.yml | ||||
| .. |Documentation| image:: https://readthedocs.org/projects/sanic/badge/?version=latest | ||||
|    :target: http://sanic.readthedocs.io/en/latest/?badge=latest | ||||
| .. |PyPI| image:: https://img.shields.io/pypi/v/sanic.svg | ||||
|   | ||||
| @@ -1,13 +1,9 @@ | ||||
| ARG BASE_IMAGE_ORG | ||||
| ARG BASE_IMAGE_NAME | ||||
| ARG BASE_IMAGE_TAG | ||||
|  | ||||
| FROM ${BASE_IMAGE_ORG}/${BASE_IMAGE_NAME}:${BASE_IMAGE_TAG} | ||||
| FROM sanicframework/sanic-build:${BASE_IMAGE_TAG} | ||||
|  | ||||
| RUN apk update | ||||
| RUN update-ca-certificates | ||||
|  | ||||
| ARG SANIC_PYPI_VERSION | ||||
|  | ||||
| RUN pip install -U pip && pip install sanic==${SANIC_PYPI_VERSION} | ||||
| RUN pip install sanic | ||||
| RUN apk del build-base | ||||
|   | ||||
							
								
								
									
										16
									
								
								sanic/app.py
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								sanic/app.py
									
									
									
									
									
								
							| @@ -5,7 +5,6 @@ import logging | ||||
| import logging.config | ||||
| import re | ||||
| import sys | ||||
|  | ||||
| from asyncio import ( | ||||
|     AbstractEventLoop, | ||||
|     CancelledError, | ||||
| @@ -94,7 +93,6 @@ from sanic.worker.inspector import Inspector | ||||
| from sanic.worker.loader import CertLoader | ||||
| from sanic.worker.manager import WorkerManager | ||||
|  | ||||
|  | ||||
| if TYPE_CHECKING: | ||||
|     try: | ||||
|         from sanic_ext import Extend  # type: ignore | ||||
| @@ -1743,6 +1741,20 @@ class Sanic( | ||||
|         if hasattr(self, "multiplexer"): | ||||
|             self.multiplexer.ack() | ||||
|  | ||||
|     def set_serving(self, serving: bool) -> None: | ||||
|         """Set the serving state of the application. | ||||
|  | ||||
|         This method is used to set the serving state of the application. | ||||
|         It is used internally by Sanic and should not typically be called | ||||
|         manually. | ||||
|  | ||||
|         Args: | ||||
|             serving (bool): Whether the application is serving. | ||||
|         """ | ||||
|         self.state.is_running = serving | ||||
|         if hasattr(self, "multiplexer"): | ||||
|             self.multiplexer.set_serving(serving) | ||||
|  | ||||
|     async def _server_event( | ||||
|         self, | ||||
|         concern: str, | ||||
|   | ||||
| @@ -3,7 +3,6 @@ from __future__ import annotations | ||||
| import os | ||||
| import platform | ||||
| import sys | ||||
|  | ||||
| from asyncio import ( | ||||
|     AbstractEventLoop, | ||||
|     CancelledError, | ||||
| @@ -49,7 +48,7 @@ from sanic.application.motd import MOTD | ||||
| from sanic.application.state import ApplicationServerInfo, Mode, ServerStage | ||||
| from sanic.base.meta import SanicMeta | ||||
| from sanic.compat import OS_IS_WINDOWS, StartMethod | ||||
| from sanic.exceptions import SanicException, ServerKilled | ||||
| from sanic.exceptions import ServerKilled | ||||
| from sanic.helpers import Default, _default, is_atty | ||||
| from sanic.http.constants import HTTP | ||||
| from sanic.http.tls import get_ssl_context, process_to_context | ||||
| @@ -65,13 +64,13 @@ from sanic.server.protocols.http_protocol import HttpProtocol | ||||
| from sanic.server.protocols.websocket_protocol import WebSocketProtocol | ||||
| from sanic.server.runners import serve | ||||
| from sanic.server.socket import configure_socket, remove_unix_socket | ||||
| from sanic.worker.constants import ProcessState | ||||
| from sanic.worker.loader import AppLoader | ||||
| from sanic.worker.manager import WorkerManager | ||||
| from sanic.worker.multiplexer import WorkerMultiplexer | ||||
| from sanic.worker.reloader import Reloader | ||||
| from sanic.worker.serve import worker_serve | ||||
|  | ||||
|  | ||||
| if TYPE_CHECKING: | ||||
|     from sanic import Sanic | ||||
|     from sanic.application.state import ApplicationState | ||||
| @@ -880,18 +879,12 @@ class StartupMixin(metaclass=SanicMeta): | ||||
|             manager.run() | ||||
|         except ServerKilled: | ||||
|             exit_code = 1 | ||||
|         except SanicException as e: | ||||
|             exit_code = 1 | ||||
|             kwargs = primary_server_info.settings | ||||
|             if e.quiet: | ||||
|                 error_logger.error(str(e)) | ||||
|             else: | ||||
|                 raise | ||||
|         except BaseException: | ||||
|             kwargs = primary_server_info.settings | ||||
|             error_logger.exception( | ||||
|                 "Experienced exception while trying to serve" | ||||
|             ) | ||||
|             raise | ||||
|         finally: | ||||
|             logger.info("Server Stopped") | ||||
|             for app in apps: | ||||
| @@ -899,7 +892,6 @@ class StartupMixin(metaclass=SanicMeta): | ||||
|                 app.router.reset() | ||||
|                 app.signal_router.reset() | ||||
|  | ||||
|             sync_manager.shutdown() | ||||
|             for sock in socks: | ||||
|                 try: | ||||
|                     sock.shutdown(SHUT_RDWR) | ||||
| @@ -911,12 +903,33 @@ class StartupMixin(metaclass=SanicMeta): | ||||
|             loop.close() | ||||
|             cls._cleanup_env_vars() | ||||
|             cls._cleanup_apps() | ||||
|  | ||||
|             from time import sleep | ||||
|  | ||||
|             limit = 100 | ||||
|             while cls._get_process_states(worker_state): | ||||
|                 sleep(0.1) | ||||
|                 limit -= 1 | ||||
|                 if limit <= 0: | ||||
|                     error_logger.warning( | ||||
|                         "Worker shutdown timed out. " | ||||
|                         "Some processes may still be running." | ||||
|                     ) | ||||
|                     break | ||||
|             sync_manager.shutdown() | ||||
|             unix = kwargs.get("unix") | ||||
|             if unix: | ||||
|                 remove_unix_socket(unix) | ||||
|             logger.info("Goodbye.") | ||||
|         if exit_code: | ||||
|             os._exit(exit_code) | ||||
|  | ||||
|     @staticmethod | ||||
|     def _get_process_states(worker_state) -> List[str]: | ||||
|         return [ | ||||
|             state for s in worker_state.values() if (state := s.get("state")) | ||||
|         ] | ||||
|  | ||||
|     @classmethod | ||||
|     def serve_single(cls, primary: Optional[Sanic] = None) -> None: | ||||
|         os.environ["SANIC_MOTD_OUTPUT"] = "true" | ||||
|   | ||||
| @@ -122,17 +122,15 @@ def _setup_system_signals( | ||||
|     register_sys_signals: bool, | ||||
|     loop: asyncio.AbstractEventLoop, | ||||
| ) -> None:  # no cov | ||||
|     # Ignore SIGINT when run_multiple | ||||
|     if run_multiple: | ||||
|     signal_func(SIGINT, SIG_IGN) | ||||
|     signal_func(SIGTERM, SIG_IGN) | ||||
|     os.environ["SANIC_WORKER_PROCESS"] = "true" | ||||
|  | ||||
|     # Register signals for graceful termination | ||||
|     if register_sys_signals: | ||||
|         if OS_IS_WINDOWS: | ||||
|             ctrlc_workaround_for_windows(app) | ||||
|         else: | ||||
|             for _signal in [SIGTERM] if run_multiple else [SIGINT, SIGTERM]: | ||||
|             for _signal in [SIGINT, SIGTERM]: | ||||
|                 loop.add_signal_handler( | ||||
|                     _signal, partial(app.stop, terminate=False) | ||||
|                 ) | ||||
| @@ -143,8 +141,6 @@ def _run_server_forever(loop, before_stop, after_stop, cleanup, unix): | ||||
|     try: | ||||
|         server_logger.info("Starting worker [%s]", pid) | ||||
|         loop.run_forever() | ||||
|     except KeyboardInterrupt: | ||||
|         pass | ||||
|     finally: | ||||
|         server_logger.info("Stopping worker [%s]", pid) | ||||
|  | ||||
| @@ -156,6 +152,7 @@ def _run_server_forever(loop, before_stop, after_stop, cleanup, unix): | ||||
|         loop.run_until_complete(after_stop()) | ||||
|         remove_unix_socket(unix) | ||||
|         loop.close() | ||||
|         server_logger.info("Worker complete [%s]", pid) | ||||
|  | ||||
|  | ||||
| def _serve_http_1( | ||||
| @@ -259,8 +256,11 @@ def _serve_http_1( | ||||
|             else: | ||||
|                 conn.abort() | ||||
|  | ||||
|         app.set_serving(False) | ||||
|  | ||||
|     _setup_system_signals(app, run_multiple, register_sys_signals, loop) | ||||
|     loop.run_until_complete(app._server_event("init", "after")) | ||||
|     app.set_serving(True) | ||||
|     _run_server_forever( | ||||
|         loop, | ||||
|         partial(app._server_event, "shutdown", "before"), | ||||
|   | ||||
| @@ -47,10 +47,10 @@ def bind_unix_socket(path: str, *, mode=0o666, backlog=100) -> socket.socket: | ||||
|     path = os.path.abspath(path) | ||||
|     folder = os.path.dirname(path) | ||||
|     if not os.path.isdir(folder): | ||||
|         raise FileNotFoundError("Socket folder does not exist") | ||||
|         raise FileNotFoundError(f"Socket folder does not exist: {folder}") | ||||
|     try: | ||||
|         if not stat.S_ISSOCK(os.stat(path, follow_symlinks=False).st_mode): | ||||
|             raise FileExistsError("Existing file is not a socket") | ||||
|             raise FileExistsError(f"Existing file is not a socket: {path}") | ||||
|     except FileNotFoundError: | ||||
|         pass | ||||
|     # Create new socket with a random temporary name | ||||
| @@ -103,10 +103,7 @@ def configure_socket( | ||||
|     unix = server_settings["unix"] | ||||
|     backlog = server_settings["backlog"] | ||||
|     if unix: | ||||
|         try: | ||||
|         sock = bind_unix_socket(unix, backlog=backlog) | ||||
|         except OSError as e: | ||||
|             raise ServerError(f"Error binding {unix}: {e}", quiet=True) | ||||
|         server_settings["unix"] = unix | ||||
|     if sock is None: | ||||
|         try: | ||||
| @@ -115,17 +112,6 @@ def configure_socket( | ||||
|                 server_settings["port"], | ||||
|                 backlog=backlog, | ||||
|             ) | ||||
|         except PermissionError: | ||||
|             p = server_settings["port"] | ||||
|             if not p or p >= 1024: | ||||
|                 raise | ||||
|             addr = f"{server_settings['host']}:{p}" | ||||
|             error = ServerError( | ||||
|                 f"Permission denied binding to {addr}.\n\n" | ||||
|                 "Use `sudo sanic` to run on a privileged port.\n" | ||||
|             ) | ||||
|             error.quiet = True | ||||
|             raise error | ||||
|         except OSError as e:  # no cov | ||||
|             error = ServerError( | ||||
|                 f"Sanic server could not start: {e}.\n\n" | ||||
|   | ||||
| @@ -532,11 +532,12 @@ class WebsocketImplProtocol: | ||||
|             raise WebsocketClosed( | ||||
|                 "Cannot receive from websocket interface after it is closed." | ||||
|             ) | ||||
|         assembler_get: Optional[asyncio.Task] = None | ||||
|         try: | ||||
|             self.recv_cancel = asyncio.Future() | ||||
|             assembler_get = asyncio.create_task(self.assembler.get(timeout)) | ||||
|             tasks = (self.recv_cancel, assembler_get) | ||||
|             tasks = ( | ||||
|                 self.recv_cancel, | ||||
|                 asyncio.ensure_future(self.assembler.get(timeout)), | ||||
|             ) | ||||
|             done, pending = await asyncio.wait( | ||||
|                 tasks, | ||||
|                 return_when=asyncio.FIRST_COMPLETED, | ||||
| @@ -550,11 +551,6 @@ class WebsocketImplProtocol: | ||||
|             else: | ||||
|                 self.recv_cancel.cancel() | ||||
|                 return done_task.result() | ||||
|         except asyncio.CancelledError: | ||||
|             # recv was cancelled | ||||
|             if assembler_get: | ||||
|                 assembler_get.cancel() | ||||
|             raise | ||||
|         finally: | ||||
|             self.recv_cancel = None | ||||
|             self.recv_lock.release() | ||||
| @@ -588,15 +584,16 @@ class WebsocketImplProtocol: | ||||
|                 "Cannot receive from websocket interface after it is closed." | ||||
|             ) | ||||
|         messages = [] | ||||
|         assembler_get: Optional[asyncio.Task] = None | ||||
|         try: | ||||
|             # Prevent pausing the transport when we're | ||||
|             # receiving a burst of messages | ||||
|             self.can_pause = False | ||||
|             self.recv_cancel = asyncio.Future() | ||||
|             while True: | ||||
|                 assembler_get = asyncio.create_task(self.assembler.get(0)) | ||||
|                 tasks = (self.recv_cancel, assembler_get) | ||||
|                 tasks = ( | ||||
|                     self.recv_cancel, | ||||
|                     asyncio.ensure_future(self.assembler.get(timeout=0)), | ||||
|                 ) | ||||
|                 done, pending = await asyncio.wait( | ||||
|                     tasks, | ||||
|                     return_when=asyncio.FIRST_COMPLETED, | ||||
| @@ -619,11 +616,6 @@ class WebsocketImplProtocol: | ||||
|                 # next message to pass into the Assembler | ||||
|                 await asyncio.sleep(0) | ||||
|             self.recv_cancel.cancel() | ||||
|         except asyncio.CancelledError: | ||||
|             # recv_burst was cancelled | ||||
|             if assembler_get: | ||||
|                 assembler_get.cancel() | ||||
|             raise | ||||
|         finally: | ||||
|             self.recv_cancel = None | ||||
|             self.can_pause = True | ||||
|   | ||||
| @@ -122,6 +122,7 @@ class WorkerManager: | ||||
|         self.monitor() | ||||
|         self.join() | ||||
|         self.terminate() | ||||
|         self.cleanup() | ||||
|  | ||||
|     def start(self): | ||||
|         for process in self.processes: | ||||
| @@ -147,6 +148,11 @@ class WorkerManager: | ||||
|             for process in self.processes: | ||||
|                 process.terminate() | ||||
|  | ||||
|     def cleanup(self): | ||||
|         """Cleanup the worker processes.""" | ||||
|         for process in self.processes: | ||||
|             process.exit() | ||||
|  | ||||
|     def restart( | ||||
|         self, | ||||
|         process_names: Optional[List[str]] = None, | ||||
|   | ||||
| @@ -28,6 +28,24 @@ class WorkerMultiplexer: | ||||
|             "state": ProcessState.ACKED.name, | ||||
|         } | ||||
|  | ||||
|     def set_serving(self, serving: bool) -> None: | ||||
|         """Set the worker to serving. | ||||
|  | ||||
|         Args: | ||||
|             serving (bool): Whether the worker is serving. | ||||
|         """ | ||||
|         self._state._state[self.name] = { | ||||
|             **self._state._state[self.name], | ||||
|             "serving": serving, | ||||
|         } | ||||
|  | ||||
|     def exit(self): | ||||
|         """Run cleanup at worker exit.""" | ||||
|         try: | ||||
|             del self._state._state[self.name] | ||||
|         except ConnectionRefusedError: | ||||
|             logger.debug("Monitor process has already exited.") | ||||
|  | ||||
|     def restart( | ||||
|         self, | ||||
|         name: str = "", | ||||
|   | ||||
| @@ -65,6 +65,20 @@ class WorkerProcess: | ||||
|         self.set_state(ProcessState.JOINED) | ||||
|         self._current_process.join() | ||||
|  | ||||
|     def exit(self): | ||||
|         limit = 100 | ||||
|         while self.is_alive() and limit > 0: | ||||
|             sleep(0.1) | ||||
|             limit -= 1 | ||||
|  | ||||
|         if not self.is_alive(): | ||||
|             try: | ||||
|                 del self.worker_state[self.name] | ||||
|             except ConnectionRefusedError: | ||||
|                 logger.debug("Monitor process has already exited.") | ||||
|             except KeyError: | ||||
|                 logger.debug("Could not find worker state to delete.") | ||||
|  | ||||
|     def terminate(self): | ||||
|         if self.state is not ProcessState.TERMINATED: | ||||
|             logger.debug( | ||||
| @@ -77,7 +91,6 @@ class WorkerProcess: | ||||
|             self.set_state(ProcessState.TERMINATED, force=True) | ||||
|             try: | ||||
|                 os.kill(self.pid, SIGINT) | ||||
|                 del self.worker_state[self.name] | ||||
|             except (KeyError, AttributeError, ProcessLookupError): | ||||
|                 ... | ||||
|  | ||||
| @@ -118,6 +131,16 @@ class WorkerProcess: | ||||
|         except AssertionError: | ||||
|             return False | ||||
|  | ||||
|     # def _run(self, **kwargs): | ||||
|     #     atexit.register(self._exit) | ||||
|     #     self.target(**kwargs) | ||||
|  | ||||
|     # def _exit(self): | ||||
|     #     try: | ||||
|     #         del self.worker_state[self.name] | ||||
|     #     except ConnectionRefusedError: | ||||
|     #         logger.debug("Monitor process has already exited.") | ||||
|  | ||||
|     def spawn(self): | ||||
|         if self.state not in (ProcessState.IDLE, ProcessState.RESTARTING): | ||||
|             raise Exception("Cannot spawn a worker process until it is idle.") | ||||
|   | ||||
		Reference in New Issue
	
	Block a user