Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
kmaehashi committed Jun 19, 2021
1 parent bc52a9f commit 54111de
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 35 deletions.
30 changes: 30 additions & 0 deletions example/example_builder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from ast import Param
from pypict.builder import Model, Parameter, IF, AND, OR, NOT


type = Parameter('Type', ['Single', 'Span', 'Stripe', 'Mirror', 'RAID-5'])
size = Parameter('Size', [10, 100, 500, 1000, 5000, 10000, 40000])
method = Parameter('Format method', ['Quick', 'Slow'])
filesys = Parameter('File System', ['FAT', 'FAT32', 'NTFS'])
cluster = Parameter('Cluster size', [512, 1024, 2048, 4096, 8192, 16384, 32768, 65536])
compression = Parameter('Compression', ['On', 'Off'])

model = Model().parameters(
type, size, method, filesys, cluster, compression
).constraints(
IF(filesys == 'FAT').THEN(size <= 4096),
IF(filesys == 'FAT32').THEN(size <= 32000),
size < 10000,
compression == 'OFF',
filesys.like('FAT*'),
IF(cluster.in_(512, 1024, 2048)).THEN(compression == 'off'),
IF(filesys.in_('FAT', 'FAT32')).THEN(compression == 'off'),

IF(
OR(
filesys != 'NTFS',
AND(filesys == 'NTFS', cluster > 4096),
)
).THEN(compression == 'Off')
)
print(model.to_string())
57 changes: 41 additions & 16 deletions pypict/builder/_constraint.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@

from pypict.builder._export import _literal
import pypict.builder


class _Constraint:
def to_string(self):
def to_string(self) -> str:
raise NotImplemented

def __str__(self):
def __str__(self) -> str:
return self.to_string()

def __repr__(self):
def __repr__(self) -> str:
return f'<PICT Constraint ("{str(self)}")>'


Expand All @@ -19,17 +19,20 @@ def __init__(self, param, op, value_or_param):
self._op = op
self._value_or_param = value_or_param

def to_string(self):
def to_string(self) -> str:
return f'{_literal(self._param)} {self._op} {_literal(self._value_or_param)}'


class _LogicalOp(_Constraint):
_op = None
_op: str = None # to be overridden

def __init__(self, consts):
def __init__(self, *consts: _Constraint):
for const in consts:
if not isinstance(const, _Constraint):
raise ValueError
self._consts = consts

def to_string(self):
def to_string(self) -> str:
return '(' + f' {self._op} '.join([str(x) for x in self._consts]) + ')'


Expand All @@ -42,38 +45,60 @@ class OR(_LogicalOp):


class NOT(_Constraint):
def __init__(self, const):
def __init__(self, const: _Constraint):
if not isinstance(const, _Constraint):
raise ValueError
self._const = const

def to_string(self):
def to_string(self) -> str:
return f'NOT {self._const}'


class IF(_Constraint):
def __init__(self, const):
def __init__(self, const: _Constraint):
if not isinstance(const, _Constraint):
raise ValueError
self._const = const
self._then = None
self._else = None

def THEN(self, const):
def THEN(self, const: _Constraint) -> 'IF':
if self._then is not None:
raise ValueError
self._then = const
return self

def ELSE(self, const):
def ELSE(self, const: _Constraint) -> 'IF':
if self._then is None:
raise ValueError
if self._else is None:
raise ValueError
self._else = const

def to_string(self):
def to_string(self) -> str:
if self._then is None:
raise ValueError
return (
f'IF {self._const}' +
f'\nTHEN {self._then}' +
(f'\nELSE {self._else}' if self._else else '') +
';'
(f'\nELSE {self._else}' if self._else else '')
)


class _ValueSet:
def __init__(self, values):
self._values = values

def to_string(self) -> str:
return '{ ' + ', '.join([_literal(x) for x in self._values]) + ' }'


def _literal(v):
if isinstance(v, pypict.builder.Parameter):
return f'[{v._name}]'
elif isinstance(v, _ValueSet):
return v.to_string()
elif isinstance(v, str):
return f'"{v}"' # TODO check?
else:
return str(v)
14 changes: 0 additions & 14 deletions pypict/builder/_export.py
Original file line number Diff line number Diff line change
@@ -1,14 +0,0 @@
from pypict import builder


def _literal(v):
if isinstance(v, builder.Parameter):
return f'[{v._name}]'
elif isinstance(v, str):
return f'"{v}"' # TODO check?
else:
return str(v)


def _ValueSet(values):
return '{ ' + ','.join([_literal(x) for x in values]) + ' }'
2 changes: 1 addition & 1 deletion pypict/builder/_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def to_string(self):
# Constraint definitions
if len(self._constraints) != 0:
for c in self._constraints:
lines.append(c.to_string())
lines.append(c.to_string() + ';')

return '\n'.join(lines)

Expand Down
11 changes: 7 additions & 4 deletions pypict/builder/_parameter.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import numbers
from typing import Iterable, Iterator, List, Optional, Tuple, Type, Union

from pypict.builder._constraint import _Relation
from pypict.builder._export import _literal, _ValueSet
from pypict.builder._constraint import _Relation, _ValueSet


NumericType = numbers.Real
Expand Down Expand Up @@ -104,10 +103,14 @@ def __le__(self, other: Union[DataTypes, 'Parameter']):
self._check_operand(other)
return _Relation(self, '<=', other)

def __in__(self, values: Iterable[DataTypes]):
def in_(self, *values: DataTypes):
for x in values:
self._check_operand(x, allow_string=True)
return _Relation(self, 'IN', _ValueSet(values))

def like(self, value):
if self._dtype != str:
if self._numeric:
raise ValueError
if not isinstance(value, StringType):
raise ValueError
return _Relation(self, 'LIKE', value)

0 comments on commit 54111de

Please sign in to comment.