登陆 Testlink -> My Settings -> My personal access key 拿到 API 授权的 key, 尝试链接
1 2 3 4 5 6 7 8 9 10 11 12 13
import testlink url = "https://<hostname>/lib/api/xmlrpc/v1/xmlrpc.php" # for this key, you can get forom Testlink -> click My Settings → my personal access key field key = "api_auth_key"# test link personal key tlk = testlink.TestLinkHelper(url, key).connect(testlink.TestlinkAPIClient) print(tlk.tlk.countProjects()) # 39
# get project info projects = tlk.getTestProjects() for sub in projects: print("id: %s, prefix: %s, name: %s" % (sub['id'], sub['prefix'], sub['name'])) # id: 5182, prefix: PLT#, name: Platform Foundations and Integrations
其他的 API 都和差不多类似的,通过使用 Ipython + tab 基本都可以找到
注意点
python 提供的接口中有一个很有意思:tlk.whatArgs('getTestProjects') 他可以给出对应 API 的调用方式,参数列表的信息,很有用
client 项目的 example 路径下,有几个示例,写的很清楚,基本上把所有支持的命令都写了,值得参考
Command is a behavioral design pattern that turns a request into a stand-alone object that contains all information about the request. This transformation lets you parameterize methods with different requests, delay or queue a request’s execution, and support undoable operations.
classSplitterextendsProcessor{ String process(Object input){ // The split() argument divides a String into pieces: return Arrays.toString(((String)input).split(" ")); } }
publicclassApply{ publicstaticvoidprocess(Processor p, Object s){ System.out.println("Using Processor " + p.name()); System.out.println(p.process(s)); } publicstatic String s = "Disagreement with beliefs is by definition incorrect"; publicstaticvoidmain(String[] args){ process(new Upcase(), s); process(new Downcase(), s); process(new Splitter(), s); } }
// Using Processor Upcase // DISAGREEMENT WITH BELIEFS IS BY DEFINITION INCORRECT // Using Processor Downcase // disagreement with beliefs is by definition incorrect // Using Processor Splitter // [Disagreement, with, beliefs, is, by, definition, incorrect]
// 虽然它这种 abstract 类中直接写具体调用的做法我总感觉很飘逸,但是理解不难 publicabstractclassStringProcessorimplementsProcessor{ public String name(){ return getClass().getSimpleName(); } publicabstract String process(Object input); publicstatic String s = "If she weighs the same as a duck, she’s made of wood"; publicstaticvoidmain(String[] args){ Apply.process(new Upcase(), s); Apply.process(new Downcase(), s); Apply.process(new Splitter(), s); } } classUpcaseextendsStringProcessor{ public String process(Object input){ // Covariant return return ((String)input).toUpperCase(); } } classDowncaseextendsStringProcessor{ public String process(Object input){ return ((String)input).toLowerCase(); } } classSplitterextendsStringProcessor{ public String process(Object input){ return Arrays.toString(((String)input).split(" ")); } }
// Using Processor Upcase // IF SHE WEIGHS THE SAME AS A DUCK, SHE’S MADE OF WOOD // Using Processor Downcase // if she weighs the same as a duck, she’s made of wood // Using Processor Splitter // [If, she, weighs, the, same, as, a, duck,, she’s, made, of, wood]
// Cannot implement a private interface except // within that interface’s defining class: // ! class DImp implements A.D { // ! public void f() {} // ! } classEImpimplementsE{ publicvoidg(){ } }
classEGImpimplementsE.G{ publicvoidf(){ } }
classEImp2implementsE{ publicvoidg(){ }
classEGimplementsE.G{ publicvoidf(){ } } }
publicstaticvoidmain(String[] args){ A a = new A(); // Can’t access A.D: // ! A.D ad = a.getD(); // Doesn’t return anything but A.D: // ! A.DImp2 di2 = a.getD(); // Cannot access a member of the interface: // ! a.getD().f(); // Only another A can do anything with getD(): A a2 = new A(); a2.receiveD(a.getD()); } }
but A.DImp2 shows that it can also be implemented as a public class. However, A.DImp2 can only be used as itself. You are not allowed to mention the fact that it implements the private interface D, so implementing a private interface is a way to force the definition of the methods in that interface without adding any type information (that is, without allowing any upcasting).
个人理解为 private 接口将接口的实现和定义限制在了定义类里面。而且一般使用的时候都是会返回接口类,像上面的 D getD(), 而 D 又是 private 的,限制了他的使用,这应该就是原文中 'A.DImp2 can only be used as itself' 的意思吧
getD() 方法是 private 修饰的嵌套接口的更特殊的使用方式,在 main() 中,我们 comment 了很多对 D 接口的引用,但是这些用法都有编译错误。唯一的使用方式是新建一个 A 对象,调用以 D 为参数的方法。
Interface E 的例子想要说明的事,接口内部也能声明接口,但是秉承接口内部元素必须都是规则,内嵌的接口也必须只能是 public 的
Python 的 re 包里面的 search 和 match 经常搞不清楚,特意整理记录下 re 包支持的方法
re.search(pattern, string, flags=0) 字符串任意位置匹配
Scan through string looking for the first location where the regular expression pattern produces a match, and return a corresponding match object. Return None if no position in the string matches the pattern; note that this is different from finding a zero-length match at some point in the string.
1 2 3 4
ret = re.search(r'[\d]+', 'aaa123bbbb') ret.group(0)
# '123'
re.match(pattern, string, flags=0) 从头开始匹配
If zero or more characters at the beginning of string match the regular expression pattern, return a corresponding match object. Return None if the string does not match the pattern; note that this is different from a zero-length match.
Note that even in MULTILINE mode, re.match() will only match at the beginning of the string and not at the beginning of each line.
If you want to locate a match anywhere in string, use search() instead (see also search() vs. match()).
C 和其他一些早期语言经常会有多中处理异常的方式,这些方式基本都是便宜形式,并且不是语言的一部分。典型的案例就是放回一个特殊的值或者设置一个特殊的 flag,接收方根据这个返回值来进行相应的处理。但是渐渐的码农们突然意识到,自己定义的异常情况可能是不充分的,并且为了覆盖这些没有覆盖到的情况,代码会变得越来越难以维护。
Exercise 1: (2) Create a class with a main( ) that throws an object of class Exception inside a try block. Give the constructor for Exception a String argument. Catch the exception inside a catch clause and print the String argument. Add a finally clause and print a message to prove you were there.
// output // my exception msg... // Into final cluster...
Exercise 2: (1) Define an object reference and initialize it to null. Try to call a method through this reference. Now wrap the code in a try-catch clause to catch the exception.
Exercise 4: (2) Create your own exception class using the extends keyword. Write a constructor for this class that takes a String argument and stores it inside the object with a String reference. Write a method that displays the stored String. Create a try-catch clause to exercise your new exception.
publicclassWhoCalled{ staticvoidf(){ // Generate an exception to fill in the stack trace try { thrownew Exception(); } catch (Exception e) { for (StackTraceElement ste : e.getStackTrace()) System.out.println(ste.getMethodName()); } }
publicclassRethrowing{ publicstaticvoidf()throws Exception { System.out.println("originating the exception in f()"); thrownew Exception("thrown from f()"); }
// originating the exception in f() // Inside g(),e.printStackTrace() // java.lang.Exception: thrown from f() // at reading.container.Rethrowing.f(Rethrowing.java:6) // at reading.container.Rethrowing.g(Rethrowing.java:11) // at reading.container.Rethrowing.main(Rethrowing.java:31) // main: printStackTrace() // java.lang.Exception: thrown from f() // at reading.container.Rethrowing.f(Rethrowing.java:6) // at reading.container.Rethrowing.g(Rethrowing.java:11) // at reading.container.Rethrowing.main(Rethrowing.java:31) // /--------------------- Dash --------------------/ // originating the exception in f() // Inside h(),e.printStackTrace() // java.lang.Exception: thrown from f() // at reading.container.Rethrowing.f(Rethrowing.java:6) // at reading.container.Rethrowing.h(Rethrowing.java:21) // at reading.container.Rethrowing.main(Rethrowing.java:38) // main: printStackTrace() // java.lang.Exception: thrown from f() // at reading.container.Rethrowing.h(Rethrowing.java:25) // at reading.container.Rethrowing.main(Rethrowing.java:38)
publicclassRethrowNew{ publicstaticvoidf()throws OneException { System.out.println("originating the exception in f()"); thrownew OneException("thrown from f()"); }
// originating the exception in f() // Caught in inner try, e.printStackTrace() // reading.container.OneException: thrown from f() // at reading.container.RethrowNew.f(RethrowNew.java:18) // at reading.container.RethrowNew.main(RethrowNew.java:24) // Caught in outer try, e.printStackTrace() // reading.container.TwoException: from inner try // at reading.container.RethrowNew.main(RethrowNew.java:29)
publicDynamicFields(int initialSize){ fields = new Object[initialSize][2]; for (int i = 0; i < initialSize; i++) fields[i] = new Object[]{null, null}; }
public String toString(){ StringBuilder result = new StringBuilder(); for (Object[] obj : fields) { result.append(obj[0]); result.append(": "); result.append(obj[1]); result.append("\n"); } return result.toString(); }
privateinthasField(String id){ for (int i = 0; i < fields.length; i++) if (id.equals(fields[i][0])) return i; return -1; }
privateint getFieldNumber(String id) throws NoSuchFieldException { int fieldNum = hasField(id); if (fieldNum == -1) thrownew NoSuchFieldException(); return fieldNum; }
privateintmakeField(String id){ for (int i = 0; i < fields.length; i++) if (fields[i][0] == null) { fields[i][0] = id; return i; } // No empty fields. Add one: Object[][] tmp = new Object[fields.length + 1][2]; for (int i = 0; i < fields.length; i++) tmp[i] = fields[i]; for (int i = fields.length; i < tmp.length; i++) tmp[i] = new Object[]{null, null}; fields = tmp; // Recursive call with expanded fields: return makeField(id); }
public Object getField(String id)throws NoSuchFieldException { return fields[getFieldNumber(id)][1]; }
public Object setField(String id, Object value) throws DynamicFieldsException { if (value == null) { // Most exceptions don’t have a "cause" constructor. // In these cases you must use initCause(), // available in all Throwable subclasses. DynamicFieldsException dfe = new DynamicFieldsException(); dfe.initCause(new NullPointerException()); throw dfe; } int fieldNumber = hasField(id); if (fieldNumber == -1) fieldNumber = makeField(id); Object result = null; try { result = getField(id); // Get old value } catch (NoSuchFieldException e) { // Use constructor that takes "cause": thrownew RuntimeException(e); } fields[fieldNumber][1] = value; return result; }
publicstaticvoidmain(String[] args){ DynamicFields df = new DynamicFields(3); System.out.println(df); try { df.setField("d", "A value for d"); df.setField("number", 47); df.setField("number2", 48); System.out.println(df); df.setField("d", "A new value for d"); df.setField("number3", 11); System.out.println("df: " + df); System.out.println("df.getField(\"d\") : " + df.getField("d")); Object field = df.setField("d", null); // Exception } catch (NoSuchFieldException e) { e.printStackTrace(System.out); } catch (DynamicFieldsException e) { e.printStackTrace(System.out); } } }
// df: d: A new value for d // number: 47 // number2: 48 // number3: 11
// df.getField("d") : A new value for d // reading.container.DynamicFieldsException // at reading.container.DynamicFields.setField(DynamicFields.java:68) // at reading.container.DynamicFields.main(DynamicFields.java:98) // Caused by: java.lang.NullPointerException // at reading.container.DynamicFields.setField(DynamicFields.java:69) // ... 1 more
// output // Exception in thread "main" java.lang.RuntimeException: From f() // at reading.container.NeverCaught.f(NeverCaught.java:5) // at reading.container.NeverCaught.g(NeverCaught.java:9) // at reading.container.NeverCaught.main(NeverCaught.java:13)
try { // The guarded region: Dangerous activities // that might throw A, B, or C } catch(A a1) { // Handler for situation A } catch(B b1) { // Handler for situation B } catch(C c1) { // Handler for situation C } finally { // Activities that happen every time }
publicclassMultipleReturns{ publicstaticvoidf(int i){ System.out.println("Initialization that requires cleanup"); try { System.out.println("Point 1"); if (i == 1) return; System.out.println("Point 2"); if (i == 2) return; System.out.println("Point 3"); if (i == 3) return; System.out.println("End"); return; } finally { System.out.println("Performing cleanup"); } }
publicstaticvoidmain(String[] args){ for (int i = 1; i <= 4; i++) f(i); } }
// Initialization that requires cleanup // Point 1 // Performing cleanup // Initialization that requires cleanup // Point 1 // Point 2 // Performing cleanup // Initialization that requires cleanup // Point 1 // Point 2 // Point 3 // Performing cleanup // Initialization that requires cleanup // Point 1 // Point 2 // Point 3 // End // Performing cleanup
publicclassStormyInningextendsInningimplementsStorm{ // OK to add new exceptions for constructors, but you // must deal with the base constructor exceptions: publicStormyInning() throws RainedOut, BaseballException { }
// Regular methods must conform to base class: // !public void walk() throws PopFoul {} //Compile error // Interface CANNOT add exceptions to existing // methods from the base class: // !public void event() throws RainedOut {} // If the method doesn’t already exist in the // base class, the exception is OK: publicvoidrainHard()throws RainedOut {}
// You can choose to not throw any exceptions, // even if the base version does: publicvoidevent(){}
// Overridden methods can throw inherited exceptions: publicvoidatBat()throws PopFoul {}
publicstaticvoidmain(String[] args){ try { StormyInning si = new StormyInning(); si.atBat(); } catch (PopFoul e) { System.out.println("Pop foul"); } catch (RainedOut e) { System.out.println("Rained out"); } catch (BaseballException e) { System.out.println("Generic baseball exception"); } // Strike not thrown in derived version. try { // What happens if you upcast? Inning i = new StormyInning(); i.atBat(); // You must catch the exceptions from the // base-class version of the method: } catch (Strike e) { System.out.println("Strike"); } catch (Foul e) { System.out.println("Foul"); } catch (RainedOut e) { System.out.println("Rained out"); } catch (BaseballException e) { System.out.println("Generic baseball exception"); } } }
publicInputFile(String fname)throws Exception { try { in = new BufferedReader(new FileReader(fname)); // Other code that might throw exceptions } catch (FileNotFoundException e) { System.out.println("Could not open " + fname); // Wasn’t open, so don’t close it throw e; } catch (Exception e) { // All other exceptions must close it try { in.close(); } catch (IOException e2) { System.out.println("in.close() unsuccessful"); } throw e; // Rethrow } finally { // Don’t close it here!!! } }
// Section 2: // If construction cannot fail you can group objects: NeedsCleanup nc2 = new NeedsCleanup(); NeedsCleanup nc3 = new NeedsCleanup(); try { // ... } finally { nc3.dispose(); // Reverse order of construction nc2.dispose(); }
publicclassMainException{ // Pass all exceptions to the console: publicstaticvoidmain(String[] args)throws Exception { // Open the file: FileInputStream file = new FileInputStream("MainException.java"); // Use the file ... // Close the file: file.close(); } }
classBerylliumSphere{ privatestaticlong counter; privatefinallong id = counter++;
public String toString(){ return"Sphere " + id; } }
publicclassContainerComparison{ publicstaticvoidmain(String[] args){ BerylliumSphere[] spheres = new BerylliumSphere[10]; for (int i = 0; i < 5; i++) spheres[i] = new BerylliumSphere(); System.out.println(Arrays.toString(spheres)); System.out.println(spheres[4]);
List<BerylliumSphere> sphereList = new ArrayList<>(); for (int i = 0; i < 5; i++) sphereList.add(new BerylliumSphere()); System.out.println(sphereList); System.out.println(sphereList.get(4));
classBerylliumSphere{ privatestaticlong counter; privatefinallong id = counter++;
public String toString(){ return"Sphere " + id; } }
publicclassArrayOptions{ publicstaticvoidmain(String[] args){ // Arrays of objects: BerylliumSphere[] a; // Local uninitialized variable BerylliumSphere[] b = new BerylliumSphere[5]; // The references inside the array are // automatically initialized to null: System.out.println("b: " + Arrays.toString(b)); BerylliumSphere[] c = new BerylliumSphere[4]; for (int i = 0; i < c.length; i++) if (c[i] == null) // Can test for null reference c[i] = new BerylliumSphere(); // Aggregate initialization: BerylliumSphere[] d = {new BerylliumSphere(), new BerylliumSphere(), new BerylliumSphere() }; // Dynamic aggregate initialization: a = new BerylliumSphere[]{ new BerylliumSphere(), new BerylliumSphere(), }; // (Trailing comma is optional in both cases) System.out.println("a.length = " + a.length); System.out.println("b.length = " + b.length); System.out.println("c.length = " + c.length); System.out.println("d.length = " + d.length); a = d; System.out.println("a.length = " + a.length); // Arrays of primitives: int[] e; // Null reference int[] f = newint[5]; // The primitives inside the array are // automatically initialized to zero: System.out.println("f: " + Arrays.toString(f)); int[] g = newint[4]; for (int i = 0; i < g.length; i++) g[i] = i * i; int[] h = {11, 47, 93}; // Compile error: variable e not initialized: //!System.out.println("e.length = " + e.length); System.out.println("f.length = " + f.length); System.out.println("g.length = " + g.length); System.out.println("h.length = " + h.length); e = h; System.out.println("e.length = " + e.length); e = newint[]{1, 2}; System.out.println("e.length = " + e.length); } }
@click.command() @click.option('--count', default=1, help='Number of greetings.') @click.option('--name', prompt='Your name', help='The person to greet.') defgreet(count, name): """Simple program that greets NAME for a total of COUNT times.""" for x in range(count): click.echo('Hello %s!' % name)
if __name__ == '__main__': greet()
在 toml 中添加程序入口
1 2
[tool.poetry.scripts] greet = "greet.greet:greet"
终端输入 poetry install 将代码安装到虚拟环境,之后输入 poetry run greet 试运行脚本,可以看到终端给出提示
1 2 3
mypc ~/tmp/clickgreet > poetry run greet Your name: jack Hello jack!
[[tool.poetry.source]] name = "douban" url = "https://pypi.doubanio.com/simple/"
Debug Click Command
测试代码,接收 count, name 参数并在终端输出
1 2 3 4 5 6 7 8 9 10 11 12 13
import click
@click.command() @click.option('--count', default=1, help='Number of greetings.') @click.option('--name', prompt='Your name', help='The person to greet.') defhello(count, name): """Simple program that greets NAME for a total of COUNT times.""" for x in range(count): click.echo('Hello %s!' % name)