forked from system7ltd/TickingMachine
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 9a5dc53
Showing
14 changed files
with
881 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,312 @@ | ||
# -*- coding: utf-8 -*- | ||
# | ||
# File: Install.py | ||
# | ||
# Copyright (c) 2007 by Tomasz J. Kotarba | ||
# Generator: ArchGenXML Version 1.5.2 | ||
# http://plone.org/products/archgenxml | ||
# | ||
# 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. | ||
# | ||
|
||
__author__ = """Tomasz J. Kotarba <tomasz@kotarba.net>""" | ||
__docformat__ = 'plaintext' | ||
|
||
|
||
import os.path | ||
import sys | ||
from StringIO import StringIO | ||
from sets import Set | ||
from App.Common import package_home | ||
from Products.CMFCore.utils import getToolByName | ||
from Products.CMFCore.utils import manage_addTool | ||
from Products.ExternalMethod.ExternalMethod import ExternalMethod | ||
from zExceptions import NotFound, BadRequest | ||
|
||
from Products.Archetypes.Extensions.utils import installTypes | ||
from Products.Archetypes.Extensions.utils import install_subskin | ||
from Products.Archetypes.config import TOOL_NAME as ARCHETYPETOOLNAME | ||
from Products.Archetypes.atapi import listTypes | ||
from Products.TickingMachine.config import PROJECTNAME | ||
from Products.TickingMachine.config import product_globals as GLOBALS | ||
|
||
def install(self, reinstall=False): | ||
""" External Method to install TickingMachine """ | ||
out = StringIO() | ||
print >> out, "Installation log of %s:" % PROJECTNAME | ||
|
||
# If the config contains a list of dependencies, try to install | ||
# them. Add a list called DEPENDENCIES to your custom | ||
# AppConfig.py (imported by config.py) to use it. | ||
try: | ||
from Products.TickingMachine.config import DEPENDENCIES | ||
except: | ||
DEPENDENCIES = [] | ||
portal = getToolByName(self,'portal_url').getPortalObject() | ||
quickinstaller = portal.portal_quickinstaller | ||
for dependency in DEPENDENCIES: | ||
print >> out, "Installing dependency %s:" % dependency | ||
quickinstaller.installProduct(dependency) | ||
get_transaction().commit(1) | ||
|
||
classes = listTypes(PROJECTNAME) | ||
installTypes(self, out, | ||
classes, | ||
PROJECTNAME) | ||
install_subskin(self, out, GLOBALS) | ||
|
||
# autoinstall tools | ||
portal = getToolByName(self,'portal_url').getPortalObject() | ||
for t in ['TickingMachine']: | ||
try: | ||
portal.manage_addProduct[PROJECTNAME].manage_addTool(t) | ||
except BadRequest: | ||
# if an instance with the same name already exists this error will | ||
# be swallowed. Zope raises in an unelegant manner a 'Bad Request' error | ||
pass | ||
except: | ||
e = sys.exc_info() | ||
if e[0] != 'Bad Request': | ||
raise | ||
|
||
# hide tools in the search form | ||
portalProperties = getToolByName(self, 'portal_properties', None) | ||
if portalProperties is not None: | ||
siteProperties = getattr(portalProperties, 'site_properties', None) | ||
if siteProperties is not None and siteProperties.hasProperty('types_not_searched'): | ||
for tool in ['TickingMachine']: | ||
current = list(siteProperties.getProperty('types_not_searched')) | ||
if tool not in current: | ||
current.append(tool) | ||
siteProperties.manage_changeProperties(**{'types_not_searched' : current}) | ||
|
||
# remove workflow for tools | ||
portal_workflow = getToolByName(self, 'portal_workflow') | ||
for tool in ['TickingMachine']: | ||
portal_workflow.setChainForPortalTypes([tool], '') | ||
|
||
# uncatalog tools | ||
for toolname in ['portal_tickingmachine']: | ||
try: | ||
portal[toolname].unindexObject() | ||
except: | ||
pass | ||
|
||
# hide tools in the navigation | ||
portalProperties = getToolByName(self, 'portal_properties', None) | ||
if portalProperties is not None: | ||
navtreeProperties = getattr(portalProperties, 'navtree_properties', None) | ||
if navtreeProperties is not None and navtreeProperties.hasProperty('idsNotToList'): | ||
for toolname in ['portal_tickingmachine']: | ||
current = list(navtreeProperties.getProperty('idsNotToList')) | ||
if toolname not in current: | ||
current.append(toolname) | ||
navtreeProperties.manage_changeProperties(**{'idsNotToList' : current}) | ||
|
||
|
||
# try to call a workflow install method | ||
# in 'InstallWorkflows.py' method 'installWorkflows' | ||
try: | ||
installWorkflows = ExternalMethod('temp', 'temp', | ||
PROJECTNAME+'.InstallWorkflows', | ||
'installWorkflows').__of__(self) | ||
except NotFound: | ||
installWorkflows = None | ||
|
||
if installWorkflows: | ||
print >>out,'Workflow Install:' | ||
res = installWorkflows(self,out) | ||
print >>out,res or 'no output' | ||
else: | ||
print >>out,'no workflow install' | ||
|
||
|
||
|
||
# enable portal_factory for given types | ||
factory_tool = getToolByName(self,'portal_factory') | ||
factory_types=[ | ||
"TickEvent", | ||
"TickingMachine", | ||
] + factory_tool.getFactoryTypes().keys() | ||
factory_tool.manage_setPortalFactoryTypes(listOfTypeIds=factory_types) | ||
|
||
from Products.TickingMachine.config import STYLESHEETS | ||
try: | ||
portal_css = getToolByName(portal, 'portal_css') | ||
for stylesheet in STYLESHEETS: | ||
try: | ||
portal_css.unregisterResource(stylesheet['id']) | ||
except: | ||
pass | ||
defaults = {'id': '', | ||
'media': 'all', | ||
'enabled': True} | ||
defaults.update(stylesheet) | ||
portal_css.registerStylesheet(**defaults) | ||
except: | ||
# No portal_css registry | ||
pass | ||
from Products.TickingMachine.config import JAVASCRIPTS | ||
try: | ||
portal_javascripts = getToolByName(portal, 'portal_javascripts') | ||
for javascript in JAVASCRIPTS: | ||
try: | ||
portal_javascripts.unregisterResource(javascript['id']) | ||
except: | ||
pass | ||
defaults = {'id': ''} | ||
defaults.update(javascript) | ||
portal_javascripts.registerScript(**defaults) | ||
except: | ||
# No portal_javascripts registry | ||
pass | ||
|
||
# try to call a custom install method | ||
# in 'AppInstall.py' method 'install' | ||
try: | ||
install = ExternalMethod('temp', 'temp', | ||
PROJECTNAME+'.AppInstall', 'install') | ||
except NotFound: | ||
install = None | ||
|
||
if install: | ||
print >>out,'Custom Install:' | ||
try: | ||
res = install(self, reinstall) | ||
except TypeError: | ||
res = install(self) | ||
if res: | ||
print >>out,res | ||
else: | ||
print >>out,'no output' | ||
else: | ||
print >>out,'no custom install' | ||
return out.getvalue() | ||
|
||
def uninstall(self, reinstall=False): | ||
out = StringIO() | ||
|
||
|
||
# unhide tools in the search form | ||
portalProperties = getToolByName(self, 'portal_properties', None) | ||
if portalProperties is not None: | ||
siteProperties = getattr(portalProperties, 'site_properties', None) | ||
if siteProperties is not None and siteProperties.hasProperty('types_not_searched'): | ||
for tool in ['TickingMachine']: | ||
current = list(siteProperties.getProperty('types_not_searched')) | ||
if tool in current: | ||
current.remove(tool) | ||
siteProperties.manage_changeProperties(**{'types_not_searched' : current}) | ||
|
||
|
||
# unhide tools | ||
portalProperties = getToolByName(self, 'portal_properties', None) | ||
if portalProperties is not None: | ||
navtreeProperties = getattr(portalProperties, 'navtree_properties', None) | ||
if navtreeProperties is not None and navtreeProperties.hasProperty('idsNotToList'): | ||
for toolname in ['portal_tickingmachine']: | ||
current = list(navtreeProperties.getProperty('idsNotToList')) | ||
if toolname in current: | ||
current.remove(toolname) | ||
navtreeProperties.manage_changeProperties(**{'idsNotToList' : current}) | ||
|
||
# try to call a workflow uninstall method | ||
# in 'InstallWorkflows.py' method 'uninstallWorkflows' | ||
try: | ||
uninstallWorkflows = ExternalMethod('temp', 'temp', | ||
PROJECTNAME+'.InstallWorkflows', | ||
'uninstallWorkflows').__of__(self) | ||
except NotFound: | ||
uninstallWorkflows = None | ||
|
||
if uninstallWorkflows: | ||
print >>out, 'Workflow Uninstall:' | ||
res = uninstallWorkflows(self, out) | ||
print >>out, res or 'no output' | ||
else: | ||
print >>out,'no workflow uninstall' | ||
|
||
# try to call a custom uninstall method | ||
# in 'AppInstall.py' method 'uninstall' | ||
try: | ||
uninstall = ExternalMethod('temp', 'temp', | ||
PROJECTNAME+'.AppInstall', 'uninstall') | ||
except: | ||
uninstall = None | ||
|
||
if uninstall: | ||
print >>out,'Custom Uninstall:' | ||
try: | ||
res = uninstall(self, reinstall) | ||
except TypeError: | ||
res = uninstall(self) | ||
if res: | ||
print >>out,res | ||
else: | ||
print >>out,'no output' | ||
else: | ||
print >>out,'no custom uninstall' | ||
|
||
return out.getvalue() | ||
|
||
def beforeUninstall(self, reinstall, product, cascade): | ||
""" try to call a custom beforeUninstall method in 'AppInstall.py' | ||
method 'beforeUninstall' | ||
""" | ||
out = StringIO() | ||
try: | ||
beforeuninstall = ExternalMethod('temp', 'temp', | ||
PROJECTNAME+'.AppInstall', 'beforeUninstall') | ||
except: | ||
beforeuninstall = [] | ||
|
||
if beforeuninstall: | ||
print >>out, 'Custom beforeUninstall:' | ||
res = beforeuninstall(self, reinstall=reinstall | ||
, product=product | ||
, cascade=cascade) | ||
if res: | ||
print >>out, res | ||
else: | ||
print >>out, 'no output' | ||
else: | ||
print >>out, 'no custom beforeUninstall' | ||
return (out,cascade) | ||
|
||
def afterInstall(self, reinstall, product): | ||
""" try to call a custom afterInstall method in 'AppInstall.py' method | ||
'afterInstall' | ||
""" | ||
out = StringIO() | ||
try: | ||
afterinstall = ExternalMethod('temp', 'temp', | ||
PROJECTNAME+'.AppInstall', 'afterInstall') | ||
except: | ||
afterinstall = None | ||
|
||
if afterinstall: | ||
print >>out, 'Custom afterInstall:' | ||
res = afterinstall(self, product=None | ||
, reinstall=None) | ||
if res: | ||
print >>out, res | ||
else: | ||
print >>out, 'no output' | ||
else: | ||
print >>out, 'no custom afterInstall' | ||
return out |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# make me a python module |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# -*- coding: utf-8 -*- | ||
# | ||
# File: ITickEvent.py | ||
# | ||
# Copyright (c) 2007 by Tomasz J. Kotarba | ||
# Generator: ArchGenXML Version 1.5.2 | ||
# http://plone.org/products/archgenxml | ||
# | ||
# 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. | ||
# | ||
|
||
__author__ = """Tomasz J. Kotarba <tomasz@kotarba.net>""" | ||
__docformat__ = 'plaintext' | ||
|
||
|
||
##code-section module-header #fill in your manual code here | ||
##/code-section module-header | ||
|
||
|
||
|
||
|
||
from zope.interface import Interface, Attribute | ||
|
||
class ITickEvent(Interface): | ||
'''An event signaling a tick (vide the TickingMachine class). | ||
''' | ||
|
||
##code-section class-header_ITickEvent #fill in your manual code here | ||
date_time = Attribute("Time of the last tick") | ||
next_tick = Attribute("Estimated time of the next tick") | ||
##/code-section class-header_ITickEvent | ||
|
||
|
||
|
||
|
||
##code-section module-footer #fill in your manual code here | ||
##/code-section module-footer | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
=============== | ||
Ticking Machine | ||
=============== | ||
|
||
A Plone product used to create applications which can react to time events | ||
|
||
TickingMachine is a Plone product built using Archetypes and Zope3 framework. It adds the notion of a 'server tick' which is, basically, a simple time event triggered at specified intervals (set with a custom portal tool - portal_tickingmachine). This subsystem uses the observer pattern and zope3 events, which means that other subsystems can subscribe to it and get notified each time a tick takes place (thus being able to perceive the time flow and react to it by performing some actions). | ||
|
||
The TickingMachine needs an external clock source. You can use the cron daemon, Zope ClockServer or whatever you wish as long as it can invoke the tick() method of the TickingMachine portal tool (e.g. by accessing it via HTTP(s) with its URL). | ||
|
||
Tested with Plone 3.0, the product has proven to be production-ready while in use in one of the FTSE100 corporations. | ||
|
||
|
||
Please note, I created this project for the now ancient version of Plone and stopped maintaining it in 2008 so it is probably of little use. I am putting it here for archiving purposes (too many of my projects were either lost or never open sourced). After I had stopped maintaining it, this product served as base for the then new collective.timedevents product (see: `here <https://github.com/system7-open-source/collective.timedevents>`_). |
Oops, something went wrong.