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 +139/−51
- generator/xcffibgen.hs +1/−0
- test/GeneratorTests.hs +1/−0
- test/generator/switch.py +82/−0
- test/generator/switch.xml +93/−0
- xcffib.cabal +10/−7
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,