Skip to content

Commit fb94472

Browse files
committed
Add numeric-constraints annotation
1 parent 814f455 commit fb94472

File tree

5 files changed

+56
-3
lines changed

5 files changed

+56
-3
lines changed

src/Nirum/Targets/Python.hs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ module Nirum.Targets.Python
2121

2222
import Control.Monad (forM)
2323
import qualified Data.List as L
24-
import Data.Maybe (catMaybes, fromMaybe)
24+
import Data.Maybe (catMaybes, fromMaybe, isJust)
2525
import GHC.Exts (IsList (toList))
2626
import Text.Printf (printf)
2727

@@ -462,13 +462,32 @@ compileTypeDeclaration src d@TypeDeclaration { typename = typename'
462462
|]
463463
compileTypeDeclaration src d@TypeDeclaration { typename = typename'
464464
, type' = UnboxedType itype
465+
, typeAnnotations = annots
465466
} = do
466467
let className = toClassName' typename'
467468
itypeExpr <- compileTypeExpression' src (Just itype)
468469
insertStandardImport "typing"
469470
insertThirdPartyImports [("nirum.deserialize", ["deserialize_meta"])]
470471
pyVer <- getPythonVersion
471-
Validator typePred valueValidators' <- compileValidator' src itype "value"
472+
Validator typePred valueValidatorsProto <-
473+
compileValidator' src itype "value"
474+
valueValidators' <- case A.lookup "numeric-constraints" annots of
475+
Just A.Annotation { A.arguments = args } -> do
476+
let constraintValidators =
477+
[ case name' of
478+
"min" -> Just $ ValueValidator
479+
[qq|value >= ($value)|]
480+
[qq|value is less than $value|]
481+
"max" -> Just $ ValueValidator
482+
[qq|value <= ($value)|]
483+
[qq|value is greater than $value|]
484+
_ -> Nothing
485+
| (name', value) <- toList args
486+
]
487+
if all isJust constraintValidators
488+
then return $ catMaybes constraintValidators
489+
else fail "Unsupported arguments on @numeric-constraints"
490+
Nothing -> return valueValidatorsProto
472491
return $ toStrict $ renderMarkup $ [compileText|
473492
class #{className}(object):
474493
#{compileDocstring " " d}

test/Nirum/Targets/PythonSpec.hs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ import System.FilePath ((</>))
77
import Test.Hspec.Meta
88
import Text.InterpolatedString.Perl6 (q)
99

10+
import qualified Nirum.Constructs.Annotation as A
1011
import Nirum.Constructs.Module (Module (Module))
1112
import Nirum.Constructs.Name (Name (Name))
13+
import Nirum.Constructs.TypeDeclaration
1214
import Nirum.Package.Metadata (Target (compilePackage))
1315
import Nirum.Targets.Python
1416
( Source (Source)
@@ -169,3 +171,16 @@ spec = do
169171
parseModulePath "foo..bar" `shouldBe` Nothing
170172
parseModulePath "foo.bar>" `shouldBe` Nothing
171173
parseModulePath "foo.bar-" `shouldBe` Nothing
174+
175+
describe "@numeric-constraints" $
176+
it "fails if unsupported arguments are present" $ do
177+
let Right annots = A.fromList
178+
[ A.Annotation "numeric-constraints"
179+
[("min", "1"), ("unsupported", "asdf")]
180+
]
181+
let unboxed = TypeDeclaration "foo" (UnboxedType "int32") annots
182+
let (Source pkg _) = makeDummySource $ Module [unboxed] Nothing
183+
let files = compilePackage pkg
184+
let result = M.lookup ("src" </> "foo" </> "__init__.py") files
185+
result `shouldBe`
186+
Just (Left "Unsupported arguments on @numeric-constraints")
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@numeric-constraints(min="1", max="12")
2+
unboxed month (int32);

test/python/constraints_test.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from pytest import raises
4+
5+
from fixture.constraints import Month
6+
7+
8+
def test_numeric_constraints():
9+
month = Month(1)
10+
assert month.value == 1
11+
12+
with raises(ValueError):
13+
Month(0)
14+
15+
with raises(ValueError):
16+
Month(13)

test/python/setup_test.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def test_setup_metadata():
2222
assert set(pkg['Provides']) == {
2323
'fixture', 'fixture.foo', 'fixture.foo.bar', 'fixture.qux',
2424
'fixture.reserved_keyword_enum', 'fixture.reserved_keyword_union',
25-
'fixture.types', 'fixture.alias',
25+
'fixture.types', 'fixture.alias', 'fixture.constraints',
2626
'renamed', 'renamed.foo', 'renamed.foo.bar',
2727
}
2828
assert ['0.3.0'] == pkg['Version']
@@ -43,6 +43,7 @@ def test_module_entry_points():
4343
'fixture.reserved-keyword-enum', 'fixture.reserved-keyword-union',
4444
'fixture.types',
4545
'fixture.alias',
46+
'fixture.constraints',
4647
'renames.test.foo', 'renames.test.foo.bar',
4748
}
4849
import fixture.foo

0 commit comments

Comments
 (0)