diff options
Diffstat (limited to 'bitbake/lib')
-rw-r--r-- | bitbake/lib/bb/command.py | 91 | ||||
-rw-r--r-- | bitbake/lib/bb/data_smart.py | 53 | ||||
-rw-r--r-- | bitbake/lib/bb/remotedata.py | 49 | ||||
-rw-r--r-- | bitbake/lib/bb/tests/data.py | 139 | ||||
-rw-r--r-- | bitbake/lib/bb/tinfoil.py | 115 |
5 files changed, 87 insertions, 360 deletions
diff --git a/bitbake/lib/bb/command.py b/bitbake/lib/bb/command.py index b38c151b3d..2879950933 100644 --- a/bitbake/lib/bb/command.py +++ b/bitbake/lib/bb/command.py | |||
@@ -450,54 +450,38 @@ class CommandsSync: | |||
450 | return all_p, best | 450 | return all_p, best |
451 | getRuntimeProviders.readonly = True | 451 | getRuntimeProviders.readonly = True |
452 | 452 | ||
453 | def dataStoreConnectorFindVar(self, command, params): | 453 | def dataStoreConnectorCmd(self, command, params): |
454 | dsindex = params[0] | 454 | dsindex = params[0] |
455 | name = params[1] | 455 | method = params[1] |
456 | datastore = command.remotedatastores[dsindex] | 456 | args = params[2] |
457 | value, overridedata = datastore._findVar(name) | 457 | kwargs = params[3] |
458 | |||
459 | if value: | ||
460 | content = value.get('_content', None) | ||
461 | if isinstance(content, bb.data_smart.DataSmart): | ||
462 | # Value is a datastore (e.g. BB_ORIGENV) - need to handle this carefully | ||
463 | idx = command.remotedatastores.check_store(content, True) | ||
464 | return {'_content': DataStoreConnectionHandle(idx), | ||
465 | '_connector_origtype': 'DataStoreConnectionHandle', | ||
466 | '_connector_overrides': overridedata} | ||
467 | elif isinstance(content, set): | ||
468 | return {'_content': list(content), | ||
469 | '_connector_origtype': 'set', | ||
470 | '_connector_overrides': overridedata} | ||
471 | else: | ||
472 | value['_connector_overrides'] = overridedata | ||
473 | else: | ||
474 | value = {} | ||
475 | value['_connector_overrides'] = overridedata | ||
476 | return value | ||
477 | dataStoreConnectorFindVar.readonly = True | ||
478 | 458 | ||
479 | def dataStoreConnectorGetKeys(self, command, params): | 459 | d = command.remotedatastores[dsindex] |
480 | dsindex = params[0] | 460 | ret = getattr(d, method)(*args, **kwargs) |
481 | datastore = command.remotedatastores[dsindex] | 461 | |
482 | return list(datastore.keys()) | 462 | if isinstance(ret, bb.data_smart.DataSmart): |
483 | dataStoreConnectorGetKeys.readonly = True | 463 | idx = command.remotedatastores.store(ret) |
464 | return DataStoreConnectionHandle(idx) | ||
484 | 465 | ||
485 | def dataStoreConnectorGetVarHistory(self, command, params): | 466 | return ret |
467 | |||
468 | def dataStoreConnectorVarHistCmd(self, command, params): | ||
486 | dsindex = params[0] | 469 | dsindex = params[0] |
487 | name = params[1] | 470 | method = params[1] |
488 | datastore = command.remotedatastores[dsindex] | 471 | args = params[2] |
489 | return datastore.varhistory.variable(name) | 472 | kwargs = params[3] |
490 | dataStoreConnectorGetVarHistory.readonly = True | ||
491 | 473 | ||
492 | def dataStoreConnectorExpandPythonRef(self, command, params): | 474 | d = command.remotedatastores[dsindex].varhistory |
493 | config_data_dict = params[0] | 475 | return getattr(d, method)(*args, **kwargs) |
494 | varname = params[1] | ||
495 | expr = params[2] | ||
496 | 476 | ||
497 | config_data = command.remotedatastores.receive_datastore(config_data_dict) | 477 | def dataStoreConnectorIncHistCmd(self, command, params): |
478 | dsindex = params[0] | ||
479 | method = params[1] | ||
480 | args = params[2] | ||
481 | kwargs = params[3] | ||
498 | 482 | ||
499 | varparse = bb.data_smart.VariableParse(varname, config_data) | 483 | d = command.remotedatastores[dsindex].inchistory |
500 | return varparse.python_sub(expr) | 484 | return getattr(d, method)(*args, **kwargs) |
501 | 485 | ||
502 | def dataStoreConnectorRelease(self, command, params): | 486 | def dataStoreConnectorRelease(self, command, params): |
503 | dsindex = params[0] | 487 | dsindex = params[0] |
@@ -505,31 +489,6 @@ class CommandsSync: | |||
505 | raise CommandError('dataStoreConnectorRelease: invalid index %d' % dsindex) | 489 | raise CommandError('dataStoreConnectorRelease: invalid index %d' % dsindex) |
506 | command.remotedatastores.release(dsindex) | 490 | command.remotedatastores.release(dsindex) |
507 | 491 | ||
508 | def dataStoreConnectorSetVarFlag(self, command, params): | ||
509 | dsindex = params[0] | ||
510 | name = params[1] | ||
511 | flag = params[2] | ||
512 | value = params[3] | ||
513 | datastore = command.remotedatastores[dsindex] | ||
514 | datastore.setVarFlag(name, flag, value) | ||
515 | |||
516 | def dataStoreConnectorDelVar(self, command, params): | ||
517 | dsindex = params[0] | ||
518 | name = params[1] | ||
519 | datastore = command.remotedatastores[dsindex] | ||
520 | if len(params) > 2: | ||
521 | flag = params[2] | ||
522 | datastore.delVarFlag(name, flag) | ||
523 | else: | ||
524 | datastore.delVar(name) | ||
525 | |||
526 | def dataStoreConnectorRenameVar(self, command, params): | ||
527 | dsindex = params[0] | ||
528 | name = params[1] | ||
529 | newname = params[2] | ||
530 | datastore = command.remotedatastores[dsindex] | ||
531 | datastore.renameVar(name, newname) | ||
532 | |||
533 | def parseRecipeFile(self, command, params): | 492 | def parseRecipeFile(self, command, params): |
534 | """ | 493 | """ |
535 | Parse the specified recipe file (with or without bbappends) | 494 | Parse the specified recipe file (with or without bbappends) |
diff --git a/bitbake/lib/bb/data_smart.py b/bitbake/lib/bb/data_smart.py index b2dc9d9fd5..70257ab7f8 100644 --- a/bitbake/lib/bb/data_smart.py +++ b/bitbake/lib/bb/data_smart.py | |||
@@ -107,10 +107,6 @@ class VariableParse: | |||
107 | else: | 107 | else: |
108 | code = match.group()[3:-1] | 108 | code = match.group()[3:-1] |
109 | 109 | ||
110 | if "_remote_data" in self.d: | ||
111 | connector = self.d["_remote_data"] | ||
112 | return connector.expandPythonRef(self.varname, code, self.d) | ||
113 | |||
114 | if self.varname: | 110 | if self.varname: |
115 | varname = 'Var <%s>' % self.varname | 111 | varname = 'Var <%s>' % self.varname |
116 | else: | 112 | else: |
@@ -268,12 +264,7 @@ class VariableHistory(object): | |||
268 | self.variables[newvar].append(i.copy()) | 264 | self.variables[newvar].append(i.copy()) |
269 | 265 | ||
270 | def variable(self, var): | 266 | def variable(self, var): |
271 | remote_connector = self.dataroot.getVar('_remote_data', False) | 267 | varhistory = [] |
272 | if remote_connector: | ||
273 | varhistory = remote_connector.getVarHistory(var) | ||
274 | else: | ||
275 | varhistory = [] | ||
276 | |||
277 | if var in self.variables: | 268 | if var in self.variables: |
278 | varhistory.extend(self.variables[var]) | 269 | varhistory.extend(self.variables[var]) |
279 | return varhistory | 270 | return varhistory |
@@ -471,10 +462,6 @@ class DataSmart(MutableMapping): | |||
471 | if var in dest: | 462 | if var in dest: |
472 | return dest[var], self.overridedata.get(var, None) | 463 | return dest[var], self.overridedata.get(var, None) |
473 | 464 | ||
474 | if "_remote_data" in dest: | ||
475 | connector = dest["_remote_data"]["_content"] | ||
476 | return connector.getVar(var) | ||
477 | |||
478 | if "_data" not in dest: | 465 | if "_data" not in dest: |
479 | break | 466 | break |
480 | dest = dest["_data"] | 467 | dest = dest["_data"] |
@@ -499,12 +486,6 @@ class DataSmart(MutableMapping): | |||
499 | if 'parsing' in loginfo: | 486 | if 'parsing' in loginfo: |
500 | parsing=True | 487 | parsing=True |
501 | 488 | ||
502 | if '_remote_data' in self.dict: | ||
503 | connector = self.dict["_remote_data"]["_content"] | ||
504 | res = connector.setVar(var, value) | ||
505 | if not res: | ||
506 | return | ||
507 | |||
508 | if 'op' not in loginfo: | 489 | if 'op' not in loginfo: |
509 | loginfo['op'] = "set" | 490 | loginfo['op'] = "set" |
510 | 491 | ||
@@ -612,12 +593,6 @@ class DataSmart(MutableMapping): | |||
612 | bb.warn("Calling renameVar with equivalent keys (%s) is invalid" % key) | 593 | bb.warn("Calling renameVar with equivalent keys (%s) is invalid" % key) |
613 | return | 594 | return |
614 | 595 | ||
615 | if '_remote_data' in self.dict: | ||
616 | connector = self.dict["_remote_data"]["_content"] | ||
617 | res = connector.renameVar(key, newkey) | ||
618 | if not res: | ||
619 | return | ||
620 | |||
621 | val = self.getVar(key, 0, parsing=True) | 596 | val = self.getVar(key, 0, parsing=True) |
622 | if val is not None: | 597 | if val is not None: |
623 | self.varhistory.rename_variable_hist(key, newkey) | 598 | self.varhistory.rename_variable_hist(key, newkey) |
@@ -663,11 +638,6 @@ class DataSmart(MutableMapping): | |||
663 | 638 | ||
664 | def delVar(self, var, **loginfo): | 639 | def delVar(self, var, **loginfo): |
665 | self.expand_cache = {} | 640 | self.expand_cache = {} |
666 | if '_remote_data' in self.dict: | ||
667 | connector = self.dict["_remote_data"]["_content"] | ||
668 | res = connector.delVar(var) | ||
669 | if not res: | ||
670 | return | ||
671 | 641 | ||
672 | loginfo['detail'] = "" | 642 | loginfo['detail'] = "" |
673 | loginfo['op'] = 'del' | 643 | loginfo['op'] = 'del' |
@@ -695,11 +665,6 @@ class DataSmart(MutableMapping): | |||
695 | 665 | ||
696 | def setVarFlag(self, var, flag, value, **loginfo): | 666 | def setVarFlag(self, var, flag, value, **loginfo): |
697 | self.expand_cache = {} | 667 | self.expand_cache = {} |
698 | if '_remote_data' in self.dict: | ||
699 | connector = self.dict["_remote_data"]["_content"] | ||
700 | res = connector.setVarFlag(var, flag, value) | ||
701 | if not res: | ||
702 | return | ||
703 | 668 | ||
704 | if 'op' not in loginfo: | 669 | if 'op' not in loginfo: |
705 | loginfo['op'] = "set" | 670 | loginfo['op'] = "set" |
@@ -850,11 +815,6 @@ class DataSmart(MutableMapping): | |||
850 | 815 | ||
851 | def delVarFlag(self, var, flag, **loginfo): | 816 | def delVarFlag(self, var, flag, **loginfo): |
852 | self.expand_cache = {} | 817 | self.expand_cache = {} |
853 | if '_remote_data' in self.dict: | ||
854 | connector = self.dict["_remote_data"]["_content"] | ||
855 | res = connector.delVarFlag(var, flag) | ||
856 | if not res: | ||
857 | return | ||
858 | 818 | ||
859 | local_var, _ = self._findVar(var) | 819 | local_var, _ = self._findVar(var) |
860 | if not local_var: | 820 | if not local_var: |
@@ -972,7 +932,7 @@ class DataSmart(MutableMapping): | |||
972 | 932 | ||
973 | def localkeys(self): | 933 | def localkeys(self): |
974 | for key in self.dict: | 934 | for key in self.dict: |
975 | if key not in ['_data', '_remote_data']: | 935 | if key not in ['_data']: |
976 | yield key | 936 | yield key |
977 | 937 | ||
978 | def __iter__(self): | 938 | def __iter__(self): |
@@ -981,7 +941,7 @@ class DataSmart(MutableMapping): | |||
981 | def keylist(d): | 941 | def keylist(d): |
982 | klist = set() | 942 | klist = set() |
983 | for key in d: | 943 | for key in d: |
984 | if key in ["_data", "_remote_data"]: | 944 | if key in ["_data"]: |
985 | continue | 945 | continue |
986 | if key in deleted: | 946 | if key in deleted: |
987 | continue | 947 | continue |
@@ -995,13 +955,6 @@ class DataSmart(MutableMapping): | |||
995 | if "_data" in d: | 955 | if "_data" in d: |
996 | klist |= keylist(d["_data"]) | 956 | klist |= keylist(d["_data"]) |
997 | 957 | ||
998 | if "_remote_data" in d: | ||
999 | connector = d["_remote_data"]["_content"] | ||
1000 | for key in connector.getKeys(): | ||
1001 | if key in deleted: | ||
1002 | continue | ||
1003 | klist.add(key) | ||
1004 | |||
1005 | return klist | 958 | return klist |
1006 | 959 | ||
1007 | self.need_overrides() | 960 | self.need_overrides() |
diff --git a/bitbake/lib/bb/remotedata.py b/bitbake/lib/bb/remotedata.py index 7391e1b45c..6c9864dd6b 100644 --- a/bitbake/lib/bb/remotedata.py +++ b/bitbake/lib/bb/remotedata.py | |||
@@ -17,16 +17,16 @@ class RemoteDatastores: | |||
17 | self.cooker = cooker | 17 | self.cooker = cooker |
18 | self.datastores = {} | 18 | self.datastores = {} |
19 | self.locked = [] | 19 | self.locked = [] |
20 | self.datastores[0] = self.cooker.data | ||
20 | self.nextindex = 1 | 21 | self.nextindex = 1 |
21 | 22 | ||
22 | def __len__(self): | 23 | def __len__(self): |
23 | return len(self.datastores) | 24 | return len(self.datastores) |
24 | 25 | ||
25 | def __getitem__(self, key): | 26 | def __getitem__(self, key): |
26 | if key is None: | 27 | # Cooker could have changed its datastore from under us |
27 | return self.cooker.data | 28 | self.datastores[0] = self.cooker.data |
28 | else: | 29 | return self.datastores[key] |
29 | return self.datastores[key] | ||
30 | 30 | ||
31 | def items(self): | 31 | def items(self): |
32 | return self.datastores.items() | 32 | return self.datastores.items() |
@@ -63,44 +63,3 @@ class RemoteDatastores: | |||
63 | raise Exception('Tried to release locked datastore %d' % idx) | 63 | raise Exception('Tried to release locked datastore %d' % idx) |
64 | del self.datastores[idx] | 64 | del self.datastores[idx] |
65 | 65 | ||
66 | def receive_datastore(self, remote_data): | ||
67 | """Receive a datastore object sent from the client (as prepared by transmit_datastore())""" | ||
68 | dct = dict(remote_data) | ||
69 | d = bb.data_smart.DataSmart() | ||
70 | d.dict = dct | ||
71 | while True: | ||
72 | if '_remote_data' in dct: | ||
73 | dsindex = dct['_remote_data']['_content'] | ||
74 | del dct['_remote_data'] | ||
75 | if dsindex is None: | ||
76 | dct['_data'] = self.cooker.data.dict | ||
77 | else: | ||
78 | dct['_data'] = self.datastores[dsindex].dict | ||
79 | break | ||
80 | elif '_data' in dct: | ||
81 | idct = dict(dct['_data']) | ||
82 | dct['_data'] = idct | ||
83 | dct = idct | ||
84 | else: | ||
85 | break | ||
86 | return d | ||
87 | |||
88 | @staticmethod | ||
89 | def transmit_datastore(d): | ||
90 | """Prepare a datastore object for sending over IPC from the client end""" | ||
91 | # FIXME content might be a dict, need to turn that into a list as well | ||
92 | def copy_dicts(dct): | ||
93 | if '_remote_data' in dct: | ||
94 | dsindex = dct['_remote_data']['_content'].dsindex | ||
95 | newdct = dct.copy() | ||
96 | newdct['_remote_data'] = {'_content': dsindex} | ||
97 | return list(newdct.items()) | ||
98 | elif '_data' in dct: | ||
99 | newdct = dct.copy() | ||
100 | newdata = copy_dicts(dct['_data']) | ||
101 | if newdata: | ||
102 | newdct['_data'] = newdata | ||
103 | return list(newdct.items()) | ||
104 | return None | ||
105 | main_dict = copy_dicts(d.dict) | ||
106 | return main_dict | ||
diff --git a/bitbake/lib/bb/tests/data.py b/bitbake/lib/bb/tests/data.py index 3e49984c93..2b137706dd 100644 --- a/bitbake/lib/bb/tests/data.py +++ b/bitbake/lib/bb/tests/data.py | |||
@@ -544,142 +544,3 @@ class Serialize(unittest.TestCase): | |||
544 | self.assertEqual(newd.getVarFlag('HELLO', 'other'), 'planet') | 544 | self.assertEqual(newd.getVarFlag('HELLO', 'other'), 'planet') |
545 | 545 | ||
546 | 546 | ||
547 | # Remote datastore tests | ||
548 | # These really only test the interface, since in actual usage we have a | ||
549 | # tinfoil connector that does everything over RPC, and this doesn't test | ||
550 | # that. | ||
551 | |||
552 | class TestConnector: | ||
553 | d = None | ||
554 | def __init__(self, d): | ||
555 | self.d = d | ||
556 | def getVar(self, name): | ||
557 | return self.d._findVar(name) | ||
558 | def getKeys(self): | ||
559 | return set(self.d.keys()) | ||
560 | def getVarHistory(self, name): | ||
561 | return self.d.varhistory.variable(name) | ||
562 | def expandPythonRef(self, varname, expr, d): | ||
563 | localdata = self.d.createCopy() | ||
564 | for key in d.localkeys(): | ||
565 | localdata.setVar(d.getVar(key)) | ||
566 | varparse = bb.data_smart.VariableParse(varname, localdata) | ||
567 | return varparse.python_sub(expr) | ||
568 | def setVar(self, name, value): | ||
569 | self.d.setVar(name, value) | ||
570 | def setVarFlag(self, name, flag, value): | ||
571 | self.d.setVarFlag(name, flag, value) | ||
572 | def delVar(self, name): | ||
573 | self.d.delVar(name) | ||
574 | return False | ||
575 | def delVarFlag(self, name, flag): | ||
576 | self.d.delVarFlag(name, flag) | ||
577 | return False | ||
578 | def renameVar(self, name, newname): | ||
579 | self.d.renameVar(name, newname) | ||
580 | return False | ||
581 | |||
582 | class Remote(unittest.TestCase): | ||
583 | def test_remote(self): | ||
584 | |||
585 | d1 = bb.data.init() | ||
586 | d1.enableTracking() | ||
587 | d2 = bb.data.init() | ||
588 | d2.enableTracking() | ||
589 | connector = TestConnector(d1) | ||
590 | |||
591 | d2.setVar('_remote_data', connector) | ||
592 | |||
593 | d1.setVar('HELLO', 'world') | ||
594 | d1.setVarFlag('OTHER', 'flagname', 'flagvalue') | ||
595 | self.assertEqual(d2.getVar('HELLO'), 'world') | ||
596 | self.assertEqual(d2.expand('${HELLO}'), 'world') | ||
597 | self.assertEqual(d2.expand('${@d.getVar("HELLO")}'), 'world') | ||
598 | self.assertIn('flagname', d2.getVarFlags('OTHER')) | ||
599 | self.assertEqual(d2.getVarFlag('OTHER', 'flagname'), 'flagvalue') | ||
600 | self.assertEqual(d1.varhistory.variable('HELLO'), d2.varhistory.variable('HELLO')) | ||
601 | # Test setVar on client side affects server | ||
602 | d2.setVar('HELLO', 'other-world') | ||
603 | self.assertEqual(d1.getVar('HELLO'), 'other-world') | ||
604 | # Test setVarFlag on client side affects server | ||
605 | d2.setVarFlag('HELLO', 'flagname', 'flagvalue') | ||
606 | self.assertEqual(d1.getVarFlag('HELLO', 'flagname'), 'flagvalue') | ||
607 | # Test client side data is incorporated in python expansion (which is done on server) | ||
608 | d2.setVar('FOO', 'bar') | ||
609 | self.assertEqual(d2.expand('${@d.getVar("FOO")}'), 'bar') | ||
610 | # Test overrides work | ||
611 | d1.setVar('FOO_test', 'baz') | ||
612 | d1.appendVar('OVERRIDES', ':test') | ||
613 | self.assertEqual(d2.getVar('FOO'), 'baz') | ||
614 | |||
615 | |||
616 | # Remote equivalents of local test classes | ||
617 | # Note that these aren't perfect since we only test in one direction | ||
618 | |||
619 | class RemoteDataExpansions(DataExpansions): | ||
620 | def setUp(self): | ||
621 | self.d1 = bb.data.init() | ||
622 | self.d = bb.data.init() | ||
623 | self.d1["foo"] = "value_of_foo" | ||
624 | self.d1["bar"] = "value_of_bar" | ||
625 | self.d1["value_of_foo"] = "value_of_'value_of_foo'" | ||
626 | connector = TestConnector(self.d1) | ||
627 | self.d.setVar('_remote_data', connector) | ||
628 | |||
629 | class TestRemoteNestedExpansions(TestNestedExpansions): | ||
630 | def setUp(self): | ||
631 | self.d1 = bb.data.init() | ||
632 | self.d = bb.data.init() | ||
633 | self.d1["foo"] = "foo" | ||
634 | self.d1["bar"] = "bar" | ||
635 | self.d1["value_of_foobar"] = "187" | ||
636 | connector = TestConnector(self.d1) | ||
637 | self.d.setVar('_remote_data', connector) | ||
638 | |||
639 | class TestRemoteConcat(TestConcat): | ||
640 | def setUp(self): | ||
641 | self.d1 = bb.data.init() | ||
642 | self.d = bb.data.init() | ||
643 | self.d1.setVar("FOO", "foo") | ||
644 | self.d1.setVar("VAL", "val") | ||
645 | self.d1.setVar("BAR", "bar") | ||
646 | connector = TestConnector(self.d1) | ||
647 | self.d.setVar('_remote_data', connector) | ||
648 | |||
649 | class TestRemoteConcatOverride(TestConcatOverride): | ||
650 | def setUp(self): | ||
651 | self.d1 = bb.data.init() | ||
652 | self.d = bb.data.init() | ||
653 | self.d1.setVar("FOO", "foo") | ||
654 | self.d1.setVar("VAL", "val") | ||
655 | self.d1.setVar("BAR", "bar") | ||
656 | connector = TestConnector(self.d1) | ||
657 | self.d.setVar('_remote_data', connector) | ||
658 | |||
659 | class TestRemoteOverrides(TestOverrides): | ||
660 | def setUp(self): | ||
661 | self.d1 = bb.data.init() | ||
662 | self.d = bb.data.init() | ||
663 | self.d1.setVar("OVERRIDES", "foo:bar:local") | ||
664 | self.d1.setVar("TEST", "testvalue") | ||
665 | connector = TestConnector(self.d1) | ||
666 | self.d.setVar('_remote_data', connector) | ||
667 | |||
668 | class TestRemoteKeyExpansion(TestKeyExpansion): | ||
669 | def setUp(self): | ||
670 | self.d1 = bb.data.init() | ||
671 | self.d = bb.data.init() | ||
672 | self.d1.setVar("FOO", "foo") | ||
673 | self.d1.setVar("BAR", "foo") | ||
674 | connector = TestConnector(self.d1) | ||
675 | self.d.setVar('_remote_data', connector) | ||
676 | |||
677 | class TestRemoteFlags(TestFlags): | ||
678 | def setUp(self): | ||
679 | self.d1 = bb.data.init() | ||
680 | self.d = bb.data.init() | ||
681 | self.d1.setVar("foo", "value of foo") | ||
682 | self.d1.setVarFlag("foo", "flag1", "value of flag1") | ||
683 | self.d1.setVarFlag("foo", "flag2", "value of flag2") | ||
684 | connector = TestConnector(self.d1) | ||
685 | self.d.setVar('_remote_data', connector) | ||
diff --git a/bitbake/lib/bb/tinfoil.py b/bitbake/lib/bb/tinfoil.py index 70b381e351..4fbad0774e 100644 --- a/bitbake/lib/bb/tinfoil.py +++ b/bitbake/lib/bb/tinfoil.py | |||
@@ -13,6 +13,7 @@ import sys | |||
13 | import atexit | 13 | import atexit |
14 | import re | 14 | import re |
15 | from collections import OrderedDict, defaultdict | 15 | from collections import OrderedDict, defaultdict |
16 | from functools import partial | ||
16 | 17 | ||
17 | import bb.cache | 18 | import bb.cache |
18 | import bb.cooker | 19 | import bb.cooker |
@@ -44,66 +45,64 @@ class TinfoilUIException(Exception): | |||
44 | class TinfoilCommandFailed(Exception): | 45 | class TinfoilCommandFailed(Exception): |
45 | """Exception raised when run_command fails""" | 46 | """Exception raised when run_command fails""" |
46 | 47 | ||
48 | class TinfoilDataStoreConnectorVarHistory: | ||
49 | def __init__(self, tinfoil, dsindex): | ||
50 | self.tinfoil = tinfoil | ||
51 | self.dsindex = dsindex | ||
52 | |||
53 | def remoteCommand(self, cmd, *args, **kwargs): | ||
54 | return self.tinfoil.run_command('dataStoreConnectorVarHistCmd', self.dsindex, cmd, args, kwargs) | ||
55 | |||
56 | def __getattr__(self, name): | ||
57 | if not hasattr(bb.data_smart.VariableHistory, name): | ||
58 | raise AttributeError("VariableHistory has no such method %s" % name) | ||
59 | |||
60 | newfunc = partial(self.remoteCommand, name) | ||
61 | setattr(self, name, newfunc) | ||
62 | return newfunc | ||
63 | |||
64 | class TinfoilDataStoreConnectorIncHistory: | ||
65 | def __init__(self, tinfoil, dsindex): | ||
66 | self.tinfoil = tinfoil | ||
67 | self.dsindex = dsindex | ||
68 | |||
69 | def remoteCommand(self, cmd, *args, **kwargs): | ||
70 | return self.tinfoil.run_command('dataStoreConnectorIncHistCmd', self.dsindex, cmd, args, kwargs) | ||
71 | |||
72 | def __getattr__(self, name): | ||
73 | if not hasattr(bb.data_smart.IncludeHistory, name): | ||
74 | raise AttributeError("IncludeHistory has no such method %s" % name) | ||
75 | |||
76 | newfunc = partial(self.remoteCommand, name) | ||
77 | setattr(self, name, newfunc) | ||
78 | return newfunc | ||
79 | |||
47 | class TinfoilDataStoreConnector: | 80 | class TinfoilDataStoreConnector: |
48 | """Connector object used to enable access to datastore objects via tinfoil""" | 81 | """ |
82 | Connector object used to enable access to datastore objects via tinfoil | ||
83 | Method calls are transmitted to the remote datastore for processing, if a datastore is | ||
84 | returned we return a connector object for the new store | ||
85 | """ | ||
49 | 86 | ||
50 | def __init__(self, tinfoil, dsindex): | 87 | def __init__(self, tinfoil, dsindex): |
51 | self.tinfoil = tinfoil | 88 | self.tinfoil = tinfoil |
52 | self.dsindex = dsindex | 89 | self.dsindex = dsindex |
53 | def getVar(self, name): | 90 | self.varhistory = TinfoilDataStoreConnectorVarHistory(tinfoil, dsindex) |
54 | value = self.tinfoil.run_command('dataStoreConnectorFindVar', self.dsindex, name) | 91 | self.inchistory = TinfoilDataStoreConnectorIncHistory(tinfoil, dsindex) |
55 | overrides = None | 92 | |
56 | if isinstance(value, dict): | 93 | def remoteCommand(self, cmd, *args, **kwargs): |
57 | if '_connector_origtype' in value: | 94 | ret = self.tinfoil.run_command('dataStoreConnectorCmd', self.dsindex, cmd, args, kwargs) |
58 | value['_content'] = self.tinfoil._reconvert_type(value['_content'], value['_connector_origtype']) | 95 | if isinstance(ret, bb.command.DataStoreConnectionHandle): |
59 | del value['_connector_origtype'] | 96 | return TinfoilDataStoreConnector(self.tinfoil, ret.dsindex) |
60 | if '_connector_overrides' in value: | ||
61 | overrides = value['_connector_overrides'] | ||
62 | del value['_connector_overrides'] | ||
63 | return value, overrides | ||
64 | def getKeys(self): | ||
65 | return set(self.tinfoil.run_command('dataStoreConnectorGetKeys', self.dsindex)) | ||
66 | def getVarHistory(self, name): | ||
67 | return self.tinfoil.run_command('dataStoreConnectorGetVarHistory', self.dsindex, name) | ||
68 | def expandPythonRef(self, varname, expr, d): | ||
69 | ds = bb.remotedata.RemoteDatastores.transmit_datastore(d) | ||
70 | ret = self.tinfoil.run_command('dataStoreConnectorExpandPythonRef', ds, varname, expr) | ||
71 | return ret | 97 | return ret |
72 | def setVar(self, varname, value): | 98 | |
73 | if self.dsindex is None: | 99 | def __getattr__(self, name): |
74 | self.tinfoil.run_command('setVariable', varname, value) | 100 | if not hasattr(bb.data._dict_type, name): |
75 | else: | 101 | raise AttributeError("Data store has no such method %s" % name) |
76 | # Not currently implemented - indicate that setting should | 102 | |
77 | # be redirected to local side | 103 | newfunc = partial(self.remoteCommand, name) |
78 | return True | 104 | setattr(self, name, newfunc) |
79 | def setVarFlag(self, varname, flagname, value): | 105 | return newfunc |
80 | if self.dsindex is None: | ||
81 | self.tinfoil.run_command('dataStoreConnectorSetVarFlag', self.dsindex, varname, flagname, value) | ||
82 | else: | ||
83 | # Not currently implemented - indicate that setting should | ||
84 | # be redirected to local side | ||
85 | return True | ||
86 | def delVar(self, varname): | ||
87 | if self.dsindex is None: | ||
88 | self.tinfoil.run_command('dataStoreConnectorDelVar', self.dsindex, varname) | ||
89 | else: | ||
90 | # Not currently implemented - indicate that setting should | ||
91 | # be redirected to local side | ||
92 | return True | ||
93 | def delVarFlag(self, varname, flagname): | ||
94 | if self.dsindex is None: | ||
95 | self.tinfoil.run_command('dataStoreConnectorDelVar', self.dsindex, varname, flagname) | ||
96 | else: | ||
97 | # Not currently implemented - indicate that setting should | ||
98 | # be redirected to local side | ||
99 | return True | ||
100 | def renameVar(self, name, newname): | ||
101 | if self.dsindex is None: | ||
102 | self.tinfoil.run_command('dataStoreConnectorRenameVar', self.dsindex, name, newname) | ||
103 | else: | ||
104 | # Not currently implemented - indicate that setting should | ||
105 | # be redirected to local side | ||
106 | return True | ||
107 | 106 | ||
108 | class TinfoilCookerAdapter: | 107 | class TinfoilCookerAdapter: |
109 | """ | 108 | """ |
@@ -412,9 +411,7 @@ class Tinfoil: | |||
412 | self.run_actions(config_params) | 411 | self.run_actions(config_params) |
413 | self.recipes_parsed = True | 412 | self.recipes_parsed = True |
414 | 413 | ||
415 | self.config_data = bb.data.init() | 414 | self.config_data = TinfoilDataStoreConnector(self, 0) |
416 | connector = TinfoilDataStoreConnector(self, None) | ||
417 | self.config_data.setVar('_remote_data', connector) | ||
418 | self.cooker = TinfoilCookerAdapter(self) | 415 | self.cooker = TinfoilCookerAdapter(self) |
419 | self.cooker_data = self.cooker.recipecaches[''] | 416 | self.cooker_data = self.cooker.recipecaches[''] |
420 | else: | 417 | else: |
@@ -842,9 +839,7 @@ class Tinfoil: | |||
842 | newobj = origtype(obj) | 839 | newobj = origtype(obj) |
843 | 840 | ||
844 | if isinstance(newobj, bb.command.DataStoreConnectionHandle): | 841 | if isinstance(newobj, bb.command.DataStoreConnectionHandle): |
845 | connector = TinfoilDataStoreConnector(self, newobj.dsindex) | 842 | newobj = TinfoilDataStoreConnector(self, newobj.dsindex) |
846 | newobj = bb.data.init() | ||
847 | newobj.setVar('_remote_data', connector) | ||
848 | 843 | ||
849 | return newobj | 844 | return newobj |
850 | 845 | ||