Skin Generator 1.0
Skin Generator é um pequeno aplicativo de código aberto que cria uma skin para Plone 3 de forma rápida e automatizada.
SkinGenerator.py — Python Source, 56Kb
Conteúdo do arquivo
# -*- coding: utf-8 -*- # GNU General Public License (GPL) # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # import os, base64 # Criação: 08/11/2008 # Última Atualização: 09/11/2008 project_version = '1.0' project_creditos = \ """ Autor: Herson Rodrigues E-mail: hersonrodrigues@gmail.com Versão: %s\n"""%project_version project_license = ' GNU General Public License (GPL)\n' class createSkin: """Classe de criação""" def __init__(self): self.container = [] def setContainer(self, nome): """Cria uma pasta container""" os.system('mkdir ' + nome) self.container = nome print 'Criado a pasta %s' %nome def getContainer(self, nome): """Retorna a pasta container""" if self.container: return self.container self.setContainer(nome) return nome def cria_pasta(self, nome, diretorio): """Cria uma pasta""" os.system('mkdir ' + diretorio + '/' + nome) print 'Criado a pasta %s' %nome return diretorio + '/' + nome def cria_arquivo(self, nome, diretorio, texto): """Cria um arquivo""" f = open(diretorio +'/'+ nome, 'w') f.write(texto) f.close() print 'Criado o arquivo %s' %nome ############################################################################### skin = createSkin() print '\n\n\n\n #### SKIN GENERATOR #### \n' print project_creditos print project_license project_name = raw_input(">>> Digite o nome da sua skin: ") if not project_name: print 'Não foi digitado um nome válido, o programa está sendo finalizado' else: project_site = raw_input(">>> Digite o nome do Site: ") if not project_site: project_site = 'Defina um nome para o site no arquivo properties.xml' # Portlets project_portlets = raw_input(">>> Quantos portlets gostaria de criar?: ") if not project_portlets: project_portlets = 0 project_portlets_items = 0 else: project_portlets = int(project_portlets) project_portlets_items = [] for i in range(project_portlets): contador = str(i+1) portlet = \ raw_input(">>> Qual o nome do portlet número "+contador+"?: ") if not portlet: portlet = 'Indefinido'+str(i) position = \ raw_input(">>> Qual a posição do portlet "+portlet+" [D/E]?: ") if position.upper() == 'E': position = 'left' else: position = 'right' project_portlets_items.append({'portlet' : portlet, 'position' : position}) # Cria a raiz da skin skin.getContainer(project_name) container = skin.getContainer(project_name) containerlower = container.lower() icontainer = container[0].upper()+container[1:] # Arquivo configure.zcml texto = \ """<configure xmlns="http://namespaces.zope.org/zope"> <include package=".browser" /> <include file="profiles.zcml" /> </configure> """ skin.cria_arquivo('configure.zcml', container, texto) # Arquivo profiles.zcml texto = \ """<configure xmlns="http://namespaces.zope.org/zope" xmlns:genericsetup="http://namespaces.zope.org/genericsetup" i18n_domain="%s"> <genericsetup:registerProfile name="default" title="%s" directory="profiles/default" description="Extension profile for %s." provides="Products.GenericSetup.interfaces.EXTENSION" /> </configure>"""%(containerlower, container, container) skin.cria_arquivo('profiles.zcml', container, texto) # Arquivo __init__.py texto = \ """from Products.CMFCore.DirectoryView import registerDirectory GLOBALS = globals() registerDirectory('skins', GLOBALS)""" skin.cria_arquivo('__init__.py', container, texto) # Arquivo AUTOR texto = \ """Autor: Herson Rodrigues Santos Página: http://herson.objectis.net E-mail: hersonrodrigues@gmail.com """ skin.cria_arquivo('AUTOR', container, texto) # Arquivo LICENSE texto = \ """ GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For %s, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS""" skin.cria_arquivo('LICENSE', container, texto) # Pasta Skins pasta_skins = skin.cria_pasta('skins', container) # Pasta Styles pasta_skins_styles = skin.cria_pasta(containerlower+'_styles', pasta_skins) # Pasta Imagens pasta_skins_imagens = skin.cria_pasta(containerlower+'_imagens', pasta_skins) # Pasta Templates pasta_skins_templates = skin.cria_pasta(containerlower+'_templates', pasta_skins) texto = \ "title:string="+container+"'s color, font, logo and border \ defaults\n plone_skin:string="+container + """ logoName:string=logo.jpg fontFamily:string="Lucida Grande", Verdana, Lucida, Helvetica, Arial, sans-serif fontBaseSize:string=69% fontColor:string=Black fontSmallSize:string=85% backgroundColor:string=White linkColor:string=#436976 linkActiveColor:string=Red linkVisitedColor:string=Purple borderWidth:string=1px borderStyle:string=solid borderStyleAnnotations:string=dashed globalBorderColor:string=#8cacbb globalBackgroundColor:string=#dee7ec globalFontColor:string=#436976 headingFontFamily:string="Lucida Grande", Verdana, Lucida, Helvetica, Arial, sans-serif contentViewBorderColor:string=#74ae0b contentViewBackgroundColor:string=#cde2a7 contentViewFontColor:string=#578308 inputFontColor:string=Black textTransform:string=lowercase evenRowBackgroundColor:string=#eef3f5 oddRowBackgroundColor:string=transparent notifyBorderColor:string=#ffa500 notifyBackgroundColor:string=#ffce7b discreetColor:string=#76797c helpBackgroundColor:string=#ffffe1 portalMinWidth:string=70em columnOneWidth:string=16em columnTwoWidth:string=16em""" # Arquivo base_properties.props skin.cria_arquivo('base_properties.props', pasta_skins_styles, texto) # Arquivo SeuArquivo.css.dtml texto = "/* INICIO DO CSS */\n\n\n\n/* FINAL DO CSS */" skin.cria_arquivo(container+'.css.dtml', pasta_skins_styles, texto) # Arquivo SeuArquivo.js texto = """// INICIO DO JAVASCRIPT \n\n \ // Jquery\njq(document).ready(function(){\n\n\n\n}); // Jquery Fim\n\n// FINAL DO JAVASCRIPT """ skin.cria_arquivo(container+'.js', pasta_skins_styles, texto) # Arquivo pagina_inicial.pt texto = \ """<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal" xmlns:metal="http://xml.zope.org/namespaces/metal" xmlns:i18n="http://xml.zope.org/namespaces/i18n" metal:use-macro="here/main_template/macros/master" i18n:domain="plone"> <head> <title tal:content="template/title">The title</title> <meta http-equiv="content-type" content="text/html;charset=utf-8"> </head> <body metal:fill-slot="main"> <h1 tal:content="context/Title">Titulo</h1> <div> Coloque aqui suas div's e estruturas htmls </div> </body> </html>""" skin.cria_arquivo('pagina_inicial.pt', pasta_skins_templates, texto) # Arquivo logo.jpg # Serializado com: base64.encodestring(open(logo.jpg,"rb").read()) texto = \ """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 cBxxxwHHHHA//9k= """ # Deserializando texto = base64.b64decode(texto) skin.cria_arquivo('logo.jpg', pasta_skins_imagens, texto) # Pasta Profiles pasta_profiles = skin.cria_pasta('profiles', container) # Pasta Default pasta_profiles_default = skin.cria_pasta('default', pasta_profiles) # Arquivo cssregistry.xml texto = \ """<?xml version="1.0"?> <object name="portal_css"> <stylesheet id="%s.css" title="" cacheable="True" compression="safe" cookable="True" enabled="1" expression="" media="all" rel="stylesheet" rendering="import"/> </object> """%container skin.cria_arquivo('cssregistry.xml', pasta_profiles_default, texto) # Arquivo jsregistry.xml texto = \ """<?xml version="1.0"?> <object name="portal_javascripts"> <javascript id="%s.js" cacheable="False" compression="safe" cookable="False" enabled="True" expression="" inline="False"/> </object>"""%container skin.cria_arquivo('jsregistry.xml', pasta_profiles_default, texto) # Arquivo properties.xml texto = \ """<?xml version="1.0"?> <site> <property name="title">%s</property> <property name="description"></property> <property name="default_page" type="string">pagina_inicial</property> <property name="selectable_views" type="lines"> <element value="folder_listing"/> <element value="news_listing"/> </property> <property name="email_from_address" type="string"></property> <property name="email_from_name" type="string">Administração - %s</property> <property name="validate_email" type="boolean">False</property> <property name="email_charset" type="string">utf-8</property> <property name="enable_permalink" type="boolean">False</property> </site>"""%(project_site, project_site) skin.cria_arquivo('properties.xml', pasta_profiles_default, texto) texto_skin = \ """<?xml version="1.0"?> <object name="portal_skins" allow_any="False" cookie_persistence="False" default_skin="%s" request_varname="plone_skin"> <object name="%s" meta_type="Filesystem Directory View" directory="Products.%s:%s/%s"/> <object name="%s" meta_type="Filesystem Directory View" directory="Products.%s:%s/%s"/> <object name="%s" meta_type="Filesystem Directory View" directory="Products.%s:%s/%s"/> <skin-path name="%s" based-on="Plone Default"> <layer name="%s" insert-after="custom"/> <layer name="%s" insert-after="%s"/> <layer name="%s" insert-after="%s"/> </skin-path> </object> """%(container, pasta_skins_imagens.split('/')[-1], container, pasta_skins_imagens.split('/')[-2], pasta_skins_imagens.split('/')[-1], pasta_skins_styles.split('/')[-1], container, pasta_skins_styles.split('/')[-2], pasta_skins_styles.split('/')[-1], pasta_skins_templates.split('/')[-1], container, pasta_skins_templates.split('/')[-2], pasta_skins_templates.split('/')[-1], container, pasta_skins_styles.split('/')[-1], pasta_skins_imagens.split('/')[-1], pasta_skins_styles.split('/')[-1], pasta_skins_templates.split('/')[-1], pasta_skins_imagens.split('/')[-1]) skin.cria_arquivo('skins.xml', pasta_profiles_default, texto_skin) # Arquivo properties.xml texto = \ """<metadata> <description>%s - %s</description> <version>1.0</version> <!-- <dependencies> <dependency>profile-Products.NomeDoProduto:default</dependency> </dependencies> --> </metadata>"""%(container, project_site) skin.cria_arquivo('metadata.xml', pasta_profiles_default, texto) # Arquivo catalog.xml texto = \ """<?xml version="1.0"?> <object name="portal_catalog" meta_type="Plone Catalog Tool"> <!-- Exemplo de criação de indice, veja como pegar os icones dos tipos do plone <index name="icon" meta_type="FieldIndex"> <indexed_attr value="icon"/> </index> <column value="icon"/> --> <!-- Exemplo de criação de indice, este pega o texto das páginas e notícias <index name="getText" meta_type="FieldIndex"> <indexed_attr value="getText"/> </index> <column value="getText"/> --> </object> """ skin.cria_arquivo('catalog.xml', pasta_profiles_default, texto) if project_portlets_items: # Arquivo portlets.xml texto_main = '' texto_main_colum = '' texto_header = \ """<?xml version="1.0"?> <portlets> """ for item in project_portlets_items: portletlower = item['portlet'].lower()+'_portlet' portletname = item['portlet'] portletpos = item['position'] texto_main = texto_main + """ <portlet addview="%s" title="%s" description="" /> """%(portletlower, portletname) texto_main_colum = texto_main_colum + """ <assignment name="%s" category="context" key="/" manager="plone.%scolumn" type="%s"/> """%(portletname, portletpos, portletlower) texto_footer = \ """ </portlets> """ texto = texto_header + texto_main + texto_main_colum + texto_footer skin.cria_arquivo('portlets.xml', pasta_profiles_default, texto) # Pasta Browser pasta_browser = skin.cria_pasta('browser', container) # Arquivo __init__.py texto = '#' skin.cria_arquivo('__init__.py', pasta_browser, texto) # Arquivo interfaces.py texto = \ """from plone.theme.interfaces import IDefaultPloneLayer class I%s(IDefaultPloneLayer): \"\"\"Marcador que define uma interface Zope 3\"\"\" """%(icontainer) skin.cria_arquivo('interfaces.py', pasta_browser, texto) # Arquivo configure.zcml if project_portlets_items: texto_main = '' texto_header = \ """<configure xmlns="http://namespaces.zope.org/zope" xmlns:browser="http://namespaces.zope.org/browser" xmlns:genericsetup="http://namespaces.zope.org/genericsetup" xmlns:plone="http://namespaces.plone.org/plone" i18n_domain="%s"> <interface interface=".interfaces.I%s" type="zope.publisher.interfaces.browser.IBrowserSkinType" name="%s" /> """%(containerlower, icontainer, container) for item in project_portlets_items: portletlower = item['portlet'].lower()+'_portlet' portletname = item['portlet'] portletpos = item['position'] texto_main = texto_main + """<!-- Portlet - %s --> <plone:portlet name="%s" interface=".portlets.I%sPortlet" assignment=".portlets.%sAssignment" view_permission="zope2.View" edit_permission="cmf.ManagePortal" renderer=".portlets.%sRenderer" addview=".portlets.%sAddForm" editview=".portlets.%sEditForm" /> """%(portletname, portletlower, portletname, portletname, portletname, portletname, portletname) texto_footer = \ """ </configure> """ texto = texto_header + texto_main + texto_footer else: texto = \ """<configure xmlns="http://namespaces.zope.org/zope" xmlns:browser="http://namespaces.zope.org/browser" i18n_domain="%s"> <interface interface=".interfaces.I%s" type="zope.publisher.interfaces.browser.IBrowserSkinType" name="%s" /> </configure> """%(containerlower, icontainer, container) skin.cria_arquivo('configure.zcml', pasta_browser, texto) if project_portlets_items: # Pasta Templates pasta_templates = skin.cria_pasta('templates', pasta_browser) # Pasta Portlets pasta_portlets = skin.cria_pasta('portlets', pasta_templates) # Portlet Templates for item in project_portlets_items: portletname = item['portlet'] texto = \ """<html xmlns:tal="http://xml.zope.org/namespaces/tal" xmlns:metal="http://xml.zope.org/namespaces/metal" i18n:domain="plone"> <body> <div metal:define-macro="portlet"> <dl class="portlet %s"> <dt class="portletHeader"> <span class="portletTopLeft"/> <span> %s </span> <span class="portletTopRight"/> </dt> <dd class="portletItem odd"> <p> Escreva aqui o conteúdo do portlet </p> </dd> <dd class="portletFooter"> <span class="portletBottomLeft"/> <span> <a href="#">Veja Mais</a> </span> <span class="portletBottomRight"/> </dd> </dl> </div> </body> </html> """%(portletname, portletname) skin.cria_arquivo(portletname+'.pt', pasta_portlets, texto) if project_portlets_items: # Arquivo porlets.py texto_main = '' texto_header = \ """from zope.interface import Interface from zope.interface import implements from zope import schema from zope.formlib import form from plone.portlets.interfaces import IPortletDataProvider from plone.app.portlets.portlets import base from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile """ for item in project_portlets_items: portletlower = item['portlet'].lower()+'_portlet' portletname = item['portlet'] portletpos = item['position'] texto_main = texto_main + """# Portlet %s class I%sPortlet(IPortletDataProvider): \"\"\"A portlet It inherits from IPortletDataProvider because for this portlet, the data that is being rendered and the portlet assignment itself are the same. \"\"\" class %sAssignment(base.Assignment): \"\"\"Portlet assignment. This is what is actually managed through the portlets UI and associated with columns. \"\"\" implements(I%sPortlet) def __init__(self): pass @property def title(self): \"\"\"This property is used to give the title of the portlet in the \"manage portlets\" screen. \"\"\" return "%s" class %sRenderer(base.Renderer): \"\"\"Portlet renderer. This is registered in configure.zcml. The referenced page template is rendered, and the implicit variable 'view' will refer to an instance of this class. Other methods can be added and referenced in the template. \"\"\" render = ViewPageTemplateFile('%s/%s.pt') class %sAddForm(base.AddForm): \"\"\"Portlet add form. This is registered in configure.zcml. The form_fields variable tells zope.formlib which fields to display. The create() method actually constructs the assignment that is being added. \"\"\" form_fields = form.Fields(I%sPortlet) def create(self, data): return %sAssignment(**data) class %sEditForm(base.EditForm): \"\"\"Portlet edit form. This is registered with configure.zcml. The form_fields variable tells zope.formlib which fields to display. \"\"\" form_fields = form.Fields(I%sPortlet) """%(portletname, portletname, portletname, portletname, portletname, portletname, '/'.join(pasta_portlets.split('/')[2:]), portletname, portletname, portletname, portletname, portletname, portletname) texto = texto_header + texto_main skin.cria_arquivo('portlets.py', pasta_browser, texto)