Skip to content

Commit bd9942d

Browse files
committed
* Made ARRAY implementation strictly comply with ISO 10303-11:1994
* Updated SCL unittest.
1 parent 10999e7 commit bd9942d

File tree

2 files changed

+119
-14
lines changed

2 files changed

+119
-14
lines changed

src/fedex_python/python/SCL/AggregationDataType.py

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,20 @@
3030
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3131

3232
from SimpleDataTypes import *
33+
from TypeChecker import *
3334

3435
class BaseAggregate(object):
3536
""" A class that define common properties to ARRAY, LIST, SET and BAG.
3637
"""
3738
def __init__( self , bound1 , bound2 , base_type ):
38-
# init base list with an empty list
39-
list.__init__(self,[])
4039
# check that bound1<bound2
4140
if (bound1!=None and bound2!=None):
4241
if bound1>bound2:
4342
raise AssertionError("bound1 shall be less than or equal to bound2")
4443
self._bound1 = bound1
4544
self._bound2 = bound2
4645
self._base_type = base_type
47-
print base_type
48-
46+
4947
def __getitem__(self, index):
5048
if index<self._bound1:
5149
raise IndexError("ARRAY index out of bound (lower bound is %i, passed %i)"%(self._bound1,index))
@@ -63,21 +61,65 @@ def __setitem__(self,index,value):
6361
raise TypeError("%s type expected, passed %s."%(self._base_type, type(value)))
6462
else:
6563
# first find the length of the list, and extend it if ever
66-
# the index is
64+
# the index is
6765
list.__setitem__(self,index,value)
6866

69-
class ARRAY(list, BaseAggregate):
67+
class ARRAY(object):
7068
"""An array data type has as its domain indexed, fixed-size collections of like elements. The lower
7169
and upper bounds, which are integer-valued expressions, define the range of index values, and
7270
thus the size of each array collection.
7371
An array data type definition may optionally specify
7472
that an array value cannot contain duplicate elements.
7573
It may also specify that an array value
7674
need not contain an element at every index position.
75+
76+
Given that m is the lower bound and n is the upper bound, there are exactly n-m+1 elements
77+
in the array. These elements are indexed by subscripts from m to n, inclusive (see 12.6.1).
78+
NOTE 1 { The bounds may be positive, negative or zero, but may not be indeterminate (?) (see
79+
14.2).
7780
"""
78-
def __init__( self , bound1 , bound2 , base_type ):
79-
BaseAggregate.__init__( self , bound1 , bound2 , base_type )
81+
def __init__( self , bound_1 , bound_2 , base_type , UNIQUE = False, OPTIONAL=False):
82+
if not type(bound_1)==int:
83+
raise TypeError("ARRAY lower bound must be an integer")
84+
if not type(bound_2)==int:
85+
raise TypeError("ARRAY upper bound must be an integer")
86+
if not (bound_1 <= bound_2):
87+
raise AssertionError("ARRAY lower bound must be less than or equal to upper bound")
88+
# set up class attributes
89+
self._bound_1 = bound_1
90+
self._bound_2 = bound_2
91+
self._base_type = base_type
92+
self._unique = UNIQUE
93+
self._optional = OPTIONAL
94+
# preallocate list elements
95+
list_size = bound_2 - bound_1 + 1
96+
self._container = list_size*[None]
97+
98+
def __getitem__(self, index):
99+
if index<self._bound_1:
100+
raise IndexError("ARRAY index out of bound (lower bound is %i, passed %i)"%(self._bound_1,index))
101+
elif(index>self._bound_2):
102+
raise IndexError("ARRAY index out of bound (upper bound is %i, passed %i)"%(self._bound_2,index))
103+
else:
104+
value = self._container[index-self._bound_1]
105+
if not self._optional and value==None:
106+
raise AssertionError("Not OPTIONAL prevent the value with index %i from being None (default). Please set the value first."%index)
107+
return value
80108

109+
def __setitem__(self, index, value):
110+
if index<self._bound_1:
111+
raise IndexError("ARRAY index out of bound (lower bound is %i, passed %i)"%(self._bound_1,index))
112+
elif(index>self._bound_2):
113+
raise IndexError("ARRAY index out of bound (upper bound is %i, passed %i)"%(self._bound_2,index))
114+
else:
115+
# first check the type of the value
116+
check_type(value,self._base_type)
117+
# then check if the value is already in the array
118+
if self._unique:
119+
if value in self._container:
120+
raise AssertionError("UNIQUE keyword prevent inserting this instance.")
121+
self._container[index-self._bound_1] = value
122+
81123
class LIST(list, BaseAggregate):
82124
"""A list data type has as its domain sequences of like elements. The optional lower and upper
83125
bounds, which are integer-valued expressions, dfine the minimum and maximum number of

src/fedex_python/python/SCL_unittest.py

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,12 @@
2929
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3030
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3131

32+
import unittest
33+
3234
from SCL.SimpleDataTypes import *
3335
from SCL.TypeChecker import *
3436
from SCL.ConstructedDataTypes import *
35-
36-
import unittest
37+
from SCL.AggregationDataType import *
3738

3839
#
3940
# Simple data types
@@ -133,7 +134,70 @@ def test_create_from_bool(self):
133134
self.assertTrue(a)
134135
b = BOOLEAN(False)
135136
self.assertFalse(b)
136-
137+
138+
#
139+
# AggregationDataTypeSimple
140+
#
141+
class TestARRAY(unittest.TestCase):
142+
'''
143+
ARRAY test
144+
'''
145+
def test_create_array(self):
146+
ARRAY(1,7,REAL)
147+
#upper and lower bounds can be negative
148+
ARRAY(-1,5,INTEGER)
149+
ARRAY(-4,-3,INTEGER)
150+
# they even can be both 0
151+
ARRAY(0,0,REAL)
152+
ARRAY(1,1,BOOLEAN)
153+
# lower bound should be less or equal than upper bound
154+
try:
155+
ARRAY(3,2,REAL)
156+
except AssertionError:
157+
pass
158+
except e:
159+
self.fail('Unexpected exception thrown:', e)
160+
else:
161+
self.fail('ExpectedException not thrown')
162+
163+
def test_array_unique(self):
164+
# if UNIQUE is not set to True (False by default),
165+
# the array may contain the same instance at different
166+
# positions
167+
a = ARRAY(1,4,REAL)
168+
a[3] = REAL(4)
169+
a[4] = REAL(4)
170+
# however, if UNIQUE, then every instances in the
171+
# array must be different
172+
a = ARRAY(1,4,REAL,UNIQUE=True)
173+
a[3] = REAL(4)
174+
try:
175+
a[3] = REAL(4)
176+
except AssertionError:
177+
pass
178+
except e:
179+
self.fail('Unexpected exception thrown:', e)
180+
else:
181+
self.fail('ExpectedException not thrown')
182+
183+
def test_array_optional(self):
184+
# if OPTIONAL is not set explicitely to True
185+
# then each value must be set
186+
a = ARRAY(1,3,REAL)
187+
try:
188+
a[1]
189+
except AssertionError:
190+
pass
191+
except e:
192+
self.fail('Unexpected exception thrown:', e)
193+
else:
194+
self.fail('ExpectedException not thrown')
195+
# if OPTIONAL is set to True, then values
196+
# can be indeterminated
197+
b = ARRAY(1,3,REAL,OPTIONAL=True)
198+
b[2] = REAL(5)
199+
b[3] = REAL(5)
200+
137201
#
138202
# TypeChecker
139203
#
@@ -153,14 +217,13 @@ class P:
153217
check_type(3,P)
154218
except TypeError:
155219
pass
156-
except a:
220+
except e:
157221
self.fail('Unexpected exception thrown:', e)
158222
else:
159223
self.fail('ExpectedException not thrown')
160224

161225
def test_check_enum_type(self):
162226
enum = ENUMERATION(["my","string"])
163-
print check_type("my",enum)
164-
227+
165228
unittest.main()
166229

0 commit comments

Comments
 (0)