mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-11-03 22:55:43 +00:00 
			
		
		
		
	Merge branch 'master' of https://github.com/inventree/InvenTree into cov-use-xml
This commit is contained in:
		
							
								
								
									
										3
									
								
								.github/workflows/qc_checks.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.github/workflows/qc_checks.yaml
									
									
									
									
										vendored
									
									
								
							@@ -48,8 +48,9 @@ jobs:
 | 
			
		||||
            migrations:
 | 
			
		||||
              - '**/migrations/**'
 | 
			
		||||
              - '.github/workflows**'
 | 
			
		||||
              - 'src/backend/requirements.txt'
 | 
			
		||||
            api:
 | 
			
		||||
              - 'InvenTree/InvenTree/api_version.py'
 | 
			
		||||
              - 'src/backend/InvenTree/InvenTree/api_version.py'
 | 
			
		||||
            frontend:
 | 
			
		||||
              - 'src/frontend/**'
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -85,6 +85,7 @@ env/
 | 
			
		||||
 | 
			
		||||
# Locale stats file
 | 
			
		||||
src/backend/InvenTree/InvenTree/locale_stats.json
 | 
			
		||||
src/backend/InvenTree/InvenTree/licenses.txt
 | 
			
		||||
 | 
			
		||||
# node.js
 | 
			
		||||
node_modules/
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,9 @@
 | 
			
		||||
"""Main JSON interface views."""
 | 
			
		||||
 | 
			
		||||
import json
 | 
			
		||||
import logging
 | 
			
		||||
import sys
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.db import transaction
 | 
			
		||||
@@ -31,6 +34,60 @@ from .status import check_system_health, is_worker_running
 | 
			
		||||
from .version import inventreeApiText
 | 
			
		||||
from .views import AjaxView
 | 
			
		||||
 | 
			
		||||
logger = logging.getLogger('inventree')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class LicenseViewSerializer(serializers.Serializer):
 | 
			
		||||
    """Serializer for license information."""
 | 
			
		||||
 | 
			
		||||
    backend = serializers.CharField(help_text='Backend licenses texts', read_only=True)
 | 
			
		||||
    frontend = serializers.CharField(
 | 
			
		||||
        help_text='Frontend licenses texts', read_only=True
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class LicenseView(APIView):
 | 
			
		||||
    """Simple JSON endpoint for InvenTree license information."""
 | 
			
		||||
 | 
			
		||||
    permission_classes = [permissions.IsAuthenticated]
 | 
			
		||||
 | 
			
		||||
    def read_license_file(self, path: Path) -> list:
 | 
			
		||||
        """Extract license information from the provided file.
 | 
			
		||||
 | 
			
		||||
        Arguments:
 | 
			
		||||
            path: Path to the license file
 | 
			
		||||
 | 
			
		||||
        Returns: A list of items containing the license information
 | 
			
		||||
        """
 | 
			
		||||
        # Check if the file exists
 | 
			
		||||
        if not path.exists():
 | 
			
		||||
            logger.error("License file not found at '%s'", path)
 | 
			
		||||
            return []
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            data = json.loads(path.read_text())
 | 
			
		||||
        except json.JSONDecodeError as e:
 | 
			
		||||
            logger.exception("Failed to parse license file '%s': %s", path, e)
 | 
			
		||||
            return []
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            logger.exception("Exception while reading license file '%s': %s", path, e)
 | 
			
		||||
            return []
 | 
			
		||||
 | 
			
		||||
        # Ensure consistent string between backend and frontend licenses
 | 
			
		||||
        return [{key.lower(): value for key, value in entry.items()} for entry in data]
 | 
			
		||||
 | 
			
		||||
    @extend_schema(responses={200: OpenApiResponse(response=LicenseViewSerializer)})
 | 
			
		||||
    def get(self, request, *args, **kwargs):
 | 
			
		||||
        """Return information about the InvenTree server."""
 | 
			
		||||
        backend = Path(__file__).parent.joinpath('licenses.txt')
 | 
			
		||||
        frontend = Path(__file__).parent.parent.joinpath(
 | 
			
		||||
            'web/static/web/.vite/dependencies.json'
 | 
			
		||||
        )
 | 
			
		||||
        return JsonResponse({
 | 
			
		||||
            'backend': self.read_license_file(backend),
 | 
			
		||||
            'frontend': self.read_license_file(frontend),
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VersionViewSerializer(serializers.Serializer):
 | 
			
		||||
    """Serializer for a single version."""
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,14 @@
 | 
			
		||||
"""InvenTree API version information."""
 | 
			
		||||
 | 
			
		||||
# InvenTree API version
 | 
			
		||||
INVENTREE_API_VERSION = 185
 | 
			
		||||
INVENTREE_API_VERSION = 186
 | 
			
		||||
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
 | 
			
		||||
 | 
			
		||||
INVENTREE_API_TEXT = """
 | 
			
		||||
 | 
			
		||||
v186 - 2024-03-26 : https://github.com/inventree/InvenTree/pull/6855
 | 
			
		||||
    - Adds license information to the API
 | 
			
		||||
 | 
			
		||||
v185 - 2024-03-24 : https://github.com/inventree/InvenTree/pull/6836
 | 
			
		||||
    - Remove /plugin/activate endpoint
 | 
			
		||||
    - Update docstrings and typing for various API endpoints (no functional changes)
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,14 @@ from stock.urls import stock_urls
 | 
			
		||||
from web.urls import api_urls as web_api_urls
 | 
			
		||||
from web.urls import urlpatterns as platform_urls
 | 
			
		||||
 | 
			
		||||
from .api import APISearchView, InfoView, NotFoundView, VersionTextView, VersionView
 | 
			
		||||
from .api import (
 | 
			
		||||
    APISearchView,
 | 
			
		||||
    InfoView,
 | 
			
		||||
    LicenseView,
 | 
			
		||||
    NotFoundView,
 | 
			
		||||
    VersionTextView,
 | 
			
		||||
    VersionView,
 | 
			
		||||
)
 | 
			
		||||
from .magic_login import GetSimpleLoginView
 | 
			
		||||
from .social_auth_urls import (
 | 
			
		||||
    EmailListView,
 | 
			
		||||
@@ -99,6 +106,7 @@ apipatterns = [
 | 
			
		||||
        name='schema',
 | 
			
		||||
    ),
 | 
			
		||||
    # InvenTree information endpoints
 | 
			
		||||
    path('license/', LicenseView.as_view(), name='api-license'),  # license info
 | 
			
		||||
    path(
 | 
			
		||||
        'version-text', VersionTextView.as_view(), name='api-version-text'
 | 
			
		||||
    ),  # version text
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,15 @@ from stock.models import StockItem, StockLocation
 | 
			
		||||
class LocatePluginTests(InvenTreeAPITestCase):
 | 
			
		||||
    """Tests for LocateMixin."""
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        """Set up the test case."""
 | 
			
		||||
        super().setUp()
 | 
			
		||||
 | 
			
		||||
        # Activate plugin
 | 
			
		||||
        config = registry.get_plugin('samplelocate').plugin_config()
 | 
			
		||||
        config.active = True
 | 
			
		||||
        config.save()
 | 
			
		||||
 | 
			
		||||
    fixtures = ['category', 'part', 'location', 'stock']
 | 
			
		||||
 | 
			
		||||
    def test_installed(self):
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@ django-maintenance-mode                 # Shut down application while reloading
 | 
			
		||||
django-markdownify                      # Markdown rendering
 | 
			
		||||
django-mptt                             # Modified Preorder Tree Traversal
 | 
			
		||||
django-markdownify                      # Markdown rendering
 | 
			
		||||
django-money>=3.0.0,<3.5.0              # Django app for currency management # FIXED 2023-10-31 3.3.0 breaks due to https://github.com/django-money/django-money/issues/731
 | 
			
		||||
django-money>=3.0.0,<3.3.0              # Django app for currency management # FIXED 2023-10-31 3.3.0 breaks due to https://github.com/django-money/django-money/issues/731
 | 
			
		||||
django-mptt                             # Modified Preorder Tree Traversal
 | 
			
		||||
django-redis>=5.0.0                     # Redis integration
 | 
			
		||||
django-q2                               # Background task scheduling
 | 
			
		||||
@@ -41,6 +41,7 @@ gunicorn                                # Gunicorn web server
 | 
			
		||||
pdf2image                               # PDF to image conversion
 | 
			
		||||
pillow                                  # Image manipulation
 | 
			
		||||
pint==0.21                              # Unit conversion  # FIXED 2023-05-30 breaks tests https://github.com/matmair/InvenTree/actions/runs/5095665936/jobs/9160852560
 | 
			
		||||
pip-licenses                            # License information for installed packages
 | 
			
		||||
python-barcode[images]                  # Barcode generator
 | 
			
		||||
python-dotenv                           # Environment variable management
 | 
			
		||||
pyyaml>=6.0.1                           # YAML parsing
 | 
			
		||||
 
 | 
			
		||||
@@ -96,7 +96,7 @@ django-js-asset==2.2.0
 | 
			
		||||
    # via django-mptt
 | 
			
		||||
django-maintenance-mode==0.21.1
 | 
			
		||||
django-markdownify==0.9.3
 | 
			
		||||
django-money==3.4.1
 | 
			
		||||
django-money==3.2.0
 | 
			
		||||
django-mptt==0.16.0
 | 
			
		||||
django-otp==1.3.0
 | 
			
		||||
    # via django-allauth-2fa
 | 
			
		||||
@@ -230,6 +230,9 @@ pillow==10.2.0
 | 
			
		||||
    #   qrcode
 | 
			
		||||
    #   weasyprint
 | 
			
		||||
pint==0.21
 | 
			
		||||
pip-licenses==4.3.4
 | 
			
		||||
prettytable==3.10.0
 | 
			
		||||
    # via pip-licenses
 | 
			
		||||
protobuf==4.25.3
 | 
			
		||||
    # via
 | 
			
		||||
    #   googleapis-common-protos
 | 
			
		||||
@@ -329,6 +332,8 @@ urllib3==2.2.1
 | 
			
		||||
    #   dulwich
 | 
			
		||||
    #   requests
 | 
			
		||||
    #   sentry-sdk
 | 
			
		||||
wcwidth==0.2.13
 | 
			
		||||
    # via prettytable
 | 
			
		||||
weasyprint==61.2
 | 
			
		||||
    # via django-weasyprint
 | 
			
		||||
webencodings==0.5.1
 | 
			
		||||
 
 | 
			
		||||
@@ -65,6 +65,7 @@
 | 
			
		||||
        "@types/react-router-dom": "^5.3.3",
 | 
			
		||||
        "@vitejs/plugin-react": "^4.2.1",
 | 
			
		||||
        "babel-plugin-macros": "^3.1.0",
 | 
			
		||||
        "rollup-plugin-license": "^3.3.1",
 | 
			
		||||
        "nyc": "^15.1.0",
 | 
			
		||||
        "typescript": "^5.3.3",
 | 
			
		||||
        "vite": "^5.2.7",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										90
									
								
								src/frontend/src/components/modals/LicenseModal.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								src/frontend/src/components/modals/LicenseModal.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,90 @@
 | 
			
		||||
import { Trans, t } from '@lingui/macro';
 | 
			
		||||
import {
 | 
			
		||||
  Accordion,
 | 
			
		||||
  Alert,
 | 
			
		||||
  Divider,
 | 
			
		||||
  Group,
 | 
			
		||||
  LoadingOverlay,
 | 
			
		||||
  Space,
 | 
			
		||||
  Stack,
 | 
			
		||||
  Tabs,
 | 
			
		||||
  Text
 | 
			
		||||
} from '@mantine/core';
 | 
			
		||||
import { useQuery } from '@tanstack/react-query';
 | 
			
		||||
 | 
			
		||||
import { api } from '../../App';
 | 
			
		||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
 | 
			
		||||
import { apiUrl } from '../../states/ApiState';
 | 
			
		||||
 | 
			
		||||
export function LicenceView(entries: Readonly<any[]>) {
 | 
			
		||||
  return (
 | 
			
		||||
    <Stack spacing="xs">
 | 
			
		||||
      <Divider />
 | 
			
		||||
      {entries?.length > 0 && (
 | 
			
		||||
        <Accordion variant="contained" defaultValue="-">
 | 
			
		||||
          {entries?.map((entry: any, index: number) => (
 | 
			
		||||
            <Accordion.Item key={entry.name} value={`entry-${index}`}>
 | 
			
		||||
              <Accordion.Control>
 | 
			
		||||
                <Group position="apart" grow>
 | 
			
		||||
                  <Text>{entry.name}</Text>
 | 
			
		||||
                  <Text>{entry.license}</Text>
 | 
			
		||||
                  <Space />
 | 
			
		||||
                  <Text>{entry.version}</Text>
 | 
			
		||||
                </Group>
 | 
			
		||||
              </Accordion.Control>
 | 
			
		||||
              <Accordion.Panel style={{ whiteSpace: 'pre-line' }}>
 | 
			
		||||
                {entry.licensetext || t`No license text available`}
 | 
			
		||||
              </Accordion.Panel>
 | 
			
		||||
            </Accordion.Item>
 | 
			
		||||
          ))}
 | 
			
		||||
        </Accordion>
 | 
			
		||||
      )}
 | 
			
		||||
    </Stack>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function LicenseModal() {
 | 
			
		||||
  const { data, isFetching, isError } = useQuery({
 | 
			
		||||
    queryKey: ['license'],
 | 
			
		||||
    queryFn: () =>
 | 
			
		||||
      api
 | 
			
		||||
        .get(apiUrl(ApiEndpoints.license))
 | 
			
		||||
        .then((res) => res.data ?? {})
 | 
			
		||||
        .catch(() => {})
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Stack spacing="xs">
 | 
			
		||||
      <Divider />
 | 
			
		||||
      <LoadingOverlay visible={isFetching} />
 | 
			
		||||
      {isFetching && (
 | 
			
		||||
        <Text>
 | 
			
		||||
          <Trans>Loading license information</Trans>
 | 
			
		||||
        </Text>
 | 
			
		||||
      )}
 | 
			
		||||
      {isError ? (
 | 
			
		||||
        <Alert color="red" title={t`Error`}>
 | 
			
		||||
          <Text>
 | 
			
		||||
            <Trans>Failed to fetch license information</Trans>
 | 
			
		||||
          </Text>
 | 
			
		||||
        </Alert>
 | 
			
		||||
      ) : (
 | 
			
		||||
        <Tabs defaultValue={Object.keys(data)[0] ?? ''}>
 | 
			
		||||
          <Tabs.List>
 | 
			
		||||
            {Object.keys(data ?? {}).map((key) => (
 | 
			
		||||
              <Tabs.Tab key={key} value={key}>
 | 
			
		||||
                <Trans>{key} Packages</Trans>
 | 
			
		||||
              </Tabs.Tab>
 | 
			
		||||
            ))}
 | 
			
		||||
          </Tabs.List>
 | 
			
		||||
 | 
			
		||||
          {Object.keys(data ?? {}).map((key) => (
 | 
			
		||||
            <Tabs.Panel key={key} value={key}>
 | 
			
		||||
              {LicenceView(data[key] ?? [])}
 | 
			
		||||
            </Tabs.Panel>
 | 
			
		||||
          ))}
 | 
			
		||||
        </Tabs>
 | 
			
		||||
      )}
 | 
			
		||||
    </Stack>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
@@ -10,6 +10,7 @@ import { ModalsProvider } from '@mantine/modals';
 | 
			
		||||
import { Notifications } from '@mantine/notifications';
 | 
			
		||||
 | 
			
		||||
import { AboutInvenTreeModal } from '../components/modals/AboutInvenTreeModal';
 | 
			
		||||
import { LicenseModal } from '../components/modals/LicenseModal';
 | 
			
		||||
import { QrCodeModal } from '../components/modals/QrCodeModal';
 | 
			
		||||
import { ServerInfoModal } from '../components/modals/ServerInfoModal';
 | 
			
		||||
import { useLocalState } from '../states/LocalState';
 | 
			
		||||
@@ -65,7 +66,8 @@ export function ThemeContext({ children }: { children: JSX.Element }) {
 | 
			
		||||
          modals={{
 | 
			
		||||
            qr: QrCodeModal,
 | 
			
		||||
            info: ServerInfoModal,
 | 
			
		||||
            about: AboutInvenTreeModal
 | 
			
		||||
            about: AboutInvenTreeModal,
 | 
			
		||||
            license: LicenseModal
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
          {children}
 | 
			
		||||
 
 | 
			
		||||
@@ -96,8 +96,19 @@ function aboutInvenTree() {
 | 
			
		||||
    innerProps: {}
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
function licenseInfo() {
 | 
			
		||||
  return openContextModal({
 | 
			
		||||
    modal: 'license',
 | 
			
		||||
    title: (
 | 
			
		||||
      <StylishText size="xl">
 | 
			
		||||
        <Trans>License Information</Trans>
 | 
			
		||||
      </StylishText>
 | 
			
		||||
    ),
 | 
			
		||||
    size: 'xl',
 | 
			
		||||
    innerProps: {}
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO @matmair: Add the following pages and adjust the links
 | 
			
		||||
export const aboutLinks: DocumentationLinkItem[] = [
 | 
			
		||||
  {
 | 
			
		||||
    id: 'instance',
 | 
			
		||||
@@ -114,8 +125,7 @@ export const aboutLinks: DocumentationLinkItem[] = [
 | 
			
		||||
  {
 | 
			
		||||
    id: 'licenses',
 | 
			
		||||
    title: <Trans>Licenses</Trans>,
 | 
			
		||||
    description: <Trans>Licenses for packages used by InvenTree</Trans>,
 | 
			
		||||
    link: '/licenses',
 | 
			
		||||
    placeholder: true
 | 
			
		||||
    description: <Trans>Licenses for dependencies of the service</Trans>,
 | 
			
		||||
    action: licenseInfo
 | 
			
		||||
  }
 | 
			
		||||
];
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,7 @@ export enum ApiEndpoints {
 | 
			
		||||
  news = 'news/',
 | 
			
		||||
  global_status = 'generic/status/',
 | 
			
		||||
  version = 'version/',
 | 
			
		||||
  license = 'license/',
 | 
			
		||||
  sso_providers = 'auth/providers/',
 | 
			
		||||
  group_list = 'user/group/',
 | 
			
		||||
  owner_list = 'user/owner/',
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
import react from '@vitejs/plugin-react';
 | 
			
		||||
import { platform, release } from 'node:os';
 | 
			
		||||
import license from 'rollup-plugin-license';
 | 
			
		||||
import { defineConfig, splitVendorChunkPlugin } from 'vite';
 | 
			
		||||
import istanbul from 'vite-plugin-istanbul';
 | 
			
		||||
 | 
			
		||||
@@ -19,6 +20,19 @@ export default defineConfig({
 | 
			
		||||
      }
 | 
			
		||||
    }),
 | 
			
		||||
    splitVendorChunkPlugin(),
 | 
			
		||||
    license({
 | 
			
		||||
      sourcemap: true,
 | 
			
		||||
      thirdParty: {
 | 
			
		||||
        includePrivate: true,
 | 
			
		||||
        multipleVersions: true,
 | 
			
		||||
        output: {
 | 
			
		||||
          file: '../../InvenTree/web/static/web/.vite/dependencies.json',
 | 
			
		||||
          template(dependencies) {
 | 
			
		||||
            return JSON.stringify(dependencies);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }),
 | 
			
		||||
    istanbul({
 | 
			
		||||
      include: 'src/*',
 | 
			
		||||
      exclude: ['node_modules', 'test/'],
 | 
			
		||||
 
 | 
			
		||||
@@ -942,7 +942,7 @@
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280"
 | 
			
		||||
  integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==
 | 
			
		||||
 | 
			
		||||
"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14":
 | 
			
		||||
"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15":
 | 
			
		||||
  version "1.4.15"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
 | 
			
		||||
  integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
 | 
			
		||||
@@ -1769,6 +1769,11 @@ aria-hidden@^1.1.3:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    tslib "^2.0.0"
 | 
			
		||||
 | 
			
		||||
array-find-index@^1.0.2:
 | 
			
		||||
  version "1.0.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
 | 
			
		||||
  integrity sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==
 | 
			
		||||
 | 
			
		||||
asynckit@^0.4.0:
 | 
			
		||||
  version "0.4.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
 | 
			
		||||
@@ -2061,6 +2066,11 @@ commander@^10.0.0:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06"
 | 
			
		||||
  integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==
 | 
			
		||||
 | 
			
		||||
commenting@~1.1.0:
 | 
			
		||||
  version "1.1.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/commenting/-/commenting-1.1.0.tgz#fae14345c6437b8554f30bc6aa6c1e1633033590"
 | 
			
		||||
  integrity sha512-YeNK4tavZwtH7jEgK1ZINXzLKm6DZdEMfsaaieOsCAN0S8vsY7UeuO3Q7d/M018EFgE+IeUAuBOKkFccBZsUZA==
 | 
			
		||||
 | 
			
		||||
commondir@^1.0.1:
 | 
			
		||||
  version "1.0.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
 | 
			
		||||
@@ -2481,7 +2491,7 @@ glob-parent@~5.1.0:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    is-glob "^4.0.1"
 | 
			
		||||
 | 
			
		||||
glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
 | 
			
		||||
glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.2.0:
 | 
			
		||||
  version "7.2.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
 | 
			
		||||
  integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
 | 
			
		||||
@@ -2863,7 +2873,7 @@ lodash.sortby@^4.7.0:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
 | 
			
		||||
  integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==
 | 
			
		||||
 | 
			
		||||
lodash@^4.17.19, lodash@^4.17.21:
 | 
			
		||||
lodash@^4.17.19, lodash@^4.17.21, lodash@~4.17.21:
 | 
			
		||||
  version "4.17.21"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
 | 
			
		||||
  integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
 | 
			
		||||
@@ -2897,6 +2907,13 @@ lru-cache@^6.0.0:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    yallist "^4.0.0"
 | 
			
		||||
 | 
			
		||||
magic-string@~0.30.0:
 | 
			
		||||
  version "0.30.8"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.8.tgz#14e8624246d2bedba70d5462aa99ac9681844613"
 | 
			
		||||
  integrity sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@jridgewell/sourcemap-codec" "^1.4.15"
 | 
			
		||||
 | 
			
		||||
make-dir@^3.0.0, make-dir@^3.0.2:
 | 
			
		||||
  version "3.1.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
 | 
			
		||||
@@ -2958,6 +2975,16 @@ minimatch@^3.0.4, minimatch@^3.1.1:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    brace-expansion "^1.1.7"
 | 
			
		||||
 | 
			
		||||
mkdirp@~3.0.0:
 | 
			
		||||
  version "3.0.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50"
 | 
			
		||||
  integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==
 | 
			
		||||
 | 
			
		||||
moment@~2.30.1:
 | 
			
		||||
  version "2.30.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae"
 | 
			
		||||
  integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==
 | 
			
		||||
 | 
			
		||||
moo@^0.5.1:
 | 
			
		||||
  version "0.5.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.2.tgz#f9fe82473bc7c184b0d32e2215d3f6e67278733c"
 | 
			
		||||
@@ -3115,6 +3142,11 @@ package-hash@^4.0.0:
 | 
			
		||||
    lodash.flattendeep "^4.4.0"
 | 
			
		||||
    release-zalgo "^1.0.0"
 | 
			
		||||
 | 
			
		||||
package-name-regex@~2.0.6:
 | 
			
		||||
  version "2.0.6"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/package-name-regex/-/package-name-regex-2.0.6.tgz#b54bcb04d950e38082b7bb38fa558e01c1679334"
 | 
			
		||||
  integrity sha512-gFL35q7kbE/zBaPA3UKhp2vSzcPYx2ecbYuwv1ucE9Il6IIgBDweBlH8D68UFGZic2MkllKa2KHCfC1IQBQUYA==
 | 
			
		||||
 | 
			
		||||
parent-module@^1.0.0:
 | 
			
		||||
  version "1.0.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
 | 
			
		||||
@@ -3514,6 +3546,21 @@ rimraf@^3.0.0:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    glob "^7.1.3"
 | 
			
		||||
 | 
			
		||||
rollup-plugin-license@^3.3.1:
 | 
			
		||||
  version "3.3.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/rollup-plugin-license/-/rollup-plugin-license-3.3.1.tgz#73b68e33477524198d6f3f9befc905f59bf37c53"
 | 
			
		||||
  integrity sha512-lwZ/J8QgSnP0unVOH2FQuOBkeiyp0EBvrbYdNU33lOaYD8xP9Zoki+PGoWMD31EUq8Q07GGocSABTYlWMKkwuw==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    commenting "~1.1.0"
 | 
			
		||||
    glob "~7.2.0"
 | 
			
		||||
    lodash "~4.17.21"
 | 
			
		||||
    magic-string "~0.30.0"
 | 
			
		||||
    mkdirp "~3.0.0"
 | 
			
		||||
    moment "~2.30.1"
 | 
			
		||||
    package-name-regex "~2.0.6"
 | 
			
		||||
    spdx-expression-validate "~2.0.0"
 | 
			
		||||
    spdx-satisfies "~5.0.1"
 | 
			
		||||
 | 
			
		||||
rollup@^4.13.0:
 | 
			
		||||
  version "4.13.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.13.0.tgz#dd2ae144b4cdc2ea25420477f68d4937a721237a"
 | 
			
		||||
@@ -3643,6 +3690,54 @@ spawn-wrap@^2.0.0:
 | 
			
		||||
    signal-exit "^3.0.2"
 | 
			
		||||
    which "^2.0.1"
 | 
			
		||||
 | 
			
		||||
spdx-compare@^1.0.0:
 | 
			
		||||
  version "1.0.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/spdx-compare/-/spdx-compare-1.0.0.tgz#2c55f117362078d7409e6d7b08ce70a857cd3ed7"
 | 
			
		||||
  integrity sha512-C1mDZOX0hnu0ep9dfmuoi03+eOdDoz2yvK79RxbcrVEG1NO1Ph35yW102DHWKN4pk80nwCgeMmSY5L25VE4D9A==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    array-find-index "^1.0.2"
 | 
			
		||||
    spdx-expression-parse "^3.0.0"
 | 
			
		||||
    spdx-ranges "^2.0.0"
 | 
			
		||||
 | 
			
		||||
spdx-exceptions@^2.1.0:
 | 
			
		||||
  version "2.5.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66"
 | 
			
		||||
  integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==
 | 
			
		||||
 | 
			
		||||
spdx-expression-parse@^3.0.0:
 | 
			
		||||
  version "3.0.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679"
 | 
			
		||||
  integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    spdx-exceptions "^2.1.0"
 | 
			
		||||
    spdx-license-ids "^3.0.0"
 | 
			
		||||
 | 
			
		||||
spdx-expression-validate@~2.0.0:
 | 
			
		||||
  version "2.0.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/spdx-expression-validate/-/spdx-expression-validate-2.0.0.tgz#25c9408e1c63fad94fff5517bb7101ffcd23350b"
 | 
			
		||||
  integrity sha512-b3wydZLM+Tc6CFvaRDBOF9d76oGIHNCLYFeHbftFXUWjnfZWganmDmvtM5sm1cRwJc/VDBMLyGGrsLFd1vOxbg==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    spdx-expression-parse "^3.0.0"
 | 
			
		||||
 | 
			
		||||
spdx-license-ids@^3.0.0:
 | 
			
		||||
  version "3.0.17"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz#887da8aa73218e51a1d917502d79863161a93f9c"
 | 
			
		||||
  integrity sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==
 | 
			
		||||
 | 
			
		||||
spdx-ranges@^2.0.0:
 | 
			
		||||
  version "2.1.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/spdx-ranges/-/spdx-ranges-2.1.1.tgz#87573927ba51e92b3f4550ab60bfc83dd07bac20"
 | 
			
		||||
  integrity sha512-mcdpQFV7UDAgLpXEE/jOMqvK4LBoO0uTQg0uvXUewmEFhpiZx5yJSZITHB8w1ZahKdhfZqP5GPEOKLyEq5p8XA==
 | 
			
		||||
 | 
			
		||||
spdx-satisfies@~5.0.1:
 | 
			
		||||
  version "5.0.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/spdx-satisfies/-/spdx-satisfies-5.0.1.tgz#9feeb2524686c08e5f7933c16248d4fdf07ed6a6"
 | 
			
		||||
  integrity sha512-Nwor6W6gzFp8XX4neaKQ7ChV4wmpSh2sSDemMFSzHxpTw460jxFYeOn+jq4ybnSSw/5sc3pjka9MQPouksQNpw==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    spdx-compare "^1.0.0"
 | 
			
		||||
    spdx-expression-parse "^3.0.0"
 | 
			
		||||
    spdx-ranges "^2.0.0"
 | 
			
		||||
 | 
			
		||||
sprintf-js@~1.0.2:
 | 
			
		||||
  version "1.0.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								tasks.py
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								tasks.py
									
									
									
									
									
								
							@@ -247,6 +247,12 @@ def install(c, uv=False):
 | 
			
		||||
    # Run plugins install
 | 
			
		||||
    plugins(c, uv=uv)
 | 
			
		||||
 | 
			
		||||
    # Compile license information
 | 
			
		||||
    lic_path = managePyDir().joinpath('InvenTree', 'licenses.txt')
 | 
			
		||||
    c.run(
 | 
			
		||||
        f'pip-licenses --format=json --with-license-file --no-license-path > {lic_path}'
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@task(help={'tests': 'Set up test dataset at the end'})
 | 
			
		||||
def setup_dev(c, tests=False):
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user