def _analyse(self): # list all sections sections = self.r2ob.cmdj("Sj") sm = filter(lambda a: self.sym_sect in a['name'], sections) if sm: sm = sm[0] else: return # get dynsym section as binary string sym_sect = u.bytes2str( self.r2ob.cmdj("pcj %i@%i" % (sm[self.size_type], sm[self.addr_type]))) # cast to Elf_Sym structures symstr_sect_c = c.create_string_buffer(sym_sect) symstr_sect_l = [] for i in range(len(sym_sect) / c.sizeof(self.Elf_Sym)): offset = i * c.sizeof(self.Elf_Sym) symstr_sect_l.append((u.cast(symstr_sect_c, offset, self.Elf_Sym), offset)) # get dynstr section as binary string ss = filter(lambda a: self.symstr_sect in a['name'], sections)[0] ss_sect = u.bytes2str( self.r2ob.cmdj("pcj %i@%i" % (ss[self.size_type], ss[self.addr_type]))) self.symbols = self._parse_symbols(symstr_sect_l, ss_sect, sm[self.addr_type], ss[self.addr_type])
def get_properties(clas_or_proto, *prefixes): '''Yield all properties of an ObjC class or protocol with a name starting with one of the given prefixes. @param clas_or_proto: The class or protocol (L{Class_t} or L{Protocol_t}). @param prefixes: No, one or more property names to match (C{str}-s). @return: For each property, yield a 3-tuple (I{name}, I{attributes}, I{setter}, I{property}) where I{attributes} is a comma-separated list of the property attibutes, I{setter} is the name of the property setter method, provided the property is writable and I{property} is the C{Property} object. For read-only properties, the I{setter} is an empty name "". @note: ObjC Property Attributes: - T<type>"name" = Type - & = Retain last value (retain) - C = Copy - D = Dynamic (@dynamic) - G<name> = Getter selector name - N = Non-atomic (nonatomic) - P = To be garbage collected - R = Read-only (readonly) - S<name> = Setter selector name - t<encoding> = Old-style type encoding - W = Weak reference (__weak) @see: U{Property Attributes<http://Developer.Apple.com/library/content/documentation/ Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html>}. ''' n = c_uint() if isinstance(clas_or_proto, Class_t): props = libobjc.class_copyPropertyList(clas_or_proto, byref(n)) setters = set(_[0] for _ in get_methods(clas_or_proto, 'set')) elif isinstance(clas_or_proto, Protocol_t): props = libobjc.protocol_copyPropertyList(clas_or_proto, byref(n)) setters = [] else: raise TypeError('%s not a %s nor %s: %r' % ('clas_or_proto', Class_t.__name__, Protocol_t.__name__, clas_or_proto)) for prop in props: name = bytes2str(libobjc.property_getName(prop)) if name and name.startswith(prefixes or name): # XXX should yield name, ObjCProperty instance # attrs T@"type",&,C,D,G<name>,N,P,R,S<name>,W,t<encoding>,V<varname> attrs = bytes2str(libobjc.property_getAttributes(prop)) attrs = '%s=(%s)' % (attrs, ', '.join( _PropertyAttributes.get(_[:1], _[:1]) + _[1:] for _ in attrs.split(','))) setter = '' if setters: set_ = 'set' + name.capitalize() + ':' if set_ in setters: setter = _PropertyAttributes['S'] + set_ yield name, attrs, setter, prop
def nsBundleRename(ns_title, match='Python'): '''Change the bundle title if the current title matches. @param ns_title: New bundle title (L{NSStr}). @keyword match: Optional, previous title to match (C{str}). @return: The previous bundle title (C{str}) or None. @note: Used to mimick C{NSApplication.setTitle_(ns_title)}, the name of an L{App} shown in the menu bar. ''' t = ns_title and ns2py(ns_title) if t: _Globals.argv0 = bytes2str(t) # <http://Developer.Apple.com/documentation/ # foundation/nsbundle/1495012-bundlewithpath> # ns = NSBundle.bundleWithPath_(os.path.abspath(match)) p, ns = None, NSMain.Bundle if ns: ns = ns.localizedInfoDictionary() or ns.infoDictionary() if ns: p = ns.objectForKey_(NSMain.BundleName) or None if p: p = ns2py(p, dflt='') or '' if t and match in ('', None, p): # can't be empty ns.setObject_forKey_(ns_title, NSMain.BundleName) return p
def get_methods(clas, *prefixes): '''Yield all methods of an ObjC class with a name starting with one of the given prefixes. @param clas: The class (L{Class_t}). @param prefixes: No, one or more method names to match (C{str}-s). @return: For each method yield a 4-tuple (I{name, encoding, rargtypes, method}), where I{name} is the method name, I{encoding} is the type encoding of the method signature including the return type, I{rargtypes} the C{ctypes} signature, the argtypes C{list}** preceeded by the restype and I{method} the L{Method_t} object. @note: In Python 3+ I{rargtypes} is a C{map} object, not a C{list}. ''' def _ctype(code): return emcoding2ctype(code, dflt=IMP_t) # c_void_p n = c_uint() for method in libobjc.class_copyMethodList(clas, byref(n)): sel = libobjc.method_getName(method) name = bytes2str(libobjc.sel_getName(sel)) if name.startswith(prefixes or name): # XXX should yield name, ObjCMethod instance encoding = libobjc.method_getTypeEncoding(method) rescode = libobjc.method_copyReturnType(method) if not encoding.startswith(rescode): encoding = rescode + encoding rargtypes = map(_ctype, split_encoding(encoding)) yield name, str2bytes(encoding), tuple(rargtypes), method
def get_selectornameof(sel): '''Get the name of an ObjC selector. @param sel: The selector (L{SEL_t}). @return: The selector name (C{str}) if found, C{""} otherwise. ''' isinstanceOf(sel, SEL_t, name='sel') return bytes2str(libobjc.sel_getName(sel)) or ''
def _analyse(self): elf_phdr = u.bytes2str( self.r2ob.cmdj("pcj %i@%i" % (self.Elf_Phdr_size * self.phnum, self.phoff))) elf_phdr_c = c.create_string_buffer(elf_phdr) segments_l = [] for i in range(len(elf_phdr) / self.Elf_Phdr_size): offset = i * self.Elf_Phdr_size segments_l.append((u.cast(elf_phdr_c, offset, self.Elf_Phdr), offset)) self.phdrs = [i for i in self._parse_segments(segments_l)]
def _analyse(self): elf_dyn = u.bytes2str( self.r2ob.cmdj( "pcj %i@%i" % (self.Elf_Dyn_size * self.Elf_Dyn_num, self.dynseg_off))) elf_dyn_c = c.create_string_buffer(elf_dyn) dyns = [] for i in range(len(elf_dyn) / self.Elf_Dyn_size): offset = i * self.Elf_Dyn_size dyns.append((u.cast(elf_dyn_c, offset, self.Elf_Dyn), offset)) self.dyns = [i for i in self._parse_dyns(dyns)]
def infer(v0, v1): dmp = diff_match_patch.diff_match_patch() diffs = dmp.diff_main(utils.bytes2str(v0), utils.bytes2str(v1)) dmp.diff_cleanupEfficiency(diffs) index = 0 sequence = [] op = None for diff in diffs: data = utils.str2bytes(diff[1]) if diff[0] == 0: index += len(data) elif diff[0] == 1: if op is not None and op.type == 'd': op = operation('i', op.pos, data) else: op = operation('i', index, data) sequence.append(op) else: op = operation('d', index, data) sequence.append(op) index += len(data) return sequence
def get_method(clas, name): '''Get a method of an ObjC class by name. @param clas: Class (L{Class_t}). @param name: Method name (C{str}). @return: The method (L{Method_t}) if found, None otherwise. ''' n = c_uint() for method in libobjc.class_copyMethodList(clas, byref(n)): sel = libobjc.method_getName(method) if bytes2str(libobjc.sel_getName(sel)) == name: return method return None
def get_classname(clas, dflt=missing): '''Get the name of an ObjC class. @param clas: The class (L{Class_t}). @return: The class name (C{str}). @raise ValueError: Invalid I{clas}, iff no I{dflt} provided. ''' if clas and isinstanceOf(clas, Class_t, name='clas'): return bytes2str(libobjc.class_getName(clas)) if dflt is missing: raise ValueError('no such %s: %r' % ('Class', clas)) return dflt
def __new__(cls, ustr): '''New L{NSStr} wrapping C{NS[Constant]String}. @param ustr: The string value (C{str} or C{unicode}). @return: The string (L{NSStr}). ''' self = super(NSStr, cls).__new__(cls, cfString(ustr)) self._str = bytes2str(ustr) # L{ObjCinstance} caches ObjC objects using the # objc_ptr.value as key, which may or may not # create in a singleton for each string value, # retaining strings seems to help singletons. return self if len(ustr) > 1 else retain(self)
def _analyse_reln(self, addend=False): r_c = self.relsz[0]["d_val"] if not addend else self.relasz[0]["d_val"] v_addr = self.rel[0]["d_ptr"] if not addend else self.rela[0]["d_ptr"] sz = self.Elf_Rel_size if not addend else self.Elf_Rela_size reln = self.Elf_Rel if not addend else self.Elf_Rela relocs = u.bytes2str(self.r2ob.cmdj("pcj %i@%i" % (sz * r_c, v_addr))) relocs_c = c.create_string_buffer(relocs) rels = [] for i in range(len(relocs) / sz): offset = i * sz rels.append((u.cast(relocs_c, offset, reln), v_addr + offset)) for i in self._parse_reln(rels, addend): self.relocs.append(i)
def title(self, title): '''Set the title. ''' if isinstance(title, NSStr): try: self.NS.setTitle_(title) except AttributeError: # no NSApplication.setTitle_ pass title = nsString2str(title) else: try: t = NSStr(title) self.NS.setTitle_(t) release(t) except AttributeError: # no NSApplication.setTitle_ t.release() self._title = bytes2str(title)
def get_protocols(clas, *prefixes): '''Yield all protocols of an ObjC class with a name starting with one of the given prefixes. @param clas: The class (L{Class_t}). @param prefixes: No, one or more protocol names to match (C{str}-s). @return: For each protocol, yield a 2-tuple (I{name}, I{protocol}) where I{name} is the protocol name and I{protocol} the L{Protocol_t} object. ''' n = c_uint() for proto in libobjc.class_copyProtocolList(clas, byref(n)): name = bytes2str(libobjc.protocol_getName(proto)) if name.startswith(prefixes or name): # XXX should yield name, ObjCProtocol instance yield name, proto
def get_ivars(clas, *prefixes): '''Yield all instance variables (ivar) of an ObjC class with a name starting with one of the given prefixes. @param clas: The class (L{Class_t}). @param prefixes: No, one or more ivar names to match (C{str}-s). @return: For each ivar yield a 4-tuple (I{name, encoding, ctype, ivar}) where I{name} is the ivar name, I{encoding} is the ivar's type encoding, I{ctype} is the ivar's C{ctypes} type and I{ivar} the L{Ivar_t} object. ''' n = c_uint() for ivar in libobjc.class_copyIvarList(clas, byref(n)): name = bytes2str(libobjc.ivar_getName(ivar)) if name.startswith(prefixes or name): # XXX should yield name, ObjCIvar instance encoding = libobjc.ivar_getTypeEncoding(ivar) ctype = emcoding2ctype(encoding, dflt=Ivar_t) # c_void_p yield name, str2bytes(encoding), ctype, ivar
def _traitsin(traits, raiser=True): # Convert and check traits if isinstance(traits, _Ints): ts = traits & _maskTraits elif isinstance(traits, _ByteStrs): ts = 0 for t in bytes2str(traits).strip().split(): m = _familyTraits.get(t.lower(), None) if m: ts |= m elif raiser and m is None: raise FontTraitError('invalid %s: %r' % ('trait', t)) else: raise FontTraitError('invalid %s: %r' % ('traits', traits)) # check for mutually exclusive traits if _traitex(ts, FontTrait.Condensed | FontTrait.Expanded) or \ _traitex(ts, FontTrait.Italic | FontTrait.UnItalic) or \ _traitex(ts, FontTrait.Bold | FontTrait.UnBold): raise FontTraitError('incompatible %s: %r' % ('traits', traits)) return ts
def url2NS(py, url2=None): '''Create an C{NSURL} instance from a Python string. @param py: The URL (C{str} or C{unicode}). @keyword url2: Optionally, relative to this URL (C{str} or C{unicode}). @return: The ObjC instance (C{NSURL}). @see: U{URL<http://Developer.Apple.com/documentation/foundation/url>} for parsing an C{NSURL}. ''' ns = release(NSStr(py)) if ':' in bytes2str(py): if url2: return NSURL.alloc().initWithString_relativeToURL_(ns, url2NS(url2)) else: return NSURL.alloc().initWithString_(ns) elif url2: return NSURL.alloc().initFileURLWithPath_relativeToURL_(ns, url2NS(url2)) else: return NSURL.alloc().initFileURLWithPath_(ns)
def __init__(self, title='Main', frame=None, excl=0, auto=False, **kwds): '''Create a new L{Window}. @keyword title: Window title (C{str}). @keyword frame: Window frame (L{Rect}, L{NSRect_t}, L{NSRect4_t}, or None). @keyword excl: Window styles to exclude (L{WindowStyle}C{.attribute}). @keyword auto: Release window resource when closed (C{bool}). @keyword kwds: Optional, additional keyword arguments. @raise WindowError: Unique C{Id} exists. ''' self._frame = Screen(0.5) if frame is None else Rect(frame) self._ratio = self._frame.width, self._frame.height self.NS = NSWindow.alloc( ).initWithContentRect_styleMask_backing_defer_( self.frame.NS, WindowStyle.Typical ^ excl, # PYCHOK expected NSBackingStoreBuffered, NO) self.title = bytes2str(title) self.front(True) if kwds: super(Window, self).__init__(**kwds) # XXX self.NS.setIdentifier_(int2NS(id(self))) self._NSuniqID = u = self.NS.uniqueID() if u in _Globals.Windows: raise WindowError('%s %r exists: %r' % ('.uniqueID', u, _Globals.Windows[u])) _Globals.Windows[u] = self if _Globals.App and not self.app: self.app = _Globals.App if auto: self.NS.setReleasedWhenClosed_(YES) self._auto = True self.NSdelegate = retain(NSWindowDelegate.alloc().init(self))
def ratio(self, ratio): '''Set this window's aspect ratio. @param ratio: New ratio (L{Size}, 2-tuple (width, height), str("w:h") or C{NSSize_t}). @raise WindowError: Invalid I{ratio}. ''' try: r = bytes2str(ratio, dflt=None) if r is not None: r = map(int, r.split(':')) elif isinstance(ratio, (tuple, list)) and len(ratio) == 2: r = tuple(ratio) else: # NSSize_t r = ratio.width, ratio.height except (AttributeError, ValueError): raise WindowError('invalid %s: %r' % ('ratio', ratio)) r = aspect_ratio(*r) if r: self._ratio = r self.NS.setContentAspectRatio_(NSSize_t(r[0], r[1]))
def DownloadBlock(self, request_iterator, context): hashs = [] for request in request_iterator: session_id = request.SessionId path = request.Path base_rev = int(request.BaseRev) hashs.append(request.Hash) user = global_variables._user_session.get_user_by_session(session_id) truepath = utils.get_true_path(user, path) + '.metadata' mnode = global_variables._metadata_cache.get_usable_node(truepath) mnode.acquire_lock() if mnode.empty or not mnode.obj.path == truepath: mnode.load(truepath) data, boundaries = mnode.obj.read(base_rev) boundaries.append(len(data)) hashs_base = mnode.obj.get_hashlist(base_rev) blocks = [] for hash in hashs: i = hashs_base.index(hash) blockdata = data[boundaries[i]:boundaries[i + 1]] blocks.append({'hash': hash, 'data': utils.bytes2str(blockdata)}) jstr = json.dumps({'blocks': blocks}) mnode.release_lock() return GRPCServer_pb2.StringResponse(PayLoad=jstr)
def label(self, label): '''Set the badge text of the app's dock tile (C{str}). ''' self._label = bytes2str(label) self.NS.setBadgeLabel_(release(NSStr(label))) self.NS.display()
def split_encoding(encoding): # MCCABE 18 '''Split a type encoding into separate type encodings. Does not handle C{bitfield}s, C{array}s, C{struct}s, C{union}s, etc. and strips any offset, size or width specifiers from the encoding. @return: The individual type encodings (C{list}). @raise TypeCodeError: Invalid or unbalanced I{encoding}. @example: >>> split_encoding('^v16@0:8') >>> ['^v', '@', ':'] >>> split_encoding('{CGSize=dd}40@0:8{PyObject=@}Q32') >>> ['{CGSize=dd}', '@', ':', '{PyObject=@}', 'Q'] Supported Type Encodings: - B = bool (C++ bool, C99 _Bool) - c, C = char, unsigned char - f, d = float, double - i, I = int, unsigned int - l, L = long, unsigned long (32-bit in 64-bit Apps) - q, Q = long long, unsigned long long - s, S = short, unsigned short - t, T = 128-bit int, unsigned int - v = void - * = string (char *) - : = method selector C{SEL/cmd} - # = class - #"name" = class "name" - @ = object instance C{Id/self} or statically typed - @"name" = instance C{Id/self} of class "name" - ^type = pointer to type - ? = unknown type (among other things, used for function pointers) PyCocoa specific: - P = Python object, shorthand for C{PyObjectEncoding} Unsupported Type Encodings: - bW = bitfield of width W - [Ltype] = array of L items of type - E{lb}name=type...E{rb} = structure - (name=type...) = union - <...> = block - ?<...> = block with signature Unknown or for ObjC internal use: - A = ? - j = ? - n, N = in, inout - o, O = out, bycopy - r, R = const, byref - V = oneway @note: Type encodings may be preceeded by C{"name"}, for example a C{bitfield} C{"name"b1}, C{struct} items C{E{lb}CGsize="width"d"heigth"dE{rb}}, C{union} items, etc. and all such C{"name"} prefixes are ignored. @see: U{Type Encodings<http://Developer.Apple.com/library/content/documentation/ Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html>}, U{NSHipster Type Encodings<http://NSHipster.com/type-encodings>} and U{Digits in type encoding<http://StackOverflow.com/questions/11527385/ how-are-the-digits-in-objc-method-type-encoding-calculated>}. ''' code = [] codes = [] opened = [] # opened braces, brackets, parensm etc. quoted = False # inside double quotes for b in iterbytes(str2bytes(encoding)): if b in _TYPEOPENERS: if code and code[-1] != b'^' and not opened: codes.append(_join(code)) code = [] opened.append(_TYPE2CLOSER[b]) code.append(b) elif b in _TYPECLOSERS: code.append(b) if not opened or b != opened.pop(): raise TypeCodeError('encoding %s: %r' % ('unbalanced', bytes2str(_join(code)))) if not opened: codes.append(_join(code)) code = [] elif opened: # inside braces, etc # XXX ignore digits? code.append(b) # stick anything on elif b == b'"': code.append(b) if quoted: # closing quotes code = _join(code) if code[:2] in (b'@"', b'#"'): # XXX only @"..." and #"..." are OK # XXX what about ^@"..." and ^#"..."? codes.append(code) elif code[:1] == b'"': pass # ignore prefix "name" else: raise TypeCodeError('encoding %s: %r' % ('invalid', bytes2str(code))) code = [] quoted = not quoted elif quoted: # inside quotes # XXX only alphanumeric, '_', '.'? code.append(b) # stick anything on elif b in _TYPECODESET: if code and code[-1] != b'^': # not a pointer, previous char != '^' codes.append(_join(code)) code = [] code.append(b) elif b in _TYPESKIPPED: pass # ignore type, width and offsets if opened: raise TypeCodeError('encoding %s: %r' % ('unbalanced', bytes2str(encoding))) if code: # final type code codes.append(_join(code)) return codes
def encoding2ctype(code, dflt=missing, name='type'): # MCCABE 20 '''Return the C{ctypes} type for a single ObjC type encoding code. @param code: The type encoding (C{bytes}). @keyword dflt: Default encoding (C{ctype}). @keyword name: Name of the type (C{str}). @return: The C{ctype} (C{ctypes}). @raise TypeCodeError: Invalid or unbalanced I{code}, unless a I{dflt} C{ctype} is provided. ''' try: return _encoding2ctype[code] except KeyError: pass coderr = code if code[:1] == b'r': # const ptr or decorator code = code[1:] try: c = code[-1:] if c == b'"': # ..."name" suffix i = code.find(c) if i < 1: raise TypeCodeError code = code[:i] # drop "name" elif c == b']': # array ...[...] i = code.find(b'[') if i < 0: raise TypeCodeError elif i > 0: # ignore array type code = code[:i + 1] + c else: # convert array to pointer code = b'^' + code[1:-1].strip(b'0123456789') elif c in _TYPECLOSERS: # Block, Struct or Union o = _TYPE2OPENER[c] if code[:1] != o: o = b'^' + o if code[:2] != o: raise TypeCodeError code = o + c # {} or ^{}, etc. if code[:1] == b'^': if len(code) < 2: raise TypeCodeError # ctype = POINTER(_encoding2ctype[code[1:]]) # breaks on '^^^...' ctype = POINTER(encoding2ctype(code[1:])) # allows '^^^...' _encoding2ctype[code] = ctype return ctype elif len(code): return _encoding2ctype[code] else: raise TypeCodeError except TypeCodeError: raise TypeCodeError('%s encoding %s: %r' % (bytes2str(name), 'invalid', coderr)) except KeyError: pass if dflt is missing: raise TypeCodeError('%s encoding %s: %r' % (bytes2str(name), 'unknown', coderr)) elif code[:1] == b'^': return POINTER(dflt) else: return dflt
def __str__(self): return 'None' if self.value is None else bytes2str(self.name_)
def name(self, name): '''Set the font name (C{str}). ''' self._name = bytes2str(name)
def _analyse(self): elf_ehdr = u.bytes2str( self.r2ob.cmdj("pcj %i@%i" % (self.Elf_Ehdr_size, self.elf_offset))) elf_ehdr_c = c.create_string_buffer(elf_ehdr) ehdr = u.cast(elf_ehdr_c, 0, self.Elf_Ehdr) self.ehdr = OrderedDict([ ( "ei_class", self.elf_class, ), ( "ei_class_desc", ELFCLASS.get(self.elf_class, "N/A"), ), ( "e_type", ET[ehdr.e_type], ), ( "e_machine", EM[ehdr.e_machine], ), ( "e_version", EV[ehdr.e_version], ), ( "e_entry", ehdr.e_entry, ), ( "e_phoff", ehdr.e_phoff, ), ( "e_shoff", ehdr.e_shoff, ), ( "e_flags", ehdr.e_flags, ), ( "e_ehsize", ehdr.e_ehsize, ), ( "e_phentsize", ehdr.e_phentsize, ), ( "e_phnum", ehdr.e_phnum, ), ( "e_shentsize", ehdr.e_shentsize, ), ( "e_shnum", ehdr.e_shnum, ), ("e_shstrndx", ehdr.e_shstrndx), ])
def __init__(self, family_or_font, size=0, traits=0, weight=5): '''New L{Font}. @param family_or_font: Generic font name (C{str}, L{Str}, L{NSStr}) like "Times" or "Helvetica" or a L{Font}, C{NSFont} or C{NSFontDescriptor} instance. @keyword size: Desired point size (C{int}), zero for any. @keyword traits: Desired font traits (C{str} or C{FontTrait}C{s mask}). @keyword weigth: Desired book weight (C{int}) in range 0..15, where 0=light, 5=regular, 9=bold and 15=heavy. @raise FontError: No such I{family_or_font}. @raise FontTraitError: Mutually exclusive I{traits}. @raise TypeError: Invalid I{family_or_font}. @raise ValueError: Invalid I{weight}. @note: The new L{Font} may not exhibit the desired I{traits} and I{weight}. The I{weight} is ignored if I{traits} include C{FontTrait.Bold}, both I{traits} and I{weight} are ignored if I{family_or_font} is C{NSFontDescriptor}. @see: Function L{fontsof} to obtain all available fonts of a particular font family. ''' if isinstance(family_or_font, Str): ns, py = family_or_font.NS, str(family_or_font) elif isinstance(family_or_font, _ByteStrs): ns, py = release(NSStr(family_or_font)), bytes2str(family_or_font) elif isinstance(family_or_font, NSStr): ns, py = family_or_font, nsString2str(family_or_font) # elif isObjCInstanceOf(family_or_font, NSFontDescriptor): # <http://Developer.Apple.com/documentation/appkit/nsfont/1525386-init> # ignore traits and weight # ns, py = NSFont.alloc().init_(family_or_font, size), None elif isObjCInstanceOf(family_or_font, NSFont, name='family_or_font'): ns, py = family_or_font, None if size == 0: size = ns.pointSize() if traits == 0: traits = NSMain.FontManager.traitsOfFont_(ns) if not (size == ns.pointSize() and traits == NSMain.FontManager.traitsOfFont_(ns)): ns = ns.familyName() py = nsString2str(ns) if py is not None: # <http://Developer.Apple.com/documentation/appkit/ # nsfontmanager/1462332-fontwithfamily> self._traits = _traitsin(traits) self._weight = _weightin(weight) ns = NSMain.FontManager.fontWithFamily_traits_weight_size_( ns, self._traits, self._weight, size) if isNone(ns): self._family = py self._size = flint(size) raise FontError('no such %s: %s' % ('font', self._argstr())) self._NS = ns # _RO # <http://Developer.Apple.com/library/content/documentation/ # TextFonts/Conceptual/CocoaTextArchitecture/FontHandling/FontHandling.html> self._family = nsString2str(ns.familyName()) self._height = flint(NSMain.LayoutManager.defaultLineHeightForFont_(ns) + 1) self._name = nsString2str(ns.fontName()) self._size = flint(ns.pointSize()) # traits not always reflect actual traits self._traits = NSMain.FontManager.traitsOfFont_(ns) or 0 # update with the family traits, if any self._traits |= _traitsin(self._family, raiser=False) if ns.isFixedPitch() and not self.isMonoSpace: self._traits |= FontTrait.MonoSpace self._weight = NSMain.FontManager.weightOfFont_(ns)