Revision 4651c69f

b/src/Ganeti/BasicTypes.hs
41 41
  , goodMatchPriority
42 42
  , prefixMatch
43 43
  , compareNameComponent
44
  , ListSet(..)
45
  , emptyListSet
44 46
  ) where
45 47

  
46 48
import Control.Applicative
......
48 50
import Control.Monad.Trans
49 51
import Data.Function
50 52
import Data.List
53
import Data.Set (Set)
54
import qualified Data.Set as Set (empty)
55
import Text.JSON (JSON)
56
import qualified Text.JSON as JSON (readJSON, showJSON)
51 57

  
52 58
-- | Generic monad for our error handling mechanisms.
53 59
data GenericResult a b
......
224 230
           -> LookupResult  -- ^ Result of the lookup
225 231
lookupName l s = foldr (chooseLookupResult s)
226 232
                       (LookupResult FailMatch s) l
233

  
234
-- | Wrapper for a Haskell 'Set'
235
--
236
-- This type wraps a 'Set' and it is used in the Haskell to Python
237
-- opcode generation to transform a Haskell 'Set' into a Python 'list'
238
-- without duplicate elements.
239
newtype ListSet a = ListSet { unListSet :: Set a }
240
  deriving (Eq, Show)
241

  
242
instance (Ord a, JSON a) => JSON (ListSet a) where
243
  showJSON = JSON.showJSON . unListSet
244
  readJSON = liftM ListSet . JSON.readJSON
245

  
246
emptyListSet :: ListSet a
247
emptyListSet = ListSet Set.empty
b/src/Ganeti/OpParams.hs
252 252
  ) where
253 253

  
254 254
import Control.Monad (liftM)
255
import Data.Set (Set)
256
import qualified Data.Set as Set
257 255
import Text.JSON (JSON, JSValue(..), JSObject (..), readJSON, showJSON,
258 256
                  fromJSString, toJSObject)
259 257
import qualified Text.JSON
......
266 264
import Ganeti.Types
267 265
import qualified Ganeti.Query.Language as Qlang
268 266

  
269

  
270 267
-- * Helper functions and types
271 268

  
272 269
-- | Build a boolean field.
......
448 445
  showJSON (ExportTargetRemote l) = showJSON l
449 446
  readJSON = readExportTarget
450 447

  
451

  
452 448
-- * Common opcode parameters
453 449

  
454 450
pDryRun :: Field
......
483 479
  withDoc "Reason trail field" $
484 480
  simpleField C.opcodeReason [t| ReasonTrail |]
485 481

  
486

  
487 482
-- * Parameters
488 483

  
489 484
pDebugSimulateErrors :: Field
......
499 494
pSkipChecks :: Field
500 495
pSkipChecks = 
501 496
  withDoc "Which checks to skip" .
502
  defaultField [| Set.empty |] $
503
  simpleField "skip_checks" [t| Set VerifyOptionalChecks |]
497
  defaultField [| emptyListSet |] $
498
  simpleField "skip_checks" [t| ListSet VerifyOptionalChecks |]
504 499

  
505 500
pIgnoreErrors :: Field
506 501
pIgnoreErrors =
507 502
  withDoc "List of error codes that should be treated as warnings" .
508
  defaultField [| Set.empty |] $
509
  simpleField "ignore_errors" [t| Set CVErrorCode |]
503
  defaultField [| emptyListSet |] $
504
  simpleField "ignore_errors" [t| ListSet CVErrorCode |]
510 505

  
511 506
pVerbose :: Field
512 507
pVerbose =
b/src/Ganeti/PyValueInstances.hs
35 35
import Data.List (intercalate)
36 36
import Data.Map (Map)
37 37
import qualified Data.Map as Map
38
import Data.Set (Set)
39
import qualified Data.Set as Set
38
import qualified Data.Set as Set (toList)
40 39

  
40
import Ganeti.BasicTypes
41 41
import Ganeti.THH
42 42

  
43 43
instance PyValue Bool
......
59 59
    "{" ++ intercalate ", " (map showPair (Map.assocs mp)) ++ "}"
60 60
    where showPair (k, x) = show k ++ ":" ++ show x
61 61

  
62
instance PyValue a => PyValue (Set a) where
63
  showValue s = showValue (Set.toList s)
62
instance PyValue a => PyValue (ListSet a) where
63
  showValue = showValue . Set.toList . unListSet
b/src/Ganeti/THH.hs
578 578
                "()" -> "None"
579 579
                "Map" -> "DictOf"
580 580
                "Set" -> "SetOf"
581
                "ListSet" -> "SetOf"
581 582
                "Either" -> "Or"
582 583
                "GenericContainer" -> "DictOf"
583 584
                "JSValue" -> "Any"
b/test/hs/Test/Ganeti/OpCodes.hs
149 149
      "OP_CLUSTER_QUERY" -> pure OpCodes.OpClusterQuery
150 150
      "OP_CLUSTER_VERIFY" ->
151 151
        OpCodes.OpClusterVerify <$> arbitrary <*> arbitrary <*>
152
          genSet Nothing <*> genSet Nothing <*> arbitrary <*>
152
          genListSet Nothing <*> genListSet Nothing <*> arbitrary <*>
153 153
          genMaybe genNameNE
154 154
      "OP_CLUSTER_VERIFY_CONFIG" ->
155 155
        OpCodes.OpClusterVerifyConfig <$> arbitrary <*> arbitrary <*>
156
          genSet Nothing <*> arbitrary
156
          genListSet Nothing <*> arbitrary
157 157
      "OP_CLUSTER_VERIFY_GROUP" ->
158 158
        OpCodes.OpClusterVerifyGroup <$> genNameNE <*> arbitrary <*>
159
          arbitrary <*> genSet Nothing <*> genSet Nothing <*> arbitrary
159
          arbitrary <*> genListSet Nothing <*> genListSet Nothing <*> arbitrary
160 160
      "OP_CLUSTER_VERIFY_DISKS" -> pure OpCodes.OpClusterVerifyDisks
161 161
      "OP_GROUP_VERIFY_DISKS" ->
162 162
        OpCodes.OpGroupVerifyDisks <$> genNameNE
b/test/hs/Test/Ganeti/TestCommon.hs
50 50
  , SmallRatio(..)
51 51
  , genSetHelper
52 52
  , genSet
53
  , genListSet
53 54
  , genIPv4Address
54 55
  , genIPv4Network
55 56
  , genIp6Addr
......
279 280
           newelem <- elements candidates `suchThat` (`Set.notMember` set)
280 281
           return (Set.insert newelem set)) Set.empty [1..size']
281 282

  
282
-- | Generates a set of arbitrary elements.
283
-- | Generates a 'Set' of arbitrary elements.
283 284
genSet :: (Ord a, Bounded a, Enum a) => Maybe Int -> Gen (Set.Set a)
284 285
genSet = genSetHelper [minBound..maxBound]
285 286

  
287
-- | Generates a 'Set' of arbitrary elements wrapped in a 'ListSet'
288
genListSet :: (Ord a, Bounded a, Enum a) => Maybe Int
289
              -> Gen (BasicTypes.ListSet a)
290
genListSet is = BasicTypes.ListSet <$> genSet is
291

  
286 292
-- | Generate an arbitrary IPv4 address in textual form.
287 293
genIPv4 :: Gen String
288 294
genIPv4 = do

Also available in: Unified diff