packages feed

xcffib 0.4.2 → 0.5.0

raw patch · 6 files changed

+326/−58 lines, 6 filesdep +eitherdep +semigroupsdep ~optparse-applicativedep ~xcb-typesPVP ok

version bump matches the API change (PVP)

Dependencies added: either, semigroups

Dependency ranges changed: optparse-applicative, xcb-types

API changes (from Hackage documentation)

Files

generator/Data/XCB/Python/Parse.hs view
@@ -28,6 +28,7 @@ import Data.Bits import qualified Data.ByteString.Char8 as BS import Data.Either+import Data.Either.Combinators import Data.List import qualified Data.Map as M import Data.Tree@@ -210,7 +211,9 @@ xExpressionToPyExpr _ (Value i) = mkInt i xExpressionToPyExpr _ (Bit i) = BinaryOp (ShiftLeft ()) (mkInt 1) (mkInt i) () xExpressionToPyExpr acc (FieldRef n) = mkName $ acc n-xExpressionToPyExpr _ (EnumRef _ n) = mkName n+xExpressionToPyExpr _ (EnumRef (UnQualType enum) n) = mkName $ enum ++ "." ++ n+-- Currently xcb only uses unqualified types, not sure how qualtype should behave+xExpressionToPyExpr _ (EnumRef (QualType _ _) _) = error "Qualified type, unknown behavior" xExpressionToPyExpr acc (PopCount e) =   mkCall "xcffib.popcount" [xExpressionToPyExpr acc e] -- http://cgit.freedesktop.org/xcb/proto/tree/doc/xml-xcb.txt#n290@@ -224,6 +227,7 @@   let o' = xUnopToPyOp o       e' = xExpressionToNestedPyExpr acc e   in Paren (UnaryOp o' e' ()) ()+xExpressionToPyExpr _ (ParamRef n) = mkName n  getConst :: XExpression -> Maybe Int getConst (Value i) = Just i@@ -282,15 +286,34 @@                      -> TypeInfoMap                      -> GenStructElem Type                      -> Either (Maybe String, String)-                               (String, Expr (), Expr (), Maybe Int)+                               (String, Either (Expr (), Expr ())+                                               ([(Expr (), [GenStructElem Type])]), Maybe Int) structElemToPyUnpack _ _ _ (Pad i) = Left (Nothing, mkPad i)  -- XXX: This is a cheap hack for noop, we should really do better. structElemToPyUnpack _ _ _ (Doc _ _ _) = Left (Nothing, "")--- XXX: What does fd/switch mean? we should implement it correctly+-- XXX: What does fd mean? we should implement it correctly structElemToPyUnpack _ _ _ (Fd _) = Left (Nothing, "")-structElemToPyUnpack _ _ _ (Switch _ _ _) = Left (Nothing, "") +-- The switch fields pick the way to expression to pack based on the expression+structElemToPyUnpack _ _ _ (Switch name expr _ bitcases) =+  let cmp = xExpressionToPyExpr ((++) "self.") expr+      switch = map (mkSwitch cmp) bitcases+  in Right (name, Right switch, Nothing)+    where+      mkSwitch :: Expr ()+               -> BitCase+               -> (Expr (), [GenStructElem Type])+      mkSwitch cmp (BitCase Nothing bcCmp _ elems) =+        let cmpVal = xExpressionToPyExpr id bcCmp+            equality = BinaryOp (P.BinaryAnd ()) cmp cmpVal ()+        in (equality, elems)++      mkSwitch cmp (BitCase (Just _) bcCmp _ elems) =+        let cmpVal = xExpressionToPyExpr id bcCmp+            equality = BinaryOp (P.Equality ()) cmp cmpVal ()+        in (equality, elems)+ -- The enum field is mostly for user information, so we ignore it. structElemToPyUnpack unpacker ext m (X.List n typ len _) =   let attr = ((++) "self.")@@ -306,7 +329,7 @@       constLen = do         l <- len         getConst l-  in Right (n, list, cons, constLen)+  in Right (n, Left (list, cons), constLen)  -- The mask and enum fields are for user information, we can ignore them here. structElemToPyUnpack unpacker ext m (SField n typ _ _) =@@ -317,7 +340,7 @@           field = mkCall c' [unpacker]       -- TODO: Ugh. Nothing here is wrong. Do we really need to carry the       -- length of these things around?-      in Right (n, field, mkName c', Nothing)+      in Right (n, Left (field, mkName c'), Nothing) structElemToPyUnpack _ _ _ (ExprField _ _ _) = error "Only valid for requests" structElemToPyUnpack _ _ _ (ValueParam _ _ _ _) = error "Only valid for requests" @@ -325,12 +348,26 @@                    -> TypeInfoMap                    -> (String -> String)                    -> GenStructElem Type-                   -> Either (Maybe String, String) [(String, Maybe (Expr ()))]+                   -> Either (Maybe String, String) [(String, Either (Maybe (Expr ()))+                                                                     [(Expr (), [GenStructElem Type])]+                                                    )] structElemToPyPack _ _ _ (Pad i) = Left (Nothing, mkPad i)--- TODO: implement doc, switch, and fd?+-- TODO: implement doc and fd? structElemToPyPack _ _ _ (Doc _ _ _) = Left (Nothing, "")-structElemToPyPack _ _ _ (Switch _ _ _) = Left (Nothing, "") structElemToPyPack _ _ _ (Fd _) = Left (Nothing, "")+structElemToPyPack _ _ accessor (Switch n expr _ bitcases) =+  let name = accessor n+      cmp = xExpressionToPyExpr id expr+      elems = map (mkSwitch cmp) bitcases+  in Right $ [(name, Right elems)]+    where+      mkSwitch :: Expr ()+               -> BitCase+               -> (Expr (), [GenStructElem Type])+      mkSwitch cmp (BitCase _ bcCmp _ elems') =+        let cmpVal = xExpressionToPyExpr id bcCmp+            equality = BinaryOp (P.BinaryAnd ()) cmp cmpVal ()+        in (equality, elems') structElemToPyPack _ m accessor (SField n typ _ _) =   let name = accessor n   in case m M.! typ of@@ -340,7 +377,9 @@              trueB = mkCall (name ++ ".pack") noArgs              synthetic = mkCall (typNam ++ ".synthetic") [mkArg ("*" ++ name)]              falseB = mkCall (mkDot synthetic "pack") noArgs-         in Right $ [(name, Just (CondExpr trueB cond falseB ()))]+         in Right $ [(name+                    , Left (Just (CondExpr trueB cond falseB ()))+                    )] -- TODO: assert values are in enum? structElemToPyPack ext m accessor (X.List n typ expr _) =   let name = accessor n@@ -348,26 +387,33 @@       -- list, or use "%s_len" % name if there is no fieldref. We need to add       -- the _len to the arguments of the function but we don't need to pack       -- anything, which we denote using Nothing-      list_len = if isNothing expr then [(name ++ "_len", Nothing)] else []+      list_len = if isNothing expr then [(name ++ "_len", Left Nothing)] else []       list = case m M.! typ of-        BaseType c -> [(name, Just (mkCall "xcffib.pack_list" [ mkName $ name-                                                        , mkStr c-                                                        ]))]+        BaseType c -> [(name+                      , Left (Just (mkCall "xcffib.pack_list" [ mkName $ name+                                                              , mkStr c+                                                              ]))+                      )]         CompositeType tExt c ->           let c' = if tExt == ext then c else (tExt ++ "." ++ c)-          in [(name, Just (mkCall "xcffib.pack_list" ([ mkName $ name-                                                , mkName c'-                                                ])))]+          in [(name+             , Left (Just (mkCall "xcffib.pack_list" ([ mkName $ name+                                                      , mkName c'+                                                      ])))+             )]   in Right $ list_len ++ list structElemToPyPack _ m accessor (ExprField name typ expr) =   let e = (xExpressionToPyExpr accessor) expr       name' = accessor name   in case m M.! typ of-       BaseType c -> Right $ [(name', Just (mkCall "struct.pack" [ mkStr ('=' : c)-                                                           , e-                                                           ]))]-       CompositeType _ _ -> Right $ [(name',-                                      Just (mkCall (mkDot e "pack") noArgs))]+       BaseType c -> Right $ [(name'+                             , Left (Just (mkCall "struct.pack" [ mkStr ('=' : c)+                                                                , e+                                                                ]))+                             )]+       CompositeType _ _ -> Right $ [(name'+                                    , Left (Just (mkCall (mkDot e "pack") noArgs))+                                    )]  -- As near as I can tell here the padding param is unused. structElemToPyPack _ m accessor (ValueParam typ mask _ list) =@@ -377,7 +423,7 @@           list' = mkCall "xcffib.pack_list" [ mkName $ accessor list                                             , mkStr "I"                                             ]-      in Right $ [(mask, Just mask'), (list, Just list')]+      in Right $ [(mask, Left (Just mask')), (list, Left (Just list'))]     CompositeType _ _ -> error (       "ValueParams other than CARD{16,32} not allowed.") @@ -394,7 +440,6 @@ mkPackStmts ext name m accessor prefix membs =   let packF = structElemToPyPack ext m accessor       (toPack, stmts) = partitionEithers $ map packF membs-      listWrites = map (flip StmtExpr () . mkCall "buf.write" . (: [])) $ catMaybes lists       (args, keys) = let (as, ks) = unzip toPack in (catMaybes as, ks)        -- In some cases (e.g. xproto.ConfigureWindow) there is padding after@@ -403,7 +448,8 @@       -- implying it implicitly. Thus, we want to make sure that if we've already       -- been told to pack something explcitly, that we don't also pack it       -- implicitly.-      (listNames, lists) = unzip $ filter (flip notElem args . fst) (concat stmts)+      (listNames, listOrSwitches) = unzip $ filter (flip notElem args . fst) (concat stmts)+      listWrites = concat $ map (uncurry mkWrites) $ zip listNames listOrSwitches       listNames' = case (ext, name) of                      -- XXX: QueryTextExtents has a field named "odd_length"                      -- which is unused, let's just drop it.@@ -417,7 +463,27 @@                                          (mkStr ('=' : packStr) : (map mkName args))]       writeStmt = if length packStr > 0 then [StmtExpr write ()] else []   in (args ++ listNames', writeStmt ++ listWrites)+    where+      mkWrites :: String+               -> Either (Maybe (Expr ()))+                         [(Expr (), [GenStructElem Type])]+               -> Suite ()+      mkWrites _ (Left Nothing) = []+      mkWrites _ (Left (Just expr)) = [mkListWrite expr]+      mkWrites valueList (Right condList) =+        let (conds, exprs) = unzip condList+            (names, stmts) = unzip $ map (mkPackStmts ext name m accessor "") exprs+        in map (\(x, y, z) -> Conditional [(x, map (mkPop valueList) y ++ z)] [] ()) $ zip3 conds names stmts +      mkListWrite :: Expr ()+                  -> Statement ()+      mkListWrite expr' = flip StmtExpr () . mkCall "buf.write" $ (: []) expr'++      mkPop :: String+            -> String+            -> Statement ()+      mkPop toPop n = mkAssign n $ mkCall (mkDot toPop "pop") [mkInt 0]+ mkPackMethod :: String              -> String              -> TypeInfoMap@@ -473,7 +539,7 @@ mkStructStyleUnpack prefix ext m membs =   let unpacked = map (structElemToPyUnpack (mkName "unpacker") ext m) membs       initial = StructUnpackState False [] prefix-      (_, unpackStmts, size) = evalState (mkUnpackStmtsR unpacked) initial+      (_, unpackStmts, size) = evalState (mkUnpackStmts unpacked) initial       base = [mkAssign "base" $ mkName "unpacker.offset"]       bufsize =         let rhs = BinaryOp (Minus ()) (mkName "unpacker.offset") (mkName "base") ()@@ -482,16 +548,16 @@   in (statements, size)      where-       -- Apparently you only type_pad before unpacking Structs or Lists, never       -- base types.-      mkUnpackStmtsR :: [Either (Maybe String, String)-                                (String, Expr (), Expr (), Maybe Int)]-                     -> State StructUnpackState ([String], Suite (), Maybe Int)+      mkUnpackStmts :: [Either (Maybe String, String)+                               (String, Either (Expr (), Expr ())+                                               ([(Expr (), [GenStructElem Type])]), Maybe Int)]+                    -> State StructUnpackState ([String], Suite (), Maybe Int) -      mkUnpackStmtsR [] = flushAcc+      mkUnpackStmts [] = flushAcc -      mkUnpackStmtsR (Left (name, pack) : xs) = do+      mkUnpackStmts (Left (name, pack) : xs) = do         st <- get         let packs = if "%c" `isInfixOf` (stPacks st)                     then addStructData (stPacks st) pack@@ -499,27 +565,48 @@         put $ st { stNames = stNames st ++ maybeToList name                  , stPacks = packs                  }-        mkUnpackStmtsR xs+        mkUnpackStmts xs -      mkUnpackStmtsR (Right (listName, list, cons, listSz) : xs) = do+      mkUnpackStmts (Right (thisName, listOrSwitch, thisSz) : xs) = do         (packNames, packStmt, packSz) <- flushAcc         st <- get         put $ st { stNeedsPad = True }-        let pad = if stNeedsPad st-                  then [typePad cons]-                  else []-        (restNames, restStmts, restSz) <- mkUnpackStmtsR xs+        let thisStmts = mkUnpackListOrSwitch thisName listOrSwitch (stNeedsPad st) st+        (restNames, restStmts, restSz) <- mkUnpackStmts xs         let totalSize = do                           before <- packSz                           rest <- restSz-                          listSz' <- listSz-                          return $ before + rest + listSz'-            listStmt = mkAssign (mkAttr listName) list-        return ( packNames ++ [listName] ++ restNames-               , packStmt ++ pad ++ listStmt : restStmts+                          thisSz' <- thisSz+                          return $ before + rest + thisSz'+        return ( packNames ++ [thisName] ++ restNames+               , packStmt ++ thisStmts ++ restStmts                , totalSize                )+          where+            mkUnpackListOrSwitch :: String+                                 -> Either (Expr (), Expr ())+                                           ([(Expr (), [GenStructElem Type])])+                                 -> Bool+                                 -> StructUnpackState+                                 -> Suite ()+            mkUnpackListOrSwitch name' (Left (list, cons)) needsPad _ =+              let pad = if needsPad+                        then [typePad cons]+                        else []+              in pad ++ [mkAssign (mkAttr name') list]+            mkUnpackListOrSwitch _ (Right switchList) _ st' =+              let (conds, elems) = unzip switchList+                  stmts = map (mkUnpackSwitchElems st') elems+              in map (\x -> Conditional [x] [] ()) $ zip conds stmts +            mkUnpackSwitchElems :: StructUnpackState+                                -> [GenStructElem Type]+                                -> Suite ()+            mkUnpackSwitchElems st' elems' =+              let unpacked' = map (structElemToPyUnpack (mkName "unpacker") ext m) elems'+                  (_, stmts', _) = evalState (mkUnpackStmts unpacked') st'+              in stmts'+       flushAcc :: State StructUnpackState ([String], Suite (), Maybe Int)       flushAcc = do         StructUnpackState needsPad args keys <- get@@ -556,7 +643,7 @@       getName (SField n _ _ _) = Just n       getName (ExprField n _ _) = Just n       getName (ValueParam _ n _ _) = Just n-      getName (Switch n _ _) = Just n+      getName (Switch n _ _ _) = Just n       getName (Doc _ _ _) = Nothing       getName (Fd n) = Just n @@ -577,7 +664,7 @@   return $ Declaration [ mkRelImport n] processXDecl _ (XEnum name membs) =   return $ Declaration [mkEnum name $ xEnumElemsToPyEnum id membs]-processXDecl ext (XStruct n membs) = do+processXDecl ext (XStruct n _ membs) = do   m <- get   let (statements, len) = mkStructStyleUnpack "" ext m membs       pack = mkPackMethod ext n m Nothing membs Nothing@@ -588,7 +675,7 @@         return $ mkAssign "fixed_size" rhs   modify $ mkModify ext n (CompositeType ext n)   return $ Declaration [mkXClass n "xcffib.Struct" statements (pack : fixedLength ++ synthetic)]-processXDecl ext (XEvent name opcode membs noSequence) = do+processXDecl ext (XEvent name opcode _ membs noSequence) = do   m <- get   let cname = name ++ "Event"       prefix = if fromMaybe False noSequence then "x" else "x%c2x"@@ -599,7 +686,7 @@   return $ Declaration [ mkXClass cname "xcffib.Event" statements (pack : synthetic)                        , eventsUpd                        ]-processXDecl ext (XError name opcode membs) = do+processXDecl ext (XError name opcode _ membs) = do   m <- get   let cname = name ++ "Error"       prefix = "xx2x"@@ -611,7 +698,7 @@                        , alias                        , errorsUpd                        ]-processXDecl ext (XRequest name opcode membs reply) = do+processXDecl ext (XRequest name opcode _ membs reply) = do   m <- get   let       -- xtest doesn't seem to use the same packing strategy as everyone else,@@ -620,7 +707,7 @@       (args, packStmts) = mkPackStmts ext name m id prefix membs       cookieName = (name ++ "Cookie")       replyDecl = concat $ maybeToList $ do-        reply' <- reply+        GenXReply _ reply' <- reply         let (replyStmts, _) = mkStructStyleUnpack "x%c2x4x" ext m reply'             replyName = name ++ "Reply"             theReply = mkXClass replyName "xcffib.Reply" replyStmts []@@ -644,12 +731,13 @@       requestBody = buf ++ packStmts ++ [ret]       request = mkMethod name allArgs requestBody   return $ Request request replyDecl-processXDecl ext (XUnion name membs) = do+processXDecl ext (XUnion name _ membs) = do   m <- get   let unpackF = structElemToPyUnpack unpackerCopy ext m       (fields, listInfo) = partitionEithers $ map unpackF membs       toUnpack = concat $ map mkUnionUnpack fields-      (names, exprs, _, _) = unzip4 listInfo+      (names, listOrSwitches, _) = unzip3 listInfo+      (exprs, _) = unzip $ map fromLeft' listOrSwitches       lists = map (uncurry mkAssign) $ zip (map mkAttr names) exprs       initMethod = lists ++ toUnpack       -- Here, we only want to pack the first member of the union, since every
generator/xcffibgen.hs view
@@ -16,6 +16,7 @@ module Main where  +import Data.Semigroup import Data.XCB.Types import Data.XCB.Python.Parse 
test/GeneratorTests.hs view
@@ -37,6 +37,7 @@           , "request_reply"           , "no_sequence"           , "type_pad"+          , "switch"           , "render_1.7"           , "xproto_1.7"           , "render"
+ test/generator/switch.py view
@@ -0,0 +1,82 @@+import xcffib+import struct+import six+_events = {}+_errors = {}+class INT64(xcffib.Struct):+    def __init__(self, unpacker):+        if isinstance(unpacker, xcffib.Protobj):+            unpacker = xcffib.MemoryUnpacker(unpacker.pack())+        xcffib.Struct.__init__(self, unpacker)+        base = unpacker.offset+        self.hi, self.lo = unpacker.unpack("iI")+        self.bufsize = unpacker.offset - base+    def pack(self):+        buf = six.BytesIO()+        buf.write(struct.pack("=iI", self.hi, self.lo))+        return buf.getvalue()+    fixed_size = 8+    @classmethod+    def synthetic(cls, hi, lo):+        self = cls.__new__(cls)+        self.hi = hi+        self.lo = lo+        return self+class GetPropertyReply(xcffib.Reply):+    def __init__(self, unpacker):+        if isinstance(unpacker, xcffib.Protobj):+            unpacker = xcffib.MemoryUnpacker(unpacker.pack())+        xcffib.Reply.__init__(self, unpacker)+        base = unpacker.offset+        self.num_items, self.format = unpacker.unpack("xx2x4xIB")+        if self.format & PropertyFormat._8Bits:+            self.data8 = xcffib.List(unpacker, "B", self.num_items)+        if self.format & PropertyFormat._16Bits:+            self.data16 = xcffib.List(unpacker, "H", self.num_items)+        if self.format & PropertyFormat._32Bits:+            self.data32 = xcffib.List(unpacker, "I", self.num_items)+        self.bufsize = unpacker.offset - base+class GetPropertyCookie(xcffib.Cookie):+    reply_type = GetPropertyReply+class GetPropertyWithPadReply(xcffib.Reply):+    def __init__(self, unpacker):+        if isinstance(unpacker, xcffib.Protobj):+            unpacker = xcffib.MemoryUnpacker(unpacker.pack())+        xcffib.Reply.__init__(self, unpacker)+        base = unpacker.offset+        self.num_items, self.format = unpacker.unpack("xx2x4xIB")+        self.names = xcffib.List(unpacker, "B", self.num_items)+        if self.format & PropertyFormat._8Bits:+            unpacker.pad("B")+            self.data8 = xcffib.List(unpacker, "B", self.num_items)+        if self.format & PropertyFormat._16Bits:+            unpacker.pad("H")+            self.data16 = xcffib.List(unpacker, "H", self.num_items)+        if self.format & PropertyFormat._32Bits:+            unpacker.pad("I")+            self.data32 = xcffib.List(unpacker, "I", self.num_items)+        self.bufsize = unpacker.offset - base+class GetPropertyWithPadCookie(xcffib.Cookie):+    reply_type = GetPropertyWithPadReply+class switchExtension(xcffib.Extension):+    def GetProperty(self, value_mask, items, is_checked=True):+        buf = six.BytesIO()+        buf.write(struct.pack("=xx2xI", value_mask))+        if value_mask & CA.Counter:+            counter = items.pop(0)+            buf.write(struct.pack("=I", counter))+        if value_mask & CA.Value:+            value = items.pop(0)+            buf.write(value.pack() if hasattr(value, "pack") else INT64.synthetic(*value).pack())+        if value_mask & CA.ValueType:+            valueType = items.pop(0)+            buf.write(struct.pack("=I", valueType))+        if value_mask & CA.Events:+            events = items.pop(0)+            buf.write(struct.pack("=I", events))+        return self.send_request(59, buf, GetPropertyCookie, is_checked=is_checked)+    def GetPropertyWithPad(self, is_checked=True):+        buf = six.BytesIO()+        buf.write(struct.pack("=xx2x"))+        return self.send_request(60, buf, GetPropertyWithPadCookie, is_checked=is_checked)+xcffib._add_ext(key, switchExtension, _events, _errors)
+ test/generator/switch.xml view
@@ -0,0 +1,93 @@+<!-- based on xinput and sync -->+<xcb header="switch">++  <xidtype name="COUNTER" />++  <struct name="INT64">+    <field type="INT32" name="hi" />+    <field type="CARD32" name="lo" />+  </struct>++  <request name="GetProperty" opcode="59">+    <field type="CARD32"  name="value_mask" enum="CA" />+    <!-- a switch in a request with field bitcases (see sync) -->+    <switch name="items">+      <fieldref>value_mask</fieldref>+      <bitcase>+        <enumref ref="CA">Counter</enumref>+        <field type="COUNTER" name="counter" />+      </bitcase>+      <bitcase>+        <enumref ref="CA">Value</enumref>+        <field type="switch:INT64" name="value" />+      </bitcase>+      <bitcase>+        <enumref ref="CA">ValueType</enumref>+        <field type="CARD32" name="valueType" />+      </bitcase>+      <bitcase>+        <enumref ref="CA">Events</enumref>+        <field type="CARD32" name="events" />+      </bitcase>+    </switch>+    <reply>+      <field type="CARD32" name="num_items" />+      <field type="CARD8"  name="format" enum="PropertyFormat" />+      <!-- a switch in a reply with list bitcases (see sync) -->+      <switch name="items">+        <fieldref>format</fieldref>+        <bitcase>+          <enumref ref="PropertyFormat">8Bits</enumref>+          <list type="CARD8" name="data8">+            <fieldref>num_items</fieldref>+          </list>+        </bitcase>+        <bitcase>+          <enumref ref="PropertyFormat">16Bits</enumref>+          <list type="CARD16" name="data16">+            <fieldref>num_items</fieldref>+          </list>+        </bitcase>+        <bitcase>+          <enumref ref="PropertyFormat">32Bits</enumref>+          <list type="CARD32" name="data32">+            <fieldref>num_items</fieldref>+          </list>+        </bitcase>+      </switch>+    </reply>+  </request>++  <request name="GetPropertyWithPad" opcode="60">+    <reply>+      <field type="CARD32" name="num_items" />+      <field type="CARD8"  name="format" enum="PropertyFormat" />+      <list type="CARD8" name="names">+        <fieldref>num_items</fieldref>+      </list>+      <!-- a switch in a reply with list bitcases that need pads (see sync) -->+      <switch name="items">+        <fieldref>format</fieldref>+        <bitcase>+          <enumref ref="PropertyFormat">8Bits</enumref>+          <list type="CARD8" name="data8">+            <fieldref>num_items</fieldref>+          </list>+        </bitcase>+        <bitcase>+          <enumref ref="PropertyFormat">16Bits</enumref>+          <list type="CARD16" name="data16">+            <fieldref>num_items</fieldref>+          </list>+        </bitcase>+        <bitcase>+          <enumref ref="PropertyFormat">32Bits</enumref>+          <list type="CARD32" name="data32">+            <fieldref>num_items</fieldref>+          </list>+        </bitcase>+      </switch>+    </reply>+  </request>++</xcb>
xcffib.cabal view
@@ -1,5 +1,5 @@ name:                xcffib-version:             0.4.2+version:             0.5.0 synopsis:            A cffi-based python binding for X homepage:            http://github.com/tych0/xcffib license:             OtherLicense@@ -25,7 +25,7 @@  library   build-depends: base ==4.*,-                 xcb-types >= 0.7.0,+                 xcb-types >= 0.8.0,                  language-python >= 0.5.0,                  filepath,                  filemanip,@@ -33,7 +33,8 @@                  containers,                  mtl >= 2.1,                  attoparsec,-                 bytestring+                 bytestring,+                 either   hs-source-dirs: generator   exposed-modules: Data.XCB.Python.Parse,                    Data.XCB.Python.PyHelpers@@ -46,15 +47,17 @@                  xcffib >= 0.1.0,                  language-python >= 0.5.0,                  split,-                 xcb-types >= 0.7.0,-                 optparse-applicative >= 0.5,+                 xcb-types >= 0.8.0,+                 optparse-applicative >= 0.13,                  filepath,                  filemanip,                  directory >= 1.2,                  containers,                  mtl >= 2.1,                  attoparsec,-                 bytestring+                 bytestring,+                 semigroups,+                 either   ghc-options: -Wall  test-suite PyHelpersTests@@ -74,7 +77,7 @@   type: exitcode-stdio-1.0   build-depends: base ==4.*,                  xcffib >= 0.1.0,-                 xcb-types >= 0.7.0,+                 xcb-types >= 0.8.0,                  language-python >= 0.5.0,                  HUnit,                  test-framework,