mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) Add 'value' to trigger formula autocomplete
Summary: API signature for autocomplete updated to add column ID, which is necessary for exposing correct types for 'value'. Test Plan: Unit tests. Reviewers: alexmojaki Reviewed By: alexmojaki Subscribers: jarek, alexmojaki Differential Revision: https://phab.getgrist.com/D2896
This commit is contained in:
parent
8524b4f791
commit
9592e3610b
@ -20,12 +20,14 @@ var modelUtil = require('../models/modelUtil');
|
|||||||
* element. Both desiredSize and the return value are objects with 'width' and 'height' members.
|
* element. Both desiredSize and the return value are objects with 'width' and 'height' members.
|
||||||
*/
|
*/
|
||||||
function AceEditor(options) {
|
function AceEditor(options) {
|
||||||
|
options = options || {};
|
||||||
// Observable subscription is not created until the dom is built
|
// Observable subscription is not created until the dom is built
|
||||||
this.observable = (options && options.observable) || null;
|
this.observable = options.observable || null;
|
||||||
this.saveValueOnBlurEvent = !(options && (options.saveValueOnBlurEvent === false));
|
this.saveValueOnBlurEvent = !(options.saveValueOnBlurEvent === false);
|
||||||
this.calcSize = (options && options.calcSize) || ((elem, size) => size);
|
this.calcSize = options.calcSize || ((_elem, size) => size);
|
||||||
this.gristDoc = (options && options.gristDoc) || null;
|
this.gristDoc = options.gristDoc || null;
|
||||||
this.editorState = (options && options.editorState) || null;
|
this.field = options.field || null;
|
||||||
|
this.editorState = options.editorState || null;
|
||||||
this._readonly = options.readonly || false;
|
this._readonly = options.readonly || false;
|
||||||
|
|
||||||
this.editor = null;
|
this.editor = null;
|
||||||
@ -183,10 +185,11 @@ AceEditor.prototype.setFontSize = function(pxVal) {
|
|||||||
AceEditor.prototype._setup = function() {
|
AceEditor.prototype._setup = function() {
|
||||||
// Standard editor setup
|
// Standard editor setup
|
||||||
this.editor = this.autoDisposeWith('destroy', ace.edit(this.editorDom));
|
this.editor = this.autoDisposeWith('destroy', ace.edit(this.editorDom));
|
||||||
if (this.gristDoc) {
|
if (this.gristDoc && this.field) {
|
||||||
const getSuggestions = (prefix) => {
|
const getSuggestions = (prefix) => {
|
||||||
const tableId = this.gristDoc.viewModel.activeSection().table().tableId();
|
const tableId = this.gristDoc.viewModel.activeSection().table().tableId();
|
||||||
return this.gristDoc.docComm.autocomplete(prefix, tableId);
|
const columnId = this.field.column().colId();
|
||||||
|
return this.gristDoc.docComm.autocomplete(prefix, tableId, columnId);
|
||||||
};
|
};
|
||||||
setupAceEditorCompletions(this.editor, {getSuggestions});
|
setupAceEditorCompletions(this.editor, {getSuggestions});
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ export class FormulaEditor extends NewBaseEditor {
|
|||||||
this._formulaEditor = AceEditor.create({
|
this._formulaEditor = AceEditor.create({
|
||||||
// A bit awkward, but we need to assume calcSize is not used until attach() has been called
|
// A bit awkward, but we need to assume calcSize is not used until attach() has been called
|
||||||
// and _editorPlacement created.
|
// and _editorPlacement created.
|
||||||
|
field: options.field,
|
||||||
calcSize: this._calcSize.bind(this),
|
calcSize: this._calcSize.bind(this),
|
||||||
gristDoc: options.gristDoc,
|
gristDoc: options.gristDoc,
|
||||||
saveValueOnBlurEvent: !options.readonly,
|
saveValueOnBlurEvent: !options.readonly,
|
||||||
|
@ -174,9 +174,9 @@ export interface ActiveDocAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Find and return a list of auto-complete suggestions that start with `txt`, when editing a
|
* Find and return a list of auto-complete suggestions that start with `txt`, when editing a
|
||||||
* formula in table `tableId`.
|
* formula in table `tableId` and column `columnId`.
|
||||||
*/
|
*/
|
||||||
autocomplete(txt: string, tableId: string): Promise<string[]>;
|
autocomplete(txt: string, tableId: string, columnId: string): Promise<string[]>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the current instance from the doc.
|
* Removes the current instance from the doc.
|
||||||
|
@ -836,11 +836,11 @@ export class ActiveDoc extends EventEmitter {
|
|||||||
docSession.linkId = 0;
|
docSession.linkId = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async autocomplete(docSession: DocSession, txt: string, tableId: string): Promise<string[]> {
|
public async autocomplete(docSession: DocSession, txt: string, tableId: string, columnId: string): Promise<string[]> {
|
||||||
// Autocompletion can leak names of tables and columns.
|
// Autocompletion can leak names of tables and columns.
|
||||||
if (!await this._granularAccess.canScanData(docSession)) { return []; }
|
if (!await this._granularAccess.canScanData(docSession)) { return []; }
|
||||||
await this.waitForInitialization();
|
await this.waitForInitialization();
|
||||||
return this._pyCall('autocomplete', txt, tableId);
|
return this._pyCall('autocomplete', txt, tableId, columnId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public fetchURL(docSession: DocSession, url: string): Promise<UploadResult> {
|
public fetchURL(docSession: DocSession, url: string): Promise<UploadResult> {
|
||||||
|
@ -60,6 +60,9 @@ class AutocompleteContext(object):
|
|||||||
lower += '*'
|
lower += '*'
|
||||||
self._lowercase[lower] = key
|
self._lowercase[lower] = key
|
||||||
|
|
||||||
|
# Lowercase 'value' is used in trigger formulas, and is not the same as 'VALUE'.
|
||||||
|
self._lowercase.pop('value', None)
|
||||||
|
|
||||||
# Add the lowercase names to the context, and to the detailed completions in _functions.
|
# Add the lowercase names to the context, and to the detailed completions in _functions.
|
||||||
for lower, key in six.iteritems(self._lowercase):
|
for lower, key in six.iteritems(self._lowercase):
|
||||||
self._context[lower] = self._context[key]
|
self._context[lower] = self._context[key]
|
||||||
|
@ -1281,7 +1281,7 @@ class Engine(object):
|
|||||||
if not self._compute_stack:
|
if not self._compute_stack:
|
||||||
self._bring_lookups_up_to_date(doc_action)
|
self._bring_lookups_up_to_date(doc_action)
|
||||||
|
|
||||||
def autocomplete(self, txt, table_id):
|
def autocomplete(self, txt, table_id, column_id):
|
||||||
"""
|
"""
|
||||||
Return a list of suggested completions of the python fragment supplied.
|
Return a list of suggested completions of the python fragment supplied.
|
||||||
"""
|
"""
|
||||||
@ -1295,6 +1295,13 @@ class Engine(object):
|
|||||||
context = self._autocomplete_context.get_context()
|
context = self._autocomplete_context.get_context()
|
||||||
context['rec'] = table.sample_record
|
context['rec'] = table.sample_record
|
||||||
|
|
||||||
|
# Remove values from the context that need to be recomputed.
|
||||||
|
context.pop('value', None)
|
||||||
|
|
||||||
|
column = table.get_column(column_id) if table.has_column(column_id) else None
|
||||||
|
if column and not column.is_formula():
|
||||||
|
context['value'] = column.sample_value()
|
||||||
|
|
||||||
completer = rlcompleter.Completer(context)
|
completer = rlcompleter.Completer(context)
|
||||||
results = []
|
results = []
|
||||||
at = 0
|
at = 0
|
||||||
|
@ -73,8 +73,8 @@ def run(sandbox):
|
|||||||
return eng.acl_split(action_group).to_json_obj()
|
return eng.acl_split(action_group).to_json_obj()
|
||||||
|
|
||||||
@export
|
@export
|
||||||
def autocomplete(txt, table_id):
|
def autocomplete(txt, table_id, column_id):
|
||||||
return eng.autocomplete(txt, table_id)
|
return eng.autocomplete(txt, table_id, column_id)
|
||||||
|
|
||||||
@export
|
@export
|
||||||
def find_col_from_values(values, n, opt_table_id):
|
def find_col_from_values(values, n, opt_table_id):
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import testsamples
|
import testsamples
|
||||||
import test_engine
|
import test_engine
|
||||||
|
from schema import RecalcWhen
|
||||||
|
|
||||||
class TestCompletion(test_engine.EngineTestCase):
|
class TestCompletion(test_engine.EngineTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -12,19 +13,45 @@ class TestCompletion(test_engine.EngineTestCase):
|
|||||||
self.add_column('Students', 'lastVisit', type='DateTime:America/New_York')
|
self.add_column('Students', 'lastVisit', type='DateTime:America/New_York')
|
||||||
self.add_column('Schools', 'yearFounded', type='Int')
|
self.add_column('Schools', 'yearFounded', type='Int')
|
||||||
self.add_column('Schools', 'budget', type='Numeric')
|
self.add_column('Schools', 'budget', type='Numeric')
|
||||||
|
self.add_column('Schools', 'lastModified',
|
||||||
|
type="DateTime:America/Los_Angeles", isFormula=False, formula="NOW()",
|
||||||
|
recalcWhen=RecalcWhen.MANUAL_UPDATES
|
||||||
|
)
|
||||||
|
self.add_column('Schools', 'lastModifier',
|
||||||
|
type="Text", isFormula=False, formula="foo@getgrist.com",
|
||||||
|
recalcWhen=RecalcWhen.MANUAL_UPDATES
|
||||||
|
)
|
||||||
|
|
||||||
def test_keyword(self):
|
def test_keyword(self):
|
||||||
self.assertEqual(self.engine.autocomplete("for", "Address"),
|
self.assertEqual(self.engine.autocomplete("for", "Address", "city"),
|
||||||
["for", "format("])
|
["for", "format("])
|
||||||
|
|
||||||
def test_grist(self):
|
def test_grist(self):
|
||||||
self.assertEqual(self.engine.autocomplete("gri", "Address"),
|
self.assertEqual(self.engine.autocomplete("gri", "Address", "city"),
|
||||||
["grist"])
|
["grist"])
|
||||||
|
|
||||||
|
def test_value(self):
|
||||||
|
# Should only appear if column exists and is a trigger formula.
|
||||||
|
self.assertEqual(self.engine.autocomplete("val", "Schools", "lastModified"),
|
||||||
|
["value"])
|
||||||
|
self.assertEqual(self.engine.autocomplete("val", "Students", "schoolCities"),
|
||||||
|
[])
|
||||||
|
self.assertEqual(self.engine.autocomplete("val", "Students", "nonexistentColumn"),
|
||||||
|
[])
|
||||||
|
self.assertEqual(self.engine.autocomplete("valu", "Schools", "lastModifier"),
|
||||||
|
["value"])
|
||||||
|
# Should have same type as column.
|
||||||
|
self.assertGreaterEqual(set(self.engine.autocomplete("value.", "Schools", "lastModifier")),
|
||||||
|
{'value.startswith(', 'value.replace(', 'value.title('})
|
||||||
|
self.assertGreaterEqual(set(self.engine.autocomplete("value.", "Schools", "lastModified")),
|
||||||
|
{'value.month', 'value.strftime(', 'value.replace('})
|
||||||
|
self.assertGreaterEqual(set(self.engine.autocomplete("value.m", "Schools", "lastModified")),
|
||||||
|
{'value.month', 'value.minute'})
|
||||||
|
|
||||||
def test_function(self):
|
def test_function(self):
|
||||||
self.assertEqual(self.engine.autocomplete("MEDI", "Address"),
|
self.assertEqual(self.engine.autocomplete("MEDI", "Address", "city"),
|
||||||
[('MEDIAN', '(value, *more_values)', True)])
|
[('MEDIAN', '(value, *more_values)', True)])
|
||||||
self.assertEqual(self.engine.autocomplete("ma", "Address"), [
|
self.assertEqual(self.engine.autocomplete("ma", "Address", "city"), [
|
||||||
('MAX', '(value, *more_values)', True),
|
('MAX', '(value, *more_values)', True),
|
||||||
('MAXA', '(value, *more_values)', True),
|
('MAXA', '(value, *more_values)', True),
|
||||||
'map(',
|
'map(',
|
||||||
@ -33,30 +60,30 @@ class TestCompletion(test_engine.EngineTestCase):
|
|||||||
])
|
])
|
||||||
|
|
||||||
def test_member(self):
|
def test_member(self):
|
||||||
self.assertEqual(self.engine.autocomplete("datetime.tz", "Address"),
|
self.assertEqual(self.engine.autocomplete("datetime.tz", "Address", "city"),
|
||||||
["datetime.tzinfo("])
|
["datetime.tzinfo("])
|
||||||
|
|
||||||
def test_case_insensitive(self):
|
def test_case_insensitive(self):
|
||||||
self.assertEqual(self.engine.autocomplete("medi", "Address"),
|
self.assertEqual(self.engine.autocomplete("medi", "Address", "city"),
|
||||||
[('MEDIAN', '(value, *more_values)', True)])
|
[('MEDIAN', '(value, *more_values)', True)])
|
||||||
self.assertEqual(self.engine.autocomplete("std", "Address"), [
|
self.assertEqual(self.engine.autocomplete("std", "Address", "city"), [
|
||||||
('STDEV', '(value, *more_values)', True),
|
('STDEV', '(value, *more_values)', True),
|
||||||
('STDEVA', '(value, *more_values)', True),
|
('STDEVA', '(value, *more_values)', True),
|
||||||
('STDEVP', '(value, *more_values)', True),
|
('STDEVP', '(value, *more_values)', True),
|
||||||
('STDEVPA', '(value, *more_values)', True)
|
('STDEVPA', '(value, *more_values)', True)
|
||||||
])
|
])
|
||||||
self.assertEqual(self.engine.autocomplete("stu", "Address"),
|
self.assertEqual(self.engine.autocomplete("stu", "Address", "city"),
|
||||||
["Students"])
|
["Students"])
|
||||||
|
|
||||||
# Add a table name whose lowercase version conflicts with a builtin.
|
# Add a table name whose lowercase version conflicts with a builtin.
|
||||||
self.apply_user_action(['AddTable', 'Max', []])
|
self.apply_user_action(['AddTable', 'Max', []])
|
||||||
self.assertEqual(self.engine.autocomplete("max", "Address"), [
|
self.assertEqual(self.engine.autocomplete("max", "Address", "city"), [
|
||||||
('MAX', '(value, *more_values)', True),
|
('MAX', '(value, *more_values)', True),
|
||||||
('MAXA', '(value, *more_values)', True),
|
('MAXA', '(value, *more_values)', True),
|
||||||
'Max',
|
'Max',
|
||||||
'max(',
|
'max(',
|
||||||
])
|
])
|
||||||
self.assertEqual(self.engine.autocomplete("MAX", "Address"), [
|
self.assertEqual(self.engine.autocomplete("MAX", "Address", "city"), [
|
||||||
('MAX', '(value, *more_values)', True),
|
('MAX', '(value, *more_values)', True),
|
||||||
('MAXA', '(value, *more_values)', True),
|
('MAXA', '(value, *more_values)', True),
|
||||||
])
|
])
|
||||||
@ -64,89 +91,93 @@ class TestCompletion(test_engine.EngineTestCase):
|
|||||||
|
|
||||||
def test_suggest_globals_and_tables(self):
|
def test_suggest_globals_and_tables(self):
|
||||||
# Should suggest globals and table names.
|
# Should suggest globals and table names.
|
||||||
self.assertEqual(self.engine.autocomplete("ME", "Address"),
|
self.assertEqual(self.engine.autocomplete("ME", "Address", "city"),
|
||||||
[('MEDIAN', '(value, *more_values)', True)])
|
[('MEDIAN', '(value, *more_values)', True)])
|
||||||
self.assertEqual(self.engine.autocomplete("Ad", "Address"), ['Address'])
|
self.assertEqual(self.engine.autocomplete("Ad", "Address", "city"), ['Address'])
|
||||||
self.assertGreaterEqual(set(self.engine.autocomplete("S", "Address")), {
|
self.assertGreaterEqual(set(self.engine.autocomplete("S", "Address", "city")), {
|
||||||
'Schools',
|
'Schools',
|
||||||
'Students',
|
'Students',
|
||||||
('SUM', '(value1, *more_values)', True),
|
('SUM', '(value1, *more_values)', True),
|
||||||
('STDEV', '(value, *more_values)', True),
|
('STDEV', '(value, *more_values)', True),
|
||||||
})
|
})
|
||||||
self.assertGreaterEqual(set(self.engine.autocomplete("s", "Address")), {
|
self.assertGreaterEqual(set(self.engine.autocomplete("s", "Address", "city")), {
|
||||||
'Schools',
|
'Schools',
|
||||||
'Students',
|
'Students',
|
||||||
'sum(',
|
'sum(',
|
||||||
('SUM', '(value1, *more_values)', True),
|
('SUM', '(value1, *more_values)', True),
|
||||||
('STDEV', '(value, *more_values)', True),
|
('STDEV', '(value, *more_values)', True),
|
||||||
})
|
})
|
||||||
self.assertEqual(self.engine.autocomplete("Addr", "Schools"), ['Address'])
|
self.assertEqual(self.engine.autocomplete("Addr", "Schools", "budget"), ['Address'])
|
||||||
|
|
||||||
def test_suggest_columns(self):
|
def test_suggest_columns(self):
|
||||||
self.assertEqual(self.engine.autocomplete("$ci", "Address"),
|
self.assertEqual(self.engine.autocomplete("$ci", "Address", "city"),
|
||||||
["$city"])
|
["$city"])
|
||||||
self.assertEqual(self.engine.autocomplete("rec.i", "Address"),
|
self.assertEqual(self.engine.autocomplete("rec.i", "Address", "city"),
|
||||||
["rec.id"])
|
["rec.id"])
|
||||||
self.assertEqual(len(self.engine.autocomplete("$", "Address")),
|
self.assertEqual(len(self.engine.autocomplete("$", "Address", "city")),
|
||||||
2)
|
2)
|
||||||
|
|
||||||
# A few more detailed examples.
|
# A few more detailed examples.
|
||||||
self.assertEqual(self.engine.autocomplete("$", "Students"),
|
self.assertEqual(self.engine.autocomplete("$", "Students", "school"),
|
||||||
['$birthDate', '$firstName', '$id', '$lastName', '$lastVisit',
|
['$birthDate', '$firstName', '$id', '$lastName', '$lastVisit',
|
||||||
'$school', '$schoolCities', '$schoolIds', '$schoolName'])
|
'$school', '$schoolCities', '$schoolIds', '$schoolName'])
|
||||||
self.assertEqual(self.engine.autocomplete("$fi", "Students"), ['$firstName'])
|
self.assertEqual(self.engine.autocomplete("$fi", "Students", "birthDate"), ['$firstName'])
|
||||||
self.assertEqual(self.engine.autocomplete("$school", "Students"),
|
self.assertEqual(self.engine.autocomplete("$school", "Students", "lastVisit"),
|
||||||
['$school', '$schoolCities', '$schoolIds', '$schoolName'])
|
['$school', '$schoolCities', '$schoolIds', '$schoolName'])
|
||||||
|
|
||||||
def test_suggest_lookup_methods(self):
|
def test_suggest_lookup_methods(self):
|
||||||
# Should suggest lookup formulas for tables.
|
# Should suggest lookup formulas for tables.
|
||||||
self.assertEqual(self.engine.autocomplete("Address.", "Students"), [
|
self.assertEqual(self.engine.autocomplete("Address.", "Students", "firstName"), [
|
||||||
'Address.all',
|
'Address.all',
|
||||||
('Address.lookupOne', '(colName=<value>, ...)', True),
|
('Address.lookupOne', '(colName=<value>, ...)', True),
|
||||||
('Address.lookupRecords', '(colName=<value>, ...)', True),
|
('Address.lookupRecords', '(colName=<value>, ...)', True),
|
||||||
])
|
])
|
||||||
|
|
||||||
self.assertEqual(self.engine.autocomplete("Address.lookup", "Students"), [
|
self.assertEqual(self.engine.autocomplete("Address.lookup", "Students", "lastName"), [
|
||||||
('Address.lookupOne', '(colName=<value>, ...)', True),
|
('Address.lookupOne', '(colName=<value>, ...)', True),
|
||||||
('Address.lookupRecords', '(colName=<value>, ...)', True),
|
('Address.lookupRecords', '(colName=<value>, ...)', True),
|
||||||
])
|
])
|
||||||
|
|
||||||
self.assertEqual(self.engine.autocomplete("address.look", "Students"), [
|
self.assertEqual(self.engine.autocomplete("address.look", "Students", "schoolName"), [
|
||||||
('Address.lookupOne', '(colName=<value>, ...)', True),
|
('Address.lookupOne', '(colName=<value>, ...)', True),
|
||||||
('Address.lookupRecords', '(colName=<value>, ...)', True),
|
('Address.lookupRecords', '(colName=<value>, ...)', True),
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_suggest_column_type_methods(self):
|
def test_suggest_column_type_methods(self):
|
||||||
# Should treat columns as correct types.
|
# Should treat columns as correct types.
|
||||||
self.assertGreaterEqual(set(self.engine.autocomplete("$firstName.", "Students")),
|
self.assertGreaterEqual(set(self.engine.autocomplete("$firstName.", "Students", "firstName")),
|
||||||
{'$firstName.startswith(', '$firstName.replace(', '$firstName.title('})
|
{'$firstName.startswith(', '$firstName.replace(', '$firstName.title('})
|
||||||
self.assertGreaterEqual(set(self.engine.autocomplete("$birthDate.", "Students")),
|
self.assertGreaterEqual(set(self.engine.autocomplete("$birthDate.", "Students", "lastName")),
|
||||||
{'$birthDate.month', '$birthDate.strftime(', '$birthDate.replace('})
|
{'$birthDate.month', '$birthDate.strftime(', '$birthDate.replace('})
|
||||||
self.assertGreaterEqual(set(self.engine.autocomplete("$lastVisit.m", "Students")),
|
self.assertGreaterEqual(set(self.engine.autocomplete("$lastVisit.m", "Students", "firstName")),
|
||||||
{'$lastVisit.month', '$lastVisit.minute'})
|
{'$lastVisit.month', '$lastVisit.minute'})
|
||||||
self.assertGreaterEqual(set(self.engine.autocomplete("$school.", "Students")),
|
self.assertGreaterEqual(set(self.engine.autocomplete("$school.", "Students", "firstName")),
|
||||||
{'$school.address', '$school.name',
|
{'$school.address', '$school.name',
|
||||||
'$school.yearFounded', '$school.budget'})
|
'$school.yearFounded', '$school.budget'})
|
||||||
self.assertEqual(self.engine.autocomplete("$school.year", "Students"),
|
self.assertEqual(self.engine.autocomplete("$school.year", "Students", "lastName"),
|
||||||
['$school.yearFounded'])
|
['$school.yearFounded'])
|
||||||
self.assertGreaterEqual(set(self.engine.autocomplete("$yearFounded.", "Schools")),
|
self.assertGreaterEqual(set(self.engine.autocomplete("$yearFounded.", "Schools", "budget")),
|
||||||
{'$yearFounded.denominator', # Only integers have this
|
{'$yearFounded.denominator', # Only integers have this
|
||||||
'$yearFounded.bit_length(', # and this
|
'$yearFounded.bit_length(', # and this
|
||||||
'$yearFounded.real'})
|
'$yearFounded.real'})
|
||||||
self.assertGreaterEqual(set(self.engine.autocomplete("$budget.", "Schools")),
|
self.assertGreaterEqual(set(self.engine.autocomplete("$budget.", "Schools", "budget")),
|
||||||
{'$budget.is_integer(', # Only floats have this
|
{'$budget.is_integer(', # Only floats have this
|
||||||
'$budget.real'})
|
'$budget.real'})
|
||||||
|
|
||||||
def test_suggest_follows_references(self):
|
def test_suggest_follows_references(self):
|
||||||
# Should follow references and autocomplete those types.
|
# Should follow references and autocomplete those types.
|
||||||
self.assertEqual(self.engine.autocomplete("$school.name.st", "Students"),
|
self.assertEqual(self.engine.autocomplete("$school.name.st", "Students", "firstName"),
|
||||||
['$school.name.startswith(', '$school.name.strip('])
|
['$school.name.startswith(', '$school.name.strip('])
|
||||||
self.assertGreaterEqual(set(self.engine.autocomplete("$school.yearFounded.", "Students")),
|
self.assertGreaterEqual(
|
||||||
{'$school.yearFounded.denominator',
|
set(self.engine.autocomplete("$school.yearFounded.","Students", "firstName")),
|
||||||
'$school.yearFounded.bit_length(',
|
{
|
||||||
'$school.yearFounded.real'})
|
'$school.yearFounded.denominator',
|
||||||
|
'$school.yearFounded.bit_length(',
|
||||||
|
'$school.yearFounded.real'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(self.engine.autocomplete("$school.address.", "Students"),
|
self.assertEqual(self.engine.autocomplete("$school.address.", "Students", "lastName"),
|
||||||
['$school.address.city', '$school.address.id'])
|
['$school.address.city', '$school.address.id'])
|
||||||
self.assertEqual(self.engine.autocomplete("$school.address.city.st", "Students"),
|
self.assertEqual(self.engine.autocomplete("$school.address.city.st", "Students", "lastName"),
|
||||||
['$school.address.city.startswith(', '$school.address.city.strip('])
|
['$school.address.city.startswith(', '$school.address.city.strip('])
|
||||||
|
@ -312,11 +312,17 @@ class TestRenames(test_engine.EngineTestCase):
|
|||||||
# Renaming a table should not leave the old name available for auto-complete.
|
# Renaming a table should not leave the old name available for auto-complete.
|
||||||
self.load_sample(self.sample)
|
self.load_sample(self.sample)
|
||||||
names = {"People", "Persons"}
|
names = {"People", "Persons"}
|
||||||
self.assertEqual(names.intersection(self.engine.autocomplete("Pe", "Address")), {"People"})
|
self.assertEqual(
|
||||||
|
names.intersection(self.engine.autocomplete("Pe", "Address", "city")),
|
||||||
|
{"People"}
|
||||||
|
)
|
||||||
|
|
||||||
# Rename the table and ensure that "People" is no longer present among top-level names.
|
# Rename the table and ensure that "People" is no longer present among top-level names.
|
||||||
out_actions = self.apply_user_action(["RenameTable", "People", "Persons"])
|
out_actions = self.apply_user_action(["RenameTable", "People", "Persons"])
|
||||||
self.assertEqual(names.intersection(self.engine.autocomplete("Pe", "Address")), {"Persons"})
|
self.assertEqual(
|
||||||
|
names.intersection(self.engine.autocomplete("Pe", "Address", "city")),
|
||||||
|
{"Persons"}
|
||||||
|
)
|
||||||
|
|
||||||
def test_rename_to_id(self):
|
def test_rename_to_id(self):
|
||||||
# Check that we renaming a column to "Id" disambiguates it with a suffix.
|
# Check that we renaming a column to "Id" disambiguates it with a suffix.
|
||||||
|
Loading…
Reference in New Issue
Block a user