datafolklabs / cement Goto Github PK
View Code? Open in Web Editor NEWApplication Framework for Python
Home Page: http://builtoncement.com
License: BSD 3-Clause "New" or "Revised" License
Application Framework for Python
Home Page: http://builtoncement.com
License: BSD 3-Clause "New" or "Revised" License
In the following section, missing a ..code-block:
You will also notice that your app is already loading an ‘example’ plugin. Plugins are enabled under their [plugin] config either in your main application configuration file, or in the plugins.d/.conf file for that plugin. An example plugin config looks like: [example] enable_plugin = true provider = helloworld
RFE: Add INIT script to pasted projects
The documentation on namespaces and how config options and --options interact is lacking. Should include some examples of accessing root_config['namespace']['namespace_option'] as well as how --options overwrite config['options'].
For example... if you have a namespace called 'my-namespace', it will fail to load becasue the actual module is 'my_namespace'. When loaded namespaces... the '-' should be converted to '_' just when loaded the controller.
currently, if I pass --myoption to the root namespace, it will overwrite namespaces['root'].config['myoption'] ... but not any other namespaces such as namespaces['my_other_namespace'].config['myoption']. I'm not completely sold that this is a good idea... the general thought is:
--option defined as global scope (root namespace, and inherited by merge_root_options) would generally mean that namespaces['root'].config['myoption'] is also used in global scope.
Testing within cement is difficult as it mostly relies on a functioning application built on cement to really test functionality. Additionally, need to maintain a 'helloworld' test application for each version of cement to ensure previous versions of the same API don't break with new updates.
Most users won't really understand the difference between a command and a namespace.. So passing
$ myapp namespace-helpshould automatically run
$ myapp namespace --helprather than error out and telling the user to do it. Should be possible run_namespace_command().
Also, would be nice to clean up '--help' to separate commands and namespaces... something like:
Commands: cmd1, cmd2, cmd3, cmd4 Namespaces: namespace1*, namespace2*, namespace3* Help? try [COMMAND]-help *OR* [NAMESPACE]-help
Following issues were passed along via email:
1) I believe that the project's generated Exception classes should be capitalized (in .../core/exc.py). In fact, in the "default" method of the RootController class (in .../controllers/root.py), you raise an ArgumentError when no command is passed to the script. The class name is correctly capitalized here but the class definitions are not. (You may also want to check any other files that raise Exceptions: After capitalizing all of the class names manually, I got an ImportError from .../core/appmain.py. I didn't check anywhere else and changed that definitions back to the original.) 2) Also in the Exception class definitions, the base Exception class(MyPyProject) should probably also have a __unicode__ method like: def __unicode__(self): return unicode(self.msg) in case anyone is expecting/dealing with Unicode.
On successful registration of a hook function via @register_hook() decorator, the original func is not returned. Subsequent calls to that function directly result in:
TypeError: 'NoneType' object is not callable
$ helloworld myplugin this-command-is-bogus
CementArgumentError > Unknown command 'myplugin', see --help?
Should be:
$ helloworld myplugin this-command-is-bogus
CementArgumentError > Unknown command 'this-command-is-bogus', see --help?
$ myapp bogus_command CementArgumentError > Unknown command 'bogus_command', see --help?
Should catch CementArgumentError, but display 'MyAppArgumentError' (paster template change).
Hit enter too quickly. I see cement is dependent on python2.6 in various respects and I was testing under 2.4 on a centos5 server.
Sorry for the noise.
Was testing the default root command (not passing anything to args and letting it trigger the default):
====================================================================== ERROR: root_tests.test_default_raises_exception ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/wdierkes/env/mf/lib/python2.7/site-packages/nose-1.0.0-py2.7.egg/nose/case.py", line 187, in runTest self.test(*self.arg) File "/Users/wdierkes/devel/monkeyfarm/client/tests/root_tests.py", line 39, in test_default_raises_exception (res_dict, output_txt) = simulate(args) File "/Users/wdierkes/env/mf/lib/python2.7/site-packages/cement-0.8.16-py2.7.egg/cement/core/testing.py", line 34, in simulate cmd = re.sub('-', '_', sys.argv[1]) IndexError: list index out of range @raises(MFArgumentError) @with_setup(setup_func, teardown_func) def test_default_raises_exception(): # This fails because only the default command is to raise an exception args = [__file__] (res_dict, output_txt) = simulate(args)
Would be interesting to have paste commands or options that would add waf support for a pasted project.
http://freehackers.org/~tnagy/wafbook/index.html#_obtaining_waf
As of 0.8.1 command functions can return 'output_file' in its return dictionary... which then writes the output to the file (after rendering from Genshi/JSON/Etc.
This could be huge if it had some real documentation :)
For packaging needs, we need to move the paster stuff to its own package (because the setup.py for cement references the paster plugins in cement-devel):
$ paster --help Usage: paster [paster_options] COMMAND [command_options] Options: --version show program's version number and exit --plugin=PLUGINS Add a plugin to the list of commands (plugins are Egg specs; will also require() the Egg) -h, --help Show this help message Cannot load command cement-app: No module named paste.commands Cannot load command cement-plugin: No module named paste.commands Cannot load command cement-helper: No module named paste.commands Commands: create Create the file layout for a Python distribution help Display help make-config Install a package and create a fresh config file/directory points Show information about entry points post Run a request for the described application request Run a request for the described application serve Serve the described application setup-app Setup an application, given a config file
Might be nice to be able to easily setup [hidden?] aliases for commands, something like:
@expose(aliases=['del', 'rm'], namespace='root') def delete(self, *args, **kw): # delete something ....
Currently --help looks like:
Commands: cmd1, cmd2, cmd3 Namespaces: nam1, nam2, nam3
Would be cool to offer an alternate layout like:
Commands: cmd1 This is my command description cmd2 This is what the cmd2 does cmd3 This is something else Namespaces: nam1 This is the description of nam1 nam2 This is the description of nam2
Yo!
from my "collect" namespace controller, I do this:
root_config= get_config() basedir= root_config['app_basepath'] log.debug("Generating SQL template for %s" % config['store']) # Get the templated SQL for MySQL schema creation templ_filename= os.path.join(basedir, "templates", "collect", "remove_schema.mysql.sql") templ= NewTextTemplate(open(templ_filename).read())
and I get the following:
(tiktok)jpipes@serialcoder:~/virtualenv/tiktok/tiktok$ tiktok collect removedb Traceback (most recent call last): File "/home/jpipes/virtualenv/tiktok/bin/tiktok", line 8, in load_entry_point('tiktok==0.1', 'console_scripts', 'tiktok')() File "/home/jpipes/virtualenv/tiktok/tiktok/tiktok/core/appmain.py", line 39, in main run_command(sys.argv[1]) File "/home/jpipes/virtualenv/tiktok/lib/python2.6/site-packages/Cement-0.8-py2.6.egg/cement/core/command.py", line 76, in run_command cli_opts=cli_opts, cli_args=cli_args) File "/home/jpipes/virtualenv/tiktok/lib/python2.6/site-packages/Cement-0.8-py2.6.egg/cement/core/controller.py", line 55, in run_controller_command func = getattr(controller, func)(*args, **kw) File "/home/jpipes/virtualenv/tiktok/lib/python2.6/site-packages/Cement-0.8-py2.6.egg/cement/core/view.py", line 62, in wrapper res = self.func(*args, **kw) File "/home/jpipes/virtualenv/tiktok/tiktok/tiktok/controllers/collect.py", line 133, in removedb templ= NewTextTemplate(open(templ_filename).read()) IOError: [Errno 2] No such file or directory: '/home/jpipes/virtualenv/tiktok/tiktok/tiktok/core/templates/collect/remove_schema.mysql.sql'
config['app_basepath'] is set in /core/config.py to this:
dcf['app_basepath'] = os.path.dirname(file)
Unfortunately, file is in $app_name/core/config.py and therefore, the app_basepath gets set to that /core directory. I believe it should be one directory level up?
Cheers!
jay
.... Or atleast document how to do it.
May be able to easily expose -help commands for controller functions.. if they have doc strings. Just an idea.
loading clibasic plugin Traceback (most recent call last): File "/Users/wdierkes/env/mf/bin/mf", line 8, in load_entry_point('monkeyfarm==0.1', 'console_scripts', 'mf')() File "/Users/wdierkes/devel/monkeyfarm/mf/mf/core/appmain.py", line 39, in main run_command(sys.argv[1]) File "/Users/wdierkes/devel/cement/cement/core/command.py", line 76, in run_command cli_opts=cli_opts, cli_args=cli_args) File "/Users/wdierkes/devel/cement/cement/core/controller.py", line 55, in run_controller_command func = getattr(controller, func)(*args, **kw) File "/Users/wdierkes/devel/cement/cement/core/view.py", line 62, in wrapper res = self.func(*args, **kw) File "/Users/wdierkes/devel/monkeyfarm/mf/mf/controllers/distro.py", line 27, in create abort_on_error(errors) File "/Users/wdierkes/devel/rosendale/rosendale/helpers/error.py", line 12, in abort_on_error abort(errors) File "/Users/wdierkes/devel/rosendale/rosendale/helpers/error.py", line 54, in abort run_controller_command('root', 'error', errors=errors) File "/Users/wdierkes/devel/cement/cement/core/controller.py", line 55, in run_controller_command func = getattr(controller, func)(*args, **kw) File "/Users/wdierkes/devel/cement/cement/core/view.py", line 80, in wrapper print tmpl.generate(**res).render() File "build/bdist.macosx-10.6-universal/egg/genshi/core.py", line 179, in render File "build/bdist.macosx-10.6-universal/egg/genshi/output.py", line 60, in encode File "build/bdist.macosx-10.6-universal/egg/genshi/output.py", line 515, in __call__ File "build/bdist.macosx-10.6-universal/egg/genshi/core.py", line 283, in _ensure File "build/bdist.macosx-10.6-universal/egg/genshi/template/base.py", line 543, in _exec File "build/bdist.macosx-10.6-universal/egg/genshi/template/base.py", line 520, in _eval File "build/bdist.macosx-10.6-universal/egg/genshi/template/base.py", line 286, in _eval_expr File "build/bdist.macosx-10.6-universal/egg/genshi/template/eval.py", line 180, in evaluate File "", line 11, in File "build/bdist.macosx-10.6-universal/egg/genshi/template/eval.py", line 330, in lookup_item TypeError: list indices must be integers, not tuple
validate_config_hook doesn't work so great for sub blocks... seems only the root config gets passed to a validate_config_hook registered function... so in the registered_function... you need to do:
from cement.core.namespace import get_config config = get_config('namespace_I_want')
Remove the following from doc under "An Overview of Features".
This is currently labeled as experimental, only because it has the potential to blow up on itself if you pass it data that is not serializable. For example, a function object will not serialize... however we’ve added a wrapper to Jsonify classes base on the __dict__.
In setup_logging, backupCount=int(config['log_max_bytes']) should be log_max_files.
If root, install to /etc//.conf, if not install to ~/..conf. Not sure how to make all that work properly, currently no configs are installed and a warning is thrown.
In helloworld.core.config:
from cement.core.namespace import get_config as cement_get_config def get_config(namespace='root'): return cement_get_config(namespace)
log_to_console should only disable logger from printing to console... but with it set to 'false' it seems even genshi output isn't rendered.
Not properly calling CementNamespace .... for plugins should explicitly pass version, required_cement_api, description, etc:
sayhi = CementNamespace('sayhi', controller='sayhiController')
Remove base app module from namespace packages in setup.py (app, plugin) and remove the namespace declaration in init.py
None of the docstrings generated sphinx documentation in cement 0.8.10 ... see http://buildoncement.org under API documentation.
RFE: Change default config statedir to ~/ rather than ./
When the time comes that Cement makes it into Fedora/Ubuntu/Etc ... Need a standard way of supporting multiple API versions. This might just be having 'lay_cement' be a wrapper to alternative lay_cement versions... or something more complicated. Essentialy, every call that needs to change for an API version could check required_api_version and redirect to alternate functions if necessary... but need to figure that out and test, test, test.
Test
with markdown
af
asdf
asdf
Can add the option of returning 'output_file' in the return dict to render. If output_file exists in dict, write output to the file.
The following is the result of registering a namespace called 'greetings' in a bootstrap file, but where the 'controller/greetings.py' doesn't yet exist.
Traceback (most recent call last): File "/usr/local/bin/helloworld", line 8, in load_entry_point('helloworld==0.1', 'console_scripts', 'helloworld')() File "/home/nahil/helloworld/helloworld/core/appmain.py", line 31, in main lay_cement(config=default_config, banner=BANNER) File "/usr/local/lib/python2.6/dist-packages/Cement-0.8-py2.6.egg/cement/core/app_setup.py", line 130, in lay_cement globals(), locals(), ['root'], -1) File "/home/nahil/helloworld/helloworld/bootstrap/root.py", line 30, in from helloworld.bootstrap import greetings File "/home/nahil/helloworld/helloworld/bootstrap/greetings.py", line 12, in register_namespace(greetings) File "/usr/local/lib/python2.6/dist-packages/Cement-0.8-py2.6.egg/cement/core/namespace.py", line 162, in register_namespace globals(), locals(), [namespace_obj.controller], -1) ImportError: No module named greetings
Would be a good idea to perhaps try/except around this situation and make the error clear to the user, as well as add something to the documentation to clarify the relationship between namespace and controller.
Simplify a bit... error handling is very app specific and can easily be added outside of the template.
Adding imports to app/model/init.py causes a 'No handlers found for cement.core.namespace' error because logging isn't setup when the module is imported. Should have a basic root logger setup before anything (it gets removed by lay_cement anyway).
Nothing is logged from shared plugins. For example, using rosendale.clibasic... nothing will log from that provider.
$ myapp command --json | python -mjson.tool
Option Parsing, Config File Parsing, Logging, Templating (Genshi/Json), etc... should eventually be abstracted out into plugins so that they can be replaced by comparable pieces that provide the same purpose with other functionality. Should start with templating which should be relatively easy.
Need to allow users to create cement-{app,plugin,helper} projects from an alternate template location.
If a plugin [block] is added to the primary applictions config file, but also has a plugin config.. the plugin is loaded twice... and lists twice with 'list-plugins' from rosendale.
currently there is no way to override the default fmt and datefmt in logging output.
it would be useful to expose that as a configuration option.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.