2022-06-05 22:56:52 +00:00
""" Tasks for automating certain actions and interacting with InvenTree from the CLI. """
2021-04-25 01:29:07 +00:00
import json
2022-05-20 15:24:51 +00:00
import os
2021-11-24 22:07:48 +00:00
import pathlib
2021-11-24 23:46:23 +00:00
import re
2022-07-31 13:16:58 +00:00
import shutil
2022-05-20 15:24:51 +00:00
import sys
2022-07-27 00:42:34 +00:00
from pathlib import Path
2020-08-21 10:39:43 +00:00
2022-05-15 19:01:55 +00:00
from invoke import task
2021-04-11 04:05:55 +00:00
2021-04-01 13:06:17 +00:00
2020-08-21 11:08:04 +00:00
def apps ( ) :
2022-06-05 22:56:52 +00:00
""" Returns a list of installed apps. """
2020-08-21 11:08:04 +00:00
return [
' build ' ,
' common ' ,
' company ' ,
' label ' ,
' order ' ,
' part ' ,
' report ' ,
' stock ' ,
2020-10-03 13:45:24 +00:00
' users ' ,
2022-05-18 23:02:07 +00:00
' plugin ' ,
' InvenTree ' ,
2020-08-21 11:08:04 +00:00
]
2021-04-01 13:06:17 +00:00
2022-06-11 00:07:57 +00:00
def content_excludes ( ) :
""" Returns a list of content types to exclude from import/export. """
excludes = [
" contenttypes " ,
" auth.permission " ,
" authtoken.token " ,
" error_report.error " ,
" admin.logentry " ,
" django_q.schedule " ,
" django_q.task " ,
" django_q.ormq " ,
" users.owner " ,
" exchange.rate " ,
" exchange.exchangebackend " ,
" common.notificationentry " ,
2022-09-07 23:49:14 +00:00
" common.notificationmessage " ,
2022-06-11 00:07:57 +00:00
" user_sessions.session " ,
]
output = " "
for e in excludes :
output + = f " --exclude { e } "
return output
2022-07-27 00:42:34 +00:00
def localDir ( ) - > Path :
2022-06-01 15:37:39 +00:00
""" Returns the directory of *THIS* file.
2020-08-21 10:39:43 +00:00
Used to ensure that the various scripts always run
in the correct directory .
"""
2022-07-27 00:42:34 +00:00
return Path ( __file__ ) . parent . resolve ( )
2020-08-21 10:39:43 +00:00
2021-04-01 13:06:17 +00:00
2020-08-21 10:39:43 +00:00
def managePyDir ( ) :
2022-06-11 00:07:57 +00:00
""" Returns the directory of the manage.py file. """
2022-07-27 00:42:34 +00:00
return localDir ( ) . joinpath ( ' InvenTree ' )
2020-08-21 10:39:43 +00:00
2021-04-01 13:06:17 +00:00
2020-08-21 10:39:43 +00:00
def managePyPath ( ) :
2022-06-11 00:07:57 +00:00
""" Return the path of the manage.py file. """
2022-07-27 00:42:34 +00:00
return managePyDir ( ) . joinpath ( ' manage.py ' )
2020-08-21 10:39:43 +00:00
2021-04-01 13:06:17 +00:00
2022-06-05 22:56:52 +00:00
def manage ( c , cmd , pty : bool = False ) :
2022-06-01 15:37:39 +00:00
""" Runs a given command against django ' s " manage.py " script.
2020-08-21 10:39:43 +00:00
Args :
2022-06-05 22:56:52 +00:00
c : Command line context .
cmd : Django command to run .
pty ( bool , optional ) : Run an interactive session . Defaults to False .
2020-08-21 10:39:43 +00:00
"""
2022-07-08 00:41:42 +00:00
c . run ( ' cd " {path} " && python3 manage.py {cmd} ' . format (
2020-08-21 10:39:43 +00:00
path = managePyDir ( ) ,
cmd = cmd
2020-08-28 19:38:16 +00:00
) , pty = pty )
2020-08-21 10:39:43 +00:00
2022-05-20 11:37:12 +00:00
2022-06-11 00:07:57 +00:00
# Install tasks
2022-01-06 01:25:07 +00:00
@task
def plugins ( c ) :
2022-06-11 00:07:57 +00:00
""" Installs all plugins as specified in ' plugins.txt ' . """
2022-01-06 03:20:26 +00:00
from InvenTree . InvenTree . config import get_plugin_file
plugin_file = get_plugin_file ( )
print ( f " Installing plugin packages from ' { plugin_file } ' " )
2022-01-06 01:25:07 +00:00
# Install the plugins
2022-07-08 00:41:42 +00:00
c . run ( f " pip3 install --disable-pip-version-check -U -r ' { plugin_file } ' " )
2022-01-06 01:25:07 +00:00
2022-05-20 11:37:12 +00:00
2022-01-06 02:31:04 +00:00
@task ( post = [ plugins ] )
def install ( c ) :
2022-06-11 00:07:57 +00:00
""" Installs required python packages. """
2022-01-06 02:31:04 +00:00
print ( " Installing required python packages from ' requirements.txt ' " )
# Install required Python packages with PIP
2022-07-26 01:21:25 +00:00
c . run ( ' pip3 install --upgrade pip ' )
2022-07-08 00:41:42 +00:00
c . run ( ' pip3 install --no-cache-dir --disable-pip-version-check -U -r requirements.txt ' )
2022-01-06 02:31:04 +00:00
2022-05-20 11:37:12 +00:00
2022-07-29 04:58:54 +00:00
@task ( help = { ' tests ' : ' Set up test dataset at the end ' } )
def setup_dev ( c , tests = False ) :
2022-06-11 00:07:57 +00:00
""" Sets up everything needed for the dev enviroment. """
2022-06-28 12:12:00 +00:00
print ( " Installing required python packages from ' requirements-dev.txt ' " )
2022-05-15 22:15:25 +00:00
# Install required Python packages with PIP
2022-07-08 00:41:42 +00:00
c . run ( ' pip3 install -U -r requirements-dev.txt ' )
2022-05-15 22:15:25 +00:00
# Install pre-commit hook
2022-07-29 04:58:54 +00:00
print ( " Installing pre-commit for checks before git commits... " )
2022-05-15 22:15:25 +00:00
c . run ( ' pre-commit install ' )
2022-05-15 22:19:37 +00:00
# Update all the hooks
c . run ( ' pre-commit autoupdate ' )
2022-07-29 04:58:54 +00:00
print ( " pre-commit set up is done... " )
# Set up test-data if flag is set
if tests :
setup_test ( c )
2022-05-15 22:19:37 +00:00
2022-05-20 11:37:12 +00:00
2022-06-11 00:07:57 +00:00
# Setup / maintenance tasks
2020-08-21 11:24:02 +00:00
@task
def superuser ( c ) :
2022-06-01 15:37:39 +00:00
""" Create a superuser/admin account for the database. """
2020-08-28 19:38:16 +00:00
manage ( c , ' createsuperuser ' , pty = True )
2020-08-21 11:24:02 +00:00
2021-08-17 23:52:27 +00:00
2021-06-18 11:53:15 +00:00
@task
2021-10-04 21:05:26 +00:00
def rebuild_models ( c ) :
2022-06-11 00:07:57 +00:00
""" Rebuild database models with MPTT structures. """
2021-10-04 21:05:26 +00:00
manage ( c , " rebuild_models " , pty = True )
2021-06-18 11:53:15 +00:00
2021-11-19 20:50:41 +00:00
2021-10-04 21:05:26 +00:00
@task
def rebuild_thumbnails ( c ) :
2022-06-11 00:07:57 +00:00
""" Rebuild missing image thumbnails. """
2021-10-04 21:05:26 +00:00
manage ( c , " rebuild_thumbnails " , pty = True )
2021-08-17 23:52:27 +00:00
2021-11-19 20:50:41 +00:00
2021-07-31 23:06:17 +00:00
@task
def clean_settings ( c ) :
2022-06-11 00:07:57 +00:00
""" Clean the setting tables of old settings. """
2021-07-31 23:06:17 +00:00
manage ( c , " clean_settings " )
2021-11-19 20:50:41 +00:00
2021-12-11 22:07:37 +00:00
@task ( help = { ' mail ' : ' mail of the user whos MFA should be disabled ' } )
def remove_mfa ( c , mail = ' ' ) :
2022-06-11 00:07:57 +00:00
""" Remove MFA for a user. """
2021-12-11 22:07:37 +00:00
if not mail :
print ( ' You must provide a users mail ' )
manage ( c , f " remove_mfa { mail } " )
2020-08-21 10:39:43 +00:00
@task
2020-08-21 11:08:04 +00:00
def static ( c ) :
2022-06-01 15:37:39 +00:00
""" Copies required static files to the STATIC_ROOT directory, as per Django requirements. """
2021-04-20 11:37:19 +00:00
manage ( c , " prerender " )
2021-04-01 13:40:47 +00:00
manage ( c , " collectstatic --no-input " )
2020-08-21 11:08:04 +00:00
2021-08-19 21:36:54 +00:00
@task
def translate_stats ( c ) :
2022-06-01 15:37:39 +00:00
""" Collect translation stats.
2021-08-19 21:36:54 +00:00
The file generated from this is needed for the UI .
"""
2023-01-09 20:54:25 +00:00
# Recompile the translation files (.mo)
# We do not run 'invoke translate' here, as that will touch the source (.po) files too!
try :
manage ( c , ' compilemessages ' , pty = True )
except Exception :
print ( " WARNING: Translation files could not be compiled: " )
2022-07-27 00:42:34 +00:00
path = Path ( ' InvenTree ' , ' script ' , ' translation_stats.py ' )
2022-07-08 00:41:42 +00:00
c . run ( f ' python3 { path } ' )
2021-08-19 21:36:54 +00:00
@task ( post = [ translate_stats , static ] )
2020-08-21 11:13:28 +00:00
def translate ( c ) :
2022-06-11 00:07:57 +00:00
""" Rebuild translation source files. Advanced use only!
2020-08-21 11:13:28 +00:00
2022-05-02 00:53:43 +00:00
Note : This command should not be used on a local install ,
it is performed as part of the InvenTree translation toolchain .
2020-08-21 11:13:28 +00:00
"""
2020-10-24 11:13:40 +00:00
# Translate applicable .py / .html / .js files
2021-05-05 07:34:35 +00:00
manage ( c , " makemessages --all -e py,html,js --no-wrap " )
2020-08-21 11:13:28 +00:00
manage ( c , " compilemessages " )
2021-08-17 08:22:07 +00:00
2022-10-16 13:09:31 +00:00
@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 " )
@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 " )
2023-01-09 20:54:25 +00:00
@task ( post = [ rebuild_models , rebuild_thumbnails ] )
2022-06-11 00:07:57 +00:00
def migrate ( c ) :
""" Performs database migrations.
This is a critical step if the database schema have been altered !
"""
print ( " Running InvenTree database migrations... " )
print ( " ======================================== " )
manage ( c , " makemigrations " )
manage ( c , " migrate --noinput " )
manage ( c , " migrate --run-syncdb " )
manage ( c , " check " )
print ( " ======================================== " )
print ( " InvenTree database migrations completed! " )
2023-01-09 20:54:25 +00:00
@task (
post = [ static , clean_settings , translate_stats ] ,
help = {
' skip_backup ' : ' Skip database backup step (advanced users) '
}
)
def update ( c , skip_backup = False ) :
2022-06-01 15:37:39 +00:00
""" Update InvenTree installation.
2021-08-17 08:22:07 +00:00
This command should be invoked after source code has been updated ,
e . g . downloading new code from GitHub .
The following tasks are performed , in order :
- install
2023-01-09 20:54:25 +00:00
- backup ( optional )
2021-08-17 08:22:07 +00:00
- migrate
2021-08-19 21:37:38 +00:00
- static
2021-08-17 08:22:07 +00:00
- clean_settings
2022-06-11 00:07:57 +00:00
- translate_stats
2021-08-17 08:22:07 +00:00
"""
2023-01-09 20:54:25 +00:00
# Ensure required components are installed
install ( c )
if not skip_backup :
backup ( c )
# Perform database migrations
migrate ( c )
2021-08-17 08:22:07 +00:00
2022-06-11 00:07:57 +00:00
# Data tasks
2022-06-09 01:47:29 +00:00
@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) "
} )
def export_records ( c , filename = ' data.json ' , overwrite = False , include_permissions = False , delete_temp = False ) :
""" Export all database records to a file.
Write data to the file defined by filename .
If - - overwrite is not set , the user will be prompted about overwriting an existing files .
If - - include - permissions is not set , the file defined by filename will have permissions specified for a user or group removed .
If - - delete - temp is not set , the temporary file ( which includes permissions ) will not be deleted . This file is named filename . tmp
For historical reasons , calling this function without any arguments will thus result in two files :
- data . json : does not include permissions
- data . json . tmp : includes permissions
If you want the script to overwrite any existing files without asking , add argument - o / - - overwrite .
If you only want one file , add argument - d / - - delete - temp .
If you want only one file , with permissions , then additionally add argument - i / - - include - permissions
"""
2020-11-12 02:31:27 +00:00
# Get an absolute path to the file
if not os . path . isabs ( filename ) :
2022-07-27 00:42:34 +00:00
filename = localDir ( ) . joinpath ( filename ) . resolve ( )
2020-11-12 02:31:27 +00:00
print ( f " Exporting database records to file ' { filename } ' " )
2022-08-16 02:09:00 +00:00
if Path ( filename ) . is_file ( ) and overwrite is False :
2020-11-12 02:31:27 +00:00
response = input ( " 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 " )
2020-11-12 05:10:00 +00:00
sys . exit ( 1 )
2020-11-12 02:31:27 +00:00
2021-04-25 01:29:07 +00:00
tmpfile = f " { filename } .tmp "
2020-11-12 02:31:27 +00:00
2021-06-13 18:08:42 +00:00
cmd = f " dumpdata --indent 2 --output ' { tmpfile } ' { content_excludes ( ) } "
2021-04-25 01:29:07 +00:00
# Dump data to temporary file
2020-11-12 05:10:00 +00:00
manage ( c , cmd , pty = True )
2020-11-12 02:31:27 +00:00
2021-04-25 01:41:48 +00:00
print ( " Running data post-processing step... " )
2021-04-25 02:07:58 +00:00
# Post-process the file, to remove any "permissions" specified for a user or group
2021-04-25 01:29:07 +00:00
with open ( tmpfile , " r " ) as f_in :
data = json . loads ( f_in . read ( ) )
2022-06-09 01:47:29 +00:00
if include_permissions is False :
for entry in data :
if " model " in entry :
2021-05-06 10:11:38 +00:00
2022-06-09 01:47:29 +00:00
# Clear out any permissions specified for a group
if entry [ " model " ] == " auth.group " :
entry [ " fields " ] [ " permissions " ] = [ ]
2021-04-25 01:29:07 +00:00
2022-06-09 01:47:29 +00:00
# Clear out any permissions specified for a user
if entry [ " model " ] == " auth.user " :
entry [ " fields " ] [ " user_permissions " ] = [ ]
2021-04-25 01:29:07 +00:00
# Write the processed data to file
with open ( filename , " w " ) as f_out :
f_out . write ( json . dumps ( data , indent = 2 ) )
2021-04-25 02:07:58 +00:00
print ( " Data export completed " )
2022-06-09 01:47:29 +00:00
if delete_temp is True :
print ( " Removing temporary file " )
os . remove ( tmpfile )
2021-04-25 01:29:07 +00:00
2022-05-02 00:45:26 +00:00
@task ( help = { ' filename ' : ' Input filename ' , ' clear ' : ' Clear existing data before import ' } , post = [ rebuild_models , rebuild_thumbnails ] )
def import_records ( c , filename = ' data.json ' , clear = False ) :
2022-06-11 00:07:57 +00:00
""" Import database records from a file. """
2020-11-12 02:31:27 +00:00
# Get an absolute path to the supplied filename
if not os . path . isabs ( filename ) :
2022-07-27 00:42:34 +00:00
filename = localDir ( ) . joinpath ( filename )
2020-11-12 02:31:27 +00:00
if not os . path . exists ( filename ) :
print ( f " Error: File ' { filename } ' does not exist " )
2020-11-12 05:10:00 +00:00
sys . exit ( 1 )
2020-11-12 02:31:27 +00:00
2022-05-02 00:45:26 +00:00
if clear :
delete_data ( c , force = True )
2020-11-12 02:31:27 +00:00
print ( f " Importing database records from ' { filename } ' " )
2021-04-25 02:07:58 +00:00
# Pre-process the data, to remove any "permissions" specified for a user or group
tmpfile = f " { filename } .tmp.json "
with open ( filename , " r " ) as f_in :
data = json . loads ( f_in . read ( ) )
for entry in data :
if " model " in entry :
2021-05-06 10:11:38 +00:00
2021-04-25 02:07:58 +00:00
# Clear out any permissions specified for a group
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 " ] = [ ]
# Write the processed data to the tmp file
with open ( tmpfile , " w " ) as f_out :
f_out . write ( json . dumps ( data , indent = 2 ) )
2021-06-13 18:08:42 +00:00
cmd = f " loaddata ' { tmpfile } ' -i { content_excludes ( ) } "
2020-11-12 02:31:27 +00:00
manage ( c , cmd , pty = True )
2021-04-25 02:07:58 +00:00
print ( " Data import completed " )
2021-06-21 00:23:53 +00:00
@task
def delete_data ( c , force = False ) :
2022-06-01 15:37:39 +00:00
""" Delete all database records!
2021-06-21 00:23:53 +00:00
Warning : This will REALLY delete all records in the database ! !
"""
2022-05-20 11:37:12 +00:00
print ( " Deleting all data from InvenTree database... " )
2022-05-02 00:45:26 +00:00
2021-06-21 00:23:53 +00:00
if force :
2021-06-21 00:38:50 +00:00
manage ( c , ' flush --noinput ' )
2021-06-21 00:23:53 +00:00
else :
manage ( c , ' flush ' )
2021-10-04 21:05:26 +00:00
@task ( post = [ rebuild_models , rebuild_thumbnails ] )
2020-11-12 02:31:27 +00:00
def import_fixtures ( c ) :
2022-06-01 15:37:39 +00:00
""" Import fixture data into the database.
2020-11-12 02:31:27 +00:00
This command imports all existing test fixture data into the database .
Warning :
- Intended for testing / development only !
- Running this command may overwrite existing database data ! !
- Don ' t say you were not warned...
"""
fixtures = [
# Build model
' build ' ,
2021-05-06 10:11:38 +00:00
2020-11-12 03:48:57 +00:00
# Common models
' settings ' ,
2020-11-12 02:31:27 +00:00
# Company model
' company ' ,
' price_breaks ' ,
' supplier_part ' ,
# Order model
' order ' ,
# Part model
' bom ' ,
' category ' ,
' params ' ,
' part ' ,
' test_templates ' ,
# Stock model
' location ' ,
' stock_tests ' ,
' stock ' ,
2021-04-25 01:41:48 +00:00
# Users
' users '
2020-11-12 02:31:27 +00:00
]
command = ' loaddata ' + ' ' . join ( fixtures )
manage ( c , command , pty = True )
2021-02-10 15:55:04 +00:00
2022-06-11 00:07:57 +00:00
# Execution tasks
2022-07-20 01:44:25 +00:00
@task
def wait ( c ) :
""" Wait until the database connection is ready. """
return manage ( c , " wait_for_db " )
@task ( pre = [ wait ] , help = { ' address ' : ' Server address:port (default=127.0.0.1:8000) ' } )
2020-08-21 11:49:03 +00:00
def server ( c , address = " 127.0.0.1:8000 " ) :
2022-06-01 15:37:39 +00:00
""" Launch a (deveopment) server using Django ' s in-built webserver.
2020-08-21 11:49:03 +00:00
Note : This is * not * sufficient for a production installation .
"""
2020-09-28 11:26:40 +00:00
manage ( c , " runserver {address} " . format ( address = address ) , pty = True )
2021-08-28 10:59:41 +00:00
2022-06-11 00:07:57 +00:00
@task ( pre = [ wait ] )
def worker ( c ) :
""" Run the InvenTree background worker process. """
manage ( c , ' qcluster ' , pty = True )
# Testing tasks
@task
def render_js_files ( c ) :
""" Render templated javascript files (used for static testing). """
manage ( c , " test InvenTree.ci_render_js " )
2021-11-24 22:07:48 +00:00
@task ( post = [ translate_stats , static , server ] )
def test_translations ( c ) :
2022-06-11 00:07:57 +00:00
""" Add a fictional language to test if each component is ready for translations. """
2021-11-24 22:07:48 +00:00
import django
from django . conf import settings
# setup django
2022-07-27 00:42:34 +00:00
base_path = Path . cwd ( )
new_base_path = pathlib . Path ( ' InvenTree ' ) . resolve ( )
2021-11-24 22:07:48 +00:00
sys . path . append ( str ( new_base_path ) )
os . chdir ( new_base_path )
os . environ . setdefault ( ' DJANGO_SETTINGS_MODULE ' , ' InvenTree.settings ' )
django . setup ( )
# Add language
print ( " Add dummy language... " )
print ( " ======================================== " )
manage ( c , " makemessages -e py,html,js --no-wrap -l xx " )
# change translation
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 '
2021-11-24 23:46:23 +00:00
# complie regex
reg = re . compile (
2022-05-28 00:38:12 +00:00
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
2021-11-24 23:46:23 +00:00
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 :
for line in file_org :
2021-11-24 22:07:48 +00:00
if line . startswith ( ' msgstr " ' ) :
2021-11-24 23:46:23 +00:00
# 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
elif line . startswith ( ' msgid " ' ) :
last_string = last_string + line # a new translatable string starts -> start append
file_new . write ( line )
2021-11-24 22:07:48 +00:00
else :
2021-11-24 23:46:23 +00:00
if last_string :
last_string = last_string + line # a string is beeing read in -> continue appending
file_new . write ( line )
2021-11-24 22:07:48 +00:00
# change out translation files
2022-07-27 00:42:34 +00:00
file_path . rename ( str ( file_path ) + ' _old ' )
new_file_path . rename ( file_path )
2021-11-24 22:07:48 +00:00
# compile languages
print ( " Compile languages ... " )
print ( " ======================================== " )
manage ( c , " compilemessages " )
# reset cwd
os . chdir ( base_path )
# set env flag
os . environ [ ' TEST_TRANSLATIONS ' ] = ' True '
2021-08-28 10:59:41 +00:00
@task
2022-12-08 13:15:26 +00:00
def test ( c , disable_pty = False ) :
2022-06-11 00:07:57 +00:00
""" Run unit-tests for InvenTree codebase. """
# Run sanity check on the django install
manage ( c , ' check ' )
2022-12-08 13:15:26 +00:00
pty = not disable_pty
2022-06-11 00:07:57 +00:00
# Run coverage tests
2022-12-08 13:15:26 +00:00
manage ( c , ' test ' , pty = pty )
2022-06-11 00:07:57 +00:00
2022-11-14 04:58:22 +00:00
@task ( help = { ' dev ' : ' Set up development environment at the end ' } )
2022-07-30 00:34:16 +00:00
def setup_test ( c , ignore_update = False , dev = False , path = " inventree-demo-dataset " ) :
2022-07-21 01:41:42 +00:00
""" Setup a testing enviroment. """
2022-07-30 00:34:16 +00:00
2022-07-31 13:16:58 +00:00
from InvenTree . InvenTree . config import get_media_dir
2022-07-30 00:34:16 +00:00
if not ignore_update :
update ( c )
2022-07-21 01:41:42 +00:00
# Remove old data directory
2022-07-30 00:34:16 +00:00
if os . path . exists ( path ) :
print ( " Removing old data ... " )
c . run ( f ' rm { path } -r ' )
2022-07-21 01:41:42 +00:00
# Get test data
2022-07-30 00:34:16 +00:00
print ( " Cloning demo dataset ... " )
c . run ( f ' git clone https://github.com/inventree/demo-dataset { path } -v ' )
2022-07-29 04:58:54 +00:00
print ( " ======================================== " )
# Make sure migrations are done - might have just deleted sqlite database
2022-07-30 00:34:16 +00:00
if not ignore_update :
migrate ( c )
2022-07-21 01:41:42 +00:00
# Load data
2022-07-31 13:16:58 +00:00
print ( " Loading database records ... " )
2022-07-30 00:34:16 +00:00
import_records ( c , filename = f ' { path } /inventree_data.json ' , clear = True )
2022-07-31 13:16:58 +00:00
# Copy media files
print ( " Copying media files ... " )
src = Path ( path ) . joinpath ( ' media ' ) . resolve ( )
dst = get_media_dir ( )
shutil . copytree ( src , dst , dirs_exist_ok = True )
2022-12-08 13:15:26 +00:00
print ( " Done setting up test environment... " )
2022-07-29 04:58:54 +00:00
print ( " ======================================== " )
# Set up development setup if flag is set
if dev :
setup_dev ( c )
2022-07-21 01:41:42 +00:00
2022-06-11 00:07:57 +00:00
@task
def coverage ( c ) :
""" Run code-coverage of the InvenTree codebase, using the ' coverage ' code-analysis tools.
Generates a code coverage report ( available in the htmlcov directory )
"""
# Run sanity check on the django install
manage ( c , ' check ' )
# Run coverage tests
c . run ( ' coverage run {manage} test {apps} ' . format (
manage = managePyPath ( ) ,
apps = ' ' . join ( apps ( ) )
) )
# Generate coverage report
c . run ( ' coverage html ' )