Android运行jython,android-platform_sdk-程序员宅基地

技术标签: Android运行jython  

/*

* Copyright (C) 2010 The Android Open Source Project

*

* Licensed under the Apache License, Version 2.0 (the "License");

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License at

*

* http://www.apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

package com.android.monkeyrunner;

import java.lang.reflect.AccessibleObject;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

import java.lang.reflect.Modifier;

import java.text.BreakIterator;

import java.util.Arrays;

import java.util.Collection;

import java.util.Collections;

import java.util.List;

import java.util.Map;

import java.util.Map.Entry;

import java.util.logging.Level;

import java.util.logging.Logger;

import org.python.core.ArgParser;

import org.python.core.ClassDictInit;

import org.python.core.Py;

import org.python.core.PyDictionary;

import org.python.core.PyFloat;

import org.python.core.PyInteger;

import org.python.core.PyList;

import org.python.core.PyNone;

import org.python.core.PyObject;

import org.python.core.PyReflectedField;

import org.python.core.PyReflectedFunction;

import org.python.core.PyString;

import org.python.core.PyStringMap;

import org.python.core.PyTuple;

import com.android.monkeyrunner.doc.MonkeyRunnerExported;

import com.google.common.base.Preconditions;

import com.google.common.base.Predicate;

import com.google.common.base.Predicates;

import com.google.common.collect.Collections2;

import com.google.common.collect.ImmutableMap;

import com.google.common.collect.Lists;

import com.google.common.collect.Maps;

import com.google.common.collect.Sets;

import com.google.common.collect.ImmutableMap.Builder;

/**

* Collection of useful utilities function for interacting with the Jython interpreter.

*/

public final class JythonUtils {

private static final Logger LOG = Logger.getLogger(JythonUtils.class.getCanonicalName());

private JythonUtils() { }

/**

* Mapping of PyObject classes to the java class we want to convert them to.

*/

private static final Map, Class>> PYOBJECT_TO_JAVA_OBJECT_MAP;

static {

Builder, Class>> builder = ImmutableMap.builder();

builder.put(PyString.class, String.class);

// What python calls float, most people call double

builder.put(PyFloat.class, Double.class);

builder.put(PyInteger.class, Integer.class);

PYOBJECT_TO_JAVA_OBJECT_MAP = builder.build();

}

/**

* Utility method to be called from Jython bindings to give proper handling of keyword and

* positional arguments.

*

* @param args the PyObject arguments from the binding

* @param kws the keyword arguments from the binding

* @return an ArgParser for this binding, or null on error

*/

public static ArgParser createArgParser(PyObject[] args, String[] kws) {

StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();

// Up 2 levels in the current stack to give us the calling function

StackTraceElement element = stackTrace[2];

String methodName = element.getMethodName();

String className = element.getClassName();

Class> clz;

try {

clz = Class.forName(className);

} catch (ClassNotFoundException e) {

LOG.log(Level.SEVERE, "Got exception: ", e);

return null;

}

Method m;

try {

m = clz.getMethod(methodName, PyObject[].class, String[].class);

} catch (SecurityException e) {

LOG.log(Level.SEVERE, "Got exception: ", e);

return null;

} catch (NoSuchMethodException e) {

LOG.log(Level.SEVERE, "Got exception: ", e);

return null;

}

MonkeyRunnerExported annotation = m.getAnnotation(MonkeyRunnerExported.class);

return new ArgParser(methodName, args, kws,

annotation.args());

}

/**

* Get a python floating point value from an ArgParser.

*

* @param ap the ArgParser to get the value from.

* @param position the position in the parser

* @return the double value

*/

public static double getFloat(ArgParser ap, int position) {

PyObject arg = ap.getPyObject(position);

if (Py.isInstance(arg, PyFloat.TYPE)) {

return ((PyFloat) arg).asDouble();

}

if (Py.isInstance(arg, PyInteger.TYPE)) {

return ((PyInteger) arg).asDouble();

}

throw Py.TypeError("Unable to parse argument: " + position);

}

/**

* Get a python floating point value from an ArgParser.

*

* @param ap the ArgParser to get the value from.

* @param position the position in the parser

* @param defaultValue the default value to return if the arg isn't specified.

* @return the double value

*/

public static double getFloat(ArgParser ap, int position, double defaultValue) {

PyObject arg = ap.getPyObject(position, new PyFloat(defaultValue));

if (Py.isInstance(arg, PyFloat.TYPE)) {

return ((PyFloat) arg).asDouble();

}

if (Py.isInstance(arg, PyInteger.TYPE)) {

return ((PyInteger) arg).asDouble();

}

throw Py.TypeError("Unable to parse argument: " + position);

}

/**

* Get a list of arguments from an ArgParser.

*

* @param ap the ArgParser

* @param position the position in the parser to get the argument from

* @return a list of those items

*/

@SuppressWarnings("unchecked")

public static List getList(ArgParser ap, int position) {

PyObject arg = ap.getPyObject(position, Py.None);

if (Py.isInstance(arg, PyNone.TYPE)) {

return Collections.emptyList();

}

List ret = Lists.newArrayList();

PyList array = (PyList) arg;

for (int x = 0; x < array.__len__(); x++) {

PyObject item = array.__getitem__(x);

Class> javaClass = PYOBJECT_TO_JAVA_OBJECT_MAP.get(item.getClass());

if (javaClass != null) {

ret.add(item.__tojava__(javaClass));

}

}

return ret;

}

/**

* Get a dictionary from an ArgParser. For ease of use, key types are always coerced to

* strings. If key type cannot be coeraced to string, an exception is raised.

*

* @param ap the ArgParser to work with

* @param position the position in the parser to get.

* @return a Map mapping the String key to the value

*/

public static Map getMap(ArgParser ap, int position) {

PyObject arg = ap.getPyObject(position, Py.None);

if (Py.isInstance(arg, PyNone.TYPE)) {

return Collections.emptyMap();

}

Map ret = Maps.newHashMap();

// cast is safe as getPyObjectbyType ensures it

PyDictionary dict = (PyDictionary) arg;

PyList items = dict.items();

for (int x = 0; x < items.__len__(); x++) {

// It's a list of tuples

PyTuple item = (PyTuple) items.__getitem__(x);

// We call str(key) on the key to get the string and then convert it to the java string.

String key = (String) item.__getitem__(0).__str__().__tojava__(String.class);

PyObject value = item.__getitem__(1);

// Look up the conversion type and convert the value

Class> javaClass = PYOBJECT_TO_JAVA_OBJECT_MAP.get(value.getClass());

if (javaClass != null) {

ret.put(key, value.__tojava__(javaClass));

}

}

return ret;

}

private static PyObject convertObject(Object o) {

if (o instanceof String) {

return new PyString((String) o);

} else if (o instanceof Double) {

return new PyFloat((Double) o);

} else if (o instanceof Integer) {

return new PyInteger((Integer) o);

} else if (o instanceof Float) {

float f = (Float) o;

return new PyFloat(f);

}

return Py.None;

}

/**

* Convert the given Java Map into a PyDictionary.

*

* @param map the map to convert

* @return the python dictionary

*/

public static PyDictionary convertMapToDict(Map map) {

Map resultMap = Maps.newHashMap();

for (Entry entry : map.entrySet()) {

resultMap.put(new PyString(entry.getKey()),

convertObject(entry.getValue()));

}

return new PyDictionary(resultMap);

}

/**

* This function should be called from classDictInit for any classes that are being exported

* to jython. This jython converts all the MonkeyRunnerExported annotations for the given class

* into the proper python form. It also removes any functions listed in the dictionary that

* aren't specifically annotated in the java class.

*

* NOTE: Make sure the calling class implements {@link ClassDictInit} to ensure that

* classDictInit gets called.

*

* @param clz the class to examine.

* @param dict the dictionary to update.

*/

public static void convertDocAnnotationsForClass(Class> clz, PyObject dict) {

Preconditions.checkNotNull(dict);

Preconditions.checkArgument(dict instanceof PyStringMap);

// See if the class has the annotation

if (clz.isAnnotationPresent(MonkeyRunnerExported.class)) {

MonkeyRunnerExported doc = clz.getAnnotation(MonkeyRunnerExported.class);

String fullDoc = buildClassDoc(doc, clz);

dict.__setitem__("__doc__", new PyString(fullDoc));

}

// Get all the keys from the dict and put them into a set. As we visit the annotated methods,

// we will remove them from this set. At the end, these are the "hidden" methods that

// should be removed from the dict

Collection functions = Sets.newHashSet();

for (PyObject item : dict.asIterable()) {

functions.add(item.toString());

}

// And remove anything that starts with __, as those are pretty important to retain

functions = Collections2.filter(functions, new Predicate() {

@Override

public boolean apply(String value) {

return !value.startsWith("__");

}

});

// Look at all the methods in the class and find the one's that have the

// @MonkeyRunnerExported annotation.

for (Method m : clz.getMethods()) {

if (m.isAnnotationPresent(MonkeyRunnerExported.class)) {

String methodName = m.getName();

PyObject pyFunc = dict.__finditem__(methodName);

if (pyFunc != null && pyFunc instanceof PyReflectedFunction) {

PyReflectedFunction realPyFunc = (PyReflectedFunction) pyFunc;

MonkeyRunnerExported doc = m.getAnnotation(MonkeyRunnerExported.class);

realPyFunc.__doc__ = new PyString(buildDoc(doc));

functions.remove(methodName);

}

}

}

// Also look at all the fields (both static and instance).

for (Field f : clz.getFields()) {

if (f.isAnnotationPresent(MonkeyRunnerExported.class)) {

String fieldName = f.getName();

PyObject pyField = dict.__finditem__(fieldName);

if (pyField != null && pyField instanceof PyReflectedField) {

PyReflectedField realPyfield = (PyReflectedField) pyField;

MonkeyRunnerExported doc = f.getAnnotation(MonkeyRunnerExported.class);

// TODO: figure out how to set field documentation. __doc__ is Read Only

// in this context.

// realPyfield.__setattr__("__doc__", new PyString(buildDoc(doc)));

functions.remove(fieldName);

}

}

}

// Now remove any elements left from the functions collection

for (String name : functions) {

dict.__delitem__(name);

}

}

private static final Predicate SHOULD_BE_DOCUMENTED = new Predicate() {

@Override

public boolean apply(AccessibleObject ao) {

return ao.isAnnotationPresent(MonkeyRunnerExported.class);

}

};

private static final Predicate IS_FIELD_STATIC = new Predicate() {

@Override

public boolean apply(Field f) {

return (f.getModifiers() & Modifier.STATIC) != 0;

}

};

/**

* build a jython doc-string for a class from the annotation and the fields

* contained within the class

*

* @param doc the annotation

* @param clz the class to be documented

* @return the doc-string

*/

private static String buildClassDoc(MonkeyRunnerExported doc, Class> clz) {

// Below the class doc, we need to document all the documented field this class contains

Collection annotatedFields = Collections2.filter(Arrays.asList(clz.getFields()), SHOULD_BE_DOCUMENTED);

Collection staticFields = Collections2.filter(annotatedFields, IS_FIELD_STATIC);

Collection nonStaticFields = Collections2.filter(annotatedFields, Predicates.not(IS_FIELD_STATIC));

StringBuilder sb = new StringBuilder();

for (String line : splitString(doc.doc(), 80)) {

sb.append(line).append("\n");

}

if (staticFields.size() > 0) {

sb.append("\nClass Fields: \n");

for (Field f : staticFields) {

sb.append(buildFieldDoc(f));

}

}

if (nonStaticFields.size() > 0) {

sb.append("\n\nFields: \n");

for (Field f : nonStaticFields) {

sb.append(buildFieldDoc(f));

}

}

return sb.toString();

}

/**

* Build a doc-string for the annotated field.

*

* @param f the field.

* @return the doc-string.

*/

private static String buildFieldDoc(Field f) {

MonkeyRunnerExported annotation = f.getAnnotation(MonkeyRunnerExported.class);

StringBuilder sb = new StringBuilder();

int indentOffset = 2 + 3 + f.getName().length();

String indent = makeIndent(indentOffset);

sb.append(" ").append(f.getName()).append(" - ");

boolean first = true;

for (String line : splitString(annotation.doc(), 80 - indentOffset)) {

if (first) {

first = false;

sb.append(line).append("\n");

} else {

sb.append(indent).append(line).append("\n");

}

}

return sb.toString();

}

/**

* Build a jython doc-string from the MonkeyRunnerExported annotation.

*

* @param doc the annotation to build from

* @return a jython doc-string

*/

private static String buildDoc(MonkeyRunnerExported doc) {

Collection docs = splitString(doc.doc(), 80);

StringBuilder sb = new StringBuilder();

for (String d : docs) {

sb.append(d).append("\n");

}

if (doc.args() != null && doc.args().length > 0) {

String[] args = doc.args();

String[] argDocs = doc.argDocs();

sb.append("\n Args:\n");

for (int x = 0; x < doc.args().length; x++) {

sb.append(" ").append(args[x]);

if (argDocs != null && argDocs.length > x) {

sb.append(" - ");

int indentOffset = args[x].length() + 3 + 4;

Collection lines = splitString(argDocs[x], 80 - indentOffset);

boolean first = true;

String indent = makeIndent(indentOffset);

for (String line : lines) {

if (first) {

first = false;

sb.append(line).append("\n");

} else {

sb.append(indent).append(line).append("\n");

}

}

}

}

}

return sb.toString();

}

private static String makeIndent(int indentOffset) {

if (indentOffset == 0) {

return "";

}

StringBuffer sb = new StringBuffer();

while (indentOffset > 0) {

sb.append(' ');

indentOffset--;

}

return sb.toString();

}

private static Collection splitString(String source, int offset) {

BreakIterator boundary = BreakIterator.getLineInstance();

boundary.setText(source);

List lines = Lists.newArrayList();

StringBuilder currentLine = new StringBuilder();

int start = boundary.first();

for (int end = boundary.next();

end != BreakIterator.DONE;

start = end, end = boundary.next()) {

String b = source.substring(start, end);

if (currentLine.length() + b.length() < offset) {

currentLine.append(b);

} else {

// emit the old line

lines.add(currentLine.toString());

currentLine = new StringBuilder(b);

}

}

lines.add(currentLine.toString());

return lines;

}

}

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_30240263/article/details/117680698

智能推荐

面试的一些技巧_竞选大队长时到台上演讲怎样不紧张端庄大方举止得体-程序员宅基地

文章浏览阅读423次。应试者要想在面试答辩中获得成功,必须注意以下几个问题:(一)淡化面试的成败意识应试者对于面试的成败,首先在思想上应注意淡化,要有一种“不以物喜,不以己悲”的超然态度。如果在面试中有这样的心态,才会处变不惊。如果只想到成功,不想到失败,那么在面试中一遇到意外情况,就会惊慌失措,一败涂地。(二)保持自信应试者在面试前树立了自信,在面试中也要始终保持自信,只有保持了自信,才能够在面试中始终保持高度的注意力、缜密的思维力、敏锐的判断力、充沛的精力,夺取答辩的胜利。(三)保持愉悦的精神状态愉悦的精神状态,_竞选大队长时到台上演讲怎样不紧张端庄大方举止得体

SpringBoot增删改查的返回值类型_springboot mapper查詢返回數字-程序员宅基地

文章浏览阅读2.1k次。select(查询)方法需要集合或者数组去装数据,而update(修改),delete(删除),insert(添加)方法是不需要设置返回类型的,它们都是默认返回一个int。/** * 查询水果 * @return */ @RequestMapping("/selFruit") public List<Fruit> selFruit(){ List<Fruit> list = fruitService...._springboot mapper查詢返回數字

项目实战:C/C++游戏:2048[C语言版]-程序员宅基地

文章浏览阅读4.2k次,点赞14次,收藏65次。项目实战:C/C++游戏:2048[C语言版]目录项目实战:C/C++游戏:2048[C语言版]1.编译环境2.项目运行效果3.思路简介:1.游戏规则2.核心算法4.主要源码:1.编译环境Win10专业版x64 VS2015这是2017年9或10月份写的 一个练手的,和上一篇Flappy Bird 是一起的, 留以后一个永久的回忆..._c++游戏

python 卡方检验 特征选择_结合Scikit-learn介绍几种常用的特征选择方法-程序员宅基地

文章浏览阅读437次。特征选择(排序)对于数据科学家、机器学习从业者来说非常重要。好的特征选择能够提升模型的性能,更能帮助我们理解数据的特点、底层结构,这对进一步改善模型、算法都有着重要作用。特征选择主要有两个功能:减少特征数量、降维,使模型泛化能力更强,减少过拟合增强对特征和特征值之间的理解拿到数据集,一个特征选择方法,往往很难同时完成这两个目的。通常情况下,我们经常不管三七二十一,选择一种自己最熟悉或者最方便的特征..._python sklearn卡方检验选择特征

Android 锁屏后无法接收UDP_android接收udp组播熄屏收不到-程序员宅基地

文章浏览阅读4.1k次。今天遇到一个很神奇的问题。 应用中有一个服务,服务中使用线程池 进行UDP的接收和发送。 但是,当锁屏后,数据无论如何都接收不到,当打开锁屏的时候,数据接收又恢复正常了。 并且,使用电源锁也没有任何效果。 PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE); wl = pm.newWakeLoc_android接收udp组播熄屏收不到

Netty的Reactor线程模型_reactor线程组-程序员宅基地

文章浏览阅读450次。上图是一个Reactor线程模型,基于select(),epoll(),Reactor线程将I/O调用请求和I/O操作分离开,理论上一个Reactor线程能处理N个网络I/O操作,但是当并发量很大的时候,一个Reactor线程就会出现响应缓慢,连接超时等问题。============================================================那么一个Reacto_reactor线程组

随便推点

PyCharm刷新项目(文件)目录_pycharm运行后,项目目录内的文件夹为啥不及时更新‘-程序员宅基地

文章浏览阅读2.5w次,点赞14次,收藏12次。利用PyCharm做项目,有时会有写文件(保存到项目中)的需求,但是可能是因为电脑比较慢,项目目录不会自动更新,需要自己手动刷新。可以自行设置“显示刷新图标”:view -->toolbar,需要刷新时,点一下就好了。_pycharm运行后,项目目录内的文件夹为啥不及时更新‘

python链表的建立_python创建链表-程序员宅基地

文章浏览阅读2.5k次,点赞2次,收藏8次。python链表的建立。_python创建链表

Jetpack架构组件 — Room入坑详解-程序员宅基地

文章浏览阅读5.7k次,点赞5次,收藏12次。Room是Jetpack组件库一员,属于ORM库,主要是对Sqlite做了一层抽象,从而简化开发者对数据库操作。Room支持编译时的语法检查,并且支持返..._jetpack room kapt

linux下 tar解压 gz解压 bz2等各种解压文件使用方法_hornycraft解锁农场-程序员宅基地

文章浏览阅读1.6k次。linux下 tar解压 gz解压 bz2等各种解压文件使用方法2010-03-23 15:15.tar  解包:tar xvf FileName.tar  打包:tar cvf FileName.tar DirName  (注:tar是打包,不是压缩!)  ———————————————  .gz  解压1:gunzip FileName.gz  解压2:gzip -_hornycraft解锁农场

知识图谱入门系列_nerrdfs-程序员宅基地

文章浏览阅读571次。很好的入门解说,包括实现方式及意义第一次在知乎上发帖,有不准确的地方欢迎大家指正!!!,后续会持续更新知识图谱相关技术细节。本贴大概介绍一下知识图谱中相关的技术。知识图谱针对于知识图谱基础知识,领域应用和学术前沿趋势进行介绍。知识图谱介绍知识图谱(Knowledge Graph)以结构化的形式描述客观世界中概念、实体及其关系。是融合了认知计算、知识表示与推理、信息检索与抽取、自然语言处理、Web技术、机器学习与大数据挖掘等等方向的交叉学科。人工智能是以传统符号派与目前流行的深度神经._nerrdfs

Thinkphp 模板/内置标签/Foreach标签_{foreach name="typelist" item="vo"}-程序员宅基地

文章浏览阅读4k次。Foreach标签foreach标签类似与volist标签,只是更加简单,没有太多额外的属性,例如:&lt;foreach name="list" item="vo"&gt; {$vo.id}:{$vo.name}&lt;/foreach&gt;name表示数据源 item表示循环变量。可以输出索引,如下:&lt;foreach name="list" item..._{foreach name="typelist" item="vo"}