Skip to content
Permalink
Browse files

Allow optional limit on recurrence expansion size.

  • Loading branch information...
cyrusdaboo committed Jul 27, 2015
1 parent 74f0d43 commit 23fdbc6b67953735688952caa55c486669fb4b21
@@ -0,0 +1,20 @@
##
# Copyright (c) 2015 Cyrus Daboo. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##

from pycalendar.exceptions import ErrorBase

class TooManyInstancesError(ErrorBase):
pass
@@ -17,6 +17,7 @@
from pycalendar import xmlutils
from pycalendar.datetime import DateTime
from pycalendar.icalendar import definitions, xmldefinitions
from pycalendar.icalendar.exceptions import TooManyInstancesError
from pycalendar.period import Period
from pycalendar.valueutils import ValueMixin
import cStringIO as StringIO
@@ -880,7 +881,7 @@ def getUIDescription(self):
return result


def expand(self, start, range, items, float_offset=0):
def expand(self, start, range, items, float_offset=0, maxInstances=None):

# Have to normalize this to be very sure we are starting with a valid date, as otherwise
# we could end up looping forever when doing recurrence.
@@ -906,9 +907,9 @@ def expand(self, start, range, items, float_offset=0):

# Simple expansion is one where there is no BYXXX rule part
if not self.hasBy():
self.mFullyCached = self.simpleExpand(start, range, self.mRecurrences, float_offset)
self.mFullyCached = self.simpleExpand(start, range, self.mRecurrences, float_offset, maxInstances=maxInstances)
else:
self.mFullyCached = self.complexExpand(start, range, self.mRecurrences, float_offset)
self.mFullyCached = self.complexExpand(start, range, self.mRecurrences, float_offset, maxInstances=maxInstances)

# Set cache values
self.mCached = True
@@ -925,7 +926,7 @@ def expand(self, start, range, items, float_offset=0):
return limited


def simpleExpand(self, start, range, items, float_offset):
def simpleExpand(self, start, range, items, float_offset, maxInstances=None):
start_iter = start.duplicate()
ctr = 0

@@ -942,6 +943,8 @@ def simpleExpand(self, start, range, items, float_offset):

# Add current one to list
items.append(start_iter.duplicate())
if maxInstances and len(items) > maxInstances:
raise TooManyInstancesError("Too many instances")

# Get next item
start_iter.recur(self.mFreq, self.mInterval, allow_invalid=True)
@@ -961,7 +964,7 @@ def simpleExpand(self, start, range, items, float_offset):
return True


def complexExpand(self, start, range, items, float_offset):
def complexExpand(self, start, range, items, float_offset, maxInstances=None):
start_iter = start.duplicate()
ctr = 0

@@ -1039,6 +1042,8 @@ def complexExpand(self, start, range, items, float_offset):

# Add current one to list
items.append(iter)
if maxInstances and len(items) > maxInstances:
raise TooManyInstancesError("Too many instances")

# Check limits
if self.mUseCount:
@@ -14,6 +14,7 @@
# limitations under the License.
##

from pycalendar.icalendar.exceptions import TooManyInstancesError
from pycalendar.utils import set_difference

class RecurrenceSet(object):
@@ -182,7 +183,7 @@ def getExperiods(self):
return self.mExperiods


def expand(self, start, range, items, float_offset=0):
def expand(self, start, range, items, float_offset=0, maxInstances=None):
# Need to return whether the limit was applied or not
limited = False

@@ -197,18 +198,22 @@ def expand(self, start, range, items, float_offset=0):

# RRULES
for iter in self.mRrules:
if iter.expand(start, range, include, float_offset=float_offset):
if iter.expand(start, range, include, float_offset=float_offset, maxInstances=maxInstances):
limited = True

# RDATES
for iter in self.mRdates:
if range.isDateWithinPeriod(iter):
include.append(iter)
if maxInstances and len(include) > maxInstances:
raise TooManyInstancesError("Too many instances")
else:
limited = True
for iter in self.mRperiods:
if range.isPeriodOverlap(iter):
include.append(iter.getStart())
if maxInstances and len(include) > maxInstances:
raise TooManyInstancesError("Too many instances")
else:
limited = True

0 comments on commit 23fdbc6

Please sign in to comment.
You can’t perform that action at this time.