Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
system7ltd committed Oct 19, 2017
0 parents commit 9a5dc53
Show file tree
Hide file tree
Showing 14 changed files with 881 additions and 0 deletions.
312 changes: 312 additions & 0 deletions Extensions/Install.py
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
1 change: 1 addition & 0 deletions Extensions/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# make me a python module
55 changes: 55 additions & 0 deletions ITickEvent.py
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



14 changes: 14 additions & 0 deletions README.rst
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>`_).
Loading

0 comments on commit 9a5dc53

Please sign in to comment.