diff options
author | Josh Blum | 2013-07-07 00:25:35 -0700 |
---|---|---|
committer | Josh Blum | 2013-07-07 00:25:35 -0700 |
commit | a8f263d94f8eb772a3a334aa5bb08c6e30b996ec (patch) | |
tree | bb9baa13d27d7d0150a6ee6c52add5288b502a0d | |
parent | 2001959902f85723c289e3f942ec2e49954a04bc (diff) | |
download | sandhi-a8f263d94f8eb772a3a334aa5bb08c6e30b996ec.tar.gz sandhi-a8f263d94f8eb772a3a334aa5bb08c6e30b996ec.tar.bz2 sandhi-a8f263d94f8eb772a3a334aa5bb08c6e30b996ec.zip |
gras: restore property access w/ json
-rw-r--r-- | include/gras/callable.hpp | 12 | ||||
-rw-r--r-- | lib/callable.cpp | 25 | ||||
-rw-r--r-- | lib/gras_impl/query_common.hpp | 2 | ||||
-rw-r--r-- | lib/pmc_to_ptree.cpp | 94 | ||||
-rw-r--r-- | lib/top_block_query.cpp | 55 | ||||
-rw-r--r-- | python/gras/GRAS_PyBlock.i | 13 | ||||
-rw-r--r-- | tests/query_test.py | 44 |
7 files changed, 114 insertions, 131 deletions
diff --git a/include/gras/callable.hpp b/include/gras/callable.hpp index 9d24c83..792be93 100644 --- a/include/gras/callable.hpp +++ b/include/gras/callable.hpp @@ -6,6 +6,7 @@ #include <gras/gras.hpp> #include <PMC/PMC.hpp> #include <boost/shared_ptr.hpp> +#include <vector> #include <string> namespace gras @@ -34,12 +35,23 @@ namespace gras class GRAS_API Callable { public: + //! Default constructor Callable(void); //! Destructor (virtual for subclasses) virtual ~Callable(void); + //! Get a list of keys for registered calls + std::vector<std::string> get_registered_keys(void) const; + +protected: + /*! + * Unregister a previously registered call. + * Throws if the key is not found in the registry. + */ + void unregister_call(const std::string &key); + /******************************************************************* * Register API - don't look here, template magic, not helpful ******************************************************************/ diff --git a/lib/callable.cpp b/lib/callable.cpp index 385715a..f52d604 100644 --- a/lib/callable.cpp +++ b/lib/callable.cpp @@ -1,6 +1,7 @@ // Copyright (C) by Josh Blum. See LICENSE.txt for licensing information. #include <gras/callable.hpp> +#include <boost/foreach.hpp> #include <boost/shared_ptr.hpp> #include <stdexcept> #include <map> @@ -8,6 +9,7 @@ using namespace gras; typedef std::map<std::string, boost::shared_ptr<CallableRegistryEntry> > CallableRegistry; +typedef std::pair<std::string, boost::shared_ptr<CallableRegistryEntry> > CallableRegistryPair; Callable::Callable(void) { @@ -19,6 +21,24 @@ Callable::~Callable(void) _call_registry.reset(); } +std::vector<std::string> Callable::get_registered_keys(void) const +{ + CallableRegistry *cr = reinterpret_cast<CallableRegistry *>(_call_registry.get()); + std::vector<std::string> keys; + BOOST_FOREACH(const CallableRegistryPair &p, (*cr)) + { + keys.push_back(p.first); + } + return keys; +} + +void Callable::unregister_call(const std::string &key) +{ + CallableRegistry *cr = reinterpret_cast<CallableRegistry *>(_call_registry.get()); + if (cr->count(key) == 0) throw std::invalid_argument("Callable - no method registered for key: " + key); + cr->erase(key); +} + void Callable::_register_call(const std::string &key, void *entry) { CallableRegistry *cr = reinterpret_cast<CallableRegistry *>(_call_registry.get()); @@ -28,9 +48,8 @@ void Callable::_register_call(const std::string &key, void *entry) PMCC Callable::_handle_call(const std::string &key, const PMCC &args) { CallableRegistry *cr = reinterpret_cast<CallableRegistry *>(_call_registry.get()); - boost::shared_ptr<CallableRegistryEntry> entry = (*cr)[key]; - if (not entry) throw std::invalid_argument("Callable: no method registered for key: " + key); - return entry->call(args); + if (cr->count(key) == 0) throw std::invalid_argument("Callable - no method registered for key: " + key); + return (*cr)[key]->call(args); } CallableRegistryEntry::CallableRegistryEntry(void) diff --git a/lib/gras_impl/query_common.hpp b/lib/gras_impl/query_common.hpp index 3111d11..65110ac 100644 --- a/lib/gras_impl/query_common.hpp +++ b/lib/gras_impl/query_common.hpp @@ -11,7 +11,7 @@ namespace gras { - PMCC ptree_to_pmc(const boost::property_tree::ptree &value, const std::type_info &hint); + PMCC ptree_to_pmc(const boost::property_tree::ptree &value); boost::property_tree::ptree pmc_to_ptree(const PMCC &value); boost::property_tree::ptree json_to_ptree(const std::string &s); diff --git a/lib/pmc_to_ptree.cpp b/lib/pmc_to_ptree.cpp index a53261d..20a0aa7 100644 --- a/lib/pmc_to_ptree.cpp +++ b/lib/pmc_to_ptree.cpp @@ -11,85 +11,45 @@ using namespace boost::property_tree; -PMCC gras::ptree_to_pmc(const ptree &value, const std::type_info &hint) +PMCC gras::ptree_to_pmc(const ptree &value) { - //if the type is PMCC - educated guess and recursively call - if (hint == typeid(PMCC) or hint == typeid(PMC)) - { - //single child - if (value.size() == 0) - { - //can we cast to number? - try{return ptree_to_pmc(value, typeid(double));} - catch(...){} - - //can we cast to complex? - try{return ptree_to_pmc(value, typeid(std::complex<double>));} - catch(...){} - - //then string - return ptree_to_pmc(value, typeid(std::string)); - } - //array - else - { - try{return ptree_to_pmc(value, typeid(std::vector<std::complex<double> >));} - catch(...){} - - try{return ptree_to_pmc(value, typeid(std::vector<double>));} - catch(...){} - } - } #define ptree_to_pmc_try(type) \ - if (hint == typeid(type)) return PMC_M(value.get_value<type >()); - - //determine number - ptree_to_pmc_try(char); - ptree_to_pmc_try(signed char); - ptree_to_pmc_try(unsigned char); - ptree_to_pmc_try(signed short); - ptree_to_pmc_try(unsigned short); - ptree_to_pmc_try(signed int); - ptree_to_pmc_try(unsigned int); - ptree_to_pmc_try(signed long); - ptree_to_pmc_try(unsigned long); - ptree_to_pmc_try(signed long long); - ptree_to_pmc_try(unsigned long long); - ptree_to_pmc_try(float); - ptree_to_pmc_try(double); - ptree_to_pmc_try(std::complex<float>); - ptree_to_pmc_try(std::complex<double>); - - //string - ptree_to_pmc_try(std::string); + try{return PMC_M(value.get_value<type >());} \ + catch(...){} - //determine number vector #define ptree_to_pmc_tryv(type) \ - if (hint == typeid(std::vector<type >)) \ - { \ + try{ \ std::vector<type > vec; \ BOOST_FOREACH(const ptree::value_type &elem, value) \ { \ vec.push_back(elem.second.get_value<type >()); \ } \ return PMC_M(vec); \ + }catch(...){} + + //single child + if (value.size() == 0) + { + //can we cast to integer? + ptree_to_pmc_try(long) + + //can we cast to float? + ptree_to_pmc_try(double) + + //can we cast to complex? + ptree_to_pmc_try(std::complex<double>) + + //then string + ptree_to_pmc_try(std::string); + } + //array + else + { + ptree_to_pmc_tryv(long); + ptree_to_pmc_tryv(double); + ptree_to_pmc_tryv(std::complex<double>); } - ptree_to_pmc_tryv(char); - ptree_to_pmc_tryv(signed char); - ptree_to_pmc_tryv(unsigned char); - ptree_to_pmc_tryv(signed short); - ptree_to_pmc_tryv(unsigned short); - ptree_to_pmc_tryv(signed int); - ptree_to_pmc_tryv(unsigned int); - ptree_to_pmc_tryv(signed long); - ptree_to_pmc_tryv(unsigned long); - ptree_to_pmc_tryv(signed long long); - ptree_to_pmc_tryv(unsigned long long); - ptree_to_pmc_tryv(float); - ptree_to_pmc_tryv(double); - ptree_to_pmc_tryv(std::complex<float>); - ptree_to_pmc_tryv(std::complex<double>); //otherwise null -- will crap out return PMC(); diff --git a/lib/top_block_query.cpp b/lib/top_block_query.cpp index 7a5e13e..ee9d234 100644 --- a/lib/top_block_query.cpp +++ b/lib/top_block_query.cpp @@ -36,28 +36,11 @@ static ptree query_blocks(ElementImpl *self, const ptree &) { BlockActor *actor = dynamic_cast<BlockActor *>(w->get_actor()); ptree prop_e; - /* - typedef std::pair<std::string, PropertyRegistryPair> PropRegistryKVP; - BOOST_FOREACH(const PropRegistryKVP &p, actor->data->property_registry) + BOOST_FOREACH(const std::string &key, actor->data->block->get_registered_keys()) { - ptree prop_attrs; - if (p.second.setter) - { - ptree type; - type.put_value(p.second.setter->type().name()); - prop_attrs.push_back(std::make_pair("setter", type)); - } - if (p.second.getter) - { - ptree type; - type.put_value(p.second.getter->type().name()); - prop_attrs.push_back(std::make_pair("getter", type)); - } - ptree block_attrs; - block_attrs.push_back(std::make_pair(p.first, prop_attrs)); - prop_e.push_back(std::make_pair("props", block_attrs)); + ptree pname; pname.put_value(key); + prop_e.push_back(std::make_pair("call", pname)); } - */ e.push_back(std::make_pair(actor->data->block->get_uid(), prop_e)); } root.push_back(std::make_pair("blocks", e)); @@ -174,32 +157,28 @@ static ptree query_stats(ElementImpl *self, const ptree &query) return root; } -static ptree query_props(ElementImpl *self, const ptree &query) +static ptree query_calls(ElementImpl *self, const ptree &query) { ptree root; const std::string block_id = query.get<std::string>("block"); - const std::string prop_key = query.get<std::string>("key"); - const bool set = query.count("value") != 0; + const std::string call_name = query.get<std::string>("name"); BOOST_FOREACH(Apology::Worker *w, self->executor->get_workers()) { BlockActor *actor = dynamic_cast<BlockActor *>(w->get_actor()); if (actor->data->block->get_uid() != block_id) continue; - /* - if (set) + PMCList args; + if (query.count("args") != 0) { - const std::type_info &t = actor->data->property_registry[prop_key].setter->type(); - const PMCC p = ptree_to_pmc(query.get_child("value"), t); - actor->data->block->Block::_set_property(prop_key, p); - } - else - { - PMCC p = actor->data->block->Block::_get_property(prop_key); - ptree v = pmc_to_ptree(p); - root.push_back(std::make_pair("block", query.get_child("block"))); - root.push_back(std::make_pair("key", query.get_child("key"))); - root.push_back(std::make_pair("value", v)); + BOOST_FOREACH(const ptree::value_type &elem, query.get_child("args")) + { + args.push_back(ptree_to_pmc(elem.second)); + } } - */ + const PMCC p = actor->data->block->Block::_handle_call(call_name, PMC_M(args)); + ptree v = pmc_to_ptree(p); + root.push_back(std::make_pair("block", query.get_child("block"))); + root.push_back(std::make_pair("name", query.get_child("name"))); + root.push_back(std::make_pair("value", v)); } return root; } @@ -269,6 +248,6 @@ std::string TopBlock::query(const std::string &args) if (path == "/topology.dot") return query_topology(this->get(), query); if (path == "/blocks.json") result = query_blocks(this->get(), query); if (path == "/stats.json") result = query_stats(this->get(), query); - if (path == "/props.json") result = query_props(this->get(), query); + if (path == "/calls.json") result = query_calls(this->get(), query); return ptree_to_json(result); } diff --git a/python/gras/GRAS_PyBlock.i b/python/gras/GRAS_PyBlock.i index ff91a6f..80fc2bb 100644 --- a/python/gras/GRAS_PyBlock.i +++ b/python/gras/GRAS_PyBlock.i @@ -170,6 +170,18 @@ struct BlockPython : Block } virtual PMCC _Py_handle_call_ts(const std::string &key, const PMCC &args) = 0; + + //dummy registration so the C++ knows at least the key names + void dummy_register_call(const std::string &key) + { + this->register_call(key, &BlockPython::__my_dummy); + } + + //dummy call that should not really be called! + void __my_dummy(void) + { + throw std::runtime_error("BlockPython dummy method called -- should not happen!"); + } }; } @@ -281,5 +293,6 @@ class PyBlock(BlockPython): return PMC_M(pyret) def register_call(self, key, call): + self.dummy_register_call(key) #c++ knows key name self.__call_registry[key] = call %} diff --git a/tests/query_test.py b/tests/query_test.py index 98561ff..8e5bfaf 100644 --- a/tests/query_test.py +++ b/tests/query_test.py @@ -9,11 +9,11 @@ class MyBlock(gras.Block): def __init__(self): gras.Block.__init__(self, "MyBlock", out_sig=[numpy.uint32], in_sig=[numpy.uint32]) self.numeric_value = 0 - self.register_getter("numeric_value", self.get_numeric_value) - self.register_setter("numeric_value", self.set_numeric_value) + self.register_call("get_numeric_value", self.get_numeric_value) + self.register_call("set_numeric_value", self.set_numeric_value) self.vector_value = [0] - self.register_getter("vector_value", self.get_vector_value) - self.register_setter("vector_value", self.set_vector_value) + self.register_call("get_vector_value", self.get_vector_value) + self.register_call("set_vector_value", self.set_vector_value) def work(self, ins, outs): n = min(len(ins[0]), len(outs[0])) @@ -85,37 +85,37 @@ class QueryTest(unittest.TestCase): #set the integer property self.tb.query(dict( - path="/props.json", + path="/calls.json", block='test_numeric_query', - key='numeric_value', - value=42, + name='set_numeric_value', + args=[42], )) self.assertEqual(block.numeric_value, 42) #get the integer property - block.set('numeric_value', 21) + block.set_numeric_value(21) result = self.tb.query(dict( - path="/props.json", + path="/calls.json", block='test_numeric_query', - key='numeric_value', + name='get_numeric_value', )) self.assertEqual(result['value'], 21) #set the complex property self.tb.query(dict( - path="/props.json", + path="/calls.json", block='test_numeric_query', - key='numeric_value', - value='(0, 42)', + name='set_numeric_value', + args=['(0, 42)'], )) self.assertEqual(block.numeric_value, 42j) #get the complex property - block.set('numeric_value', 21j) + block.set_numeric_value(21j) result = self.tb.query(dict( - path="/props.json", + path="/calls.json", block='test_numeric_query', - key='numeric_value', + name='get_numeric_value', )) self.assertEqual(result['value'], '(0,21)') @@ -129,19 +129,19 @@ class QueryTest(unittest.TestCase): #set the vector property self.tb.query(dict( - path="/props.json", + path="/calls.json", block='test_vector_query', - key='vector_value', - value=[1, 2, 3, 4, 5], + name='set_vector_value', + args=[[1, 2, 3, 4, 5]], )) self.assertEqual(list(block.vector_value), [1, 2, 3, 4, 5]) #get the vector property - block.set('vector_value', [6, 7, 8, 9]) + block.set_vector_value([6, 7, 8, 9]) result = self.tb.query(dict( - path="/props.json", + path="/calls.json", block='test_vector_query', - key='vector_value', + name='get_vector_value', )) self.assertEqual(list(result['value']), [6, 7, 8, 9]) |