| 1 | [wiki:DeveloperGuidelines] | S3 |
| 2 | |
| 3 | = S3 Framework Extensions for Web2py = |
| 4 | |
| 5 | All S3 framework extensions for web2py reside as a Python package in {{{modules/s3}}}: |
| 6 | |
| 7 | ||'''Module'''||'''Functionality'''|| |
| 8 | ||s3aaa||Authentication, Authorization, Accouting|| |
| 9 | ||s3cfg||Deployment Settings|| |
| 10 | ||s3gis||GIS Module|| |
| 11 | ||s3msg||Messaging API|| |
| 12 | ||s3test|| || |
| 13 | ||s3tools||Tools|| |
| 14 | ||s3utils||Utilities|| |
| 15 | ||s3validators||Custom Validators|| |
| 16 | ||s3vita||Person Finder Toolkit (VITA)|| |
| 17 | ||s3widgets||Custom UI Widgets|| |
| 18 | ||s3xrc||Extensible Resource Controller (S3XRC)|| |
| 19 | ||s3rest||RESTful API (S3XRC)|| |
| 20 | ||s3crud||RESTful CRUD Methods (S3XRC)|| |
| 21 | ||s3search||RESTful Search Methods|| |
| 22 | ||s3export||Resource Export Toolkit (S3XRC)|| |
| 23 | ||s3import||Resource Import Toolkit (S3XRC)|| |
| 24 | ||s3model||Data Model Extensions (S3XRC)|| |
| 25 | ||s3xml||XML Toolkit (S3XML)|| |
| 26 | |
| 27 | == The s3base Namespace == |
| 28 | |
| 29 | The names of the S3 package (=classes, functions, constants) are defined in {{{modules/s3/__init__.py}}} - all names which are imported in this file are available under the {{{s3base}}} namespace. |
| 30 | |
| 31 | This namespace is imported in {{{models/000_1st_run.py}}}, thus it is available to ''all'' models and controllers - you don't need to import any S3 names separately, and neither do you need to think under which namespace a S3 class or function is available: always simply use the {{{s3base}}} prefix: |
| 32 | |
| 33 | {{{ |
| 34 | gis = s3base.GIS(...) |
| 35 | resource = s3base.S3Resource(...) |
| 36 | }}} |
| 37 | |
| 38 | For convenience, the names of {{{s3utils}}}, {{{s3widgets}}} and {{{s3validators}}} are also imported into the global namespace, so you do not need a namesace prefix to access them: |
| 39 | |
| 40 | {{{ |
| 41 | mytable.myfield.requires = IS_UTC_DATETIME() |
| 42 | mywidget = S3CheckboxWidget.widget() |
| 43 | }}} |
| 44 | |
| 45 | == Extending S3 == |
| 46 | |
| 47 | If you're going to add things to S3, please do it at the right place: |
| 48 | |
| 49 | - Utility functions which are meant to be globally available belong into {{{modules/s3/s3utils.py}}} |
| 50 | - All other utility functions should either be class methods or should not be globally available |
| 51 | - New classes should be added to the respective modules |
| 52 | - New modules should be added as separate files |
| 53 | |
| 54 | To make a class, function or constant available in the {{{s3base}}} namespace, you should import it in {{{modules/s3/__init__.py}}}: |
| 55 | |
| 56 | {{{ |
| 57 | from s3xrc import S3ResourceController |
| 58 | }}} |
| 59 | |
| 60 | Note that you need to use the {{{from s3xxx import yyy}}} notation (relative import). |
| 61 | |
| 62 | == Importing Modules == |
| 63 | |
| 64 | Any submodule in modules/s3 can import names from any other submodule in modules/s3 by simply {{{from s3xxx import yyy}}}, by relative import: |
| 65 | |
| 66 | {{{ |
| 67 | from s3xrc import S3ResourceController |
| 68 | }}} |
| 69 | |
| 70 | If you use the wildcard: |
| 71 | |
| 72 | {{{ |
| 73 | from s3xxx import * |
| 74 | }}} |
| 75 | |
| 76 | then you have to ensure that the name you want to import is listed in the {{{__all__}}} variable inside the respective {{{s3xxx}}} submodule: |
| 77 | |
| 78 | {{{ |
| 79 | __all__ = ["MyClass", "MyOtherClass"] |
| 80 | }}} |
| 81 | |
| 82 | If {{{__all___}}} is not declared inside a submodule, then all names are imported - but this should be avoided. |
| 83 | |
| 84 | You can also import names from other modules in the {{{modules}}} directory, by relative import: |
| 85 | |
| 86 | {{{ |
| 87 | from ..pyparsing import ParseBaseException |
| 88 | }}} |
| 89 | |
| 90 | Note the {{{..}}} before the module path. |
| 91 | |
| 92 | == Coding Conventions == |
| 93 | |
| 94 | Please consider our coding conventions when coding S3 extensions: |
| 95 | |
| 96 | - names of top-level functions must be prefixed by {{{s3_}}}, must be all lowercase (no CamelCase!), with words separated by underscores, e.g. {{{s3_my_function}}} |
| 97 | - names of genuine S3 classes (even if based on web2py classes) must be prefixed by S3, and use CamelCase, e.g. {{{S3ResourceController}}} |
| 98 | - names of customized web2py classes (which are meant to be used instead of the native web2py class) are ''suffixed'' with S3, e.g. {{{AuthS3}}} |
| 99 | - constants must be prefixed by S3, all uppercase, with words separated by underscores, e.g. S3_MY_CONSTANT |
| 100 | - functions inside of classes can be named arbitrarily, however, their names should somehow indicate what they do |
| 101 | |
| 102 | - all modules must have a docstring describing the module, the module author(s), the copyright and license |
| 103 | - the copyright statement must declare the SSF as copyright holder, and the license must be MIT |
| 104 | - dependencies can be declared with the {{{@requires:}}} statement |
| 105 | |
| 106 | {{{ |
| 107 | """ Utilities |
| 108 | |
| 109 | @requires: U{B{I{gluon}} <http://web2py.com>} |
| 110 | |
| 111 | @author: Fran Boon <fran[at]aidiq.com> |
| 112 | @author: Michael Howden <michael[at]aidiq.com> |
| 113 | @author: Pradnya Kulkarni |
| 114 | |
| 115 | @copyright: (c) 2010 Sahana Software Foundation |
| 116 | @license: MIT |
| 117 | |
| 118 | Permission is hereby granted, free of charge, to any person |
| 119 | obtaining a copy of this software and associated documentation |
| 120 | files (the "Software"), to deal in the Software without |
| 121 | restriction, including without limitation the rights to use, |
| 122 | copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 123 | copies of the Software, and to permit persons to whom the |
| 124 | Software is furnished to do so, subject to the following |
| 125 | conditions: |
| 126 | |
| 127 | The above copyright notice and this permission notice shall be |
| 128 | included in all copies or substantial portions of the Software. |
| 129 | |
| 130 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 131 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
| 132 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 133 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
| 134 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
| 135 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| 136 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| 137 | OTHER DEALINGS IN THE SOFTWARE. |
| 138 | |
| 139 | """ |
| 140 | |
| 141 | }}} |
| 142 | |
| 143 | |
| 144 | - all functions - in classes or top-level - must have docstrings explaining what they are supposed to do |
| 145 | - the docstring should contain an {{{@author: }}} tag if the author differs from the module author |
| 146 | - you should add your email address, if you want others to contact you with questions or suggestions |
| 147 | |
| 148 | {{{ |
| 149 | def shn_split_multi_value(value): |
| 150 | """ |
| 151 | @author: Michael Howden <michael[at]aidiq.com> |
| 152 | |
| 153 | Converts a series of numbers delimited by |, or already in a string into a list |
| 154 | |
| 155 | If value = None, returns [] |
| 156 | |
| 157 | """ |
| 158 | |
| 159 | }}} |
| 160 | |
| 161 | - use {{{@status:}}} to indicate the current status of the implementation |
| 162 | - use {{{@see:}}} to refer to web pages (e.g. Eden wiki pages) |
| 163 | - see [http://epydoc.sourceforge.net/manual-fields.html] for more docstring tags |