2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-15 11:35:41 +00:00

switched to single quotes everywhere

This commit is contained in:
Matthias Mair
2024-01-07 21:03:14 +01:00
parent a92442e60e
commit f83fedbbb8
181 changed files with 2080 additions and 2080 deletions

270
tasks.py
View File

@ -22,7 +22,7 @@ def checkPythonVersion():
REQ_MAJOR = 3
REQ_MINOR = 9
version = sys.version.split(" ")[0]
version = sys.version.split(' ')[0]
valid = True
@ -33,8 +33,8 @@ def checkPythonVersion():
valid = False
if not valid:
print(f"The installed python version ({version}) is not supported!")
print(f"InvenTree requires Python {REQ_MAJOR}.{REQ_MINOR} or above")
print(f'The installed python version ({version}) is not supported!')
print(f'InvenTree requires Python {REQ_MAJOR}.{REQ_MINOR} or above')
sys.exit(1)
@ -62,26 +62,26 @@ def apps():
def content_excludes():
"""Returns a list of content types to exclude from import/export."""
excludes = [
"contenttypes",
"auth.permission",
"users.apitoken",
"error_report.error",
"admin.logentry",
"django_q.schedule",
"django_q.task",
"django_q.ormq",
"users.owner",
"exchange.rate",
"exchange.exchangebackend",
"common.notificationentry",
"common.notificationmessage",
"user_sessions.session",
'contenttypes',
'auth.permission',
'users.apitoken',
'error_report.error',
'admin.logentry',
'django_q.schedule',
'django_q.task',
'django_q.ormq',
'users.owner',
'exchange.rate',
'exchange.exchangebackend',
'common.notificationentry',
'common.notificationmessage',
'user_sessions.session',
]
output = ""
output = ''
for e in excludes:
output += f"--exclude {e} "
output += f'--exclude {e} '
return output
@ -175,12 +175,12 @@ def check_file_existance(filename: str, overwrite: bool = False):
"""
if Path(filename).is_file() and overwrite is False:
response = input(
"Warning: file already exists. Do you want to overwrite? [y/N]: "
'Warning: file already exists. Do you want to overwrite? [y/N]: '
)
response = str(response).strip().lower()
if response not in ['y', 'yes']:
print("Cancelled export operation")
print('Cancelled export operation')
sys.exit(1)
@ -220,12 +220,12 @@ def setup_dev(c, tests=False):
c.run('pip3 install -U -r requirements-dev.txt')
# Install pre-commit hook
print("Installing pre-commit for checks before git commits...")
print('Installing pre-commit for checks before git commits...')
c.run('pre-commit install')
# Update all the hooks
c.run('pre-commit autoupdate')
print("pre-commit set up is done...")
print('pre-commit set up is done...')
# Set up test-data if flag is set
if tests:
@ -242,19 +242,19 @@ def superuser(c):
@task
def rebuild_models(c):
"""Rebuild database models with MPTT structures."""
manage(c, "rebuild_models", pty=True)
manage(c, 'rebuild_models', pty=True)
@task
def rebuild_thumbnails(c):
"""Rebuild missing image thumbnails."""
manage(c, "rebuild_thumbnails", pty=True)
manage(c, 'rebuild_thumbnails', pty=True)
@task
def clean_settings(c):
"""Clean the setting tables of old settings."""
manage(c, "clean_settings")
manage(c, 'clean_settings')
@task(help={'mail': "mail of the user who's MFA should be disabled"})
@ -263,16 +263,16 @@ def remove_mfa(c, mail=''):
if not mail:
print('You must provide a users mail')
manage(c, f"remove_mfa {mail}")
manage(c, f'remove_mfa {mail}')
@task(help={'frontend': 'Build the frontend'})
def static(c, frontend=False):
"""Copies required static files to the STATIC_ROOT directory, as per Django requirements."""
manage(c, "prerender")
manage(c, 'prerender')
if frontend and node_available():
frontend_build(c)
manage(c, "collectstatic --no-input")
manage(c, 'collectstatic --no-input')
@task
@ -286,7 +286,7 @@ def translate_stats(c):
try:
manage(c, 'compilemessages', pty=True)
except Exception:
print("WARNING: Translation files could not be compiled:")
print('WARNING: Translation files could not be compiled:')
path = Path('InvenTree', 'script', 'translation_stats.py')
c.run(f'python3 {path}')
@ -300,8 +300,8 @@ def translate(c):
it is performed as part of the InvenTree translation toolchain.
"""
# Translate applicable .py / .html / .js / .tsx files
manage(c, "makemessages --all -e py,html,js --no-wrap")
manage(c, "compilemessages")
manage(c, 'makemessages --all -e py,html,js --no-wrap')
manage(c, 'compilemessages')
if node_available():
frontend_install(c)
@ -315,19 +315,19 @@ def translate(c):
@task
def backup(c):
"""Backup the database and media files."""
print("Backing up InvenTree database...")
manage(c, "dbbackup --noinput --clean --compress")
print("Backing up InvenTree media files...")
manage(c, "mediabackup --noinput --clean --compress")
print('Backing up InvenTree database...')
manage(c, 'dbbackup --noinput --clean --compress')
print('Backing up InvenTree media files...')
manage(c, 'mediabackup --noinput --clean --compress')
@task
def restore(c):
"""Restore the database and media files."""
print("Restoring InvenTree database...")
manage(c, "dbrestore --noinput --uncompress")
print("Restoring InvenTree media files...")
manage(c, "mediarestore --noinput --uncompress")
print('Restoring InvenTree database...')
manage(c, 'dbrestore --noinput --uncompress')
print('Restoring InvenTree media files...')
manage(c, 'mediarestore --noinput --uncompress')
@task(post=[rebuild_models, rebuild_thumbnails])
@ -336,16 +336,16 @@ def migrate(c):
This is a critical step if the database schema have been altered!
"""
print("Running InvenTree database migrations...")
print("========================================")
print('Running InvenTree database migrations...')
print('========================================')
manage(c, "makemigrations")
manage(c, "migrate --noinput")
manage(c, "migrate --run-syncdb")
manage(c, "check")
manage(c, 'makemigrations')
manage(c, 'migrate --noinput')
manage(c, 'migrate --run-syncdb')
manage(c, 'check')
print("========================================")
print("InvenTree database migrations completed!")
print('========================================')
print('InvenTree database migrations completed!')
@task(
@ -399,9 +399,9 @@ def update(c, skip_backup=False, frontend: bool = False):
@task(
help={
'filename': "Output filename (default = 'data.json')",
'overwrite': "Overwrite existing files without asking first (default = off/False)",
'include_permissions': "Include user and group permissions in the output file (filename) (default = off/False)",
'delete_temp': "Delete temporary files (containing permissions) at end of run. Note that this will delete temporary files from previous runs as well. (default = off/False)",
'overwrite': 'Overwrite existing files without asking first (default = off/False)',
'include_permissions': 'Include user and group permissions in the output file (filename) (default = off/False)',
'delete_temp': 'Delete temporary files (containing permissions) at end of run. Note that this will delete temporary files from previous runs as well. (default = off/False)',
}
)
def export_records(
@ -436,38 +436,38 @@ def export_records(
check_file_existance(filename, overwrite)
tmpfile = f"{filename}.tmp"
tmpfile = f'{filename}.tmp'
cmd = f"dumpdata --indent 2 --output '{tmpfile}' {content_excludes()}"
# Dump data to temporary file
manage(c, cmd, pty=True)
print("Running data post-processing step...")
print('Running data post-processing step...')
# Post-process the file, to remove any "permissions" specified for a user or group
with open(tmpfile, "r") as f_in:
with open(tmpfile, 'r') as f_in:
data = json.loads(f_in.read())
if include_permissions is False:
for entry in data:
if "model" in entry:
if 'model' in entry:
# Clear out any permissions specified for a group
if entry["model"] == "auth.group":
entry["fields"]["permissions"] = []
if entry['model'] == 'auth.group':
entry['fields']['permissions'] = []
# Clear out any permissions specified for a user
if entry["model"] == "auth.user":
entry["fields"]["user_permissions"] = []
if entry['model'] == 'auth.user':
entry['fields']['user_permissions'] = []
# Write the processed data to file
with open(filename, "w") as f_out:
with open(filename, 'w') as f_out:
f_out.write(json.dumps(data, indent=2))
print("Data export completed")
print('Data export completed')
if delete_temp is True:
print("Removing temporary file")
print('Removing temporary file')
os.remove(tmpfile)
@ -491,30 +491,30 @@ def import_records(c, filename='data.json', clear=False):
print(f"Importing database records from '{filename}'")
# Pre-process the data, to remove any "permissions" specified for a user or group
tmpfile = f"{filename}.tmp.json"
tmpfile = f'{filename}.tmp.json'
with open(filename, "r") as f_in:
with open(filename, 'r') as f_in:
data = json.loads(f_in.read())
for entry in data:
if "model" in entry:
if 'model' in entry:
# Clear out any permissions specified for a group
if entry["model"] == "auth.group":
entry["fields"]["permissions"] = []
if entry['model'] == 'auth.group':
entry['fields']['permissions'] = []
# Clear out any permissions specified for a user
if entry["model"] == "auth.user":
entry["fields"]["user_permissions"] = []
if entry['model'] == 'auth.user':
entry['fields']['user_permissions'] = []
# Write the processed data to the tmp file
with open(tmpfile, "w") as f_out:
with open(tmpfile, 'w') as f_out:
f_out.write(json.dumps(data, indent=2))
cmd = f"loaddata '{tmpfile}' -i {content_excludes()}"
manage(c, cmd, pty=True)
print("Data import completed")
print('Data import completed')
@task
@ -523,7 +523,7 @@ def delete_data(c, force=False):
Warning: This will REALLY delete all records in the database!!
"""
print("Deleting all data from InvenTree database...")
print('Deleting all data from InvenTree database...')
if force:
manage(c, 'flush --noinput')
@ -576,16 +576,16 @@ def import_fixtures(c):
@task
def wait(c):
"""Wait until the database connection is ready."""
return manage(c, "wait_for_db")
return manage(c, 'wait_for_db')
@task(pre=[wait], help={'address': 'Server address:port (default=127.0.0.1:8000)'})
def server(c, address="127.0.0.1:8000"):
def server(c, address='127.0.0.1:8000'):
"""Launch a (development) server using Django's in-built webserver.
Note: This is *not* sufficient for a production installation.
"""
manage(c, "runserver {address}".format(address=address), pty=True)
manage(c, 'runserver {address}'.format(address=address), pty=True)
@task(pre=[wait])
@ -598,7 +598,7 @@ def worker(c):
@task
def render_js_files(c):
"""Render templated javascript files (used for static testing)."""
manage(c, "test InvenTree.ci_render_js")
manage(c, 'test InvenTree.ci_render_js')
@task(post=[translate_stats, static, server])
@ -616,34 +616,34 @@ def test_translations(c):
django.setup()
# Add language
print("Add dummy language...")
print("========================================")
manage(c, "makemessages -e py,html,js --no-wrap -l xx")
print('Add dummy language...')
print('========================================')
manage(c, 'makemessages -e py,html,js --no-wrap -l xx')
# change translation
print("Fill in dummy translations...")
print("========================================")
print('Fill in dummy translations...')
print('========================================')
file_path = pathlib.Path(settings.LOCALE_PATHS[0], 'xx', 'LC_MESSAGES', 'django.po')
new_file_path = str(file_path) + '_new'
# compile regex
reg = re.compile(
r"[a-zA-Z0-9]{1}" # match any single letter and number # noqa: W504
+ r"(?![^{\(\<]*[}\)\>])" # that is not inside curly brackets, brackets or a tag # noqa: W504
+ r"(?<![^\%][^\(][)][a-z])" # that is not a specially formatted variable with singles # noqa: W504
+ r"(?![^\\][\n])" # that is not a newline
r'[a-zA-Z0-9]{1}' # match any single letter and number # noqa: W504
+ r'(?![^{\(\<]*[}\)\>])' # that is not inside curly brackets, brackets or a tag # noqa: W504
+ r'(?<![^\%][^\(][)][a-z])' # that is not a specially formatted variable with singles # noqa: W504
+ r'(?![^\\][\n])' # that is not a newline
)
last_string = ''
# loop through input file lines
with open(file_path, "rt") as file_org:
with open(new_file_path, "wt") as file_new:
with open(file_path, 'rt') as file_org:
with open(new_file_path, 'wt') as file_new:
for line in file_org:
if line.startswith('msgstr "'):
# write output -> replace regex matches with x in the read in (multi)string
file_new.write(f'msgstr "{reg.sub("x", last_string[7:-2])}"\n')
last_string = "" # reset (multi)string
last_string = '' # reset (multi)string
elif line.startswith('msgid "'):
last_string = (
last_string + line
@ -661,9 +661,9 @@ def test_translations(c):
new_file_path.rename(file_path)
# compile languages
print("Compile languages ...")
print("========================================")
manage(c, "compilemessages")
print('Compile languages ...')
print('========================================')
manage(c, 'compilemessages')
# reset cwd
os.chdir(base_path)
@ -728,7 +728,7 @@ def test(
@task(help={'dev': 'Set up development environment at the end'})
def setup_test(c, ignore_update=False, dev=False, path="inventree-demo-dataset"):
def setup_test(c, ignore_update=False, dev=False, path='inventree-demo-dataset'):
"""Setup a testing environment."""
from InvenTree.InvenTree.config import get_media_dir
@ -737,31 +737,31 @@ def setup_test(c, ignore_update=False, dev=False, path="inventree-demo-dataset")
# Remove old data directory
if os.path.exists(path):
print("Removing old data ...")
print('Removing old data ...')
c.run(f'rm {path} -r')
# Get test data
print("Cloning demo dataset ...")
print('Cloning demo dataset ...')
c.run(f'git clone https://github.com/inventree/demo-dataset {path} -v --depth=1')
print("========================================")
print('========================================')
# Make sure migrations are done - might have just deleted sqlite database
if not ignore_update:
migrate(c)
# Load data
print("Loading database records ...")
print('Loading database records ...')
import_records(c, filename=f'{path}/inventree_data.json', clear=True)
# Copy media files
print("Copying media files ...")
print('Copying media files ...')
src = Path(path).joinpath('media').resolve()
dst = get_media_dir()
shutil.copytree(src, dst, dirs_exist_ok=True)
print("Done setting up test environment...")
print("========================================")
print('Done setting up test environment...')
print('========================================')
# Set up development setup if flag is set
if dev:
@ -771,7 +771,7 @@ def setup_test(c, ignore_update=False, dev=False, path="inventree-demo-dataset")
@task(
help={
'filename': "Output filename (default = 'schema.yml')",
'overwrite': "Overwrite existing files without asking first (default = off/False)",
'overwrite': 'Overwrite existing files without asking first (default = off/False)',
}
)
def schema(c, filename='schema.yml', overwrite=False):
@ -850,8 +850,8 @@ def frontend_install(c):
Args:
c: Context variable
"""
print("Installing frontend dependencies")
yarn(c, "yarn install")
print('Installing frontend dependencies')
yarn(c, 'yarn install')
@task
@ -861,9 +861,9 @@ def frontend_trans(c):
Args:
c: Context variable
"""
print("Compiling frontend translations")
yarn(c, "yarn run extract")
yarn(c, "yarn run compile")
print('Compiling frontend translations')
yarn(c, 'yarn run extract')
yarn(c, 'yarn run compile')
@task
@ -873,8 +873,8 @@ def frontend_build(c):
Args:
c: Context variable
"""
print("Building frontend")
yarn(c, "yarn run build --emptyOutDir")
print('Building frontend')
yarn(c, 'yarn run build --emptyOutDir')
@task
@ -884,18 +884,18 @@ def frontend_dev(c):
Args:
c: Context variable
"""
print("Starting frontend development server")
yarn(c, "yarn run dev")
print('Starting frontend development server')
yarn(c, 'yarn run dev')
@task(
help={
'ref': "git ref, default: current git ref",
'tag': "git tag to look for release",
'file': "destination to frontend-build.zip file",
'repo': "GitHub repository, default: InvenTree/inventree",
'extract': "Also extract and place at the correct destination, default: True",
'clean': "Delete old files from InvenTree/web/static/web first, default: True",
'ref': 'git ref, default: current git ref',
'tag': 'git tag to look for release',
'file': 'destination to frontend-build.zip file',
'repo': 'GitHub repository, default: InvenTree/inventree',
'extract': 'Also extract and place at the correct destination, default: True',
'clean': 'Delete old files from InvenTree/web/static/web first, default: True',
}
)
def frontend_download(
@ -903,7 +903,7 @@ def frontend_download(
ref=None,
tag=None,
file=None,
repo="InvenTree/inventree",
repo='InvenTree/inventree',
extract=True,
clean=True,
):
@ -928,7 +928,7 @@ def frontend_download(
import requests
# globals
default_headers = {"Accept": "application/vnd.github.v3+json"}
default_headers = {'Accept': 'application/vnd.github.v3+json'}
# helper functions
def find_resource(resource, key, value):
@ -942,34 +942,34 @@ def frontend_download(
if not extract:
return
dest_path = Path(__file__).parent / "InvenTree/web/static/web"
dest_path = Path(__file__).parent / 'InvenTree/web/static/web'
# if clean, delete static/web directory
if clean:
shutil.rmtree(dest_path, ignore_errors=True)
os.makedirs(dest_path)
print(f"Cleaned directory: {dest_path}")
print(f'Cleaned directory: {dest_path}')
# unzip build to static folder
with ZipFile(file, "r") as zip_ref:
with ZipFile(file, 'r') as zip_ref:
zip_ref.extractall(dest_path)
print(f"Unzipped downloaded frontend build to: {dest_path}")
print(f'Unzipped downloaded frontend build to: {dest_path}')
def handle_download(url):
# download frontend-build.zip to temporary file
with requests.get(
url, headers=default_headers, stream=True, allow_redirects=True
) as response, NamedTemporaryFile(suffix=".zip") as dst:
) as response, NamedTemporaryFile(suffix='.zip') as dst:
response.raise_for_status()
# auto decode the gzipped raw data
response.raw.read = functools.partial(
response.raw.read, decode_content=True
)
with open(dst.name, "wb") as f:
with open(dst.name, 'wb') as f:
shutil.copyfileobj(response.raw, f)
print(f"Downloaded frontend build to temporary file: {dst.name}")
print(f'Downloaded frontend build to temporary file: {dst.name}')
handle_extract(dst.name)
@ -980,26 +980,26 @@ def frontend_download(
# check arguments
if ref is not None and tag is not None:
print("[ERROR] Do not set ref and tag.")
print('[ERROR] Do not set ref and tag.')
return
if ref is None and tag is None:
try:
ref = subprocess.check_output(
["git", "rev-parse", "HEAD"], encoding="utf-8"
['git', 'rev-parse', 'HEAD'], encoding='utf-8'
).strip()
except Exception:
print("[ERROR] Cannot get current ref via 'git rev-parse HEAD'")
return
if ref is None and tag is None:
print("[ERROR] Either ref or tag needs to be set.")
print('[ERROR] Either ref or tag needs to be set.')
if tag:
tag = tag.lstrip("v")
tag = tag.lstrip('v')
try:
handle_download(
f"https://github.com/{repo}/releases/download/{tag}/frontend-build.zip"
f'https://github.com/{repo}/releases/download/{tag}/frontend-build.zip'
)
except Exception as e:
if not isinstance(e, requests.HTTPError):
@ -1015,12 +1015,12 @@ Then try continuing by running: invoke frontend-download --file <path-to-downloa
if ref:
# get workflow run from all workflow runs on that particular ref
workflow_runs = requests.get(
f"https://api.github.com/repos/{repo}/actions/runs?head_sha={ref}",
f'https://api.github.com/repos/{repo}/actions/runs?head_sha={ref}',
headers=default_headers,
).json()
if not (qc_run := find_resource(workflow_runs["workflow_runs"], "name", "QC")):
print("[ERROR] Cannot find any workflow runs for current sha")
if not (qc_run := find_resource(workflow_runs['workflow_runs'], 'name', 'QC')):
print('[ERROR] Cannot find any workflow runs for current sha')
return
print(
f"Found workflow {qc_run['name']} (run {qc_run['run_number']}-{qc_run['run_attempt']})"
@ -1028,14 +1028,14 @@ Then try continuing by running: invoke frontend-download --file <path-to-downloa
# get frontend-build artifact from all artifacts available for this workflow run
artifacts = requests.get(
qc_run["artifacts_url"], headers=default_headers
qc_run['artifacts_url'], headers=default_headers
).json()
if not (
frontend_artifact := find_resource(
artifacts["artifacts"], "name", "frontend-build"
artifacts['artifacts'], 'name', 'frontend-build'
)
):
print("[ERROR] Cannot find frontend-build.zip attachment for current sha")
print('[ERROR] Cannot find frontend-build.zip attachment for current sha')
return
print(
f"Found artifact {frontend_artifact['name']} with id {frontend_artifact['id']} ({frontend_artifact['size_in_bytes']/1e6:.2f}MB)."