// Python 3.12 keywords - cannot be used as column IDs or table names
// https://docs.python.org/3/reference/lexical_analysis.html#keywords
export const PYTHON_KEYWORDS = new Set([
// Boolean and None
'False',
'None',
'True',
// Logical operators
'and',
'not',
'or',
// Control flow
'if',
'elif',
'else',
'for',
'while',
'break',
'continue',
'pass',
// Function and class definition
'def',
'class',
'lambda',
'return',
'yield',
// Exception handling
'try',
'except',
'finally',
'raise',
// Import and module
'import',
'from',
'as',
// Scope and context
'global',
'nonlocal',
'with',
// Async/await (Python 3.5+)
'async',
'await',
// Other
'assert',
'del',
'in',
'is'
])
export const GRIST_RESERVED_PREFIXES = ['gristHelper_', '_grist_'] as const
export function isPythonKeyword(identifier: string): boolean {
return PYTHON_KEYWORDS.has(identifier)
}
export function hasGristReservedPrefix(identifier: string): boolean {
return GRIST_RESERVED_PREFIXES.some((prefix) => identifier.startsWith(prefix))
}
export function getPythonKeywordError(identifier: string, type: 'column' | 'table'): string {
if (isPythonKeyword(identifier)) {
return (
`${type} ID "${identifier}" is a Python keyword and cannot be used. ` +
`Python keywords are reserved because Grist uses Python for formulas. ` +
`Suggestion: Use "${identifier}_col" or "${identifier}_field" instead.`
)
}
if (hasGristReservedPrefix(identifier)) {
const prefix = GRIST_RESERVED_PREFIXES.find((p) => identifier.startsWith(p))
return (
`${type} ID "${identifier}" starts with reserved prefix "${prefix}". ` +
`This prefix is used internally by Grist for system columns. ` +
`Suggestion: Use a different name without this prefix.`
)
}
return ''
}