xcffib 0.3.6 → 0.4.0
raw patch · 12 files changed
+211/−34 lines, 12 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Data.XCB.Python.Parse: instance Eq TypeInfo
- Data.XCB.Python.Parse: instance Ord TypeInfo
- Data.XCB.Python.Parse: instance Show BindingPart
- Data.XCB.Python.Parse: instance Show TypeInfo
- Data.XCB.Python.PyHelpers: instance PseudoArgument (Argument ())
- Data.XCB.Python.PyHelpers: instance PseudoArgument (Expr ())
- Data.XCB.Python.PyHelpers: instance PseudoExpr (Expr ())
- Data.XCB.Python.PyHelpers: instance PseudoExpr String
+ Data.XCB.Python.Parse: instance GHC.Classes.Eq Data.XCB.Python.Parse.TypeInfo
+ Data.XCB.Python.Parse: instance GHC.Classes.Ord Data.XCB.Python.Parse.TypeInfo
+ Data.XCB.Python.Parse: instance GHC.Show.Show Data.XCB.Python.Parse.BindingPart
+ Data.XCB.Python.Parse: instance GHC.Show.Show Data.XCB.Python.Parse.TypeInfo
+ Data.XCB.Python.PyHelpers: instance Data.XCB.Python.PyHelpers.PseudoArgument (Language.Python.Common.AST.Argument ())
+ Data.XCB.Python.PyHelpers: instance Data.XCB.Python.PyHelpers.PseudoArgument (Language.Python.Common.AST.Expr ())
+ Data.XCB.Python.PyHelpers: instance Data.XCB.Python.PyHelpers.PseudoExpr (Language.Python.Common.AST.Expr ())
+ Data.XCB.Python.PyHelpers: instance Data.XCB.Python.PyHelpers.PseudoExpr GHC.Base.String
+ Data.XCB.Python.PyHelpers: mkArg :: String -> Argument ()
Files
- generator/Data/XCB/Python/Parse.hs +61/−31
- generator/Data/XCB/Python/PyHelpers.hs +1/−0
- tests/GeneratorTests.hs +1/−0
- tests/generator/event.py +15/−0
- tests/generator/no_sequence.py +5/−0
- tests/generator/render.py +59/−0
- tests/generator/render.xml +27/−0
- tests/generator/request.py +1/−1
- tests/generator/request_reply.py +6/−0
- tests/generator/struct.py +17/−0
- tests/generator/type_pad.py +17/−1
- xcffib.cabal +1/−1
generator/Data/XCB/Python/Parse.hs view
@@ -48,8 +48,7 @@ -- struct.unpack string, second is the size. BaseType String | -- | A composite type, i.e. a Struct or Union created by XCB. First arg is- -- the extension that defined it, second is the name of the type, third arg- -- is the size if it is known.+ -- the extension that defined it, second is the name of the type. CompositeType String String deriving (Eq, Ord, Show) @@ -336,25 +335,30 @@ let name = accessor n in case m M.! typ of BaseType c -> Left (Just name, c)- -- XXX: be a little smarter here? we should really make sure that things- -- have a .pack(); if users are calling us via the old style api, we need- -- to support that as well. This isn't super necessary, though, because- -- currently (xcb-proto 1.10) there are no direct packs of raw structs, so- -- this is really only necessary if xpyb gets forward ported in the future if- -- there are actually calls of this type.- CompositeType _ _ -> Right $ [(name, mkCall (name ++ ".pack") noArgs)]+ CompositeType _ typNam ->+ let cond = mkCall "hasattr" [mkArg name, ArgExpr (mkStr "pack") ()]+ trueB = mkCall (name ++ ".pack") noArgs+ synthetic = mkCall (typNam ++ ".synthetic") [mkArg ("*" ++ name)]+ falseB = mkCall (mkDot synthetic "pack") noArgs+ in Right $ [(name, CondExpr trueB cond falseB ())] -- TODO: assert values are in enum?-structElemToPyPack ext m accessor (X.List n typ _ _) =+structElemToPyPack ext m accessor (X.List n typ expr _) = let name = accessor n- in case m M.! typ of- BaseType c -> Right $ [(name, mkCall "xcffib.pack_list" [ mkName $ name- , mkStr c- ])]+ -- The convention seems to be either to have a <fieldref> nested in the+ -- list, or use "%s_len" % name if there is no fieldref. We use a little+ -- hack here and write an empty string, since we don't need to write this+ -- length, but we have no way to indicate that right now.+ list_len = if isNothing expr then [(name ++ "_len", mkStr "")] else []+ list = case m M.! typ of+ BaseType c -> [(name, mkCall "xcffib.pack_list" [ mkName $ name+ , mkStr c+ ])] CompositeType tExt c -> let c' = if tExt == ext then c else (tExt ++ "." ++ c)- in Right $ [(name, mkCall "xcffib.pack_list" ([ mkName $ name- , mkName c'- ]))]+ in [(name, 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@@ -401,12 +405,12 @@ -- implicitly. (listNames, lists) = unzip $ filter (flip notElem args . fst) (concat stmts) listNames' = case (ext, name) of- -- XXX: QueryTextExtents has a field named "odd_length" with a- -- fieldref of "string_len", so we fix it up here to match.+ -- XXX: QueryTextExtents has a field named "odd_length"+ -- which is unused, let's just drop it. ("xproto", "QueryTextExtents") ->- let replacer "odd_length" = "string_len"- replacer s = s- in map replacer listNames+ let notOdd "odd_length" = False+ notOdd _ = True+ in filter notOdd listNames _ -> listNames packStr = addStructData prefix $ intercalate "" keys write = mkCall "buf.write" [mkCall "struct.pack"@@ -535,6 +539,30 @@ ] in M.union m m' +mkSyntheticMethod :: [GenStructElem Type] -> [Statement ()]+mkSyntheticMethod membs = do+ let names = catMaybes $ map getName membs+ args = mkParams $ "cls" : names+ self = mkAssign "self" $ mkCall (mkDot "cls" "__new__") [mkName "cls"]+ body = map assign names+ ret = mkReturn $ mkName "self"+ synthetic = mkMethod "synthetic" args $ (self : body) ++ [ret]+ classmethod = Decorator [ident "classmethod"] noArgs ()+ if null names then [] else [Decorated [classmethod] synthetic ()]+ where+ getName :: GenStructElem Type -> Maybe String+ getName (Pad _) = Nothing+ getName (X.List n _ _ _) = Just n+ getName (SField n _ _ _) = Just n+ getName (ExprField n _ _) = Just n+ getName (ValueParam _ n _ _) = Just n+ getName (Switch n _ _) = Just n+ getName (Doc _ _ _) = Nothing+ getName (Fd n) = Just n++ assign :: String -> Statement ()+ assign n = mkAssign (mkDot "self" n) $ mkName n+ processXDecl :: String -> XDecl -> State TypeInfoMap BindingPart@@ -553,20 +581,22 @@ m <- get let (statements, len) = mkStructStyleUnpack "" ext m membs pack = mkPackMethod ext n m Nothing membs Nothing+ synthetic = mkSyntheticMethod membs fixedLength = maybeToList $ do theLen <- len let rhs = mkInt theLen return $ mkAssign "fixed_size" rhs modify $ mkModify ext n (CompositeType ext n)- return $ Declaration [mkXClass n "xcffib.Struct" statements (pack : fixedLength)]+ return $ Declaration [mkXClass n "xcffib.Struct" statements (pack : fixedLength ++ synthetic)] processXDecl ext (XEvent name opcode membs noSequence) = do m <- get let cname = name ++ "Event" prefix = if fromMaybe False noSequence then "x" else "x%c2x" pack = mkPackMethod ext name m (Just (prefix, opcode)) membs (Just 32)+ synthetic = mkSyntheticMethod membs (statements, _) = mkStructStyleUnpack prefix ext m membs eventsUpd = mkDictUpdate "_events" opcode cname- return $ Declaration [ mkXClass cname "xcffib.Event" statements [pack]+ return $ Declaration [ mkXClass cname "xcffib.Event" statements (pack : synthetic) , eventsUpd ] processXDecl ext (XError name opcode membs) = do@@ -586,7 +616,7 @@ let -- xtest doesn't seem to use the same packing strategy as everyone else, -- but there is no clear indication in the XML as to why that is. yay.- prefix = if ext == "xtest" then "xx2x" else "x%c2x"+ prefix = if ext /= "xproto" then "xx2x" else "x%c2x" (args, packStmts) = mkPackStmts ext name m id prefix membs cookieName = (name ++ "Cookie") replyDecl = concat $ maybeToList $ do@@ -605,12 +635,12 @@ argChecked = ArgKeyword (ident "is_checked") (mkName "is_checked") () checkedParam = Param (ident "is_checked") Nothing (Just isChecked) () allArgs = (mkParams $ "self" : args) ++ [checkedParam]- mkArg = flip ArgExpr ()- ret = mkReturn $ mkCall "self.send_request" ((map mkArg [ mkInt opcode- , mkName "buf"- ])- ++ hasReply- ++ [argChecked])+ mkArg' = flip ArgExpr ()+ ret = mkReturn $ mkCall "self.send_request" ((map mkArg' [ mkInt opcode+ , mkName "buf"+ ])+ ++ hasReply+ ++ [argChecked]) requestBody = buf ++ packStmts ++ [ret] request = mkMethod name allArgs requestBody return $ Request request replyDecl
generator/Data/XCB/Python/PyHelpers.hs view
@@ -21,6 +21,7 @@ mkAssign, mkCall, noArgs,+ mkArg, mkEnum, mkName, mkDot,
tests/GeneratorTests.hs view
@@ -39,6 +39,7 @@ , "type_pad" , "render_1.7" , "xproto_1.7"+ , "render" ] mkFname :: String -> FilePath
tests/generator/event.py view
@@ -22,5 +22,20 @@ if buf_len < 32: buf.write(struct.pack("x" * (32 - buf_len))) return buf.getvalue()+ @classmethod+ def synthetic(cls, rotation, timestamp, config_timestamp, root, request_window, sizeID, subpixel_order, width, height, mwidth, mheight):+ self = cls.__new__(cls)+ self.rotation = rotation+ self.timestamp = timestamp+ self.config_timestamp = config_timestamp+ self.root = root+ self.request_window = request_window+ self.sizeID = sizeID+ self.subpixel_order = subpixel_order+ self.width = width+ self.height = height+ self.mwidth = mwidth+ self.mheight = mheight+ return self _events[0] = ScreenChangeNotifyEvent xcffib._add_ext(key, eventExtension, _events, _errors)
tests/generator/no_sequence.py view
@@ -20,5 +20,10 @@ if buf_len < 32: buf.write(struct.pack("x" * (32 - buf_len))) return buf.getvalue()+ @classmethod+ def synthetic(cls, keys):+ self = cls.__new__(cls)+ self.keys = keys+ return self _events[11] = KeymapNotifyEvent xcffib._add_ext(key, no_sequenceExtension, _events, _errors)
+ tests/generator/render.py view
@@ -0,0 +1,59 @@+import xcffib+import struct+import six+MAJOR_VERSION = 0+MINOR_VERSION = 11+key = xcffib.ExtensionKey("RENDER")+_events = {}+_errors = {}+class COLOR(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.red, self.green, self.blue, self.alpha = unpacker.unpack("HHHH")+ self.bufsize = unpacker.offset - base+ def pack(self):+ buf = six.BytesIO()+ buf.write(struct.pack("=HHHH", self.red, self.green, self.blue, self.alpha))+ return buf.getvalue()+ fixed_size = 8+ @classmethod+ def synthetic(cls, red, green, blue, alpha):+ self = cls.__new__(cls)+ self.red = red+ self.green = green+ self.blue = blue+ self.alpha = alpha+ return self+class RECTANGLE(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.x, self.y, self.width, self.height = unpacker.unpack("hhHH")+ self.bufsize = unpacker.offset - base+ def pack(self):+ buf = six.BytesIO()+ buf.write(struct.pack("=hhHH", self.x, self.y, self.width, self.height))+ return buf.getvalue()+ fixed_size = 8+ @classmethod+ def synthetic(cls, x, y, width, height):+ self = cls.__new__(cls)+ self.x = x+ self.y = y+ self.width = width+ self.height = height+ return self+class renderExtension(xcffib.Extension):+ def FillRectangles(self, op, dst, color, rects_len, rects, is_checked=False):+ buf = six.BytesIO()+ buf.write(struct.pack("=xx2xB3xI", op, dst))+ buf.write(color.pack() if hasattr(color, "pack") else COLOR.synthetic(*color).pack())+ buf.write("")+ buf.write(xcffib.pack_list(rects, RECTANGLE))+ return self.send_request(26, buf, is_checked=is_checked)+xcffib._add_ext(key, renderExtension, _events, _errors)
+ tests/generator/render.xml view
@@ -0,0 +1,27 @@+<xcb header="render" extension-xname="RENDER" extension-name="Render"+ major-version="0" minor-version="11">++ <struct name="COLOR">+ <field type="CARD16" name="red" />+ <field type="CARD16" name="green" />+ <field type="CARD16" name="blue" />+ <field type="CARD16" name="alpha" />+ </struct>++ <xidtype name="PICTURE" />++ <struct name="RECTANGLE">+ <field type="INT16" name="x" />+ <field type="INT16" name="y" />+ <field type="CARD16" name="width" />+ <field type="CARD16" name="height" />+ </struct>++ <request name="FillRectangles" opcode="26">+ <field type="CARD8" name="op" enum="PictOp" />+ <pad bytes="3" />+ <field type="PICTURE" name="dst" />+ <field type="COLOR" name="color" />+ <list type="RECTANGLE" name="rects" />+ </request>+</xcb>
tests/generator/request.py view
@@ -6,7 +6,7 @@ class requestExtension(xcffib.Extension): def CreateWindow(self, depth, wid, parent, x, y, width, height, border_width, _class, visual, value_mask, value_list, is_checked=False): buf = six.BytesIO()- buf.write(struct.pack("=xB2xIIhhHHHHI", depth, wid, parent, x, y, width, height, border_width, _class, visual))+ buf.write(struct.pack("=xx2xBIIhhHHHHI", depth, wid, parent, x, y, width, height, border_width, _class, visual)) buf.write(struct.pack("=I", value_mask)) buf.write(xcffib.pack_list(value_list, "I")) return self.send_request(1, buf, is_checked=is_checked)
tests/generator/request_reply.py view
@@ -17,6 +17,12 @@ buf.write(struct.pack("=B", self.name_len)) buf.write(xcffib.pack_list(self.name, "c")) return buf.getvalue()+ @classmethod+ def synthetic(cls, name_len, name):+ self = cls.__new__(cls)+ self.name_len = name_len+ self.name = name+ return self class ListExtensionsReply(xcffib.Reply): def __init__(self, unpacker): if isinstance(unpacker, xcffib.Protobj):
tests/generator/struct.py view
@@ -16,6 +16,13 @@ buf.write(struct.pack("=Iii", self.resolution, self.minimum, self.maximum)) return buf.getvalue() fixed_size = 12+ @classmethod+ def synthetic(cls, resolution, minimum, maximum):+ self = cls.__new__(cls)+ self.resolution = resolution+ self.minimum = minimum+ self.maximum = maximum+ return self class ValuatorInfo(xcffib.Struct): def __init__(self, unpacker): if isinstance(unpacker, xcffib.Protobj):@@ -30,4 +37,14 @@ buf.write(struct.pack("=BBBBI", self.class_id, self.len, self.axes_len, self.mode, self.motion_size)) buf.write(xcffib.pack_list(self.axes, AxisInfo)) return buf.getvalue()+ @classmethod+ def synthetic(cls, class_id, len, axes_len, mode, motion_size, axes):+ self = cls.__new__(cls)+ self.class_id = class_id+ self.len = len+ self.axes_len = axes_len+ self.mode = mode+ self.motion_size = motion_size+ self.axes = axes+ return self xcffib._add_ext(key, structExtension, _events, _errors)
tests/generator/type_pad.py view
@@ -16,6 +16,16 @@ buf.write(struct.pack("=hhhhhH", self.left_side_bearing, self.right_side_bearing, self.character_width, self.ascent, self.descent, self.attributes)) return buf.getvalue() fixed_size = 12+ @classmethod+ def synthetic(cls, left_side_bearing, right_side_bearing, character_width, ascent, descent, attributes):+ self = cls.__new__(cls)+ self.left_side_bearing = left_side_bearing+ self.right_side_bearing = right_side_bearing+ self.character_width = character_width+ self.ascent = ascent+ self.descent = descent+ self.attributes = attributes+ return self class FONTPROP(xcffib.Struct): def __init__(self, unpacker): if isinstance(unpacker, xcffib.Protobj):@@ -29,6 +39,12 @@ buf.write(struct.pack("=II", self.name, self.value)) return buf.getvalue() fixed_size = 8+ @classmethod+ def synthetic(cls, name, value):+ self = cls.__new__(cls)+ self.name = name+ self.value = value+ return self class ListFontsWithInfoReply(xcffib.Reply): def __init__(self, unpacker): if isinstance(unpacker, xcffib.Protobj):@@ -51,7 +67,7 @@ class type_padExtension(xcffib.Extension): def ListFontsWithInfo(self, max_names, pattern_len, pattern, is_checked=True): buf = six.BytesIO()- buf.write(struct.pack("=xx2xHH", max_names, pattern_len))+ buf.write(struct.pack("=xx2xxHH", max_names, pattern_len)) buf.write(xcffib.pack_list(pattern, "c")) return self.send_request(50, buf, ListFontsWithInfoCookie, is_checked=is_checked) xcffib._add_ext(key, type_padExtension, _events, _errors)
xcffib.cabal view
@@ -1,5 +1,5 @@ name: xcffib-version: 0.3.6+version: 0.4.0 synopsis: A cffi-based python binding for X homepage: http://github.com/tych0/xcffib license: OtherLicense