Gitの改行コード自動置換機能(autocrlf)を無効化する

https://stackoverflow.com/questions/21822650/disable-git-eol-conversions git config --global core.autocrlf false git add --renormalize . すでにautocrlfが適用されたファイルを元に戻すために、既存のローカルリポジトリではadd --renormalizeが必要です。 GitのCRLF自動置換機能のためにDocker Buildに失敗する例 改行コードCRLFで以下のようなDockerfileを作成すると、 # syntax=docker/dockerfile:1.4 FROM ubuntu:22.04 RUN <<EOF set -eux echo "OK" EOF 以下のようなエラーとなり、ビルドに失敗します。 ------ > [2/2] RUN <<EOF (set -eux...): #8 0.294 /bin/sh: 1: set: Illegal option - ------ executor failed running [/bin/sh -c set -eux echo "OK" ]: exit code: 2 GitのCRLF自動置換機能によって、Dockerfileの改行コードがCRLFに書き換えられることでも同じことが起きます。 Linuxの仮想化ソフトウェアであるDockerの構成ファイルにCRLFが使われることが想定されないのは理解できます。 WindowsでDockerを扱っていることは理解してください。 .gitattributesでリポジトリごとに改行コードのポリシーを変更することができますが、令和の時代に改行コードの切り替えができないテキストエディタを使うこともないと思われるので、 不要なCRLF自動置換機能を無効化する方が、たくさんのリポジトリを扱う人には向いているでしょう。

2023年4月16日 · aoirint

pyenvでPyInstallerを使えるようにする

env PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install 3.11.3 https://pyinstaller.org/en/stable/development/venv.html

2023年4月16日 · aoirint

HTTPリクエストからOriginヘッダを削除(Manifest V3 Chrome拡張, Chrome 101+)

動作環境 Google Chrome 108 Manifest V3 内容 Chrome拡張から送られるHTTPリクエストについて、 ローカルで動くHTTPサーバhttp://127.0.0.1:8000のOriginチェックを回避するため、 Originヘッダを削除します。 declarativeNetRequest機能を使用します。manifest.jsonのpermissionsにdeclarativeNetRequestWithHostAccess(Chrome 96+)の追記が必要です。 加工するHTTPリクエストを、この拡張機能から送られるHTTPリクエストに絞るため、initiatorDomainsオプション(Chrome 101+)を使用しています。将来的に、より厳密な検査ができるオプションが追加される可能性があります。 chrome.declarativeNetRequestのドキュメント: https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/ また、CORSを回避するには、manifest.jsonのhost_permissionsにhttp://127.0.0.1:8000/*を追記します。 https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/host_permissions XMLHttpRequest and fetch access to those origins without cross-origin restrictions (though not for requests from content scripts, as was the case in Manifest V2). background.js // license: CC0 chrome.declarativeNetRequest.updateDynamicRules({ removeRuleIds: [1], addRules: [ { id: 1, priority: 1, action: { type: 'modifyHeaders', requestHeaders: [ { 'header': 'Origin', 'operation': 'remove' }, ], }, condition: { urlFilter: '127.0.0.1:8000/*', initiatorDomains: [chrome.runtime.id], // chrome-extension://{extension_id} }, }, ], })

2022年12月7日 · aoirint

Python, asyncioを使った同期・非同期処理の実装例

Python 3.9.13 (pyenv) Ubuntu 20.04 (WSL2) https://github.com/aoirint/python_asyncio_examples なんかこう書くとうまく動くということしかわからん、という実装例です。 https://twitter.com/aoirint/status/1544891079786627074 基本実装 同期関数から非同期関数を同期的に呼び出す asyncio.run Details import asyncio import time def main(): async def func(): await asyncio.sleep(3) print('func exited') # 1 asyncio.run(func()) time.sleep(1) print('main exited') # 2 main() print('exited') # 3 同期関数から非同期関数を非同期的に呼び出す threading.Thread + asyncio.run Details import asyncio from concurrent.futures import ThreadPoolExecutor import threading import time def main(): async def func(): await asyncio.sleep(3) print('func exited') # 3 thread = threading.Thread(target=lambda: asyncio.run(func())) thread.start() time.sleep(1) print('main exited') # 1 main() print('exited') # 2 非同期関数から同期関数を同期的に呼び出す ふつうに呼び出す Details import asyncio import time async def main(): def func(): time.sleep(3) print('func exited') # 1 func() await asyncio.sleep(1) print('main exited') # 2 asyncio.run(main()) print('exited') # 3 非同期関数から同期関数を非同期的に呼び出す asyncio.new_event_loop + ThreadPoolExecutor + EventLoop.run_in_executor Details import asyncio from concurrent.futures import ThreadPoolExecutor import time async def main(): def func(): time.sleep(3) print('func exited') # 3 loop = asyncio.new_event_loop() executor = ThreadPoolExecutor() loop.run_in_executor(executor, func) await asyncio.sleep(1) print('main exited') # 1 asyncio.run(main()) print('exited') # 2 非同期関数から非同期関数を同期的に呼び出す awaitキーワード Details import asyncio async def main(): async def func(): await asyncio.sleep(3) print('func exited') # 1 await func() await asyncio.sleep(1) print('main exited') # 2 asyncio.run(main()) print('exited') # 3 非同期関数から非同期関数を非同期的に呼び出す threading.Thread + asyncio.run Details import asyncio import threading async def main(): async def func(): await asyncio.sleep(3) print('func exited') # 3 thread = threading.Thread(target=lambda: asyncio.run(func())) thread.start() await asyncio.sleep(1) print('main exited') # 1 asyncio.run(main()) print('exited') # 2 非同期関数から同期間数を非同期的に3つずつ呼び出す asyncio.new_event_loop + ThreadPoolExecutor + EventLoop.run_in_executor Details import asyncio from concurrent.futures import ThreadPoolExecutor import time async def main(): def func(): time.sleep(3) print('func exited') # 3 loop = asyncio.new_event_loop() executor = ThreadPoolExecutor(max_workers=3) loop.run_in_executor(executor, func) loop.run_in_executor(executor, func) loop.run_in_executor(executor, func) loop.run_in_executor(executor, func) loop.run_in_executor(executor, func) loop.run_in_executor(executor, func) loop.run_in_executor(executor, func) loop.run_in_executor(executor, func) loop.run_in_executor(executor, func) await asyncio.sleep(1) print('main exited') # 1 asyncio.run(main()) print('exited') # 2 よく見るエラー RuntimeError: Event loop is closed TBW ...

2022年7月7日 · aoirint

Django 3.xから4.xへの更新でPOSTリクエスト時にCSRF検証に失敗する

想定: 3.xで動いていたフォーム送信が4.xへの更新でCSRF検証に失敗するために動かなくなった settings.pyにCSRF_TRUSTED_ORIGINSを追加すればよい。 https://docs.djangoproject.com/en/4.0/ref/settings/#std-setting-CSRF_TRUSTED_ORIGINS Origin: e.g. https://example.com https://developer.mozilla.org/ja/docs/Glossary/Origin CSRF検証のドキュメントを3.xと比べると、以下の記述が増えている。 CsrfViewMiddleware verifies the Origin header, if provided by the browser, against the current host and the CSRF_TRUSTED_ORIGINS setting. This provides protection against cross-subdomain attacks. 4.x: https://docs.djangoproject.com/en/4.0/ref/csrf/#how-it-works 3.x: https://docs.djangoproject.com/en/3.2/ref/csrf/#how-it-works

2022年6月24日 · aoirint

GitHub ActionsでPyPIにPythonパッケージをpushする(GitHub Release連携でバージョン付け)

https://qiita.com/aoirint/items/09ea153751a65bf4876f#github-release%E4%BD%9C%E6%88%90%E6%99%82%E3%81%ABpypi%E3%81%AB%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%89 上の記事のWorkflowテンプレートをちょっと改良した。 GitHub Release作成時にリリースタグをパッケージバージョンにしてpush 構成 mypackage/__init__.pyに以下のように開発用のバージョン情報を記述する。 リリース時にGithub Actionsでリリースタグに置換してからPyPIにpushする。 __VERSION__ = '0.0.0' GitHub Secrets PYPI_API_TOKEN GitHub Workflow .github/workflows/pypi.yml name: Publish a package to PyPI on: release: types: - created env: VERSION: ${{ github.event.release.tag_name != '' && github.event.release.tag_name || '0.0.0' }} jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Setup Python uses: actions/setup-python@v2 with: python-version: 3.x - name: Install Dependencies run: | pip3 install -r requirements.txt pip3 install wheel - name: Replace version run: | sed -i "s/__VERSION__ = '0.0.0'/__VERSION__ = '${{ env.VERSION }}'/" mypackage/__init__.py - name: Build Package run: python3 setup.py sdist bdist_wheel - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: user: __token__ password: ${{ secrets.PYPI_API_TOKEN }}

2022年6月24日 · aoirint

GitHub ActionsでDocker RegistryにDockerイメージをpushする(latestタグ、GitHub Release連携でバージョン付け)

https://blog.aoirint.com/entry/2021/github_actions_docker_io_token/ 上の記事のWorkflowテンプレートをちょっと改良した。 Docker Hub以外のDockerレジストリに対応 GitHub Release作成時にリリースタグをイメージタグにしてpush レジストリURL Docker Hub: docker.io GitHub Container Registry: ghcr.io GitLab Container Registry: registry.gitlab.com GitHub Secrets DOCKER_USERNAME DOCKER_TOKEN GitHub Workflow .github/workflows/docker.yml https://github.com/docker/login-action https://github.com/docker/build-push-action name: Push to Docker registry on: push: branches: - main release: types: - created env: IMAGE_NAME: docker.io/username/imagename IMAGE_TAG: ${{ github.event.release.tag_name != '' && github.event.release.tag_name || 'latest' }} jobs: push: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Setup Docker Buildx id: buildx uses: docker/setup-buildx-action@v2 - name: Login to Docker Registry uses: docker/login-action@v2 with: registry: docker.io username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_TOKEN }} - name: Build and Deploy Docker image uses: docker/build-push-action@v3 env: IMAGE_NAME_AND_TAG: ${{ format('{0}:{1}', env.IMAGE_NAME, env.IMAGE_TAG) }} with: context: . builder: ${{ steps.buildx.outputs.name }} file: ./Dockerfile push: true tags: ${{ env.IMAGE_NAME_AND_TAG }} cache-from: type=registry,ref=${{ env.IMAGE_NAME_AND_TAG }}-buildcache cache-to: type=registry,ref=${{ env.IMAGE_NAME_AND_TAG }}-buildcache,mode=max

2022年6月24日 · aoirint

pip-compileでMetadataGenerationFailedの例外が起きる

pip-compileは、pip-toolsパッケージ(jazzband/pip-tools)に含まれるコマンドで、 Pythonパッケージのリストrequirements.inから、 依存ツリーのライブラリバージョンリストrequirements.txtを出力してくれる便利なツールである。 入力例 requirements.in django requests gunicorn mysqlclient python-dateutil requests-oauthlib schedule pip-compile requirements.in 出力例 requirements.txt # # This file is autogenerated by pip-compile with python 3.8 # To update, run: # # pip-compile requirements.in # asgiref==3.5.2 # via django backports-zoneinfo==0.2.1 # via django certifi==2022.6.15 # via requests charset-normalizer==2.0.12 # via requests django==4.0.5 # via -r requirements.in gunicorn==20.1.0 # via -r requirements.in idna==3.3 # via requests mysqlclient==2.1.1 # via -r requirements.in oauthlib==3.2.0 # via requests-oauthlib python-dateutil==2.8.2 # via -r requirements.in requests==2.28.0 # via # -r requirements.in # requests-oauthlib requests-oauthlib==1.3.1 # via -r requirements.in schedule==1.1.0 # via -r requirements.in six==1.16.0 # via python-dateutil sqlparse==0.4.2 # via django urllib3==1.26.9 # via requests # The following packages are considered to be unsafe in a requirements file: # setuptools https://pypi.org/project/pip-tools/ (現在 pip-tools==6.6.2) https://github.com/jazzband/pip-tools ところでPythonパッケージは、システムパッケージの事前インストールを要求することがある。 以下、システムパッケージ名はDebian/Ubuntuを想定する。 ...

2022年6月24日 · aoirint

Python subprcess stdout, stderrをキャプチャする

threading https://ja.stackoverflow.com/questions/60539/subprocess-popenのstdoutとstderrをリアルタイムに取得する # python 3.9 import subprocess from threading import Thread def main(): command = [ 'mycommand', '-opt1', ] proc = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) def read_stdout(stdout): for line in stdout: line_text = line.decode('utf-8').strip() print(f'STDOUT: {line_text}', flush=True) print('stdout closed') # closed when process exited def read_stderr(stderr): for line in stderr: line_text = line.decode('utf-8').strip() print(f'STDERR: {line_text}', flush=True) print('stderr closed') # closed when process exited Thread(target=read_stdout, args=(proc.stdout,)).start() Thread(target=read_stderr, args=(proc.stderr,)).start() while True: returncode = proc.poll() if returncode is not None: break time.sleep(0.01) print(f'exited {returncode}') asyncio https://stackoverflow.com/questions/28492103/how-to-combine-python-asyncio-with-threads https://qiita.com/matsui-k20xx/items/4d1c00c4eefd60ba635b import time import asyncio from concurrent.futures import ThreadPoolExecutor async def main(): loop = asyncio.get_event_loop() executor = ThreadPoolExecutor(2) def operation(): time.sleep(1) print('aaa', flush=True) # 2個ずつ実行される(asyncio.runの実行終了まで2秒かかる) loop.run_in_executor(executor, operation) loop.run_in_executor(executor, operation) loop.run_in_executor(executor, operation) loop.run_in_executor(executor, operation) # main関数の実行はブロックされない print('before aaa') asyncio.run(main()) import time import asyncio from asyncio.subprocess import create_subprocess_exec, PIPE from concurrent.futures import ThreadPoolExecutor async def main(): command = [ 'mycommand', '-opt1', ] proc = await create_subprocess_exec( command[0], *command[1:], stdout=PIPE, stderr=PIPE, ) loop = asyncio.get_event_loop() executor = ThreadPoolExecutor() def read_stdout(stdout): while True: line = asyncio.run_coroutine_threadsafe(stdout.readline(), loop).result() if not line: break line_text = line.decode('utf-8').strip() print(f'STDOUT: {line_text}', flush=True) print('stdout closed') # closed when process exited def read_stderr(stderr): while True: line = asyncio.run_coroutine_threadsafe(stderr.readline(), loop).result() if not line: break line_text = line.decode('utf-8').strip() print(f'STDERR: {line_text}', flush=True) print('stderr closed') # closed when process exited loop.run_in_executor(executor, read_stdout, proc.stdout) loop.run_in_executor(executor, read_stderr, proc.stderr) await proc.wait() print(f'exited {proc.returncode}') https://stackoverflow.com/questions/45600579/asyncio-event-loop-is-closed-when-getting-loop 終了時にEvent loop is closedというエラーが出ることがある? ...

2022年6月6日 · aoirint

VODのHLS配信に関するメモ

https://blog.foresta.me/posts/convert_mp4_to_hls_with_ffmpeg/ https://yosshi.snowdrop.asia/2015/07/27/1156/ https://ffmpeg.org/ffmpeg-formats.html ffmpeg -i video.mp4 -f hls -hls_time 9 -hls_playlist_type vod -hls_segment_filename "stream%3d.ts" stream.m3u8 ffmpeg -i video.mp4 -c:v libx264 -c:a aac -f hls -hls_time 9 -hls_playlist_type vod -hls_segment_filename "stream%3d.ts" stream.m3u8 https://paulownia.hatenablog.com/entry/2020/10/18/163104 https://hub.docker.com/_/nginx default.conf.template server { root /webroot; location ~* \.ts$ { types { video/MP2T ts; } } location ~* \.m3u8$ { types { application/vnd.apple.mpegurl m3u8; # application/x-mpegURL m3u8; } } } niconico: duration: 6s, application/vnd.apple.mpegurl, video/MP2T (durationはキーフレームとかいろいろで勝手に変わるかも?) ffmpeg -i video.mp4 \ -acodec copy \ -vcodec copy \ -vbsf h264_mp4toannexb \ -map 0 \ -f segment \ -segment_format mpegts \ -segment_time 30 \ -segment_list stream.m3u8 \ -segment_list_flags \ -cache stream%03d.ts codecをコピーすると1ファイルのtsに出力されてしまう場合がある libx264で再エンコードする ...

2022年6月6日 · aoirint