Last active
August 29, 2015 14:14
-
-
Save ptomato/a768cfbaeb26724acdab to your computer and use it in GitHub Desktop.
GJS overrides reader
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const Gio = imports.gi.Gio; | |
let file = Gio.File.new_for_path(ARGV[0]); | |
let moduleName = file.get_basename().split('.')[0]; | |
imports.searchPath.unshift(file.get_parent().get_path()); | |
let module = imports[moduleName]; | |
imports.searchPath.shift(); | |
// Create missing parts of GObject-introspected API. Since we are importing the | |
// override file directly instead of together with the GIR module, then if we | |
// don't do this, statements like this will fail: | |
// GLib.Variant.prototype.toString = function () { ... }; | |
let lastAttempt; | |
while (true) { | |
try { | |
module._init(); | |
break; | |
} catch (e if e instanceof TypeError) { | |
if (!e.message.search('is undefined')) | |
throw e; | |
let undefinedSymbol = e.message.split(' ')[0]; | |
let props = undefinedSymbol.split('.'); | |
if (lastAttempt === undefinedSymbol) | |
throw e; | |
lastAttempt = undefinedSymbol; | |
if (props[0] === 'this' || props[0] === moduleName) | |
props.shift(); | |
let object = module; | |
let name; | |
while((name = props.shift())) { | |
object[name] = function () {}; | |
object = object[name]; | |
} | |
continue; | |
} | |
} | |
function ApiSymbol(name, type) { | |
this.name = name; | |
this.type = type; | |
this.children = []; | |
} | |
// These are modules imported by the overrides files, that we don't want to | |
// introspect. I'm not sure if there's a way to tell if an object was imported | |
// via imports or imports.gi. | |
const MODULES = ['ByteArray', 'Gi', 'GjsPrivate', 'GObject', 'Lang']; | |
ApiSymbol.prototype.gather = function (object, inPrototype) { | |
Object.keys(object).forEach((name) => { | |
if (name.startsWith('_')) | |
return; | |
if (this.type === 'module' && name === this.name || MODULES.indexOf(name) !== -1) | |
return; | |
if (this.type === 'class' && name === 'prototype') | |
return; | |
if (name === 'constructor') | |
return; | |
let member = object[name]; | |
if (typeof member === 'undefined') | |
return; | |
let symbol = new ApiSymbol(name, typeof member); | |
if (typeof member.prototype !== 'undefined' && Object.keys(member.prototype).length > 0) | |
symbol.type = 'class'; | |
if (member instanceof Array) | |
symbol.type = 'array'; | |
if (inPrototype && this.type === 'class' && symbol.type === 'function') | |
symbol.type = 'method'; | |
this.children.push(symbol); | |
if (symbol.type === 'object') { | |
symbol.gather(member); | |
} else if (symbol.type === 'class') { | |
symbol.gather(member); | |
symbol.gather(member.prototype, true); | |
} | |
}); | |
}; | |
let api = new ApiSymbol(moduleName, 'module'); | |
api.gather(module[moduleName]); | |
print(JSON.stringify(api, null, ' ')); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import importlib | |
import inspect | |
import os.path | |
import sys | |
import gi | |
dirname, basename = os.path.split(sys.argv[1]) | |
modulename, ext = os.path.splitext(basename) | |
oldsyspath = sys.path | |
sys.path = [dirname] + sys.path | |
module = importlib.import_module('gi.overrides.' + modulename) | |
sys.path = oldsyspath | |
class ApiSymbol(object): | |
def __init__(self, name, typ): | |
self.name = name | |
self.type = typ | |
self.children = [] | |
_GI_INTERNAL = ['deprecated_init', 'get_introspection_module', 'override'] | |
def gather(self, obj): | |
for name in obj.__dict__: | |
if name.startswith('_'): | |
continue | |
if name in self._GI_INTERNAL: | |
continue | |
member = obj.__dict__[name] | |
# This skips over the corresponding module imported from the GIR | |
if isinstance(member, gi.module.IntrospectionModule): | |
continue | |
# hrtype = human readable type | |
hrtype = type(member) | |
if inspect.ismodule(member): | |
continue | |
elif inspect.isclass(member): | |
hrtype = 'class' | |
elif inspect.ismethod(member): | |
hrtype = 'method' | |
elif inspect.isfunction(member): | |
hrtype = 'function' | |
# I wonder why inspect doesn't get this | |
if self.type == 'class' and hrtype == 'function': | |
hrtype = 'method' | |
symbol = ApiSymbol(name, hrtype) | |
self.children.append(symbol) | |
if hrtype == 'class': | |
symbol.gather(member) | |
def __str__(self): | |
retval = 'name: {0.name}\ntype: {0.type}\n'.format(self) | |
if self.children: | |
children_descs = '\n'.join(map(str, self.children)) | |
children_descs = '\n'.join(map(lambda l: ' ' + l, children_descs.split('\n'))) | |
retval += 'children:\n' + children_descs | |
return retval | |
api = ApiSymbol(modulename, 'module') | |
api.gather(module) | |
print api |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment