From 861b1c31ef93c2c3c5b15cc7fbd6a5b36348882e Mon Sep 17 00:00:00 2001 From: philippe Date: Wed, 2 Jul 2025 09:51:29 -0400 Subject: [PATCH 1/4] Add filepath to extract-meta errors --- dash/extract-meta.js | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/dash/extract-meta.js b/dash/extract-meta.js index 3427ef81d3..997616b031 100755 --- a/dash/extract-meta.js +++ b/dash/extract-meta.js @@ -47,6 +47,7 @@ function getTsConfigCompilerOptions() { let failedBuild = false; const excludedDocProps = ['setProps', 'id', 'className', 'style']; +const errorFiles = []; const isOptional = prop => (prop.getFlags() & ts.SymbolFlags.Optional) !== 0; @@ -91,14 +92,18 @@ function logError(error, filePath) { if (error instanceof Error) { process.stderr.write(error.stack + '\n'); } + if (filePath && !errorFiles.includes(filePath)) { + errorFiles.push(filePath); + } } -function isReservedPropName(propName) { +function isReservedPropName(propName, filepath) { reservedPatterns.forEach(reservedPattern => { if (reservedPattern.test(propName)) { - process.stderr.write( - `\nERROR: "${propName}" matches reserved word ` + - `pattern: ${reservedPattern.toString()}\n` + logError( + `\nERROR:${filepath}: "${propName}" matches reserved word ` + + `pattern: ${reservedPattern.toString()}\n`, + filepath ); failedBuild = true; } @@ -140,7 +145,7 @@ function parseJSX(filepath) { const src = fs.readFileSync(filepath); const doc = reactDocs.parse(src); Object.keys(doc.props).forEach(propName => - isReservedPropName(propName) + isReservedPropName(propName, filepath) ); docstringWarning(doc); return doc; @@ -152,6 +157,7 @@ function parseJSX(filepath) { function gatherComponents(sources, components = {}) { const names = []; const filepaths = []; + let currentFilepath = ""; // For debugging purposes. const gather = filepath => { if (ignorePattern && ignorePattern.test(filepath)) { @@ -166,8 +172,9 @@ function gatherComponents(sources, components = {}) { filepaths.push(filepath); names.push(name); } catch (err) { - process.stderr.write( - `ERROR: Invalid component file ${filepath}: ${err}` + logError( + `ERROR: Invalid component file ${filepath}: ${err}`, + filepath, ); } } @@ -594,7 +601,7 @@ function gatherComponents(sources, components = {}) { properties.forEach(prop => { const name = prop.getName(); - if (isReservedPropName(name)) { + if (isReservedPropName(name, currentFilepath)) { return; } const propType = checker.getTypeOfSymbolAtLocation( @@ -660,6 +667,7 @@ function gatherComponents(sources, components = {}) { }; zipArrays(filepaths, names).forEach(([filepath, name]) => { + currentFilepath = filepath; const source = program.getSourceFile(filepath); const moduleSymbol = checker.getSymbolAtLocation(source); const exports = checker.getExportsOfModule(moduleSymbol); @@ -791,5 +799,9 @@ if (!failedBuild) { process.stdout.write(JSON.stringify(metadata, null, 2)); } else { logError('extract-meta failed'); + logError('Check these files for errors:') + errorFiles.forEach((errorFile) => { + logError(`Error in: ${errorFile}`) + }) process.exit(1); } From ed05ef88fa13bfb889183d49fb08f70b5271de5b Mon Sep 17 00:00:00 2001 From: philippe Date: Thu, 3 Jul 2025 08:29:32 -0400 Subject: [PATCH 2/4] add base prop to extract meta error --- dash/extract-meta.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/dash/extract-meta.js b/dash/extract-meta.js index 997616b031..57fc92419d 100755 --- a/dash/extract-meta.js +++ b/dash/extract-meta.js @@ -97,11 +97,11 @@ function logError(error, filePath) { } } -function isReservedPropName(propName, filepath) { +function isReservedPropName(propName, filepath, baseProp) { reservedPatterns.forEach(reservedPattern => { if (reservedPattern.test(propName)) { logError( - `\nERROR:${filepath}: "${propName}" matches reserved word ` + + `\nERROR:${filepath}: "${baseProp ? baseProp + "." : ""}${propName}" matches reserved word ` + `pattern: ${reservedPattern.toString()}\n`, filepath ); @@ -157,7 +157,7 @@ function parseJSX(filepath) { function gatherComponents(sources, components = {}) { const names = []; const filepaths = []; - let currentFilepath = ""; // For debugging purposes. + let currentFilepath = "", currentBasePropName = ""; // For debugging purposes. const gather = filepath => { if (ignorePattern && ignorePattern.test(filepath)) { @@ -601,7 +601,11 @@ function gatherComponents(sources, components = {}) { properties.forEach(prop => { const name = prop.getName(); - if (isReservedPropName(name, currentFilepath)) { + + if (parentType === null) { + currentBasePropName = name; + } + if (isReservedPropName(name, currentFilepath, currentBasePropName)) { return; } const propType = checker.getTypeOfSymbolAtLocation( From 6a04b6ba1d2d07bc562e70a466ff4a1c08085b0a Mon Sep 17 00:00:00 2001 From: philippe Date: Thu, 3 Jul 2025 09:17:51 -0400 Subject: [PATCH 3/4] remove setuptools pkg_resources usage --- dash/_hooks.py | 2 +- dash/dash.py | 2 +- dash/development/component_generator.py | 4 ++-- requirements/install.txt | 1 - 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/dash/_hooks.py b/dash/_hooks.py index 058f0f7e12..7a0c5c8f83 100644 --- a/dash/_hooks.py +++ b/dash/_hooks.py @@ -244,7 +244,7 @@ def get_hooks(cls, hook: str): return cls.hooks.get_hooks(hook) @classmethod - def register_setuptools(cls): + def register_plugins(cls): if cls._registered: # Only have to register once. return diff --git a/dash/dash.py b/dash/dash.py index cf6d0f43f1..1dddf541a2 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -642,7 +642,7 @@ def _setup_hooks(self): from ._hooks import HooksManager self._hooks = HooksManager - self._hooks.register_setuptools() + self._hooks.register_plugins() for setup in self._hooks.get_hooks("setup"): setup(self) diff --git a/dash/development/component_generator.py b/dash/development/component_generator.py index 276dbfb0f5..4d18353bd4 100644 --- a/dash/development/component_generator.py +++ b/dash/development/component_generator.py @@ -8,7 +8,7 @@ import argparse import shutil import functools -import pkg_resources +from importlib import resources import yaml from ._r_components_generation import write_class_file @@ -57,7 +57,7 @@ def generate_components( is_windows = sys.platform == "win32" - extract_path = pkg_resources.resource_filename("dash", "extract-meta.js") + extract_path = os.path.join(str(resources.files("dash")), "extract-meta.js") reserved_patterns = "|".join(f"^{p}$" for p in reserved_words) diff --git a/requirements/install.txt b/requirements/install.txt index df0e1299e3..d5cbde53ca 100644 --- a/requirements/install.txt +++ b/requirements/install.txt @@ -6,4 +6,3 @@ typing_extensions>=4.1.1 requests retrying nest-asyncio -setuptools From e6ed22e8ac0c0828f41d6628bccc9e0370211956 Mon Sep 17 00:00:00 2001 From: philippe Date: Mon, 7 Jul 2025 11:25:16 -0400 Subject: [PATCH 4/4] fix build for 3.8 --- dash/development/component_generator.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dash/development/component_generator.py b/dash/development/component_generator.py index 4d18353bd4..a08295d3cf 100644 --- a/dash/development/component_generator.py +++ b/dash/development/component_generator.py @@ -57,7 +57,9 @@ def generate_components( is_windows = sys.platform == "win32" - extract_path = os.path.join(str(resources.files("dash")), "extract-meta.js") + # Python 3.8 compatible approach using importlib.resources.path() + with resources.path("dash", "extract-meta.js") as resource_path: + extract_path = str(resource_path) reserved_patterns = "|".join(f"^{p}$" for p in reserved_words)