mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-30 20:55:42 +00:00 
			
		
		
		
	[PUI] Add licenses texts to PUI (#6855)
* compile a license texts bundle * add backend license extraction on install * change path for licenses * add to gitignore * Add api to expose license paths * add texts * add frontend rendering of licensing files * Handle errors when fetching license information * Format backend packages.txt in json * Improved API rendering: - Handle file errors - Render as JSON object * Improve frontend modal rendering - Separate frontend / backend into tabs - Split packages into accordion * Generate JSON file for fronten deps * Fix rendering for frontend deps * Update src/frontend/src/components/modals/LicenseModal.tsx Co-authored-by: Lukas <76838159+wolflu05@users.noreply.github.com> * Update src/frontend/src/components/modals/LicenseModal.tsx Co-authored-by: Lukas <76838159+wolflu05@users.noreply.github.com> * make reading of licenses objects dynamic * remove unsued import * style fixes * style fixes * default to first value * use new syntax to call docker compose * merge fix * fix path * Roll back #6942 * Update qc_checks.yaml Run migration checks when requirements file changes --------- Co-authored-by: Oliver Walters <oliver.henry.walters@gmail.com> Co-authored-by: Lukas <76838159+wolflu05@users.noreply.github.com>
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 | ||||
|   | ||||
| @@ -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
									
									
									
									
									
								
							| @@ -244,6 +244,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