Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4d9aa9d1b | ||
|
|
54f2072e97 | ||
|
|
d1042cde0e | ||
|
|
5f4275679d | ||
|
|
1ba0bee1ea | ||
|
|
ea7aa93a28 | ||
|
|
9eccf69456 | ||
|
|
9cebfa85df | ||
|
|
af3cf62b8e | ||
|
|
f20a1245e7 | ||
|
|
92a4989a8d | ||
|
|
be3b22ce36 | ||
|
|
258b8e4ecc | ||
|
|
7df92aad03 | ||
|
|
2dac705779 |
@@ -31,8 +31,7 @@
|
||||
"ms-python.python",
|
||||
"ms-python.vscode-pylance",
|
||||
"batisteo.vscode-django",
|
||||
"eamodio.gitlens",
|
||||
"biomejs.biome"
|
||||
"eamodio.gitlens"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
db:
|
||||
image: postgres:13
|
||||
@@ -11,12 +13,6 @@ services:
|
||||
POSTGRES_USER: inventree_user
|
||||
POSTGRES_PASSWORD: inventree_password
|
||||
|
||||
redis:
|
||||
image: redis:7.0
|
||||
restart: always
|
||||
expose:
|
||||
- 6379
|
||||
|
||||
inventree:
|
||||
build:
|
||||
context: ..
|
||||
@@ -35,8 +31,6 @@ services:
|
||||
INVENTREE_DB_HOST: db
|
||||
INVENTREE_DB_USER: inventree_user
|
||||
INVENTREE_DB_PASSWORD: inventree_password
|
||||
INVENTREE_CACHE_HOST: redis
|
||||
INVENTREE_CACHE_PORT: 6379
|
||||
INVENTREE_PLUGINS_ENABLED: True
|
||||
INVENTREE_SITE_URL: http://localhost:8000
|
||||
INVENTREE_CORS_ORIGIN_ALLOW_ALL: True
|
||||
|
||||
@@ -11,10 +11,10 @@ python3 -m venv /home/inventree/dev/venv --system-site-packages --upgrade-deps
|
||||
invoke update -s
|
||||
|
||||
# Configure dev environment
|
||||
invoke dev.setup-dev
|
||||
invoke setup-dev
|
||||
|
||||
# Install required frontend packages
|
||||
invoke int.frontend-install
|
||||
invoke frontend-install
|
||||
|
||||
# remove existing gitconfig created by "Avoiding Dubious Ownership" step
|
||||
# so that it gets copied from host to the container to have your global
|
||||
|
||||
4
.github/FUNDING.yml
vendored
@@ -1,3 +1,5 @@
|
||||
polar: inventree
|
||||
github: inventree
|
||||
ko_fi: inventree
|
||||
patreon: inventree
|
||||
polar: inventree
|
||||
custom: [paypal.me/inventree]
|
||||
|
||||
1
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1 +0,0 @@
|
||||
blank_issues_enabled: false
|
||||
6
.github/actions/migration/action.yaml
vendored
@@ -9,9 +9,9 @@ runs:
|
||||
shell: bash
|
||||
run: |
|
||||
invoke migrate
|
||||
invoke dev.import-fixtures
|
||||
invoke import-fixtures
|
||||
invoke export-records -f data.json
|
||||
python3 ./src/backend/InvenTree/manage.py flush --noinput
|
||||
invoke migrate
|
||||
invoke import-records -c -f data.json
|
||||
invoke import-records -c -f data.json
|
||||
invoke import-records -f data.json
|
||||
invoke import-records -f data.json
|
||||
|
||||
9
.github/actions/setup/action.yaml
vendored
@@ -44,11 +44,6 @@ runs:
|
||||
with:
|
||||
python-version: ${{ env.python_version }}
|
||||
cache: pip
|
||||
cache-dependency-path: |
|
||||
src/backend/requirements.txt
|
||||
src/backend/requirements-dev.txt
|
||||
contrib/container/requirements.txt
|
||||
contrib/dev_reqs/requirements.txt
|
||||
- name: Install Base Python Dependencies
|
||||
if: ${{ inputs.python == 'true' }}
|
||||
shell: bash
|
||||
@@ -88,7 +83,7 @@ runs:
|
||||
|
||||
# Invoke commands
|
||||
- name: Install dev requirements
|
||||
if: ${{ inputs.dev-install == 'true' || inputs.install == 'true' }}
|
||||
if: ${{ inputs.dev-install == 'true' ||inputs.install == 'true' }}
|
||||
shell: bash
|
||||
run: uv pip install --require-hashes -r src/backend/requirements-dev.txt
|
||||
- name: Run invoke install
|
||||
@@ -98,4 +93,4 @@ runs:
|
||||
- name: Run invoke update
|
||||
if: ${{ inputs.update == 'true' }}
|
||||
shell: bash
|
||||
run: invoke update --uv --skip-backup --skip-static
|
||||
run: invoke update --uv
|
||||
|
||||
34
.github/dependabot.yml
vendored
@@ -15,11 +15,22 @@ updates:
|
||||
interval: weekly
|
||||
|
||||
- package-ecosystem: pip
|
||||
directories:
|
||||
- /contrib/container
|
||||
- /docs
|
||||
- /contrib/dev_reqs
|
||||
- /src/backend
|
||||
directory: /contrib/container
|
||||
schedule:
|
||||
interval: weekly
|
||||
|
||||
- package-ecosystem: pip
|
||||
directory: /docs
|
||||
schedule:
|
||||
interval: weekly
|
||||
|
||||
- package-ecosystem: pip
|
||||
directory: /.github
|
||||
schedule:
|
||||
interval: weekly
|
||||
|
||||
- package-ecosystem: pip
|
||||
directory: /src/backend
|
||||
schedule:
|
||||
interval: weekly
|
||||
groups:
|
||||
@@ -28,9 +39,16 @@ updates:
|
||||
- "*" # Include all dependencies
|
||||
|
||||
- package-ecosystem: npm
|
||||
directories:
|
||||
- /src/frontend
|
||||
- /src/backend
|
||||
directory: /src/backend
|
||||
schedule:
|
||||
interval: weekly
|
||||
groups:
|
||||
dependencies:
|
||||
patterns:
|
||||
- "*" # Include all dependencies
|
||||
|
||||
- package-ecosystem: npm
|
||||
directory: /src/frontend
|
||||
schedule:
|
||||
interval: weekly
|
||||
groups:
|
||||
|
||||
4
.github/release.yml
vendored
@@ -4,7 +4,6 @@ changelog:
|
||||
exclude:
|
||||
labels:
|
||||
- translation
|
||||
- translations
|
||||
- documentation
|
||||
categories:
|
||||
- title: Breaking Changes
|
||||
@@ -14,9 +13,6 @@ changelog:
|
||||
- title: Security Patches
|
||||
labels:
|
||||
- security
|
||||
- title: Database Changes
|
||||
labels:
|
||||
- migration
|
||||
- title: New Features
|
||||
labels:
|
||||
- Semver-Minor
|
||||
|
||||
4
.github/scripts/check_js_templates.py
vendored
@@ -71,7 +71,7 @@ def check_prohibited_tags(data):
|
||||
for filename in pathlib.Path(js_i18n_dir).rglob('*.js'):
|
||||
print(f"Checking file 'translated/{os.path.basename(filename)}':")
|
||||
|
||||
with open(filename, encoding='utf-8') as js_file:
|
||||
with open(filename, 'r') as js_file:
|
||||
data = js_file.readlines()
|
||||
|
||||
errors += check_invalid_tag(data)
|
||||
@@ -81,7 +81,7 @@ for filename in pathlib.Path(js_dynamic_dir).rglob('*.js'):
|
||||
print(f"Checking file 'dynamic/{os.path.basename(filename)}':")
|
||||
|
||||
# Check that the 'dynamic' files do not contains any translated strings
|
||||
with open(filename, encoding='utf-8') as js_file:
|
||||
with open(filename, 'r') as js_file:
|
||||
data = js_file.readlines()
|
||||
|
||||
invalid_tags = ['blocktrans', 'blocktranslate', 'trans', 'translate']
|
||||
|
||||
4
.github/scripts/check_migration_files.py
vendored
@@ -20,9 +20,9 @@ for line in str(out.decode()).split('\n'):
|
||||
if len(migrations) == 0:
|
||||
sys.exit(0)
|
||||
|
||||
print(f'There are {len(migrations)} unstaged migration files:')
|
||||
print('There are {n} unstaged migration files:'.format(n=len(migrations)))
|
||||
|
||||
for m in migrations:
|
||||
print(f' - {m}')
|
||||
print(' - {m}'.format(m=m))
|
||||
|
||||
sys.exit(len(migrations))
|
||||
|
||||
100
.github/scripts/check_source_strings.py
vendored
@@ -1,100 +0,0 @@
|
||||
"""Script to check source strings for translations."""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
|
||||
import rapidfuzz
|
||||
|
||||
BACKEND_SOURCE_FILE = [
|
||||
'..',
|
||||
'..',
|
||||
'src',
|
||||
'backend',
|
||||
'InvenTree',
|
||||
'locale',
|
||||
'en',
|
||||
'LC_MESSAGES',
|
||||
'django.po',
|
||||
]
|
||||
|
||||
FRONTEND_SOURCE_FILE = [
|
||||
'..',
|
||||
'..',
|
||||
'src',
|
||||
'frontend',
|
||||
'src',
|
||||
'locales',
|
||||
'en',
|
||||
'messages.po',
|
||||
]
|
||||
|
||||
|
||||
def extract_source_strings(file_path):
|
||||
"""Extract source strings from the provided file."""
|
||||
here = os.path.abspath(os.path.dirname(__file__))
|
||||
abs_file_path = os.path.abspath(os.path.join(here, *file_path))
|
||||
|
||||
sources = []
|
||||
|
||||
with open(abs_file_path, encoding='utf-8') as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if line.startswith('msgid '):
|
||||
msgid = line[6:].strip()
|
||||
|
||||
if msgid in sources:
|
||||
print(f'Duplicate source string: {msgid}')
|
||||
else:
|
||||
sources.append(msgid)
|
||||
|
||||
return sources
|
||||
|
||||
|
||||
def compare_source_strings(sources, threshold):
|
||||
"""Compare source strings to find duplicates (or close matches)."""
|
||||
issues = 0
|
||||
|
||||
for i, source in enumerate(sources):
|
||||
for other in sources[i + 1 :]:
|
||||
if other.lower() == source.lower():
|
||||
print(f'- Duplicate: {source} ~ {other}')
|
||||
issues += 1
|
||||
continue
|
||||
|
||||
ratio = rapidfuzz.fuzz.ratio(source, other)
|
||||
if ratio > threshold:
|
||||
print(f'- Close match: {source} ~ {other} ({ratio:.1f}%)')
|
||||
issues += 1
|
||||
|
||||
if issues:
|
||||
print(f' - Found {issues} issues.')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Check source strings for translations.'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--backend', action='store_true', help='Check backend source strings'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--frontend', action='store_true', help='Check frontend source strings'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--threshold',
|
||||
type=int,
|
||||
help='Set the threshold for string comparison',
|
||||
default=99,
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.backend:
|
||||
backend_sources = extract_source_strings(BACKEND_SOURCE_FILE)
|
||||
print('Backend source strings:', len(backend_sources))
|
||||
compare_source_strings(backend_sources, args.threshold)
|
||||
|
||||
if args.frontend:
|
||||
frontend_sources = extract_source_strings(FRONTEND_SOURCE_FILE)
|
||||
print('Frontend source strings:', len(frontend_sources))
|
||||
compare_source_strings(frontend_sources, args.threshold)
|
||||
42
.github/scripts/version_check.py
vendored
@@ -10,7 +10,6 @@ tagged branch:
|
||||
|
||||
"""
|
||||
|
||||
import itertools
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
@@ -19,11 +18,8 @@ from pathlib import Path
|
||||
|
||||
import requests
|
||||
|
||||
REPO = os.getenv('GITHUB_REPOSITORY', 'inventree/inventree')
|
||||
GITHUB_API_URL = os.getenv('GITHUB_API_URL', 'https://api.github.com')
|
||||
|
||||
|
||||
def get_existing_release_tags(include_prerelease=True):
|
||||
def get_existing_release_tags():
|
||||
"""Request information on existing releases via the GitHub API."""
|
||||
# Check for github token
|
||||
token = os.getenv('GITHUB_TOKEN', None)
|
||||
@@ -32,7 +28,9 @@ def get_existing_release_tags(include_prerelease=True):
|
||||
if token:
|
||||
headers = {'Authorization': f'Bearer {token}'}
|
||||
|
||||
response = requests.get(f'{GITHUB_API_URL}/repos/{REPO}/releases', headers=headers)
|
||||
response = requests.get(
|
||||
'https://api.github.com/repos/inventree/inventree/releases', headers=headers
|
||||
)
|
||||
|
||||
if response.status_code != 200:
|
||||
raise ValueError(
|
||||
@@ -52,9 +50,6 @@ def get_existing_release_tags(include_prerelease=True):
|
||||
print(f"Version '{tag}' did not match expected pattern")
|
||||
continue
|
||||
|
||||
if not include_prerelease and release['prerelease']:
|
||||
continue
|
||||
|
||||
tags.append([int(x) for x in match.groups()])
|
||||
|
||||
return tags
|
||||
@@ -78,7 +73,7 @@ def check_version_number(version_string, allow_duplicate=False):
|
||||
version_tuple = [int(x) for x in match.groups()]
|
||||
|
||||
# Look through the existing releases
|
||||
existing = get_existing_release_tags(include_prerelease=False)
|
||||
existing = get_existing_release_tags()
|
||||
|
||||
# Assume that this is the highest release, unless told otherwise
|
||||
highest_release = True
|
||||
@@ -89,17 +84,12 @@ def check_version_number(version_string, allow_duplicate=False):
|
||||
|
||||
if release > version_tuple:
|
||||
highest_release = False
|
||||
print(f'Found newer release: {release!s}')
|
||||
print(f'Found newer release: {str(release)}')
|
||||
|
||||
return highest_release
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Ensure that we are running in GH Actions
|
||||
if os.environ.get('GITHUB_ACTIONS', '') != 'true':
|
||||
print('This script is intended to be run within a GitHub Action!')
|
||||
sys.exit(1)
|
||||
|
||||
if 'only_version' in sys.argv:
|
||||
here = Path(__file__).parent.absolute()
|
||||
version_file = here.joinpath(
|
||||
@@ -107,18 +97,16 @@ if __name__ == '__main__':
|
||||
)
|
||||
text = version_file.read_text()
|
||||
results = re.findall(r"""INVENTREE_API_VERSION = (.*)""", text)
|
||||
# If 2. args is true lower the version number by 1
|
||||
if len(sys.argv) > 2 and sys.argv[2] == 'true':
|
||||
results[0] = str(int(results[0]) - 1)
|
||||
print(results[0])
|
||||
exit(0)
|
||||
|
||||
# GITHUB_REF_TYPE may be either 'branch' or 'tag'
|
||||
GITHUB_REF_TYPE = os.environ['GITHUB_REF_TYPE']
|
||||
|
||||
# GITHUB_REF may be either 'refs/heads/<branch>' or 'refs/heads/<tag>'
|
||||
GITHUB_REF = os.environ['GITHUB_REF']
|
||||
|
||||
GITHUB_REF_NAME = os.environ['GITHUB_REF_NAME']
|
||||
|
||||
GITHUB_BASE_REF = os.environ['GITHUB_BASE_REF']
|
||||
|
||||
# Print out version information, makes debugging actions *much* easier!
|
||||
@@ -134,7 +122,7 @@ if __name__ == '__main__':
|
||||
|
||||
version = None
|
||||
|
||||
with open(version_file, encoding='utf-8') as f:
|
||||
with open(version_file, 'r') as f:
|
||||
text = f.read()
|
||||
|
||||
# Extract the InvenTree software version
|
||||
@@ -175,7 +163,10 @@ if __name__ == '__main__':
|
||||
print(f"Version number '{version}' does not match tag '{version_tag}'")
|
||||
sys.exit
|
||||
|
||||
docker_tags = [version_tag, 'stable'] if highest_release else [version_tag]
|
||||
if highest_release:
|
||||
docker_tags = [version_tag, 'stable']
|
||||
else:
|
||||
docker_tags = [version_tag]
|
||||
|
||||
elif GITHUB_REF_TYPE == 'branch':
|
||||
# Otherwise we know we are targeting the 'master' branch
|
||||
@@ -196,13 +187,10 @@ if __name__ == '__main__':
|
||||
print(f"Version check passed for '{version}'!")
|
||||
print(f"Docker tags: '{docker_tags}'")
|
||||
|
||||
target_repos = [REPO.lower(), f'ghcr.io/{REPO.lower()}']
|
||||
|
||||
# Ref: https://getridbug.com/python/how-to-set-environment-variables-in-github-actions-using-python/
|
||||
with open(os.getenv('GITHUB_ENV'), 'a', encoding='utf-8') as env_file:
|
||||
with open(os.getenv('GITHUB_ENV'), 'a') as env_file:
|
||||
# Construct tag string
|
||||
tag_list = [[f'{r}:{t}' for t in docker_tags] for r in target_repos]
|
||||
tags = ','.join(itertools.chain(*tag_list))
|
||||
tags = ','.join([f'inventree/inventree:{tag}' for tag in docker_tags])
|
||||
|
||||
env_file.write(f'docker_tags={tags}\n')
|
||||
|
||||
|
||||
2
.github/workflows/backport.yaml
vendored
@@ -25,7 +25,7 @@ jobs:
|
||||
)
|
||||
steps:
|
||||
- name: Backport Action
|
||||
uses: sqren/backport-github-action@ad888e978060bc1b2798690dd9d03c4036560947 # pin@v9.2.2
|
||||
uses: sqren/backport-github-action@f54e19901f2a57f8b82360f2490d47ee82ec82c6 # pin@v9.2.2
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
auto_backport_label_prefix: backport-to-
|
||||
|
||||
7
.github/workflows/check_translations.yaml
vendored
@@ -30,16 +30,13 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # pin@v4.1.5
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
install: true
|
||||
apt-dependency: gettext
|
||||
- name: Test Translations
|
||||
run: invoke dev.translate
|
||||
- name: Check for Duplicates
|
||||
run: |
|
||||
python ./.github/scripts/check_source_strings.py --frontend --backend
|
||||
run: invoke translate
|
||||
- name: Check Migration Files
|
||||
run: python3 .github/scripts/check_migration_files.py
|
||||
|
||||
36
.github/workflows/docker.yaml
vendored
@@ -39,7 +39,7 @@ jobs:
|
||||
docker: ${{ steps.filter.outputs.docker }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # pin@v4.1.5
|
||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # pin@v3.0.2
|
||||
id: filter
|
||||
with:
|
||||
@@ -66,9 +66,9 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # pin@v4.1.5
|
||||
- name: Set Up Python ${{ env.python_version }}
|
||||
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # pin@v5.3.0
|
||||
uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # pin@v5.1.0
|
||||
with:
|
||||
python-version: ${{ env.python_version }}
|
||||
- name: Version Check
|
||||
@@ -97,7 +97,7 @@ jobs:
|
||||
run: |
|
||||
docker compose --project-directory . -f contrib/container/dev-docker-compose.yml run inventree-dev-server invoke install
|
||||
docker compose --project-directory . -f contrib/container/dev-docker-compose.yml run inventree-dev-server invoke update
|
||||
docker compose --project-directory . -f contrib/container/dev-docker-compose.yml run inventree-dev-server invoke dev.setup-dev
|
||||
docker compose --project-directory . -f contrib/container/dev-docker-compose.yml run inventree-dev-server invoke setup-dev
|
||||
docker compose --project-directory . -f contrib/container/dev-docker-compose.yml up -d
|
||||
docker compose --project-directory . -f contrib/container/dev-docker-compose.yml run inventree-dev-server invoke wait
|
||||
- name: Check Data Directory
|
||||
@@ -115,40 +115,39 @@ jobs:
|
||||
- name: Run Unit Tests
|
||||
run: |
|
||||
echo "GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}" >> contrib/container/docker.dev.env
|
||||
docker compose --project-directory . -f contrib/container/dev-docker-compose.yml run --rm inventree-dev-server invoke dev.test --disable-pty
|
||||
- name: Run Migration Tests
|
||||
run: |
|
||||
docker compose --project-directory . -f contrib/container/dev-docker-compose.yml run --rm inventree-dev-server invoke dev.test --migrations
|
||||
docker compose --project-directory . -f contrib/container/dev-docker-compose.yml run inventree-dev-server invoke test --disable-pty
|
||||
docker compose --project-directory . -f contrib/container/dev-docker-compose.yml run inventree-dev-server invoke test --migrations --disable-pty
|
||||
docker compose --project-directory . -f contrib/container/dev-docker-compose.yml down
|
||||
- name: Clean up test folder
|
||||
run: |
|
||||
rm -rf InvenTree/_testfolder
|
||||
- name: Set up QEMU
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # pin@v3.2.0
|
||||
uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # pin@v3.0.0
|
||||
- name: Set up Docker Buildx
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # pin@v3.8.0
|
||||
uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # pin@v3.3.0
|
||||
- name: Set up cosign
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # pin@v3.7.0
|
||||
uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # pin@v3.5.0
|
||||
- name: Check if Dockerhub login is required
|
||||
id: docker_login
|
||||
run: |
|
||||
if [ -z "${{ secrets.DOCKER_USERNAME }}" ]; then
|
||||
echo "skip_dockerhub_login=true" >> $GITHUB_OUTPUT
|
||||
echo "skip_dockerhub_login=true" >> $GITHUB_ENV
|
||||
else
|
||||
echo "skip_dockerhub_login=false" >> $GITHUB_OUTPUT
|
||||
echo "skip_dockerhub_login=false" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: Login to Dockerhub
|
||||
if: github.event_name != 'pull_request' && steps.docker_login.outputs.skip_dockerhub_login != 'true'
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # pin@v3.3.0
|
||||
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # pin@v3.1.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Log into registry ghcr.io
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # pin@v3.3.0
|
||||
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # pin@v3.1.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
@@ -157,20 +156,17 @@ jobs:
|
||||
- name: Extract Docker metadata
|
||||
if: github.event_name != 'pull_request'
|
||||
id: meta
|
||||
uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96 # pin@v5.6.1
|
||||
uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # pin@v5.5.1
|
||||
with:
|
||||
images: |
|
||||
inventree/inventree
|
||||
ghcr.io/${{ github.repository }}
|
||||
|
||||
- uses: depot/setup-action@v1
|
||||
|
||||
- name: Push Docker Images
|
||||
id: push-docker
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: depot/build-push-action@v1
|
||||
uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # pin@v5.3.0
|
||||
with:
|
||||
project: jczzbjkk68
|
||||
context: .
|
||||
file: ./contrib/container/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
||||
111
.github/workflows/qc_checks.yaml
vendored
@@ -10,9 +10,11 @@ on:
|
||||
|
||||
env:
|
||||
python_version: 3.9
|
||||
node_version: 20
|
||||
node_version: 18
|
||||
# The OS version must be set per job
|
||||
server_start_sleep: 60
|
||||
requests_version: 2.31.0
|
||||
pyyaml_version: 6.0.1
|
||||
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
INVENTREE_DB_ENGINE: sqlite3
|
||||
@@ -38,7 +40,7 @@ jobs:
|
||||
force: ${{ steps.force.outputs.force }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # pin@v4.1.5
|
||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # pin@v3.0.2
|
||||
id: filter
|
||||
with:
|
||||
@@ -70,7 +72,7 @@ jobs:
|
||||
needs: ["pre-commit"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # pin@v4.1.5
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
@@ -92,9 +94,9 @@ jobs:
|
||||
if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.frontend == 'true' || needs.paths-filter.outputs.force == 'true'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # pin@v4.1.5
|
||||
- name: Set up Python ${{ env.python_version }}
|
||||
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # pin@v5.3.0
|
||||
uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # pin@v5.1.0
|
||||
with:
|
||||
python-version: ${{ env.python_version }}
|
||||
cache: "pip"
|
||||
@@ -113,9 +115,9 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # pin@v4.1.5
|
||||
- name: Set up Python ${{ env.python_version }}
|
||||
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # pin@v5.3.0
|
||||
uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # pin@v5.1.0
|
||||
with:
|
||||
python-version: ${{ env.python_version }}
|
||||
- name: Check Config
|
||||
@@ -149,7 +151,7 @@ jobs:
|
||||
version: ${{ steps.version.outputs.version }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # pin@v4.1.5
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
@@ -157,41 +159,29 @@ jobs:
|
||||
dev-install: true
|
||||
update: true
|
||||
- name: Export API Documentation
|
||||
run: invoke dev.schema --ignore-warnings --filename src/backend/InvenTree/schema.yml
|
||||
run: invoke schema --ignore-warnings --filename src/backend/InvenTree/schema.yml
|
||||
- name: Upload schema
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # pin@v4.4.3
|
||||
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # pin@v4.3.3
|
||||
with:
|
||||
name: schema.yml
|
||||
path: src/backend/InvenTree/schema.yml
|
||||
- name: Download public schema
|
||||
if: needs.paths-filter.outputs.api == 'false'
|
||||
run: |
|
||||
pip install --require-hashes -r contrib/dev_reqs/requirements.txt >/dev/null 2>&1
|
||||
version="$(python3 .github/scripts/version_check.py only_version ${{ needs.paths-filter.outputs.api }} 2>&1)"
|
||||
version="$(python3 .github/scripts/version_check.py only_version 2>&1)"
|
||||
echo "Version: $version"
|
||||
url="https://raw.githubusercontent.com/inventree/schema/main/export/${version}/api.yaml"
|
||||
echo "URL: $url"
|
||||
code=$(curl -s -o api.yaml $url --write-out '%{http_code}' --silent)
|
||||
if [ "$code" != "200" ]; then
|
||||
exit 1
|
||||
fi
|
||||
curl -s -o api.yaml $url
|
||||
echo "Downloaded api.yaml"
|
||||
- name: Running OpenAPI Spec diff action
|
||||
id: breaking_changes
|
||||
uses: oasdiff/oasdiff-action/diff@1c611ffb1253a72924624aa4fb662e302b3565d3 # pin@main
|
||||
with:
|
||||
base: 'api.yaml'
|
||||
revision: 'src/backend/InvenTree/schema.yml'
|
||||
format: 'html'
|
||||
- name: Echoing diff to step
|
||||
run: echo "${{ steps.breaking_changes.outputs.diff }}" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: Check for differences in API Schema
|
||||
if: needs.paths-filter.outputs.api == 'false'
|
||||
run: |
|
||||
diff --color -u src/backend/InvenTree/schema.yml api.yaml
|
||||
diff -u src/backend/InvenTree/schema.yml api.yaml && echo "no difference in API schema " || exit 2
|
||||
- name: Check schema - including warnings
|
||||
run: invoke dev.schema
|
||||
run: invoke schema
|
||||
continue-on-error: true
|
||||
- name: Extract version for publishing
|
||||
id: version
|
||||
@@ -211,13 +201,12 @@ jobs:
|
||||
version: ${{ needs.schema.outputs.version }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
name: Checkout Code
|
||||
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
|
||||
with:
|
||||
repository: inventree/schema
|
||||
token: ${{ secrets.SCHEMA_PAT }}
|
||||
- name: Download schema artifact
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
|
||||
with:
|
||||
name: schema.yml
|
||||
- name: Move schema to correct location
|
||||
@@ -226,9 +215,8 @@ jobs:
|
||||
mkdir export/${version}
|
||||
mv schema.yml export/${version}/api.yaml
|
||||
- uses: stefanzweifel/git-auto-commit-action@8621497c8c39c72f3e2a999a26b4ca1b5058a842 # v5.0.1
|
||||
name: Commit schema changes
|
||||
with:
|
||||
commit_message: "Update API schema for ${{ env.version }} / ${{ github.sha }}"
|
||||
commit_message: "Update API schema for ${version}"
|
||||
|
||||
python:
|
||||
name: Tests - inventree-python
|
||||
@@ -250,7 +238,7 @@ jobs:
|
||||
INVENTREE_SITE_URL: http://127.0.0.1:12345
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # pin@v4.1.5
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
@@ -262,9 +250,9 @@ jobs:
|
||||
run: git clone --depth 1 https://github.com/inventree/${{ env.wrapper_name }} ./${{ env.wrapper_name }}
|
||||
- name: Start InvenTree Server
|
||||
run: |
|
||||
invoke dev.delete-data -f
|
||||
invoke dev.import-fixtures
|
||||
invoke dev.server -a 127.0.0.1:12345 &
|
||||
invoke delete-data -f
|
||||
invoke import-fixtures
|
||||
invoke server -a 127.0.0.1:12345 &
|
||||
invoke wait
|
||||
- name: Run Tests For `${{ env.wrapper_name }}`
|
||||
run: |
|
||||
@@ -281,8 +269,7 @@ jobs:
|
||||
continue-on-error: true # continue if a step fails so that coverage gets pushed
|
||||
strategy:
|
||||
matrix:
|
||||
python_version: [3.9]
|
||||
# python_version: [3.9, 3.12] # Disabled due to requirement issues
|
||||
python_version: [3.9, 3.12]
|
||||
|
||||
env:
|
||||
INVENTREE_DB_NAME: ./inventree.sqlite
|
||||
@@ -292,7 +279,7 @@ jobs:
|
||||
python_version: ${{ matrix.python_version }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # pin@v4.1.5
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
@@ -302,13 +289,13 @@ jobs:
|
||||
- name: Data Export Test
|
||||
uses: ./.github/actions/migration
|
||||
- name: Test Translations
|
||||
run: invoke dev.translate
|
||||
run: invoke translate
|
||||
- name: Check Migration Files
|
||||
run: python3 .github/scripts/check_migration_files.py
|
||||
- name: Coverage Tests
|
||||
run: invoke dev.test --coverage
|
||||
run: invoke test --coverage
|
||||
- name: Upload coverage reports to Codecov
|
||||
uses: codecov/codecov-action@7f8b4b4bde536c465e797be725718b88c5d95e0e # pin@v5.1.1
|
||||
uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # pin@v4.3.1
|
||||
if: always()
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
@@ -346,7 +333,7 @@ jobs:
|
||||
- 6379:6379
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # pin@v4.1.5
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
@@ -355,7 +342,7 @@ jobs:
|
||||
dev-install: true
|
||||
update: true
|
||||
- name: Run Tests
|
||||
run: invoke dev.test
|
||||
run: invoke test
|
||||
- name: Data Export Test
|
||||
uses: ./.github/actions/migration
|
||||
|
||||
@@ -390,7 +377,7 @@ jobs:
|
||||
- 3306:3306
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # pin@v4.1.5
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
@@ -399,7 +386,7 @@ jobs:
|
||||
dev-install: true
|
||||
update: true
|
||||
- name: Run Tests
|
||||
run: invoke dev.test
|
||||
run: invoke test
|
||||
- name: Data Export Test
|
||||
uses: ./.github/actions/migration
|
||||
|
||||
@@ -429,7 +416,7 @@ jobs:
|
||||
- 5432:5432
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # pin@v4.1.5
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
@@ -438,9 +425,9 @@ jobs:
|
||||
dev-install: true
|
||||
update: true
|
||||
- name: Run Tests
|
||||
run: invoke dev.test --migrations --report --coverage
|
||||
run: invoke test --migrations --report --coverage
|
||||
- name: Upload coverage reports to Codecov
|
||||
uses: codecov/codecov-action@7f8b4b4bde536c465e797be725718b88c5d95e0e # pin@v5.1.1
|
||||
uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # pin@v4.3.1
|
||||
if: always()
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
@@ -460,7 +447,7 @@ jobs:
|
||||
INVENTREE_PLUGINS_ENABLED: false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # pin@v4.1.5
|
||||
name: Checkout Code
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
@@ -517,7 +504,7 @@ jobs:
|
||||
VITE_COVERAGE: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # pin@v4.1.5
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
@@ -525,17 +512,17 @@ jobs:
|
||||
install: true
|
||||
update: true
|
||||
- name: Set up test data
|
||||
run: invoke dev.setup-test -i
|
||||
run: invoke setup-test -i
|
||||
- name: Rebuild thumbnails
|
||||
run: invoke int.rebuild-thumbnails
|
||||
run: invoke rebuild-thumbnails
|
||||
- name: Install dependencies
|
||||
run: invoke int.frontend-compile
|
||||
run: inv frontend-compile
|
||||
- name: Install Playwright Browsers
|
||||
run: cd src/frontend && npx playwright install --with-deps
|
||||
- name: Run Playwright tests
|
||||
id: tests
|
||||
run: cd src/frontend && npx nyc playwright test
|
||||
- uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # pin@v4
|
||||
- uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # pin@v4
|
||||
if: ${{ !cancelled() && steps.tests.outcome == 'failure' }}
|
||||
with:
|
||||
name: playwright-report
|
||||
@@ -545,19 +532,12 @@ jobs:
|
||||
if: always()
|
||||
run: cd src/frontend && npx nyc report --report-dir ./coverage --temp-dir .nyc_output --reporter=lcov --exclude-after-remap false
|
||||
- name: Upload coverage reports to Codecov
|
||||
uses: codecov/codecov-action@7f8b4b4bde536c465e797be725718b88c5d95e0e # pin@v5.1.1
|
||||
uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # pin@v4.3.1
|
||||
if: always()
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
slug: inventree/InvenTree
|
||||
flags: pui
|
||||
- name: Upload bundler info
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
run: |
|
||||
cd src/frontend
|
||||
yarn install
|
||||
yarn run build
|
||||
|
||||
platform_ui_build:
|
||||
name: Build - UI Platform
|
||||
@@ -565,7 +545,7 @@ jobs:
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # pin@v4.1.5
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
@@ -574,14 +554,11 @@ jobs:
|
||||
run: cd src/frontend && yarn install
|
||||
- name: Build frontend
|
||||
run: cd src/frontend && yarn run compile && yarn run build
|
||||
- name: Write version file - SHA
|
||||
run: cd src/backend/InvenTree/web/static/web/.vite && echo "$GITHUB_SHA" > sha.txt
|
||||
- name: Zip frontend
|
||||
run: |
|
||||
cd src/backend/InvenTree/web/static
|
||||
zip -r frontend-build.zip web/ web/.vite
|
||||
- uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # pin@v4.4.3
|
||||
- uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # pin@v4.3.3
|
||||
with:
|
||||
name: frontend-build
|
||||
path: src/backend/InvenTree/web/static/web
|
||||
include-hidden-files: true
|
||||
|
||||
96
.github/workflows/release.yaml
vendored
@@ -1,18 +1,13 @@
|
||||
# Runs on releases
|
||||
|
||||
name: Publish release
|
||||
name: Publish release notes
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
permissions:
|
||||
contents: read
|
||||
env:
|
||||
python_version: 3.9
|
||||
|
||||
jobs:
|
||||
stable:
|
||||
runs-on: ubuntu-24.04
|
||||
name: Write release to stable branch
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
@@ -20,7 +15,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # pin@v4.1.5
|
||||
- name: Version Check
|
||||
run: |
|
||||
pip install --require-hashes -r contrib/dev_reqs/requirements.txt
|
||||
@@ -33,15 +28,13 @@ jobs:
|
||||
branch: stable
|
||||
force: true
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-24.04
|
||||
name: Build and attest frontend
|
||||
publish-build:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
attestations: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # pin@v4.1.5
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
@@ -50,85 +43,14 @@ jobs:
|
||||
run: cd src/frontend && yarn install
|
||||
- name: Build frontend
|
||||
run: cd src/frontend && npm run compile && npm run build
|
||||
- name: Create SBOM for frontend
|
||||
uses: anchore/sbom-action@df80a981bc6edbc4e220a492d3cbe9f5547a6e75 # pin@v0
|
||||
with:
|
||||
artifact-name: frontend-build.spdx
|
||||
path: src/frontend
|
||||
- name: Write version file - SHA
|
||||
run: cd src/backend/InvenTree/web/static/web/.vite && echo "$GITHUB_SHA" > sha.txt
|
||||
- name: Write version file - TAG
|
||||
run: cd src/backend/InvenTree/web/static/web/.vite && echo "${{ github.ref_name }}" > tag.txt
|
||||
- name: Zip frontend
|
||||
run: |
|
||||
cd src/backend/InvenTree/web/static/web
|
||||
zip -r ../frontend-build.zip * .vite
|
||||
- name: Attest Build Provenance
|
||||
id: attest
|
||||
uses: actions/attest-build-provenance@7668571508540a607bdfd90a87a560489fe372eb # pin@v1
|
||||
with:
|
||||
subject-path: "${{ github.workspace }}/src/backend/InvenTree/web/static/frontend-build.zip"
|
||||
|
||||
- name: Upload frontend
|
||||
uses: svenstaro/upload-release-action@04733e069f2d7f7f0b4aebc4fbdbce8613b03ccd # pin@2.9.0
|
||||
zip -r ../frontend-build.zip *
|
||||
- uses: svenstaro/upload-release-action@04733e069f2d7f7f0b4aebc4fbdbce8613b03ccd # pin@2.9.0
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: src/backend/InvenTree/web/static/frontend-build.zip
|
||||
asset_name: frontend-build.zip
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
- name: Upload Attestation
|
||||
uses: svenstaro/upload-release-action@04733e069f2d7f7f0b4aebc4fbdbce8613b03ccd # pin@2.9.0
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
asset_name: frontend-build.intoto.jsonl
|
||||
file: ${{ steps.attest.outputs.bundle-path}}
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
|
||||
docs:
|
||||
runs-on: ubuntu-24.04
|
||||
name: Build and publish documentation
|
||||
permissions:
|
||||
contents: write
|
||||
env:
|
||||
INVENTREE_DB_ENGINE: sqlite3
|
||||
INVENTREE_DB_NAME: inventree
|
||||
INVENTREE_MEDIA_ROOT: /home/runner/work/InvenTree/test_inventree_media
|
||||
INVENTREE_STATIC_ROOT: /home/runner/work/InvenTree/test_inventree_static
|
||||
INVENTREE_BACKUP_DIR: /home/runner/work/InvenTree/test_inventree_backup
|
||||
INVENTREE_SITE_URL: http://localhost:8000
|
||||
INVENTREE_DEBUG: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
install: true
|
||||
npm: true
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install --require-hashes -r contrib/dev_reqs/requirements.txt
|
||||
pip install --require-hashes -r docs/requirements.txt
|
||||
- name: Build documentation
|
||||
run: |
|
||||
invoke migrate
|
||||
invoke int.export-definitions --basedir "docs"
|
||||
invoke dev.schema --filename docs/schema.yml --ignore-warnings
|
||||
python docs/extract_schema.py docs/schema.yml
|
||||
mkdocs build -f docs/mkdocs.yml
|
||||
- name: Zip build docs
|
||||
run: |
|
||||
cd docs/site
|
||||
zip -r docs-html.zip *
|
||||
- name: Publish documentation
|
||||
uses: svenstaro/upload-release-action@04733e069f2d7f7f0b4aebc4fbdbce8613b03ccd # pin@2.9.0
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: docs/site/docs-html.zip
|
||||
asset_name: docs-html.zip
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
|
||||
8
.github/workflows/scorecard.yaml
vendored
@@ -32,12 +32,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
|
||||
uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
@@ -59,7 +59,7 @@ jobs:
|
||||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
@@ -67,6 +67,6 @@ jobs:
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9
|
||||
uses: github/codeql-action/upload-sarif@b7cec7526559c32f1616476ff32d17ba4c59b2d6 # v3.25.5
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
40
.github/workflows/translations.yaml
vendored
@@ -7,17 +7,16 @@ on:
|
||||
|
||||
env:
|
||||
python_version: 3.9
|
||||
node_version: 20
|
||||
node_version: 18
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
synchronize-with-crowdin:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -31,7 +30,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4.2.2
|
||||
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # pin@v4.1.5
|
||||
- name: Environment Setup
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
@@ -39,30 +38,17 @@ jobs:
|
||||
npm: true
|
||||
apt-dependency: gettext
|
||||
- name: Make Translations
|
||||
run: invoke dev.translate
|
||||
- name: Remove compiled static files
|
||||
run: rm -rf src/backend/InvenTree/static
|
||||
- name: Remove all local changes that are not *.po files
|
||||
run: invoke translate
|
||||
- name: Commit files
|
||||
run: |
|
||||
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git config --local user.name "github-actions[bot]"
|
||||
git add src/backend/InvenTree/locale/en/LC_MESSAGES/django.po src/frontend/src/locales/en/messages.po
|
||||
git commit -m "add translations" || true
|
||||
git reset --hard
|
||||
git reset HEAD~
|
||||
- name: crowdin action
|
||||
uses: crowdin/github-action@8dfaf9c206381653e3767e3cb5ea5f08b45f02bf # pin@v2
|
||||
git checkout -b l10_local
|
||||
git add "*.po"
|
||||
git commit -m "updated translation base"
|
||||
- name: Push changes
|
||||
uses: ad-m/github-push-action@d91a481090679876dfc4178fef17f286781251df # pin@v0.8.0
|
||||
with:
|
||||
upload_sources: true
|
||||
upload_translations: false
|
||||
download_translations: true
|
||||
localization_branch_name: l10_crowdin
|
||||
create_pull_request: true
|
||||
pull_request_title: 'New Crowdin updates'
|
||||
pull_request_body: 'New Crowdin translations by [Crowdin GH Action](https://github.com/crowdin/github-action)'
|
||||
pull_request_base_branch_name: 'master'
|
||||
pull_request_labels: 'translations'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
|
||||
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
branch: l10
|
||||
force: true
|
||||
|
||||
7
.gitignore
vendored
@@ -31,7 +31,6 @@ var/
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
*.sqlite
|
||||
*.sqlite3
|
||||
*.sqlite3-journal
|
||||
*.backup
|
||||
@@ -88,10 +87,6 @@ env/
|
||||
src/backend/InvenTree/InvenTree/locale_stats.json
|
||||
src/backend/InvenTree/InvenTree/licenses.txt
|
||||
|
||||
# Logs
|
||||
src/backend/InvenTree/logs.json
|
||||
src/backend/InvenTree/logs.log
|
||||
|
||||
# node.js
|
||||
node_modules/
|
||||
|
||||
@@ -113,7 +108,5 @@ src/backend/InvenTree/web/static
|
||||
InvenTree/web/static
|
||||
|
||||
# Generated docs files
|
||||
docs/schema.yml
|
||||
docs/docs/api/*.yml
|
||||
docs/docs/api/schema/*.yml
|
||||
inventree_settings.json
|
||||
|
||||
@@ -14,10 +14,7 @@ env:
|
||||
- INVENTREE_BACKUP_DIR=/opt/inventree/backup
|
||||
- INVENTREE_PLUGIN_FILE=/opt/inventree/plugins.txt
|
||||
- INVENTREE_CONFIG_FILE=/opt/inventree/config.yaml
|
||||
- APP_REPO=inventree/InvenTree
|
||||
before_install: contrib/packager.io/preinstall.sh
|
||||
after_install: contrib/packager.io/postinstall.sh
|
||||
before_remove: contrib/packager.io/preinstall.sh
|
||||
before:
|
||||
- contrib/packager.io/before.sh
|
||||
dependencies:
|
||||
@@ -35,7 +32,7 @@ dependencies:
|
||||
- gettext
|
||||
- nginx
|
||||
- jq
|
||||
- "libffi7 | libffi8"
|
||||
- libffi7
|
||||
targets:
|
||||
ubuntu-20.04: true
|
||||
debian-11: true
|
||||
|
||||
@@ -10,73 +10,82 @@ exclude: |
|
||||
)$
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v5.0.0
|
||||
rev: v4.6.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: check-yaml
|
||||
- id: mixed-line-ending
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.7.3
|
||||
rev: v0.4.1
|
||||
hooks:
|
||||
- id: ruff-format
|
||||
args: [--preview]
|
||||
- id: ruff
|
||||
args: [
|
||||
--fix,
|
||||
# --unsafe-fixes,
|
||||
--preview
|
||||
]
|
||||
- repo: https://github.com/astral-sh/uv-pre-commit
|
||||
rev: 0.5.1
|
||||
rev: 0.1.35
|
||||
hooks:
|
||||
- id: pip-compile
|
||||
name: pip-compile requirements-dev.in
|
||||
args: [src/backend/requirements-dev.in, -o, src/backend/requirements-dev.txt, --no-strip-extras, --generate-hashes]
|
||||
args: [src/backend/requirements-dev.in, -o, src/backend/requirements-dev.txt, --python-version=3.9, --no-strip-extras, --generate-hashes]
|
||||
files: src/backend/requirements-dev\.(in|txt)$
|
||||
- id: pip-compile
|
||||
name: pip-compile requirements.txt
|
||||
args: [src/backend/requirements.in, -o, src/backend/requirements.txt, --no-strip-extras, --generate-hashes]
|
||||
args: [src/backend/requirements.in, -o, src/backend/requirements.txt,--python-version=3.9, --no-strip-extras,--generate-hashes]
|
||||
files: src/backend/requirements\.(in|txt)$
|
||||
- id: pip-compile
|
||||
name: pip-compile requirements.txt
|
||||
args: [contrib/dev_reqs/requirements.in, -o, contrib/dev_reqs/requirements.txt, --no-strip-extras, --generate-hashes]
|
||||
args: [contrib/dev_reqs/requirements.in, -o, contrib/dev_reqs/requirements.txt,--python-version=3.9, --no-strip-extras, --generate-hashes]
|
||||
files: contrib/dev_reqs/requirements\.(in|txt)$
|
||||
- id: pip-compile
|
||||
name: pip-compile requirements.txt
|
||||
args: [docs/requirements.in, -o, docs/requirements.txt, --no-strip-extras, --generate-hashes]
|
||||
args: [docs/requirements.in, -o, docs/requirements.txt,--python-version=3.9, --no-strip-extras, --generate-hashes]
|
||||
files: docs/requirements\.(in|txt)$
|
||||
- id: pip-compile
|
||||
name: pip-compile requirements.txt
|
||||
args: [contrib/container/requirements.in, -o, contrib/container/requirements.txt, --python-version=3.11, --no-strip-extras, --generate-hashes]
|
||||
args: [contrib/container/requirements.in, -o, contrib/container/requirements.txt,--python-version=3.11, --no-strip-extras, --generate-hashes]
|
||||
files: contrib/container/requirements\.(in|txt)$
|
||||
- repo: https://github.com/Riverside-Healthcare/djLint
|
||||
rev: v1.36.1
|
||||
rev: v1.34.1
|
||||
hooks:
|
||||
- id: djlint-django
|
||||
- repo: https://github.com/codespell-project/codespell
|
||||
rev: v2.3.0
|
||||
rev: v2.2.6
|
||||
hooks:
|
||||
- id: codespell
|
||||
additional_dependencies:
|
||||
- tomli
|
||||
exclude: >
|
||||
(?x)^(
|
||||
docs/docs/stylesheets/.*|
|
||||
docs/docs/javascripts/.*|
|
||||
docs/docs/webfonts/.* |
|
||||
src/frontend/src/locales/.* |
|
||||
pyproject.toml |
|
||||
src/frontend/vite.config.ts |
|
||||
)$
|
||||
- repo: https://github.com/biomejs/pre-commit
|
||||
rev: "v0.5.0"
|
||||
hooks:
|
||||
- id: biome-check
|
||||
additional_dependencies: ["@biomejs/biome@1.9.4"]
|
||||
files: ^src/frontend/.*\.(js|ts|tsx)$
|
||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||
rev: "v4.0.0-alpha.8"
|
||||
hooks:
|
||||
- id: prettier
|
||||
files: ^src/frontend/.*\.(js|jsx|ts|tsx)$
|
||||
additional_dependencies:
|
||||
- "prettier@^2.4.1"
|
||||
- "@trivago/prettier-plugin-sort-imports"
|
||||
- repo: https://github.com/pre-commit/mirrors-eslint
|
||||
rev: "v9.1.0"
|
||||
hooks:
|
||||
- id: eslint
|
||||
additional_dependencies:
|
||||
- eslint@^8.41.0
|
||||
- eslint-config-google@^0.14.0
|
||||
- eslint-plugin-react@6.10.3
|
||||
- babel-eslint@6.1.2
|
||||
- "@typescript-eslint/eslint-plugin@latest"
|
||||
- "@typescript-eslint/parser"
|
||||
files: ^src/frontend/.*\.(js|jsx|ts|tsx)$
|
||||
- repo: https://github.com/gitleaks/gitleaks
|
||||
rev: v8.21.2
|
||||
rev: v8.18.2
|
||||
hooks:
|
||||
- id: gitleaks
|
||||
#- repo: https://github.com/jumanjihouse/pre-commit-hooks
|
||||
|
||||
5
.vscode/extensions.json
vendored
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"biomejs.biome"
|
||||
]
|
||||
}
|
||||
26
.vscode/launch.json
vendored
@@ -6,37 +6,19 @@
|
||||
"configurations": [
|
||||
{
|
||||
"name": "InvenTree Server",
|
||||
"type": "debugpy",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/src/backend/InvenTree/manage.py",
|
||||
"args": [
|
||||
"runserver",
|
||||
// "0.0.0.0:8000", // expose server in network (useful for testing with mobile app)
|
||||
// "--noreload" // disable auto-reload
|
||||
],
|
||||
"django": true,
|
||||
"justMyCode": true
|
||||
},
|
||||
{
|
||||
"name": "InvenTree Server - Tests",
|
||||
"type": "debugpy",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/src/backend/InvenTree/manage.py",
|
||||
"args": [
|
||||
"test",
|
||||
// "part.test_api.PartCategoryAPITest", // run only a specific test
|
||||
],
|
||||
"args": ["runserver"],
|
||||
"django": true,
|
||||
"justMyCode": true
|
||||
},
|
||||
{
|
||||
"name": "InvenTree Server - 3rd party",
|
||||
"type": "debugpy",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/src/backend/InvenTree/manage.py",
|
||||
"args": [
|
||||
"runserver"
|
||||
],
|
||||
"args": ["runserver"],
|
||||
"django": true,
|
||||
"justMyCode": false
|
||||
},
|
||||
|
||||
8
.vscode/settings.json
vendored
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "biomejs.biome"
|
||||
},
|
||||
"editor.codeActionsOnSave": {
|
||||
"quickfix.biome": "explicit"
|
||||
}
|
||||
}
|
||||
20
.vscode/tasks.json
vendored
@@ -9,61 +9,61 @@
|
||||
{
|
||||
"label": "worker",
|
||||
"type": "shell",
|
||||
"command": "invoke worker",
|
||||
"command": "inv worker",
|
||||
"problemMatcher": [],
|
||||
},
|
||||
{
|
||||
"label": "clean-settings",
|
||||
"type": "shell",
|
||||
"command": "invoke int.clean-settings",
|
||||
"command": "inv clean-settings",
|
||||
"problemMatcher": [],
|
||||
},
|
||||
{
|
||||
"label": "delete-data",
|
||||
"type": "shell",
|
||||
"command": "invoke dev.delete-data",
|
||||
"command": "inv delete-data",
|
||||
"problemMatcher": [],
|
||||
},
|
||||
{
|
||||
"label": "migrate",
|
||||
"type": "shell",
|
||||
"command": "invoke migrate",
|
||||
"command": "inv migrate",
|
||||
"problemMatcher": [],
|
||||
},
|
||||
{
|
||||
"label": "server",
|
||||
"type": "shell",
|
||||
"command": "invoke dev.server",
|
||||
"command": "inv server",
|
||||
"problemMatcher": [],
|
||||
},
|
||||
{
|
||||
"label": "setup-dev",
|
||||
"type": "shell",
|
||||
"command": "invoke dev.setup-dev",
|
||||
"command": "inv setup-dev",
|
||||
"problemMatcher": [],
|
||||
},
|
||||
{
|
||||
"label": "setup-test",
|
||||
"type": "shell",
|
||||
"command": "invoke dev.setup-test -i --path dev/inventree-demo-dataset",
|
||||
"command": "inv setup-test -i --path dev/inventree-demo-dataset",
|
||||
"problemMatcher": [],
|
||||
},
|
||||
{
|
||||
"label": "superuser",
|
||||
"type": "shell",
|
||||
"command": "invoke superuser",
|
||||
"command": "inv superuser",
|
||||
"problemMatcher": [],
|
||||
},
|
||||
{
|
||||
"label": "test",
|
||||
"type": "shell",
|
||||
"command": "invoke dev.test",
|
||||
"command": "inv test",
|
||||
"problemMatcher": [],
|
||||
},
|
||||
{
|
||||
"label": "update",
|
||||
"type": "shell",
|
||||
"command": "invoke update",
|
||||
"command": "inv update",
|
||||
"problemMatcher": [],
|
||||
},
|
||||
]
|
||||
|
||||
@@ -39,7 +39,7 @@ InvenTree/
|
||||
│ │ ├─ tsconfig.json # Settings for frontend compilation
|
||||
├─ .pkgr.yml # Build definition for Debian/Ubuntu packages
|
||||
├─ .pre-commit-config.yaml # Code formatter/linter configuration
|
||||
├─ CONTRIBUTING.md # Contribution guidelines and overview
|
||||
├─ CONTRIBUTING.md # Contirbution guidelines and overview
|
||||
├─ Procfile # Process definition for Debian/Ubuntu packages
|
||||
├─ README.md # General project information and overview
|
||||
├─ runtime.txt # Python runtime settings for Debian/Ubuntu packages build
|
||||
|
||||
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 - InvenTree Developers
|
||||
Copyright (c) 2017-2022 InvenTree
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
36
README.md
@@ -4,14 +4,13 @@
|
||||
<p>Open Source Inventory Management System </p>
|
||||
|
||||
<!-- Badges -->
|
||||
[](https://opensource.org/license/MIT)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||

|
||||
[](https://inventree.readthedocs.io/en/latest/?badge=latest)
|
||||

|
||||
[](https://app.netlify.com/sites/inventree/deploys)
|
||||
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/7179)
|
||||
[](https://securityscorecards.dev/viewer/?uri=github.com/inventree/InvenTree)
|
||||
[](https://app.netlify.com/sites/inventree/deploys)
|
||||
[](https://sonarcloud.io/summary/new_code?id=inventree_InvenTree)
|
||||
|
||||
[](https://codecov.io/gh/inventree/InvenTree)
|
||||
@@ -19,10 +18,10 @@
|
||||

|
||||
[](https://hub.docker.com/r/inventree/inventree)
|
||||
|
||||
[](https://github.com/inventree/InvenTree/)
|
||||

|
||||
[](https://twitter.com/inventreedb)
|
||||
[](https://www.reddit.com/r/InvenTree/)
|
||||
[](https://chaos.social/@InvenTree)
|
||||
|
||||
|
||||
<h4>
|
||||
<a href="https://demo.inventree.org/">View Demo</a>
|
||||
@@ -67,7 +66,7 @@ InvenTree is designed to be **extensible**, and provides multiple options for **
|
||||
<li><a href="https://www.djangoproject.com/">Django</a></li>
|
||||
<li><a href="https://www.django-rest-framework.org/">DRF</a></li>
|
||||
<li><a href="https://django-q.readthedocs.io/">Django Q</a></li>
|
||||
<li><a href="https://docs.allauth.org/">Django-Allauth</a></li>
|
||||
<li><a href="https://django-allauth.readthedocs.io/">Django-Allauth</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
@@ -82,7 +81,7 @@ InvenTree is designed to be **extensible**, and provides multiple options for **
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Client - CUI</summary>
|
||||
<summary>Client</summary>
|
||||
<ul>
|
||||
<li><a href="https://getbootstrap.com/">Bootstrap</a></li>
|
||||
<li><a href="https://jquery.com/">jQuery</a></li>
|
||||
@@ -90,27 +89,13 @@ InvenTree is designed to be **extensible**, and provides multiple options for **
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Client - PUI</summary>
|
||||
<ul>
|
||||
<li><a href="https://react.dev/">React</a></li>
|
||||
<li><a href="https://lingui.dev/">Lingui</a></li>
|
||||
<li><a href="https://reactrouter.com/">React Router</a></li>
|
||||
<li><a href="https://tanstack.com/query/">TanStack Query</a></li>
|
||||
<li><a href="https://github.com/pmndrs/zustand">Zustand</a></li>
|
||||
<li><a href="https://mantine.dev/">Mantine</a></li>
|
||||
<li><a href="https://icflorescu.github.io/mantine-datatable/">Mantine Data Table</a></li>
|
||||
<li><a href="https://codemirror.net/">CodeMirror</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>DevOps</summary>
|
||||
<ul>
|
||||
<li><a href="https://hub.docker.com/r/inventree/inventree">Docker</a></li>
|
||||
<li><a href="https://crowdin.com/project/inventree">Crowdin</a></li>
|
||||
<li><a href="https://app.codecov.io/gh/inventree/InvenTree">Codecov</a></li>
|
||||
<li><a href="https://sonarcloud.io/project/overview?id=inventree_InvenTree">SonarCloud</a></li>
|
||||
<li><a href="https://app.deepsource.com/gh/inventree/InvenTree">DeepSource</a></li>
|
||||
<li><a href="https://packager.io/gh/inventree/InvenTree">Packager.io</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
@@ -138,7 +123,7 @@ Refer to the [getting started guide](https://docs.inventree.org/en/latest/start/
|
||||
<!-- Mobile App -->
|
||||
## :iphone: Mobile App
|
||||
|
||||
InvenTree is supported by a [companion mobile app](https://docs.inventree.org/app/) which allows users access to stock control information and functionality.
|
||||
InvenTree is supported by a [companion mobile app](https://docs.inventree.org/en/latest/app/app/) which allows users access to stock control information and functionality.
|
||||
|
||||
<div align="center"><h4>
|
||||
<a href="https://play.google.com/store/apps/details?id=inventree.inventree_app">Android Play Store</a>
|
||||
@@ -164,7 +149,10 @@ If you use InvenTree and find it to be useful, please consider [sponsoring the p
|
||||
<!-- Acknowledgments -->
|
||||
## :gem: Acknowledgements
|
||||
|
||||
We want to acknowledge [PartKeepr](https://github.com/partkeepr/PartKeepr) as a valuable predecessor and inspiration.
|
||||
We would like to acknowledge a few special projects:
|
||||
- [PartKeepr](https://github.com/partkeepr/PartKeepr) as a valuable predecessor and inspiration
|
||||
- [Readme Template](https://github.com/Louis3797/awesome-readme-template) for the template of this page
|
||||
|
||||
Find a full list of used third-party libraries in [our documentation](https://docs.inventree.org/en/latest/credits/).
|
||||
|
||||
## :heart: Support
|
||||
|
||||
40
biome.json
@@ -1,40 +0,0 @@
|
||||
{
|
||||
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
|
||||
"javascript": {
|
||||
"formatter": {
|
||||
"quoteStyle": "single",
|
||||
"jsxQuoteStyle": "single",
|
||||
"trailingCommas": "none",
|
||||
"indentStyle": "space"
|
||||
}
|
||||
},
|
||||
"linter": {
|
||||
"rules": {
|
||||
"suspicious" : {
|
||||
"noExplicitAny": "off",
|
||||
"noDoubleEquals": "off",
|
||||
"noArrayIndexKey": "off",
|
||||
"useDefaultSwitchClauseLast": "off"
|
||||
},
|
||||
"style": {
|
||||
"noUselessElse": "off",
|
||||
"noNonNullAssertion": "off",
|
||||
"noParameterAssign": "off"
|
||||
}, "correctness":{
|
||||
"useExhaustiveDependencies": "off",
|
||||
"useJsxKeyInIterable": "off",
|
||||
"noUnsafeOptionalChaining": "off",
|
||||
"noSwitchDeclarations": "off",
|
||||
"noUnusedImports":"error"
|
||||
}, "complexity": {
|
||||
"noBannedTypes": "off",
|
||||
"noExtraBooleanCast": "off",
|
||||
"noForEach": "off",
|
||||
"noUselessSwitchCase": "off",
|
||||
"useLiteralKeys":"off"
|
||||
}, "performance": {
|
||||
"noDelete":"off"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ coverage:
|
||||
project:
|
||||
default:
|
||||
target: 82%
|
||||
patch: off
|
||||
|
||||
github_checks:
|
||||
annotations: true
|
||||
@@ -27,11 +26,3 @@ flag_management:
|
||||
statuses:
|
||||
- type: project
|
||||
target: 45%
|
||||
|
||||
comment:
|
||||
require_bundle_changes: True
|
||||
bundle_change_threshold: "1Kb"
|
||||
|
||||
bundle_analysis:
|
||||
warning_threshold: "5%"
|
||||
status: "informational"
|
||||
|
||||
@@ -1,55 +1,49 @@
|
||||
# InvenTree environment variables for docker compose deployment
|
||||
# For a full list of the available configuration options, refer to the InvenTree documentation:
|
||||
# https://docs.inventree.org/en/stable/start/config/
|
||||
|
||||
# Specify the name of the docker-compose project
|
||||
COMPOSE_PROJECT_NAME=inventree
|
||||
|
||||
# InvenTree version tag (e.g. 'stable' / 'latest' / 'x.x.x')
|
||||
INVENTREE_TAG=stable
|
||||
|
||||
# InvenTree server URL - update this to match your server URL
|
||||
INVENTREE_SITE_URL="http://inventree.localhost"
|
||||
#INVENTREE_SITE_URL="http://192.168.1.2" # You can specify a local IP address here
|
||||
#INVENTREE_SITE_URL="https://inventree.my-domain.com" # Or a public domain name (which you control)
|
||||
|
||||
# Specify the location of the external data volume
|
||||
# By default, placed in local directory 'inventree-data'
|
||||
INVENTREE_EXT_VOLUME=./inventree-data
|
||||
|
||||
# Ensure debug is false for a production setup
|
||||
INVENTREE_DEBUG=False
|
||||
INVENTREE_LOG_LEVEL=WARNING
|
||||
|
||||
# InvenTree admin account details
|
||||
# Un-comment (and complete) these lines to auto-create an admin acount
|
||||
#INVENTREE_ADMIN_USER=
|
||||
#INVENTREE_ADMIN_PASSWORD=
|
||||
#INVENTREE_ADMIN_EMAIL=
|
||||
|
||||
# Database configuration options
|
||||
INVENTREE_DB_ENGINE=postgresql
|
||||
INVENTREE_DB_NAME=inventree
|
||||
INVENTREE_DB_HOST=inventree-db
|
||||
INVENTREE_DB_PORT=5432
|
||||
|
||||
# Database credentials - These should be changed from the default values!
|
||||
INVENTREE_DB_USER=pguser
|
||||
INVENTREE_DB_PASSWORD=pgpassword
|
||||
|
||||
# Redis cache setup (disabled by default)
|
||||
# Un-comment the following lines to enable Redis cache
|
||||
# Note that you will also have to run docker-compose with the --profile redis command
|
||||
# Refer to settings.py for other cache options
|
||||
#INVENTREE_CACHE_HOST=inventree-cache
|
||||
#INVENTREE_CACHE_PORT=6379
|
||||
|
||||
# Options for gunicorn server
|
||||
INVENTREE_GUNICORN_TIMEOUT=90
|
||||
|
||||
# Enable custom plugins?
|
||||
INVENTREE_PLUGINS_ENABLED=True
|
||||
|
||||
# Run migrations automatically?
|
||||
INVENTREE_AUTO_UPDATE=True
|
||||
|
||||
# InvenTree superuser account details
|
||||
# Un-comment (and complete) these lines to auto-create an admin account
|
||||
#INVENTREE_ADMIN_USER=
|
||||
#INVENTREE_ADMIN_PASSWORD=
|
||||
#INVENTREE_ADMIN_EMAIL=
|
||||
# Image tag that should be used
|
||||
INVENTREE_TAG=stable
|
||||
|
||||
# Database configuration options
|
||||
# DO NOT CHANGE THESE SETTINGS (unless you really know what you are doing)
|
||||
INVENTREE_DB_ENGINE=postgresql
|
||||
INVENTREE_DB_NAME=inventree
|
||||
INVENTREE_DB_HOST=inventree-db
|
||||
INVENTREE_DB_PORT=5432
|
||||
# Site URL - update this to match your host
|
||||
INVENTREE_SITE_URL="http://inventree.localhost"
|
||||
|
||||
# Database credentials - These should be changed from the default values!
|
||||
# Note: These are *NOT* the InvenTree server login credentials,
|
||||
# they are the credentials for the PostgreSQL database
|
||||
INVENTREE_DB_USER=pguser
|
||||
INVENTREE_DB_PASSWORD=pgpassword
|
||||
|
||||
# Redis cache setup
|
||||
# Refer to the documentation for other cache options
|
||||
INVENTREE_CACHE_ENABLED=True
|
||||
INVENTREE_CACHE_HOST=inventree-cache
|
||||
INVENTREE_CACHE_PORT=6379
|
||||
|
||||
# Options for gunicorn server
|
||||
INVENTREE_GUNICORN_TIMEOUT=90
|
||||
COMPOSE_PROJECT_NAME=inventree
|
||||
|
||||
@@ -1,21 +1,17 @@
|
||||
# Example Caddyfile for InvenTree
|
||||
# Example Caddyfile for Inventree
|
||||
# The following environment variables may be used:
|
||||
# - INVENTREE_SITE_URL: The upstream URL of the InvenTree site (default: inventree.localhost)
|
||||
# - INVENTREE_SERVER: The internal URL of the InvenTree container (default: http://inventree-server:8000)
|
||||
# - INVENTREE_SITE_URL: The upstream URL of the Inventree site (default: inventree.localhost)
|
||||
# - INVENTREE_SERVER: The internal URL of the Inventree container (default: http://inventree-server:8000)
|
||||
#
|
||||
# Note that while this file is a good starting point, it may need to be modified to suit your specific requirements
|
||||
#
|
||||
# Ref to the Caddyfile documentation: https://caddyserver.com/docs/caddyfile
|
||||
|
||||
|
||||
# Logging configuration for Caddy
|
||||
(log_common) {
|
||||
log {
|
||||
output file /var/log/caddy/{args[0]}.access.log
|
||||
}
|
||||
}
|
||||
|
||||
# CORS headers control (used for static and media files)
|
||||
(cors-headers) {
|
||||
header Allow GET,HEAD,OPTIONS
|
||||
header Access-Control-Allow-Origin *
|
||||
@@ -29,10 +25,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
# The default server address is configured in the .env file
|
||||
# If not specified, the default address is used - http://inventree.localhost
|
||||
# If you need to listen on multiple addresses, or use a different port, you can modify this section directly
|
||||
{$INVENTREE_SITE_URL:http://inventree.localhost} {
|
||||
# Change the host to your domain (this will serve at inventree.localhost)
|
||||
{$INVENTREE_SITE_URL:inventree.localhost} {
|
||||
import log_common inventree
|
||||
|
||||
encode gzip
|
||||
@@ -41,7 +35,6 @@
|
||||
max_size 100MB
|
||||
}
|
||||
|
||||
# Handle static request files
|
||||
handle_path /static/* {
|
||||
import cors-headers static
|
||||
|
||||
@@ -49,29 +42,18 @@
|
||||
file_server
|
||||
}
|
||||
|
||||
# Handle media request files
|
||||
handle_path /media/* {
|
||||
import cors-headers media
|
||||
|
||||
root * /var/www/media
|
||||
file_server
|
||||
|
||||
# Force download of media files (for security)
|
||||
# Comment out this line if you do not want to force download
|
||||
header Content-Disposition attachment
|
||||
|
||||
# Authentication is handled by the forward_auth directive
|
||||
# This is required to ensure that media files are only accessible to authenticated users
|
||||
forward_auth {$INVENTREE_SERVER:"http://inventree-server:8000"} {
|
||||
uri /auth/
|
||||
}
|
||||
}
|
||||
|
||||
# All other requests are proxied to the InvenTree server
|
||||
reverse_proxy {$INVENTREE_SERVER:"http://inventree-server:8000"} {
|
||||
|
||||
# If you are running behind another proxy, you may need to specify 'trusted_proxies'
|
||||
# Ref: https://caddyserver.com/docs/json/apps/http/servers/trusted_proxies/
|
||||
# trusted_proxies ...
|
||||
}
|
||||
reverse_proxy {$INVENTREE_SERVER:"http://inventree-server:8000"}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
ARG base_image=python:3.11-alpine3.18
|
||||
FROM ${base_image} AS inventree_base
|
||||
ARG base_image
|
||||
|
||||
# Build arguments for this image
|
||||
ARG commit_tag=""
|
||||
@@ -49,18 +48,13 @@ ENV INVENTREE_BACKGROUND_WORKERS="4"
|
||||
ENV INVENTREE_WEB_ADDR=0.0.0.0
|
||||
ENV INVENTREE_WEB_PORT=8000
|
||||
|
||||
LABEL org.opencontainers.image.created=${DATE} \
|
||||
org.opencontainers.image.vendor="inventree" \
|
||||
org.opencontainers.image.title="InvenTree backend server" \
|
||||
org.opencontainers.image.description="InvenTree is the open-source inventory management system" \
|
||||
org.opencontainers.image.url="https://inventree.org" \
|
||||
org.opencontainers.image.documentation="https://docs.inventree.org" \
|
||||
org.opencontainers.image.source="https://github.com/inventree/InvenTree" \
|
||||
org.opencontainers.image.revision=${commit_hash} \
|
||||
org.opencontainers.image.licenses="MIT" \
|
||||
org.opencontainers.image.base.name="docker.io/library/${base_image}" \
|
||||
org.opencontainers.image.version=${commit_tag}
|
||||
|
||||
LABEL org.label-schema.schema-version="1.0" \
|
||||
org.label-schema.build-date=${DATE} \
|
||||
org.label-schema.vendor="inventree" \
|
||||
org.label-schema.name="inventree/inventree" \
|
||||
org.label-schema.url="https://hub.docker.com/r/inventree/inventree" \
|
||||
org.label-schema.vcs-url="https://github.com/inventree/InvenTree.git" \
|
||||
org.label-schema.vcs-ref=${commit_tag}
|
||||
|
||||
# Install required system level packages
|
||||
RUN apk add --no-cache \
|
||||
@@ -70,13 +64,12 @@ RUN apk add --no-cache \
|
||||
# Weasyprint requirements : https://doc.courtbouillon.org/weasyprint/stable/first_steps.html#alpine-3-12
|
||||
py3-pip py3-pillow py3-cffi py3-brotli pango poppler-utils openldap \
|
||||
# Postgres client
|
||||
postgresql15-client \
|
||||
postgresql13-client \
|
||||
# MySQL / MariaDB client
|
||||
mariadb-client mariadb-connector-c \
|
||||
&& \
|
||||
# font support
|
||||
apk --update --upgrade --no-cache add fontconfig ttf-freefont font-terminus font-noto font-noto-cjk font-noto-extra \
|
||||
&& fc-cache -f
|
||||
# fonts
|
||||
apk --update --upgrade --no-cache add fontconfig ttf-freefont font-noto terminus-font && fc-cache -f
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
@@ -115,7 +108,7 @@ RUN apk add --no-cache --update nodejs npm yarn
|
||||
RUN yarn config set network-timeout 600000 -g
|
||||
COPY src ${INVENTREE_HOME}/src
|
||||
COPY tasks.py ${INVENTREE_HOME}/tasks.py
|
||||
RUN cd ${INVENTREE_HOME} && invoke int.frontend-compile
|
||||
RUN cd ${INVENTREE_HOME} && inv frontend-compile
|
||||
|
||||
# InvenTree production image:
|
||||
# - Copies required files from local directory
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
version: "3.8"
|
||||
|
||||
# Docker compose recipe for InvenTree development server
|
||||
# - Runs PostgreSQL as the database backend
|
||||
# - Uses built-in django webserver
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
version: "3.8"
|
||||
|
||||
# Docker compose recipe for a production-ready InvenTree setup, with the following containers:
|
||||
# - PostgreSQL as the database backend
|
||||
# - gunicorn as the InvenTree web server
|
||||
@@ -51,9 +53,14 @@ services:
|
||||
restart: unless-stopped
|
||||
|
||||
# redis acts as database cache manager
|
||||
# only runs under the "redis" profile : https://docs.docker.com/compose/profiles/
|
||||
inventree-cache:
|
||||
image: redis:7.0
|
||||
container_name: inventree-cache
|
||||
depends_on:
|
||||
- inventree-db
|
||||
profiles:
|
||||
- redis
|
||||
env_file:
|
||||
- .env
|
||||
expose:
|
||||
@@ -71,7 +78,6 @@ services:
|
||||
- 8000
|
||||
depends_on:
|
||||
- inventree-db
|
||||
- inventree-cache
|
||||
env_file:
|
||||
- .env
|
||||
volumes:
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#!/bin/ash
|
||||
|
||||
# Install system packages required for building InvenTree python libraries
|
||||
# Note that for postgreslql, we use the version 13, which matches the version used in the InvenTree docker image
|
||||
# Note that for postgreslql, we use the 13 version, which matches the version used in the InvenTree docker image
|
||||
|
||||
apk add gcc g++ musl-dev openssl-dev libffi-dev cargo python3-dev openldap-dev \
|
||||
libstdc++ build-base linux-headers py3-grpcio \
|
||||
jpeg-dev openjpeg-dev libwebp-dev zlib-dev \
|
||||
sqlite sqlite-dev \
|
||||
mariadb-connector-c-dev mariadb-client mariadb-dev \
|
||||
postgresql15-dev postgresql-libs \
|
||||
postgresql13-dev postgresql-libs \
|
||||
$@
|
||||
|
||||
@@ -17,7 +17,6 @@ gunicorn>=22.0.0
|
||||
# LDAP required packages
|
||||
django-auth-ldap # Django integration for ldap auth
|
||||
python-ldap # LDAP auth support
|
||||
django<5.0 # Force lower to match main project
|
||||
|
||||
# Upgraded python package installer
|
||||
uv
|
||||
|
||||
@@ -4,232 +4,217 @@ asgiref==3.8.1 \
|
||||
--hash=sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47 \
|
||||
--hash=sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590
|
||||
# via django
|
||||
django==4.2.17 \
|
||||
--hash=sha256:3a93350214ba25f178d4045c0786c61573e7dbfa3c509b3551374f1e11ba8de0 \
|
||||
--hash=sha256:6b56d834cc94c8b21a8f4e775064896be3b4a4ca387f2612d4406a5927cd2fdc
|
||||
# via
|
||||
# -r contrib/container/requirements.in
|
||||
# django-auth-ldap
|
||||
django-auth-ldap==5.1.0 \
|
||||
--hash=sha256:9c607e8d9c53cf2a0ccafbe0acfc33eb1d1fd474c46ec52d30aee0dca1da9668 \
|
||||
--hash=sha256:a5f7bdb54b2ab80e4e9eb080cd3e06e89e4c9d2d534ddb39b66cd970dd6d3536
|
||||
# via -r contrib/container/requirements.in
|
||||
gunicorn==23.0.0 \
|
||||
--hash=sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d \
|
||||
--hash=sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec
|
||||
# via -r contrib/container/requirements.in
|
||||
django==4.2.11 \
|
||||
--hash=sha256:6e6ff3db2d8dd0c986b4eec8554c8e4f919b5c1ff62a5b4390c17aff2ed6e5c4 \
|
||||
--hash=sha256:ddc24a0a8280a0430baa37aff11f28574720af05888c62b7cfe71d219f4599d3
|
||||
# via django-auth-ldap
|
||||
django-auth-ldap==4.8.0 \
|
||||
--hash=sha256:4b4b944f3c28bce362f33fb6e8db68429ed8fd8f12f0c0c4b1a4344a7ef225ce \
|
||||
--hash=sha256:604250938ddc9fda619f247c7a59b0b2f06e53a7d3f46a156f28aa30dd71a738
|
||||
gunicorn==22.0.0 \
|
||||
--hash=sha256:350679f91b24062c86e386e198a15438d53a7a8207235a78ba1b53df4c4378d9 \
|
||||
--hash=sha256:4a0b436239ff76fb33f11c07a16482c521a7e09c1ce3cc293c2330afe01bec63
|
||||
invoke==2.2.0 \
|
||||
--hash=sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820 \
|
||||
--hash=sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5
|
||||
# via -r contrib/container/requirements.in
|
||||
mariadb==1.1.11 \
|
||||
--hash=sha256:0f8de8d66ca71bd102f34a970a331b7d75bdf7f8050d80e37cdcc6ff3c85cf7a \
|
||||
--hash=sha256:2e72ea65f1d7d8563ee84e172f2a583193092bdb6ff83c470ca9722873273ecc \
|
||||
--hash=sha256:3f64b520089cb60c4f8302f365ed0ae057c4c859ab70fc8b1c4358192c3c8f27 \
|
||||
--hash=sha256:579420293fa790d5ae0a6cb4bdb7e8be8facc2ceefb6123c2b0e8042b3fa725d \
|
||||
--hash=sha256:6f28d8ccc597a3a1368be14078110f743900dbb3b0c7f1cce3072d83bec59c8a \
|
||||
--hash=sha256:c1992ebf9c6f012ac158e33fef9f2c4ba899f721064c4ae3a3489233793296c0 \
|
||||
--hash=sha256:cf6647cee081e21d0994b409ba8c8fa2077f3972f1de3627c5502fb31d14f806 \
|
||||
--hash=sha256:d7302ccd15f0beee7b286885cbf6ac71ddc240374691d669784d99f89ba34d79 \
|
||||
--hash=sha256:dbc4cf0e302ca82d46f9431a0b04f048e9c21ee56d6f3162c29605f84d63b40c \
|
||||
--hash=sha256:e94f1738bec09c97b601ddbb1908eb24524ba4630f507a775d82ffdb6c5794b3 \
|
||||
--hash=sha256:f6dfdc954edf02b6519419a054798cda6034dc459d1d482e3329e37aa27d34f0
|
||||
# via -r contrib/container/requirements.in
|
||||
mysqlclient==2.2.6 \
|
||||
--hash=sha256:3da70a07753ba6be881f7d75e795e254f6a0c12795778034acc69769b0649d37 \
|
||||
--hash=sha256:43c5b30be0675080b9c815f457d73397f0442173e7be83d089b126835e2617ae \
|
||||
--hash=sha256:794857bce4f9a1903a99786dd29ad7887f45a870b3d11585b8c51c4a753c4174 \
|
||||
--hash=sha256:b0a5cddf1d3488b254605041070086cac743401d876a659a72d706a0d89c8ebb \
|
||||
--hash=sha256:c0b46d9b78b461dbb62482089ca8040fa916595b1b30f831ebbd1b0a82b43d53 \
|
||||
--hash=sha256:e940b41d85dfd7b190fa47d52f525f878cfa203d4653bf6a35b271b3c3be125b \
|
||||
--hash=sha256:e94a92858203d97fd584bdb6d7ee8c56f2590db8d77fd44215c0dcf5e739bc37 \
|
||||
--hash=sha256:f3efb849d6f7ef4b9788a0eda2e896b975e0ebf1d6bf3dcabea63fd698e5b0b5
|
||||
# via -r contrib/container/requirements.in
|
||||
packaging==24.2 \
|
||||
--hash=sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759 \
|
||||
--hash=sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f
|
||||
mariadb==1.1.10 \
|
||||
--hash=sha256:03d6284ef713d1cad40146576a4cc2d6cbc1662060f2a0e59b174e1694521698 \
|
||||
--hash=sha256:1ce87971c02375236ff8933e6c593c748e7b2f2950b86eabfab4289fd250ea63 \
|
||||
--hash=sha256:1d81b22efbaaf4c5bc5e4cc4e2ef3c459538c1a939371089d8c5591d6f26a62e \
|
||||
--hash=sha256:29040e426f877ddc45f337c6eb381b6bbab63cc6bf8431a28effe30162142513 \
|
||||
--hash=sha256:4521aa721f926946bd71491f872e8babc78fa97755ed2114f5684b77363107cb \
|
||||
--hash=sha256:49200378c614984f5ec875481662a49d7c97c2be27970b01b32fa4b7520d4e22 \
|
||||
--hash=sha256:5d652117e2fdf12b9723e7452a05fce9e6ccbae6ea48871b21a3a8fde259dc48 \
|
||||
--hash=sha256:8c8c6b27486b0e1772a23002c702b5fd244eecf9f05633dd6cb345fc26755a20 \
|
||||
--hash=sha256:a332893e3ef7ceb7970ab4bd7c844bcb4bd68a051ca51313566f9808d7411f2d \
|
||||
--hash=sha256:d7b09ec4abd02ed235257feb769f90cd4066e8f536b55b92f5166103d5b66a63 \
|
||||
--hash=sha256:dff8b28ce4044574870d7bdd2d9f9f5da8e5f95a7ff6d226185db733060d1a93
|
||||
mysqlclient==2.2.4 \
|
||||
--hash=sha256:329e4eec086a2336fe3541f1ce095d87a6f169d1cc8ba7b04ac68bcb234c9711 \
|
||||
--hash=sha256:33bc9fb3464e7d7c10b1eaf7336c5ff8f2a3d3b88bab432116ad2490beb3bf41 \
|
||||
--hash=sha256:3c318755e06df599338dad7625f884b8a71fcf322a9939ef78c9b3db93e1de7a \
|
||||
--hash=sha256:4e80dcad884dd6e14949ac6daf769123223a52a6805345608bf49cdaf7bc8b3a \
|
||||
--hash=sha256:9d3310295cb682232cadc28abd172f406c718b9ada41d2371259098ae37779d3 \
|
||||
--hash=sha256:9d4c015480c4a6b2b1602eccd9846103fc70606244788d04aa14b31c4bd1f0e2 \
|
||||
--hash=sha256:ac44777eab0a66c14cb0d38965572f762e193ec2e5c0723bcd11319cc5b693c5 \
|
||||
--hash=sha256:d43987bb9626096a302ca6ddcdd81feaeca65ced1d5fe892a6a66b808326aa54 \
|
||||
--hash=sha256:e1ebe3f41d152d7cb7c265349fdb7f1eca86ccb0ca24a90036cde48e00ceb2ab
|
||||
packaging==24.0 \
|
||||
--hash=sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5 \
|
||||
--hash=sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9
|
||||
# via
|
||||
# gunicorn
|
||||
# mariadb
|
||||
psycopg[binary, pool]==3.2.3 \
|
||||
--hash=sha256:644d3973fe26908c73d4be746074f6e5224b03c1101d302d9a53bf565ad64907 \
|
||||
--hash=sha256:a5764f67c27bec8bfac85764d23c534af2c27b893550377e37ce59c12aac47a2
|
||||
# via -r contrib/container/requirements.in
|
||||
psycopg-binary==3.2.3 \
|
||||
--hash=sha256:0463a11b1cace5a6aeffaf167920707b912b8986a9c7920341c75e3686277920 \
|
||||
--hash=sha256:05a1bdce30356e70a05428928717765f4a9229999421013f41338d9680d03a63 \
|
||||
--hash=sha256:06b5cc915e57621eebf2393f4173793ed7e3387295f07fed93ed3fb6a6ccf585 \
|
||||
--hash=sha256:07d019a786eb020c0f984691aa1b994cb79430061065a694cf6f94056c603d26 \
|
||||
--hash=sha256:09baa041856b35598d335b1a74e19a49da8500acedf78164600694c0ba8ce21b \
|
||||
--hash=sha256:1303bf8347d6be7ad26d1362af2c38b3a90b8293e8d56244296488ee8591058e \
|
||||
--hash=sha256:192a5f8496e6e1243fdd9ac20e117e667c0712f148c5f9343483b84435854c78 \
|
||||
--hash=sha256:1985ab05e9abebfbdf3163a16ebb37fbc5d49aff2bf5b3d7375ff0920bbb54cd \
|
||||
--hash=sha256:1f8b0d0e99d8e19923e6e07379fa00570be5182c201a8c0b5aaa9a4d4a4ea20b \
|
||||
--hash=sha256:257c4aea6f70a9aef39b2a77d0658a41bf05c243e2bf41895eb02220ac6306f3 \
|
||||
--hash=sha256:261f0031ee6074765096a19b27ed0f75498a8338c3dcd7f4f0d831e38adf12d1 \
|
||||
--hash=sha256:2773f850a778575dd7158a6dd072f7925b67f3ba305e2003538e8831fec77a1d \
|
||||
--hash=sha256:2a29f5294b0b6360bfda69653697eff70aaf2908f58d1073b0acd6f6ab5b5a4f \
|
||||
--hash=sha256:2bb342a01c76f38a12432848e6013c57eb630103e7556cf79b705b53814c3949 \
|
||||
--hash=sha256:2c0419cdad8c70eaeb3116bb28e7b42d546f91baf5179d7556f230d40942dc78 \
|
||||
--hash=sha256:3bffb61e198a91f712cc3d7f2d176a697cb05b284b2ad150fb8edb308eba9002 \
|
||||
--hash=sha256:41fdec0182efac66b27478ac15ef54c9ebcecf0e26ed467eb7d6f262a913318b \
|
||||
--hash=sha256:48f8ca6ee8939bab760225b2ab82934d54330eec10afe4394a92d3f2a0c37dd6 \
|
||||
--hash=sha256:4926ea5c46da30bec4a85907aa3f7e4ea6313145b2aa9469fdb861798daf1502 \
|
||||
--hash=sha256:4c57615791a337378fe5381143259a6c432cdcbb1d3e6428bfb7ce59fff3fb5c \
|
||||
--hash=sha256:4e76ce2475ed4885fe13b8254058be710ec0de74ebd8ef8224cf44a9a3358e5f \
|
||||
--hash=sha256:5361ea13c241d4f0ec3f95e0bf976c15e2e451e9cc7ef2e5ccfc9d170b197a40 \
|
||||
--hash=sha256:5905729668ef1418bd36fbe876322dcb0f90b46811bba96d505af89e6fbdce2f \
|
||||
--hash=sha256:5938b257b04c851c2d1e6cb2f8c18318f06017f35be9a5fe761ee1e2e344dfb7 \
|
||||
--hash=sha256:5e37d5027e297a627da3551a1e962316d0f88ee4ada74c768f6c9234e26346d9 \
|
||||
--hash=sha256:64a607e630d9f4b2797f641884e52b9f8e239d35943f51bef817a384ec1678fe \
|
||||
--hash=sha256:64dc6e9ec64f592f19dc01a784e87267a64a743d34f68488924251253da3c818 \
|
||||
--hash=sha256:69320f05de8cdf4077ecd7fefdec223890eea232af0d58f2530cbda2871244a0 \
|
||||
--hash=sha256:6d8f2144e0d5808c2e2aed40fbebe13869cd00c2ae745aca4b3b16a435edb056 \
|
||||
--hash=sha256:700679c02f9348a0d0a2adcd33a0275717cd0d0aee9d4482b47d935023629505 \
|
||||
--hash=sha256:709447bd7203b0b2debab1acec23123eb80b386f6c29e7604a5d4326a11e5bd6 \
|
||||
--hash=sha256:71adcc8bc80a65b776510bc39992edf942ace35b153ed7a9c6c573a6849ce308 \
|
||||
--hash=sha256:71db8896b942770ed7ab4efa59b22eee5203be2dfdee3c5258d60e57605d688c \
|
||||
--hash=sha256:74fbf5dd3ef09beafd3557631e282f00f8af4e7a78fbfce8ab06d9cd5a789aae \
|
||||
--hash=sha256:79498df398970abcee3d326edd1d4655de7d77aa9aecd578154f8af35ce7bbd2 \
|
||||
--hash=sha256:7ad357e426b0ea5c3043b8ec905546fa44b734bf11d33b3da3959f6e4447d350 \
|
||||
--hash=sha256:7d784f614e4d53050cbe8abf2ae9d1aaacf8ed31ce57b42ce3bf2a48a66c3a5c \
|
||||
--hash=sha256:80a2337e2dfb26950894c8301358961430a0304f7bfe729d34cc036474e9c9b1 \
|
||||
--hash=sha256:824c867a38521d61d62b60aca7db7ca013a2b479e428a0db47d25d8ca5067410 \
|
||||
--hash=sha256:842da42a63ecb32612bb7f5b9e9f8617eab9bc23bd58679a441f4150fcc51c96 \
|
||||
--hash=sha256:8b7be9a6c06518967b641fb15032b1ed682fd3b0443f64078899c61034a0bca6 \
|
||||
--hash=sha256:9099e443d4cc24ac6872e6a05f93205ba1a231b1a8917317b07c9ef2b955f1f4 \
|
||||
--hash=sha256:94253be2b57ef2fea7ffe08996067aabf56a1eb9648342c9e3bad9e10c46e045 \
|
||||
--hash=sha256:949551752930d5e478817e0b49956350d866b26578ced0042a61967e3fcccdea \
|
||||
--hash=sha256:96334bb64d054e36fed346c50c4190bad9d7c586376204f50bede21a913bf942 \
|
||||
--hash=sha256:965455eac8547f32b3181d5ec9ad8b9be500c10fe06193543efaaebe3e4ce70c \
|
||||
--hash=sha256:967b47a0fd237aa17c2748fdb7425015c394a6fb57cdad1562e46a6eb070f96d \
|
||||
--hash=sha256:9994f7db390c17fc2bd4c09dca722fd792ff8a49bb3bdace0c50a83f22f1767d \
|
||||
--hash=sha256:9b60b465773a52c7d4705b0a751f7f1cdccf81dd12aee3b921b31a6e76b07b0e \
|
||||
--hash=sha256:aeddf7b3b3f6e24ccf7d0edfe2d94094ea76b40e831c16eff5230e040ce3b76b \
|
||||
--hash=sha256:c64c4cd0d50d5b2288ab1bcb26c7126c772bbdebdfadcd77225a77df01c4a57e \
|
||||
--hash=sha256:cb987f14af7da7c24f803111dbc7392f5070fd350146af3345103f76ea82e339 \
|
||||
--hash=sha256:dc4fa2240c9fceddaa815a58f29212826fafe43ce80ff666d38c4a03fb036955 \
|
||||
--hash=sha256:e56b1fd529e5dde2d1452a7d72907b37ed1b4f07fdced5d8fb1e963acfff6749 \
|
||||
--hash=sha256:e8630943143c6d6ca9aefc88bbe5e76c90553f4e1a3b2dc339e67dc34aa86f7e \
|
||||
--hash=sha256:e8eb9a4e394926b93ad919cad1b0a918e9b4c846609e8c1cfb6b743683f64da0 \
|
||||
--hash=sha256:e90352d7b610b4693fad0feea48549d4315d10f1eba5605421c92bb834e90170 \
|
||||
--hash=sha256:f0b018e37608c3bfc6039a1dc4eb461e89334465a19916be0153c757a78ea426 \
|
||||
--hash=sha256:f73adc05452fb85e7a12ed3f69c81540a8875960739082e6ea5e28c373a30774 \
|
||||
--hash=sha256:fa33ead69ed133210d96af0c63448b1385df48b9c0247eda735c5896b9e6dbbf \
|
||||
--hash=sha256:fc6d87a1c44df8d493ef44988a3ded751e284e02cdf785f746c2d357e99782a6 \
|
||||
--hash=sha256:fd40af959173ea0d087b6b232b855cfeaa6738f47cb2a0fd10a7f4fa8b74293f \
|
||||
--hash=sha256:fd65774ed7d65101b314808b6893e1a75b7664f680c3ef18d2e5c84d570fa393 \
|
||||
--hash=sha256:fda0162b0dbfa5eaed6cdc708179fa27e148cb8490c7d62e5cf30713909658ea
|
||||
psycopg[binary, pool]==3.1.18 \
|
||||
--hash=sha256:31144d3fb4c17d78094d9e579826f047d4af1da6a10427d91dfcfb6ecdf6f12b \
|
||||
--hash=sha256:4d5a0a5a8590906daa58ebd5f3cfc34091377354a1acced269dd10faf55da60e
|
||||
psycopg-binary==3.1.18 \
|
||||
--hash=sha256:02bd4da45d5ee9941432e2e9bf36fa71a3ac21c6536fe7366d1bd3dd70d6b1e7 \
|
||||
--hash=sha256:0f68ac2364a50d4cf9bb803b4341e83678668f1881a253e1224574921c69868c \
|
||||
--hash=sha256:13bcd3742112446037d15e360b27a03af4b5afcf767f5ee374ef8f5dd7571b31 \
|
||||
--hash=sha256:1729d0e3dfe2546d823841eb7a3d003144189d6f5e138ee63e5227f8b75276a5 \
|
||||
--hash=sha256:1859aeb2133f5ecdd9cbcee155f5e38699afc06a365f903b1512c765fd8d457e \
|
||||
--hash=sha256:1c9b6bd7fb5c6638cb32469674707649b526acfe786ba6d5a78ca4293d87bae4 \
|
||||
--hash=sha256:247474af262bdd5559ee6e669926c4f23e9cf53dae2d34c4d991723c72196404 \
|
||||
--hash=sha256:258d2f0cb45e4574f8b2fe7c6d0a0e2eb58903a4fd1fbaf60954fba82d595ab7 \
|
||||
--hash=sha256:2e2484ae835dedc80cdc7f1b1a939377dc967fed862262cfd097aa9f50cade46 \
|
||||
--hash=sha256:320047e3d3554b857e16c2b6b615a85e0db6a02426f4d203a4594a2f125dfe57 \
|
||||
--hash=sha256:39242546383f6b97032de7af30edb483d237a0616f6050512eee7b218a2aa8ee \
|
||||
--hash=sha256:3c2b039ae0c45eee4cd85300ef802c0f97d0afc78350946a5d0ec77dd2d7e834 \
|
||||
--hash=sha256:3c7afcd6f1d55992f26d9ff7b0bd4ee6b475eb43aa3f054d67d32e09f18b0065 \
|
||||
--hash=sha256:3e4b0bb91da6f2238dbd4fbb4afc40dfb4f045bb611b92fce4d381b26413c686 \
|
||||
--hash=sha256:3e7ce4d988112ca6c75765c7f24c83bdc476a6a5ce00878df6c140ca32c3e16d \
|
||||
--hash=sha256:4085f56a8d4fc8b455e8f44380705c7795be5317419aa5f8214f315e4205d804 \
|
||||
--hash=sha256:4575da95fc441244a0e2ebaf33a2b2f74164603341d2046b5cde0a9aa86aa7e2 \
|
||||
--hash=sha256:489aa4fe5a0b653b68341e9e44af247dedbbc655326854aa34c163ef1bcb3143 \
|
||||
--hash=sha256:4e4de16a637ec190cbee82e0c2dc4860fed17a23a35f7a1e6dc479a5c6876722 \
|
||||
--hash=sha256:531381f6647fc267383dca88dbe8a70d0feff433a8e3d0c4939201fea7ae1b82 \
|
||||
--hash=sha256:55ff0948457bfa8c0d35c46e3a75193906d1c275538877ba65907fd67aa059ad \
|
||||
--hash=sha256:59701118c7d8842e451f1e562d08e8708b3f5d14974eefbce9374badd723c4ae \
|
||||
--hash=sha256:5c323103dfa663b88204cf5f028e83c77d7a715f9b6f51d2bbc8184b99ddd90a \
|
||||
--hash=sha256:5d6e860edf877d4413e4a807e837d55e3a7c7df701e9d6943c06e460fa6c058f \
|
||||
--hash=sha256:639dd78ac09b144b0119076783cb64e1128cc8612243e9701d1503c816750b2e \
|
||||
--hash=sha256:6432047b8b24ef97e3fbee1d1593a0faaa9544c7a41a2c67d1f10e7621374c83 \
|
||||
--hash=sha256:67284e2e450dc7a9e4d76e78c0bd357dc946334a3d410defaeb2635607f632cd \
|
||||
--hash=sha256:6ebecbf2406cd6875bdd2453e31067d1bd8efe96705a9489ef37e93b50dc6f09 \
|
||||
--hash=sha256:7121acc783c4e86d2d320a7fb803460fab158a7f0a04c5e8c5d49065118c1e73 \
|
||||
--hash=sha256:74e498586b72fb819ca8ea82107747d0cb6e00ae685ea6d1ab3f929318a8ce2d \
|
||||
--hash=sha256:780a90bcb69bf27a8b08bc35b958e974cb6ea7a04cdec69e737f66378a344d68 \
|
||||
--hash=sha256:7ac1785d67241d5074f8086705fa68e046becea27964267ab3abd392481d7773 \
|
||||
--hash=sha256:812726266ab96de681f2c7dbd6b734d327f493a78357fcc16b2ac86ff4f4e080 \
|
||||
--hash=sha256:824a1bfd0db96cc6bef2d1e52d9e0963f5bf653dd5bc3ab519a38f5e6f21c299 \
|
||||
--hash=sha256:87dd9154b757a5fbf6d590f6f6ea75f4ad7b764a813ae04b1d91a70713f414a1 \
|
||||
--hash=sha256:887f8d856c91510148be942c7acd702ccf761a05f59f8abc123c22ab77b5a16c \
|
||||
--hash=sha256:888a72c2aca4316ca6d4a619291b805677bae99bba2f6e31a3c18424a48c7e4d \
|
||||
--hash=sha256:8f54978c4b646dec77fefd8485fa82ec1a87807f334004372af1aaa6de9539a5 \
|
||||
--hash=sha256:91074f78a9f890af5f2c786691575b6b93a4967ad6b8c5a90101f7b8c1a91d9c \
|
||||
--hash=sha256:9d684227ef8212e27da5f2aff9d4d303cc30b27ac1702d4f6881935549486dd5 \
|
||||
--hash=sha256:9e24e7b6a68a51cc3b162d0339ae4e1263b253e887987d5c759652f5692b5efe \
|
||||
--hash=sha256:9ffcbbd389e486d3fd83d30107bbf8b27845a295051ccabde240f235d04ed921 \
|
||||
--hash=sha256:a87e9eeb80ce8ec8c2783f29bce9a50bbcd2e2342a340f159c3326bf4697afa1 \
|
||||
--hash=sha256:ad35ac7fd989184bf4d38a87decfb5a262b419e8ba8dcaeec97848817412c64a \
|
||||
--hash=sha256:b15e3653c82384b043d820fc637199b5c6a36b37fa4a4943e0652785bb2bad5d \
|
||||
--hash=sha256:b293e01057e63c3ac0002aa132a1071ce0fdb13b9ee2b6b45d3abdb3525c597d \
|
||||
--hash=sha256:b2f7f95746efd1be2dc240248cc157f4315db3fd09fef2adfcc2a76e24aa5741 \
|
||||
--hash=sha256:bd27f713f2e5ef3fd6796e66c1a5203a27a30ecb847be27a78e1df8a9a5ae68c \
|
||||
--hash=sha256:c38a4796abf7380f83b1653c2711cb2449dd0b2e5aca1caa75447d6fa5179c69 \
|
||||
--hash=sha256:c76659ae29a84f2c14f56aad305dd00eb685bd88f8c0a3281a9a4bc6bd7d2aa7 \
|
||||
--hash=sha256:c84a0174109f329eeda169004c7b7ca2e884a6305acab4a39600be67f915ed38 \
|
||||
--hash=sha256:cd2a9f7f0d4dacc5b9ce7f0e767ae6cc64153264151f50698898c42cabffec0c \
|
||||
--hash=sha256:d322ba72cde4ca2eefc2196dad9ad7e52451acd2f04e3688d590290625d0c970 \
|
||||
--hash=sha256:d4422af5232699f14b7266a754da49dc9bcd45eba244cf3812307934cd5d6679 \
|
||||
--hash=sha256:d46ae44d66bf6058a812467f6ae84e4e157dee281bfb1cfaeca07dee07452e85 \
|
||||
--hash=sha256:da917f6df8c6b2002043193cb0d74cc173b3af7eb5800ad69c4e1fbac2a71c30 \
|
||||
--hash=sha256:dea4a59da7850192fdead9da888e6b96166e90608cf39e17b503f45826b16f84 \
|
||||
--hash=sha256:e05f6825f8db4428782135e6986fec79b139210398f3710ed4aa6ef41473c008 \
|
||||
--hash=sha256:e1cf59e0bb12e031a48bb628aae32df3d0c98fd6c759cb89f464b1047f0ca9c8 \
|
||||
--hash=sha256:e252d66276c992319ed6cd69a3ffa17538943954075051e992143ccbf6dc3d3e \
|
||||
--hash=sha256:e262398e5d51563093edf30612cd1e20fedd932ad0994697d7781ca4880cdc3d \
|
||||
--hash=sha256:e28ff8f3de7b56588c2a398dc135fd9f157d12c612bd3daa7e6ba9872337f6f5 \
|
||||
--hash=sha256:eea5f14933177ffe5c40b200f04f814258cc14b14a71024ad109f308e8bad414 \
|
||||
--hash=sha256:f876ebbf92db70125f6375f91ab4bc6b27648aa68f90d661b1fc5affb4c9731c \
|
||||
--hash=sha256:f8ff3bc08b43f36fdc24fedb86d42749298a458c4724fb588c4d76823ac39f54
|
||||
# via psycopg
|
||||
psycopg-pool==3.2.4 \
|
||||
--hash=sha256:61774b5bbf23e8d22bedc7504707135aaf744679f8ef9b3fe29942920746a6ed \
|
||||
--hash=sha256:f6a22cff0f21f06d72fb2f5cb48c618946777c49385358e0c88d062c59cbd224
|
||||
psycopg-pool==3.2.1 \
|
||||
--hash=sha256:060b551d1b97a8d358c668be58b637780b884de14d861f4f5ecc48b7563aafb7 \
|
||||
--hash=sha256:6509a75c073590952915eddbba7ce8b8332a440a31e77bba69561483492829ad
|
||||
# via psycopg
|
||||
pyasn1==0.6.1 \
|
||||
--hash=sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629 \
|
||||
--hash=sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034
|
||||
pyasn1==0.6.0 \
|
||||
--hash=sha256:3a35ab2c4b5ef98e17dfdec8ab074046fbda76e281c5a706ccd82328cfc8f64c \
|
||||
--hash=sha256:cca4bb0f2df5504f02f6f8a775b6e416ff9b0b3b16f7ee80b5a3153d9b804473
|
||||
# via
|
||||
# pyasn1-modules
|
||||
# python-ldap
|
||||
pyasn1-modules==0.4.1 \
|
||||
--hash=sha256:49bfa96b45a292b711e986f222502c1c9a5e1f4e568fc30e2574a6c7d07838fd \
|
||||
--hash=sha256:c28e2dbf9c06ad61c71a075c7e0f9fd0f1b0bb2d2ad4377f240d33ac2ab60a7c
|
||||
pyasn1-modules==0.4.0 \
|
||||
--hash=sha256:831dbcea1b177b28c9baddf4c6d1013c24c3accd14a1873fffaa6a2e905f17b6 \
|
||||
--hash=sha256:be04f15b66c206eed667e0bb5ab27e2b1855ea54a842e5037738099e8ca4ae0b
|
||||
# via python-ldap
|
||||
python-ldap==3.4.4 \
|
||||
--hash=sha256:7edb0accec4e037797705f3a05cbf36a9fde50d08c8f67f2aef99a2628fab828
|
||||
# via
|
||||
# -r contrib/container/requirements.in
|
||||
# django-auth-ldap
|
||||
pyyaml==6.0.2 \
|
||||
--hash=sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff \
|
||||
--hash=sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48 \
|
||||
--hash=sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086 \
|
||||
--hash=sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e \
|
||||
--hash=sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133 \
|
||||
--hash=sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5 \
|
||||
--hash=sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484 \
|
||||
--hash=sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee \
|
||||
--hash=sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5 \
|
||||
--hash=sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68 \
|
||||
--hash=sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a \
|
||||
--hash=sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf \
|
||||
--hash=sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99 \
|
||||
--hash=sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8 \
|
||||
--hash=sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85 \
|
||||
--hash=sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19 \
|
||||
--hash=sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc \
|
||||
--hash=sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a \
|
||||
--hash=sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1 \
|
||||
--hash=sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317 \
|
||||
--hash=sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c \
|
||||
--hash=sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631 \
|
||||
--hash=sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d \
|
||||
--hash=sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652 \
|
||||
--hash=sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5 \
|
||||
--hash=sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e \
|
||||
--hash=sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b \
|
||||
--hash=sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8 \
|
||||
--hash=sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476 \
|
||||
--hash=sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706 \
|
||||
--hash=sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563 \
|
||||
--hash=sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237 \
|
||||
--hash=sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b \
|
||||
--hash=sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083 \
|
||||
--hash=sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180 \
|
||||
--hash=sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425 \
|
||||
--hash=sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e \
|
||||
--hash=sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f \
|
||||
--hash=sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725 \
|
||||
--hash=sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183 \
|
||||
--hash=sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab \
|
||||
--hash=sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774 \
|
||||
--hash=sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725 \
|
||||
--hash=sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e \
|
||||
--hash=sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5 \
|
||||
--hash=sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d \
|
||||
--hash=sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290 \
|
||||
--hash=sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44 \
|
||||
--hash=sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed \
|
||||
--hash=sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4 \
|
||||
--hash=sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba \
|
||||
--hash=sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12 \
|
||||
--hash=sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4
|
||||
# via -r contrib/container/requirements.in
|
||||
setuptools==75.6.0 \
|
||||
--hash=sha256:8199222558df7c86216af4f84c30e9b34a61d8ba19366cc914424cdbd28252f6 \
|
||||
--hash=sha256:ce74b49e8f7110f9bf04883b730f4765b774ef3ef28f722cce7c273d253aaf7d
|
||||
# via -r contrib/container/requirements.in
|
||||
sqlparse==0.5.3 \
|
||||
--hash=sha256:09f67787f56a0b16ecdbde1bfc7f5d9c3371ca683cfeaa8e6ff60b4807ec9272 \
|
||||
--hash=sha256:cf2196ed3418f3ba5de6af7e82c694a9fbdbfecccdfc72e281548517081f16ca
|
||||
# via django-auth-ldap
|
||||
pyyaml==6.0.1 \
|
||||
--hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \
|
||||
--hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \
|
||||
--hash=sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df \
|
||||
--hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \
|
||||
--hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \
|
||||
--hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \
|
||||
--hash=sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595 \
|
||||
--hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \
|
||||
--hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \
|
||||
--hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \
|
||||
--hash=sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290 \
|
||||
--hash=sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9 \
|
||||
--hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \
|
||||
--hash=sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6 \
|
||||
--hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \
|
||||
--hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \
|
||||
--hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \
|
||||
--hash=sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6 \
|
||||
--hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \
|
||||
--hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \
|
||||
--hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \
|
||||
--hash=sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0 \
|
||||
--hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \
|
||||
--hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \
|
||||
--hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \
|
||||
--hash=sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28 \
|
||||
--hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \
|
||||
--hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \
|
||||
--hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \
|
||||
--hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \
|
||||
--hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \
|
||||
--hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \
|
||||
--hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \
|
||||
--hash=sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0 \
|
||||
--hash=sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515 \
|
||||
--hash=sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c \
|
||||
--hash=sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c \
|
||||
--hash=sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924 \
|
||||
--hash=sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 \
|
||||
--hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \
|
||||
--hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \
|
||||
--hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \
|
||||
--hash=sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54 \
|
||||
--hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \
|
||||
--hash=sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b \
|
||||
--hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \
|
||||
--hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \
|
||||
--hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \
|
||||
--hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \
|
||||
--hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \
|
||||
--hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f
|
||||
setuptools==69.5.1 \
|
||||
--hash=sha256:6c1fccdac05a97e598fb0ae3bbed5904ccb317337a51139dcd51453611bbb987 \
|
||||
--hash=sha256:c636ac361bc47580504644275c9ad802c50415c7522212252c033bd15f301f32
|
||||
sqlparse==0.5.0 \
|
||||
--hash=sha256:714d0a4932c059d16189f58ef5411ec2287a4360f17cdd0edd2d09d4c5087c93 \
|
||||
--hash=sha256:c204494cd97479d0e39f28c93d46c0b2d5959c7b9ab904762ea6c7af211c8663
|
||||
# via django
|
||||
typing-extensions==4.12.2 \
|
||||
--hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \
|
||||
--hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8
|
||||
typing-extensions==4.11.0 \
|
||||
--hash=sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0 \
|
||||
--hash=sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a
|
||||
# via
|
||||
# psycopg
|
||||
# psycopg-pool
|
||||
uv==0.5.7 \
|
||||
--hash=sha256:071b57c934bdee8d7502a70e9ea0739a10e9b2d1d0c67e923a09e7a23d9a181b \
|
||||
--hash=sha256:13961a8116515eb288c4f91849fba11ebda0dfeec44cc356e388b3b03b2dbbe1 \
|
||||
--hash=sha256:1c5b89c64fb627f52f1e9c9bbc4dcc7bae29c4c5ab8eff46da3c966bbd4caed2 \
|
||||
--hash=sha256:27c630780e1856a70fbeb267e1ed6835268a1b50963ab9a984fafa4184389def \
|
||||
--hash=sha256:46b03a9a78438219fb3060c096773284e2f22417a9c1f8fdd602f0650b3355c2 \
|
||||
--hash=sha256:4d22a5046a6246af85c92257d110ed8fbcd98b16824e4efa9d825d001222b2cb \
|
||||
--hash=sha256:737a06b15c4e6b8ab7dd0a577ba766380bda4c18ba4ecfcfff37d336f1b03a00 \
|
||||
--hash=sha256:747c011da9f631354a1c89b62b19b8572e040d3fe01c6fb8d650facc7a09fdbb \
|
||||
--hash=sha256:76b514c79136e779cccf90cce5d60f317a0d42074e9f4c059f198ef435f2f6ab \
|
||||
--hash=sha256:78c3c040e52c09a410b9788656d6e760d557f223058537081cb03a3e25ce89de \
|
||||
--hash=sha256:a141b40444c4184efba9fdc10abb3c1cff32154c7f8b0ad46ddc180d65a82d90 \
|
||||
--hash=sha256:a45648db157d2aaff859fe71ec738efea09b972b8864feb2fd61ef856a15b24f \
|
||||
--hash=sha256:a4fc62749bda8e7ae62212b1d85cdf6c7bad41918b3c8ac5a6d730dd093d793d \
|
||||
--hash=sha256:b79e32438390add793bebc41b0729054e375be30bc53f124ee212d9c97affc39 \
|
||||
--hash=sha256:ba25eb99891b95b5200d5e369b788d443fae370b097e7268a71e9ba753f2af3f \
|
||||
--hash=sha256:c1e7b5bcc8b380e333e948c01f6f4c6203067b5de60a05f8ed786332af7a9132 \
|
||||
--hash=sha256:d0600d2b2fbd9a9446bfbb7f03d88bc3d0293b949ce40e326429dd4fe246c926 \
|
||||
--hash=sha256:fb4a3ccbe13072b98919413ac8378dd3e2b5480352f75c349a4f71f423801485
|
||||
# via -r contrib/container/requirements.in
|
||||
wheel==0.45.1 \
|
||||
--hash=sha256:661e1abd9198507b1409a20c02106d9670b2576e916d58f520316666abca6729 \
|
||||
--hash=sha256:708e7481cc80179af0e556bbf0cc00b8444c7321e2700b8d8580231d13017248
|
||||
# via -r contrib/container/requirements.in
|
||||
uv==0.1.38 \
|
||||
--hash=sha256:03242a734a572733f2b9a5dbb94517e918fe26fc01114b7c51d12296dfbb8f8b \
|
||||
--hash=sha256:067af2d986329db4fa3c7373017d49f0e16ddff23e483b7e5bc3a5a18ce08ea6 \
|
||||
--hash=sha256:0937ad16ae0e0b6bb6dd3c386f8fb33141ad08d1762eaacffb4d2b27fb466a17 \
|
||||
--hash=sha256:0e1d64ac437b0a14fbcec55b1c3f162fa24860711e0d855fcd9c672b149a122a \
|
||||
--hash=sha256:1be7aa46936c0351ccb1400ea95e5381b3f05fef772fa3b9f23af728cc175dea \
|
||||
--hash=sha256:309e73a3ec3a5a536a3efaf434270fc94b483069f1425765165c1c9d786c27fd \
|
||||
--hash=sha256:4251f9771d392d7badc1e5fb934b397b12ca00fef9d955207ade169cc1f7e872 \
|
||||
--hash=sha256:43772e7589f70e954b1ae29230e575ef9e4d8d769138a94dfa5ae7eaf1e26ac5 \
|
||||
--hash=sha256:4a6024256d38b77151e32876be9fcb99cf75df7a86b26e0161cc202bed558adf \
|
||||
--hash=sha256:5a98d6aacd4b57b7e00daf154919e7c9206fefdf40bd28cfb13efe0e0324d491 \
|
||||
--hash=sha256:8de6dbd8f348ee90af044f4cc7b6650521d25ba2d20a813c1e157a3f90069dd9 \
|
||||
--hash=sha256:9133e24db9bdd4f412eab69586d03294419825432a9a27ee1b510a4c01eb7b0b \
|
||||
--hash=sha256:92f65b6e4e5c8126501785af3629dc537d7c82caa56ac9336a86929c73d0e138 \
|
||||
--hash=sha256:afd85029923e712b6b2c45ddc1680c785392220876c766521e45778db3f71f8e \
|
||||
--hash=sha256:b0b15e51a0f8240969bc412ed0dd60cfe3f664b30173139ef263d71c596d631f \
|
||||
--hash=sha256:ea44c07605d1359a7d82bf42706dd86d341f15f4ca2e1f36e51626a7111c2ad5 \
|
||||
--hash=sha256:f87c9711493c53d32012a96b49c4d53aabdf7ed666cbf2c3fb55dd402a6b31a8
|
||||
wheel==0.43.0 \
|
||||
--hash=sha256:465ef92c69fa5c5da2d1cf8ac40559a8c940886afcef87dcf14b9470862f1d85 \
|
||||
--hash=sha256:55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Packages needed for CI/packages
|
||||
requests==2.32.3
|
||||
pyyaml==6.0.2
|
||||
jc==1.25.4
|
||||
requests==2.31.0
|
||||
pyyaml==6.0.1
|
||||
jc==1.25.2
|
||||
|
||||
@@ -1,239 +1,228 @@
|
||||
# This file was autogenerated by uv via the following command:
|
||||
# uv pip compile contrib/dev_reqs/requirements.in -o contrib/dev_reqs/requirements.txt --no-strip-extras --generate-hashes
|
||||
certifi==2024.8.30 \
|
||||
--hash=sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8 \
|
||||
--hash=sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9
|
||||
# uv pip compile contrib/dev_reqs/requirements.in -o contrib/dev_reqs/requirements.txt --python-version=3.9 --no-strip-extras --generate-hashes
|
||||
certifi==2024.2.2 \
|
||||
--hash=sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f \
|
||||
--hash=sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1
|
||||
# via requests
|
||||
charset-normalizer==3.4.0 \
|
||||
--hash=sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621 \
|
||||
--hash=sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6 \
|
||||
--hash=sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8 \
|
||||
--hash=sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912 \
|
||||
--hash=sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c \
|
||||
--hash=sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b \
|
||||
--hash=sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d \
|
||||
--hash=sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d \
|
||||
--hash=sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95 \
|
||||
--hash=sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e \
|
||||
--hash=sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565 \
|
||||
--hash=sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64 \
|
||||
--hash=sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab \
|
||||
--hash=sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be \
|
||||
--hash=sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e \
|
||||
--hash=sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907 \
|
||||
--hash=sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0 \
|
||||
--hash=sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2 \
|
||||
--hash=sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62 \
|
||||
--hash=sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62 \
|
||||
--hash=sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23 \
|
||||
--hash=sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc \
|
||||
--hash=sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284 \
|
||||
--hash=sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca \
|
||||
--hash=sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455 \
|
||||
--hash=sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858 \
|
||||
--hash=sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b \
|
||||
--hash=sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594 \
|
||||
--hash=sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc \
|
||||
--hash=sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db \
|
||||
--hash=sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b \
|
||||
--hash=sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea \
|
||||
--hash=sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6 \
|
||||
--hash=sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920 \
|
||||
--hash=sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749 \
|
||||
--hash=sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7 \
|
||||
--hash=sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd \
|
||||
--hash=sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99 \
|
||||
--hash=sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242 \
|
||||
--hash=sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee \
|
||||
--hash=sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129 \
|
||||
--hash=sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2 \
|
||||
--hash=sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51 \
|
||||
--hash=sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee \
|
||||
--hash=sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8 \
|
||||
--hash=sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b \
|
||||
--hash=sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613 \
|
||||
--hash=sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742 \
|
||||
--hash=sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe \
|
||||
--hash=sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3 \
|
||||
--hash=sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5 \
|
||||
--hash=sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631 \
|
||||
--hash=sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7 \
|
||||
--hash=sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15 \
|
||||
--hash=sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c \
|
||||
--hash=sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea \
|
||||
--hash=sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417 \
|
||||
--hash=sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250 \
|
||||
--hash=sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88 \
|
||||
--hash=sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca \
|
||||
--hash=sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa \
|
||||
--hash=sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99 \
|
||||
--hash=sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149 \
|
||||
--hash=sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41 \
|
||||
--hash=sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574 \
|
||||
--hash=sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0 \
|
||||
--hash=sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f \
|
||||
--hash=sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d \
|
||||
--hash=sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654 \
|
||||
--hash=sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3 \
|
||||
--hash=sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19 \
|
||||
--hash=sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90 \
|
||||
--hash=sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578 \
|
||||
--hash=sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9 \
|
||||
--hash=sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1 \
|
||||
--hash=sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51 \
|
||||
--hash=sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719 \
|
||||
--hash=sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236 \
|
||||
--hash=sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a \
|
||||
--hash=sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c \
|
||||
--hash=sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade \
|
||||
--hash=sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944 \
|
||||
--hash=sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc \
|
||||
--hash=sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6 \
|
||||
--hash=sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6 \
|
||||
--hash=sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27 \
|
||||
--hash=sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6 \
|
||||
--hash=sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2 \
|
||||
--hash=sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12 \
|
||||
--hash=sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf \
|
||||
--hash=sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114 \
|
||||
--hash=sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7 \
|
||||
--hash=sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf \
|
||||
--hash=sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d \
|
||||
--hash=sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b \
|
||||
--hash=sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed \
|
||||
--hash=sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03 \
|
||||
--hash=sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4 \
|
||||
--hash=sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67 \
|
||||
--hash=sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365 \
|
||||
--hash=sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a \
|
||||
--hash=sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748 \
|
||||
--hash=sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b \
|
||||
--hash=sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079 \
|
||||
--hash=sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482
|
||||
charset-normalizer==3.3.2 \
|
||||
--hash=sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027 \
|
||||
--hash=sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087 \
|
||||
--hash=sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786 \
|
||||
--hash=sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8 \
|
||||
--hash=sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09 \
|
||||
--hash=sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185 \
|
||||
--hash=sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574 \
|
||||
--hash=sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e \
|
||||
--hash=sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519 \
|
||||
--hash=sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898 \
|
||||
--hash=sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269 \
|
||||
--hash=sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3 \
|
||||
--hash=sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f \
|
||||
--hash=sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6 \
|
||||
--hash=sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8 \
|
||||
--hash=sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a \
|
||||
--hash=sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73 \
|
||||
--hash=sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc \
|
||||
--hash=sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714 \
|
||||
--hash=sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2 \
|
||||
--hash=sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc \
|
||||
--hash=sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce \
|
||||
--hash=sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d \
|
||||
--hash=sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e \
|
||||
--hash=sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6 \
|
||||
--hash=sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269 \
|
||||
--hash=sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 \
|
||||
--hash=sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d \
|
||||
--hash=sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a \
|
||||
--hash=sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4 \
|
||||
--hash=sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 \
|
||||
--hash=sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d \
|
||||
--hash=sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0 \
|
||||
--hash=sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed \
|
||||
--hash=sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068 \
|
||||
--hash=sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac \
|
||||
--hash=sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25 \
|
||||
--hash=sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 \
|
||||
--hash=sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab \
|
||||
--hash=sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26 \
|
||||
--hash=sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2 \
|
||||
--hash=sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db \
|
||||
--hash=sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f \
|
||||
--hash=sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5 \
|
||||
--hash=sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99 \
|
||||
--hash=sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c \
|
||||
--hash=sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d \
|
||||
--hash=sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811 \
|
||||
--hash=sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa \
|
||||
--hash=sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a \
|
||||
--hash=sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03 \
|
||||
--hash=sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b \
|
||||
--hash=sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04 \
|
||||
--hash=sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c \
|
||||
--hash=sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001 \
|
||||
--hash=sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458 \
|
||||
--hash=sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389 \
|
||||
--hash=sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99 \
|
||||
--hash=sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985 \
|
||||
--hash=sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537 \
|
||||
--hash=sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238 \
|
||||
--hash=sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f \
|
||||
--hash=sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d \
|
||||
--hash=sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796 \
|
||||
--hash=sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a \
|
||||
--hash=sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143 \
|
||||
--hash=sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8 \
|
||||
--hash=sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c \
|
||||
--hash=sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5 \
|
||||
--hash=sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5 \
|
||||
--hash=sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711 \
|
||||
--hash=sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4 \
|
||||
--hash=sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6 \
|
||||
--hash=sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c \
|
||||
--hash=sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7 \
|
||||
--hash=sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4 \
|
||||
--hash=sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b \
|
||||
--hash=sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae \
|
||||
--hash=sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12 \
|
||||
--hash=sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c \
|
||||
--hash=sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae \
|
||||
--hash=sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8 \
|
||||
--hash=sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887 \
|
||||
--hash=sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b \
|
||||
--hash=sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4 \
|
||||
--hash=sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f \
|
||||
--hash=sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5 \
|
||||
--hash=sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33 \
|
||||
--hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \
|
||||
--hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561
|
||||
# via requests
|
||||
idna==3.10 \
|
||||
--hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \
|
||||
--hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3
|
||||
idna==3.7 \
|
||||
--hash=sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc \
|
||||
--hash=sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0
|
||||
# via requests
|
||||
jc==1.25.4 \
|
||||
--hash=sha256:1e4f45d2e5b72cf9d300b0d9df0578c0d3b553843e3ad37a525d93bb0e94aca1 \
|
||||
--hash=sha256:a32eaf029c56b582dadae48895f20784d0f84f2fa28a8e2b32f377a8bffa8b39
|
||||
# via -r contrib/dev_reqs/requirements.in
|
||||
pygments==2.18.0 \
|
||||
--hash=sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199 \
|
||||
--hash=sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a
|
||||
jc==1.25.2 \
|
||||
--hash=sha256:26e412a65a478f9da3097653db6277f915cfae5c0f0a3f42026b405936abd358 \
|
||||
--hash=sha256:97ada193495f79550f06fe0cbfb119ff470bcca57c1cc593a5cdb0008720e0b3
|
||||
pygments==2.17.2 \
|
||||
--hash=sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c \
|
||||
--hash=sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367
|
||||
# via jc
|
||||
pyyaml==6.0.2 \
|
||||
--hash=sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff \
|
||||
--hash=sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48 \
|
||||
--hash=sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086 \
|
||||
--hash=sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e \
|
||||
--hash=sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133 \
|
||||
--hash=sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5 \
|
||||
--hash=sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484 \
|
||||
--hash=sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee \
|
||||
--hash=sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5 \
|
||||
--hash=sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68 \
|
||||
--hash=sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a \
|
||||
--hash=sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf \
|
||||
--hash=sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99 \
|
||||
--hash=sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8 \
|
||||
--hash=sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85 \
|
||||
--hash=sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19 \
|
||||
--hash=sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc \
|
||||
--hash=sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a \
|
||||
--hash=sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1 \
|
||||
--hash=sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317 \
|
||||
--hash=sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c \
|
||||
--hash=sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631 \
|
||||
--hash=sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d \
|
||||
--hash=sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652 \
|
||||
--hash=sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5 \
|
||||
--hash=sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e \
|
||||
--hash=sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b \
|
||||
--hash=sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8 \
|
||||
--hash=sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476 \
|
||||
--hash=sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706 \
|
||||
--hash=sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563 \
|
||||
--hash=sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237 \
|
||||
--hash=sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b \
|
||||
--hash=sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083 \
|
||||
--hash=sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180 \
|
||||
--hash=sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425 \
|
||||
--hash=sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e \
|
||||
--hash=sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f \
|
||||
--hash=sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725 \
|
||||
--hash=sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183 \
|
||||
--hash=sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab \
|
||||
--hash=sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774 \
|
||||
--hash=sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725 \
|
||||
--hash=sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e \
|
||||
--hash=sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5 \
|
||||
--hash=sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d \
|
||||
--hash=sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290 \
|
||||
--hash=sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44 \
|
||||
--hash=sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed \
|
||||
--hash=sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4 \
|
||||
--hash=sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba \
|
||||
--hash=sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12 \
|
||||
--hash=sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4
|
||||
# via -r contrib/dev_reqs/requirements.in
|
||||
requests==2.32.3 \
|
||||
--hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \
|
||||
--hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6
|
||||
# via -r contrib/dev_reqs/requirements.in
|
||||
pyyaml==6.0.1 \
|
||||
--hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \
|
||||
--hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \
|
||||
--hash=sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df \
|
||||
--hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \
|
||||
--hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \
|
||||
--hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \
|
||||
--hash=sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595 \
|
||||
--hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \
|
||||
--hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \
|
||||
--hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \
|
||||
--hash=sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290 \
|
||||
--hash=sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9 \
|
||||
--hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \
|
||||
--hash=sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6 \
|
||||
--hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \
|
||||
--hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \
|
||||
--hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \
|
||||
--hash=sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6 \
|
||||
--hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \
|
||||
--hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \
|
||||
--hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \
|
||||
--hash=sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0 \
|
||||
--hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \
|
||||
--hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \
|
||||
--hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \
|
||||
--hash=sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28 \
|
||||
--hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \
|
||||
--hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \
|
||||
--hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \
|
||||
--hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \
|
||||
--hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \
|
||||
--hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \
|
||||
--hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \
|
||||
--hash=sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0 \
|
||||
--hash=sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515 \
|
||||
--hash=sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c \
|
||||
--hash=sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c \
|
||||
--hash=sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924 \
|
||||
--hash=sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 \
|
||||
--hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \
|
||||
--hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \
|
||||
--hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \
|
||||
--hash=sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54 \
|
||||
--hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \
|
||||
--hash=sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b \
|
||||
--hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \
|
||||
--hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \
|
||||
--hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \
|
||||
--hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \
|
||||
--hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \
|
||||
--hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f
|
||||
requests==2.31.0 \
|
||||
--hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \
|
||||
--hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1
|
||||
ruamel-yaml==0.18.6 \
|
||||
--hash=sha256:57b53ba33def16c4f3d807c0ccbc00f8a6081827e81ba2491691b76882d0c636 \
|
||||
--hash=sha256:8b27e6a217e786c6fbe5634d8f3f11bc63e0f80f6a5890f28863d9c45aac311b
|
||||
# via jc
|
||||
ruamel-yaml-clib==0.2.12 \
|
||||
--hash=sha256:040ae85536960525ea62868b642bdb0c2cc6021c9f9d507810c0c604e66f5a7b \
|
||||
--hash=sha256:0467c5965282c62203273b838ae77c0d29d7638c8a4e3a1c8bdd3602c10904e4 \
|
||||
--hash=sha256:0b7e75b4965e1d4690e93021adfcecccbca7d61c7bddd8e22406ef2ff20d74ef \
|
||||
--hash=sha256:11f891336688faf5156a36293a9c362bdc7c88f03a8a027c2c1d8e0bcde998e5 \
|
||||
--hash=sha256:20b0f8dc160ba83b6dcc0e256846e1a02d044e13f7ea74a3d1d56ede4e48c632 \
|
||||
--hash=sha256:22353049ba4181685023b25b5b51a574bce33e7f51c759371a7422dcae5402a6 \
|
||||
--hash=sha256:32621c177bbf782ca5a18ba4d7af0f1082a3f6e517ac2a18b3974d4edf349680 \
|
||||
--hash=sha256:3bc2a80e6420ca8b7d3590791e2dfc709c88ab9152c00eeb511c9875ce5778bf \
|
||||
--hash=sha256:3eac5a91891ceb88138c113f9db04f3cebdae277f5d44eaa3651a4f573e6a5da \
|
||||
--hash=sha256:4a6679521a58256a90b0d89e03992c15144c5f3858f40d7c18886023d7943db6 \
|
||||
--hash=sha256:4c8c5d82f50bb53986a5e02d1b3092b03622c02c2eb78e29bec33fd9593bae1a \
|
||||
--hash=sha256:5a0e060aace4c24dcaf71023bbd7d42674e3b230f7e7b97317baf1e953e5b519 \
|
||||
--hash=sha256:6442cb36270b3afb1b4951f060eccca1ce49f3d087ca1ca4563a6eb479cb3de6 \
|
||||
--hash=sha256:6c8fbb13ec503f99a91901ab46e0b07ae7941cd527393187039aec586fdfd36f \
|
||||
--hash=sha256:749c16fcc4a2b09f28843cda5a193e0283e47454b63ec4b81eaa2242f50e4ccd \
|
||||
--hash=sha256:7dd5adc8b930b12c8fc5b99e2d535a09889941aa0d0bd06f4749e9a9397c71d2 \
|
||||
--hash=sha256:811ea1594b8a0fb466172c384267a4e5e367298af6b228931f273b111f17ef52 \
|
||||
--hash=sha256:932205970b9f9991b34f55136be327501903f7c66830e9760a8ffb15b07f05cd \
|
||||
--hash=sha256:943f32bc9dedb3abff9879edc134901df92cfce2c3d5c9348f172f62eb2d771d \
|
||||
--hash=sha256:95c3829bb364fdb8e0332c9931ecf57d9be3519241323c5274bd82f709cebc0c \
|
||||
--hash=sha256:96777d473c05ee3e5e3c3e999f5d23c6f4ec5b0c38c098b3a5229085f74236c6 \
|
||||
--hash=sha256:a274fb2cb086c7a3dea4322ec27f4cb5cc4b6298adb583ab0e211a4682f241eb \
|
||||
--hash=sha256:a606ef75a60ecf3d924613892cc603b154178ee25abb3055db5062da811fd969 \
|
||||
--hash=sha256:ab007f2f5a87bd08ab1499bdf96f3d5c6ad4dcfa364884cb4549aa0154b13a28 \
|
||||
--hash=sha256:bb43a269eb827806502c7c8efb7ae7e9e9d0573257a46e8e952f4d4caba4f31e \
|
||||
--hash=sha256:bc5f1e1c28e966d61d2519f2a3d451ba989f9ea0f2307de7bc45baa526de9e45 \
|
||||
--hash=sha256:bd0a08f0bab19093c54e18a14a10b4322e1eacc5217056f3c063bd2f59853ce4 \
|
||||
--hash=sha256:beffaed67936fbbeffd10966a4eb53c402fafd3d6833770516bf7314bc6ffa12 \
|
||||
--hash=sha256:bf165fef1f223beae7333275156ab2022cffe255dcc51c27f066b4370da81e31 \
|
||||
--hash=sha256:cf12567a7b565cbf65d438dec6cfbe2917d3c1bdddfce84a9930b7d35ea59642 \
|
||||
--hash=sha256:d84318609196d6bd6da0edfa25cedfbabd8dbde5140a0a23af29ad4b8f91fb1e \
|
||||
--hash=sha256:d85252669dc32f98ebcd5d36768f5d4faeaeaa2d655ac0473be490ecdae3c285 \
|
||||
--hash=sha256:e143ada795c341b56de9418c58d028989093ee611aa27ffb9b7f609c00d813ed \
|
||||
--hash=sha256:e188d2699864c11c36cdfdada94d781fd5d6b0071cd9c427bceb08ad3d7c70e1 \
|
||||
--hash=sha256:e2f1c3765db32be59d18ab3953f43ab62a761327aafc1594a2a1fbe038b8b8a7 \
|
||||
--hash=sha256:e5b8daf27af0b90da7bb903a876477a9e6d7270be6146906b276605997c7e9a3 \
|
||||
--hash=sha256:e7e3736715fbf53e9be2a79eb4db68e4ed857017344d697e8b9749444ae57475 \
|
||||
--hash=sha256:e8c4ebfcfd57177b572e2040777b8abc537cdef58a2120e830124946aa9b42c5 \
|
||||
--hash=sha256:f66efbc1caa63c088dead1c4170d148eabc9b80d95fb75b6c92ac0aad2437d76 \
|
||||
--hash=sha256:fc4b630cd3fa2cf7fce38afa91d7cfe844a9f75d7f0f36393fa98815e911d987 \
|
||||
--hash=sha256:fd5415dded15c3822597455bc02bcd66e81ef8b7a48cb71a33628fc9fdde39df
|
||||
ruamel-yaml-clib==0.2.8 \
|
||||
--hash=sha256:024cfe1fc7c7f4e1aff4a81e718109e13409767e4f871443cbff3dba3578203d \
|
||||
--hash=sha256:03d1162b6d1df1caa3a4bd27aa51ce17c9afc2046c31b0ad60a0a96ec22f8001 \
|
||||
--hash=sha256:07238db9cbdf8fc1e9de2489a4f68474e70dffcb32232db7c08fa61ca0c7c462 \
|
||||
--hash=sha256:09b055c05697b38ecacb7ac50bdab2240bfca1a0c4872b0fd309bb07dc9aa3a9 \
|
||||
--hash=sha256:1707814f0d9791df063f8c19bb51b0d1278b8e9a2353abbb676c2f685dee6afe \
|
||||
--hash=sha256:1758ce7d8e1a29d23de54a16ae867abd370f01b5a69e1a3ba75223eaa3ca1a1b \
|
||||
--hash=sha256:184565012b60405d93838167f425713180b949e9d8dd0bbc7b49f074407c5a8b \
|
||||
--hash=sha256:1b617618914cb00bf5c34d4357c37aa15183fa229b24767259657746c9077615 \
|
||||
--hash=sha256:1dc67314e7e1086c9fdf2680b7b6c2be1c0d8e3a8279f2e993ca2a7545fecf62 \
|
||||
--hash=sha256:25ac8c08322002b06fa1d49d1646181f0b2c72f5cbc15a85e80b4c30a544bb15 \
|
||||
--hash=sha256:25c515e350e5b739842fc3228d662413ef28f295791af5e5110b543cf0b57d9b \
|
||||
--hash=sha256:305889baa4043a09e5b76f8e2a51d4ffba44259f6b4c72dec8ca56207d9c6fe1 \
|
||||
--hash=sha256:3213ece08ea033eb159ac52ae052a4899b56ecc124bb80020d9bbceeb50258e9 \
|
||||
--hash=sha256:3f215c5daf6a9d7bbed4a0a4f760f3113b10e82ff4c5c44bec20a68c8014f675 \
|
||||
--hash=sha256:46d378daaac94f454b3a0e3d8d78cafd78a026b1d71443f4966c696b48a6d899 \
|
||||
--hash=sha256:4ecbf9c3e19f9562c7fdd462e8d18dd902a47ca046a2e64dba80699f0b6c09b7 \
|
||||
--hash=sha256:53a300ed9cea38cf5a2a9b069058137c2ca1ce658a874b79baceb8f892f915a7 \
|
||||
--hash=sha256:56f4252222c067b4ce51ae12cbac231bce32aee1d33fbfc9d17e5b8d6966c312 \
|
||||
--hash=sha256:5c365d91c88390c8d0a8545df0b5857172824b1c604e867161e6b3d59a827eaa \
|
||||
--hash=sha256:700e4ebb569e59e16a976857c8798aee258dceac7c7d6b50cab63e080058df91 \
|
||||
--hash=sha256:75e1ed13e1f9de23c5607fe6bd1aeaae21e523b32d83bb33918245361e9cc51b \
|
||||
--hash=sha256:77159f5d5b5c14f7c34073862a6b7d34944075d9f93e681638f6d753606c6ce6 \
|
||||
--hash=sha256:7f67a1ee819dc4562d444bbafb135832b0b909f81cc90f7aa00260968c9ca1b3 \
|
||||
--hash=sha256:840f0c7f194986a63d2c2465ca63af8ccbbc90ab1c6001b1978f05119b5e7334 \
|
||||
--hash=sha256:84b554931e932c46f94ab306913ad7e11bba988104c5cff26d90d03f68258cd5 \
|
||||
--hash=sha256:87ea5ff66d8064301a154b3933ae406b0863402a799b16e4a1d24d9fbbcbe0d3 \
|
||||
--hash=sha256:955eae71ac26c1ab35924203fda6220f84dce57d6d7884f189743e2abe3a9fbe \
|
||||
--hash=sha256:a1a45e0bb052edf6a1d3a93baef85319733a888363938e1fc9924cb00c8df24c \
|
||||
--hash=sha256:a5aa27bad2bb83670b71683aae140a1f52b0857a2deff56ad3f6c13a017a26ed \
|
||||
--hash=sha256:a6a9ffd280b71ad062eae53ac1659ad86a17f59a0fdc7699fd9be40525153337 \
|
||||
--hash=sha256:a75879bacf2c987c003368cf14bed0ffe99e8e85acfa6c0bfffc21a090f16880 \
|
||||
--hash=sha256:aa2267c6a303eb483de8d02db2871afb5c5fc15618d894300b88958f729ad74f \
|
||||
--hash=sha256:aab7fd643f71d7946f2ee58cc88c9b7bfc97debd71dcc93e03e2d174628e7e2d \
|
||||
--hash=sha256:b16420e621d26fdfa949a8b4b47ade8810c56002f5389970db4ddda51dbff248 \
|
||||
--hash=sha256:b42169467c42b692c19cf539c38d4602069d8c1505e97b86387fcf7afb766e1d \
|
||||
--hash=sha256:bba64af9fa9cebe325a62fa398760f5c7206b215201b0ec825005f1b18b9bccf \
|
||||
--hash=sha256:beb2e0404003de9a4cab9753a8805a8fe9320ee6673136ed7f04255fe60bb512 \
|
||||
--hash=sha256:bef08cd86169d9eafb3ccb0a39edb11d8e25f3dae2b28f5c52fd997521133069 \
|
||||
--hash=sha256:c2a72e9109ea74e511e29032f3b670835f8a59bbdc9ce692c5b4ed91ccf1eedb \
|
||||
--hash=sha256:c58ecd827313af6864893e7af0a3bb85fd529f862b6adbefe14643947cfe2942 \
|
||||
--hash=sha256:c69212f63169ec1cfc9bb44723bf2917cbbd8f6191a00ef3410f5a7fe300722d \
|
||||
--hash=sha256:cabddb8d8ead485e255fe80429f833172b4cadf99274db39abc080e068cbcc31 \
|
||||
--hash=sha256:d176b57452ab5b7028ac47e7b3cf644bcfdc8cacfecf7e71759f7f51a59e5c92 \
|
||||
--hash=sha256:da09ad1c359a728e112d60116f626cc9f29730ff3e0e7db72b9a2dbc2e4beed5 \
|
||||
--hash=sha256:e2b4c44b60eadec492926a7270abb100ef9f72798e18743939bdbf037aab8c28 \
|
||||
--hash=sha256:e79e5db08739731b0ce4850bed599235d601701d5694c36570a99a0c5ca41a9d \
|
||||
--hash=sha256:ebc06178e8821efc9692ea7544aa5644217358490145629914d8020042c24aa1 \
|
||||
--hash=sha256:edaef1c1200c4b4cb914583150dcaa3bc30e592e907c01117c08b13a07255ec2 \
|
||||
--hash=sha256:f481f16baec5290e45aebdc2a5168ebc6d35189ae6fea7a58787613a25f6e875 \
|
||||
--hash=sha256:fff3573c2db359f091e1589c3d7c5fc2f86f5bdb6f24252c2d8e539d4e45f412
|
||||
# via ruamel-yaml
|
||||
urllib3==2.2.3 \
|
||||
--hash=sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac \
|
||||
--hash=sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9
|
||||
urllib3==2.2.1 \
|
||||
--hash=sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d \
|
||||
--hash=sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19
|
||||
# via requests
|
||||
xmltodict==0.14.2 \
|
||||
--hash=sha256:201e7c28bb210e374999d1dde6382923ab0ed1a8a5faeece48ab525b7810a553 \
|
||||
--hash=sha256:20cc7d723ed729276e808f26fb6b3599f786cbc37e06c65e192ba77c40f20aac
|
||||
xmltodict==0.13.0 \
|
||||
--hash=sha256:341595a488e3e01a85a9d8911d8912fd922ede5fecc4dce437eb4b6c8d037e56 \
|
||||
--hash=sha256:aa89e8fd76320154a40d19a0df04a4695fb9dc5ba977cbb68ab3e4eb225e7852
|
||||
# via jc
|
||||
|
||||
@@ -75,7 +75,6 @@ root_command() {
|
||||
;;
|
||||
"Debian GNU/Linux" | "debian gnu/linux" | Raspbian)
|
||||
if [[ $VER == "12" ]]; then
|
||||
DIST_VER="11"
|
||||
SUPPORTED=true
|
||||
elif [[ $VER == "11" ]]; then
|
||||
SUPPORTED=true
|
||||
|
||||
@@ -5,40 +5,33 @@
|
||||
|
||||
set -eu
|
||||
|
||||
# The sha is the second element in APP_PKG_ITERATION
|
||||
VERSION="$APP_PKG_VERSION-$APP_PKG_ITERATION"
|
||||
echo "Setting VERSION information to $VERSION"
|
||||
echo "$VERSION" > VERSION
|
||||
|
||||
# The sha is the second element in APP_PKG_ITERATION
|
||||
SHA=$(echo $APP_PKG_ITERATION | cut -d'.' -f2)
|
||||
|
||||
# Download info
|
||||
echo "INFO collection | Getting info from github for commit $SHA"
|
||||
curl -L -s -f \
|
||||
echo "Getting info from github for commit $SHA"
|
||||
curl -L \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
https://api.github.com/repos/$APP_REPO/commits/$SHA > commit.json
|
||||
echo "INFO collection | Got commit.json with size $(wc -c commit.json)"
|
||||
curl -L -s -f \
|
||||
https://api.github.com/repos/InvenTree/InvenTree/commits/$SHA > commit.json
|
||||
curl -L \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
https://api.github.com/repos/$APP_REPO/commits/$SHA/branches-where-head > branches.json
|
||||
echo "INFO collection | Got branches.json with size $(wc -c branches.json)"
|
||||
curl -L -s -f \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
https://api.github.com/repos/$APP_REPO/commits/$APP_PKG_VERSION > tag.json
|
||||
echo "INFO collection | Got tag.json with size $(wc -c tag.json)"
|
||||
https://api.github.com/repos/InvenTree/InvenTree/commits/$SHA/branches-where-head > branches.json
|
||||
|
||||
# Extract info
|
||||
echo "INFO extract | Extracting info from github"
|
||||
echo "Extracting info from github"
|
||||
DATE=$(jq -r '.commit.committer.date' commit.json)
|
||||
BRANCH=$(jq -r '.[].name' branches.json)
|
||||
NODE_ID=$(jq -r '.node_id' commit.json)
|
||||
SIGNATURE=$(jq -r '.commit.verification.signature' commit.json)
|
||||
FULL_SHA=$(jq -r '.sha' commit.json)
|
||||
|
||||
echo "INFO write | Write VERSION information"
|
||||
echo "$VERSION" > VERSION
|
||||
echo "Write VERSION information"
|
||||
echo "INVENTREE_COMMIT_HASH='$SHA'" >> VERSION
|
||||
echo "INVENTREE_COMMIT_SHA='$FULL_SHA'" >> VERSION
|
||||
echo "INVENTREE_COMMIT_DATE='$DATE'" >> VERSION
|
||||
echo "INVENTREE_PKG_INSTALLER='PKG'" >> VERSION
|
||||
echo "INVENTREE_PKG_BRANCH='$BRANCH'" >> VERSION
|
||||
@@ -46,22 +39,5 @@ echo "INVENTREE_PKG_TARGET='$TARGET'" >> VERSION
|
||||
echo "NODE_ID='$NODE_ID'" >> VERSION
|
||||
echo "SIGNATURE='$SIGNATURE'" >> VERSION
|
||||
|
||||
echo "INFO write | Written VERSION information"
|
||||
echo "### VERSION ###"
|
||||
echo "Written VERSION information"
|
||||
cat VERSION
|
||||
echo "### VERSION ###"
|
||||
|
||||
# Try to get frontend
|
||||
echo "INFO frontend | Trying to get frontend"
|
||||
# Check if tag sha is the same as the commit sha
|
||||
TAG_SHA=$(jq -r '.sha' tag.json)
|
||||
if [ "$TAG_SHA" != "$FULL_SHA" ]; then
|
||||
echo "INFO frontend | Tag sha '$TAG_SHA' is not the same as commit sha $FULL_SHA, can not download frontend"
|
||||
else
|
||||
echo "INFO frontend | Getting frontend from github via tag"
|
||||
curl https://github.com/$APP_REPO/releases/download/$APP_PKG_VERSION/frontend-build.zip -L -O -f
|
||||
mkdir -p src/backend/InvenTree/web/static
|
||||
echo "INFO frontend | Unzipping frontend"
|
||||
unzip -qq frontend-build.zip -d src/backend/InvenTree/web/static/web
|
||||
echo "INFO frontend | Unzipped frontend"
|
||||
fi
|
||||
|
||||
@@ -2,10 +2,6 @@
|
||||
#
|
||||
# packager.io postinstall script functions
|
||||
#
|
||||
Color_Off='\033[0m'
|
||||
On_Red='\033[41m'
|
||||
PYTHON_FROM=9
|
||||
PYTHON_TO=12
|
||||
|
||||
function detect_docker() {
|
||||
if [ -n "$(grep docker </proc/1/cgroup)" ]; then
|
||||
@@ -13,7 +9,6 @@ function detect_docker() {
|
||||
else
|
||||
DOCKER="no"
|
||||
fi
|
||||
echo "# POI04| Running in docker: ${DOCKER}"
|
||||
}
|
||||
|
||||
function detect_initcmd() {
|
||||
@@ -31,7 +26,6 @@ function detect_initcmd() {
|
||||
if [ "${DOCKER}" == "yes" ]; then
|
||||
INIT_CMD="initctl"
|
||||
fi
|
||||
echo "# POI05| Using init command: ${INIT_CMD}"
|
||||
}
|
||||
|
||||
function detect_ip() {
|
||||
@@ -39,52 +33,27 @@ function detect_ip() {
|
||||
|
||||
if [ "${SETUP_NO_CALLS}" == "true" ]; then
|
||||
# Use local IP address
|
||||
echo "# POI06| Getting the IP address of the first local IP address"
|
||||
echo "# Getting the IP address of the first local IP address"
|
||||
export INVENTREE_IP=$(hostname -I | awk '{print $1}')
|
||||
else
|
||||
# Use web service to get the IP address
|
||||
echo "# POI06| Getting the IP address of the server via web service"
|
||||
echo "# Getting the IP address of the server via web service"
|
||||
export INVENTREE_IP=$(curl -s https://checkip.amazonaws.com)
|
||||
fi
|
||||
|
||||
echo "# POI06| IP address is ${INVENTREE_IP}"
|
||||
echo "IP address is ${INVENTREE_IP}"
|
||||
}
|
||||
|
||||
function detect_python() {
|
||||
# Detect if there is already a python version installed in /opt/inventree/env/lib
|
||||
if test -f "${APP_HOME}/env/bin/python"; then
|
||||
echo "# POI07| Python environment already present"
|
||||
echo "# Python environment already present"
|
||||
# Extract earliest python version initialised from /opt/inventree/env/lib
|
||||
SETUP_PYTHON=$(ls -1 ${APP_HOME}/env/bin/python* | sort | head -n 1)
|
||||
echo "# POI07| Found earlier used version: ${SETUP_PYTHON}"
|
||||
echo "# Found earliest version: ${SETUP_PYTHON}"
|
||||
else
|
||||
echo "# POI07| No python environment found - using environment variable: ${SETUP_PYTHON}"
|
||||
echo "# No python environment found - using ${SETUP_PYTHON}"
|
||||
fi
|
||||
|
||||
# Try to detect a python between 3.9 and 3.12 in reverse order
|
||||
if [ -z "$(which ${SETUP_PYTHON})" ]; then
|
||||
echo "# POI07| Trying to detecting python3.${PYTHON_FROM} to python3.${PYTHON_TO} - using newest version"
|
||||
for i in $(seq $PYTHON_TO -1 $PYTHON_FROM); do
|
||||
echo "# POI07| Checking for python3.${i}"
|
||||
if [ -n "$(which python3.${i})" ]; then
|
||||
SETUP_PYTHON="python3.${i}"
|
||||
echo "# POI07| Found python3.${i} installed - using for setup ${SETUP_PYTHON}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Ensure python can be executed - abort if not
|
||||
if [ -z "$(which ${SETUP_PYTHON})" ]; then
|
||||
echo "${On_Red}"
|
||||
echo "# POI07| Python ${SETUP_PYTHON} not found - aborting!"
|
||||
echo "# POI07| Please ensure python can be executed with the command '$SETUP_PYTHON' by the current user '$USER'."
|
||||
echo "# POI07| If you are using a different python version, please set the environment variable SETUP_PYTHON to the correct command - eg. 'python3.10'."
|
||||
echo "${Color_Off}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "# POI07| Using python command: ${SETUP_PYTHON}"
|
||||
}
|
||||
|
||||
function get_env() {
|
||||
@@ -99,7 +68,7 @@ function get_env() {
|
||||
done
|
||||
|
||||
if [ -n "${SETUP_DEBUG}" ]; then
|
||||
echo "# POI02| Done getting env $envname: ${!envname}"
|
||||
echo "Done getting env $envname: ${!envname}"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -107,7 +76,7 @@ function detect_local_env() {
|
||||
# Get all possible envs for the install
|
||||
|
||||
if [ -n "${SETUP_DEBUG}" ]; then
|
||||
echo "# POI02| Printing local envs - before #++#"
|
||||
echo "# Printing local envs - before #++#"
|
||||
printenv
|
||||
fi
|
||||
|
||||
@@ -117,7 +86,7 @@ function detect_local_env() {
|
||||
done
|
||||
|
||||
if [ -n "${SETUP_DEBUG}" ]; then
|
||||
echo "# POI02| Printing local envs - after #++#"
|
||||
echo "# Printing local envs - after #++#"
|
||||
printenv
|
||||
fi
|
||||
}
|
||||
@@ -125,40 +94,38 @@ function detect_local_env() {
|
||||
function detect_envs() {
|
||||
# Detect all envs that should be passed to setup commands
|
||||
|
||||
echo "# POI03| Setting base environment variables"
|
||||
echo "# Setting base environment variables"
|
||||
|
||||
export INVENTREE_CONFIG_FILE=${INVENTREE_CONFIG_FILE:-${CONF_DIR}/config.yaml}
|
||||
|
||||
if test -f "${INVENTREE_CONFIG_FILE}"; then
|
||||
echo "# POI03| Using existing config file: ${INVENTREE_CONFIG_FILE}"
|
||||
echo "# Using existing config file: ${INVENTREE_CONFIG_FILE}"
|
||||
|
||||
# Install parser
|
||||
echo "# POI03| Installing requirements"
|
||||
pip install --require-hashes -r ${APP_HOME}/contrib/dev_reqs/requirements.txt -q
|
||||
echo "# POI03| Installed requirements"
|
||||
|
||||
# Load config
|
||||
export INVENTREE_CONF_DATA=$(cat ${INVENTREE_CONFIG_FILE} | jc --yaml)
|
||||
local CONF=$(cat ${INVENTREE_CONFIG_FILE} | jc --yaml)
|
||||
|
||||
# Parse the config file
|
||||
export INVENTREE_MEDIA_ROOT=$(jq -r '.[].media_root' <<< ${INVENTREE_CONF_DATA})
|
||||
export INVENTREE_STATIC_ROOT=$(jq -r '.[].static_root' <<< ${INVENTREE_CONF_DATA})
|
||||
export INVENTREE_BACKUP_DIR=$(jq -r '.[].backup_dir' <<< ${INVENTREE_CONF_DATA})
|
||||
export INVENTREE_PLUGINS_ENABLED=$(jq -r '.[].plugins_enabled' <<< ${INVENTREE_CONF_DATA})
|
||||
export INVENTREE_PLUGIN_FILE=$(jq -r '.[].plugin_file' <<< ${INVENTREE_CONF_DATA})
|
||||
export INVENTREE_SECRET_KEY_FILE=$(jq -r '.[].secret_key_file' <<< ${INVENTREE_CONF_DATA})
|
||||
export INVENTREE_MEDIA_ROOT=$(jq -r '.[].media_root' <<< ${CONF})
|
||||
export INVENTREE_STATIC_ROOT=$(jq -r '.[].static_root' <<< ${CONF})
|
||||
export INVENTREE_BACKUP_DIR=$(jq -r '.[].backup_dir' <<< ${CONF})
|
||||
export INVENTREE_PLUGINS_ENABLED=$(jq -r '.[].plugins_enabled' <<< ${CONF})
|
||||
export INVENTREE_PLUGIN_FILE=$(jq -r '.[].plugin_file' <<< ${CONF})
|
||||
export INVENTREE_SECRET_KEY_FILE=$(jq -r '.[].secret_key_file' <<< ${CONF})
|
||||
|
||||
export INVENTREE_DB_ENGINE=$(jq -r '.[].database.ENGINE' <<< ${INVENTREE_CONF_DATA})
|
||||
export INVENTREE_DB_NAME=$(jq -r '.[].database.NAME' <<< ${INVENTREE_CONF_DATA})
|
||||
export INVENTREE_DB_USER=$(jq -r '.[].database.USER' <<< ${INVENTREE_CONF_DATA})
|
||||
export INVENTREE_DB_PASSWORD=$(jq -r '.[].database.PASSWORD' <<< ${INVENTREE_CONF_DATA})
|
||||
export INVENTREE_DB_HOST=$(jq -r '.[].database.HOST' <<< ${INVENTREE_CONF_DATA})
|
||||
export INVENTREE_DB_PORT=$(jq -r '.[].database.PORT' <<< ${INVENTREE_CONF_DATA})
|
||||
export INVENTREE_DB_ENGINE=$(jq -r '.[].database.ENGINE' <<< ${CONF})
|
||||
export INVENTREE_DB_NAME=$(jq -r '.[].database.NAME' <<< ${CONF})
|
||||
export INVENTREE_DB_USER=$(jq -r '.[].database.USER' <<< ${CONF})
|
||||
export INVENTREE_DB_PASSWORD=$(jq -r '.[].database.PASSWORD' <<< ${CONF})
|
||||
export INVENTREE_DB_HOST=$(jq -r '.[].database.HOST' <<< ${CONF})
|
||||
export INVENTREE_DB_PORT=$(jq -r '.[].database.PORT' <<< ${CONF})
|
||||
else
|
||||
echo "# POI03| No config file found: ${INVENTREE_CONFIG_FILE}, using envs or defaults"
|
||||
echo "# No config file found: ${INVENTREE_CONFIG_FILE}, using envs or defaults"
|
||||
|
||||
if [ -n "${SETUP_DEBUG}" ]; then
|
||||
echo "# POI03| Print current envs"
|
||||
echo "# Print current envs"
|
||||
printenv | grep INVENTREE_
|
||||
printenv | grep SETUP_
|
||||
fi
|
||||
@@ -181,43 +148,43 @@ function detect_envs() {
|
||||
fi
|
||||
|
||||
# For debugging pass out the envs
|
||||
echo "# POI03| Collected environment variables:"
|
||||
echo "# POI03| INVENTREE_MEDIA_ROOT=${INVENTREE_MEDIA_ROOT}"
|
||||
echo "# POI03| INVENTREE_STATIC_ROOT=${INVENTREE_STATIC_ROOT}"
|
||||
echo "# POI03| INVENTREE_BACKUP_DIR=${INVENTREE_BACKUP_DIR}"
|
||||
echo "# POI03| INVENTREE_PLUGINS_ENABLED=${INVENTREE_PLUGINS_ENABLED}"
|
||||
echo "# POI03| INVENTREE_PLUGIN_FILE=${INVENTREE_PLUGIN_FILE}"
|
||||
echo "# POI03| INVENTREE_SECRET_KEY_FILE=${INVENTREE_SECRET_KEY_FILE}"
|
||||
echo "# POI03| INVENTREE_DB_ENGINE=${INVENTREE_DB_ENGINE}"
|
||||
echo "# POI03| INVENTREE_DB_NAME=${INVENTREE_DB_NAME}"
|
||||
echo "# POI03| INVENTREE_DB_USER=${INVENTREE_DB_USER}"
|
||||
echo "# Collected environment variables:"
|
||||
echo "# INVENTREE_MEDIA_ROOT=${INVENTREE_MEDIA_ROOT}"
|
||||
echo "# INVENTREE_STATIC_ROOT=${INVENTREE_STATIC_ROOT}"
|
||||
echo "# INVENTREE_BACKUP_DIR=${INVENTREE_BACKUP_DIR}"
|
||||
echo "# INVENTREE_PLUGINS_ENABLED=${INVENTREE_PLUGINS_ENABLED}"
|
||||
echo "# INVENTREE_PLUGIN_FILE=${INVENTREE_PLUGIN_FILE}"
|
||||
echo "# INVENTREE_SECRET_KEY_FILE=${INVENTREE_SECRET_KEY_FILE}"
|
||||
echo "# INVENTREE_DB_ENGINE=${INVENTREE_DB_ENGINE}"
|
||||
echo "# INVENTREE_DB_NAME=${INVENTREE_DB_NAME}"
|
||||
echo "# INVENTREE_DB_USER=${INVENTREE_DB_USER}"
|
||||
if [ -n "${SETUP_DEBUG}" ]; then
|
||||
echo "# POI03| INVENTREE_DB_PASSWORD=${INVENTREE_DB_PASSWORD}"
|
||||
echo "# INVENTREE_DB_PASSWORD=${INVENTREE_DB_PASSWORD}"
|
||||
fi
|
||||
echo "# POI03| INVENTREE_DB_HOST=${INVENTREE_DB_HOST}"
|
||||
echo "# POI03| INVENTREE_DB_PORT=${INVENTREE_DB_PORT}"
|
||||
echo "# INVENTREE_DB_HOST=${INVENTREE_DB_HOST}"
|
||||
echo "# INVENTREE_DB_PORT=${INVENTREE_DB_PORT}"
|
||||
}
|
||||
|
||||
function create_initscripts() {
|
||||
|
||||
# Make sure python env exists
|
||||
if test -f "${APP_HOME}/env"; then
|
||||
echo "# POI09| python environment already present - skipping"
|
||||
echo "# python environment already present - skipping"
|
||||
else
|
||||
echo "# POI09| Setting up python environment"
|
||||
echo "# Setting up python environment"
|
||||
sudo -u ${APP_USER} --preserve-env=$SETUP_ENVS bash -c "cd ${APP_HOME} && ${SETUP_PYTHON} -m venv env"
|
||||
sudo -u ${APP_USER} --preserve-env=$SETUP_ENVS bash -c "cd ${APP_HOME} && env/bin/pip install invoke wheel"
|
||||
|
||||
# Check INSTALLER_EXTRA exists and load it
|
||||
if test -f "${APP_HOME}/INSTALLER_EXTRA"; then
|
||||
echo "# POI09| Loading extra packages from INSTALLER_EXTRA"
|
||||
echo "# Loading extra packages from INSTALLER_EXTRA"
|
||||
source ${APP_HOME}/INSTALLER_EXTRA
|
||||
fi
|
||||
|
||||
if [ -n "${SETUP_EXTRA_PIP}" ]; then
|
||||
echo "# POI09| Installing extra pip packages"
|
||||
echo "# Installing extra pip packages"
|
||||
if [ -n "${SETUP_DEBUG}" ]; then
|
||||
echo "# POI09| Extra pip packages: ${SETUP_EXTRA_PIP}"
|
||||
echo "# Extra pip packages: ${SETUP_EXTRA_PIP}"
|
||||
fi
|
||||
sudo -u ${APP_USER} --preserve-env=$SETUP_ENVS bash -c "cd ${APP_HOME} && env/bin/pip install ${SETUP_EXTRA_PIP}"
|
||||
# Write extra packages to INSTALLER_EXTRA
|
||||
@@ -227,45 +194,37 @@ function create_initscripts() {
|
||||
|
||||
# Unlink default config if it exists
|
||||
if test -f "/etc/nginx/sites-enabled/default"; then
|
||||
echo "# POI09| Unlinking default nginx config\n# POI09| Old file still in /etc/nginx/sites-available/default"
|
||||
echo "# Unlinking default nginx config\n# Old file still in /etc/nginx/sites-available/default"
|
||||
sudo unlink /etc/nginx/sites-enabled/default
|
||||
echo "# POI09| Unlinked default nginx config"
|
||||
fi
|
||||
|
||||
# Create InvenTree specific nginx config
|
||||
echo "# POI09| Stopping nginx"
|
||||
echo "# Stopping nginx"
|
||||
${INIT_CMD} stop nginx
|
||||
echo "# POI09| Stopped nginx"
|
||||
echo "# POI09| Setting up nginx to ${SETUP_NGINX_FILE}"
|
||||
echo "# Setting up nginx to ${SETUP_NGINX_FILE}"
|
||||
# Always use the latest nginx config; important if new headers are added / needed for security
|
||||
cp ${APP_HOME}/contrib/packager.io/nginx.prod.conf ${SETUP_NGINX_FILE}
|
||||
sed -i s/inventree-server:8000/localhost:6000/g ${SETUP_NGINX_FILE}
|
||||
sed -i s=var/www=opt/inventree/data=g ${SETUP_NGINX_FILE}
|
||||
# Start nginx
|
||||
echo "# POI09| Starting nginx"
|
||||
echo "# Starting nginx"
|
||||
${INIT_CMD} start nginx
|
||||
echo "# POI09| Started nginx"
|
||||
|
||||
echo "# POI09| (Re)creating init scripts"
|
||||
echo "# (Re)creating init scripts"
|
||||
# This resets scale parameters to a known state
|
||||
inventree scale web="1" worker="1"
|
||||
|
||||
echo "# POI09| Enabling InvenTree on boot"
|
||||
echo "# Enabling InvenTree on boot"
|
||||
${INIT_CMD} enable inventree
|
||||
echo "# POI09| Enabled InvenTree on boot"
|
||||
}
|
||||
|
||||
function create_admin() {
|
||||
# Create data for admin users - stop with setting SETUP_ADMIN_NOCREATION to true
|
||||
if [ "${SETUP_ADMIN_NOCREATION}" == "true" ]; then
|
||||
echo "# POI10| Admin creation is disabled - skipping"
|
||||
return
|
||||
fi
|
||||
# Create data for admin user
|
||||
|
||||
if test -f "${SETUP_ADMIN_PASSWORD_FILE}"; then
|
||||
echo "# POI10| Admin data already exists - skipping"
|
||||
echo "# Admin data already exists - skipping"
|
||||
else
|
||||
echo "# POI10| Creating admin user data"
|
||||
echo "# Creating admin user data"
|
||||
|
||||
# Static admin data
|
||||
export INVENTREE_ADMIN_USER=${INVENTREE_ADMIN_USER:-admin}
|
||||
@@ -280,41 +239,38 @@ function create_admin() {
|
||||
}
|
||||
|
||||
function start_inventree() {
|
||||
echo "# POI15| Starting InvenTree"
|
||||
echo "# Starting InvenTree"
|
||||
${INIT_CMD} start inventree
|
||||
echo "# POI15| Started InvenTree"
|
||||
}
|
||||
|
||||
function stop_inventree() {
|
||||
echo "# POI11| Stopping InvenTree"
|
||||
echo "# Stopping InvenTree"
|
||||
${INIT_CMD} stop inventree
|
||||
echo "# POI11| Stopped InvenTree"
|
||||
}
|
||||
|
||||
function update_or_install() {
|
||||
set -e
|
||||
|
||||
# Set permissions so app user can write there
|
||||
chown ${APP_USER}:${APP_GROUP} ${APP_HOME} -R
|
||||
|
||||
# Run update as app user
|
||||
echo "# POI12| Updating InvenTree"
|
||||
echo "# Updating InvenTree"
|
||||
sudo -u ${APP_USER} --preserve-env=$SETUP_ENVS bash -c "cd ${APP_HOME} && pip install wheel"
|
||||
sudo -u ${APP_USER} --preserve-env=$SETUP_ENVS bash -c "cd ${APP_HOME} && invoke update | sed -e 's/^/# POI12| u | /;'"
|
||||
sudo -u ${APP_USER} --preserve-env=$SETUP_ENVS bash -c "cd ${APP_HOME} && invoke update | sed -e 's/^/# inv update| /;'"
|
||||
|
||||
# Make sure permissions are correct again
|
||||
echo "# POI12| Set permissions for data dir and media: ${DATA_DIR}"
|
||||
echo "# Set permissions for data dir and media: ${DATA_DIR}"
|
||||
chown ${APP_USER}:${APP_GROUP} ${DATA_DIR} -R
|
||||
chown ${APP_USER}:${APP_GROUP} ${CONF_DIR} -R
|
||||
}
|
||||
|
||||
function set_env() {
|
||||
echo "# POI13| Setting up InvenTree config values"
|
||||
echo "# Setting up InvenTree config values"
|
||||
|
||||
inventree config:set INVENTREE_CONFIG_FILE=${INVENTREE_CONFIG_FILE}
|
||||
|
||||
# Changing the config file
|
||||
echo "# POI13| Writing the settings to the config file ${INVENTREE_CONFIG_FILE}"
|
||||
echo "# Writing the settings to the config file ${INVENTREE_CONFIG_FILE}"
|
||||
# Media Root
|
||||
sed -i s=#media_root:\ \'/home/inventree/data/media\'=media_root:\ \'${INVENTREE_MEDIA_ROOT}\'=g ${INVENTREE_CONFIG_FILE}
|
||||
# Static Root
|
||||
@@ -331,42 +287,37 @@ function set_env() {
|
||||
sed -i s=debug:\ True=debug:\ False=g ${INVENTREE_CONFIG_FILE}
|
||||
|
||||
# Database engine
|
||||
sed -i s=#\ ENGINE:\ Database\ engine.\ Selection\ from:=ENGINE:\ ${INVENTREE_DB_ENGINE}=g ${INVENTREE_CONFIG_FILE}
|
||||
sed -i s=#ENGINE:\ sampleengine=ENGINE:\ ${INVENTREE_DB_ENGINE}=g ${INVENTREE_CONFIG_FILE}
|
||||
# Database name
|
||||
sed -i s=#\ NAME:\ Database\ name=NAME:\ \'${INVENTREE_DB_NAME}\'=g ${INVENTREE_CONFIG_FILE}
|
||||
sed -i s=#NAME:\ \'/path/to/database\'=NAME:\ \'${INVENTREE_DB_NAME}\'=g ${INVENTREE_CONFIG_FILE}
|
||||
# Database user
|
||||
sed -i s=#\ USER:\ Database\ username\ \(if\ required\)=USER:\ ${INVENTREE_DB_USER}=g ${INVENTREE_CONFIG_FILE}
|
||||
sed -i s=#USER:\ sampleuser=USER:\ ${INVENTREE_DB_USER}=g ${INVENTREE_CONFIG_FILE}
|
||||
# Database password
|
||||
sed -i s=#\ PASSWORD:\ Database\ password\ \(if\ required\)=PASSWORD:\ ${INVENTREE_DB_PASSWORD}=g ${INVENTREE_CONFIG_FILE}
|
||||
sed -i s=#PASSWORD:\ samplepassword=PASSWORD:\ ${INVENTREE_DB_PASSWORD}=g ${INVENTREE_CONFIG_FILE}
|
||||
# Database host
|
||||
sed -i s=#\ HOST:\ Database\ host\ address\ \(if\ required\)=HOST:\ ${INVENTREE_DB_HOST}=g ${INVENTREE_CONFIG_FILE}
|
||||
sed -i s=#HOST:\ samplehost=HOST:\ ${INVENTREE_DB_HOST}=g ${INVENTREE_CONFIG_FILE}
|
||||
# Database port
|
||||
sed -i s=#\ PORT:\ Database\ host\ port\ \(if\ required\)=PORT:\ ${INVENTREE_DB_PORT}=g ${INVENTREE_CONFIG_FILE}
|
||||
sed -i s=#PORT:\ 123456=PORT:\ ${INVENTREE_DB_PORT}=g ${INVENTREE_CONFIG_FILE}
|
||||
|
||||
# Fixing the permissions
|
||||
chown ${APP_USER}:${APP_GROUP} ${DATA_DIR} ${INVENTREE_CONFIG_FILE}
|
||||
|
||||
echo "# POI13| Done setting up InvenTree config values"
|
||||
}
|
||||
|
||||
function set_site() {
|
||||
# Ensure IP is known
|
||||
if [ -z "${INVENTREE_IP}" ]; then
|
||||
echo "# POI14| No IP address found - skipping"
|
||||
echo "# No IP address found - skipping"
|
||||
return
|
||||
fi
|
||||
|
||||
# Check if INVENTREE_SITE_URL in inventree config
|
||||
if [ -z "$(inventree config:get INVENTREE_SITE_URL)" ]; then
|
||||
echo "# POI14| Setting up InvenTree site URL"
|
||||
echo "# Setting up InvenTree site URL"
|
||||
inventree config:set INVENTREE_SITE_URL=http://${INVENTREE_IP}
|
||||
else
|
||||
echo "# POI14| Site URL already set - skipping"
|
||||
fi
|
||||
}
|
||||
|
||||
function final_message() {
|
||||
echo "# POI16| Printing Final message"
|
||||
echo -e "####################################################################################"
|
||||
echo -e "This InvenTree install uses nginx, the settings for the webserver can be found in"
|
||||
echo -e "${SETUP_NGINX_FILE}"
|
||||
@@ -377,46 +328,3 @@ function final_message() {
|
||||
echo -e " Password: ${INVENTREE_ADMIN_PASSWORD}"
|
||||
echo -e "####################################################################################"
|
||||
}
|
||||
|
||||
|
||||
function update_checks() {
|
||||
echo "# POI08| Running upgrade"
|
||||
local old_version=$1
|
||||
local old_version_rev=$(echo ${old_version} | cut -d'-' -f1 | cut -d'.' -f2)
|
||||
local new_version=$(dpkg-query --show --showformat='${Version}' inventree)
|
||||
local new_version_rev=$(echo ${new_version} | cut -d'-' -f1 | cut -d'.' -f2)
|
||||
echo "# POI08| Old version is: ${old_version} | ${old_version_rev} - updating to ${new_version} | ${old_version_rev}"
|
||||
|
||||
local ABORT=false
|
||||
function check_config_value() {
|
||||
local env_key=$1
|
||||
local config_key=$2
|
||||
local name=$3
|
||||
|
||||
local value=$(inventree config:get ${env_key})
|
||||
if [ -z "${value}" ] || [ "$value" == "null" ]; then
|
||||
value=$(jq -r ".[].${config_key}" <<< ${INVENTREE_CONF_DATA})
|
||||
fi
|
||||
if [ -z "${value}" ] || [ "$value" == "null" ]; then
|
||||
echo "# POI08| No setting for ${name} found - please set it manually either in ${INVENTREE_CONFIG_FILE} under '${config_key}' or with 'inventree config:set ${env_key}=value'"
|
||||
ABORT=true
|
||||
else
|
||||
echo "# POI08| Found setting for ${name} - ${value}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Custom checks if old version is below 0.8.0
|
||||
if [ "${old_version_rev}" -lt "9" ]; then
|
||||
echo "# POI08| Old version is below 0.9.0 - You might be missing some configs"
|
||||
|
||||
# Check for BACKUP_DIR and SITE_URL in INVENTREE_CONF_DATA and config
|
||||
check_config_value "INVENTREE_SITE_URL" "site_url" "site URL"
|
||||
check_config_value "INVENTREE_BACKUP_DIR" "backup_dir" "backup dir"
|
||||
|
||||
if [ "${ABORT}" = true ]; then
|
||||
echo "# POI08| Aborting - please set the missing values and run the update again"
|
||||
exit 1
|
||||
fi
|
||||
echo "# POI08| All checks passed - continuing with the update"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -3,18 +3,15 @@
|
||||
# packager.io postinstall script
|
||||
#
|
||||
|
||||
echo "# POI01| Running postinstall script - start - $(date)"
|
||||
exec > >(tee ${APP_HOME}/log/setup_$(date +"%F_%H_%M_%S").log) 2>&1
|
||||
|
||||
PATH=${APP_HOME}/env/bin:${APP_HOME}/:/sbin:/bin:/usr/sbin:/usr/bin:
|
||||
|
||||
# import functions
|
||||
echo "# POI01| Importing functions"
|
||||
. ${APP_HOME}/contrib/packager.io/functions.sh
|
||||
echo "# POI01| Functions imported"
|
||||
|
||||
# Envs that should be passed to setup commands
|
||||
export SETUP_ENVS=PATH,APP_HOME,INVENTREE_MEDIA_ROOT,INVENTREE_STATIC_ROOT,INVENTREE_BACKUP_DIR,INVENTREE_SITE_URL,INVENTREE_PLUGINS_ENABLED,INVENTREE_PLUGIN_FILE,INVENTREE_CONFIG_FILE,INVENTREE_SECRET_KEY_FILE,INVENTREE_DB_ENGINE,INVENTREE_DB_NAME,INVENTREE_DB_USER,INVENTREE_DB_PASSWORD,INVENTREE_DB_HOST,INVENTREE_DB_PORT,INVENTREE_ADMIN_USER,INVENTREE_ADMIN_EMAIL,INVENTREE_ADMIN_PASSWORD,SETUP_NGINX_FILE,SETUP_ADMIN_PASSWORD_FILE,SETUP_NO_CALLS,SETUP_DEBUG,SETUP_EXTRA_PIP,SETUP_PYTHON,SETUP_ADMIN_NOCREATION
|
||||
export SETUP_ENVS=PATH,APP_HOME,INVENTREE_MEDIA_ROOT,INVENTREE_STATIC_ROOT,INVENTREE_BACKUP_DIR,INVENTREE_PLUGINS_ENABLED,INVENTREE_PLUGIN_FILE,INVENTREE_CONFIG_FILE,INVENTREE_SECRET_KEY_FILE,INVENTREE_DB_ENGINE,INVENTREE_DB_NAME,INVENTREE_DB_USER,INVENTREE_DB_PASSWORD,INVENTREE_DB_HOST,INVENTREE_DB_PORT,INVENTREE_ADMIN_USER,INVENTREE_ADMIN_EMAIL,INVENTREE_ADMIN_PASSWORD,SETUP_NGINX_FILE,SETUP_ADMIN_PASSWORD_FILE,SETUP_NO_CALLS,SETUP_DEBUG,SETUP_EXTRA_PIP,SETUP_PYTHON
|
||||
|
||||
# Get the envs
|
||||
detect_local_env
|
||||
@@ -27,7 +24,6 @@ export SETUP_NGINX_FILE=${SETUP_NGINX_FILE:-/etc/nginx/sites-enabled/inventree.c
|
||||
export SETUP_ADMIN_PASSWORD_FILE=${CONF_DIR}/admin_password.txt
|
||||
export SETUP_NO_CALLS=${SETUP_NO_CALLS:-false}
|
||||
export SETUP_PYTHON=${SETUP_PYTHON:-python3.9}
|
||||
export SETUP_ADMIN_NOCREATION=${SETUP_ADMIN_NOCREATION:-false}
|
||||
# SETUP_DEBUG can be set to get debug info
|
||||
# SETUP_EXTRA_PIP can be set to install extra pip packages
|
||||
# SETUP_PYTHON can be set to use a different python version
|
||||
@@ -39,14 +35,6 @@ detect_initcmd
|
||||
detect_ip
|
||||
detect_python
|
||||
|
||||
# Check if we are updating and need to alert
|
||||
echo "# POI08| Checking if update checks are needed"
|
||||
if [ -z "$2" ]; then
|
||||
echo "# POI08| Normal install - no need for checks"
|
||||
else
|
||||
update_checks $2
|
||||
fi
|
||||
|
||||
# create processes
|
||||
create_initscripts
|
||||
create_admin
|
||||
@@ -63,4 +51,3 @@ start_inventree
|
||||
|
||||
# show info
|
||||
final_message
|
||||
echo "# POI17| Running postinstall script - done - $(date)"
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# packager.io preinstall/preremove script
|
||||
#
|
||||
echo "# PRI01| Running preinstall script - start - $(date)"
|
||||
PATH=${APP_HOME}/env/bin:${APP_HOME}/:/sbin:/bin:/usr/sbin:/usr/bin:
|
||||
|
||||
# Envs that should be passed to setup commands
|
||||
export SETUP_ENVS=PATH,APP_HOME,INVENTREE_MEDIA_ROOT,INVENTREE_STATIC_ROOT,INVENTREE_BACKUP_DIR,INVENTREE_PLUGINS_ENABLED,INVENTREE_PLUGIN_FILE,INVENTREE_CONFIG_FILE,INVENTREE_SECRET_KEY_FILE,INVENTREE_DB_ENGINE,INVENTREE_DB_NAME,INVENTREE_DB_USER,INVENTREE_DB_PASSWORD,INVENTREE_DB_HOST,INVENTREE_DB_PORT,INVENTREE_ADMIN_USER,INVENTREE_ADMIN_EMAIL,INVENTREE_ADMIN_PASSWORD,SETUP_NGINX_FILE,SETUP_ADMIN_PASSWORD_FILE,SETUP_NO_CALLS,SETUP_DEBUG,SETUP_EXTRA_PIP,SETUP_PYTHON
|
||||
|
||||
if test -f "${APP_HOME}/env/bin/pip"; then
|
||||
# Check if clear-generated is available
|
||||
if sudo -u ${APP_USER} --preserve-env=$SETUP_ENVS bash -c "cd ${APP_HOME} && invoke int.clear-generated --help" > /dev/null 2>&1; then
|
||||
echo "# PRI02| Clearing precompiled files"
|
||||
sudo -u ${APP_USER} --preserve-env=$SETUP_ENVS bash -c "cd ${APP_HOME} && invoke int.clear-generated"
|
||||
else
|
||||
echo "# PRI02| Clearing precompiled files - skipping"
|
||||
fi
|
||||
else
|
||||
echo "# PRI02| No python environment found - skipping"
|
||||
fi
|
||||
|
||||
echo "# PRI03| Running preinstall script - done - $(date)"
|
||||
@@ -1,14 +1,8 @@
|
||||
# Configuration file for Crowdin project integration
|
||||
# See: https://crowdin.com/project/inventree
|
||||
|
||||
"commit_message": "Fix: New translations %original_file_name% from Crowdin"
|
||||
"append_commit_message": false
|
||||
"preserve_hierarchy": true
|
||||
|
||||
files:
|
||||
- source: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po
|
||||
dest: /%original_path%/%original_file_name%
|
||||
translation: /src/backend/InvenTree/locale/%two_letters_code%/LC_MESSAGES/%original_file_name%
|
||||
- source: /src/frontend/src/locales/en/messages.po
|
||||
dest: /%original_path%/%original_file_name%
|
||||
translation: /src/frontend/src/locales/%two_letters_code%/%original_file_name%
|
||||
|
||||
4
docs/.gitignore
vendored
@@ -13,10 +13,6 @@ site/
|
||||
# Generated API schema files
|
||||
docs/api/schema/*.yml
|
||||
|
||||
# Temporary cache files
|
||||
url_cache.txt
|
||||
invoke-commands.txt
|
||||
|
||||
# Temp files
|
||||
releases.json
|
||||
versions.json
|
||||
|
||||
@@ -10,7 +10,7 @@ tld = os.path.abspath(os.path.join(here, '..'))
|
||||
|
||||
config_file = os.path.join(tld, 'mkdocs.yml')
|
||||
|
||||
with open(config_file, encoding='utf-8') as f:
|
||||
with open(config_file, 'r') as f:
|
||||
data = yaml.load(f, yaml.BaseLoader)
|
||||
|
||||
assert data['strict'] == 'true'
|
||||
|
||||
@@ -22,10 +22,10 @@ The API is self-documenting, and the documentation is provided alongside any Inv
|
||||
|
||||
### Generating Schema File
|
||||
|
||||
If you want to generate the API schema file yourself (for example to use with an external client, use the `invoke dev.schema` command. Run with the `-help` command to see available options.
|
||||
If you want to generate the API schema file yourself (for example to use with an external client, use the `invoke schema` command. Run with the `-help` command to see available options.
|
||||
|
||||
```
|
||||
invoke dev.schema -help
|
||||
invoke schema -help
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
|
Before Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 5.4 KiB |
BIN
docs/docs/assets/images/report/add_report_template.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 42 KiB |
BIN
docs/docs/assets/images/settings/user_notifications.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
docs/docs/assets/images/settings/user_reporting.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 65 KiB |
@@ -56,11 +56,3 @@ If no match is found for the scanned barcode, the following error message is dis
|
||||
## App Integration
|
||||
|
||||
Barcode scanning is a key feature of the [companion mobile app](../app/barcode.md).
|
||||
|
||||
## Barcode History
|
||||
|
||||
If enabled, InvenTree can retain logs of the most recent barcode scans. This can be very useful for debugging or auditing purpopes.
|
||||
|
||||
Refer to the [barcode settings](../settings/global.md#barcodes) to enable barcode history logging.
|
||||
|
||||
The barcode history can be viewed via the admin panel in the web interface.
|
||||
|
||||
@@ -4,11 +4,7 @@ title: Internal Barcodes
|
||||
|
||||
## Internal Barcodes
|
||||
|
||||
InvenTree ships with two integrated internal formats for generating barcodes for various items which are available through the built-in InvenTree Barcode plugin. The used format can be selected through the plugin settings of the InvenTree Barcode plugin.
|
||||
|
||||
### 1. JSON-based QR Codes
|
||||
|
||||
This format uses a simple JSON-style string to uniquely identify an item in the database.
|
||||
InvenTree defines an internal format for generating barcodes for various items. This format uses a simple JSON-style string to uniquely identify an item in the database.
|
||||
|
||||
Some simple examples of this format are shown below:
|
||||
|
||||
@@ -16,49 +12,10 @@ Some simple examples of this format are shown below:
|
||||
| --- | --- |
|
||||
| Part | `{% raw %}{"part": 10}{% endraw %}` |
|
||||
| Stock Item | `{% raw %}{"stockitem": 123}{% endraw %}` |
|
||||
| Stock Location | `{% raw %}{"stocklocation": 1}{% endraw %}` |
|
||||
| Supplier Part | `{% raw %}{"supplierpart": 99}{% endraw %}` |
|
||||
|
||||
The numerical ID value used is the *Primary Key* (PK) of the particular object in the database.
|
||||
|
||||
#### Downsides
|
||||
|
||||
1. The JSON format includes binary only characters (`{% raw %}{{% endraw %}` and `{% raw %}"{% endraw %}`) which requires unnecessary use of the binary QR code encoding which means fewer amount of chars can be encoded with the same version of QR code.
|
||||
2. The model name key has not a fixed length. Some model names are longer than others. E.g. a part QR code with the shortest possible id requires 11 chars, while a stock location QR code with the same id would already require 20 chars, which already requires QR code version 2 and quickly version 3.
|
||||
|
||||
!!! info "QR code versions"
|
||||
There are 40 different qr code versions from 1-40. They all can encode more data than the previous version, but require more "squares". E.g. a V1 QR codes has 21x21 "squares" while a V2 already has 25x25. For more information see [QR code comparison](https://www.qrcode.com/en/about/version.html).
|
||||
|
||||
For a more detailed size analysis of the JSON-based QR codes refer to [this issue](https://github.com/inventree/InvenTree/issues/6612).
|
||||
|
||||
### 2. Short alphanumeric QR Codes
|
||||
|
||||
While JSON-based QR Codes encode all necessary information, they come with the described downsides. This new, short, alphanumeric only format is build to improve those downsides. The basic format uses an alphanumeric string: `INV-??x`
|
||||
|
||||
- `INV-` is a constant prefix. This is configurable in the InvenTree Barcode plugins settings per instance to support environments that use multiple instances.
|
||||
- `??` is a two character alphanumeric (`0-9A-Z $%*+-./:` (45 chars)) code, individual to each model.
|
||||
- `x` the actual pk of the model.
|
||||
|
||||
Now with an overhead of 6 chars for every model, this format supports the following amount of model instances using the described QR code modes:
|
||||
|
||||
| QR code mode | Alphanumeric mode | Mixed mode |
|
||||
| --- | --- | --- |
|
||||
| v1 M ECL (15%) | `10**14` items (~3.170 items per sec for 1000 years) | `10**20` items (~3.170.979.198 items per sec for 1000 years) |
|
||||
| v1 Q ECL (25%) | `10**10` items (~0.317 items per sec for 1000 years) | `10**13` items (~317 items per sec for 1000 years) |
|
||||
| v1 H ECL (30%) | `10**4` items (~100 items per day for 100 days) | `10**3` items (~100 items per day for 10 days (*even worse*)) |
|
||||
|
||||
!!! info "QR code mixed mode"
|
||||
Normally the QR code data is encoded only in one format (binary, alphanumeric, numeric). But the data can also be split into multiple chunks using different formats. This is especially useful with long model ids, because the first 6 chars can be encoded using the alphanumeric mode and the id using the more efficient numeric mode. Mixed mode is used by default, because the `qrcode` template tag uses a default value for optimize of 1.
|
||||
|
||||
Some simple examples of this format are shown below:
|
||||
|
||||
| Model Type | Example Barcode |
|
||||
| --- | --- |
|
||||
| Part | `INV-PA10` |
|
||||
| Stock Item | `INV-SI123` |
|
||||
| Stock Location | `INV-SL1` |
|
||||
| Supplier Part | `INV-SP99` |
|
||||
|
||||
## Report Integration
|
||||
|
||||
This barcode format can be used to generate 1D or 2D barcodes (e.g. for [labels and reports](../report/barcodes.md))
|
||||
|
||||
116
docs/docs/build/build.md
vendored
@@ -26,6 +26,14 @@ To navigate to the Build Order display, select *Build* from the main navigation
|
||||
{% include "img.html" %}
|
||||
{% endwith %}
|
||||
|
||||
#### Tree View
|
||||
|
||||
*Tree View* also provides a tabulated view of Build Orders. Orders are displayed in a hierarchical manner, showing any parent / child relationships between different build orders.
|
||||
|
||||
{% with id="build_tree", url="build/build_tree.png", description="Build Tree" %}
|
||||
{% include "img.html" %}
|
||||
{% endwith %}
|
||||
|
||||
#### Calendar View
|
||||
|
||||
*Calendar View* shows a calendar display with upcoming build orders, based on the various dates specified for each build.
|
||||
@@ -66,23 +74,10 @@ Each *Build Order* has an associated *Status* flag, which indicates the state of
|
||||
|
||||
| Status | Description |
|
||||
| ----------- | ----------- |
|
||||
| `Pending` | Build order has been created, but is not yet in production |
|
||||
| `Production` | Build order is currently in production |
|
||||
| `On Hold` | Build order has been placed on hold, but is still active |
|
||||
| `Cancelled` | Build order has been cancelled |
|
||||
| `Completed` | Build order has been completed |
|
||||
|
||||
**Source Code**
|
||||
|
||||
Refer to the source code for the Build Order status codes:
|
||||
|
||||
::: build.status_codes.BuildStatus
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
| `Pending` | Build has been created and build is ready for subpart allocation |
|
||||
| `Production` | One or more build outputs have been created for this build |
|
||||
| `Cancelled` | Build has been cancelled |
|
||||
| `Completed` | Build has been completed |
|
||||
|
||||
### Stock Allocations
|
||||
|
||||
@@ -104,29 +99,41 @@ For further information, refer to the [stock allocation documentation](./allocat
|
||||
|
||||
## Build Order Display
|
||||
|
||||
The detail view for a single build order provides multiple display panels, as follows:
|
||||
The detail view for a single build order provides multiple display tabs, as follows:
|
||||
|
||||
### Build Details
|
||||
|
||||
The *Build Details* panel provides an overview of the Build Order:
|
||||
The *Build Details* tab provides an overview of the Build Order:
|
||||
|
||||
{% with id="build_details", url="build/build_panel_details.png", description="Build details panel" %}
|
||||
{% with id="build_details", url="build/build_details.png", description="Details tab" %}
|
||||
{% include "img.html" %}
|
||||
{% endwith %}
|
||||
|
||||
### Line Items
|
||||
### Allocate Stock
|
||||
|
||||
The *Line Items* panel displays all the line items (as defined by the [bill of materials](./bom.md)) required to complete the build order.
|
||||
The *Allocate Stock* tab provides an interface to allocate required stock (as specified by the BOM) to the build:
|
||||
|
||||
{% with id="build_allocate", url="build/build_panel_line_items.png", description="Build line items panel" %}
|
||||
{% with id="build_allocate", url="build/build_allocate.png", description="Allocation tab" %}
|
||||
{% include "img.html" %}
|
||||
{% endwith %}
|
||||
|
||||
The allocation table (as shown above) provides an interface to allocate required stock, and also shows the stock allocation progress for each line item in the build.
|
||||
The allocation table (as shown above) shows the stock allocation progress for this build. In the example above, there are two BOM lines, which have been partially allocated.
|
||||
|
||||
### Incomplete Outputs
|
||||
!!! info "Completed Builds"
|
||||
The *Allocate Stock* tab is not available if the build has been completed!
|
||||
|
||||
The *Incomplete Outputs* panel shows the list of in-progress [build outputs](./output.md) (created stock items) associated with this build.
|
||||
### Consumed Stock
|
||||
|
||||
The *Consumed Stock* tab displays all stock items which have been *consumed* by this build order. These stock items remain in the database after the build order has been completed, but are no longer available for use.
|
||||
|
||||
- [Tracked stock items](./allocate.md#tracked-stock) are consumed by specific build outputs
|
||||
- [Untracked stock items](./allocate.md#untracked-stock) are consumed by the build order
|
||||
|
||||
### Build Outputs
|
||||
|
||||
The *Build Outputs* tab shows the [build outputs](./output.md) (created stock items) associated with this build.
|
||||
|
||||
As shown below, there are separate panels for *incomplete* and *completed* build outputs.
|
||||
|
||||
{% with id="build_outputs", url="build/build_outputs.png", description="Outputs tab" %}
|
||||
{% include "img.html" %}
|
||||
@@ -139,48 +146,11 @@ The *Incomplete Outputs* panel shows the list of in-progress [build outputs](./o
|
||||
- Outputs which are "in progress" can be completed or cancelled
|
||||
- Completed outputs (which are simply *stock items*) can be viewed in the stock table at the bottom of the screen
|
||||
|
||||
### Completed Outputs
|
||||
|
||||
This panel displays all the completed build outputs (stock items) which have been created by this build order:
|
||||
|
||||
### Allocated Stock
|
||||
|
||||
The *Allocated Stock* tab displays all stock items which have been *allocated* to this build order. These stock items are reserved for this build, and will be consumed when the build is completed:
|
||||
|
||||
{% with id="allocated_stock_table", url="build/allocated_stock_table.png", description="Allocated Stock Table" %}
|
||||
{% include "img.html" %}
|
||||
{% endwith %}
|
||||
|
||||
### Consumed Stock
|
||||
|
||||
The *Consumed Stock* tab displays all stock items which have been *consumed* by this build order. These stock items remain in the database after the build order has been completed, but are no longer available for use.
|
||||
|
||||
- [Tracked stock items](./allocate.md#tracked-stock) are consumed by specific build outputs
|
||||
- [Untracked stock items](./allocate.md#untracked-stock) are consumed by the build order
|
||||
|
||||
### Child Builds
|
||||
|
||||
If there exist any build orders which are *children* of the selected build order, they are displayed in the *Child Builds* tab:
|
||||
|
||||
{% with id="build_childs", url="build/build_childs.png", description="Child builds panel" %}
|
||||
{% include "img.html" %}
|
||||
{% endwith %}
|
||||
|
||||
### Test Results
|
||||
|
||||
For *trackable* parts, test results can be recorded against each build output. These results are displayed in the *Test Results* panel:
|
||||
|
||||
{% with id="build_test_results", url="build/build_panel_test_results.png", description="Test Results panel" %}
|
||||
{% include "img.html" %}
|
||||
{% endwith %}
|
||||
|
||||
This table provides a summary of the test results for each build output, and allows test results to be quickly added for each build output.
|
||||
|
||||
### Test Statistics
|
||||
|
||||
For *trackable* parts, this panel displays a summary of the test results for all build outputs:
|
||||
|
||||
{% with id="build_test_stats", url="build/build_panel_test_statistics.png", description="Test Statistics panel" %}
|
||||
{% with id="build_childs", url="build/build_childs.png", description="Child builds tab" %}
|
||||
{% include "img.html" %}
|
||||
{% endwith %}
|
||||
|
||||
@@ -221,10 +191,6 @@ To create a build order for your part, you have two options:
|
||||
|
||||
Fill-out the form as required, then click the "Submit" button to create the build.
|
||||
|
||||
### Create Child Builds
|
||||
|
||||
When creating a new build order, you have the option to automatically generate build orders for any subassembly parts. This can be useful to create a complete tree of build orders for a complex assembly. *However*, it must be noted that any build orders created for subassemblies will use the default BOM quantity for that part. Any child build orders created in this manner must be manually reviewed, to ensure that the correct quantity is being built as per your production requirements.
|
||||
|
||||
## Complete Build Order
|
||||
|
||||
To complete a build, click on <span class='fas fa-tools'></span> icon on the build detail page, the `Complete Build` form will be displayed.
|
||||
@@ -268,17 +234,3 @@ Build orders may (optionally) have a target complete date specified. If this dat
|
||||
|
||||
- Builds can be filtered by overdue status in the build list
|
||||
- Overdue builds will be displayed on the home page
|
||||
|
||||
## Build Order Settings
|
||||
|
||||
The following [global settings](../settings/global.md) are available for adjusting the behavior of build orders:
|
||||
|
||||
| Name | Description | Default | Units |
|
||||
| ---- | ----------- | ------- | ----- |
|
||||
{{ globalsetting("BUILDORDER_REFERENCE_PATTERN") }}
|
||||
{{ globalsetting("BUILDORDER_REQUIRE_RESPONSIBLE") }}
|
||||
{{ globalsetting("BUILDORDER_REQUIRE_ACTIVE_PART") }}
|
||||
{{ globalsetting("BUILDORDER_REQUIRE_LOCKED_PART") }}
|
||||
{{ globalsetting("BUILDORDER_REQUIRE_VALID_BOM") }}
|
||||
{{ globalsetting("BUILDORDER_REQUIRE_CLOSED_CHILDS") }}
|
||||
{{ globalsetting("PREVENT_BUILD_COMPLETION_HAVING_INCOMPLETED_TESTS") }}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
---
|
||||
title: Custom States
|
||||
---
|
||||
|
||||
## Custom States
|
||||
|
||||
Several models within InvenTree support the use of custom states. The custom states are display only - the business logic is not affected by the state.
|
||||
|
||||
States can be added in the Admin Center under the "Custom States" section. Each state has a name, label and a color that are used to display the state in the user interface. Changes to these settings will only be reflected in the user interface after a full reload of the interface.
|
||||
|
||||
States need to be assigned to a model, state (for example status on a StockItem) and a logical key - that will be used for business logic. These 3 values combined need to be unique throughout the system.
|
||||
|
||||
Custom states can be used in the following models:
|
||||
- StockItem
|
||||
- Orders (PurchaseOrder, SalesOrder, ReturnOrder, ReturnOrderLine)
|
||||
@@ -4,55 +4,4 @@ title: InvenTree Demo
|
||||
|
||||
## InvenTree Demo
|
||||
|
||||
If you are interested in trying out InvenTree, you can access the InvenTree demo instance at [https://demo.inventree.org](https://demo.inventree.org).
|
||||
|
||||
This page is populated with a sample dataset, which is reset every 24 hours.
|
||||
|
||||
You can read more about the InvenTree demo here: [https://inventree.org/demo.html](https://inventree.org/demo.html)
|
||||
|
||||
### User Accounts
|
||||
|
||||
The demo instance has a number of user accounts which you can use to explore the system:
|
||||
|
||||
| Username | Password | Staff Access | Enabled | Description |
|
||||
| -------- | -------- | ------------ | ------- | ----------- |
|
||||
| noaccess | youshallnotpass | No | Yes | Can login, but has no permissions |
|
||||
| allaccess | nolimits | No | Yes | View / create / edit all pages and items |
|
||||
| reader | readonly | No | Yes | Can view all pages but cannot create, edit or delete database records |
|
||||
| engineer | partsonly | No | Yes | Can manage parts, view stock, but no access to purchase orders or sales orders |
|
||||
| steven | wizardstaff | Yes | Yes | Staff account, can access some admin sections |
|
||||
| ian | inactive | No | No | Inactive account, cannot log in |
|
||||
| susan | inactive | No | No | Inactive account, cannot log in |
|
||||
| admin | inventree | Yes | Yes | Superuser account, can access all parts of the system |
|
||||
|
||||
### Dataset
|
||||
|
||||
The demo instance is populated with a sample dataset, which is reset every 24 hours.
|
||||
|
||||
The source data used in the demo instance can be found on our [GitHub page](https://github.com/inventree/demo-dataset).
|
||||
|
||||
### Local Setup
|
||||
|
||||
If you wish to install the demo dataset locally (for initial testing), you can run the following command (via [invoke](./start/invoke.md)):
|
||||
|
||||
```bash
|
||||
invoke dev.setup-test -i
|
||||
```
|
||||
|
||||
*(Note: The command above may be slightly different if you are running in docker.)*
|
||||
|
||||
This will install the demo dataset into your local InvenTree instance.
|
||||
|
||||
!!! warning "Warning"
|
||||
This command will **delete all existing data** in your InvenTree instance! It is not intended to be used on a production system, or loaded into an existing dataset.
|
||||
|
||||
### Clear Data
|
||||
|
||||
To clear demo data from your instance, and start afresh with a clean database, you can run the following command (via [invoke](./start/invoke.md)):
|
||||
|
||||
```bash
|
||||
invoke dev.delete-data
|
||||
```
|
||||
|
||||
!!! warning "Warning"
|
||||
This command will **delete all existing data** in your InvenTree instance, including any data that you have added yourself.
|
||||
This page has moved to [https://inventree.org/demo.html](https://inventree.org/demo.html)
|
||||
|
||||
@@ -22,9 +22,9 @@ To setup a development environment using [docker](../start/docker.md), run the f
|
||||
|
||||
```bash
|
||||
git clone https://github.com/inventree/InvenTree.git && cd InvenTree
|
||||
docker compose --project-directory . -f contrib/container/dev-docker-compose.yml run --rm inventree-dev-server invoke install
|
||||
docker compose --project-directory . -f contrib/container/dev-docker-compose.yml run --rm inventree-dev-server invoke dev.setup-test --dev
|
||||
docker compose --project-directory . -f contrib/container/dev-docker-compose.yml up -d
|
||||
docker compose run inventree-dev-server invoke install
|
||||
docker compose run inventree-dev-server invoke setup-test --dev
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### Bare Metal
|
||||
@@ -34,46 +34,33 @@ A "bare metal" development setup can be installed as follows:
|
||||
```bash
|
||||
git clone https://github.com/inventree/InvenTree.git && cd InvenTree
|
||||
python3 -m venv env && source env/bin/activate
|
||||
pip install django invoke && invoke
|
||||
invoke dev.setup-dev --tests
|
||||
pip install invoke && invoke
|
||||
pip install invoke && invoke setup-dev --tests
|
||||
```
|
||||
|
||||
Read the [InvenTree setup documentation](../start/intro.md) for a complete installation reference guide.
|
||||
|
||||
!!! note "Required Packages"
|
||||
Depending on your system, you may need to install additional software packages as required.
|
||||
|
||||
### Setup Devtools
|
||||
|
||||
Run the following command to set up all toolsets for development.
|
||||
|
||||
```bash
|
||||
invoke dev.setup-dev
|
||||
invoke setup-dev
|
||||
```
|
||||
|
||||
*We recommend you run this command before starting to contribute. This will install and set up `pre-commit` to run some checks before each commit and help reduce errors.*
|
||||
|
||||
## Branches and Versioning
|
||||
|
||||
InvenTree roughly follow the [GitLab flow](https://about.gitlab.com/topics/version-control/what-are-gitlab-flow-best-practices/) branching style, to allow simple management of multiple tagged releases, short-lived branches, and development on the main branch.
|
||||
|
||||
There are nominally 5 active branches:
|
||||
- `master` - The main development branch
|
||||
- `stable` - The latest stable release
|
||||
- `l10n` - Translation branch: Source to Crowdin
|
||||
- `l10_crowdin` - Translation branch: Source from Crowdin
|
||||
- `y.y.x` - Release branch for the currently supported version (e.g. `0.5.x`)
|
||||
|
||||
All other branches are removed periodically by maintainers or core team members. This includes old release branches.
|
||||
Do not use them as base for feature development or forks as patches from them might not be accepted without rebasing.
|
||||
InvenTree roughly follow the [GitLab flow](https://docs.gitlab.com/ee/topics/gitlab_flow.html) branching style, to allow simple management of multiple tagged releases, short-lived branches, and development on the main branch.
|
||||
|
||||
### Version Numbering
|
||||
|
||||
InvenTree version numbering follows the [semantic versioning](https://semver.org/) specification.
|
||||
|
||||
### Main Development Branch
|
||||
### Master Branch
|
||||
|
||||
The HEAD of the "master" branch of InvenTree represents the current "latest" state of code development.
|
||||
The HEAD of the "main" or "master" branch of InvenTree represents the current "latest" state of code development.
|
||||
|
||||
- All feature branches are merged into master
|
||||
- All bug fixes are merged into master
|
||||
@@ -86,6 +73,7 @@ Feature branches should be branched *from* the *master* branch.
|
||||
|
||||
- One major feature per branch / pull request
|
||||
- Feature pull requests are merged back *into* the master branch
|
||||
- Features *may* also be merged into a release candidate branch
|
||||
|
||||
### Stable Branch
|
||||
|
||||
@@ -94,28 +82,21 @@ The HEAD of the "stable" branch represents the latest stable release code.
|
||||
- Versioned releases are merged into the "stable" branch
|
||||
- Bug fix branches are made *from* the "stable" branch
|
||||
|
||||
#### Release Candidate Branches
|
||||
|
||||
### Bugfix Branches
|
||||
- Release candidate branches are made from master, and merged into stable.
|
||||
- RC branches are targeted at a major/minor version e.g. "0.5"
|
||||
- When a release candidate branch is merged into *stable*, the release is tagged
|
||||
|
||||
#### Bugfix Branches
|
||||
|
||||
- If a bug is discovered in a tagged release version of InvenTree, a "bugfix" or "hotfix" branch should be made *from* that tagged release
|
||||
- When approved, the branch is merged back *into* stable, with an incremented PATCH number (e.g. 0.4.1 -> 0.4.2)
|
||||
- The bugfix *must* also be cherry picked into the *master* branch.
|
||||
- A bugfix *might* also be backported from *master* to the *stable* branch automatically if marked with the `backport` label.
|
||||
|
||||
### Translation Branches
|
||||
|
||||
Crowdin is used for web-based translation management. The handling of files is fully automated, the `l10n` and `l10_crowdin` branches are used to manage the translation process and are not meant to be touched manually by anyone.
|
||||
|
||||
The translation process is as follows:
|
||||
1. Commits to `master` trigger CI by GitHub Actions
|
||||
2. Translation source files are created and automatically pushed to the `l10n` branch - this is the source branch for Crowdin
|
||||
3. Crowdin picks up on the new source files and makes them available for translation
|
||||
4. Translations made in Crowdin are automatically pushed back to the `l10_crowdin` branch by Crowdin once they are approved
|
||||
5. The `l10_crowdin` branch is merged back into `master` by a maintainer periodically
|
||||
|
||||
## API versioning
|
||||
|
||||
The [API version]({{ sourcefile("src/backend/InvenTree/InvenTree/api_version.py") }}) needs to be bumped every time when the API is changed.
|
||||
The [API version](https://github.com/inventree/InvenTree/blob/0.15.x/src/backend/InvenTree/InvenTree/api_version.py) needs to be bumped every time when the API is changed.
|
||||
|
||||
## Environment
|
||||
|
||||
@@ -128,7 +109,7 @@ The core software modules are targeting the following versions:
|
||||
| Python | {{ config.extra.min_python_version }} | Minimum required version |
|
||||
| Invoke | {{ config.extra.min_invoke_version }} | Minimum required version |
|
||||
| Django | {{ config.extra.django_version }} | Pinned version |
|
||||
| Node | 20 | Only needed for frontend development |
|
||||
| Node | 18 | Only needed for frontend development |
|
||||
|
||||
Any other software dependencies are handled by the project package config.
|
||||
|
||||
@@ -172,35 +153,21 @@ The various github actions can be found in the `./github/workflows` directory
|
||||
### Run tests locally
|
||||
|
||||
To run test locally, use:
|
||||
|
||||
```
|
||||
invoke dev.test
|
||||
invoke test
|
||||
```
|
||||
|
||||
To run only partial tests, for example for a module use:
|
||||
```
|
||||
invoke dev.test --runtest order
|
||||
invoke test --runtest order
|
||||
```
|
||||
|
||||
To see all the available options:
|
||||
|
||||
```
|
||||
invoke dev.test --help
|
||||
invoke test --help
|
||||
```
|
||||
|
||||
#### Database Permission Issues
|
||||
|
||||
For local testing django creates a test database and removes it after testing. If you encounter permission issues while running unit test, ensure that your database user has permission to create new databases.
|
||||
|
||||
For example, in PostgreSQL, run:
|
||||
|
||||
```
|
||||
alter user myuser createdb;
|
||||
```
|
||||
|
||||
!!! info "Devcontainer"
|
||||
The default database container which is provided in the devcontainer is already setup with the required permissions
|
||||
|
||||
## Code Style
|
||||
|
||||
Code style is automatically checked as part of the project's CI pipeline on GitHub. This means that any pull requests which do not conform to the style guidelines will fail CI checks.
|
||||
|
||||
@@ -18,13 +18,12 @@ You need to make sure that you have the following tools installed before continu
|
||||
|
||||
#### Docker Containers
|
||||
|
||||
The InvenTree devcontainer setup will install the following docker containers:
|
||||
The InvenTree devcontainer setup will install two docker containers:
|
||||
|
||||
| Container | Description |
|
||||
| --- | --- |
|
||||
| inventree | InvenTree host server |
|
||||
| db | InvenTree database (postgresql) |
|
||||
| redis | Redis server for caching |
|
||||
| inventree | InvenTree server |
|
||||
|
||||
#### Setup/Installation
|
||||
|
||||
@@ -52,7 +51,7 @@ Tasks can help you executing scripts. You can run them by open the command panel
|
||||
|
||||
#### Setup demo dataset
|
||||
|
||||
If you need some demo test-data, run the `setup-test` task. This will import an `admin` user with the password `inventree`. For more info on what this dataset contains see [inventree/demo-dataset](../demo.md).
|
||||
If you need some demo test-data, run the `setup-test` task. This will import an `admin` user with the password `inventree`. For more info on what this dataset contains see [inventree/demo-dataset](https://github.com/inventree/demo-dataset).
|
||||
|
||||
#### Setup a superuser
|
||||
|
||||
@@ -67,7 +66,7 @@ If you need to process your queue with background workers, run the `worker` task
|
||||
You can either only run InvenTree or use the integrated debugger for debugging. Goto the `Run and debug` side panel make sure `InvenTree Server` is selected. Click on the play button on the left.
|
||||
|
||||
!!! tip "Debug with 3rd party"
|
||||
Sometimes you need to debug also some 3rd party packages. Just select `InvenTree Server - 3rd party`
|
||||
Sometimes you need to debug also some 3rd party packages. Just select `InvenTree Servre - 3rd party`
|
||||
|
||||
You can now set breakpoints and vscode will automatically pause execution if that point is hit. You can see all variables available in that context and evaluate some code with the debugger console at the bottom. Use the play or step buttons to continue execution.
|
||||
|
||||
@@ -120,9 +119,3 @@ If you are running a devcontainer in Windows, you may experience some performanc
|
||||
For a significant improvement in performance, the source code should be installed into the **WSL 2** filesystem (not on your "Windows" filesystem). This will greatly improve file access performance, and also make the devcontainer much more responsive to file system changes.
|
||||
|
||||
You can also refer to the [Improve disk performance guide](https://code.visualstudio.com/remote/advancedcontainers/improve-performance) for more information.
|
||||
|
||||
### Redis Caching
|
||||
|
||||
The devcontainer setup provides a [redis](https://redis.io/) container which can be used for managing global cache. By default this is disabled, but it can be easily enabled for testing or developing with the [redis cache](../start/config.md#caching) enabled.
|
||||
|
||||
To enable the cache, locate the InvenTree configuration file (`./dev/config.yaml`) and set the `cache.enabled` setting to `True`.
|
||||
|
||||
@@ -1,48 +1,37 @@
|
||||
---
|
||||
title: React Frontend Development
|
||||
title: Platform UI / React
|
||||
---
|
||||
|
||||
## Setup
|
||||
|
||||
The following documentation details how to setup and run a development installation of the InvenTree frontend user interface.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
To run the frontend development server, you will need to have the following installed:
|
||||
|
||||
- Node.js
|
||||
- Yarn
|
||||
|
||||
!!! note "Devcontainer"
|
||||
The [devcontainer](./devcontainer.md) setup already includes all prerequisite packages, and is ready to run the frontend server.
|
||||
The new React-based UI will not be available by default. In order to set your development environment up to view the frontend, follow this guide.
|
||||
The new UI requires a separate frontend server to run to serve data for the new Frontend.
|
||||
|
||||
### Install
|
||||
|
||||
The React frontend requires its own packages that aren't installed via the usual [invoke](../start/invoke.md) tasks.
|
||||
The React frontend requires its own packages that aren't installed via the usual invoke tasks.
|
||||
|
||||
#### Docker
|
||||
|
||||
Run the following command:
|
||||
`docker compose run inventree-dev-server invoke int.frontend-compile`
|
||||
`docker compose run inventree-dev-server invoke frontend-compile`
|
||||
This will install the required packages for running the React frontend on your InvenTree dev server.
|
||||
|
||||
#### Devcontainer
|
||||
|
||||
!!! warning "This guide assumes you already have a running devcontainer"
|
||||
|
||||
!!! info "All these steps are performed within Visual Studio Code"
|
||||
|
||||
Open a new terminal from the top menu by clicking `Terminal > New Terminal`
|
||||
Make sure this terminal is running within the virtual env. The start of the last line should display `(venv)`
|
||||
|
||||
Run the command `invoke int.frontend-compile`. Wait for this to finish
|
||||
Run the command `invoke frontend-compile`. Wait for this to finish
|
||||
|
||||
### Running
|
||||
|
||||
After finishing the install, you need to launch a frontend server to be able to view the new UI.
|
||||
|
||||
Using the previously described ways of running commands, execute the following:
|
||||
`invoke dev.frontend-server` in your environment
|
||||
`invoke frontend-dev` in your environment
|
||||
This command does not run as a background daemon, and will occupy the window it's ran in.
|
||||
|
||||
### Accessing
|
||||
@@ -51,7 +40,7 @@ When the frontend server is running, it will be available on port 5173.
|
||||
i.e: https://localhost:5173/
|
||||
|
||||
!!! note "Backend Server"
|
||||
The InvenTree backend server must also be running, for the frontend interface to have something to connect to! To launch a backend server, use the `invoke dev.server` command.
|
||||
The InvenTree backend server must also be running, for the frontend interface to have something to connect to! To launch a backend server, use the `invoke server` command.
|
||||
|
||||
### Debugging
|
||||
|
||||
@@ -88,49 +77,3 @@ When running the frontend development server, some features may not work entirel
|
||||
#### SSO Login
|
||||
|
||||
When logging into the frontend dev server via SSO, the redirect URL may not redirect correctly.
|
||||
|
||||
## Testing
|
||||
|
||||
The frontend codebase it tested using [Playwright](https://playwright.dev/). There are a large number of tests that cover the frontend codebase, which are run automatically as part of the CI pipeline.
|
||||
|
||||
### Install Playwright
|
||||
|
||||
To install the required packages to run the tests, you can use the following command:
|
||||
|
||||
```bash
|
||||
cd src/frontend
|
||||
npx playwright install
|
||||
```
|
||||
|
||||
### Running Tests
|
||||
|
||||
To run the tests locally, in an interactive editor, you can use the following command:
|
||||
|
||||
```bash
|
||||
cd src/frontend
|
||||
npx playwright test --ui
|
||||
```
|
||||
|
||||
This will first launch the backend server (at `http://localhost:8000`), and then run the tests against the frontend server (at `http://localhost:5173`). An interactive browser window will open, and you can run the tests individually or as a group.
|
||||
|
||||
### Viewing Reports
|
||||
|
||||
The playwright tests are run automatically as part of the project's CI pipeline, and the results are stored as a downloadable report. The report file can be "replayed" using playwright, to view the results of the test run, as well as closely inspect any failed tests.
|
||||
|
||||
To view the report, you can use the following command, after downloading the report and extracting from the zipped file:
|
||||
|
||||
```bash
|
||||
npx playwright show-report path/to/report
|
||||
```
|
||||
|
||||
### No Tests Found
|
||||
|
||||
If there is any problem in the testing launch sequence, the playwright UI will display the message "No Tests". In this case, an error has occurred, likely launching the InvenTree server process (which runs in the background).
|
||||
|
||||
To debug this situation, and determine what error needs to be resolved, run the following command:
|
||||
|
||||
```bash
|
||||
npx playwright test --debug
|
||||
```
|
||||
|
||||
This will print out any errors to the console, allowing you to resolve issues before continuing. In all likelihood, your InvenTree installation needs to be updated, and simply running `invoke update` will allow you to continue.
|
||||
|
||||
@@ -149,7 +149,7 @@ class SampleActionPlugin(ActionMixin, InvenTreePlugin):
|
||||
# metadata
|
||||
AUTHOR = "Sample Author"
|
||||
DESCRIPTION = "A very basic plugin with one mixin"
|
||||
PUBLISH_DATE = "2222-02-22"
|
||||
PUBLISH_DATE = "22.02.2222"
|
||||
VERSION = "1.2.3" # We recommend semver and increase the major version with each new major release of InvenTree
|
||||
WEBSITE = "https://example.com/"
|
||||
LICENSE = "MIT" # use what you want - OSI approved is ♥
|
||||
|
||||
@@ -6,9 +6,6 @@ title: Machines
|
||||
|
||||
InvenTree has a builtin machine registry. There are different machine types available where each type can have different drivers. Drivers and even custom machine types can be provided by plugins.
|
||||
|
||||
!!! info "Requires Redis"
|
||||
If the machines features is used in production setup using workers, a shared [redis cache](../../start/processes.md#cache-server) is required to function properly.
|
||||
|
||||
### Registry
|
||||
|
||||
The machine registry is the main component which gets initialized on server start and manages all configured machines.
|
||||
@@ -24,13 +21,6 @@ The machine registry initialization process can be divided into three stages:
|
||||
2. The driver.init_driver function is called for each used driver
|
||||
3. The machine.initialize function is called for each machine, which calls the driver.init_machine function for each machine, then the machine.initialized state is set to true
|
||||
|
||||
#### Production setup (with a worker)
|
||||
|
||||
If a worker is connected, there exist multiple instances of the machine registry (one in each worker thread and one in the main thread) due to the nature of how python handles state in different processes. Therefore the machine instances and drivers are instantiated multiple times (The `__init__` method is called multiple times). But the init functions and update hooks (e.g. `init_machine`) are only called once from the main process.
|
||||
|
||||
The registry, driver and machine state (e.g. machine status codes, errors, ...) is stored in the cache. Therefore a shared redis cache is needed. (The local in-memory cache which is used by default is not capable to cache across multiple processes)
|
||||
|
||||
|
||||
### Machine types
|
||||
|
||||
Each machine type can provide a different type of connection functionality between inventree and a physical machine. These machine types are already built into InvenTree.
|
||||
@@ -47,8 +37,6 @@ If you want to create your own machine type, please also take a look at the alre
|
||||
|
||||
```py
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from generic.states import ColorEnum
|
||||
from plugin.machine import BaseDriver, BaseMachineType, MachineStatus
|
||||
|
||||
class ABCBaseDriver(BaseDriver):
|
||||
@@ -74,9 +62,9 @@ class ABCMachine(BaseMachineType):
|
||||
base_driver = ABCBaseDriver
|
||||
|
||||
class ABCStatus(MachineStatus):
|
||||
CONNECTED = 100, _('Connected'), ColorEnum.success
|
||||
STANDBY = 101, _('Standby'), ColorEnum.success
|
||||
PRINTING = 110, _('Printing'), ColorEnum.primary
|
||||
CONNECTED = 100, _('Connected'), 'success'
|
||||
STANDBY = 101, _('Standby'), 'success'
|
||||
PRINTING = 110, _('Printing'), 'primary'
|
||||
|
||||
MACHINE_STATUS = ABCStatus
|
||||
default_machine_status = ABCStatus.DISCONNECTED
|
||||
@@ -98,7 +86,6 @@ The machine type class gets instantiated for each machine on server startup and
|
||||
- update
|
||||
- restart
|
||||
- handle_error
|
||||
- clear_errors
|
||||
- get_setting
|
||||
- set_setting
|
||||
- check_setting
|
||||
|
||||
@@ -9,14 +9,14 @@ The InvenTree server code supports an extensible plugin architecture, allowing c
|
||||
Plugins can be added from multiple sources:
|
||||
|
||||
- Plugins can be installed in InvenTrees venv via PIP (python package manager)
|
||||
- Custom plugins should be placed in the directory `./data/plugins`.
|
||||
- Custom plugins should be placed in the directory `./src/backend/InvenTree/plugins`.
|
||||
- InvenTree built-in plugins are located in the directory `./src/backend/InvenTree/plugin/builtin`.
|
||||
|
||||
For further information, read more about [installing plugins](./plugins/install.md).
|
||||
|
||||
### Plugin Base Class
|
||||
|
||||
Custom plugins must inherit from the [InvenTreePlugin class]({{ sourcefile("src/backend/InvenTree/plugin/plugin.py") }}). Any plugins installed via the methods outlined above will be "discovered" when the InvenTree server launches.
|
||||
Custom plugins must inherit from the [InvenTreePlugin class](https://github.com/inventree/InvenTree/blob/2d1776a151721d65d0ae007049d358085b2fcfd5/InvenTree/plugin/plugin.py#L204). Any plugins installed via the methods outlined above will be "discovered" when the InvenTree server launches.
|
||||
|
||||
!!! warning "Namechange"
|
||||
The name of the base class was changed with `0.7.0` from `IntegrationPluginBase` to `InvenTreePlugin`. While the old name is still available till `0.8.0` we strongly suggest upgrading your plugins. Deprecation warnings are raised if the old name is used.
|
||||
@@ -28,7 +28,7 @@ Please read all release notes and watch out for warnings - we generally provide
|
||||
|
||||
#### Plugins
|
||||
|
||||
General classes and mechanisms are provided under the `plugin` [namespaces]({{ sourcefile("src/backend/InvenTree/plugin/__init__.py") }}). These include:
|
||||
General classes and mechanisms are provided under the `plugin` [namespaces](https://github.com/inventree/InvenTree/blob/0.15.x/src/backend/InvenTree/plugin/__init__.py). These include:
|
||||
|
||||
```python
|
||||
# Management objects
|
||||
@@ -44,7 +44,7 @@ MixinNotImplementedError # Is raised if a mixin was not implemented (core mec
|
||||
|
||||
#### Mixins
|
||||
|
||||
Mixins are split up internally to keep the source tree clean and enable better testing separation. All public APIs that should be used are exposed under `plugin.mixins`. These include all built-in mixins and notification methods. An up-to-date reference can be found in the source code [can be found here]({{ sourcefile("src/backend/InvenTree/plugin/mixins/__init__.py") }}).
|
||||
Mixins are split up internally to keep the source tree clean and enable better testing separation. All public APIs that should be used are exposed under `plugin.mixins`. These include all built-in mixins and notification methods. An up-to-date reference can be found in the source code (current master can be [found here](https://github.com/inventree/InvenTree/blob/0.15.x/src/backend/InvenTree/plugin/mixins/__init__.py)).
|
||||
|
||||
#### Models and other internal InvenTree APIs
|
||||
|
||||
@@ -72,7 +72,7 @@ MIN_VERSION = None # Lowest InvenTree version number that is supported by the p
|
||||
MAX_VERSION = None # Highest InvenTree version number that is supported by the plugin
|
||||
```
|
||||
|
||||
Refer to the [sample plugins]({{ sourcedir("src/backend/InvenTree/plugin/samples") }}) for further examples.
|
||||
Refer to the [sample plugins](https://github.com/inventree/InvenTree/tree/master/src/backend/InvenTree/plugin/samples) for further examples.
|
||||
|
||||
### Plugin Config
|
||||
|
||||
@@ -83,7 +83,7 @@ The configuration entries must be enabled via the [InvenTree admin interface](..
|
||||
!!! warning "Disabled by Default"
|
||||
Newly discovered plugins are disabled by default, and must be manually enabled (in the admin interface) by a user with staff privileges.
|
||||
|
||||
## Plugin Mixins
|
||||
### Plugin Mixins
|
||||
|
||||
Common use cases are covered by pre-supplied modules in the form of *mixins* (similar to how [Django]({% include "django.html" %}/topics/class-based-views/mixins/) does it). Each mixin enables the integration into a specific area of InvenTree. Sometimes it also enhances the plugin with helper functions to supply often used functions out-of-the-box.
|
||||
|
||||
@@ -106,11 +106,3 @@ Supported mixin classes are:
|
||||
| [SettingsMixin](./plugins/settings.md) | Integrate user configurable settings |
|
||||
| [UrlsMixin](./plugins/urls.md) | Respond to custom URL endpoints |
|
||||
| [ValidationMixin](./plugins/validation.md) | Provide custom validation of database models |
|
||||
|
||||
## Static Files
|
||||
|
||||
If your plugin requires static files (e.g. CSS, JavaScript, images), these should be placed in the top level `static` directory within the distributed plugin package. These files will be automatically collected by InvenTree when the plugin is installed, and copied to an appropriate location.
|
||||
|
||||
These files will be available to the InvenTree web interface, and can be accessed via the URL `/static/plugins/<plugin_name>/<filename>`. Static files are served by the [proxy server](../start/processes.md#proxy-server).
|
||||
|
||||
For example, if the plugin is named `my_plugin`, and contains a file `CustomPanel.js`, it can be accessed via the URL `/static/plugins/my_plugin/CustomPanel.js`.
|
||||
|
||||
@@ -15,14 +15,4 @@ POST {
|
||||
}
|
||||
```
|
||||
|
||||
### Sample Plugin
|
||||
|
||||
A sample action plugin is provided in the `InvenTree` source code, which can be used as a template for creating custom action plugins:
|
||||
|
||||
::: plugin.samples.integration.simpleactionplugin.SimpleActionPlugin
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
For an example of a very simple action plugin, refer to `/src/backend/InvenTree/plugin/samples/integratoni/simpleactionplugin.py`
|
||||
|
||||
@@ -5,15 +5,3 @@ title: Schedule Mixin
|
||||
## APICallMixin
|
||||
|
||||
The APICallMixin class provides basic functionality for integration with an external API.
|
||||
|
||||
### Sample Plugin
|
||||
|
||||
The following example demonstrates how to use the `APICallMixin` class to make a simple API call:
|
||||
|
||||
::: plugin.samples.integration.api_caller.SampleApiCallerPlugin
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
title: Barcode Mixin
|
||||
---
|
||||
|
||||
## Barcode Plugins
|
||||
### Barcode Plugins
|
||||
|
||||
InvenTree supports decoding of arbitrary barcode data and generation of internal barcode formats via a **Barcode Plugin** interface. Barcode data POSTed to the `/api/barcode/` endpoint will be supplied to all loaded barcode plugins, and the first plugin to successfully interpret the barcode data will return a response to the client.
|
||||
InvenTree supports decoding of arbitrary barcode data via a **Barcode Plugin** interface. Barcode data POSTed to the `/api/barcode/` endpoint will be supplied to all loaded barcode plugins, and the first plugin to successfully interpret the barcode data will return a response to the client.
|
||||
|
||||
InvenTree can generate native QR codes to represent database objects (e.g. a single StockItem). This barcode can then be used to perform quick lookup of a stock item or location in the database. A client application (for example the InvenTree mobile app) scans a barcode, and sends the barcode data to the InvenTree server. The server then uses the **InvenTreeBarcodePlugin** (found at `src/backend/InvenTree/plugin/builtin/barcodes/inventree_barcode.py`) to decode the supplied barcode data.
|
||||
InvenTree can generate native QR codes to represent database objects (e.g. a single StockItem). This barcode can then be used to perform quick lookup of a stock item or location in the database. A client application (for example the InvenTree mobile app) scans a barcode, and sends the barcode data to the InvenTree server. The server then uses the **InvenTreeBarcodePlugin** (found at `/src/backend/InvenTree/plugins/barcode/inventree.py`) to decode the supplied barcode data.
|
||||
|
||||
Any third-party barcodes can be decoded by writing a matching plugin to decode the barcode data. These plugins could then perform a server-side action or render a JSON response back to the client for further action.
|
||||
|
||||
@@ -24,27 +24,15 @@ POST {
|
||||
}
|
||||
```
|
||||
|
||||
### Builtin Plugin
|
||||
|
||||
The InvenTree server includes a builtin barcode plugin which can generate and decode the QR codes. This plugin is enabled by default.
|
||||
|
||||
::: plugin.builtin.barcodes.inventree_barcode.InvenTreeInternalBarcodePlugin
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
|
||||
|
||||
### Example Plugin
|
||||
|
||||
Please find below a very simple example that is used to return a part if the barcode starts with `PART-`
|
||||
### Example
|
||||
Please find below a very simple example that is executed each time a barcode is scanned.
|
||||
|
||||
```python
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from InvenTree.models import InvenTreeBarcodeMixin
|
||||
from plugin import InvenTreePlugin
|
||||
from plugin.mixins import BarcodeMixin
|
||||
from part.models import Part
|
||||
|
||||
class InvenTreeBarcodePlugin(BarcodeMixin, InvenTreePlugin):
|
||||
|
||||
@@ -54,39 +42,16 @@ class InvenTreeBarcodePlugin(BarcodeMixin, InvenTreePlugin):
|
||||
VERSION = "0.0.1"
|
||||
AUTHOR = "Michael"
|
||||
|
||||
def scan(self, barcode_data):
|
||||
if barcode_data.startswith("PART-"):
|
||||
try:
|
||||
pk = int(barcode_data.split("PART-")[1])
|
||||
instance = Part.objects.get(pk=pk)
|
||||
label = Part.barcode_model_type()
|
||||
status = 0
|
||||
|
||||
def scan(self, barcode_data):
|
||||
|
||||
self.status = self.status+1
|
||||
print('Started barcode plugin', self.status)
|
||||
print(barcode_data)
|
||||
response = {}
|
||||
return response
|
||||
|
||||
return {label: instance.format_matched_response()}
|
||||
except Part.DoesNotExist:
|
||||
pass
|
||||
```
|
||||
|
||||
To try it just copy the file to src/InvenTree/plugins and restart the server. Open the scan barcode window and start to scan codes or type in text manually. Each time the timeout is hit the plugin will execute and printout the result. The timeout can be changed in `Settings->Barcode Support->Barcode Input Delay`.
|
||||
|
||||
### Custom Internal Format
|
||||
|
||||
To implement a custom internal barcode format, the `generate(...)` method from the Barcode Mixin needs to be overridden. Then the plugin can be selected at `System Settings > Barcodes > Barcode Generation Plugin`.
|
||||
|
||||
```python
|
||||
from InvenTree.models import InvenTreeBarcodeMixin
|
||||
from plugin import InvenTreePlugin
|
||||
from plugin.mixins import BarcodeMixin
|
||||
|
||||
class InvenTreeBarcodePlugin(BarcodeMixin, InvenTreePlugin):
|
||||
NAME = "MyInternalBarcode"
|
||||
TITLE = "My Internal Barcodes"
|
||||
DESCRIPTION = "support for custom internal barcodes"
|
||||
VERSION = "0.0.1"
|
||||
AUTHOR = "InvenTree contributors"
|
||||
|
||||
def generate(self, model_instance: InvenTreeBarcodeMixin):
|
||||
return f'{model_instance.barcode_model_type()}: {model_instance.pk}'
|
||||
```
|
||||
|
||||
!!! info "Scanning implementation required"
|
||||
The parsing of the custom format needs to be implemented too, so that the scanning of the generated QR codes resolves to the correct part.
|
||||
|
||||
@@ -6,24 +6,7 @@ title: Currency Exchange Mixin
|
||||
|
||||
The `CurrencyExchangeMixin` class enabled plugins to provide custom backends for updating currency exchange rate information.
|
||||
|
||||
Any implementing classes must provide the `update_exchange_rates` method.
|
||||
|
||||
### Builtin Plugin
|
||||
|
||||
The default builtin plugin for handling currency exchange rates is the `InvenTreeCurrencyExchangePlugin` class.
|
||||
|
||||
::: plugin.builtin.integration.currency_exchange.InvenTreeCurrencyExchange
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
|
||||
|
||||
### Sample Plugin
|
||||
|
||||
A simple example is shown below (with fake data).
|
||||
Any implementing classes must provide the `update_exchange_rates` method. A simple example is shown below (with fake data).
|
||||
|
||||
```python
|
||||
|
||||
|
||||
@@ -15,173 +15,59 @@ When a certain (server-side) event occurs, the background worker passes the even
|
||||
{% include 'img.html' %}
|
||||
{% endwith %}
|
||||
|
||||
## Events
|
||||
|
||||
Events are passed through using a string identifier, e.g. `build.completed`
|
||||
|
||||
The arguments (and keyword arguments) passed to the receiving function depend entirely on the type of event.
|
||||
|
||||
!!! info "Read the Code"
|
||||
Implementing a response to a particular event requires a working knowledge of the InvenTree code base, especially related to that event being received. While the *available* events are documented here, to implement a response to a particular event you will need to read the code to understand what data is passed to the event handler.
|
||||
|
||||
## Generic Events
|
||||
|
||||
There are a number of *generic* events which are generated on certain database actions. Whenever a database object is created, updated, or deleted, a corresponding event is generated.
|
||||
|
||||
#### Object Created
|
||||
|
||||
When a new object is created in the database, an event is generated with the following event name: `<app>_<model>.created`, where `<model>` is the name of the model class (e.g. `part`, `stockitem`, etc).
|
||||
|
||||
The event is called with the following keywords arguments:
|
||||
|
||||
- `model`: The model class of the object that was created
|
||||
- `id`: The primary key of the object that was created
|
||||
|
||||
**Example:**
|
||||
|
||||
A new `Part` object is created with primary key `123`, resulting in the following event being generated:
|
||||
|
||||
```python
|
||||
trigger_event('part_part.created', model='part', id=123)
|
||||
```
|
||||
|
||||
### Object Updated
|
||||
|
||||
When an object is updated in the database, an event is generated with the following event name: `<app>_<model>.saved`, where `<model>` is the name of the model class (e.g. `part`, `stockitem`, etc).
|
||||
|
||||
The event is called with the following keywords arguments:
|
||||
|
||||
- `model`: The model class of the object that was updated
|
||||
- `id`: The primary key of the object that was updated
|
||||
|
||||
**Example:**
|
||||
|
||||
A `Part` object with primary key `123` is updated, resulting in the following event being generated:
|
||||
|
||||
```python
|
||||
trigger_event('part_part.saved', model='part', id=123)
|
||||
```
|
||||
|
||||
### Object Deleted
|
||||
|
||||
When an object is deleted from the database, an event is generated with the following event name: `<app>_<model>.deleted`, where `<model>` is the name of the model class (e.g. `part`, `stockitem`, etc).
|
||||
|
||||
The event is called with the following keywords arguments:
|
||||
|
||||
- `model`: The model class of the object that was deleted
|
||||
- `id`: The primary key of the object that was deleted (if available)
|
||||
|
||||
**Example:**
|
||||
|
||||
A `Part` object with primary key `123` is deleted, resulting in the following event being generated:
|
||||
|
||||
```python
|
||||
trigger_event('part_part.deleted', model='part', id=123)
|
||||
```
|
||||
|
||||
!!! warning "Object Deleted"
|
||||
Note that the event is triggered *after* the object has been deleted from the database, so the object itself is no longer available.
|
||||
|
||||
## Specific Events
|
||||
|
||||
In addition to the *generic* events listed above, there are a number of other events which are triggered by *specific* actions within the InvenTree codebase.
|
||||
|
||||
The available events are provided in the enumerations listed below. Note that while the names of the events are documented here, the exact arguments passed to the event handler will depend on the specific event being triggered.
|
||||
|
||||
### Build Events
|
||||
|
||||
::: build.events.BuildEvents
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
|
||||
### Part Events
|
||||
|
||||
::: part.events.PartEvents
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
|
||||
### Stock Events
|
||||
|
||||
::: stock.events.StockEvents
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
|
||||
### Purchase Order Events
|
||||
|
||||
::: order.events.PurchaseOrderEvents
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
|
||||
### Sales Order Events
|
||||
|
||||
::: order.events.SalesOrderEvents
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
|
||||
### Return Order Events
|
||||
|
||||
::: order.events.ReturnOrderEvents
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
|
||||
### Plugin Events
|
||||
|
||||
::: plugin.events.PluginEvents
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
|
||||
## Samples
|
||||
|
||||
### Sample Plugin - All events
|
||||
### Example (all events)
|
||||
|
||||
Implementing classes must at least provide a `process_event` function:
|
||||
|
||||
::: plugin.samples.event.event_sample.EventPluginSample
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
```python
|
||||
class EventPlugin(EventMixin, InvenTreePlugin):
|
||||
"""
|
||||
A simple example plugin which responds to events on the InvenTree server.
|
||||
|
||||
### Sample Plugin - Specific Events
|
||||
This example simply prints out the event information.
|
||||
A more complex plugin could respond to specific events however it wanted.
|
||||
"""
|
||||
|
||||
NAME = "EventPlugin"
|
||||
SLUG = "event"
|
||||
TITLE = "Triggered Events"
|
||||
|
||||
def process_event(self, event, *args, **kwargs):
|
||||
print(f"Processing triggered event: '{event}'")
|
||||
```
|
||||
|
||||
### Example (specific events)
|
||||
|
||||
If you want to process just some specific events, you can also implement the `wants_process_event` function to decide if you want to process this event or not. This function will be executed synchronously, so be aware that it should contain simple logic.
|
||||
|
||||
Overall this function can reduce the workload on the background workers significantly since less events are queued to be processed.
|
||||
|
||||
::: plugin.samples.event.filtered_event_sample.FilteredEventPluginSample
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
```python
|
||||
class EventPlugin(EventMixin, InvenTreePlugin):
|
||||
"""
|
||||
A simple example plugin which responds to 'salesordershipment.completed' event on the InvenTree server.
|
||||
|
||||
This example simply prints out the event information.
|
||||
A more complex plugin can run enhanced logic on this event.
|
||||
"""
|
||||
|
||||
NAME = "EventPlugin"
|
||||
SLUG = "event"
|
||||
TITLE = "Triggered Events"
|
||||
|
||||
def wants_process_event(self, event):
|
||||
"""Here you can decide if this event should be send to `process_event` or not."""
|
||||
return event == "salesordershipment.completed"
|
||||
|
||||
def process_event(self, event, *args, **kwargs):
|
||||
"""Here you can run you'r specific logic."""
|
||||
print(f"Sales order was completely shipped: '{args}' '{kwargs}'")
|
||||
```
|
||||
|
||||
### Events
|
||||
|
||||
Events are passed through using a string identifier, e.g. `build.completed`
|
||||
|
||||
The arguments (and keyword arguments) passed to the receiving function depend entirely on the type of event.
|
||||
|
||||
Implementing a response to a particular event requires a working knowledge of the InvenTree code base, especially related to that event being received.
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
title: Icon Pack Mixin
|
||||
---
|
||||
|
||||
## IconPackMixin
|
||||
|
||||
The IconPackMixin class provides basic functionality for letting plugins expose custom icon packs that are available in the InvenTree UI. This is especially useful to provide a custom crafted icon pack with icons for different location types, e.g. different sizes and styles of drawers, bags, ESD bags, ... which are not available in the standard tabler icons library.
|
||||
|
||||
### Sample Plugin
|
||||
|
||||
The following example demonstrates how to use the `IconPackMixin` class to add a custom icon pack:
|
||||
|
||||
::: plugin.samples.icons.icon_sample.SampleIconPlugin
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
@@ -74,10 +74,10 @@ Admin users can install plugins directly from the web interface, via the "Plugin
|
||||
|
||||
#### Local Directory
|
||||
|
||||
Custom plugins can be placed in the `data/plugins/` directory, where they will be automatically discovered. This can be useful for developing and testing plugins, but can prove more difficult in production (e.g. when using Docker).
|
||||
Custom plugins can be placed in the `src/InvenTree/plugins/` directory, where they will be automatically discovered. This can be useful for developing and testing plugins, but can prove more difficult in production (e.g. when using Docker).
|
||||
|
||||
!!! info "Git Tracking"
|
||||
The `data/plugins/` directory is excluded from Git version tracking - any plugin files here will be hidden from Git
|
||||
The `src/backend/InvenTree/plugins/` directory is excluded from Git version tracking - any plugin files here will be hidden from Git
|
||||
|
||||
!!! warning "Not Recommended For Production"
|
||||
Loading plugins via the local *plugins* directory is not recommended for production. If you cannot use PIP installation (above), specify a custom plugin directory (below) or use a [VCS](https://pip.pypa.io/en/stable/topics/vcs-support/) as a plugin install source.
|
||||
|
||||
@@ -172,14 +172,6 @@ InvenTree supplies the `InvenTreeLabelPlugin` out of the box, which generates a
|
||||
|
||||
The default plugin also features a *DEBUG* mode which generates a raw HTML output, rather than PDF. This can be handy for tracking down any template rendering errors in your labels.
|
||||
|
||||
::: plugin.builtin.labels.inventree_label.InvenTreeLabelPlugin
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
|
||||
### Available Data
|
||||
|
||||
The *label* data are supplied to the plugin in both `PDF` and `PNG` formats. This provides compatibility with a great range of label printers "out of the box". Conversion to other formats, if required, is left as an exercise for the plugin developer.
|
||||
|
||||
@@ -28,16 +28,4 @@ If a locate plugin is installed and activated, the [InvenTree mobile app](../../
|
||||
|
||||
### Implementation
|
||||
|
||||
Refer to the [InvenTree source code]({{ sourcefile("src/backend/InvenTree/plugin/samples/locate/locate_sample.py") }}) for a simple implementation example.
|
||||
|
||||
### Sample Plugin
|
||||
|
||||
A simple example is provided in the InvenTree code base:
|
||||
|
||||
::: plugin.samples.locate.locate_sample.SampleLocatePlugin
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
Refer to the [InvenTree source code](https://github.com/inventree/InvenTree/blob/0.15.x/src/backend/InvenTree/plugin/samples/locate/locate_sample.py) for a simple implementation example.
|
||||
|
||||
@@ -4,12 +4,6 @@ title: Panel Mixin
|
||||
|
||||
## PanelMixin
|
||||
|
||||
!!! warning "Legacy User Interface"
|
||||
This plugin mixin class is designed specifically for the the *legacy* user interface (which is rendered on the server using django templates). The new user interface (which is rendered on the client using React) does not support this mixin class. Instead, refer to the new [User Interface Mixin](./ui.md) class.
|
||||
|
||||
!!! warning "Deprecated Class"
|
||||
This mixin class is considered deprecated, and will be removed in the 1.0.0 release.
|
||||
|
||||
The `PanelMixin` enables plugins to render custom content to "panels" on individual pages in the web interface.
|
||||
|
||||
Most pages in the web interface support multiple panels, which are selected via the sidebar menu on the left side of the screen:
|
||||
@@ -58,18 +52,6 @@ Or to add a template file that will be rendered as javascript code, from the plu
|
||||
|
||||
Note : see convention for template directory above.
|
||||
|
||||
## Sample Plugin
|
||||
|
||||
A sample plugin is provided in the InvenTree code base:
|
||||
|
||||
::: plugin.samples.integration.custom_panel_sample.CustomPanelSample
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
|
||||
## Example Implementations
|
||||
|
||||
Refer to the `CustomPanelSample` example class in the `./plugin/samples/integration/` directory, for a fully worked example of how custom UI panels can be implemented.
|
||||
|
||||
@@ -14,14 +14,48 @@ A plugin which implements the ReportMixin mixin can define the `add_report_conte
|
||||
|
||||
Additionally the `add_label_context` method, allowing custom context data to be added to a label template at time of printing.
|
||||
|
||||
### Sample Plugin
|
||||
### Example
|
||||
|
||||
A sample plugin which provides additional context data to the report templates is available:
|
||||
A sample plugin which provides additional context data to the report templates can be found [in the InvenTree source code](https://github.com/inventree/InvenTree/blob/0.15.x/src/backend/InvenTree/plugin/samples/integration/report_plugin_sample.py):
|
||||
|
||||
::: plugin.samples.integration.report_plugin_sample.SampleReportPlugin
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
```python
|
||||
"""Sample plugin for extending reporting functionality"""
|
||||
|
||||
import random
|
||||
|
||||
from plugin import InvenTreePlugin
|
||||
from plugin.mixins import ReportMixin
|
||||
from report.models import PurchaseOrderReport
|
||||
|
||||
|
||||
class SampleReportPlugin(ReportMixin, InvenTreePlugin):
|
||||
"""Sample plugin which provides extra context data to a report"""
|
||||
|
||||
NAME = "Sample Report Plugin"
|
||||
SLUG = "reportexample"
|
||||
TITLE = "Sample Report Plugin"
|
||||
DESCRIPTION = "A sample plugin which provides extra context data to a report"
|
||||
VERSION = "1.0"
|
||||
|
||||
def some_custom_function(self):
|
||||
"""Some custom function which is not required for the plugin to function"""
|
||||
return random.randint(0, 100)
|
||||
|
||||
def add_report_context(self, report_instance, model_instance, request, context):
|
||||
|
||||
"""Add example content to the report instance"""
|
||||
|
||||
# We can add any extra context data we want to the report
|
||||
|
||||
# Generate a random string of data
|
||||
context['random_text'] = ''.join(random.choices('abcdefghijklmnopqrstuvwxyz', k=20))
|
||||
|
||||
# Call a custom method
|
||||
context['random_int'] = self.some_custom_function()
|
||||
|
||||
# We can also add extra data to the context which is specific to the report type
|
||||
context['is_purchase_order'] = isinstance(report_instance, PurchaseOrderReport)
|
||||
|
||||
# We can also use the 'request' object to add extra context data
|
||||
context['request_method'] = request.method
|
||||
```
|
||||
|
||||
@@ -18,14 +18,45 @@ The ScheduleMixin class provides a plugin with the ability to call functions at
|
||||
{% include 'img.html' %}
|
||||
{% endwith %}
|
||||
|
||||
### SamplePlugin
|
||||
### Example
|
||||
|
||||
An example of a plugin which supports scheduled tasks:
|
||||
|
||||
::: plugin.samples.integration.scheduled_task.ScheduledTaskPlugin
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
```python
|
||||
class ScheduledTaskPlugin(ScheduleMixin, SettingsMixin, InvenTreePlugin):
|
||||
"""
|
||||
Sample plugin which runs a scheduled task, and provides user configuration.
|
||||
"""
|
||||
|
||||
NAME = "Scheduled Tasks"
|
||||
SLUG = 'schedule'
|
||||
|
||||
SCHEDULED_TASKS = {
|
||||
'global': {
|
||||
'func': 'some_module.function',
|
||||
'schedule': 'H', # Run every hour
|
||||
},
|
||||
'member': {
|
||||
'func': 'foo',
|
||||
'schedule': 'I', # Minutes
|
||||
'minutes': 15,
|
||||
},
|
||||
}
|
||||
|
||||
SETTINGS = {
|
||||
'SECRET': {
|
||||
'name': 'A secret',
|
||||
'description': 'User configurable value',
|
||||
},
|
||||
}
|
||||
|
||||
def foo(self):
|
||||
"""
|
||||
This function runs every 15 minutes
|
||||
"""
|
||||
secret_value = self.get_setting('SECRET')
|
||||
print(f"foo - SECRET = {secret_value})
|
||||
```
|
||||
|
||||
!!! info "More Info"
|
||||
For more information on any of the methods described below, refer to the InvenTree source code. [A working example is available as a starting point](https://github.com/inventree/InvenTree/blob/0.15.x/src/backend/InvenTree/plugin/samples/integration/scheduled_task.py).
|
||||
|
||||
@@ -15,7 +15,7 @@ The dict must be formatted similar to the following sample that shows how to use
|
||||
|
||||
Take a look at the settings defined in `InvenTree.common.models.InvenTreeSetting` for all possible parameters.
|
||||
|
||||
### Example Plugin
|
||||
### Example
|
||||
|
||||
Below is a simple example of how a plugin can implement settings:
|
||||
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
---
|
||||
Title: Unit Tests
|
||||
---
|
||||
|
||||
## Unit Tests
|
||||
For complicated plugins it makes sense to add unit tests the code to ensure
|
||||
that plugins work correctly and are compatible with future versions too.
|
||||
You can run these tests as part of your ci against the current stable and
|
||||
latest tag to get notified when something breaks before it gets released as
|
||||
part of stable. InvenTree offers a framework for testing. Please refer
|
||||
to [Unit Tests](../../develop/contributing.md) for more information.
|
||||
|
||||
### Prerequisites
|
||||
For plugin testing the following environment variables must be set to True:
|
||||
|
||||
| Name | Function | Value |
|
||||
| --- | --- | --- |
|
||||
| INVENTREE_PLUGINS_ENABLED | Enables the use of 3rd party plugins | True |
|
||||
| INVENTREE_PLUGIN_TESTING | Enables enables all plugins no matter of their active state in the db or built-in flag | True |
|
||||
| INVENTREE_PLUGIN_TESTING_SETUP | Enables the url mixin | True |
|
||||
|
||||
### Test program
|
||||
|
||||
A file called test_plugin_name.py should be added to the plugin directory. It can have the
|
||||
following structure:
|
||||
|
||||
```
|
||||
# Basic unit tests for the plugin
|
||||
from InvenTree.unit_test import InvenTreeTestCase
|
||||
|
||||
class TestMyPlugin(InvenTreeTestCase):
|
||||
def test_my_function(self):
|
||||
do some work here...
|
||||
```
|
||||
|
||||
The test can be executed using invoke:
|
||||
|
||||
```
|
||||
invoke dev.test -r module.file.class
|
||||
```
|
||||
|
||||
Plugins are usually installed outside of the InventTree directory, e.g. in .local/lib/...
|
||||
I that case module must be omitted.
|
||||
|
||||
```
|
||||
invoke dev.test -r plugin_directory.test_plugin_name.TestMyPlugin
|
||||
```
|
||||
|
||||
### do some work here... A simple Example
|
||||
A simple example is shown here. Assume the plugin has a function that converts a price string
|
||||
that comes from a supplier API to a float value. The price might have the form "1.456,34 €".
|
||||
It can be different based on country and local settings.
|
||||
The function in the plugin will convert it to a float 1456.34. It is in the class MySupplier
|
||||
and has the following structure:
|
||||
|
||||
```
|
||||
class MySupplier():
|
||||
|
||||
def reformat_price(self, string_price):
|
||||
|
||||
...
|
||||
return float_price
|
||||
```
|
||||
|
||||
This function needs to be tested. The test can look like this:
|
||||
|
||||
```
|
||||
from .myplugin import MySupplier
|
||||
|
||||
def test_reformat_price(self):
|
||||
|
||||
self.assertEqual(MySupplier.reformat_price(self, '1.456,34 €'), 1456.34)
|
||||
self.assertEqual(MySupplier.reformat_price(self, '1,45645 €'), 1.45645)
|
||||
self.assertEqual(MySupplier.reformat_price(self, '1,56 $'), 1.56)
|
||||
self.assertEqual(MySupplier.reformat_price(self, ''), 0)
|
||||
self.assertEqual(MySupplier.reformat_price(self, 'Mumpitz'), 0)
|
||||
```
|
||||
|
||||
The function assertEqual flags an error in case the two arguments are not equal. In equal case
|
||||
no error is flagged and the test passes. The test function tests five different
|
||||
input variations. More might be added based on the requirements.
|
||||
|
||||
### Involve the database
|
||||
Now we test a function that uses InvenTree database objects. The function checks if a part
|
||||
should be updated with latest data from a supplier. Parts that are not purchasable or inactive
|
||||
should not be updated. The function in the plugin has the following form:
|
||||
|
||||
```
|
||||
class MySupplier():
|
||||
|
||||
def should_be_updated(self, my_part):
|
||||
|
||||
...
|
||||
return True/False
|
||||
```
|
||||
|
||||
To test this function, parts are needed in the database. The test framework creates
|
||||
a dummy database for each run which is empty. Parts for testing need to be added.
|
||||
This is done in the test function which looks like:
|
||||
|
||||
```
|
||||
from part.models import Part, PartCategory
|
||||
|
||||
|
||||
def test_should_be_updated(self):
|
||||
test_cat = PartCategory.objects.create(name='test_cat')
|
||||
active_part = Part.objects.create(
|
||||
name='Part1',
|
||||
IPN='IPN1',
|
||||
category=test_cat,
|
||||
active=True,
|
||||
purchaseable=True,
|
||||
component=True,
|
||||
virtual=False)
|
||||
inactive_part = Part.objects.create(
|
||||
name='Part2',
|
||||
IPN='IPN2',
|
||||
category=test_cat,
|
||||
active=False,
|
||||
purchaseable=True,
|
||||
component=True,
|
||||
virtual=False)
|
||||
non_purchasable_part = Part.objects.create(
|
||||
name='Part3',
|
||||
IPN='IPN3',
|
||||
category=test_cat,
|
||||
active=True,
|
||||
purchaseable=False,
|
||||
component=True,
|
||||
virtual=False)
|
||||
|
||||
self.assertEqual(MySupplier.should_be_updated(self, active_part, True, 'Active part')
|
||||
self.assertEqual(MySupplier.should_be_updated(self, inactive_part, False, 'Inactive part')
|
||||
self.assertEqual(MySupplier.should_be_updated(self, non_purchasable_part, False, 'Non purchasable part')
|
||||
```
|
||||
|
||||
A category and three parts are created. One part is active, one is inactive and one is not
|
||||
purchasable. The function should_be_updated is tested with all
|
||||
three parts. The first test should return True, the others False. A message was added to the assert
|
||||
function for better clarity of test results.
|
||||
|
||||
The dummy database is completely separate from the one that you might use for development
|
||||
and it is deleted after the test. There is no danger for your development database.
|
||||
|
||||
In case everything is OK, the result looks like:
|
||||
|
||||
```
|
||||
----------------------------------------------------------------------
|
||||
Ran 1 tests in 0.809s
|
||||
|
||||
OK
|
||||
Destroying test database for alias 'default'...
|
||||
```
|
||||
|
||||
In case of a problem you will see something like:
|
||||
|
||||
```
|
||||
======================================================================
|
||||
FAIL: test_should_be_updated (inventree_supplier_sync.test_supplier_sync.TestSyncPlugin)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "/home/michael/.local/lib/python3.10/site-packages/inventree_supplier_sync/test_supplier_sync.py", line 73, in test_should_be_updated
|
||||
self.assertEqual(SupplierSyncPlugin.should_be_updated(self, non_purchasable_part,), False, 'Non purchasable part')
|
||||
AssertionError: True != False : Non purchasable part
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 3 tests in 0.679s
|
||||
|
||||
FAILED (failures=1)
|
||||
Destroying test database for alias 'default'...
|
||||
|
||||
```
|
||||
|
||||
In the AssertionError the message appears that was added to the assertEqual function.
|
||||
@@ -1,219 +0,0 @@
|
||||
---
|
||||
title: User Interface Mixin
|
||||
---
|
||||
|
||||
## User Interface Mixin
|
||||
|
||||
The `UserInterfaceMixin` class provides a set of methods to implement custom functionality for the InvenTree web interface.
|
||||
|
||||
### Enable User Interface Mixin
|
||||
|
||||
To enable user interface plugins, the global setting `ENABLE_PLUGINS_INTERFACE` must be enabled, in the [plugin settings](../../settings/global.md#plugin-settings).
|
||||
|
||||
## Custom UI Features
|
||||
|
||||
The InvenTree user interface functionality can be extended in various ways using plugins. Multiple types of user interface *features* can be added to the InvenTree user interface.
|
||||
|
||||
The entrypoint for user interface plugins is the `UserInterfaceMixin` class, which provides a number of methods which can be overridden to provide custom functionality. The `get_ui_features` method is used to extract available user interface features from the plugin:
|
||||
|
||||
::: plugin.base.ui.mixins.UserInterfaceMixin.get_ui_features
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_sources: True
|
||||
summary: False
|
||||
members: []
|
||||
|
||||
Note here that the `get_ui_features` calls other methods to extract the available features from the plugin, based on the requested feature type. These methods can be overridden to provide custom functionality.
|
||||
|
||||
!!! info "Implementation"
|
||||
Your custom plugin does not need to override the `get_ui_features` method. Instead, override one of the other methods to provide custom functionality.
|
||||
|
||||
### UIFeature Return Type
|
||||
|
||||
The `get_ui_features` method should return a list of `UIFeature` objects, which define the available user interface features for the plugin. The `UIFeature` class is defined as follows:
|
||||
|
||||
::: plugin.base.ui.mixins.UIFeature
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_sources: True
|
||||
summary: False
|
||||
members: []
|
||||
|
||||
Note that the *options* field contains fields which may be specific to a particular feature type - read the documentation below on each feature type for more information.
|
||||
|
||||
### Dynamic Feature Loading
|
||||
|
||||
Each of the provided feature types can be loaded dynamically by the plugin, based on the information provided in the API request. For example, the plugin can choose to show or hide a particular feature based on the user permissions, or the current state of the system.
|
||||
|
||||
For examples of this dynamic feature loading, refer to the [sample plugin](#sample-plugin) implementation which demonstrates how to dynamically load custom panels based on the provided context.
|
||||
|
||||
### Javascript Source Files
|
||||
|
||||
The rendering function for the custom user interface features expect that the plugin provides a Javascript source file which contains the necessary code to render the custom content. The path to this file should be provided in the `source` field of the `UIFeature` object.
|
||||
|
||||
Note that the `source` field can include the name of the function to be called (if this differs from the expected default function name).
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
"source": "/static/plugins/my_plugin/my_plugin.js:my_custom_function"
|
||||
```
|
||||
|
||||
## Available UI Feature Types
|
||||
|
||||
The following user interface feature types are available:
|
||||
|
||||
### Dashboard Items
|
||||
|
||||
The InvenTree dashboard is a collection of "items" which are displayed on the main dashboard page. Custom dashboard items can be added to the dashboard by implementing the `get_ui_dashboard_items` method:
|
||||
|
||||
::: plugin.base.ui.mixins.UserInterfaceMixin.get_ui_dashboard_items
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_sources: True
|
||||
summary: False
|
||||
members: []
|
||||
|
||||
#### Dashboard Item Options
|
||||
|
||||
The *options* field in the returned `UIFeature` object can contain the following properties:
|
||||
|
||||
::: plugin.base.ui.mixins.CustomDashboardItemOptions
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_sources: True
|
||||
summary: False
|
||||
members: []
|
||||
|
||||
#### Source Function
|
||||
|
||||
The frontend code expects a path to a javascript file containing a function named `renderDashboardItem` which will be called to render the custom dashboard item. Note that this function name can be overridden by appending the function name in the `source` field of the `UIFeature` object.
|
||||
|
||||
#### Example
|
||||
|
||||
Refer to the [sample plugin](#sample-plugin) for an example of how to implement server side rendering for custom panels.
|
||||
|
||||
### Panels
|
||||
|
||||
Many of the pages in the InvenTree web interface are built using a series of "panels" which are displayed on the page. Custom panels can be added to these pages, by implementing the `get_ui_panels` method:
|
||||
|
||||
::: plugin.base.ui.mixins.UserInterfaceMixin.get_ui_panels
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_sources: True
|
||||
summary: False
|
||||
members: []
|
||||
|
||||
#### Panel Options
|
||||
|
||||
The *options* field in the returned `UIFeature` object can contain the following properties:
|
||||
|
||||
::: plugin.base.ui.mixins.CustomPanelOptions
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_sources: True
|
||||
summary: False
|
||||
members: []
|
||||
|
||||
#### Source Function
|
||||
|
||||
The frontend code expects a path to a javascript file containing a function named `renderPanel` which will be called to render the custom panel. Note that this function name can be overridden by appending the function name in the `source` field of the `UIFeature` object.
|
||||
|
||||
#### Example
|
||||
|
||||
Refer to the [sample plugin](#sample-plugin) for an example of how to implement server side rendering for custom panels.
|
||||
|
||||
### Template Editors
|
||||
|
||||
The `get_ui_template_editors` feature type can be used to provide custom template editors.
|
||||
|
||||
::: plugin.base.ui.mixins.UserInterfaceMixin.get_ui_template_editors
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_sources: True
|
||||
summary: False
|
||||
members: []
|
||||
|
||||
### Template previews
|
||||
|
||||
The `get_ui_template_previews` feature type can be used to provide custom template previews:
|
||||
|
||||
::: plugin.base.ui.mixins.UserInterfaceMixin.get_ui_template_previews
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_sources: True
|
||||
summary: False
|
||||
members: []
|
||||
|
||||
## Plugin Context
|
||||
|
||||
When rendering certain content in the user interface, the rendering functions are passed a `context` object which contains information about the current page being rendered. The type of the `context` object is defined in the `PluginContext` file:
|
||||
|
||||
{{ includefile("src/frontend/src/components/plugins/PluginContext.tsx", title="Plugin Context", fmt="javascript") }}
|
||||
|
||||
This context data can be used to provide additional information to the rendering functions, and can be used to dynamically render content based on the current state of the system.
|
||||
|
||||
### Additional Context
|
||||
|
||||
Note that additional context can be passed to the rendering functions by adding additional key-value pairs to the `context` field in the `UIFeature` return type (provided by the backend via the API). This field is optional, and can be used at the discretion of the plugin developer.
|
||||
|
||||
## File Distribution
|
||||
|
||||
When distributing a custom UI plugin, the plugin should include the necessary frontend code to render the custom content. This frontend code should be included in the plugin package, and should be made available to the InvenTree frontend when the plugin is installed.
|
||||
|
||||
The simplest (and recommended) way to achieve this is to distribute the compiled javascript files with the plugin package, in a top-level `static` directory. This directory will be automatically collected by InvenTree when the plugin is installed, and the files will be copied to the appropriate location.
|
||||
|
||||
Read more about [static plugin files](../plugins.md#static-files) for more information.
|
||||
|
||||
## Sample Plugin
|
||||
|
||||
A (very simple) sample plugin which implements custom user interface functionality is provided in the InvenTree source code, which provides a full working example of how to implement custom user interface functionality.
|
||||
|
||||
::: plugin.samples.integration.user_interface_sample.SampleUserInterfacePlugin
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
|
||||
### More Examples
|
||||
|
||||
Some more complex examples of user interface plugins can be found on the InvenTree GitHub repository:
|
||||
|
||||
- [inventree-test-statistics](https://github.com/inventree/inventree-test-statistics)
|
||||
- [inventree-order-history](https://github.com/inventree/inventree-order-history)
|
||||
|
||||
## Consistent Theming
|
||||
|
||||
When developing a custom UI plugin for InvenTree, the plugin should aim to match the existing InvenTree theme as closely as possible. This will help to ensure that the custom content fits seamlessly into the existing user interface.
|
||||
|
||||
To achieve this, we strongly recommend that you use the same framework as the InvenTree frontend - which is built using [React](https://react.dev) on top of the [Mantine](https://mantine.dev) UI component library.
|
||||
|
||||
### Mantine
|
||||
|
||||
The Mantine UI component library is used throughout the InvenTree frontend, and provides a consistent look and feel to the user interface. By using Mantine components in your custom UI plugin, you can ensure that your custom content fits seamlessly into the existing InvenTree theme.
|
||||
|
||||
### InvenTree Component Library
|
||||
|
||||
We are working to develop and distribute a library of custom InvenTree components which can be used to build custom UI plugins. This library will be made available to plugin developers in the near future.
|
||||
|
||||
### Examples
|
||||
|
||||
Refer to some of the existing InvenTree plugins linked above for examples of building custom UI plugins using the Mantine component library for seamless integration.
|
||||
@@ -65,7 +65,7 @@ Additionally, add the following imports after the extended line.
|
||||
#### Blocks
|
||||
The page_base file is split into multiple sections called blocks. This allows you to implement sections of the webpage while getting many items like navbars, sidebars, and general layout provided for you.
|
||||
|
||||
The current default page base can be found [here]({{ sourcefile("src/backend/InvenTree/templates/page_base.html") }}). Look through this file to determine overridable blocks. The [stock app]({{ sourcedir("src/backend/InvenTree/stock") }}) offers a great example of implementing these blocks.
|
||||
The current default page base can be found [here](https://github.com/inventree/InvenTree/blob/0.15.x/src/backend/InvenTree/templates/page_base.html). Look through this file to determine overridable blocks. The [stock app](https://github.com/inventree/InvenTree/tree/master/src/backend/InvenTree/stock) offers a great example of implementing these blocks.
|
||||
|
||||
!!! warning "Sidebar Block"
|
||||
You may notice that implementing the `sidebar` block doesn't initially work. Be sure to enable the sidebar using JavaScript. This can be achieved by appending the following code, replacing `label` with a label of your choosing, to the end of your template file.
|
||||
|
||||
@@ -9,40 +9,34 @@ The `ValidationMixin` class enables plugins to perform custom validation of obje
|
||||
Any of the methods described below can be implemented in a custom plugin to provide functionality as required.
|
||||
|
||||
!!! info "More Info"
|
||||
For more information on any of the methods described below, refer to the InvenTree source code. [A working example is available as a starting point]({{ sourcefile("src/backend/InvenTree/plugin/samples/integration/validation_sample.py") }}).
|
||||
For more information on any of the methods described below, refer to the InvenTree source code. [A working example is available as a starting point](https://github.com/inventree/InvenTree/blob/0.15.x/src/backend/InvenTree/plugin/samples/integration/validation_sample.py).
|
||||
|
||||
!!! info "Multi Plugin Support"
|
||||
It is possible to have multiple plugins loaded simultaneously which support validation methods. For example when validating a field, if one plugin returns a null value (`None`) then the *next* plugin (if available) will be queried.
|
||||
|
||||
## Model Deletion
|
||||
|
||||
Any model which inherits the `PluginValidationMixin` class is exposed to the plugin system for custom deletion validation. Before the model is deleted from the database, it is first passed to the plugin ecosystem to check if it really should be deleted.
|
||||
|
||||
A custom plugin may implement the `validate_model_deletion` method to perform custom validation on the model instance before it is deleted.
|
||||
|
||||
::: plugin.base.integration.ValidationMixin.ValidationMixin.validate_model_deletion
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_sources: True
|
||||
summary: False
|
||||
members: []
|
||||
|
||||
## Model Validation
|
||||
|
||||
Any model which inherits the `PluginValidationMixin` mixin class is exposed to the plugin system for custom validation. Before the model is saved to the database (either when created, or updated), it is first passed to the plugin ecosystem for validation.
|
||||
|
||||
Any plugin which inherits the `ValidationMixin` can implement the `validate_model_instance` method, and run a custom validation routine.
|
||||
|
||||
::: plugin.base.integration.ValidationMixin.ValidationMixin.validate_model_instance
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_sources: True
|
||||
summary: False
|
||||
members: []
|
||||
The `validate_model_instance` method is passed the following arguments:
|
||||
|
||||
| Argument | Description |
|
||||
| --- | --- |
|
||||
| `instance` | The model instance to be validated |
|
||||
| `deltas` | A dict of field deltas (if the instance is being updated) |
|
||||
|
||||
```python
|
||||
def validate_model_instance(self, instance, deltas=None):
|
||||
"""Validate the supplied model instance.
|
||||
|
||||
Arguments:
|
||||
instance: The model instance to be validated
|
||||
deltas: A dict of field deltas (if the instance is being updated)
|
||||
"""
|
||||
...
|
||||
```
|
||||
|
||||
### Error Messages
|
||||
|
||||
@@ -58,7 +52,7 @@ To indicate a *field* validation error (i.e. the validation error applies only t
|
||||
|
||||
Note that an error can be which corresponds to multiple model instance fields.
|
||||
|
||||
### Example Plugin
|
||||
### Example
|
||||
|
||||
Presented below is a simple working example for a plugin which implements the `validate_model_instance` method:
|
||||
|
||||
@@ -108,70 +102,21 @@ By default, part names are not subject to any particular naming conventions or r
|
||||
|
||||
If the custom method determines that the part name is *objectionable*, it should throw a `ValidationError` which will be handled upstream by parent calling methods.
|
||||
|
||||
::: plugin.base.integration.ValidationMixin.ValidationMixin.validate_part_name
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_sources: True
|
||||
summary: False
|
||||
members: []
|
||||
|
||||
### Part IPN
|
||||
|
||||
Validation of the Part IPN (Internal Part Number) field is exposed to custom plugins via the `validate_part_ipn` method. Any plugins which extend the `ValidationMixin` class can implement this method, and raise a `ValidationError` if the IPN value does not match a required convention.
|
||||
|
||||
::: plugin.base.integration.ValidationMixin.ValidationMixin.validate_part_ipn
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_sources: True
|
||||
summary: False
|
||||
members: []
|
||||
Validation of the Part IPN (Internal Part Number) field is exposed to custom plugins via the `validate_part_IPN` method. Any plugins which extend the `ValidationMixin` class can implement this method, and raise a `ValidationError` if the IPN value does not match a required convention.
|
||||
|
||||
### Part Parameter Values
|
||||
|
||||
[Part parameters](../../part/parameter.md) can also have custom validation rules applied, by implementing the `validate_part_parameter` method. A plugin which implements this method should raise a `ValidationError` with an appropriate message if the part parameter value does not match a required convention.
|
||||
|
||||
::: plugin.base.integration.ValidationMixin.ValidationMixin.validate_part_parameter
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_sources: True
|
||||
summary: False
|
||||
members: []
|
||||
|
||||
### Batch Codes
|
||||
|
||||
[Batch codes](../../stock/tracking.md#batch-codes) can be generated and/or validated by custom plugins.
|
||||
|
||||
#### Validate Batch Code
|
||||
|
||||
The `validate_batch_code` method allows plugins to raise an error if a batch code input by the user does not meet a particular pattern.
|
||||
|
||||
::: plugin.base.integration.ValidationMixin.ValidationMixin.validate_batch_code
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_sources: True
|
||||
summary: False
|
||||
members: []
|
||||
|
||||
#### Generate Batch Code
|
||||
|
||||
The `generate_batch_code` method can be implemented to generate a new batch code, based on a set of provided information.
|
||||
|
||||
::: plugin.base.integration.ValidationMixin.ValidationMixin.generate_batch_code
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_sources: True
|
||||
summary: False
|
||||
members: []
|
||||
The `generate_batch_code` method can be implemented to generate a new batch code.
|
||||
|
||||
### Serial Numbers
|
||||
|
||||
@@ -183,30 +128,17 @@ The default InvenTree [serial numbering system](../../stock/tracking.md#serial-n
|
||||
|
||||
Custom serial number validation can be implemented using the `validate_serial_number` method. A *proposed* serial number is passed to this method, which then has the opportunity to raise a `ValidationError` to indicate that the serial number is not valid.
|
||||
|
||||
::: plugin.base.integration.ValidationMixin.ValidationMixin.validate_serial_number
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_sources: True
|
||||
summary: False
|
||||
members: []
|
||||
|
||||
!!! info "Stock Item"
|
||||
If the `stock_item` argument is provided, then this stock item has already been assigned with the provided serial number. This stock item should be excluded from any subsequent checks for *uniqueness*. The `stock_item` parameter is optional, and may be `None` if the serial number is being validated in a context where no stock item is available.
|
||||
|
||||
##### Example
|
||||
|
||||
A plugin which requires all serial numbers to be valid hexadecimal values may implement this method as follows:
|
||||
|
||||
```python
|
||||
def validate_serial_number(self, serial: str, part: Part, stock_item: StockItem = None):
|
||||
def validate_serial_number(self, serial: str, part: Part):
|
||||
"""Validate the supplied serial number
|
||||
|
||||
Arguments:
|
||||
serial: The proposed serial number (string)
|
||||
part: The Part instance for which this serial number is being validated
|
||||
stock_item: The StockItem instance for which this serial number is being validated
|
||||
"""
|
||||
|
||||
try:
|
||||
@@ -222,15 +154,6 @@ While InvenTree supports arbitrary text values in the serial number fields, behi
|
||||
|
||||
A custom plugin can implement the `convert_serial_to_int` method to determine how a particular serial number is converted to an integer representation.
|
||||
|
||||
::: plugin.base.integration.ValidationMixin.ValidationMixin.convert_serial_to_int
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_sources: True
|
||||
summary: False
|
||||
members: []
|
||||
|
||||
!!! info "Not Required"
|
||||
If this method is not implemented, or the serial number cannot be converted to an integer, then the sorting algorithm falls back to the text (string) value
|
||||
|
||||
@@ -240,15 +163,6 @@ A core component of the InvenTree serial number system is the ability to *increm
|
||||
|
||||
For custom serial number schemes, it is important to provide a method to generate the *next* serial number given a current value. The `increment_serial_number` method can be implemented by a plugin to achieve this.
|
||||
|
||||
::: plugin.base.integration.ValidationMixin.ValidationMixin.increment_serial_number
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_sources: True
|
||||
summary: False
|
||||
members: []
|
||||
|
||||
!!! info "Invalid Increment"
|
||||
If the provided number cannot be incremented (or an error occurs) the method should return `None`
|
||||
|
||||
@@ -268,15 +182,3 @@ def increment_serial_number(self, serial: str):
|
||||
|
||||
return val
|
||||
```
|
||||
|
||||
## Sample Plugin
|
||||
|
||||
A sample plugin which implements custom validation routines is provided in the InvenTree source code:
|
||||
|
||||
::: plugin.samples.integration.validation_sample.SampleValidatorPlugin
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
|
||||
@@ -14,7 +14,7 @@ Navigate to the "Settings" page and click on the "Display" tab, you should see t
|
||||
{% include 'img.html' %}
|
||||
{% endwith %}
|
||||
|
||||
The drop-down list let's you select any other color theme found in your static folder (see next section to find out how to [add color themes](#add-color-theme)). Once selected, click on the "Apply Theme" button for the new color theme to be activated.
|
||||
The drop-down list let's you select any other color theme found in your static folder (see next section to find out how to [add color themes](#add-color-themes)). Once selected, click on the "Apply Theme" button for the new color theme to be activated.
|
||||
|
||||
!!! info "Per-user Setting"
|
||||
Color themes are "user specific" which means that changing the color theme in your own settings won't affect other users.
|
||||
|
||||
@@ -14,24 +14,39 @@ InvenTree installation is not officially supported natively on Windows. However
|
||||
|
||||
### Command 'invoke' not found
|
||||
|
||||
If the `invoke` command does not work, it means that the invoke tool has not been correctly installed.
|
||||
If the `invoke` command does not work, it means that the [invoke](https://pypi.org/project/invoke/) python library has not been correctly installed.
|
||||
|
||||
Refer to the [invoke installation guide](./start/invoke.md#installation) for more information.
|
||||
Update the installed python packages with PIP:
|
||||
|
||||
### Can't find any collection named tasks
|
||||
|
||||
Refer to the [invoke guide](./start/invoke.md#cant-find-any-collection-named-tasks) for more information.
|
||||
```
|
||||
pip3 install -U --require-hashes -r requirements.txt
|
||||
```
|
||||
|
||||
### Invoke Version
|
||||
|
||||
If the installed version of invoke is too old, users may see error messages during the installation procedure. Refer to the [invoke guide](./start/invoke.md#minimum-version) for more information.
|
||||
If the installed version of invoke is too old, users may see error messages during the installation procedure, such as:
|
||||
|
||||
### INVE-E1 - No frontend included
|
||||
- *'update' did not receive all required positional arguments!*
|
||||
- *Function has keyword-only arguments or annotations*
|
||||
|
||||
Make sure you are running a stable or production release of InvenTree. The frontend panel is not included in development releases.
|
||||
More Information: [Error Codes - INVE-E1](./settings/error_codes.md#inve-e1)
|
||||
As per the [invoke guide](./start/intro.md#invoke), the minimum required version of Invoke is `{{ config.extra.min_invoke_version }}`.
|
||||
|
||||
### No module named <xxx>
|
||||
To determine the version of invoke you have installed, run either:
|
||||
|
||||
```
|
||||
invoke --version
|
||||
```
|
||||
```
|
||||
python -m invoke --version
|
||||
```
|
||||
|
||||
If you are running an older version of invoke, ensure it is updated to the latest version:
|
||||
|
||||
```
|
||||
pip install -U invoke
|
||||
```
|
||||
|
||||
### No module named 'django'
|
||||
|
||||
During the install or update process, you may be presented with an error like:
|
||||
|
||||
@@ -49,27 +64,6 @@ This error occurs because your installed python version is not up to date. We [r
|
||||
|
||||
You (or your system administrator) needs to update python to meet the minimum requirements for InvenTree.
|
||||
|
||||
### InvenTree Site URL
|
||||
|
||||
During the installation or update process, you may see an error similar to:
|
||||
|
||||
```
|
||||
'No CSRF_TRUSTED_ORIGINS specified. Please provide a list of trusted origins, or specify INVENTREE_SITE_URL'
|
||||
```
|
||||
|
||||
If you see this error, it means that the `INVENTREE_SITE_URL` environment variable has not correctly specified. Refer to the [configuration documentation](./start/config.md#site-url) for more information.
|
||||
|
||||
### Login Issues
|
||||
|
||||
If you have successfully started the InvenTree server, but are experiencing issues logging in, it may be due to the security interactions between your web browser and the server. While the default configuration should work for most users, if you do experience login issues, ensure that your [server access settings](./start/config.md#server-access) are correctly configured.
|
||||
|
||||
### Session Cookies
|
||||
|
||||
The [0.17.0 release](https://github.com/inventree/InvenTree/releases/tag/0.17.0) included [a change to the way that session cookies were handled](https://github.com/inventree/InvenTree/pull/8269). This change may cause login issues for existing InvenTree installs which are upgraded from an older version. System administrators should refer to the [server access settings](./start/config.md#server-access) and ensure that the following settings are correctly configured:
|
||||
|
||||
- **INVENTREE_SESSION_COOKIE_SECURE**: `False`
|
||||
- **INVENTREE_COOKIE_SAMESITE**: `False`
|
||||
|
||||
## Update Issues
|
||||
|
||||
Sometimes, users may encounter unexpected error messages when updating their InvenTree installation to a newer version.
|
||||
@@ -89,26 +83,6 @@ For more information, refer to the installation guides:
|
||||
!!! warning "Invoke Update"
|
||||
You must ensure that the `invoke update` command is performed *every time* you update InvenTree
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
Before performing an update, check the release notes! Any *breaking changes* (changes which require user intervention) will be clearly noted.
|
||||
|
||||
### Cannot import name get_storage_class
|
||||
|
||||
When running an install or update, you may see an error similar to:
|
||||
|
||||
```python
|
||||
ImportError: cannot import name 'get_storage_class' from 'django.core.files.storage'
|
||||
```
|
||||
|
||||
In such a situation, it is likely that the automatic backup procedure is unable to run, as the required python packages are not yet installed or are unavailable.
|
||||
|
||||
To proceed in this case, you can skip the backup procedure by running the `invoke update` command with the `--skip-backup` flag:
|
||||
|
||||
```bash
|
||||
invoke update --skip-backup
|
||||
```
|
||||
|
||||
### Feature *x* does not work after update
|
||||
|
||||
If a particular menu / item is not visible after updating InvenTree, or a certain function no longer seems to work, it may be due to your internet browser caching old versions of CSS and JavaScript files.
|
||||
|
||||
@@ -39,7 +39,7 @@ InvenTree allows you to upload simple BOM files in multiple formats, and downloa
|
||||
|
||||
## Build Parts
|
||||
|
||||
InvenTree features a build management system to help you track the progress of your builds.
|
||||
Inventree features a build management system to help you track the progress of your builds.
|
||||
Builds consume stock items to make new parts, you can decide to automatically or manually allocate parts from your current inventory.
|
||||
|
||||
[Read more...](./build/build.md)
|
||||
|
||||
@@ -57,7 +57,7 @@ def fetch_rtd_versions():
|
||||
versions = sorted(versions, key=lambda x: StrictVersion(x['version']), reverse=True)
|
||||
|
||||
# Add "latest" version first
|
||||
if not any(x['title'] == 'latest' for x in versions):
|
||||
if not any((x['title'] == 'latest' for x in versions)):
|
||||
versions.insert(
|
||||
0,
|
||||
{
|
||||
@@ -70,7 +70,7 @@ def fetch_rtd_versions():
|
||||
# Ensure we have the 'latest' version
|
||||
current_version = os.environ.get('READTHEDOCS_VERSION', None)
|
||||
|
||||
if current_version and not any(x['title'] == current_version for x in versions):
|
||||
if current_version and not any((x['title'] == current_version for x in versions)):
|
||||
versions.append({
|
||||
'version': current_version,
|
||||
'title': current_version,
|
||||
@@ -82,7 +82,7 @@ def fetch_rtd_versions():
|
||||
print('Discovered the following versions:')
|
||||
print(versions)
|
||||
|
||||
with open(output_filename, 'w', encoding='utf-8') as file:
|
||||
with open(output_filename, 'w') as file:
|
||||
json.dump(versions, file, indent=2)
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ def get_release_data():
|
||||
# Release information has been cached to file
|
||||
|
||||
print("Loading release information from 'releases.json'")
|
||||
with open(json_file, encoding='utf-8') as f:
|
||||
with open(json_file) as f:
|
||||
return json.loads(f.read())
|
||||
|
||||
# Download release information via the GitHub API
|
||||
@@ -127,7 +127,7 @@ def get_release_data():
|
||||
page += 1
|
||||
|
||||
# Cache these results to file
|
||||
with open(json_file, 'w', encoding='utf-8') as f:
|
||||
with open(json_file, 'w') as f:
|
||||
print("Saving release information to 'releases.json'")
|
||||
f.write(json.dumps(releases))
|
||||
|
||||
@@ -154,14 +154,14 @@ def on_config(config, *args, **kwargs):
|
||||
|
||||
# Check for 'versions.json' file
|
||||
# If it does not exist, we need to fetch it from the RTD API
|
||||
# if os.path.exists(os.path.join(os.path.dirname(__file__), 'versions.json')):
|
||||
# print("Found 'versions.json' file")
|
||||
# else:
|
||||
# fetch_rtd_versions()
|
||||
if os.path.exists(os.path.join(os.path.dirname(__file__), 'versions.json')):
|
||||
print("Found 'versions.json' file")
|
||||
else:
|
||||
fetch_rtd_versions()
|
||||
|
||||
if rtd:
|
||||
rtd_version = os.environ.get('READTHEDOCS_VERSION')
|
||||
rtd_language = os.environ.get('READTHEDOCS_LANGUAGE')
|
||||
rtd_version = os.environ['READTHEDOCS_VERSION']
|
||||
rtd_language = os.environ['READTHEDOCS_LANGUAGE']
|
||||
|
||||
site_url = f'https://docs.inventree.org/{rtd_language}/{rtd_version}'
|
||||
assets_dir = f'/{rtd_language}/{rtd_version}/assets'
|
||||
@@ -173,7 +173,7 @@ def on_config(config, *args, **kwargs):
|
||||
# Add *all* readthedocs related keys
|
||||
readthedocs = {}
|
||||
|
||||
for key in os.environ:
|
||||
for key in os.environ.keys():
|
||||
if key.startswith('READTHEDOCS_'):
|
||||
k = key.replace('READTHEDOCS_', '').lower()
|
||||
readthedocs[k] = os.environ[key]
|
||||
|
||||
@@ -61,7 +61,7 @@ A *contact* can be assigned to orders, (such as [purchase orders](./purchase_ord
|
||||
|
||||
A company can have multiple registered addresses for use with all types of orders.
|
||||
An address is broken down to internationally recognised elements that are designed to allow for formatting an address according to user needs.
|
||||
Addresses are composed differently across the world, and InvenTree reflects this by splitting addresses into components:
|
||||
Addresses are composed differently across the world, and Inventree reflects this by splitting addresses into components:
|
||||
- Line 1: Main street address
|
||||
- Line 2: Extra street address line
|
||||
- Postal Code: Also known as ZIP code, this is normally a number 3-5 digits in length
|
||||
|
||||
@@ -20,25 +20,8 @@ Each Purchase Order has a specific status code which indicates the current state
|
||||
| --- | --- |
|
||||
| Pending | The purchase order has been created, but has not been submitted to the supplier |
|
||||
| In Progress | The purchase order has been issued to the supplier, and is in progress |
|
||||
| On Hold | The purchase order has been placed on hold, but is still active |
|
||||
| Complete | The purchase order has been completed, and is now closed |
|
||||
| Cancelled | The purchase order was cancelled, and is now closed |
|
||||
| Lost | The purchase order was lost, and is now closed |
|
||||
| Returned | The purchase order was returned, and is now closed |
|
||||
|
||||
**Source Code**
|
||||
|
||||
Refer to the source code for the Purchase Order status codes:
|
||||
|
||||
::: order.status_codes.PurchaseOrderStatus
|
||||
options:
|
||||
show_bases: False
|
||||
show_root_heading: False
|
||||
show_root_toc_entry: False
|
||||
show_source: True
|
||||
members: []
|
||||
|
||||
Purchase Order Status supports [custom states](../concepts/custom_states.md).
|
||||
|
||||
### Purchase Order Currency
|
||||
|
||||
@@ -93,14 +76,6 @@ There are two options to mark items as "received":
|
||||
!!! note "Permissions"
|
||||
Marking line items as received requires the "Purchase order" ADD permission.
|
||||
|
||||
### Item Location
|
||||
|
||||
When receiving items from a purchase order, the location of the items must be specified. There are multiple ways to specify the location:
|
||||
|
||||
* **Order Destination**: The *destination* field of the purchase order can be set to a specific location. When receiving items, the location will default to the destination location.
|
||||
|
||||
* **Line Item Location**: Each line item can have a specific location set. When receiving items, the location will default to the line item location. *Note: A destination specified at the line item level will override the destination specified at the order level.*
|
||||
|
||||
### Received Items
|
||||
|
||||
Each item marked as "received" is automatically converted into a stock item.
|
||||
@@ -149,14 +124,3 @@ This view can be accessed externally as an ICS calendar using a URL like the fol
|
||||
`http://inventree.example.org/api/order/calendar/purchase-order/calendar.ics`
|
||||
|
||||
by default, completed orders are not exported. These can be included by appending `?include_completed=True` to the URL.
|
||||
|
||||
## Purchase Order Settings
|
||||
|
||||
The following [global settings](../settings/global.md) are available for purchase orders:
|
||||
|
||||
| Name | Description | Default | Units |
|
||||
| ---- | ----------- | ------- | ----- |
|
||||
{{ globalsetting("PURCHASEORDER_REFERENCE_PATTERN") }}
|
||||
{{ globalsetting("PURCHASEORDER_REQUIRE_RESPONSIBLE") }}
|
||||
{{ globalsetting("PURCHASEORDER_EDIT_COMPLETED_ORDERS") }}
|
||||
{{ globalsetting("PURCHASEORDER_AUTO_COMPLETE") }}
|
||||
|
||||